add various direction examples
This commit is contained in:
parent
556241bae3
commit
4cbd15bc0d
4 changed files with 63 additions and 1 deletions
|
|
@ -62,6 +62,8 @@ Check the `examples/` directory for ready-to-run scripts demonstrating core feat
|
||||||
* **`examples/01_simple_route.py`**: Basic single-net routing with visualization.
|
* **`examples/01_simple_route.py`**: Basic single-net routing with visualization.
|
||||||
* **`examples/02_congestion_resolution.py`**: Multi-net routing resolving bottlenecks using Negotiated Congestion.
|
* **`examples/02_congestion_resolution.py`**: Multi-net routing resolving bottlenecks using Negotiated Congestion.
|
||||||
* **`examples/03_locked_paths.py`**: Incremental workflow using `lock_net()` to route around previously fixed paths.
|
* **`examples/03_locked_paths.py`**: Incremental workflow using `lock_net()` to route around previously fixed paths.
|
||||||
|
* **`examples/04_sbends_and_radii.py`**: Complex paths using parametric S-bends and multiple bend radii.
|
||||||
|
* **`examples/05_orientation_stress.py`**: Stress test for various port orientation combinations (U-turns, opposite directions).
|
||||||
|
|
||||||
Run an example:
|
Run an example:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
56
examples/05_orientation_stress.py
Normal file
56
examples/05_orientation_stress.py
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
from inire.geometry.collision import CollisionEngine
|
||||||
|
from inire.geometry.primitives import Port
|
||||||
|
from inire.router.astar import AStarRouter
|
||||||
|
from inire.router.cost import CostEvaluator
|
||||||
|
from inire.router.danger_map import DangerMap
|
||||||
|
from inire.router.pathfinder import PathFinder
|
||||||
|
from inire.utils.visualization import plot_routing_results
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("Running Example 05: Orientation Stress Test...")
|
||||||
|
|
||||||
|
# 1. Setup Environment
|
||||||
|
# Give some breathing room (-20 to 120) for U-turns and flips (R=10)
|
||||||
|
bounds = (-20, -20, 120, 120)
|
||||||
|
engine = CollisionEngine(clearance=2.0)
|
||||||
|
danger_map = DangerMap(bounds=bounds)
|
||||||
|
danger_map.precompute([])
|
||||||
|
|
||||||
|
evaluator = CostEvaluator(engine, danger_map, greedy_h_weight=1.1)
|
||||||
|
router = AStarRouter(evaluator, node_limit=100000)
|
||||||
|
pf = PathFinder(router, evaluator)
|
||||||
|
|
||||||
|
# 2. Define Netlist with various orientation challenges
|
||||||
|
netlist = {
|
||||||
|
# Opposite directions: requires two 90-degree bends to flip orientation
|
||||||
|
"opposite": (Port(10, 80, 0), Port(90, 80, 180)),
|
||||||
|
|
||||||
|
# 90-degree turn: standard L-shape
|
||||||
|
"turn_90": (Port(10, 60, 0), Port(40, 90, 90)),
|
||||||
|
|
||||||
|
# Output behind input: requires a full U-turn
|
||||||
|
"behind": (Port(80, 40, 0), Port(20, 40, 0)),
|
||||||
|
|
||||||
|
# Sharp return: output is behind and oriented towards the input
|
||||||
|
"return_loop": (Port(80, 20, 0), Port(40, 10, 180)),
|
||||||
|
}
|
||||||
|
net_widths = {nid: 2.0 for nid in netlist}
|
||||||
|
|
||||||
|
# 3. Route
|
||||||
|
results = pf.route_all(netlist, net_widths)
|
||||||
|
|
||||||
|
# 4. Check Results
|
||||||
|
for nid, res in results.items():
|
||||||
|
status = "Success" if res.is_valid else "Failed"
|
||||||
|
total_len = sum(comp.length for comp in res.path) if res.path else 0
|
||||||
|
print(f" {nid:12}: {status}, total_length={total_len:.1f}")
|
||||||
|
|
||||||
|
# 5. Visualize
|
||||||
|
fig, ax = plot_routing_results(results, [], bounds, netlist=netlist)
|
||||||
|
fig.savefig("examples/orientation_stress.png")
|
||||||
|
print("Saved plot to examples/orientation_stress.png")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
examples/orientation_stress.png
Normal file
BIN
examples/orientation_stress.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
|
|
@ -70,6 +70,10 @@ class DangerMap:
|
||||||
safe_distances = np.maximum(distances, 0.1)
|
safe_distances = np.maximum(distances, 0.1)
|
||||||
self.grid = np.where(distances < self.safety_threshold, self.k / (safe_distances**2), 0.0).astype(np.float32)
|
self.grid = np.where(distances < self.safety_threshold, self.k / (safe_distances**2), 0.0).astype(np.float32)
|
||||||
|
|
||||||
|
def is_within_bounds(self, x: float, y: float) -> bool:
|
||||||
|
"""Check if a coordinate is within the design bounds."""
|
||||||
|
return self.minx <= x <= self.maxx and self.miny <= y <= self.maxy
|
||||||
|
|
||||||
def get_cost(self, x: float, y: float) -> float:
|
def get_cost(self, x: float, y: float) -> float:
|
||||||
"""Get the proximity cost at a specific coordinate."""
|
"""Get the proximity cost at a specific coordinate."""
|
||||||
ix = int((x - self.minx) / self.resolution)
|
ix = int((x - self.minx) / self.resolution)
|
||||||
|
|
@ -77,4 +81,4 @@ class DangerMap:
|
||||||
|
|
||||||
if 0 <= ix < self.width_cells and 0 <= iy < self.height_cells:
|
if 0 <= ix < self.width_cells and 0 <= iy < self.height_cells:
|
||||||
return float(self.grid[ix, iy])
|
return float(self.grid[ix, iy])
|
||||||
return 1e6 # Outside bounds is expensive
|
return 1e15 # Outside bounds is impossible
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue