public void UpdateTimes() { if (_necessaryFixes.Count == 0) { return; } ClassInvariant(); UpdateTimesLoopInvariant(); while (_necessaryFixes.Count > 0) { int current = _necessaryFixes.Min.Vertex; _necessaryFixes.Remove(_necessaryFixes.Min); foreach (Arc arc in OutgoingArcs(current)) { if (Solution.GetEntryTime(arc.Head) < Solution.GetEntryTime(arc.Tail) + arc.Length) { CostLayer.SetEntryTime(arc.Head, Solution.GetEntryTime(arc.Tail) + arc.Length); _necessaryFixes.Add(new TimeAtVertex(arc.Head, Solution.GetEntryTime(arc.Tail) + arc.Length)); } else if (Solution.GetEntryTime(arc.Head) > Solution.GetEntryTime(arc.Tail) + arc.Length) { TimeSpan oldTime = Solution.GetEntryTime(arc.Head); TimeSpan newTime = IncomingArcs(arc.Head) .Select(a => Solution.GetEntryTime(a.Tail) + a.Length) .Append(Solution.GetOperation(arc.Head).EarliestEarliestEntry) .Max(); if (oldTime != newTime) { CostLayer.SetEntryTime(arc.Head, newTime); _necessaryFixes.Add(new TimeAtVertex(arc.Head, newTime)); } } } UpdateTimesLoopInvariant(); } ClassInvariant(); TimesGraphIntegrity.DoCheck(this); }
public IEnumerable <Arc> GetCriticalArcs(IEnumerable <int> backtrackFrom, bool onlyDisjunctive = true) { if (!TimesAreUpToDate()) { throw new Exception(); } TimesGraphIntegrity.DoCheck(this); ClassInvariant(); // used iff obj == max weighted tardiness HashSet <int> alreadyReturned = new HashSet <int>(); var indicesOfCosts = backtrackFrom; foreach (int vertex in indicesOfCosts) { int current = vertex; while (true) { if (alreadyReturned.Contains(current)) { break; } alreadyReturned.Add(current); if (!_graph.IncomingArcs(current).Any()) { break; } Arc arc = _graph.IncomingArcs(current) .FirstOrDefault(a => Solution.GetEntryTime(a.Head) == Solution.GetEntryTime(a.Tail) + a.Length); if (arc.Equals(default))
private static IJobShopLayer Step( int iteration, IJobShopLayer origin, double bestCost, ITabooList tabooList, Random random, double moveImmediatelyImprovementRate = 0.00001, // improvement >= 0.001% -> move to the next solution immediately int minArcsToCheckCount = 1, bool verbose = true) { TimesGraphIntegrity.DoCheck(origin.RoutingLayer.ClosureLayer.SequencingLayer.GraphLayer); var moves = GetMoves(origin, tabooList, random); if (moves.Length == 0) { throw new NoMoves(); } if (verbose) { Console.WriteLine($"Inspecting {moves.Length} moves."); } //TabooType[] tabooTypes = new TabooType[moves.Length]; // init all to 'unknown' if (tabooList.Any()) { for (int i = 0; i < moves.Length; i++) { if (tabooList.IsAprioriTaboo(moves[i].ActualMove)) { moves[i].TabooType = TabooType.AprioriTaboo; } } } double originCost = origin.GetTotalCost(); //double[] resultCosts = Enumerable.Repeat(double.MaxValue, moves.Length).ToArray(); // Try the moves. for (int i = 0; i < moves.Length; i++) { if (moves[i].TabooType == TabooType.AprioriTaboo) { if (verbose) { Console.Write(ShortToString(moves[i].TabooType) + " "); } continue; } // Clone & execute. var clone = origin.Clone(); clone.ExecuteMove(moves[i].ActualMove); moves[i].Cost = clone.GetTotalCost(); // Never trust yourself Assert(SingleThreadSearchChecks, clone.GetHashCode() != origin.GetHashCode() || !clone.Equals(origin)); // decide if the move is taboo if (!tabooList.Any()) { moves[i].TabooType = TabooType.NotTaboo; } else if (moves[i].Cost < 0.9999 * bestCost) { moves[i].TabooType = TabooType.Ascension; } else if (tabooList.IsAposterioriTaboo(clone)) { moves[i].TabooType = TabooType.AposterioriTaboo; } else { moves[i].TabooType = TabooType.NotTaboo; } if (verbose) { Console.Write( ShortToString(moves[i].TabooType) + (moves[i].Cost < 0.9999 * originCost? "^" : "") + " "); } // break, if the improvement is large enough (&& not taboo). double improvementRate = (bestCost - moves[i].Cost) / bestCost; if (i > minArcsToCheckCount && improvementRate > moveImmediatelyImprovementRate && (moves[i].TabooType == TabooType.Ascension || moves[i].TabooType == TabooType.NotTaboo)) { break; } } if ((iteration % 10) == 0) { //Console.WriteLine("hello..."); } // Find the move to return. int candidateIndex = -1; Move candidate = null; for (int i = 0; i < moves.Length; i++) { var move = moves[i]; var taboo = moves[i].TabooType; if ((candidateIndex == -1 || moves[i].Cost < moves[candidateIndex].Cost) && taboo != TabooType.AposterioriTaboo && taboo != TabooType.AprioriTaboo) { candidateIndex = i; candidate = move.ActualMove; } } Assert(SingleThreadSearchChecks, candidate != null); if (candidate == null) { Console.WriteLine("all moves taboo!"); double minCost = moves.Select(m => m.Cost).Min(); candidateIndex = Enumerable.Range(0, moves.Length).First(i => (moves[i].Cost == minCost)); candidate = moves[candidateIndex].ActualMove; } if (moves[candidateIndex].Cost > 0.9999 * bestCost) { tabooList.ProhibitUndoOfMove(origin, candidate); Assert(SingleThreadSearchChecks, tabooList.IsAprioriTaboo(candidate) || tabooList.IsAposterioriTaboo(origin), "When adding elements to the taboo-list, the original solution (before executing the move) must be taboo."); if (SingleThreadSearchChecks.On && (candidate.Type == MoveType.RemoveCriticalArcLeftClosure || candidate.Type == MoveType.RemoveCriticalArcRightClosure)) { Assert(SingleThreadSearchChecks, origin.TransitiveArcExist(candidate.CriticalArc)); var target = origin.Clone(); target.ExecuteMove(candidate); Assert(SingleThreadSearchChecks, !target.TransitiveArcExist(candidate.CriticalArc)); } } // Execute this move & return. origin.ExecuteMove(candidate); return(origin); }