using System.Collections.Concurrent; using System.Diagnostics; using System.Globalization; namespace StellaOps.ElkSharp; internal static partial class ElkEdgeRouterIterative { private static CandidateSolution ApplyFinalSharedLanePolish( CandidateSolution solution, ElkPositionedNode[] nodes, ElkLayoutDirection direction, double minLineClearance, bool preferLeanTerminalCleanup = false) { var current = solution; if (current.RetryState.SharedLaneViolations <= 0) { return current; } var maxRounds = preferLeanTerminalCleanup ? 1 : 3; for (var round = 0; round < maxRounds; round++) { var sharedLaneSeverity = new Dictionary(StringComparer.Ordinal); ElkEdgeRoutingScoring.CountSharedLaneViolations(current.Edges, nodes, sharedLaneSeverity, 10); if (sharedLaneSeverity.Count == 0) { break; } var improved = false; foreach (var edgeId in sharedLaneSeverity .OrderByDescending(pair => pair.Value) .ThenBy(pair => pair.Key, StringComparer.Ordinal) .Select(pair => pair.Key)) { var focusEdgeIds = ExpandSharedLanePolishFocus(current.Edges, nodes, edgeId).ToArray(); if (focusEdgeIds.Length == 0) { continue; } var directCandidate = ElkEdgePostProcessor.SeparateSharedLaneConflicts( current.Edges, nodes, minLineClearance, focusEdgeIds); var directClosureCandidate = preferLeanTerminalCleanup ? ApplyHybridTerminalRuleCleanupRound( directCandidate, nodes, direction, minLineClearance, focusEdgeIds) : CloseRemainingTerminalViolations( directCandidate, nodes, direction, minLineClearance, focusEdgeIds); var closureCandidate = preferLeanTerminalCleanup ? ApplyHybridTerminalRuleCleanupRound( current.Edges, nodes, direction, minLineClearance, focusEdgeIds) : CloseRemainingTerminalViolations( current.Edges, nodes, direction, minLineClearance, focusEdgeIds); var aggressiveCandidate = ApplyAggressiveSharedLaneClosure( current.Edges, nodes, direction, minLineClearance, focusEdgeIds); var directRetryState = BuildRetryState( ElkEdgeRoutingScoring.ComputeScore(directCandidate, nodes), HighwayProcessingEnabled ? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(directCandidate, nodes).Count : 0); var directClosureRetryState = BuildRetryState( ElkEdgeRoutingScoring.ComputeScore(directClosureCandidate, nodes), HighwayProcessingEnabled ? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(directClosureCandidate, nodes).Count : 0); var closureRetryState = BuildRetryState( ElkEdgeRoutingScoring.ComputeScore(closureCandidate, nodes), HighwayProcessingEnabled ? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(closureCandidate, nodes).Count : 0); var aggressiveRetryState = BuildRetryState( ElkEdgeRoutingScoring.ComputeScore(aggressiveCandidate, nodes), HighwayProcessingEnabled ? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(aggressiveCandidate, nodes).Count : 0); ElkLayoutDiagnostics.LogProgress( $"Winner shared-lane focus edge={edgeId} focus=[{string.Join(", ", focusEdgeIds)}] " + $"direct={DescribeRetryState(directRetryState)} " + $"direct-closure={DescribeRetryState(directClosureRetryState)} " + $"closure={DescribeRetryState(closureRetryState)} " + $"aggressive={DescribeRetryState(aggressiveRetryState)}"); var candidateEdges = ChoosePreferredSharedLanePolishLayout(directCandidate, directClosureCandidate, nodes); candidateEdges = ChoosePreferredSharedLanePolishLayout(candidateEdges, closureCandidate, nodes); candidateEdges = ChoosePreferredSharedLanePolishLayout(candidateEdges, aggressiveCandidate, nodes); candidateEdges = ChoosePreferredSharedLanePolishLayout(current.Edges, candidateEdges, nodes); var candidateScore = ElkEdgeRoutingScoring.ComputeScore(candidateEdges, nodes); var candidateRetryState = BuildRetryState( candidateScore, HighwayProcessingEnabled ? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(candidateEdges, nodes).Count : 0); var improvedSharedLanes = candidateRetryState.SharedLaneViolations < current.RetryState.SharedLaneViolations; if (HasBlockingSharedLanePromotionRegression(candidateRetryState, current.RetryState) || (!improvedSharedLanes && !IsBetterCandidate(candidateScore, candidateRetryState, current.Score, current.RetryState))) { continue; } current = current with { Score = candidateScore, RetryState = candidateRetryState, Edges = candidateEdges, }; improved = true; break; } if (!improved) { break; } } return current; } }