Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions quactography/classical/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import numpy as np

def save_graph(G, output_base, copies=1):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chaque fonction devrait avoir une documentation qui décrit ce que fait la fonction, les paramètres et les retours

for i in range(copies):
output_file = f"{output_base}_{i}.npz"
nodes = list(G.nodes())
edges = list(G.edges())

nodes_array = np.array(nodes)
edges_array = np.array(edges)

np.savez(output_file, nodes=nodes_array, edges=edges_array)

print(f"Copie {i+1}/{copies} saved as '{output_file}'.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En anglais: copy


54 changes: 54 additions & 0 deletions quactography/classical/utils/random_grid_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import numpy as np
import random
import networkx as nx

def generer_grille(size, obstacle_mode="ratio", obstacle_ratio=0.2, obstacle_number=20):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anglais

"""
Generate a random 2D grid and its corresponding NetworkX graph.

Parameters
----------
size : int
Size of the grid (the grid will be of shape `size x size`).
Must be a positive integer.
obstacle_mode : str
Strategy used to place obstacles in the grid. Options are:
- "ratio": place a proportion of obstacles based on `obstacle_ratio`
- "number": place a fixed number of obstacles based on `obstacle_number`
obstacle_ratio : float
Used only if `obstacle_mode` is "ratio". Defines the proportion of cells
to be turned into obstacles. Must be a float between 0 and 1.
obstacle_number : int
Used only if `obstacle_mode` is "number". Defines the exact number of obstacles
to place in the grid. Must be a positive integer.

Returns
-------
grid : np.ndarray
A 2D NumPy array of shape `(size, size)` representing the grid, where `1`
denotes an obstacle and `0` a free cell.
G : networkx.Graph
A 2D grid graph where each node is a tuple `(x, y)`. Edges connect 4-neighboring
nodes (up, down, left, right). Nodes corresponding to obstacles are removed.
"""
n = size
grid = np.zeros((n, n))
G = nx.grid_2d_graph(n, n)

obstacles = set()

if obstacle_mode == "ratio":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tu pourrais détecter automatiquement ton mode en fonction de la valeur de obstacle num. Si 0<=num<1 c'est ratio, si num >= 1 c'est le count.

num_obstacles = int(n * n * obstacle_ratio)
else:
num_obstacles = obstacle_number

while len(obstacles) < num_obstacles:
x, y = random.randint(0, n - 1), random.randint(0, n - 1)
if (x, y) != (0, 0) and (x, y) != (n - 1, n - 1):
obstacles.add((x, y))
grid[x, y] = 1 # Add an obstacle
if (x, y) in G:
G.remove_node((x, y))

return grid, G

82 changes: 82 additions & 0 deletions scripts/generate_random_grids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Generate random grids/graphs with obstacles.
This script can optionally suppress the output
display of the grid and graph nodes.
The generated graphs are saved as .npz files.
"""

import argparse
from my_research.utils.grid_dijkstra import generer_grille, save_graph
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any module named "my_research" in your PR. Are you sure it's the right path?



def _build_arg_parser():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawTextHelpFormatter
)

parser.add_argument(
'--size', type=int, default=10,
help="Size of the grid (grid will be of shape size x size)."
)

parser.add_argument(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Va voir dans scilpy pour trouver un mutually exclusive arguments.

Tu pourrais mettre un --number OU un --number avec un float pour obstacle et int pour number et c'est argparse qui empêche de mettre les deux à la fois

'--obstacles', type=str, default='ratio:0.2',
help="Obstacle settings: 'ratio:<value>' or 'number:<value>'"
)

parser.add_argument(
'--output', type=str, required=True,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le type par défaut c'est str, tu peux retirer le type si c'est str

help="Output format: 'filename.npz;<number>'. "
"This will generate <number> files like 'filename_0.npz', etc."
)

parser.add_argument(
'--save_only', action='store_true',
help="If set, suppress grid and node outputs."
)

return parser


def parse_obstacle_mode(obstacle_str):
mode, value_str = obstacle_str.split(':')
value = float(value_str) if mode == 'ratio' else int(value_str)

if mode == 'ratio' and not (0 <= value <= 1):
raise ValueError(
f"The obstacle ratio must be between 0 and 1 (received: {value})")

return mode, value


def main():
parser = _build_arg_parser()
args = parser.parse_args()

mode, value = parse_obstacle_mode(args.obstacles)

file, number = args.output.split(';')
number = int(number)

grid, G = (
generer_grille(args.size, mode, value)
if mode == "ratio"
else generer_grille(args.size, mode, value, value)
)

if not args.save_only:
print(f"{number} graphs saved as '{file}_X.npz'.")
print("Grille générée :")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mets en anglais.

print(grid)
print("Graph nodes:", list(G.nodes))

for i in range(number):
save_graph(G, f"{file}_{i}.npz")


if __name__ == "__main__":
main()