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"); } }