static void VNS(Instance instance, Process process, Random rnd, Stopwatch clock, string choice) { int typeSol = 0; List <int>[] listArray = Utility.BuildSLComplete(instance); PathStandard incumbentSol; PathStandard solHeuristic = Utility.NearestNeightbor(instance, rnd, listArray); incumbentSol = (PathStandard)solHeuristic.Clone(); Utility.PrintHeuristicSolution(instance, process, incumbentSol, incumbentSol.cost, typeSol); do { TwoOpt(instance, solHeuristic); if (incumbentSol.cost > solHeuristic.cost) { incumbentSol = (PathStandard)solHeuristic.Clone(); Utility.PrintHeuristicSolution(instance, process, incumbentSol, incumbentSol.cost, typeSol); Console.WriteLine("Incumbed changed"); } else { Console.WriteLine("Incumbed not changed"); } VNS(instance, solHeuristic, rnd); } while (clock.ElapsedMilliseconds / 1000.0 < instance.TimeLimit); Console.WriteLine("Best distance found within the timelit is: " + incumbentSol.cost); }
public static void SwapRoute(int c, int b, PathStandard pathG) { int from = b; int to = pathG.path[from]; do { int tmpTo = pathG.path[to]; pathG.path[to] = from; from = to; to = tmpTo; } while (from != c); }
public static void TwoOpt(Instance instance, PathStandard pathG) { int indexStart = 0; int cnt = 0; bool found = false; do { found = false; int a = indexStart; int b = pathG.path[a]; int c = pathG.path[b]; int d = pathG.path[c]; for (int i = 0; i < instance.NNodes - 3; i++) { double distAC = Point.Distance(instance.Coord[a], instance.Coord[c], instance.EdgeType); double distBD = Point.Distance(instance.Coord[b], instance.Coord[d], instance.EdgeType); double distAD = Point.Distance(instance.Coord[a], instance.Coord[d], instance.EdgeType); double distBC = Point.Distance(instance.Coord[b], instance.Coord[c], instance.EdgeType); double distTotABCD = Point.Distance(instance.Coord[a], instance.Coord[b], instance.EdgeType) + Point.Distance(instance.Coord[c], instance.Coord[d], instance.EdgeType); if (distAC + distBD < distTotABCD) { Utility.SwapRoute(c, b, pathG); pathG.path[a] = c; pathG.path[b] = d; pathG.cost = pathG.cost - distTotABCD + distAC + distBD; indexStart = 0; cnt = 0; found = true; break; } c = d; d = pathG.path[c]; } if (!found) { indexStart = b; cnt++; } } while (cnt < instance.NNodes); }
static void TabuSearch(Instance instance, Process process, Random rnd, Stopwatch clock, string choice) { int typeSol = 0; List <int>[] listArray = Utility.BuildSLComplete(instance); PathStandard incumbentSol; PathStandard solHeuristic = Utility.NearestNeightbor(instance, rnd, listArray); incumbentSol = (PathStandard)solHeuristic.Clone(); Utility.PrintHeuristicSolution(instance, process, incumbentSol, incumbentSol.cost, typeSol); Tabu tabu = new Tabu("A", instance, 100); TabuSearch(instance, process, tabu, solHeuristic, incumbentSol, clock); solHeuristic = (PathStandard)incumbentSol.Clone(); TwoOpt(instance, solHeuristic); Utility.PrintHeuristicSolution(instance, process, solHeuristic, incumbentSol.cost, typeSol); Console.WriteLine("Best distance found within the timelit is: " + incumbentSol.cost); }
public static void PrintHeuristicSolution(Instance instance, Process process, PathStandard pathG, double incumbentCost, int typeSol) { //Init the StreamWriter for the current solution StreamWriter file = new StreamWriter(instance.InputFile + ".dat", false); //Printing the optimal solution and the GNUPlot input file for (int i = 0; i < instance.NNodes; i++) { /* * Current GNUPlot format is: *-- previus link -- *<Blank line> * Xi Yi <index(i)> * Xj Yj <index(i)> *<Blank line> *-- next link -- */ file.WriteLine(instance.Coord[i].X + " " + instance.Coord[i].Y + " " + (i + 1)); file.WriteLine(instance.Coord[pathG.path[i]].X + " " + instance.Coord[pathG.path[i]].Y + " " + (pathG.path[i] + 1) + "\nEdges"); } //GNUPlot input file needs to be closed file.Close(); //Accessing GNUPlot to read the file if (Program.VERBOSE >= -1) { if (pathG.cost != incumbentCost) { PrintGNUPlot(process, instance.InputFile, typeSol, pathG.cost, incumbentCost); } else { PrintGNUPlot(process, instance.InputFile, typeSol, pathG.cost, -1); } } }
static void LocalBranching(Cplex cplex, Instance instance, Process process, Random rnd, Stopwatch clock) { //Define the possible value that the radius can be assume int[] possibleRadius = { 3, 5, 7, 10 }; //We start whit a radius of 3 int currentRange = 0; //Don't want print every candidate incumbent solution inside the lazy constraint callback bool BlockPrint = false; //Define the vector where is coded the incumbent solution double[] incumbentSol = new double[(instance.NNodes - 1) * instance.NNodes / 2]; //Variable where is store the cost of the incumbent solution double incumbentCost = double.MaxValue; //Create the vector conten that it will contain the last best solution find befor time limit or when it can't be improved instance.BestSol = new double[(instance.NNodes - 1) * instance.NNodes / 2]; //Build the model INumVar[] x = Utility.BuildModel(cplex, instance, -1); //List use in NearestNeightbor method List <int>[] listArray = Utility.BuildSLComplete(instance); //Create a heuristic solution PathStandard heuristicSol = Utility.NearestNeightbor(instance, rnd, listArray); //Apply 2-opt algotithm in order to improve the cost to the heuristicSol TwoOpt(instance, heuristicSol); //The heuristic solution is the incumbent, translate the encode in the format used by Cplex for (int i = 0; i < instance.NNodes; i++) { int position = Utility.xPos(i, heuristicSol.path[i], instance.NNodes); //Set to one only the edge that belong to euristic solution incumbentSol[position] = 1; } //Installation of the Lazy Constraint Callback cplex.Use(new TSPLazyConsCallback(cplex, x, instance, process, BlockPrint)); //Set the number of thread equal to the number of logical core present in the processor cplex.SetParam(Cplex.Param.Threads, cplex.GetNumCores()); //Provide to Cplex a warm start cplex.AddMIPStart(x, incumbentSol); //Create a empty expression ILinearNumExpr expr = cplex.LinearNumExpr(); //Create the firts member of the local branch constraint for (int i = 0; i < instance.NNodes; i++) { expr.AddTerm(x[Utility.xPos(i, heuristicSol.path[i], instance.NNodes)], 1); } //Create a new local branch constraint IAddable localBranchConstraint = cplex.Ge(expr, instance.NNodes - possibleRadius[currentRange]); //Add the constraint cplex.Add(localBranchConstraint); do { //Solve the model cplex.Solve(); if (incumbentCost > cplex.GetObjValue()) { incumbentCost = cplex.ObjValue; incumbentSol = cplex.GetValues(x); //Eliminate the previous local branch constraint cplex.Remove(localBranchConstraint); //Create an empty expression expr = cplex.LinearNumExpr(); StreamWriter file = new StreamWriter(instance.InputFile + ".dat", false); //Print the new incombent solution for (int i = 0; i < instance.NNodes; i++) { for (int j = i + 1; j < instance.NNodes; j++) { int position = Utility.xPos(i, j, instance.NNodes); if (incumbentSol[position] >= 0.5) { file.WriteLine(instance.Coord[i].X + " " + instance.Coord[i].Y + " " + (i + 1)); file.WriteLine(instance.Coord[j].X + " " + instance.Coord[j].Y + " " + (j + 1) + "\n"); //Create the firts member of the local branch constraint expr.AddTerm(x[position], 1); } } } Utility.PrintGNUPlot(process, instance.InputFile, 1, incumbentCost, -1); file.Close(); //Create a local branch constraint localBranchConstraint = cplex.Ge(expr, instance.NNodes - possibleRadius[currentRange]); //Add the local branch constraint cplex.Add(localBranchConstraint); } else { if (possibleRadius[currentRange] != 10) { //Increase the radius currentRange++; //Remove the previous local branch constraint cplex.Remove(localBranchConstraint); //Create the new local branch constraint localBranchConstraint = cplex.Ge(expr, instance.NNodes - possibleRadius[currentRange]); //Add the local branch constraint to the model cplex.Add(localBranchConstraint); } else { break; } } } while (clock.ElapsedMilliseconds / 1000.0 < instance.TimeLimit); //Store in the appropriate fields inside instance the last incumbent solution find and the relative cost instance.BestSol = incumbentSol; instance.BestLb = incumbentCost; }
static void HardFixing(Cplex cplex, Instance instance, Process process, Random rnd, Stopwatch clock) { StreamWriter file; //Vector used to encode the path that rappresent the best integer solution note double[] currentIncumbentSol = new double[(instance.NNodes - 1) * instance.NNodes / 2]; //Cost of the best integer solution note double currentIncumbentCost = Double.MaxValue; List <int>[] listArray = Utility.BuildSLComplete(instance); //Serve per differenziarsi rispetto alla lazy "normale" in cui stampo ogni soluzione intera(anche che non è un subtour) bool BlockPrint = false; const int VALUECONSITENOTIMPROV = 3; //Defined the max number of consecutive run of cplex whithout finds a improvement of the incumbent int consecutiveiterationNotImprov = VALUECONSITENOTIMPROV; //Defined the percentage of edge in the current solution that fixed double percentageFixing = 0.8; instance.BestSol = new double[(instance.NNodes - 1) * instance.NNodes / 2]; //Create the model INumVar[] x = Utility.BuildModel(cplex, instance, -1); //Create a heuristic solution PathStandard heuristicSol = Utility.NearestNeightbor(instance, rnd, listArray); //Apply 2-opt algorithm in order to improve the costo o the heiristicSol TwoOpt(instance, heuristicSol); //The heuristic solution is the Incumbent, translate the encode in the format used by Cplex for (int i = 0; i < instance.NNodes; i++) { int position = Utility.xPos(i, heuristicSol.path[i], instance.NNodes); //Set to one only the edge that belong to heuristic solution currentIncumbentSol[position] = 1; } currentIncumbentCost = heuristicSol.cost; //Installation of the Lazy Constraint CallBack TSPLazyConsCallback tspLazy = new TSPLazyConsCallback(cplex, x, instance, process, BlockPrint); cplex.Use(tspLazy); //Provide to Cplex a warm start cplex.AddMIPStart(x, currentIncumbentSol); //Set the number of thread equal to the number of logical core present in the processor cplex.SetParam(Cplex.Param.Threads, cplex.GetNumCores()); cplex.SetParam(Cplex.LongParam.IntSolLim, 2); do { //Modify the Model according to the current Incumbent solution Utility.ModifyModel(instance, x, rnd, percentageFixing, currentIncumbentSol); //Solve the model cplex.Solve(); if (currentIncumbentCost > cplex.GetObjValue(Cplex.IncumbentId)) { file = new StreamWriter(instance.InputFile + ".dat", false); currentIncumbentCost = cplex.GetObjValue(Cplex.IncumbentId); currentIncumbentSol = cplex.GetValues(x, Cplex.IncumbentId); //Print solution for (int i = 0; i < instance.NNodes; i++) { for (int j = i + 1; j < instance.NNodes; j++) { int position = Utility.xPos(i, j, instance.NNodes); if (currentIncumbentSol[position] >= 0.5) { file.WriteLine(instance.Coord[i].X + " " + instance.Coord[i].Y + " " + (i + 1)); file.WriteLine(instance.Coord[j].X + " " + instance.Coord[j].Y + " " + (j + 1) + "\n"); } } } file.Close(); Utility.PrintGNUPlot(process, instance.InputFile, 1, currentIncumbentCost, -1); //Restorarion the variable consecutiveIterationNotImprov to the value VALUECONSITENOTIMPROV consecutiveiterationNotImprov = VALUECONSITENOTIMPROV; } else { //If don't have improvement decrease variable consecutiveIterationNotImprov consecutiveiterationNotImprov--; } if (consecutiveiterationNotImprov == 0) { if (percentageFixing > 0.2) { percentageFixing -= 0.1; consecutiveiterationNotImprov = VALUECONSITENOTIMPROV; } else { consecutiveiterationNotImprov = VALUECONSITENOTIMPROV; } } //Restoration the lower and upper bound of all variable. for (int i = 0; i < x.Length; i++) { x[i].LB = 0; x[i].UB = 1; } } while (clock.ElapsedMilliseconds / 1000.0 < instance.TimeLimit); instance.XBest = currentIncumbentCost; instance.BestSol = currentIncumbentSol; //Empty line cplex.Output().WriteLine(); cplex.Output().WriteLine("x = " + instance.XBest + "\n"); if (Program.VERBOSE >= -1) { cplex.ExportModel(instance.InputFile + ".lp"); } }
static void VNS(Instance instance, PathStandard currentSol, Random rnd) { int a, b, c, d, e, f; a = rnd.Next(currentSol.path.Length); b = currentSol.path[a]; do { c = rnd.Next(currentSol.path.Length); d = currentSol.path[c]; } while ((a == c && b == d) || a == d || b == c); do { e = rnd.Next(currentSol.path.Length); f = currentSol.path[e]; } while ((e == a && f == b) || e == b || f == a || (e == c && f == d) || e == d || f == c); List <int> order = new List <int>(); for (int i = 0, index = 0; i < currentSol.path.Length && order.Count != 4; i++, index = currentSol.path[index]) { if (a == index) { order.Add(a); order.Add(b); i++; index = currentSol.path[index]; } else if (c == index) { order.Add(c); order.Add(d); i++; index = currentSol.path[index]; } else if (e == index) { order.Add(e); order.Add(f); i++; index = currentSol.path[index]; } } if (order[0] != a && order[2] != a) { order.Add(a); order.Add(b); } else if (order[0] != c && order[2] != c) { order.Add(c); order.Add(d); } else { order.Add(e); order.Add(f); } Utility.SwapRoute(order[2], order[1], currentSol); currentSol.path[order[0]] = order[2]; Utility.SwapRoute(order[4], order[3], currentSol); currentSol.path[order[1]] = order[4]; currentSol.path[order[3]] = order[5]; currentSol.cost += Point.Distance(instance.Coord[order[0]], instance.Coord[order[2]], instance.EdgeType) + Point.Distance(instance.Coord[order[1]], instance.Coord[order[4]], instance.EdgeType) + Point.Distance(instance.Coord[order[3]], instance.Coord[order[5]], instance.EdgeType) - Point.Distance(instance.Coord[a], instance.Coord[b], instance.EdgeType) - Point.Distance(instance.Coord[c], instance.Coord[d], instance.EdgeType) - Point.Distance(instance.Coord[e], instance.Coord[f], instance.EdgeType); }
static void TabuSearch(Instance instance, Process process, Tabu tabu, PathStandard currentSol, PathStandard incumbentPath, Stopwatch clock) { int typeSol; int indexStart = 0; string nextBestMove = ""; string nextWorstMove = ""; double bestGain = double.MaxValue; double worstGain = double.MinValue; int a, b, c, d; double distAC, distBD, distTotABCD; do { for (int j = 0; j < instance.NNodes; j++, indexStart = b) { a = indexStart; b = currentSol.path[a]; c = currentSol.path[b]; d = currentSol.path[c]; for (int i = 0; i < instance.NNodes - 3; i++, c = d, d = currentSol.path[c]) { if (!tabu.IsTabu(a, c) && !tabu.IsTabu(b, d)) { distAC = Point.Distance(instance.Coord[a], instance.Coord[c], instance.EdgeType); distBD = Point.Distance(instance.Coord[b], instance.Coord[d], instance.EdgeType); distTotABCD = Point.Distance(instance.Coord[a], instance.Coord[b], instance.EdgeType) + Point.Distance(instance.Coord[c], instance.Coord[d], instance.EdgeType); if ((distAC + distBD) - distTotABCD < bestGain && (distAC + distBD) != distTotABCD) { nextBestMove = a + ";" + b + ";" + c + ";" + d; bestGain = (distAC + distBD) - distTotABCD; } if ((distAC + distBD) - distTotABCD > worstGain && (distAC + distBD) != distTotABCD) { nextWorstMove = a + ";" + b + ";" + c + ";" + d; worstGain = (distAC + distBD) - distTotABCD; } } } } string[] currentElements = nextBestMove.Split(';'); a = int.Parse(currentElements[0]); b = int.Parse(currentElements[1]); c = int.Parse(currentElements[2]); d = int.Parse(currentElements[3]); Utility.SwapRoute(c, b, currentSol); currentSol.path[a] = c; currentSol.path[b] = d; currentSol.cost += bestGain; if (incumbentPath.cost > currentSol.cost) { incumbentPath = (PathGenetic)currentSol.Clone(); } if (bestGain < 0) { typeSol = 0; } else { tabu.AddTabu(a, b, c, d); typeSol = 1; } Utility.PrintHeuristicSolution(instance, process, currentSol, incumbentPath.cost, typeSol); bestGain = double.MaxValue; worstGain = double.MinValue; } while (clock.ElapsedMilliseconds / 1000.0 < instance.TimeLimit); }