Refactor ElkSharp hybrid routing and document speed path

This commit is contained in:
master
2026-03-29 19:33:46 +03:00
parent 7d6bc2b0ab
commit e8f7ad7652
89 changed files with 13280 additions and 10732 deletions

View File

@@ -0,0 +1,86 @@
namespace StellaOps.ElkSharp;
internal static partial class ElkEdgeRouterIterative
{
private static CandidateSolution RefineHybridWinningSolution(
CandidateSolution best,
ElkPositionedNode[] nodes,
ElkLayoutDirection direction,
double minLineClearance,
bool preferLowWaveRuntimePolish = false)
{
static string DescribeSolution(CandidateSolution solution)
{
return $"score={solution.Score.Value:F0} retry={DescribeRetryState(solution.RetryState)}";
}
var current = best;
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement start: {DescribeSolution(current)}");
if (current.RetryState.UnderNodeViolations > 0)
{
current = ApplyFinalDirectUnderNodePolish(current, nodes, minLineClearance);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after under-node polish: {DescribeSolution(current)}");
}
if (current.RetryState.UnderNodeViolations > 0
|| current.RetryState.TargetApproachJoinViolations > 0)
{
current = ApplyFinalProtectedLocalBundlePolish(current, nodes, minLineClearance);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after local-bundle polish: {DescribeSolution(current)}");
}
if (current.RetryState.SharedLaneViolations > 0
|| current.RetryState.TargetApproachJoinViolations > 0)
{
current = ApplyFinalSharedLanePolish(
current,
nodes,
direction,
minLineClearance,
preferLeanTerminalCleanup: preferLowWaveRuntimePolish);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after shared-lane polish: {DescribeSolution(current)}");
}
if (current.RetryState.BoundarySlotViolations > 0
|| current.RetryState.GatewaySourceExitViolations > 0
|| current.RetryState.EntryAngleViolations > 0)
{
current = ApplyFinalBoundarySlotPolish(current, nodes, direction, minLineClearance, maxRounds: 1);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after boundary-slot polish: {DescribeSolution(current)}");
}
if (current.RetryState.ExcessiveDetourViolations > 0
|| (!preferLowWaveRuntimePolish && current.RetryState.GatewaySourceExitViolations > 0))
{
current = ApplyWinnerDetourPolish(current, nodes, minLineClearance);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after detour polish: {DescribeSolution(current)}");
}
if (HasHybridHardRulePressure(current.RetryState))
{
current = preferLowWaveRuntimePolish
? ApplyHybridLeanPostSlotHardRulePolish(current, nodes, direction, minLineClearance)
: ApplyFinalPostSlotHardRulePolish(current, nodes, direction, minLineClearance, maxRounds: 1);
ElkLayoutDiagnostics.LogProgress($"Hybrid winner refinement after post-slot hard-rule polish: {DescribeSolution(current)}");
}
return current;
}
private static bool HasHybridHardRulePressure(RoutingRetryState retryState)
{
return retryState.RemainingShortHighways > 0
|| retryState.RepeatCollectorCorridorViolations > 0
|| retryState.RepeatCollectorNodeClearanceViolations > 0
|| retryState.TargetApproachJoinViolations > 0
|| retryState.TargetApproachBacktrackingViolations > 0
|| retryState.ExcessiveDetourViolations > 0
|| retryState.SharedLaneViolations > 0
|| retryState.BoundarySlotViolations > 0
|| retryState.BelowGraphViolations > 0
|| retryState.UnderNodeViolations > 0
|| retryState.EntryAngleViolations > 0
|| retryState.GatewaySourceExitViolations > 0;
}
}