--promote-failures: reroute with the connections that failed moved first
Each round routes every connection that has failed so far ahead of the rest, which keep their order. The promoted set only grows, so two groups cannot take turns failing; the best round is kept.
This commit is contained in:
@@ -65,3 +65,34 @@ def best_of_orders(
|
||||
scores = [score(r) for r in results]
|
||||
best = min(range(len(seeds)), key=lambda i: (scores[i], i))
|
||||
return results[best], seeds[best], list(zip(seeds, scores, strict=True))
|
||||
|
||||
|
||||
def promote_failures(
|
||||
dsn_text: str,
|
||||
engine: str,
|
||||
options: dict,
|
||||
*,
|
||||
rounds: int,
|
||||
seed: int | None = None,
|
||||
) -> tuple[RoutingResult, list[tuple[int, int]]]:
|
||||
"""Route, then route again with every connection that has failed so far
|
||||
moved to the front, keeping the rest in their order. Returns the best
|
||||
round's result and every round's score.
|
||||
|
||||
The promoted set only grows, so a connection that failed once keeps its
|
||||
early place and two groups cannot take turns failing. Stops early when a
|
||||
round routes everything or fails nothing new."""
|
||||
numbers = {n.name: i + 1 for i, n in enumerate(parse_dsn(dsn_text).nets)}
|
||||
first: frozenset = frozenset()
|
||||
best: RoutingResult | None = None
|
||||
scores: list[tuple[int, int]] = []
|
||||
for _ in range(max(int(rounds), 1)):
|
||||
result = route_once(dsn_text, engine, {**options, "route_first": first}, seed)
|
||||
scores.append(score(result))
|
||||
if best is None or scores[-1] < score(best):
|
||||
best = result
|
||||
failed = {(numbers.get(name), a, b) for name, a, b, zone in result.unrouted if not zone}
|
||||
if not failed or failed <= first:
|
||||
break
|
||||
first = first | failed
|
||||
return best, scores
|
||||
|
||||
Reference in New Issue
Block a user