213 lines
9.0 KiB
C#
213 lines
9.0 KiB
C#
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;
|
|
}
|
|
|
|
}
|