various performance work (wip)
This commit is contained in:
parent
e77fd6e69f
commit
71e263c527
25 changed files with 4071 additions and 326 deletions
|
|
@ -16,6 +16,12 @@ from inire import (
|
|||
route,
|
||||
)
|
||||
from inire.geometry.components import Straight
|
||||
from inire.geometry.collision import RoutingWorld
|
||||
from inire.results import RoutingReport, RoutingResult
|
||||
from inire.router._astar_types import AStarContext
|
||||
from inire.router._router import PathFinder, _IterationReview
|
||||
from inire.router.cost import CostEvaluator
|
||||
from inire.router.danger_map import DangerMap
|
||||
|
||||
|
||||
def test_root_module_exports_only_stable_surface() -> None:
|
||||
|
|
@ -77,14 +83,177 @@ def test_route_problem_supports_configs_and_debug_data() -> None:
|
|||
assert run.expanded_nodes
|
||||
assert run.metrics.nodes_expanded > 0
|
||||
assert run.metrics.route_iterations >= 1
|
||||
assert run.metrics.iteration_reverify_calls >= 1
|
||||
assert run.metrics.iteration_reverified_nets >= 0
|
||||
assert run.metrics.iteration_conflicting_nets >= 0
|
||||
assert run.metrics.iteration_conflict_edges >= 0
|
||||
assert run.metrics.nets_carried_forward >= 0
|
||||
assert run.metrics.nets_routed >= 1
|
||||
assert run.metrics.move_cache_abs_misses >= 0
|
||||
assert run.metrics.ray_cast_calls >= 0
|
||||
assert run.metrics.dynamic_tree_rebuilds >= 0
|
||||
assert run.metrics.visibility_corner_index_builds >= 0
|
||||
assert run.metrics.visibility_builds >= 0
|
||||
assert run.metrics.congestion_grid_span_cache_hits >= 0
|
||||
assert run.metrics.congestion_grid_span_cache_misses >= 0
|
||||
assert run.metrics.congestion_presence_cache_hits >= 0
|
||||
assert run.metrics.congestion_presence_cache_misses >= 0
|
||||
assert run.metrics.congestion_presence_skips >= 0
|
||||
assert run.metrics.congestion_candidate_precheck_hits >= 0
|
||||
assert run.metrics.congestion_candidate_precheck_misses >= 0
|
||||
assert run.metrics.congestion_candidate_precheck_skips >= 0
|
||||
assert run.metrics.congestion_candidate_nets >= 0
|
||||
assert run.metrics.congestion_net_envelope_cache_hits >= 0
|
||||
assert run.metrics.congestion_net_envelope_cache_misses >= 0
|
||||
assert run.metrics.congestion_grid_net_cache_hits >= 0
|
||||
assert run.metrics.congestion_grid_net_cache_misses >= 0
|
||||
assert run.metrics.congestion_lazy_resolutions >= 0
|
||||
assert run.metrics.congestion_lazy_requeues >= 0
|
||||
assert run.metrics.congestion_candidate_ids >= 0
|
||||
assert run.metrics.verify_dynamic_candidate_nets >= 0
|
||||
assert run.metrics.verify_path_report_calls >= 0
|
||||
|
||||
|
||||
def test_iteration_callback_observes_reverified_conflicts() -> None:
|
||||
problem = RoutingProblem(
|
||||
bounds=(0, 0, 100, 100),
|
||||
nets=(
|
||||
NetSpec("horizontal", Port(10, 50, 0), Port(90, 50, 0), width=2.0),
|
||||
NetSpec("vertical", Port(50, 10, 90), Port(50, 90, 90), width=2.0),
|
||||
),
|
||||
)
|
||||
options = RoutingOptions(
|
||||
congestion=CongestionOptions(max_iterations=1, warm_start_enabled=False),
|
||||
refinement=RefinementOptions(enabled=False),
|
||||
)
|
||||
evaluator = CostEvaluator(RoutingWorld(clearance=2.0), DangerMap(bounds=problem.bounds))
|
||||
pathfinder = PathFinder(AStarContext(evaluator, problem, options))
|
||||
snapshots: list[dict[str, str]] = []
|
||||
|
||||
def callback(iteration: int, current_results: dict[str, object]) -> None:
|
||||
_ = iteration
|
||||
snapshots.append({net_id: result.outcome for net_id, result in current_results.items()})
|
||||
|
||||
results = pathfinder.route_all(iteration_callback=callback)
|
||||
|
||||
assert snapshots == [{"horizontal": "colliding", "vertical": "colliding"}]
|
||||
assert results["horizontal"].outcome == "colliding"
|
||||
assert results["vertical"].outcome == "colliding"
|
||||
|
||||
|
||||
def test_reverify_iterations_stop_early_on_stalled_conflict_graph() -> None:
|
||||
problem = RoutingProblem(
|
||||
bounds=(0, 0, 100, 100),
|
||||
nets=(
|
||||
NetSpec("horizontal", Port(10, 50, 0), Port(90, 50, 0), width=2.0),
|
||||
NetSpec("vertical", Port(50, 10, 90), Port(50, 90, 90), width=2.0),
|
||||
),
|
||||
)
|
||||
options = RoutingOptions(
|
||||
congestion=CongestionOptions(max_iterations=10, warm_start_enabled=False),
|
||||
refinement=RefinementOptions(enabled=False),
|
||||
)
|
||||
|
||||
run = route(problem, options=options)
|
||||
|
||||
assert run.metrics.route_iterations < 10
|
||||
|
||||
|
||||
def test_route_all_restores_best_iteration_snapshot(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
problem = RoutingProblem(
|
||||
bounds=(0, 0, 100, 100),
|
||||
nets=(
|
||||
NetSpec("netA", Port(10, 50, 0), Port(90, 50, 0), width=2.0),
|
||||
NetSpec("netB", Port(50, 10, 90), Port(50, 90, 90), width=2.0),
|
||||
),
|
||||
)
|
||||
options = RoutingOptions(
|
||||
congestion=CongestionOptions(max_iterations=2, warm_start_enabled=False),
|
||||
refinement=RefinementOptions(enabled=False),
|
||||
)
|
||||
evaluator = CostEvaluator(RoutingWorld(clearance=2.0), DangerMap(bounds=problem.bounds))
|
||||
pathfinder = PathFinder(AStarContext(evaluator, problem, options))
|
||||
best_result = RoutingResult(
|
||||
net_id="netA",
|
||||
path=(Straight.generate(Port(10, 50, 0), 80.0, 2.0, dilation=1.0),),
|
||||
reached_target=True,
|
||||
report=RoutingReport(),
|
||||
)
|
||||
missing_result = RoutingResult(net_id="netA", path=(), reached_target=False)
|
||||
unroutable_b = RoutingResult(net_id="netB", path=(), reached_target=False)
|
||||
|
||||
def fake_run_iteration(self, state, iteration, reroute_net_ids, iteration_callback):
|
||||
_ = self
|
||||
_ = reroute_net_ids
|
||||
_ = iteration_callback
|
||||
if iteration == 0:
|
||||
state.results = {"netA": best_result, "netB": unroutable_b}
|
||||
return _IterationReview(
|
||||
conflicting_nets={"netA", "netB"},
|
||||
conflict_edges={("netA", "netB")},
|
||||
completed_net_ids={"netA"},
|
||||
total_dynamic_collisions=1,
|
||||
)
|
||||
state.results = {"netA": missing_result, "netB": unroutable_b}
|
||||
return _IterationReview(
|
||||
conflicting_nets={"netA", "netB"},
|
||||
conflict_edges={("netA", "netB")},
|
||||
completed_net_ids=set(),
|
||||
total_dynamic_collisions=2,
|
||||
)
|
||||
|
||||
monkeypatch.setattr(PathFinder, "_run_iteration", fake_run_iteration)
|
||||
monkeypatch.setattr(PathFinder, "_verify_results", lambda self, state: dict(state.results))
|
||||
|
||||
results = pathfinder.route_all()
|
||||
|
||||
assert results["netA"].outcome == "completed"
|
||||
assert results["netB"].outcome == "unroutable"
|
||||
|
||||
|
||||
def test_route_all_restores_best_iteration_snapshot_on_timeout(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
problem = RoutingProblem(
|
||||
bounds=(0, 0, 100, 100),
|
||||
nets=(NetSpec("netA", Port(10, 50, 0), Port(90, 50, 0), width=2.0),),
|
||||
)
|
||||
options = RoutingOptions(
|
||||
congestion=CongestionOptions(max_iterations=2, warm_start_enabled=False),
|
||||
refinement=RefinementOptions(enabled=False),
|
||||
)
|
||||
evaluator = CostEvaluator(RoutingWorld(clearance=2.0), DangerMap(bounds=problem.bounds))
|
||||
pathfinder = PathFinder(AStarContext(evaluator, problem, options))
|
||||
best_result = RoutingResult(
|
||||
net_id="netA",
|
||||
path=(Straight.generate(Port(10, 50, 0), 80.0, 2.0, dilation=1.0),),
|
||||
reached_target=True,
|
||||
report=RoutingReport(),
|
||||
)
|
||||
worse_result = RoutingResult(net_id="netA", path=(), reached_target=False)
|
||||
|
||||
def fake_run_iterations(self, state, iteration_callback):
|
||||
_ = iteration_callback
|
||||
_ = self
|
||||
state.results = {"netA": best_result}
|
||||
pathfinder._update_best_iteration(
|
||||
state,
|
||||
_IterationReview(
|
||||
conflicting_nets=set(),
|
||||
conflict_edges=set(),
|
||||
completed_net_ids={"netA"},
|
||||
total_dynamic_collisions=0,
|
||||
),
|
||||
)
|
||||
state.results = {"netA": worse_result}
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(PathFinder, "_run_iterations", fake_run_iterations)
|
||||
monkeypatch.setattr(PathFinder, "_verify_results", lambda self, state: dict(state.results))
|
||||
|
||||
results = pathfinder.route_all()
|
||||
|
||||
assert results["netA"].outcome == "completed"
|
||||
|
||||
|
||||
def test_route_problem_locked_routes_become_static_obstacles() -> None:
|
||||
locked = (Straight.generate(Port(10, 50, 0), 80.0, 2.0, dilation=1.0),)
|
||||
problem = RoutingProblem(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue