Refactor ElkSharp hybrid routing and document speed path
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
namespace StellaOps.ElkSharp;
|
||||
|
||||
internal static partial class ElkEdgeRouterIterative
|
||||
{
|
||||
private static bool IsBetterCandidate(
|
||||
EdgeRoutingScore candidate,
|
||||
RoutingRetryState candidateRetryState,
|
||||
EdgeRoutingScore best,
|
||||
RoutingRetryState bestRetryState)
|
||||
{
|
||||
if (HasHardRuleRegression(candidateRetryState, bestRetryState))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var retryComparison = CompareRetryStates(candidateRetryState, bestRetryState);
|
||||
if (retryComparison != 0)
|
||||
{
|
||||
return retryComparison < 0;
|
||||
}
|
||||
|
||||
if (candidate.NodeCrossings != best.NodeCrossings)
|
||||
{
|
||||
return candidate.NodeCrossings < best.NodeCrossings;
|
||||
}
|
||||
|
||||
return candidate.Value > best.Value;
|
||||
}
|
||||
|
||||
private static bool HasHardRuleRegression(RoutingRetryState candidate, RoutingRetryState baseline)
|
||||
{
|
||||
return candidate.RemainingShortHighways > baseline.RemainingShortHighways
|
||||
|| candidate.RepeatCollectorCorridorViolations > baseline.RepeatCollectorCorridorViolations
|
||||
|| candidate.RepeatCollectorNodeClearanceViolations > baseline.RepeatCollectorNodeClearanceViolations
|
||||
|| candidate.BelowGraphViolations > baseline.BelowGraphViolations
|
||||
|| candidate.UnderNodeViolations > baseline.UnderNodeViolations
|
||||
|| candidate.LongDiagonalViolations > baseline.LongDiagonalViolations
|
||||
|| candidate.EntryAngleViolations > baseline.EntryAngleViolations
|
||||
|| candidate.GatewaySourceExitViolations > baseline.GatewaySourceExitViolations
|
||||
|| candidate.SharedLaneViolations > baseline.SharedLaneViolations
|
||||
|| candidate.BoundarySlotViolations > baseline.BoundarySlotViolations
|
||||
|| candidate.TargetApproachJoinViolations > baseline.TargetApproachJoinViolations
|
||||
|| candidate.TargetApproachBacktrackingViolations > baseline.TargetApproachBacktrackingViolations
|
||||
|| candidate.ExcessiveDetourViolations > baseline.ExcessiveDetourViolations;
|
||||
}
|
||||
|
||||
private static bool HasBlockingSharedLanePromotionRegression(
|
||||
RoutingRetryState candidate,
|
||||
RoutingRetryState baseline)
|
||||
{
|
||||
var allowsTemporaryBoundarySlotTrade =
|
||||
candidate.SharedLaneViolations < baseline.SharedLaneViolations
|
||||
&& baseline.BoundarySlotViolations > 0
|
||||
&& candidate.BoundarySlotViolations <= baseline.BoundarySlotViolations + 1;
|
||||
|
||||
return candidate.RemainingShortHighways > baseline.RemainingShortHighways
|
||||
|| candidate.RepeatCollectorCorridorViolations > baseline.RepeatCollectorCorridorViolations
|
||||
|| candidate.RepeatCollectorNodeClearanceViolations > baseline.RepeatCollectorNodeClearanceViolations
|
||||
|| candidate.BelowGraphViolations > baseline.BelowGraphViolations
|
||||
|| candidate.UnderNodeViolations > baseline.UnderNodeViolations
|
||||
|| candidate.LongDiagonalViolations > baseline.LongDiagonalViolations
|
||||
|| candidate.EntryAngleViolations > baseline.EntryAngleViolations
|
||||
|| candidate.GatewaySourceExitViolations > baseline.GatewaySourceExitViolations
|
||||
|| candidate.SharedLaneViolations > baseline.SharedLaneViolations
|
||||
|| (!allowsTemporaryBoundarySlotTrade
|
||||
&& candidate.BoundarySlotViolations > baseline.BoundarySlotViolations)
|
||||
|| candidate.TargetApproachJoinViolations > baseline.TargetApproachJoinViolations
|
||||
|| candidate.TargetApproachBacktrackingViolations > baseline.TargetApproachBacktrackingViolations
|
||||
|| candidate.ExcessiveDetourViolations > baseline.ExcessiveDetourViolations;
|
||||
}
|
||||
|
||||
private static int CompareRetryStates(RoutingRetryState left, RoutingRetryState right)
|
||||
{
|
||||
if (left.RemainingShortHighways != right.RemainingShortHighways)
|
||||
{
|
||||
return left.RemainingShortHighways.CompareTo(right.RemainingShortHighways);
|
||||
}
|
||||
|
||||
if (left.RepeatCollectorCorridorViolations != right.RepeatCollectorCorridorViolations)
|
||||
{
|
||||
return left.RepeatCollectorCorridorViolations.CompareTo(right.RepeatCollectorCorridorViolations);
|
||||
}
|
||||
|
||||
if (left.RepeatCollectorNodeClearanceViolations != right.RepeatCollectorNodeClearanceViolations)
|
||||
{
|
||||
return left.RepeatCollectorNodeClearanceViolations.CompareTo(right.RepeatCollectorNodeClearanceViolations);
|
||||
}
|
||||
|
||||
if (left.BelowGraphViolations != right.BelowGraphViolations)
|
||||
{
|
||||
return left.BelowGraphViolations.CompareTo(right.BelowGraphViolations);
|
||||
}
|
||||
|
||||
if (left.UnderNodeViolations != right.UnderNodeViolations)
|
||||
{
|
||||
return left.UnderNodeViolations.CompareTo(right.UnderNodeViolations);
|
||||
}
|
||||
|
||||
if (left.LongDiagonalViolations != right.LongDiagonalViolations)
|
||||
{
|
||||
return left.LongDiagonalViolations.CompareTo(right.LongDiagonalViolations);
|
||||
}
|
||||
|
||||
if (left.EntryAngleViolations != right.EntryAngleViolations)
|
||||
{
|
||||
return left.EntryAngleViolations.CompareTo(right.EntryAngleViolations);
|
||||
}
|
||||
|
||||
if (left.GatewaySourceExitViolations != right.GatewaySourceExitViolations)
|
||||
{
|
||||
return left.GatewaySourceExitViolations.CompareTo(right.GatewaySourceExitViolations);
|
||||
}
|
||||
|
||||
if (left.SharedLaneViolations != right.SharedLaneViolations)
|
||||
{
|
||||
return left.SharedLaneViolations.CompareTo(right.SharedLaneViolations);
|
||||
}
|
||||
|
||||
if (left.BoundarySlotViolations != right.BoundarySlotViolations)
|
||||
{
|
||||
return left.BoundarySlotViolations.CompareTo(right.BoundarySlotViolations);
|
||||
}
|
||||
|
||||
if (left.TargetApproachJoinViolations != right.TargetApproachJoinViolations)
|
||||
{
|
||||
return left.TargetApproachJoinViolations.CompareTo(right.TargetApproachJoinViolations);
|
||||
}
|
||||
|
||||
if (left.TargetApproachBacktrackingViolations != right.TargetApproachBacktrackingViolations)
|
||||
{
|
||||
return left.TargetApproachBacktrackingViolations.CompareTo(right.TargetApproachBacktrackingViolations);
|
||||
}
|
||||
|
||||
if (left.ExcessiveDetourViolations != right.ExcessiveDetourViolations)
|
||||
{
|
||||
return left.ExcessiveDetourViolations.CompareTo(right.ExcessiveDetourViolations);
|
||||
}
|
||||
|
||||
if (left.ProximityViolations != right.ProximityViolations)
|
||||
{
|
||||
return left.ProximityViolations.CompareTo(right.ProximityViolations);
|
||||
}
|
||||
|
||||
if (left.LabelProximityViolations != right.LabelProximityViolations)
|
||||
{
|
||||
return left.LabelProximityViolations.CompareTo(right.LabelProximityViolations);
|
||||
}
|
||||
|
||||
return left.EdgeCrossings.CompareTo(right.EdgeCrossings);
|
||||
}
|
||||
|
||||
private static CandidateSolution SelectBestValidSolution(
|
||||
IReadOnlyList<CandidateSolution> solutions)
|
||||
{
|
||||
var best = solutions[0];
|
||||
for (var i = 1; i < solutions.Count; i++)
|
||||
{
|
||||
var candidate = solutions[i];
|
||||
if (IsBetterBoundarySlotRepairCandidate(
|
||||
candidate.Score,
|
||||
candidate.RetryState,
|
||||
best.Score,
|
||||
best.RetryState)
|
||||
|| candidate.Score.Value > best.Score.Value
|
||||
|| (Math.Abs(candidate.Score.Value - best.Score.Value) < 0.001d
|
||||
&& CompareRetryStates(candidate.RetryState, best.RetryState) < 0)
|
||||
|| (Math.Abs(candidate.Score.Value - best.Score.Value) < 0.001d
|
||||
&& CompareRetryStates(candidate.RetryState, best.RetryState) == 0
|
||||
&& candidate.Score.EdgeCrossings < best.Score.EdgeCrossings))
|
||||
{
|
||||
best = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
private static CandidateSolution SelectBestFallbackSolution(
|
||||
IReadOnlyList<CandidateSolution> solutions)
|
||||
{
|
||||
var best = solutions[0];
|
||||
for (var i = 1; i < solutions.Count; i++)
|
||||
{
|
||||
var candidate = solutions[i];
|
||||
if (IsBetterBoundarySlotRepairCandidate(
|
||||
candidate.Score,
|
||||
candidate.RetryState,
|
||||
best.Score,
|
||||
best.RetryState)
|
||||
|| candidate.Score.NodeCrossings < best.Score.NodeCrossings
|
||||
|| (candidate.Score.NodeCrossings == best.Score.NodeCrossings
|
||||
&& CompareRetryStates(candidate.RetryState, best.RetryState) < 0)
|
||||
|| (candidate.Score.NodeCrossings == best.Score.NodeCrossings
|
||||
&& CompareRetryStates(candidate.RetryState, best.RetryState) == 0
|
||||
&& candidate.Score.EdgeCrossings < best.Score.EdgeCrossings)
|
||||
|| (candidate.Score.NodeCrossings == best.Score.NodeCrossings
|
||||
&& CompareRetryStates(candidate.RetryState, best.RetryState) == 0
|
||||
&& candidate.Score.EdgeCrossings == best.Score.EdgeCrossings
|
||||
&& candidate.Score.Value > best.Score.Value))
|
||||
{
|
||||
best = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user