example fixes and improvements

This commit is contained in:
Jan Petykiewicz 2026-03-30 23:40:29 -07:00
commit e2c91076f7
18 changed files with 336 additions and 144 deletions

View file

@ -22,8 +22,8 @@ def main() -> None:
greedy_h_weight=1.5,
),
objective=ObjectiveWeights(
bend_penalty=250.0,
sbend_penalty=500.0,
bend_penalty=50.0,
sbend_penalty=150.0,
),
congestion=CongestionOptions(base_penalty=1000.0),
)

View file

@ -1,4 +1,7 @@
from inire import NetSpec, ObjectiveWeights, Port, RoutingOptions, RoutingProblem, SearchOptions, route
from inire import NetSpec, Port, RoutingOptions, RoutingProblem, SearchOptions
from inire.router._astar_types import AStarContext
from inire.router._router import PathFinder
from inire.router._stack import build_routing_stack
from inire.utils.visualization import plot_routing_results
@ -6,31 +9,31 @@ def main() -> None:
print("Running Example 03: Locked Paths...")
bounds = (0, -50, 100, 50)
options = RoutingOptions(
search=SearchOptions(bend_radii=(10.0,)),
objective=ObjectiveWeights(
bend_penalty=250.0,
sbend_penalty=500.0,
),
)
print("Routing initial net...")
results_a = route(
RoutingProblem(
stack = build_routing_stack(
problem=RoutingProblem(
bounds=bounds,
nets=(NetSpec("netA", Port(10, 0, 0), Port(90, 0, 0), width=2.0),),
),
options=options,
).results_by_net
options=RoutingOptions(search=SearchOptions(bend_radii=(10.0,))),
)
engine = stack.world
evaluator = stack.evaluator
results_a = stack.finder.route_all()
print("Routing detour net around locked path...")
results_b = route(
RoutingProblem(
bounds=bounds,
nets=(NetSpec("netB", Port(50, -20, 90), Port(50, 20, 90), width=2.0),),
static_obstacles=results_a["netA"].locked_geometry,
for polygon in results_a["netA"].locked_geometry:
engine.add_static_obstacle(polygon)
results_b = PathFinder(
AStarContext(
evaluator,
RoutingProblem(
bounds=bounds,
nets=(NetSpec("netB", Port(50, -20, 90), Port(50, 20, 90), width=2.0),),
),
RoutingOptions(search=SearchOptions(bend_radii=(10.0,))),
),
options=options,
).results_by_net
).route_all()
results = {**results_a, **results_b}
fig, ax = plot_routing_results(results, [], bounds)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Before After
Before After

View file

@ -1,6 +1,7 @@
from shapely.geometry import Polygon
from inire import CongestionOptions, NetSpec, ObjectiveWeights, RoutingOptions, RoutingProblem, RoutingResult, SearchOptions, route
from inire.geometry.components import BendCollisionModel, BendPhysicalGeometry
from inire.geometry.primitives import Port
from inire.utils.visualization import plot_routing_results
@ -8,10 +9,12 @@ from inire.utils.visualization import plot_routing_results
def _route_scenario(
bounds: tuple[float, float, float, float],
obstacles: list[Polygon],
bend_collision_type: str,
netlist: dict[str, tuple[Port, Port]],
widths: dict[str, float],
*,
bend_collision_type: BendCollisionModel = "arc",
bend_proxy_geometry: BendCollisionModel | None = None,
bend_physical_geometry: BendPhysicalGeometry | None = None,
bend_clip_margin: float | None = None,
) -> dict[str, RoutingResult]:
problem = RoutingProblem(
@ -23,6 +26,8 @@ def _route_scenario(
search=SearchOptions(
bend_radii=(10.0,),
bend_collision_type=bend_collision_type,
bend_proxy_geometry=bend_proxy_geometry,
bend_physical_geometry=bend_physical_geometry,
bend_clip_margin=bend_clip_margin,
),
objective=ObjectiveWeights(
@ -40,29 +45,30 @@ def main() -> None:
bounds = (-20, -20, 170, 170)
obs_arc = Polygon([(40, 110), (60, 110), (60, 130), (40, 130)])
obs_bbox = Polygon([(40, 60), (60, 60), (60, 80), (40, 80)])
obs_clipped = Polygon([(40, 10), (60, 10), (60, 30), (40, 30)])
obs_custom = Polygon([(40, 10), (60, 10), (60, 30), (40, 30)])
custom_bend = Polygon([(0, -11), (11, -11), (11, 0), (9, 0), (9, -9), (0, -9)])
obstacles = [obs_arc, obs_bbox, obs_clipped]
obstacles = [obs_arc, obs_bbox, obs_custom]
netlist_arc = {"arc_model": (Port(10, 120, 0), Port(90, 140, 90))}
netlist_bbox = {"bbox_model": (Port(10, 70, 0), Port(90, 90, 90))}
netlist_clipped = {"clipped_model": (Port(10, 20, 0), Port(90, 40, 90))}
netlist_custom = {"custom_geometry": (Port(10, 20, 0), Port(90, 40, 90))}
print("Routing Scenario 1 (Arc)...")
res_arc = _route_scenario(bounds, obstacles, "arc", netlist_arc, {"arc_model": 2.0})
res_arc = _route_scenario(bounds, obstacles, netlist_arc, {"arc_model": 2.0}, bend_collision_type="arc")
print("Routing Scenario 2 (BBox)...")
res_bbox = _route_scenario(bounds, obstacles, "bbox", netlist_bbox, {"bbox_model": 2.0})
print("Routing Scenario 3 (Clipped BBox)...")
res_clipped = _route_scenario(
res_bbox = _route_scenario(bounds, obstacles, netlist_bbox, {"bbox_model": 2.0}, bend_collision_type="bbox")
print("Routing Scenario 3 (Custom Manhattan Geometry With Matching Proxy)...")
res_custom = _route_scenario(
bounds,
obstacles,
"clipped_bbox",
netlist_clipped,
{"clipped_model": 2.0},
bend_clip_margin=1.0,
netlist_custom,
{"custom_geometry": 2.0},
bend_physical_geometry=custom_bend,
bend_proxy_geometry=custom_bend,
)
all_results = {**res_arc, **res_bbox, **res_clipped}
all_netlists = {**netlist_arc, **netlist_bbox, **netlist_clipped}
all_results = {**res_arc, **res_bbox, **res_custom}
all_netlists = {**netlist_arc, **netlist_bbox, **netlist_custom}
fig, _ax = plot_routing_results(all_results, obstacles, bounds, netlist=all_netlists)
fig.savefig("examples/06_bend_collision_models.png")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before After
Before After

View file

@ -1,65 +1,58 @@
from shapely.geometry import Polygon
from shapely.geometry import Polygon, box
from inire import CongestionOptions, NetSpec, RoutingOptions, RoutingProblem, SearchOptions
from inire.geometry.collision import RoutingWorld
from inire import CongestionOptions, NetSpec, RoutingOptions, RoutingProblem, SearchOptions, route
from inire.geometry.components import BendCollisionModel, BendPhysicalGeometry
from inire.geometry.primitives import Port
from inire.router._astar_types import AStarContext, AStarMetrics
from inire.router._router import PathFinder
from inire.router.cost import CostEvaluator
from inire.router.danger_map import DangerMap
from inire.utils.visualization import plot_routing_results
def _run_session(
bounds: tuple[float, float, float, float],
net_id: str,
start: Port,
target: Port,
*,
bend_collision_type: BendCollisionModel = "arc",
bend_proxy_geometry: BendCollisionModel | None = None,
bend_physical_geometry: BendPhysicalGeometry | None = None,
) -> dict[str, object]:
problem = RoutingProblem(
bounds=bounds,
nets=(NetSpec(net_id, start, target, width=2.0),),
)
options = RoutingOptions(
search=SearchOptions(
bend_radii=(10.0,),
bend_collision_type=bend_collision_type,
bend_proxy_geometry=bend_proxy_geometry,
bend_physical_geometry=bend_physical_geometry,
sbend_radii=(),
),
congestion=CongestionOptions(max_iterations=1, use_tiered_strategy=False),
)
return route(problem, options=options).results_by_net
def main() -> None:
print("Running Example 08: Custom Bend Geometry...")
bounds = (0, 0, 150, 150)
engine = RoutingWorld(clearance=2.0)
danger_map = DangerMap(bounds=bounds)
danger_map.precompute([])
evaluator = CostEvaluator(engine, danger_map, bend_penalty=50.0, sbend_penalty=150.0)
metrics = AStarMetrics()
start = Port(20, 20, 0)
target = Port(100, 100, 90)
custom_physical = Polygon([(0, -11), (11, -11), (11, 0), (9, 0), (9, -9), (0, -9)])
custom_proxy = box(0, -11, 11, 0)
print("Routing with standard arc...")
results_std = PathFinder(
AStarContext(
evaluator,
RoutingProblem(
bounds=bounds,
nets=(NetSpec("custom_bend", start, target, width=2.0),),
),
RoutingOptions(
search=SearchOptions(bend_radii=(10.0,), sbend_radii=()),
congestion=CongestionOptions(max_iterations=1),
),
),
metrics=metrics,
).route_all()
custom_poly = Polygon([(-10, -10), (10, -10), (10, 10), (-10, 10)])
print("Routing with custom collision model...")
results_custom = PathFinder(
AStarContext(
evaluator,
RoutingProblem(
bounds=bounds,
nets=(NetSpec("custom_model", start, target, width=2.0),),
),
RoutingOptions(
search=SearchOptions(
bend_radii=(10.0,),
bend_collision_type=custom_poly,
sbend_radii=(),
),
congestion=CongestionOptions(max_iterations=1, use_tiered_strategy=False),
),
),
metrics=AStarMetrics(),
use_tiered_strategy=False,
).route_all()
print("Routing standard arc in its own session...")
results_std = _run_session(bounds, "standard_arc", start, target)
print("Routing custom geometry with a separate custom proxy in its own session...")
results_custom = _run_session(
bounds,
"custom_geometry_and_proxy",
start,
target,
bend_physical_geometry=custom_physical,
bend_proxy_geometry=custom_proxy,
)
all_results = {**results_std, **results_custom}
fig, _ax = plot_routing_results(
@ -67,8 +60,8 @@ def main() -> None:
[],
bounds,
netlist={
"custom_bend": (start, target),
"custom_model": (start, target),
"standard_arc": (start, target),
"custom_geometry_and_proxy": (start, target),
},
)
fig.savefig("examples/08_custom_bend_geometry.png")

View file

@ -14,13 +14,14 @@ Demonstrates the Negotiated Congestion algorithm handling multiple intersecting
![Fan-Out Routing](07_large_scale_routing.png)
## 2. Custom Bend Geometry Models
## 2. Bend Geometry Models
`inire` supports multiple collision models for bends, allowing a trade-off between search speed and geometric accuracy:
* **Arc**: High-fidelity geometry (Highest accuracy).
* **BBox**: Simple axis-aligned bounding box (Fastest search).
* **Clipped BBox**: A balanced model that clips the corners of the AABB to better fit the arc (Optimal performance).
* **Custom Manhattan Geometry**: A custom 90-degree bend polygon with the same width as the normal waveguide.
Example 08 also demonstrates a custom polygonal bend geometry. It uses a centered `20x20` box as a custom bend collision model.
Example 06 uses the Manhattan polygon as both the true routed bend geometry and the collision proxy.
Example 08 compares the standard arc against a run that uses a custom physical bend plus a separate custom proxy polygon, with each net routed in its own session.
![Custom Bend Geometry](08_custom_bend_geometry.png)