76 lines
3.2 KiB
C#
76 lines
3.2 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
|
|
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRouterIterative
|
|
{
|
|
private static CandidateSolution ApplyWinnerDetourPolish(
|
|
CandidateSolution solution,
|
|
ElkPositionedNode[] nodes,
|
|
double minLineClearance)
|
|
{
|
|
var focusSeverity = new Dictionary<string, int>(StringComparer.Ordinal);
|
|
ElkEdgeRoutingScoring.CountExcessiveDetourViolations(solution.Edges, nodes, focusSeverity, 10);
|
|
ElkEdgeRoutingScoring.CountGatewaySourceExitViolations(solution.Edges, nodes, focusSeverity, 10);
|
|
|
|
if (focusSeverity.Count > 0)
|
|
{
|
|
var batchedRootEdgeIds = focusSeverity
|
|
.OrderByDescending(pair => pair.Value)
|
|
.ThenBy(pair => pair.Key, StringComparer.Ordinal)
|
|
.Take(Math.Min(focusSeverity.Count, MaxWinnerPolishBatchedRootEdges + 2))
|
|
.Select(pair => pair.Key)
|
|
.ToArray();
|
|
var batchedFocusEdgeIds = ExpandWinningSolutionFocus(solution.Edges, batchedRootEdgeIds).ToArray();
|
|
if (batchedFocusEdgeIds.Length > 0)
|
|
{
|
|
var batchedCandidateEdges = ComposeTransactionalFinalDetourCandidate(
|
|
solution.Edges,
|
|
nodes,
|
|
minLineClearance,
|
|
batchedFocusEdgeIds);
|
|
batchedCandidateEdges = ChoosePreferredHardRuleLayout(solution.Edges, batchedCandidateEdges, nodes);
|
|
if (TryPromoteFinalDetourCandidate(
|
|
solution.Edges,
|
|
batchedCandidateEdges,
|
|
nodes,
|
|
solution.Score,
|
|
solution.RetryState,
|
|
out var batchedPromotedEdges))
|
|
{
|
|
var batchedPromotedScore = ElkEdgeRoutingScoring.ComputeScore(batchedPromotedEdges, nodes);
|
|
var batchedPromotedRetryState = BuildRetryState(
|
|
batchedPromotedScore,
|
|
HighwayProcessingEnabled
|
|
? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(batchedPromotedEdges, nodes).Count
|
|
: 0);
|
|
|
|
solution = new CandidateSolution(
|
|
batchedPromotedScore,
|
|
batchedPromotedRetryState,
|
|
batchedPromotedEdges,
|
|
solution.StrategyIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
var candidateEdges = ApplyFinalDetourPolish(solution.Edges, nodes, minLineClearance, restrictedEdgeIds: null);
|
|
if (ReferenceEquals(candidateEdges, solution.Edges))
|
|
{
|
|
return solution;
|
|
}
|
|
|
|
var candidateScore = ElkEdgeRoutingScoring.ComputeScore(candidateEdges, nodes);
|
|
var candidateRetryState = BuildRetryState(
|
|
candidateScore,
|
|
HighwayProcessingEnabled
|
|
? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(candidateEdges, nodes).Count
|
|
: 0);
|
|
|
|
return new CandidateSolution(candidateScore, candidateRetryState, candidateEdges, solution.StrategyIndex);
|
|
}
|
|
|
|
}
|