Files
git.stella-ops.org/src/__Libraries/StellaOps.ElkSharp/ElkEdgeRouterIterative.LocalRepair.Selection.cs

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;
}
}