static bool HasTourElimination(Cplex cplex, Data data, IIntVar[][] x) { double[][] sol_x = new double[data.n][]; for (int i = 0; i < data.n; i++) { sol_x[i] = cplex.GetValues(x[i]); } //int shortestLenght = ShortestCicleInSelectedPaths(sol_x); int[] tour = FindSubTour(sol_x); if (tour.Length < data.n) { ILinearNumExpr sumx = cplex.LinearNumExpr(); for (int i = 0; i < tour.Length; i++) { for (int j = i + 1; j < tour.Length; j++) { sumx.AddTerm(1, x[tour[i]][tour[j]]); } } cplex.AddLazyConstraint(cplex.AddLe(cplex.Diff(sumx, (tour.Length + 1)), 0)); return(true); } else { return(false); } }
public void AddBalanceConstraint() { lCap = theModel.LinearNumExpr(); foreach (var hub in HubList) { foreach (var lane in theData.ModelData) { if (hub.Value == lane.Value.OHUB) { lCap.AddTerm(1, lane.Value.LoadedMoves); lCap.AddTerm(1, lane.Value.EmptyMoves); } if (hub.Value == lane.Value.DHUB) { lCap.AddTerm(-1, lane.Value.LoadedMoves); lCap.AddTerm(-1, lane.Value.EmptyMoves); } } theModel.AddEq(lCap, 0, hub.Value); lCap.Clear(); } }
/// <summary> /// Create objective function for the optimization model /// </summary> private void CreateObjective() { _objective = _solver.LinearNumExpr(); for (int i = 0; i < N; i++) { var cargo = _cargoList[i]; var regularCost = cargo.GetRegularCost(); var excessCost = cargo.GetExcessCost(); var demurrageCost = cargo.GetDemurrageCost(); _objective.AddTerm(yR[i], regularCost); _objective.AddTerm(yE[i], excessCost); _objective.AddTerm(m[i], demurrageCost); } for (int j = 0; j < M; j++) { _objective.AddTerm(u[j], _costOfUnsatisfied); } _solver.AddMinimize(_objective); }
//Updating the related components public static void UpdateCC(Cplex cplex, INumVar[] x, List <ILinearNumExpr> rcExpr, List <int> bufferCoeffRC, int[] relatedComponents, int i, int j) { if (relatedComponents[i] != relatedComponents[j])//Same related component, the latter is not closed yet { for (int k = 0; k < relatedComponents.Length; k++) { if ((k != j) && (relatedComponents[k] == relatedComponents[j])) { //Same as Kruskal relatedComponents[k] = relatedComponents[i]; } } //Finally also the vallue relative to the node i are updated relatedComponents[j] = relatedComponents[i]; } else//Here the current releted component is complete and the relative subtout elimination constraint can be added to the model { ILinearNumExpr expr = cplex.LinearNumExpr(); //cnt stores the # of nodes of the current related components int cnt = 0; for (int h = 0; h < relatedComponents.Length; h++) { //Only nodes of the current related components are considered if (relatedComponents[h] == relatedComponents[i]) { //Each link involving the node with index h is analized for (int k = h + 1; k < relatedComponents.Length; k++) { //Testing if the link is valid if (relatedComponents[k] == relatedComponents[i]) { //Adding the link to the expression with coefficient 1 expr.AddTerm(x[xPos(h, k, relatedComponents.Length)], 1); } } cnt++; } } //Adding the objects to the buffers rcExpr.Add(expr); bufferCoeffRC.Add(cnt); } }
public static void Main(string[] args) { if (args.Length < 1) { System.Console.WriteLine("Usage: Transport <type>"); System.Console.WriteLine(" type = 0 -> convex piecewise linear model"); System.Console.WriteLine(" type = 1 -> concave piecewise linear model"); return; } try { Cplex cplex = new Cplex(); int nbDemand = 4; int nbSupply = 3; double[] supply = { 1000.0, 850.0, 1250.0 }; double[] demand = { 900.0, 1200.0, 600.0, 400.0 }; INumVar[][] x = new INumVar[nbSupply][]; INumVar[][] y = new INumVar[nbSupply][]; for (int i = 0; i < nbSupply; i++) { x[i] = cplex.NumVarArray(nbDemand, 0.0, System.Double.MaxValue); y[i] = cplex.NumVarArray(nbDemand, 0.0, System.Double.MaxValue); } for (int i = 0; i < nbSupply; i++) // supply must meet demand { cplex.AddEq(cplex.Sum(x[i]), supply[i]); } for (int j = 0; j < nbDemand; j++) // demand must meet supply { ILinearNumExpr v = cplex.LinearNumExpr(); for (int i = 0; i < nbSupply; i++) { v.AddTerm(1.0, x[i][j]); } cplex.AddEq(v, demand[j]); } double[] points; double[] slopes; if (args[0].ToCharArray()[0] == '0') // convex case { points = new double[] { 200.0, 400.0 }; slopes = new double[] { 30.0, 80.0, 130.0 }; } else // concave case { points = new double[] { 200.0, 400.0 }; slopes = new double[] { 120.0, 80.0, 50.0 }; } for (int i = 0; i < nbSupply; ++i) { for (int j = 0; j < nbDemand; ++j) { cplex.AddEq(y[i][j], cplex.PiecewiseLinear(x[i][j], points, slopes, 0.0, 0.0)); } } ILinearNumExpr expr = cplex.LinearNumExpr(); for (int i = 0; i < nbSupply; ++i) { for (int j = 0; j < nbDemand; ++j) { expr.AddTerm(y[i][j], 1.0); } } cplex.AddMinimize(expr); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" - Solution: "); for (int i = 0; i < nbSupply; ++i) { System.Console.Write(" " + i + ": "); for (int j = 0; j < nbDemand; ++j) { System.Console.Write("" + cplex.GetValue(x[i][j]) + "\t"); } System.Console.WriteLine(); } System.Console.WriteLine(" Cost = " + cplex.ObjValue); } cplex.End(); } catch (ILOG.Concert.Exception exc) { System.Console.WriteLine(exc); } }
public static void Main(string[] args) { try { string filename = "../../../../examples/data/facility.dat"; if (args.Length > 0) { filename = args[0]; } ReadData(filename); Cplex cplex = new Cplex(); INumVar[] open = cplex.BoolVarArray(_nbLocations); INumVar[][] supply = new INumVar[_nbClients][]; for (int i = 0; i < _nbClients; i++) { supply[i] = cplex.BoolVarArray(_nbLocations); } for (int i = 0; i < _nbClients; i++) { cplex.AddEq(cplex.Sum(supply[i]), 1); } for (int j = 0; j < _nbLocations; j++) { ILinearNumExpr v = cplex.LinearNumExpr(); for (int i = 0; i < _nbClients; i++) { v.AddTerm(1.0, supply[i][j]); } cplex.AddLe(v, cplex.Prod(_capacity[j], open[j])); } ILinearNumExpr obj = cplex.ScalProd(_fixedCost, open); for (int i = 0; i < _nbClients; i++) { obj.Add(cplex.ScalProd(_cost[i], supply[i])); } cplex.AddMinimize(obj); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); double tolerance = cplex.GetParam(Cplex.Param.MIP.Tolerances.Integrality); System.Console.WriteLine("Optimal value: " + cplex.ObjValue); for (int j = 0; j < _nbLocations; j++) { if (cplex.GetValue(open[j]) >= 1 - tolerance) { System.Console.Write("Facility " + j + " is open, it serves clients "); for (int i = 0; i < _nbClients; i++) { if (cplex.GetValue(supply[i][j]) >= 1 - tolerance) { System.Console.Write(" " + i); } } System.Console.WriteLine(); } } } cplex.End(); } catch (ILOG.Concert.Exception exc) { System.Console.WriteLine("Concert exception '" + exc + "' caught"); } catch (System.IO.IOException exc) { System.Console.WriteLine("Error reading file " + args[0] + ": " + exc); } catch (InputDataReader.InputDataReaderException exc) { System.Console.WriteLine(exc); } }
public static void Main(string[] args) { try { string filename = "../../../../examples/data/steel.dat"; if (args.Length > 0) { filename = args[0]; } ReadData(filename); Cplex cplex = new Cplex(); // VARIABLES INumVar[][] Make = new INumVar[_nProd][]; for (int p = 0; p < _nProd; p++) { Make[p] = cplex.NumVarArray(_nTime, 0.0, System.Double.MaxValue); } INumVar[][] Inv = new INumVar[_nProd][]; for (int p = 0; p < _nProd; p++) { Inv[p] = cplex.NumVarArray(_nTime, 0.0, System.Double.MaxValue); } INumVar[][] Sell = new INumVar[_nProd][]; for (int p = 0; p < _nProd; p++) { Sell[p] = new INumVar[_nTime]; for (int t = 0; t < _nTime; t++) { Sell[p][t] = cplex.NumVar(0.0, _market[p][t]); } } // OBJECTIVE ILinearNumExpr TotalRevenue = cplex.LinearNumExpr(); ILinearNumExpr TotalProdCost = cplex.LinearNumExpr(); ILinearNumExpr TotalInvCost = cplex.LinearNumExpr(); for (int p = 0; p < _nProd; p++) { for (int t = 1; t < _nTime; t++) { TotalRevenue.AddTerm(_revenue[p][t], Sell[p][t]); TotalProdCost.AddTerm(_prodCost[p], Make[p][t]); TotalInvCost.AddTerm(_invCost[p], Inv[p][t]); } } cplex.AddMaximize(cplex.Diff(TotalRevenue, cplex.Sum(TotalProdCost, TotalInvCost))); // TIME AVAILABILITY CONSTRAINTS for (int t = 0; t < _nTime; t++) { ILinearNumExpr availExpr = cplex.LinearNumExpr(); for (int p = 0; p < _nProd; p++) { availExpr.AddTerm(1.0 / _rate[p], Make[p][t]); } cplex.AddLe(availExpr, _avail[t]); } // MATERIAL BALANCE CONSTRAINTS for (int p = 0; p < _nProd; p++) { cplex.AddEq(cplex.Sum(Make[p][0], _inv0[p]), cplex.Sum(Sell[p][0], Inv[p][0])); for (int t = 1; t < _nTime; t++) { cplex.AddEq(cplex.Sum(Make[p][t], Inv[p][t - 1]), cplex.Sum(Sell[p][t], Inv[p][t])); } } cplex.ExportModel("steel.lp"); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(); System.Console.WriteLine("Total Profit = " + cplex.ObjValue); System.Console.WriteLine(); System.Console.WriteLine("\tp\tt\tMake\tInv\tSell"); for (int p = 0; p < _nProd; p++) { for (int t = 0; t < _nTime; t++) { System.Console.WriteLine("\t" + p + "\t" + t + "\t" + cplex.GetValue(Make[p][t]) + "\t" + cplex.GetValue(Inv[p][t]) + "\t" + cplex.GetValue(Sell[p][t])); } } } cplex.End(); } catch (ILOG.Concert.Exception exc) { System.Console.WriteLine("Concert exception '" + exc + "' caught"); } catch (System.IO.IOException exc) { System.Console.WriteLine("Error reading file " + args[0] + ": " + exc); } catch (InputDataReader.InputDataReaderException exc) { System.Console.WriteLine(exc); } }
static void Main() { try { string resultFilename = "./ResultFiles/MTSP_MTZ.csv"; string filename = "./DataFiles/Data.dat"; Data data = new Data(filename); double timeFactor = 0; double distanceFactor = 1; double step = 0.1; int routeCounter = 0; File.WriteAllText(resultFilename, ""); do { using (Cplex cplex = new Cplex()) { #region [Decision Variables] IIntVar[][] x = new IIntVar[data.n][]; IIntVar Q = cplex.IntVar(1, 250, "Q"); for (int i = 0; i < data.n; i++) { x[i] = cplex.BoolVarArray(data.n); cplex.Add(x[i]); } #endregion #region [Objective Function] INumExpr obj = cplex.NumExpr(); for (int i = 0; i < data.n; i++) { for (int j = 0; j < data.n; j++) { if (i != j) { obj = cplex.Sum(obj, cplex.Prod( ( (timeFactor * data.timeNormalized[i][j]) + (distanceFactor * data.distanceNormalized[i][j]) ), x[i][j])); } } } cplex.AddMinimize(obj); #endregion #region [Restrictions] for (int j = 0; j < data.n; j++) { ILinearNumExpr sumj = cplex.LinearNumExpr(); for (int i = 0; i < data.n; i++) { if (i != j) { sumj.AddTerm(1, x[i][j]); } } cplex.AddEq(sumj, 1); } for (int i = 0; i < data.n; i++) { ILinearNumExpr sumi = cplex.LinearNumExpr(); for (int j = 0; j < data.n; j++) { if (i != j) { sumi.AddTerm(1, x[i][j]); } } cplex.AddEq(sumi, 1); } #endregion cplex.SetParam(Cplex.DoubleParam.WorkMem, 4000.0); cplex.SetParam(Cplex.Param.MIP.Strategy.File, 2); cplex.SetParam(Cplex.DoubleParam.EpGap, 0.1); cplex.SetParam(Cplex.BooleanParam.MemoryEmphasis, true); cplex.SetParam(Cplex.IntParam.VarSel, 4); SOLVE: Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); if (cplex.Solve()) { stopWatch.Stop(); double[][] sol_x = new double[data.n][]; for (int i = 0; i < data.n; i++) { sol_x[i] = cplex.GetValues(x[i]); } int[] tour = FindSubTour(sol_x); if (tour.Length < data.n) { ILinearNumExpr sumx = cplex.LinearNumExpr(); for (int i = 0; i < tour.Length; i++) { for (int j = 0; j < tour.Length; j++) { sumx.AddTerm(1, x[tour[i]][tour[j]]); } } cplex.AddLazyConstraint(cplex.AddLe(cplex.Diff(sumx, tour.Length), -1)); goto SOLVE; } double timeTotal = 0; double distanceTotal = 0; for (int i = 0; i < data.n; i++) { for (int j = 0; j < data.n; j++) { timeTotal += data.time[i][j] * sol_x[i][j]; distanceTotal += data.distance[i][j] * sol_x[i][j]; } } StreamWriter file = new StreamWriter(resultFilename, true); file.WriteLine($"{timeFactor},{distanceFactor},{stopWatch.Elapsed.TotalSeconds},{cplex.ObjValue},{timeTotal},{distanceTotal}"); file.Close(); StreamWriter fileRouteResult = new StreamWriter($"./ResultFiles/Route-{routeCounter}.txt"); for (int i = 0; i < data.n; i++) { for (int j = 0; j < data.n; j++) { if (sol_x[i][j] == 1) { fileRouteResult.WriteLine($"From city {i} to city {j}"); } } } fileRouteResult.Close(); } cplex.End(); } timeFactor += step; distanceFactor -= step; routeCounter++; } while (timeFactor <= 1); } catch (ILOG.Concert.Exception ex) { StreamWriter errorfile = new StreamWriter("./ErrorLog.txt"); errorfile.WriteLine("Exception Kind: ILOG.Concert.Exception (Concert Error)"); errorfile.WriteLine("Message: " + ex.Message); errorfile.WriteLine("StackTrace: " + ex.StackTrace); errorfile.Close(); } catch (InputDataReader.InputDataReaderException ex) { StreamWriter errorfile = new StreamWriter("./ErrorLog.txt"); errorfile.WriteLine("Exception Kind: InputDataReader.InputDataReaderException (Data Error)"); errorfile.WriteLine("Message: " + ex.Message); errorfile.WriteLine("StackTrace: " + ex.StackTrace); errorfile.Close(); } catch (System.IO.IOException ex) { StreamWriter errorfile = new StreamWriter("./ErrorLog.txt"); errorfile.WriteLine("Exception Kind: System.IO.IOException (IO Error)"); errorfile.WriteLine("Message: " + ex.Message); errorfile.WriteLine("StackTrace: " + ex.StackTrace); errorfile.Close(); } }
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; }
// This method separates Benders' cuts violated by the current x solution. // Violated cuts are found by solving the worker LP // public IRange Separate(double[][] xSol, IIntVar[][] x) { int i, j, k; IRange cut = null; // Update the objective function in the worker LP: // minimize sum(k in V0) sum((i,j) in A) x(i,j) * v(k,i,j) // - sum(k in V0) u(k,0) + sum(k in V0) u(k,k) ILinearNumExpr objExpr = cplex.LinearNumExpr(); for (k = 1; k < numNodes; ++k) { for (i = 0; i < numNodes; ++i) { for (j = 0; j < numNodes; ++j) { objExpr.AddTerm(v[k - 1][i][j], xSol[i][j]); } } } for (k = 1; k < numNodes; ++k) { objExpr.AddTerm(u[k - 1][k], 1.0); objExpr.AddTerm(u[k - 1][0], -1.0); } cplex.GetObjective().Expr = objExpr; // Solve the worker LP cplex.Solve(); // A violated cut is available iff the solution status is Unbounded if (cplex.GetStatus().Equals(Cplex.Status.Unbounded)) { // Get the violated cut as an unbounded ray of the worker LP ILinearNumExpr rayExpr = cplex.Ray; // Compute the cut from the unbounded ray. The cut is: // sum((i,j) in A) (sum(k in V0) v(k,i,j)) * x(i,j) >= // sum(k in V0) u(k,0) - u(k,k) ILinearNumExpr cutLhs = cplex.LinearNumExpr(); double cutRhs = 0.0; ILinearNumExprEnumerator rayEnum = rayExpr.GetLinearEnumerator(); while (rayEnum.MoveNext()) { INumVar var = rayEnum.NumVar; bool varFound = false; for (k = 1; k < numNodes && !varFound; ++k) { for (i = 0; i < numNodes && !varFound; ++i) { for (j = 0; j < numNodes && !varFound; ++j) { if (var.Equals(v[k - 1][i][j])) { cutLhs.AddTerm(x[i][j], rayEnum.Value); varFound = true; } } } } for (k = 1; k < numNodes && !varFound; ++k) { for (i = 0; i < numNodes && !varFound; ++i) { if (var.Equals(u[k - 1][i])) { if (i == 0) { cutRhs += rayEnum.Value; } else if (i == k) { cutRhs -= rayEnum.Value; } varFound = true; } } } } cut = cplex.Ge(cutLhs, cutRhs); } return(cut); } // END Separate
/// <summary> /// Getting maximum congruency for naming parameter sets A or B. Linear Programming optimization model. /// Eq. (4) and Table II in DOI:10.1109/CEC.2019.8790261 /// The matrices need to be manually entered here in the script (cTopA, cTopB, cBtmA, cBtmB) /// </summary> internal static void IdentifyTwoBestParameterSets(string caseSolver) { Cplex cpl = new Cplex(); int N = 7; //string caseSolver = "ES"; //"SGA" (default), "ES", "PSO", "FIPS" int[] cTopA; int[] cTopB; int[] cBtmA; int[] cBtmB; switch (caseSolver) { default: cTopA = new int[] { 11, 1, 1, 13, 0, 0, 2 }; cTopB = new int[] { 0, 5, 3, 0, 5, 5, 5 }; cBtmA = new int[] { 2, 12, 12, 0, 14, 14, 9 }; cBtmB = new int[] { 4, 0, 1, 4, 0, 0, 0 }; break; case "ES": cTopA = new int[] { 4, 6, 9, 3, 11, 11, 5 }; cTopB = new int[] { 2, 3, 1, 3, 1, 3, 3 }; cBtmA = new int[] { 4, 5, 2, 8, 0, 0, 6 }; cBtmB = new int[] { 3, 1, 3, 2, 5, 3, 2 }; break; case "PSO": cTopA = new int[] { 1, 3, 2, 3, 3, 7, 5 }; cTopB = new int[] { 12, 11, 3, 1, 7, 8, 5 }; cBtmA = new int[] { 7, 5, 6, 5, 5, 1, 3 }; cBtmB = new int[] { 0, 1, 9, 11, 5, 4, 7 }; break; case "FIPS": cTopA = new int[] { 6, 6, 7, 3, 5, 0, 8 }; cTopB = new int[] { 4, 6, 6, 9, 5, 9, 1 }; cBtmA = new int[] { 4, 4, 3, 7, 5, 10, 2 }; cBtmB = new int[] { 6, 4, 4, 1, 5, 1, 9 }; break; } INumVar[] xTopA = new INumVar[N]; INumVar[] xBtmB = new INumVar[N]; INumVar[] xTopB = new INumVar[N]; INumVar[] xBtmA = new INumVar[N]; ILinearNumExpr value = cpl.LinearNumExpr(); for (int n = 0; n < N; n++) { xTopA[n] = cpl.BoolVar(); xBtmB[n] = cpl.BoolVar(); xTopB[n] = cpl.BoolVar(); xBtmA[n] = cpl.BoolVar(); cpl.AddEq(cpl.Sum(xTopB[n], xTopA[n]), 1); cpl.AddEq(cpl.Sum(xBtmA[n], xBtmB[n]), 1); cpl.AddEq(cpl.Sum(xTopA[n], xBtmA[n]), 1); cpl.AddEq(cpl.Sum(xTopB[n], xBtmB[n]), 1); value.AddTerm(xTopA[n], cTopA[n]); value.AddTerm(xTopB[n], cTopB[n]); value.AddTerm(xBtmA[n], cBtmA[n]); value.AddTerm(xBtmB[n], cBtmB[n]); } cpl.AddMaximize(value); cpl.Solve(); Console.WriteLine("Parameter Grouping for Solver: {0}", caseSolver); for (int n = 0; n < N; n++) { Console.WriteLine("n: {0}", n); Console.WriteLine("xtopA: ;{0};, _____, xTopB: ;{1};", cpl.GetValue(xTopA[n]), cpl.GetValue(xTopB[n])); Console.WriteLine("xbtmB: ;{0};, _____, xBtmA: ;{1};", cpl.GetValue(xBtmB[n]), cpl.GetValue(xBtmA[n])); } Console.WriteLine("cost: {0}", cpl.GetObjValue()); Console.ReadKey(); }
// Step 4 ***************************************************************************************************** // Step 4 ***************************************************************************************************** internal static void PopulateByRow(IMPModeler model, out IIntVar[][][] var2, out IIntVar[][][][] var3, out IIntVar[][][][][] var4, out IRange[][] rng, CRegion lscrg, CRegion sscrg, double[,] adblTD, string strAreaAggregation) { var aCph = lscrg.GetCphCol().ToArray(); int intCpgCount = lscrg.GetCphCount(); //double dblILPSmallValue = 0.000000001; //double dblILPSmallValue = 0; var x = new IIntVar[intCpgCount][][]; for (int i = 0; i < intCpgCount; i++) { x[i] = new IIntVar[intCpgCount][]; for (int j = 0; j < intCpgCount; j++) { x[i][j] = model.BoolVarArray(intCpgCount); } } //cost in terms of type change var y = Generate4DNumVar(model, intCpgCount - 1, intCpgCount, intCpgCount, intCpgCount); //cost in terms of compactness (length of interior boundaries) var z = Generate4DNumVar(model, intCpgCount - 2, intCpgCount, intCpgCount, intCpgCount); var c = Generate4DNumVar(model, intCpgCount - 2, intCpgCount, intCpgCount, intCpgCount); var3 = new IIntVar[1][][][]; var4 = new IIntVar[3][][][][]; var3[0] = x; var4[0] = y; var4[1] = z; var4[2] = c; //model.AddEq(x[2][0][3], 1.0, "X1"); //model.AddEq(x[2][1][3], 1.0, "X2"); //model.AddEq(x[2][2][2], 1.0, "X3"); //model.AddEq(x[2][3][3], 1.0, "X4"); //add minimizations ILinearNumExpr pTypeCostExpr = model.LinearNumExpr(); //ILinearNumExpr pTypeCostAssitantExpr = model.LinearNumExpr(); for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { for (int k = 0; k < intCpgCount; k++) { for (int l = 0; l < intCpgCount; l++) { double dblCoe = aCph[j].dblArea * adblTD[aCph[k].intTypeIndex, aCph[l].intTypeIndex]; pTypeCostExpr.AddTerm(y[i][j][k][l], dblCoe); //pTypeCostAssitantExpr.AddTerm(y[i][j][k][l], dblILPSmallValueMinimization); } } } } //this is actually for t=1, whose compactness is known double dblCompCostFirstPart = 0; ILinearNumExpr pCompCostSecondPartExpr = model.LinearNumExpr(); var pAdjCorrCphsSD = lscrg.AdjCorrCphsSD; double dblConst = Convert.ToDouble(intCpgCount - 1) / Convert.ToDouble(intCpgCount - 2); for (int i = 0; i < intCpgCount - 2; i++) //i represents indices { double dblNminusT = intCpgCount - i - 2; //double dblTemp = (intCpgCount - i) * dblConst; dblCompCostFirstPart += 1 / dblNminusT; double dblSecondPartDenominator = lscrg.dblInteriorSegLength * dblNminusT * 2; //we don't need to divide the value by 2 because every boundary is only counted once foreach (var pCorrCphs in pAdjCorrCphsSD.Keys) { for (int l = 0; l < intCpgCount; l++) { pCompCostSecondPartExpr.AddTerm(pCorrCphs.dblSharedSegLength / dblSecondPartDenominator, z[i][pCorrCphs.FrCph.ID][pCorrCphs.ToCph.ID][l]); pCompCostSecondPartExpr.AddTerm(pCorrCphs.dblSharedSegLength / dblSecondPartDenominator, z[i][pCorrCphs.ToCph.ID][pCorrCphs.FrCph.ID][l]); } } //var pSecondPartExpr = model.Prod(pCompCostSecondPartExpr, 1 / dblSecondPartDenominator); } if (intCpgCount == 1) { model.AddMinimize(pTypeCostExpr); //we just use an empty expression } else { //Our Model*************************************** var Ftp = model.Prod(pTypeCostExpr, 1 / lscrg.dblArea); var Fcp = model.Prod(dblConst, model.Sum(dblCompCostFirstPart, model.Negative(pCompCostSecondPartExpr))); //model.AddMinimize(model.Prod(model.Sum(Ftp, Fcp), 0.5)); model.AddMinimize(model.Sum( model.Prod(1 - CAreaAgg_Base.dblLamda, Ftp), model.Prod(CAreaAgg_Base.dblLamda, Fcp))); //model.AddMinimize(Fcp); //model.AddMaximize(Fcp); //model.AddObjective() } //for showing slacks var IRangeLt = new List <IRange>(); //a polygon $p$ is assigned to exactly one polygon at a step $t$ for (int i = 0; i < intCpgCount; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { ILinearNumExpr pOneCenterExpr = model.LinearNumExpr(); for (int l = 0; l < intCpgCount; l++) { pOneCenterExpr.AddTerm(x[i][j][l], 1.0); } model.AddEq(pOneCenterExpr, 1.0, "AssignToOnlyOneCenter"); } } //polygon $r$, which is assigned by other polygons, must be a center for (int i = 0; i < intCpgCount; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { for (int l = 0; l < intCpgCount; l++) { model.AddLe(x[i][j][l], x[i][l][l], "AssignedIsCenter__" + i + "__" + j + "__" + l); } } } //only one patch is aggregated into another patch at each step for (int i = 0; i < intCpgCount; i++) //i represents indices { ILinearNumExpr pOneAggregationExpr = model.LinearNumExpr(); for (int j = 0; j < intCpgCount; j++) { pOneAggregationExpr.AddTerm(x[i][j][j], 1.0); } model.AddEq(pOneAggregationExpr, intCpgCount - i, "CountCenters"); } //a center can disappear, but will never reappear afterwards for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { model.AddGe(x[i][j][j], x[i + 1][j][j], "SteadyCenters"); } } //to make sure that the final aggregated polygon has the same color as the target polygon ILinearNumExpr pFinalStateExpr = model.LinearNumExpr(); int intTypeIndexGoal = sscrg.GetSoloCphTypeIndex(); for (int i = 0; i < intCpgCount; i++) { if (aCph[i].intTypeIndex == intTypeIndexGoal) { pFinalStateExpr.AddTerm(x[intCpgCount - 1][i][i], 1.0); } } model.AddEq(pFinalStateExpr, 1.0, "EnsureTarget"); //to restrict *y* for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { for (int k = 0; k < intCpgCount; k++) { //IRangeLt.Add(model.AddLe(model.Sum(y[i][j][k][k], x[i][j][k], x[i + 1][j][k]), 2.0 , "RestrictY")); for (int l = 0; l < intCpgCount; l++) { var LieYRight = model.LinearIntExpr(-1); LieYRight.AddTerm(x[i][j][k], 1); LieYRight.AddTerm(x[i + 1][j][l], 1); model.AddGe(y[i][j][k][l], LieYRight, "RestrictY1"); model.AddLe(y[i][j][k][l], x[i][j][k], "RestrictY2"); model.AddLe(y[i][j][k][l], x[i + 1][j][l], "RestrictY3"); } } } } //to restrict *z* for (int i = 0; i < intCpgCount - 2; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { //for (int k = j; k < intCpgCount; k++) // pay attention for (int k = 0; k < intCpgCount; k++) { for (int l = 0; l < intCpgCount; l++) { var LieZRight = model.LinearIntExpr(-1); LieZRight.AddTerm(x[i + 1][j][l], 1); LieZRight.AddTerm(x[i + 1][k][l], 1); model.AddGe(z[i][j][k][l], LieZRight, "RestrictZ1"); model.AddLe(z[i][j][k][l], x[i + 1][j][l], "RestrictZ2"); model.AddLe(z[i][j][k][l], x[i + 1][k][l], "RestrictZ3"); } } } } //to restrict *c* double dblCpgCountReciprocal = 1 / Convert.ToDouble(intCpgCount); for (int i = 0; i < intCpgCount - 2; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { //for (int k = j; k < intCpgCount; k++) // pay attention for (int k = 0; k < intCpgCount; k++) { for (int l = 0; l < intCpgCount; l++) { if (k == l) { continue; } model.AddLe(c[i][j][k][l], x[i][j][k], "RestrictC1"); var pLieContiguityExpr = model.LinearIntExpr(); //pContiguityExpr.AddTerm(x[i][j][k], 1.0); //including polygon j itself foreach (var pAdjacentCph in aCph[j].AdjacentCphSS) { pLieContiguityExpr.AddTerm(x[i][pAdjacentCph.ID][l], 1); } model.AddLe(c[i][j][k][l], pLieContiguityExpr, "Contiguity"); foreach (var pAdjacentCph in aCph[j].AdjacentCphSS) { var pContiguityExpr2 = model.LinearNumExpr(-1); pContiguityExpr2.AddTerm(x[i][j][k], 1); pContiguityExpr2.AddTerm(x[i][pAdjacentCph.ID][l], 1); model.AddGe(c[i][j][k][l], pContiguityExpr2, "Contiguity2"); } var pContiguityExprRight3 = model.LinearIntExpr(); for (int m = 0; m < intCpgCount; m++) { pContiguityExprRight3.AddTerm(c[i][m][k][l], 1); } model.AddLe(y[i][k][k][l], pContiguityExprRight3, "Contiguity3"); } } } } //If two polygons have been aggregated into one polygon, then they will //be aggregated together in later steps. Our sixth constraint achieve this by requiring for (int i = 0; i < intCpgCount - 3; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { for (int k = 0; k < intCpgCount; k++) { var pAssignTogetherExprPre = model.LinearIntExpr(); var pAssignTogetherExprAfter = model.LinearIntExpr(); for (int l = 0; l < intCpgCount; l++) { pAssignTogetherExprPre.AddTerm(z[i][j][k][l], 1); pAssignTogetherExprAfter.AddTerm(z[i + 1][j][k][l], 1); } model.AddLe(pAssignTogetherExprPre, pAssignTogetherExprAfter, "AssignTogether"); } } } var2 = new IIntVar[1][][]; if (strAreaAggregation == _strSmallest) { IIntVar[][] w = new IIntVar[intCpgCount - 1][]; for (int i = 0; i < intCpgCount - 1; i++) { w[i] = model.BoolVarArray(intCpgCount); } var2[0] = w; //there is only one smallest patch will be involved in each aggregation step for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { var pOneSmallestExpr = model.LinearIntExpr(); for (int j = 0; j < intCpgCount; j++) { pOneSmallestExpr.AddTerm(w[i][j], 1); } model.AddEq(pOneSmallestExpr, 1.0, "OneSmallest"); } //forces that the aggregation must involve the smallest patch. for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { for (int j = 0; j < intCpgCount; j++) { var pInvolveSmallestExpr = model.LinearIntExpr(); for (int k = 0; k < intCpgCount; k++) { if (j == k) //o != r { continue; } pInvolveSmallestExpr.AddTerm(y[i][j][j][k], 1); pInvolveSmallestExpr.AddTerm(y[i][k][k][j], 1); } model.AddLe(w[i][j], pInvolveSmallestExpr, "InvolveSmallest"); } } //To guarantee that patch $o$ is involved in aggregation is indeed the smallest patch double dblM = 1.1 * lscrg.dblArea; //a very large value for (int i = 0; i < intCpgCount - 1; i++) //i represents indices { var aAreaExpr = ComputeAreaExpr(model, x[i], aCph); for (int j = 0; j < intCpgCount; j++) { for (int k = 0; k < intCpgCount; k++) { if (j == k) //o != r { continue; } var pSumExpr = model.Sum(2.0, model.Negative(model.Sum(w[i][j], x[i][k][k]))); //(2-w_{t,o}-x_{t,r,r}) var pProdExpr = model.Prod(pSumExpr, dblM); //M(2-w_{t,o}-x_{t,r,r}) //A_{t,o}-A_{t,r}<= M(2-w_{t,o}-x_{t,r,r}) model.AddLe(model .Sum(aAreaExpr[j], model.Negative(aAreaExpr[k])), pProdExpr, "IndeedSmallest"); } } } } //***************compare with number of constraints counted manually************ rng = new IRange[1][]; rng[0] = new IRange[IRangeLt.Count]; for (int i = 0; i < IRangeLt.Count; i++) { rng[0][i] = IRangeLt[i]; } }
public Dictionary <EdgePair, Double> Solve(FCTPGraph ti) { Dictionary <EdgePair, Double> edgeFlows = new Dictionary <EdgePair, Double>(); Dictionary <String, Edge> edgeMap = new Dictionary <String, Edge>(); Dictionary <String, INumVar> varMap = new Dictionary <String, INumVar>(); String currentVar = ""; try { //Model Cplex cplex = new Cplex(); IModel model = cplex.GetModel(); //model.Set(GRB.StringAttr.ModelName, "tranportation"); ILinearNumExpr expr = cplex.LinearNumExpr(); //edges foreach (Edge e in ti.Edges) { String xij = edgeVarName(e.Source, e.Sink); edgeMap.Add(xij, e); INumVar var = cplex.NumVar(0, System.Double.MaxValue); var.Name = xij; varMap.Add(xij, var); expr.AddTerm(e.C, var); } //objective min Sum c_{ij} x_{ij} model.Add(cplex.Minimize(expr)); //supply constraints foreach (Node ssource in ti.Sources) { List <INumExpr> sourceConstraint = new List <INumExpr>(); foreach (Node ssink in ti.Sinks) { String name = edgeVarName(ssource.Id, ssink.Id); sourceConstraint.Add(varMap[name]); } cplex.AddEq(cplex.Sum(sourceConstraint.ToArray()), ssource.Amount); } //demand constraints foreach (Node dsink in ti.Sinks) { List <INumExpr> sinkConstraint = new List <INumExpr>(); foreach (Node dsource in ti.Sources) { String name = edgeVarName(dsource.Id, dsink.Id); sinkConstraint.Add(varMap[name]); } cplex.AddEq(cplex.Sum(sinkConstraint.ToArray()), dsink.Amount); } cplex.SetParam(Cplex.BooleanParam.Threads, 1); cplex.ExportModel("mipTranportationCplex.lp"); bool status = cplex.Solve(); Console.WriteLine("Status: " + status); foreach (String s in edgeMap.Keys) { currentVar = s; double flow = cplex.GetValue(varMap[s]); Edge e = edgeMap[s]; EdgePair ep = new EdgePair(e.Source, e.Sink); edgeFlows.Add(ep, flow); } cplex.End(); } catch (ILOG.Concert.Exception e) { Console.Out.WriteLine(currentVar + " - is current var"); Console.Out.WriteLine(e.ToString()); } return(edgeFlows); }
private void Calculate() { try { btnCalc.Enabled = false; int ret; for (int i = 0; i > dgvTransport.ColumnCount; i++) { for (int j = 0; j > dgvTransport.RowCount; j++) { if ((int.TryParse(dgvTransport[i, j].Value.ToString(), out ret) == false || dgvTransport[i, j].Value.ToString() != "T") && i != dgvTransport.ColumnCount - 1 && j != dgvTransport.RowCount - 1) { throw new ILOG.Concert.Exception("A beviteli mezők értékének vagy egész számnak, vagy T-nek kell lennie!"); } } } Cplex cplex = new Cplex(); int Supply = (int)nudSourceNum.Value; int Drain = (int)nudDrainNum.Value; int[] temp; int SumSources = 0; int SumDrains = 0; int sumValue; sumValue = 0; for (int i = 0; i < dgvTransport.RowCount - 1; i++) { int.TryParse(dgvTransport[dgvTransport.ColumnCount - 1, i].Value.ToString(), out sumValue); SumSources += sumValue; } sumValue = 0; for (int i = 0; i < dgvTransport.ColumnCount - 1; i++) { int.TryParse(dgvTransport[i, dgvTransport.RowCount - 1].Value.ToString(), out sumValue); SumDrains += sumValue; } if (SumSources != SumDrains) { //Nyílt szállítási feladat if (SumSources < SumDrains) { DataGridViewRow r = new DataGridViewRow(); r.HeaderCell.Value = "FIKTÍV"; for (int i = 0; i < dgvTransport.ColumnCount - 1; i++) { DataGridViewCell c = new DataGridViewTextBoxCell(); c.Value = 0; r.Cells.Add(c); } DataGridViewTextBoxCell cSupply = new DataGridViewTextBoxCell(); cSupply.Value = SumDrains - SumSources; r.Cells.Add(cSupply); dgvTransport.Rows.Insert(dgvTransport.RowCount - 1, r); Supply++; } //egyenlő itt nem lehet, mert csak akkor lép be, ha nem egyenlő a két érték else { DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn(); col.HeaderText = "FIKTÍV"; dgvTransport.Columns.Insert(dgvTransport.ColumnCount - 1, col); for (int i = 0; i < dgvTransport.RowCount - 1; i++) { dgvTransport[dgvTransport.ColumnCount - 2, i].Value = 0; } dgvTransport[dgvTransport.ColumnCount - 2, dgvTransport.RowCount - 1].Value = SumSources - SumDrains; Drain++; } } int[][] Cmatrix = new int[Supply][]; int[] sources = new int[Supply]; int[] drains = new int[Drain]; INumVar[][] x = new INumVar[Supply][]; INumVar[][] y = new INumVar[Supply][]; for (int i = 0; i < Supply; i++) { x[i] = cplex.NumVarArray(Drain, 0.0, int.MaxValue); y[i] = cplex.NumVarArray(Drain, 0.0, int.MaxValue); } //források for (int i = 0; i < dgvTransport.RowCount - 1; i++) { int.TryParse(dgvTransport[dgvTransport.ColumnCount - 1, i].Value.ToString(), out sources[i]); } //nyelők for (int i = 0; i < dgvTransport.ColumnCount - 1; i++) { int.TryParse(dgvTransport[i, dgvTransport.RowCount - 1].Value.ToString(), out drains[i]); } //Coef Matrix for (int i = 0; i < dgvTransport.RowCount - 1; i++) { temp = new int[Drain]; for (int j = 0; j < dgvTransport.ColumnCount - 1; j++) { if (dgvTransport[j, i].Value.ToString() != "T") { int.TryParse(dgvTransport[j, i].Value.ToString(), out temp[j]); } else { temp[j] = int.MaxValue; } } Cmatrix[i] = temp; } for (int i = 0; i < Supply; i++) // supply must meet demand { cplex.AddEq(cplex.Sum(x[i]), sources[i]); } for (int j = 0; j < Drain; j++) { // demand must meet supply ILinearNumExpr v = cplex.LinearNumExpr(); for (int i = 0; i < Supply; i++) { v.AddTerm(1.0, x[i][j]); } cplex.AddEq(v, drains[j]); } ILinearNumExpr expr = cplex.LinearNumExpr(); for (int i = 0; i < Supply; ++i) { for (int j = 0; j < Drain; ++j) { expr.AddTerm(x[i][j], Cmatrix[i][j]); } } cplex.AddMinimize(expr); cplex.Solve(); MessageBox.Show("A megoldás: " + cplex.GetStatus().ToString()); lblSolutionType.Text = "A megoldás: " + cplex.GetStatus().ToString(); System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" - Solution: "); dgvSolution.RowCount = Supply; dgvSolution.ColumnCount = Drain; for (int i = 0; i < Supply; ++i) { System.Console.Write(" " + i + ": "); for (int j = 0; j < Drain; ++j) { System.Console.Write("" + cplex.GetValue(x[i][j]) + "\t"); dgvSolution[j, i].Value = cplex.GetValue(x[i][j]); } System.Console.WriteLine(); } System.Console.WriteLine(" Cost = " + cplex.ObjValue); lblZValue.Text = "A célfüggvény értéke: " + cplex.ObjValue; cplex.End(); } catch (ILOG.Concert.Exception icex) { MessageBox.Show(icex.Message); } }
private void runModel(List <Employee> employees, List <Shift> shifts) { StreamWriter writer = File.CreateText(@"C:\Users\user\Desktop\cplex log\result9.txt"); try { Cplex model = new Cplex(); model.SetOut(writer); //------------------------------ //---Variable initialization----- //------------------------------ //Assignment variables IDictionary <string, IIntVar> assignVars = new Dictionary <string, IIntVar>(); employees.ForEach(employee => { shifts.ForEach(shift => { string name = getAssignVarName(employee, shift); assignVars.Add(name, model.BoolVar(name)); }); }); //Total assignment hours INumVar totalAssignHourVar = model.NumVar(0, Double.MaxValue, getTotalAssignVarName()); //---------------------------------- //---Constraints initialization----- //----------------------------------- //1) Min rest constraint //2) Goal total assigned hours constraint ILinearNumExpr sumAssignHourExpr = model.LinearNumExpr(); sumAssignHourExpr.AddTerm(-1.0, totalAssignHourVar); employees.ForEach(employee => { shifts.ForEach(shift1 => { ILinearNumExpr sumOverlapExpr = model.LinearNumExpr(); string name1 = getAssignVarName(employee, shift1); IIntVar assignVar1 = assignVars[name1]; sumOverlapExpr.AddTerm(1.0, assignVar1); shifts.ForEach(shift2 => { if (shift1 != shift2 && this.isDurationOverlap(shift1, shift2)) { string name2 = getAssignVarName(employee, shift2); sumOverlapExpr.AddTerm(1.0, assignVars[name2]); } }); model.AddLe(sumOverlapExpr, 1.0, "MinRestConst"); sumAssignHourExpr.AddTerm((shift1.end - shift1.begin).TotalMinutes, assignVar1); }); }); //3) No overassignment constraint shifts.ForEach(shift => { ILinearNumExpr sumAssigsExpr = model.LinearNumExpr(); employees.ForEach(employee => { string name1 = getAssignVarName(employee, shift); IIntVar assignVar1 = assignVars[name1]; sumAssigsExpr.AddTerm(1.0, assignVar1); }); model.AddLe(sumAssigsExpr, shift.shiftNumber, "NoOverAssignConst"); }); model.AddEq(sumAssignHourExpr, 0.0, "TotalAssignedHourConst"); INumVar[] goalVars = { totalAssignHourVar }; double[] coeffs = { 1.0 }; model.AddMaximize(model.ScalProd(goalVars, coeffs)); model.ExportModel(@"C:\Users\user\Desktop\cplex log\model1.lp"); bool feasible = model.Solve(); if (feasible) { double objVal = model.ObjValue; model.Output().WriteLine("Solution value = " + model.ObjValue); shifts.ForEach(shift => { ILinearNumExpr sumAssigsExpr = model.LinearNumExpr(); employees.ForEach(employee => { string name = getAssignVarName(employee, shift); }); model.AddLe(sumAssigsExpr, shift.shiftNumber, "NoOverAssignConst"); }); } else { } } catch (System.Exception ex) { Response.ContentType = "application/json; charset=utf-8"; Response.Write(ex.Message); Response.End(); } writer.Close(); }
// The constructor sets up the Cplex instance to solve the worker LP, // and creates the worker LP (i.e., the dual of flow constraints and // capacity constraints of the flow MILP) // // Modeling variables: // forall k in V0, i in V: // u(k,i) = dual variable associated with flow constraint (k,i) // // forall k in V0, forall (i,j) in A: // v(k,i,j) = dual variable associated with capacity constraint (k,i,j) // // Objective: // minimize sum(k in V0) sum((i,j) in A) x(i,j) * v(k,i,j) // - sum(k in V0) u(k,0) + sum(k in V0) u(k,k) // // Constraints: // forall k in V0, forall (i,j) in A: u(k,i) - u(k,j) <= v(k,i,j) // // Nonnegativity on variables v(k,i,j) // forall k in V0, forall (i,j) in A: v(k,i,j) >= 0 // internal WorkerLP(int numNodes) { this.numNodes = numNodes; int i, j, k; // Set up Cplex instance to solve the worker LP cplex = new Cplex(); cplex.SetOut(null); // Turn off the presolve reductions and set the CPLEX optimizer // to solve the worker LP with primal simplex method. cplex.SetParam(Cplex.Param.Preprocessing.Reduce, 0); cplex.SetParam(Cplex.Param.RootAlgorithm, Cplex.Algorithm.Primal); // Create variables v(k,i,j) forall k in V0, (i,j) in A // For simplicity, also dummy variables v(k,i,i) are created. // Those variables are fixed to 0 and do not partecipate to // the constraints. v = new INumVar[numNodes - 1][][]; for (k = 1; k < numNodes; ++k) { v[k - 1] = new INumVar[numNodes][]; for (i = 0; i < numNodes; ++i) { v[k - 1][i] = new INumVar[numNodes]; for (j = 0; j < numNodes; ++j) { v[k - 1][i][j] = cplex.NumVar(0.0, System.Double.MaxValue, "v." + k + "." + i + "." + j); cplex.Add(v[k - 1][i][j]); } v[k - 1][i][i].UB = 0.0; } } // Create variables u(k,i) forall k in V0, i in V u = new INumVar[numNodes - 1][]; for (k = 1; k < numNodes; ++k) { u[k - 1] = new INumVar[numNodes]; for (i = 0; i < numNodes; ++i) { u[k - 1][i] = cplex.NumVar(-System.Double.MaxValue, System.Double.MaxValue, "u." + k + "." + i); cplex.Add(u[k - 1][i]); } } // Initial objective function is empty cplex.AddMinimize(); // Add constraints: // forall k in V0, forall (i,j) in A: u(k,i) - u(k,j) <= v(k,i,j) for (k = 1; k < numNodes; ++k) { for (i = 0; i < numNodes; ++i) { for (j = 0; j < numNodes; ++j) { if (i != j) { ILinearNumExpr expr = cplex.LinearNumExpr(); expr.AddTerm(v[k - 1][i][j], -1.0); expr.AddTerm(u[k - 1][i], 1.0); expr.AddTerm(u[k - 1][j], -1.0); cplex.AddLe(expr, 0.0); } } } } } // END WorkerLP
//Building initial model public static INumVar[] BuildModel(Cplex cplex, Instance instance, int nEdges) { //Init the model's variables INumVar[] x = new INumVar[(instance.NNodes - 1) * instance.NNodes / 2]; /* * expr will hold all the expressions that needs to be added to the model * initially it will be the optimality's functions * later it will be Ax's rows */ ILinearNumExpr expr = cplex.LinearNumExpr(); //Populating objective function for (int i = 0; i < instance.NNodes; i++) { if (nEdges >= 0) { List <int>[] listArray = BuildSL(instance); //Only links (i,i) with i < i are correct for (int j = i + 1; j < instance.NNodes; j++) { //xPos return the correct position where to store the variable corresponding to the actual link (i,i) int position = xPos(i, j, instance.NNodes); if ((listArray[i]).IndexOf(j) < nEdges) { x[position] = cplex.NumVar(0, 1, NumVarType.Bool, "x(" + (i + 1) + "," + (j + 1) + ")"); } else { x[position] = cplex.NumVar(0, 0, NumVarType.Bool, "x(" + (i + 1) + "," + (j + 1) + ")"); } expr.AddTerm(x[position], Point.Distance(instance.Coord[i], instance.Coord[j], instance.EdgeType)); } } else { //Only links (i,i) with i < i are correct for (int j = i + 1; j < instance.NNodes; j++) { //xPos return the correct position where to store the variable corresponding to the actual link (i,i) int position = xPos(i, j, instance.NNodes); x[position] = cplex.NumVar(0, 1, NumVarType.Bool, "x(" + (i + 1) + "," + (j + 1) + ")"); expr.AddTerm(x[position], Point.Distance(instance.Coord[i], instance.Coord[j], instance.EdgeType)); } } } //Setting the optimality's function cplex.AddMinimize(expr); //Starting to elaborate Ax for (int i = 0; i < instance.NNodes; i++) { //Resetting expr expr = cplex.LinearNumExpr(); for (int j = 0; j < instance.NNodes; j++) { //For each row i only the links (i,i) or (i,i) have coefficent 1 //xPos return the correct position where link is stored inside the vector x if (i != j)//No loops wioth only one node { expr.AddTerm(x[xPos(i, j, instance.NNodes)], 1); } } //Adding to Ax the current equation with known term 2 and name degree(<current i node>) cplex.AddEq(expr, 2, "degree(" + (i + 1) + ")"); } //Printing the complete model inside the file <name_file.tsp.lp> if (Program.VERBOSE >= -1) { cplex.ExportModel(instance.InputFile + ".lp"); } return(x); }
} // END WorkerLP // This method creates the master ILP (arc variables x and degree constraints). // // Modeling variables: // forall (i,j) in A: // x(i,j) = 1, if arc (i,j) is selected // = 0, otherwise // // Objective: // minimize sum((i,j) in A) c(i,j) * x(i,j) // // Degree constraints: // forall i in V: sum((i,j) in delta+(i)) x(i,j) = 1 // forall i in V: sum((j,i) in delta-(i)) x(j,i) = 1 // // Binary constraints on arc variables: // forall (i,j) in A: x(i,j) in {0, 1} // internal static void CreateMasterILP(IModeler model, Data data, IIntVar[][] x) { int i, j; int numNodes = data.numNodes; // Create variables x(i,j) for (i,j) in A // For simplicity, also dummy variables x(i,i) are created. // Those variables are fixed to 0 and do not partecipate to // the constraints. for (i = 0; i < numNodes; ++i) { x[i] = new IIntVar[numNodes]; for (j = 0; j < numNodes; ++j) { x[i][j] = model.BoolVar("x." + i + "." + j); model.Add(x[i][j]); } x[i][i].UB = 0; } // Create objective function: minimize sum((i,j) in A ) c(i,j) * x(i,j) ILinearNumExpr objExpr = model.LinearNumExpr(); for (i = 0; i < numNodes; ++i) { objExpr.Add(model.ScalProd(x[i], data.arcCost[i])); } model.AddMinimize(objExpr); // Add the out degree constraints. // forall i in V: sum((i,j) in delta+(i)) x(i,j) = 1 for (i = 0; i < numNodes; ++i) { ILinearNumExpr expr = model.LinearNumExpr(); for (j = 0; j < i; ++j) { expr.AddTerm(x[i][j], 1.0); } for (j = i + 1; j < numNodes; ++j) { expr.AddTerm(x[i][j], 1.0); } model.AddEq(expr, 1.0); } // Add the in degree constraints. // forall i in V: sum((j,i) in delta-(i)) x(j,i) = 1 for (i = 0; i < numNodes; ++i) { ILinearNumExpr expr = model.LinearNumExpr(); for (j = 0; j < i; ++j) { expr.AddTerm(x[j][i], 1.0); } for (j = i + 1; j < numNodes; ++j) { expr.AddTerm(x[j][i], 1.0); } model.AddEq(expr, 1.0); } } // END CreateMasterILP
private void button1_Click(object sender, EventArgs e) { int[,] A = new int[, ] { { 1, 1, 1, 1, 0 }, { 1, 1, 0, 1, 1 }, { 0, 1, 1, 1, 1 } }; double[] L = new double[] { 8, 5, 7, 8, 4 }; double G = 10.7; double[] N_Max = new double[] { 2, 2, 2 }; int nbOfWorkers = A.GetLength(0); int nbOfTasks = A.GetLength(1); Cplex cplex = new Cplex(); INumVar[,] X = new INumVar[nbOfWorkers, nbOfTasks]; // C라는 2차원 인덱스가 0이면, 행의 개수을 받겠다 // C라는 2차원 인덱스가 1이면 열의 개수를 받겠다. for (int i = 0; i < A.GetLength(0); i++) { for (int j = 0; j < A.GetLength(1); j++) { X[i, j] = cplex.BoolVar(); } } List <INumVar> D_negative = new List <INumVar>(); for (int i = 0; i < nbOfWorkers; i++) { D_negative.Add(cplex.NumVar(0, double.MaxValue)); } List <INumVar> D_positive = new List <INumVar>(); for (int i = 0; i < nbOfWorkers; i++) { D_positive.Add(cplex.NumVar(0, double.MaxValue)); } //목적함수 ILinearNumExpr objectiveFunction = cplex.LinearNumExpr(); for (int i = 0; i < nbOfWorkers; i++) { objectiveFunction.AddTerm(1, D_negative[i]); } for (int i = 0; i < nbOfWorkers; i++) { objectiveFunction.AddTerm(1, D_positive[i]); // C[i, j], X[i, j] 두개를 곱해서 objectiveFunction 에 넣겠다. } //과제 for (int i = 0; i < nbOfWorkers; i++) { ILinearNumExpr constLeft1 = cplex.LinearNumExpr(); for (int j = 0; j < nbOfTasks; j++) { constLeft1.AddTerm(L[j], X[i, j]); } constLeft1.AddTerm(1, D_negative[i]); constLeft1.AddTerm(-1, D_positive[i]); cplex.AddEq(constLeft1, G); } for (int j = 0; j < nbOfTasks; j++) { ILinearNumExpr constLeft2 = cplex.LinearNumExpr(); for (int i = 0; i < X.GetLength(0); i++) { constLeft2.AddTerm(1, X[i, j]); } cplex.AddEq(constLeft2, 1); } for (int i = 0; i < nbOfWorkers; i++) { for (int j = 0; j < nbOfTasks; j++) { cplex.AddLe(X[i, j], A[i, j]); } } for (int i = 0; i < nbOfWorkers; i++) { ILinearNumExpr constLeft4 = cplex.LinearNumExpr(); for (int j = 0; j < nbOfTasks; j++) { constLeft4.AddTerm(1, X[i, j]); } cplex.AddLe(constLeft4, N_Max[i]); } cplex.AddMinimize(objectiveFunction); cplex.Solve(); string solution = ""; double tolerance = cplex.GetParam(Cplex.Param.MIP.Tolerances.Integrality); //tolerance를 정의함 for (int i = 0; i < A.GetLength(0); i++) { for (int j = 0; j < A.GetLength(1); j++) { if (cplex.GetValue(X[i, j]) >= 1 - tolerance) { solution += "(" + (i + 1).ToString() + " ," + (j + 1).ToString() + ")"; } } } MessageBox.Show("목적함수 값은 =" + cplex.GetObjValue() + "\r\n" + "선택된 변수는 =" + solution); }