public void ProhibitUndoOfMove(IJobShopLayer solution, Move move) { if (ArcTabooLength > 0 && (move.Type == MoveType.RemoveCriticalArcLeftClosure || move.Type == MoveType.RemoveCriticalArcRightClosure)) { Assert(Checks, !_prohibitedArcs.Contains(move.CriticalArc)); _prohibitedArcs.Add(move.CriticalArc); while (_prohibitedArcs.Count > ArcTabooLength) { _prohibitedArcs.RemoveAt(0); } } if (RouteTabooLength > 0 && move.Type == MoveType.ChangeRouting) { if (_prohibitedRoutes.TryGetValue(move.JobToRouteSwap, out var set)) { set.Add(move.RouteToRemove); } else { _prohibitedRoutes.Add(move.JobToRouteSwap, new HashSet <Route> { move.RouteToRemove }); } } _prohibitedSolutions.Add(solution.Clone()); }
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); }