private static SearchMove[] GetMoves(IJobShopLayer origin, ITabooList tabooList, Random random) { if (origin.GetConnectionsCost() > .5 * origin.GetTotalCost()) { return(origin.GetMoves( connectionFix: true, connectionImprovement: true, criticalArcsBased: tabooList.Any(), routeSwapBased: false, routeSwapWithHeuristicInsertion: false, //true, //!tabooList.Any(), jobReinsertion: false, routePenaltyImprovement: false) .Shuffle(random) .Select(m => new SearchMove(m)) .ToArray()); } if (origin.GetDelayCost() > origin.GetRoutingCost()) { bool changeRoute = !tabooList.Any() || random.NextDouble() < .3; return(origin .GetMoves( connectionFix: true, connectionImprovement: true, criticalArcsBased: true, routeSwapBased: changeRoute, routeSwapWithHeuristicInsertion: changeRoute, //true, //!tabooList.Any(), jobReinsertion: changeRoute, routePenaltyImprovement: false) .Shuffle(random) .Select(m => new SearchMove(m)) .ToArray()); } else { return(origin .GetMoves(false, false, false, false, false, false, routePenaltyImprovement: true) .Shuffle(random).Select(m => new SearchMove(m)).ToArray()); } }
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); }