# Inire Configuration & API Documentation This document describes the current public API for `inire`. ## 1. Primary API ### `RoutingProblem` `RoutingProblem` describes the physical routing problem: - `bounds` - `nets` - `static_obstacles` - `initial_paths` - `clearance` - `safety_zone_radius` ### `RoutingOptions` `RoutingOptions` groups all expert controls for the routing engine: - `search` - `objective` - `congestion` - `refinement` - `diagnostics` Route a problem with: ```python run = route(problem, options=options) ``` If you omit `options`, `route(problem)` uses `RoutingOptions()` defaults. The package root is the stable API surface. Deep imports under `inire.router.*` and `inire.geometry.*` remain accessible for advanced use, but they are unstable semi-private interfaces and may change without notice. Stable example: ```python from inire import route, RoutingOptions, RoutingProblem ``` Unstable example: ```python from inire.router._router import PathFinder ``` ### Incremental routing with locked geometry For incremental workflows, route one problem, reuse the result's locked geometry, and feed it into the next problem: ```python run_a = route(problem_a) problem_b = RoutingProblem( bounds=problem_a.bounds, nets=(...), static_obstacles=run_a.results_by_net["netA"].locked_geometry, ) run_b = route(problem_b) ``` `RoutingResult.locked_geometry` stores canonical physical geometry only. The next run applies its own clearance rules when treating it as a static obstacle. ### Initial paths with `PathSeed` Use `RoutingProblem.initial_paths` to provide semantic per-net seeds. Seeds are materialized with the current width, clearance, and bend collision settings for the run, and partial seeds are retried by normal routing in later iterations. ## 2. Search Options `RoutingOptions.search` is a `SearchOptions` object. | Field | Default | Description | | :-- | :-- | :-- | | `node_limit` | `1_000_000` | Maximum number of states to explore per net. | | `max_straight_length` | `2000.0` | Maximum length of a single straight segment. | | `min_straight_length` | `5.0` | Minimum length of a single straight segment. | | `greedy_h_weight` | `1.5` | Heuristic weight. `1.0` is optimal but slower. | | `bend_radii` | `(50.0, 100.0)` | Available radii for 90-degree bends. | | `sbend_radii` | `(10.0,)` | Available radii for S-bends. | | `sbend_offsets` | `None` | Optional explicit lateral offsets for S-bends. | | `bend_collision_type` | `"arc"` | Bend collision/proxy model: `"arc"`, `"bbox"`, `"clipped_bbox"`, or, for backward compatibility, a custom polygon. A legacy custom polygon here is treated as both the physical bend and its proxy unless overridden by the split fields below. | | `bend_proxy_geometry` | `None` | Optional explicit bend proxy geometry. Use this when you want a custom search/collision envelope that differs from the routed bend shape. Supplying only a custom polygon proxy warns and keeps the physical bend as the standard arc. | | `bend_physical_geometry` | `None` | Optional explicit bend physical geometry. Use `"arc"` or a custom polygon. If you set a custom physical polygon and do not set a proxy, the proxy defaults to the same polygon. | | `bend_clip_margin` | `None` | Optional legacy shrink margin for `"clipped_bbox"`. Leave `None` for the default 8-point proxy. | | `visibility_guidance` | `"tangent_corner"` | Visibility-derived straight candidate strategy. | ## 3. Objective Weights `RoutingOptions.objective` and `RoutingOptions.refinement.objective` use `ObjectiveWeights`. | Field | Default | Description | | :-- | :-- | :-- | | `unit_length_cost` | `1.0` | Cost per unit length. | | `bend_penalty` | `250.0` | Flat bend penalty before radius scaling. | | `sbend_penalty` | `500.0` | Flat S-bend penalty. | | `danger_weight` | `1.0` | Weight applied to danger-map proximity costs. | ## 4. Congestion Options `RoutingOptions.congestion` is a `CongestionOptions` object. | Field | Default | Description | | :-- | :-- | :-- | | `max_iterations` | `10` | Maximum rip-up and reroute iterations. | | `base_penalty` | `100.0` | Starting overlap penalty for negotiated congestion. | | `multiplier` | `1.5` | Multiplier applied after an iteration still needs retries. | | `use_tiered_strategy` | `True` | Use cheaper collision proxies in the first pass when applicable. | | `net_order` | `"user"` | Net ordering strategy for warm-start seeding and routed iterations. | | `warm_start_enabled` | `True` | Run the greedy warm-start seeding pass before negotiated congestion iterations. | | `shuffle_nets` | `False` | Shuffle routing order between iterations. | | `seed` | `None` | RNG seed for shuffled routing order. | ## 5. Refinement Options `RoutingOptions.refinement` is a `RefinementOptions` object. | Field | Default | Description | | :-- | :-- | :-- | | `enabled` | `True` | Enable post-route refinement. | | `objective` | `None` | Optional override objective for refinement. `None` reuses the search objective. | ## 6. Diagnostics Options `RoutingOptions.diagnostics` is a `DiagnosticsOptions` object. | Field | Default | Description | | :-- | :-- | :-- | | `capture_expanded` | `False` | Record expanded nodes for diagnostics and visualization. | | `capture_conflict_trace` | `False` | Capture authoritative post-reverify conflict trace entries for debugging negotiated-congestion failures. | | `capture_frontier_trace` | `False` | Run an analysis-only reroute for reached-but-colliding nets and capture prune causes near their final conflict hotspots. | | `capture_iteration_trace` | `False` | Capture per-iteration and per-net route-attempt attribution for negotiated-congestion diagnosis. | | `capture_pre_pair_frontier_trace` | `False` | Capture the final unresolved pre-pair-local subset iteration plus hotspot-adjacent frontier prunes for the routed nets in that basin. | ## 7. Conflict Trace `RoutingRunResult.conflict_trace` is an immutable tuple of post-reverify conflict snapshots. It is empty unless `RoutingOptions.diagnostics.capture_conflict_trace=True`. Trace types: - `ConflictTraceEntry` - `stage`: `"iteration"`, `"restored_best"`, or `"final"` - `iteration`: Iteration index for `"iteration"` entries, otherwise `None` - `completed_net_ids`: Nets with collision-free reached-target paths at that stage - `conflict_edges`: Undirected dynamic-conflict net pairs seen after full reverify - `nets`: Per-net trace payloads in routing-order order - `NetConflictTrace` - `net_id` - `outcome` - `reached_target` - `report` - `conflicting_net_ids`: Dynamic conflicting nets for that stage - `component_conflicts`: Dynamic component-pair overlaps for that stage - `ComponentConflictTrace` - `other_net_id` - `self_component_index` - `other_component_index` The conflict trace only records dynamic net-vs-net component overlaps. Static-obstacle and self-collision details remain count-only in `RoutingReport`. Use `scripts/record_conflict_trace.py` to capture JSON and Markdown trace artifacts for the built-in trace scenarios. The default target is `example_07_large_scale_routing_no_warm_start`. ## 8. Frontier Trace `RoutingRunResult.frontier_trace` is an immutable tuple of per-net post-run frontier analyses. It is empty unless `RoutingOptions.diagnostics.capture_frontier_trace=True`. Trace types: - `NetFrontierTrace` - `net_id` - `hotspot_bounds`: Buffered bounds around the net's final dynamic component-overlap hotspots - `pruned_closed_set` - `pruned_hard_collision` - `pruned_self_collision` - `pruned_cost` - `samples`: First traced prune events near those hotspots - `FrontierPruneSample` - `reason`: `"closed_set"`, `"hard_collision"`, `"self_collision"`, or `"cost"` - `move_type` - `hotspot_index` - `parent_state` - `end_state` The frontier trace is observational only. It reruns only the final reached-but-colliding nets in analysis mode, with scratch metrics, after the routed result is already fixed. Use `scripts/record_frontier_trace.py` to capture JSON and Markdown frontier-prune artifacts for the built-in trace scenarios. The default target is `example_07_large_scale_routing_no_warm_start`. Separately from the observational trace tooling, the router may run a bounded post-loop pair-local scratch reroute before refinement when the restored best snapshot ends with final two-net reached-target dynamic conflicts. In the late all-reached low-edge regime, the negotiated-congestion loop also narrows reroutes to the current conflict set and may carry capped heavy nets forward by immediately restoring their incumbent reached-target paths instead of spending more search work on pathological late reroutes. That behavior is part of normal routing and is reported through the `pair_local_search_*` and `late_phase_capped_*` counters below. ## 9. Pre-Pair Frontier Trace `RoutingRunResult.pre_pair_frontier_trace` is either a single immutable trace entry or `None`. It is populated only when `RoutingOptions.diagnostics.capture_pre_pair_frontier_trace=True`. Trace types: - `PrePairFrontierTraceEntry` - `iteration`: The final unresolved subset-reroute iteration immediately before pair-local handoff - `routed_net_ids`: Nets rerouted in that iteration, in routing order - `conflict_edges`: Dynamic conflict edges reported for that unresolved basin - `nets`: Per-net attempt attribution plus hotspot-adjacent frontier rerun data - `PrePairNetTrace` - `net_id` - `nodes_expanded` - `congestion_check_calls` - `pruned_closed_set` - `pruned_cost` - `pruned_hard_collision` - `guidance_seed_present` - `frontier`: A `NetFrontierTrace` captured against the restored best unresolved state Use `scripts/record_pre_pair_frontier_trace.py` to capture JSON and Markdown artifacts. Its default comparison target is the solved seed-42 no-warm canary versus the heavier seed-43 no-warm canary. ## 10. Iteration Trace `RoutingRunResult.iteration_trace` is an immutable tuple of negotiated-congestion iteration summaries. It is empty unless `RoutingOptions.diagnostics.capture_iteration_trace=True`. Trace types: - `IterationTraceEntry` - `iteration` - `congestion_penalty`: Penalty in effect for that iteration - `routed_net_ids`: Nets rerouted during that iteration, in routing order - `completed_nets` - `conflict_edges` - `total_dynamic_collisions` - `nodes_expanded` - `congestion_check_calls` - `congestion_candidate_ids` - `congestion_exact_pair_checks` - `net_attempts`: Per-net attribution for that iteration - `IterationNetAttemptTrace` - `net_id` - `reached_target` - `nodes_expanded` - `congestion_check_calls` - `pruned_closed_set` - `pruned_cost` - `pruned_hard_collision` - `guidance_seed_present` Use `scripts/record_iteration_trace.py` to capture JSON and Markdown iteration-attribution artifacts. Its default comparison target is the solved seed-42 no-warm canary versus the pathological seed-43 no-warm canary. ## 11. RouteMetrics `RoutingRunResult.metrics` is an immutable per-run snapshot. ### Search Counters - `nodes_expanded`: Total nodes expanded during the run. - `moves_generated`: Total candidate moves generated during the run. - `moves_added`: Total candidate moves admitted to the open set. - `pruned_closed_set`: Total moves pruned because the state was already closed at lower cost. - `pruned_hard_collision`: Total moves pruned by hard collision checks. - `pruned_cost`: Total moves pruned by cost ceilings or invalid costs. - `route_iterations`: Number of negotiated-congestion iterations entered. - `nets_routed`: Number of net-routing attempts executed across all iterations. - `nets_reached_target`: Number of those attempts that reached the requested target port. - `warm_start_paths_built`: Number of warm-start seed paths built by the greedy bootstrap pass. - `warm_start_paths_used`: Number of routing attempts satisfied directly from an initial or warm-start path. - `refine_path_calls`: Number of completed paths passed through the post-route refiner. - `timeout_events`: Number of timeout exits encountered during the run. - `iteration_reverify_calls`: Number of end-of-iteration full reverify passes against the final installed dynamic geometry. - `iteration_reverified_nets`: Number of reached-target nets reverified at iteration boundaries. - `iteration_conflicting_nets`: Total unique nets found in end-of-iteration dynamic conflicts. - `iteration_conflict_edges`: Total undirected dynamic-conflict edges observed at iteration boundaries. - `nets_carried_forward`: Number of nets retained unchanged between iterations. ### Cache Counters - `move_cache_abs_hits` / `move_cache_abs_misses`: Absolute move-geometry cache activity. - `move_cache_rel_hits` / `move_cache_rel_misses`: Relative move-geometry cache activity. - `guidance_match_moves`: Number of moves that matched the reroute guidance seed and received the guidance bonus. - `guidance_match_moves_straight`, `guidance_match_moves_bend90`, `guidance_match_moves_sbend`: Guidance-match counts split by move type. - `guidance_bonus_applied`: Total reroute-guidance bonus subtracted from move costs across the run. - `guidance_bonus_applied_straight`, `guidance_bonus_applied_bend90`, `guidance_bonus_applied_sbend`: Guidance bonus totals split by move type. - `static_safe_cache_hits`: Reuse count for the static-safe admission cache. - `hard_collision_cache_hits`: Reuse count for the hard-collision cache. - `congestion_cache_hits` / `congestion_cache_misses`: Per-search congestion-cache activity. ### Index And Collision Counters - `dynamic_path_objects_added` / `dynamic_path_objects_removed`: Dynamic-path geometry objects inserted into or removed from the live routing index. - `dynamic_tree_rebuilds`: Number of dynamic STRtree rebuilds. - `dynamic_grid_rebuilds`: Number of dynamic congestion-grid rebuilds. - `static_tree_rebuilds`: Number of static dilated-obstacle STRtree rebuilds. - `static_raw_tree_rebuilds`: Number of raw static-obstacle STRtree rebuilds used for verification. - `static_net_tree_rebuilds`: Number of net-width-specific static STRtree rebuilds. - `visibility_corner_index_builds`: Number of lazy corner-index rebuilds. - `visibility_builds`: Number of exact corner-visibility graph rebuilds. - `visibility_corner_pairs_checked`: Number of corner-pair visibility probes considered while building the exact graph. - `visibility_corner_queries_exact` / `visibility_corner_hits_exact`: Exact-corner visibility query activity. - `visibility_point_queries`, `visibility_point_cache_hits`, `visibility_point_cache_misses`: Arbitrary-point visibility query and cache activity. - `ray_cast_calls`: Number of ray-cast queries issued against static obstacles. - `ray_cast_candidate_bounds`: Total broad-phase candidate bounds considered by ray casts. - `ray_cast_exact_geometry_checks`: Total exact non-rectangular geometry checks performed by ray casts. - `congestion_check_calls`: Number of congestion broad-phase checks requested by search. - `congestion_presence_cache_hits` / `congestion_presence_cache_misses`: Reuse of cached per-span booleans indicating whether a move polygon could overlap any other routed net at all. - `congestion_presence_skips`: Number of moves that bypassed full congestion evaluation because the presence precheck found no other routed nets in any covered dynamic-grid span. - `congestion_candidate_precheck_hits` / `congestion_candidate_precheck_misses`: Reuse of cached conservative per-span booleans indicating whether any candidate nets survive the net-envelope and grid-net broad phases. - `congestion_candidate_precheck_skips`: Number of moves that bypassed full congestion evaluation because the candidate-net precheck found no surviving candidate nets after those broad phases. - `congestion_candidate_nets`: Total candidate net ids returned by the dynamic net-envelope broad phase during routing. - `congestion_net_envelope_cache_hits` / `congestion_net_envelope_cache_misses`: Reuse of cached dynamic net-envelope candidate sets keyed by the queried grid-cell span. - `congestion_grid_net_cache_hits` / `congestion_grid_net_cache_misses`: Reuse of cached per-span candidate net ids gathered from dynamic grid occupancy. - `congestion_grid_span_cache_hits` / `congestion_grid_span_cache_misses`: Reuse of cached dynamic-path candidate unions keyed by the queried grid-cell span. - `congestion_lazy_resolutions`: Number of popped nodes whose pending congestion was resolved lazily. - `congestion_lazy_requeues`: Number of lazily resolved nodes requeued after a positive congestion penalty was applied. - `congestion_candidate_ids`: Total dynamic-path object ids returned by the congestion broad phase before exact confirmation. - `congestion_exact_pair_checks`: Number of exact geometry-pair checks performed while confirming congestion hits. ### Verification Counters - `verify_path_report_calls`: Number of full path-verification passes. - `verify_static_buffer_ops`: Number of static-verification `buffer()` operations. - `verify_dynamic_candidate_nets`: Total candidate net ids returned by the dynamic net-envelope broad phase during final verification. - `verify_dynamic_exact_pair_checks`: Number of exact geometry-pair checks performed during dynamic-path verification. ### Local Search Counters - `pair_local_search_pairs_considered`: Number of final reached-target conflict pairs considered by the bounded post-loop pair-local-search phase. - `pair_local_search_attempts`: Number of pair-local-search reroute attempts executed across all considered pairs. - `pair_local_search_accepts`: Number of pair-local-search attempts accepted into the whole routed result set. - `pair_local_search_nodes_expanded`: Total A* node expansions spent inside pair-local-search attempts. - `late_phase_capped_nets`: Number of heavy nets identified in the final all-reached late phase and handled by the capped carry-forward path before pair-local handoff. - `late_phase_capped_fallbacks`: Number of those capped late-phase nets that kept their incumbent reached-target paths instead of accepting a newly searched replacement. ## 10. Internal Modules Lower-level search and collision modules are semi-private implementation details. They remain accessible through deep imports for advanced use, but they are unstable and may change without notice. The stable supported entrypoint is `route(problem, options=...)`. The current implementation structure is summarized in **[docs/architecture.md](docs/architecture.md)**. The committed example-corpus counter baseline is tracked in **[docs/performance.md](docs/performance.md)**. Use `scripts/diff_performance_baseline.py` to compare a fresh local run against that baseline. Use `scripts/record_conflict_trace.py` for opt-in conflict-hotspot traces, `scripts/record_frontier_trace.py` for hotspot-adjacent prune traces, `scripts/record_pre_pair_frontier_trace.py` for the final unresolved pre-pair basin, `scripts/record_iteration_trace.py` for per-iteration negotiated-congestion attribution, and `scripts/characterize_pair_local_search.py` to sweep example_07-style no-warm runs for pair-local repair behavior. The counter baseline is currently observational and is not enforced as a CI gate. ## 11. Tuning Notes ### Speed vs. optimality - Lower `search.greedy_h_weight` toward `1.0` for better optimality. - Raise `search.greedy_h_weight` for faster, greedier routing. ### Congestion handling - Increase `congestion.base_penalty` to separate nets more aggressively in the first iteration. - Increase `congestion.max_iterations` if congestion needs more reroute passes. - Increase `congestion.multiplier` if later iterations need to escalate more quickly. ### Bend-heavy routes - Increase `objective.bend_penalty` to discourage ladders of small bends. - Increase available `search.bend_radii` when larger turns are physically acceptable. - Use `search.bend_physical_geometry` and `search.bend_proxy_geometry` together when you need a real custom bend shape plus a different conservative proxy. ### Visibility guidance - `"tangent_corner"` is the default and best general-purpose setting in obstacle-dense layouts. - `"exact_corner"` is more conservative. - `"off"` disables visibility-derived straight candidates. ### S-bends - Leave `search.sbend_offsets=None` to let the router derive natural offsets automatically. - Provide explicit `search.sbend_offsets` for known process-preferred offsets. - S-bends are only used for offsets smaller than `2R`.