protected void AddConstraint(int t, IALPDecision a)//Add a column into RMP model { if (constraints[t].ContainsKey(a)) { return; } INumExpr exp1 = RMPModel.NumExpr(); if (t < Data.TimeHorizon - 1) { exp1 = RMPModel.Sum(Var2[t], RMPModel.Prod(-1, Var2[t + 1])); foreach (IALPResource re in Data.RS) { if (a.UseResource(re)) { exp1 = RMPModel.Sum(exp1, Var1[t][Data.RS.IndexOf(re)], RMPModel.Prod(Data.Qti(t, re, a) - 1, Var1[t + 1][Data.RS.IndexOf(re)])); } } } else { exp1 = RMPModel.Sum(exp1, Var2[t]); foreach (IALPResource re in Data.RS) { if (a.UseResource(re)) { exp1 = RMPModel.Sum(exp1, Var1[t][Data.RS.IndexOf(re)]); } } } constraints[t].Add(a, RMPModel.AddGe(exp1, Data.Rt(t, a))); }
static void Main(string[] args) { Cplex m = new Cplex(); INumVar x1 = m.NumVar(0, System.Double.MaxValue, NumVarType.Float, "food.1"); INumVar x2 = m.NumVar(0, System.Double.MaxValue, NumVarType.Float, "food.2"); INumVar x3 = m.NumVar(0, System.Double.MaxValue, NumVarType.Float, "food.3"); INumVar x4 = m.NumVar(0, System.Double.MaxValue, NumVarType.Float, "food.4"); INumVar x5 = m.NumVar(0, System.Double.MaxValue, NumVarType.Float, "food.5"); IObjective obj = m.AddMinimize(m.Sum( m.Prod(x1, 20), m.Prod(x2, 10), m.Prod(x3, 31), m.Prod(x4, 11), m.Prod(x5, 12))); INumExpr ironLHS = m.Sum(m.Prod(x1, 2), m.Prod(x3, 3), m.Prod(x4, 1), m.Prod(x5, 2)); IRange con1 = m.AddGe(ironLHS, 21, "nutrient.iron"); INumExpr calciumLHS = m.Sum(m.Prod(x2, 1), m.Prod(x3, 2), m.Prod(x4, 2), m.Prod(x5, 1)); IRange con2 = m.AddGe(calciumLHS, 12, "nutrient.calcium"); Console.WriteLine("**** Solver Output:\n"); m.Solve(); m.ExportModel("diet.lp"); Console.WriteLine("\n**** Diet Program Output:\n"); Console.WriteLine("Objective Value = {0}", m.GetObjValue()); Console.WriteLine("{0} = {1}, reduced cost = {2}", x1.Name, m.GetValue(x1), m.GetReducedCost(x1)); Console.WriteLine("{0} = {1}, reduced cost = {2}", x2.Name, m.GetValue(x2), m.GetReducedCost(x2)); Console.WriteLine("{0} = {1}, reduced cost = {2}", x3.Name, m.GetValue(x3), m.GetReducedCost(x3)); Console.WriteLine("{0} = {1}, reduced cost = {2}", x4.Name, m.GetValue(x4), m.GetReducedCost(x4)); Console.WriteLine("{0} = {1}, reduced cost = {2}", x5.Name, m.GetValue(x5), m.GetReducedCost(x5)); Console.WriteLine("{0}, slack = {1}, pi = {2}", con1.Name, m.GetSlack(con1), m.GetDual(con1)); Console.WriteLine("{0}, slack = {1}, pi = {2}", con2.Name, m.GetSlack(con2), m.GetDual(con2)); m.End(); }
public virtual void StepFoward() { alpha -= step; //TODO:Delete Agg constraint(s) foreach (var a in Aggconstraints) { RMPModel.Remove(a.Value); } List <IALPDecision> list = Aggconstraints.Keys.ToList(); Aggconstraints.Clear(); //TODO:Add DisAgg variables and constraint(s) for (int i = alpha + 1; i <= alpha + step; i++) { constraints.Add(i, new Dictionary <IALPDecision, IRange>()); Var1.Add(i, RMPModel.NumVarArray(Data.RS.Count, 0, double.MaxValue)); Var2.Add(i, RMPModel.NumVar(0, double.MaxValue)); V.Add(i, new double[Data.RS.Count]); Sita.Add(i, 0); } for (int t = alpha + 1; t <= alpha + step; t++) { if (t < Data.TimeHorizon - 1) { foreach (IALPResource re in Data.RS) { INumExpr exp2 = RMPModel.Sum(Var1[t][Data.RS.IndexOf(re)], RMPModel.Prod(-1, Var1[t + 1][Data.RS.IndexOf(re)])); RMPModel.AddGe(exp2, 0); } INumExpr exp3 = RMPModel.Sum(Var2[t], RMPModel.Prod(-1, Var2[t + 1])); RMPModel.AddGe(exp3, 0); } } foreach (IALPResource re in Data.RS) { INumExpr exp6 = RMPModel.NumExpr(); exp6 = RMPModel.Sum(AggVar1[Data.RS.IndexOf(re)], RMPModel.Prod(-1, Var1[alpha + 1][Data.RS.IndexOf(re)])); RMPModel.AddGe(exp6, 0); } INumExpr exp4 = RMPModel.NumExpr(); exp4 = RMPModel.Sum(exp4, AggVar2, RMPModel.Prod(-1, Var2[alpha + 1])); RMPModel.AddGe(exp4, 0); IALPDecision d = (Data.DS as IALPDecisionSpace).CloseAllDecision() as IALPDecision; AddConstraint1(d); foreach (IALPDecision de in list) { AddConstraint1(de); } for (int t = alpha + 1; t <= alpha + step; t++) { AddConstraint2(t, d); } }
private void initializeArbitraryBooleanConstraints(Cplex cplex, VariabilityModel vm, Dictionary <BinaryOption, INumVar> optsToCplex) { foreach (string booleanConstraint in vm.BinaryConstraints) { string[] cnfParts = booleanConstraint.Split('&'); foreach (string cnfPart in cnfParts) { string[] variables = cnfPart.Split('|'); INumExpr[] logicOrConstr = new INumExpr[variables.Length]; for (int i = 0; i < variables.Length; i++) { string var = variables[i].Trim(); // In binary domain (1 - x) equals the negation of x if (var.StartsWith("!") || var.StartsWith("-")) { logicOrConstr[i] = cplex.Sum(1, cplex.Negative((optsToCplex[vm.getBinaryOption(var.Substring(1))]))); } else { logicOrConstr[i] = optsToCplex[vm.getBinaryOption(var)]; } } // Since we use cnf notation, it is enough to check if the sum of a single clause is // greater or equal 1 cplex.AddGe(cplex.Sum(logicOrConstr), one); } } }
public void BuildRMP(List <Pairing> initialPathSet) { //GetCoverMatrix() INumExpr obj_expr = RMP.NumExpr(); foreach (Pairing path in initialPathSet) { if (path.Route.Count <= 2) { continue; } ColumnPool.Add(path); //create obj function INumVar x = RMP.NumVar(0, 1, NumVarType.Float); DvarSet.Add(x); obj_expr = RMP.Sum(obj_expr, RMP.Prod(path.Cost_with_penalty, x)); CoverMatrix.Add(path.CoverAaray); } RMP.AddObjective(ObjectiveSense.Minimize, obj_expr); //s.t for (int i = 0; i < num_task; i++) { INumExpr ct = RMP.NumExpr(); for (int j = 0; j < DvarSet.Count; j++) { ct = RMP.Sum(ct, RMP.Prod(CoverMatrix[j][i], DvarSet[j])); } constraints[i] = RMP.AddGe(ct, 1); } }
private void FindCliqueInternal() { CallsCount++; if (!cplex.Solve()) { return; } var objValue = cplex.GetObjValue(); // this branch won't give us better result than existing one if (objValue < upperBound || objValue.Almost(upperBound)) { return; } var branchingVariable = numVars.FirstOrDefault(var => !cplex.GetValue(var).IsInteger()); if (branchingVariable == null) { var values = cplex.GetValues(numVars); maxClique = graph.Nodes.Where((_, i) => values[i].Almost(1)).ToList(); upperBound = maxClique.Count; return; } var constraint = cplex.AddGe(branchingVariable, 1); FindCliqueInternal(); cplex.Remove(constraint); constraint = cplex.AddLe(branchingVariable, 0); FindCliqueInternal(); cplex.Remove(constraint); }
public static Cplex BuildLPModel(IFTMDP Ida) { Cplex model = new Cplex(); INumVar[][] v = new INumVar[Ida.TimeHorizon][]; //V(t,x) for (int t = 0; t < Ida.TimeHorizon; t++) { v[t] = model.NumVarArray(Ida.SS.Count, -double.MaxValue, double.MaxValue); } IObjective RevenueUB = model.AddMinimize(model.Prod(1, v[0][Ida.SS.IndexOf(Ida.InitialState)])); //time->State->Active-> Expression for (int t = 0; t < Ida.TimeHorizon; t++) { foreach (IMDPState s in Ida.SS) { foreach (IMDPDecision a in Ida.GenDecisionSpace(s)) { INumExpr expr = v[t][Ida.SS.IndexOf(s)]; if (t < Ida.TimeHorizon - 1) { foreach (IMDPState k in Ida.GenStateSpace(s, a)) { expr = model.Sum(expr, model.Prod(-Ida.Prob(t, s, k, a), v[t + 1][Ida.SS.IndexOf(k)])); } } model.AddGe(expr, Ida.Reward(t, s, a)); } } } //model.SetOut(null); return(model); }
/// <summary>建立最初的RMP /// 依据初始解 /// </summary> /// <param name="IS"></param> public void Build_RMP(InitialSolution IS) { initialPath_num = IS.PathSet.Count; trip_num = TripList.Count; realistic_trip_num = NetWork.num_Physical_trip; DvarSet = new List <INumVar>(); CoefSet = new List <double>(); A_Matrix = new List <int[]>(); PathSet = new List <Pairing>(); //virtualVarSet = new List<INumVar>(); //for (int virtual_x = 0; virtual_x < realistic_trip_num; virtual_x++) { // virtualVarSet.Add(masterModel.NumVar(0, 1, NumVarType.Float)); //} CoefSet = IS.Coefs; A_Matrix = IS.A_Matrix; PathSet = IS.PathSet; foreach (var p in PathSet) { ColumnPool.Add(p); } int i, j; Obj = masterModel.AddMinimize(); Constraint = new IRange[realistic_trip_num]; /**按行建模**/ //vars and obj function for (j = 0; j < initialPath_num; j++) { INumVar var = masterModel.NumVar(0, 1, NumVarType.Float); DvarSet.Add(var); Obj.Expr = masterModel.Sum(Obj.Expr, masterModel.Prod(CoefSet[j], DvarSet[j])); } //constraints for (i = 0; i < realistic_trip_num; i++) { INumExpr expr = masterModel.NumExpr(); for (j = 0; j < initialPath_num; j++) { expr = masterModel.Sum(expr, masterModel.Prod(A_Matrix[j][i], DvarSet[j]));//在从初始解传值给A_Matrix,已经针对网络复制作了处理 } Constraint[i] = masterModel.AddGe(expr, 1); } }
public static void Main(string[] args) { try { string filename = "../../../../examples/data/rates.dat"; if (args.Length > 0) { filename = args[0]; } ReadData(filename); Cplex cplex = new Cplex(); INumVar[] production = new INumVar[_generators]; for (int j = 0; j < _generators; ++j) { production[j] = cplex.SemiContVar(_minArray[j], _maxArray[j], NumVarType.Float); } cplex.AddMinimize(cplex.ScalProd(_cost, production)); cplex.AddGe(cplex.Sum(production), _demand); cplex.ExportModel("rates.lp"); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); for (int j = 0; j < _generators; ++j) { System.Console.WriteLine(" generator " + j + ": " + cplex.GetValue(production[j])); } System.Console.WriteLine("Total cost = " + cplex.ObjValue); } else { System.Console.WriteLine("No solution"); } 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/rates.dat"; if (args.Length > 0) filename = args[0]; ReadData(filename); Cplex cplex = new Cplex(); INumVar[] production = new INumVar[_generators]; for (int j = 0; j < _generators; ++j) { production[j] = cplex.SemiContVar(_minArray[j], _maxArray[j], NumVarType.Float); } cplex.AddMinimize(cplex.ScalProd(_cost, production)); cplex.AddGe(cplex.Sum(production), _demand); cplex.ExportModel("rates.lp"); if ( cplex.Solve() ) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); for (int j = 0; j < _generators; ++j) { System.Console.WriteLine(" generator " + j + ": " + cplex.GetValue(production[j])); } System.Console.WriteLine("Total cost = " + cplex.ObjValue); } else System.Console.WriteLine("No solution"); 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); } }
void AddRestricaoDemandaMinima(EntradaViewModel entrada) { entrada.Produtos.ForEach(produto => { foreach (var diaSemana in Enum.GetValues(typeof(DiaDaSemana))) { var produtoHR = produto.GetNomeVariavel((DiaDaSemana)diaSemana, false); var produtoHE = produto.GetNomeVariavel((DiaDaSemana)diaSemana, true); var demanda = produto.Demanda[(DiaDaSemana)diaSemana]; var equacao = _cplex.Prod( produto.GetTaxaUnidadeHora(), _variaveis[0][_varArray[produtoHR]], _variaveis[0][_varArray[produtoHE]] ); var restricao = _cplex.AddGe(equacao, demanda, $"RestricaoProducaoMinima_{produto.GetNomeLimpo()}_{diaSemana}"); _restricoesList.Add(restricao); } }); }
/// <summary> /// Capacity constraints for each cargo /// </summary> private void Capacity() { for (int i = 0; i < N; i++) { var cargo = _cargoList[i]; var ub = cargo.GetMaxCapacity(); _solver.AddLe(yR[i], ub); var lb = cargo.GetMinCapacity(); var constraint = _solver.LinearNumExpr(); constraint.AddTerm(yR[i], 1); constraint.AddTerm(yE[i], 1); constraint.AddTerm(m[i], 1); _solver.AddGe(constraint, lb); var excessCap = cargo.GetExcessCapacity(); _solver.AddLe(yE[i], excessCap); } }
private void decomp(int dim, int kts, int[][] dist, List <int> WorkList) { int[] lo = new int[dim]; int dk = dim * kts; for (int i = 0; i < dim; i++) { lo[i] = 1; } Cplex cplex = new Cplex(); NumVarType varType = NumVarType.Bool; INumVar[][] x = new INumVar[dim][]; for (int i = 0; i < dim; i++) { x[i] = cplex.NumVarArray(dk, 0, 1); } for (int i = 0; i < dim; i++) { for (int j = 0; j < dk; j++) { x[i][j] = cplex.BoolVar(); } } //**************************************** //Что тут происходит? for (int j = 0; j < dim; j++) { INumExpr xcolSum = cplex.NumExpr(); for (int k = 0; k < kts; k++) { for (int i = 0; i < dim; i++) { xcolSum = cplex.Sum(xcolSum, x[i][k * dim + j]); } } cplex.AddEq(lo[j], xcolSum); } varType = NumVarType.Float; INumVar[] u = new INumVar[dk]; for (int j = 0; j < dk; j++) { u[j] = cplex.NumVar(0, 100000); } for (int j = 1; j < dk; j++) { cplex.AddGe(u[j], 0); } for (int k = 0; k < kts; k++) { for (int i = 1; i < dim; i++) { for (int j = 1; j < dim; j++) { if (i != j) { if (kts == 1) { cplex.AddLe(cplex.Sum(cplex.Diff(u[k * dim + i], u[k * dim + j]), cplex.Prod(dim, x[i][k * dim + j])), dim - 1); } else { cplex.AddLe(cplex.Sum(cplex.Diff(u[k * dim + i], u[k * dim + j]), cplex.Prod(dim, x[i][k * dim + j])), dim); } } } } } for (int i = 0; i < dim; i++) { INumExpr xrowSum = cplex.NumExpr(); for (int j = 0; j < dk; j++) { xrowSum = cplex.Sum(xrowSum, x[i][j]); } cplex.AddEq(lo[i], xrowSum); } //Условия независимости кластеров if (kts > 1) { int[] a = new int[kts + 1]; for (int k = 1; k < kts; k++) { if (k > 1 && k < kts - 1) { continue; } int p; for (int i = 1; i <= k; i++) { a[i] = i; } p = k; while (p >= 1) { for (int m = 0; m < dim; m++) { INumExpr xcolrowSum = cplex.NumExpr(); for (int j = 1; j <= kts; j++) { bool row = false; for (int i = 1; i <= k; i++) { if (a[i] == j) { row = true; } } if (row) { for (int t = 0; t < dim; t++) { xcolrowSum = cplex.Sum(xcolrowSum, x[m][(j - 1) * dim + t]); } } else { for (int t = 0; t < dim; t++) { xcolrowSum = cplex.Sum(xcolrowSum, x[t][(j - 1) * dim + m]); } } } cplex.AddLe(xcolrowSum, lo[m]); } if (a[k] == kts) { p--; } else { p = k; } if (p >= 1) { for (int i = k; i >= p; i--) { a[i] = a[p] + i - p + 1; } } } } } INumExpr costSum = cplex.NumExpr(); INumExpr[] costSum1 = new INumExpr[kts]; if (kts == 1) { for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { costSum = cplex.Sum(costSum, cplex.Prod(x[i][j], dist[i][j])); } } cplex.AddMinimize(costSum); } else { for (int k = 0; k < kts; k++) { costSum1[k] = cplex.NumExpr(); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { costSum1[k] = cplex.Sum(costSum1[k], cplex.Prod(x[i][k * dim + j], dist[i][j])); } } //cplex.AddLe(costSum1[k], costSum); } costSum = cplex.Max(costSum1); cplex.AddMinimize(costSum); } try { if (cplex.Solve()) { textBox1.Text += "lambda = " + cplex.ObjValue + Environment.NewLine; textBox1.Text += DateTime.Now.ToString() + Environment.NewLine; WorkList.Clear(); int num_clust = 0; for (int k = 0; k < kts; k++) { int dim1 = 0; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { if (Convert.ToInt16(cplex.GetValue(x[i][k * dim + j])) == 1) { dim1++; } } } if (dim1 > 0) { num_clust++; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { if (Convert.ToInt16(cplex.GetValue(x[i][k * dim + j])) == 1) { WorkList.Add(i); break; } } } WorkList.Add(-1); } } textBox1.Text += DateTime.Now.ToString() + Environment.NewLine; } else { textBox1.Text += "Нет решения" + Environment.NewLine; textBox1.Text += DateTime.Now.ToString() + Environment.NewLine; } cplex.End(); } catch (ILOG.Concert.Exception ex) { textBox1.Text += "Concert Error: " + ex + Environment.NewLine; textBox1.Text += DateTime.Now.ToString() + Environment.NewLine; } }
public static void Main(string[] args) { int nMonths = cost.Length; int nProducts = cost[0].Length; try { Cplex cplex = new Cplex(); INumVar[] produce = cplex.NumVarArray(nMonths, 0, System.Double.MaxValue); INumVar[][] use = new INumVar[nMonths][]; INumVar[][] buy = new INumVar[nMonths][]; INumVar[][] store = new INumVar[nMonths][]; for (int i = 0; i < nMonths; i++) { use[i] = cplex.NumVarArray(nProducts, 0.0, System.Double.MaxValue); buy[i] = cplex.NumVarArray(nProducts, 0.0, System.Double.MaxValue); store[i] = cplex.NumVarArray(nProducts, 0.0, 1000.0); } for (int p = 0; p < nProducts; p++) { store[nMonths - 1][p].LB = 500.0; store[nMonths - 1][p].UB = 500.0; } INumExpr profit = cplex.NumExpr(); for (int i = 0; i < nMonths; i++) { // Not more than 200 tons of vegetable oil can be refined cplex.AddLe(cplex.Sum(use[i][v1], use[i][v2]), 200.0); // Not more than 250 tons of non-vegetable oil can be refined cplex.AddLe(cplex.Sum(use[i][o1], use[i][o2], use[i][o3]), 250.0); // Constraints on food composition cplex.AddLe(cplex.Prod(3.0, produce[i]), cplex.Sum(cplex.Prod(8.8, use[i][v1]), cplex.Prod(6.1, use[i][v2]), cplex.Prod(2.0, use[i][o1]), cplex.Prod(4.2, use[i][o2]), cplex.Prod(5.0, use[i][o3]))); cplex.AddGe(cplex.Prod(6.0, produce[i]), cplex.Sum(cplex.Prod(8.8, use[i][v1]), cplex.Prod(6.1, use[i][v2]), cplex.Prod(2.0, use[i][o1]), cplex.Prod(4.2, use[i][o2]), cplex.Prod(5.0, use[i][o3]))); cplex.AddEq(produce[i], cplex.Sum(use[i])); // Raw oil can be stored for later use if (i == 0) { for (int p = 0; p < nProducts; p++) { cplex.AddEq(cplex.Sum(500.0, buy[i][p]), cplex.Sum(use[i][p], store[i][p])); } } else { for (int p = 0; p < nProducts; p++) { cplex.AddEq(cplex.Sum(store[i - 1][p], buy[i][p]), cplex.Sum(use[i][p], store[i][p])); } } // Logical constraints: // The food cannot use more than 3 oils // (or at least two oils must not be used) cplex.AddGe(cplex.Sum(cplex.Eq(use[i][v1], 0), cplex.Eq(use[i][v2], 0), cplex.Eq(use[i][o1], 0), cplex.Eq(use[i][o2], 0), cplex.Eq(use[i][o3], 0)), 2); // When an oil is used, the quantity must be at least 20 tons for (int p = 0; p < nProducts; p++) { cplex.Add(cplex.Or(cplex.Eq(use[i][p], 0), cplex.Ge(use[i][p], 20))); } // If products v1 or v2 are used, then product o3 is also used cplex.Add(cplex.IfThen(cplex.Or(cplex.Ge(use[i][v1], 20), cplex.Ge(use[i][v2], 20)), cplex.Ge(use[i][o3], 20))); // Objective function profit = cplex.Sum(profit, cplex.Prod(150, produce[i])); profit = cplex.Diff(profit, cplex.ScalProd(cost[i], buy[i])); profit = cplex.Diff(profit, cplex.Prod(5, cplex.Sum(store[i]))); } cplex.AddMaximize(profit); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" Maximum profit = " + cplex.ObjValue); for (int i = 0; i < nMonths; i++) { System.Console.WriteLine(" Month {0}", i); System.Console.Write(" . buy "); for (int p = 0; p < nProducts; p++) { System.Console.Write("{0,8:F2} ", cplex.GetValue(buy[i][p])); } System.Console.WriteLine(); System.Console.Write(" . use "); for (int p = 0; p < nProducts; p++) { System.Console.Write("{0,8:F2} ", cplex.GetValue(use[i][p])); } System.Console.WriteLine(); System.Console.Write(" . store "); for (int p = 0; p < nProducts; p++) { System.Console.Write("{0,8:F2} ", cplex.GetValue(store[i][p])); } System.Console.WriteLine(); } } cplex.End(); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("Concert exception caught: " + e); } }
/// <summary> /// The example's main function. /// </summary> public static void Main(string[] args) { int retval = 0; Cplex cplex = null; try { cplex = new Cplex(); /* ***************************************************************** * * * * S E T U P P R O B L E M * * * * We create the following problem: * * Minimize * * obj: 3x1 - x2 + 3x3 + 2x4 + x5 + 2x6 + 4x7 * * Subject To * * c1: x1 + x2 = 4 * * c2: x1 + x3 >= 3 * * c3: x6 + x7 <= 5 * * c4: -x1 + x7 >= -2 * * q1: [ -x1^2 + x2^2 ] <= 0 * * q2: [ 4.25x3^2 -2x3*x4 + 4.25x4^2 - 2x4*x5 + 4x5^2 ] + 2 x1 <= 9.0 * q3: [ x6^2 - x7^2 ] >= 4 * * Bounds * * 0 <= x1 <= 3 * * x2 Free * * 0 <= x3 <= 0.5 * * x4 Free * * x5 Free * * x7 Free * * End * * * * ***************************************************************** */ INumVar[] x = new INumVar[7]; x[0] = cplex.NumVar(0, 3, "x1"); x[1] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x2"); x[2] = cplex.NumVar(0, 0.5, "x3"); x[3] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x4"); x[4] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x5"); x[5] = cplex.NumVar(0, System.Double.PositiveInfinity, "x6"); x[6] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x7"); IRange[] linear = new IRange[4]; linear[0] = cplex.AddEq(cplex.Sum(x[0], x[1]), 4.0, "c1"); linear[1] = cplex.AddGe(cplex.Sum(x[0], x[2]), 3.0, "c2"); linear[2] = cplex.AddLe(cplex.Sum(x[5], x[6]), 5.0, "c3"); linear[3] = cplex.AddGe(cplex.Diff(x[6], x[0]), -2.0, "c4"); IRange[] quad = new IRange[3]; quad[0] = cplex.AddLe(cplex.Sum(cplex.Prod(-1, x[0], x[0]), cplex.Prod(x[1], x[1])), 0.0, "q1"); quad[1] = cplex.AddLe(cplex.Sum(cplex.Prod(4.25, x[2], x[2]), cplex.Prod(-2,x[2],x[3]), cplex.Prod(4.25,x[3],x[3]), cplex.Prod(-2,x[3],x[4]), cplex.Prod(4,x[4],x[4]), cplex.Prod(2,x[0])), 9.0, "q2"); quad[2] = cplex.AddGe(cplex.Sum(cplex.Prod(x[5], x[5]), cplex.Prod(-1, x[6], x[6])), 4.0, "q3"); cplex.AddMinimize(cplex.Sum(cplex.Prod(3.0, x[0]), cplex.Prod(-1.0, x[1]), cplex.Prod(3.0, x[2]), cplex.Prod(2.0, x[3]), cplex.Prod(1.0, x[4]), cplex.Prod(2.0, x[5]), cplex.Prod(4.0, x[6])), "obj"); /* ***************************************************************** * * * * O P T I M I Z E P R O B L E M * * * * ***************************************************************** */ cplex.SetParam(Cplex.Param.Barrier.QCPConvergeTol, 1e-10); cplex.Solve(); /* ***************************************************************** * * * * Q U E R Y S O L U T I O N * * * * ***************************************************************** */ double[] xval = cplex.GetValues(x); double[] slack = cplex.GetSlacks(linear); double[] qslack = cplex.GetSlacks(quad); double[] cpi = cplex.GetReducedCosts(x); double[] rpi = cplex.GetDuals(linear); double[] qpi = getqconstrmultipliers(cplex, xval, ZEROTOL, x, quad); // Also store solution in a dictionary so that we can look up // values by variable and not only by index. IDictionary<INumVar, System.Double> xmap = new Dictionary<INumVar, System.Double>(); for (int j = 0; j < x.Length; ++j) { xmap.Add(x[j], xval[j]); } /* ***************************************************************** * * * * C H E C K K K T C O N D I T I O N S * * * * Here we verify that the optimal solution computed by CPLEX * * (and the qpi[] values computed above) satisfy the KKT * * conditions. * * * * ***************************************************************** */ // Primal feasibility: This example is about duals so we skip this test. // Dual feasibility: We must verify // - for <= constraints (linear or quadratic) the dual // multiplier is non-positive. // - for >= constraints (linear or quadratic) the dual // multiplier is non-negative. for (int i = 0; i < linear.Length; ++i) { if (linear[i].LB <= System.Double.NegativeInfinity) { // <= constraint if (rpi[i] > ZEROTOL) throw new System.SystemException("Dual feasibility test failed for row " + linear[i] + ": " + rpi[i]); } else if (linear[i].UB >= System.Double.PositiveInfinity) { // >= constraint if (rpi[i] < -ZEROTOL) throw new System.SystemException("Dual feasibility test failed for row " + linear[i] + ": " + rpi[i]); } else { // nothing to do for equality constraints } } for (int i = 0; i < quad.Length; ++i) { if (quad[i].LB <= System.Double.NegativeInfinity) { // <= constraint if (qpi[i] > ZEROTOL) throw new System.SystemException("Dual feasibility test failed for quad " + quad[i] + ": " + qpi[i]); } else if (quad[i].UB >= System.Double.PositiveInfinity) { // >= constraint if (qpi[i] < -ZEROTOL) throw new System.SystemException("Dual feasibility test failed for quad " + quad[i] + ": " + qpi[i]); } else { // nothing to do for equality constraints } } // Complementary slackness. // For any constraint the product of primal slack and dual multiplier // must be 0. for (int i = 0; i < linear.Length; ++i) { if (System.Math.Abs(linear[i].UB - linear[i].LB) > ZEROTOL && System.Math.Abs(slack[i] * rpi[i]) > ZEROTOL) throw new System.SystemException("Complementary slackness test failed for row " + linear[i] + ": " + System.Math.Abs(slack[i] * rpi[i])); } for (int i = 0; i < quad.Length; ++i) { if (System.Math.Abs(quad[i].UB - quad[i].LB) > ZEROTOL && System.Math.Abs(qslack[i] * qpi[i]) > ZEROTOL) throw new System.SystemException("Complementary slackness test failed for quad " + quad[i] + ": " + System.Math.Abs(qslack[i] * qpi[i])); } for (int j = 0; j < x.Length; ++j) { if (x[j].UB < System.Double.PositiveInfinity) { double slk = x[j].UB - xval[j]; double dual = cpi[j] < -ZEROTOL ? cpi[j] : 0.0; if (System.Math.Abs(slk * dual) > ZEROTOL) throw new System.SystemException("Complementary slackness test failed for column " + x[j] + ": " + System.Math.Abs(slk * dual)); } if (x[j].LB > System.Double.NegativeInfinity) { double slk = xval[j] - x[j].LB; double dual = cpi[j] > ZEROTOL ? cpi[j] : 0.0; if (System.Math.Abs(slk * dual) > ZEROTOL) throw new System.SystemException("Complementary slackness test failed for column " + x[j] + ": " + System.Math.Abs(slk * dual)); } } // Stationarity. // The difference between objective function and gradient at optimal // solution multiplied by dual multipliers must be 0, i.E., for the // optimal solution x // 0 == c // - sum(r in rows) r'(x)*rpi[r] // - sum(q in quads) q'(x)*qpi[q] // - sum(c in cols) b'(x)*cpi[c] // where r' and q' are the derivatives of a row or quadratic constraint, // x is the optimal solution and rpi[r] and qpi[q] are the dual // multipliers for row r and quadratic constraint q. // b' is the derivative of a bound constraint and cpi[c] the dual bound // multiplier for column c. IDictionary<INumVar, System.Double> kktsum = new Dictionary<INumVar, System.Double>(); for (int j = 0; j < x.Length; ++j) { kktsum.Add(x[j], 0.0); } // Objective function. for (ILinearNumExprEnumerator it = ((ILinearNumExpr)cplex.GetObjective().Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = it.Value; } // Linear constraints. // The derivative of a linear constraint ax - b (<)= 0 is just a. for (int i = 0; i < linear.Length; ++i) { for (ILinearNumExprEnumerator it = ((ILinearNumExpr)linear[i].Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = kktsum[it.NumVar] - rpi[i] * it.Value; } } // Quadratic constraints. // The derivative of a constraint xQx + ax - b <= 0 is // Qx + Q'x + a. for (int i = 0; i < quad.Length; ++i) { for (ILinearNumExprEnumerator it = ((ILinearNumExpr)quad[i].Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = kktsum[it.NumVar] - qpi[i] * it.Value; } for (IQuadNumExprEnumerator it = ((IQuadNumExpr)quad[i].Expr).GetQuadEnumerator(); it.MoveNext(); /* nothing */) { INumVar v1 = it.NumVar1; INumVar v2 = it.NumVar2; kktsum[v1] = kktsum[v1] - qpi[i] * xmap[v2] * it.Value; kktsum[v2] = kktsum[v2] - qpi[i] * xmap[v1] * it.Value; } } // Bounds. // The derivative for lower bounds is -1 and that for upper bounds // is 1. // CPLEX already returns dj with the appropriate sign so there is // no need to distinguish between different bound types here. for (int j = 0; j < x.Length; ++j) { kktsum[x[j]] = kktsum[x[j]] - cpi[j]; } foreach (INumVar v in x) { if (System.Math.Abs(kktsum[v]) > ZEROTOL) throw new System.SystemException("Stationarity test failed at " + v + ": " + System.Math.Abs(kktsum[v])); } // KKT conditions satisfied. Dump out the optimal solutions and // the dual values. System.Console.WriteLine("Optimal solution satisfies KKT conditions."); System.Console.WriteLine(" x[] = " + arrayToString(xval)); System.Console.WriteLine(" cpi[] = " + arrayToString(cpi)); System.Console.WriteLine(" rpi[] = " + arrayToString(rpi)); System.Console.WriteLine(" qpi[] = " + arrayToString(qpi)); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("IloException: " + e.Message); System.Console.WriteLine(e.StackTrace); retval = -1; } finally { if (cplex != null) cplex.End(); } System.Environment.Exit(retval); }
/// <summary>建立最初的RMP /// 依据初始解 /// </summary> /// <param name="IS"></param> public void Build_RMP(InitialSolution IS)//主问题的建模 { initialPath_num = IS.PathSet.Count; trip_num = TripList.Count; realistic_trip_num = NetWork.num_Physical_trip; DvarSet = new List <INumVar>(); //x CoefSet = new List <double>(); //cij AccumuWorkSet = new List <double>(); //每条交路累计工作时间 ObjCoefSet = new List <double>(); A_Matrix = new List <int[]>(); //aij PathSet = new List <Pairing>(); //列池 //int n = 196;//n代表的是整个高一车队每天所需要的乘务员和乘务长的总和 CoefSet = IS.Coefs;//IS初始解 AccumuWorkSet = IS.AccumuWorkSet; A_Matrix = IS.A_Matrix; PathSet = IS.PathSet; ObjCoefSet = IS.ObjCoefs; //for(int k = 0 ; k < IS.Coefs.Count ; k++) //{ // ObjCoefSet.Add(Network.GetObjCoef(IS.AccumuWorkSet[k] , IS.Coefs[k])); //} foreach (var p in PathSet) { ColumnPool.Add(p); } int i, j; masterModel = new Cplex(); Obj = masterModel.AddMinimize(); Constraint = new IRange[realistic_trip_num];//这种I打头的都是cplex里面的东西 /**按行建模**/ //vars and obj function for (j = 0; j < initialPath_num; j++) //定义决策变量和目标函数 { INumVar var = masterModel.NumVar(0, 1, NumVarType.Float); //INumVar-cplex里面的,定义决策变量。后面括号中的意思是定义var是0-1之间的浮点值 DvarSet.Add(var); Obj.Expr = masterModel.Sum(Obj.Expr, masterModel.Prod(CoefSet[j], DvarSet[j])); //后面的小括号里面是一个cij*xj,大括号里面的是累计,包括之前的expr } //constraints for (i = 0; i < realistic_trip_num; i++) //对每一行 这部分的内容是aij*xj>=n { INumExpr expr = masterModel.NumExpr(); for (j = 0; j < initialPath_num; j++) //对每一列 { expr = masterModel.Sum(expr, masterModel.Prod(A_Matrix[j][i], DvarSet[j])); //在从初始解传值给A_Matrix,已经针对网络复制作了处理 }//小括号路里aij*xj Constraint[i] = masterModel.AddGe(expr, NUMBER_CREW); //约束list addge表示返回一个大于等于n的数 } for (j = 0; j < initialPath_num; j++)//对每一列 { INumExpr expr = masterModel.NumExpr(); expr = masterModel.Sum(expr, DvarSet[j]);//在从初始解传值给A_Matrix,已经针对网络复制作了处理 } //这里怎样使约束expr的值等于1???????????????????????????????????????????????? }
public static void Main (string[] args) { int nMonths = cost.Length; int nProducts = cost[0].Length; try { Cplex cplex = new Cplex(); INumVar[] produce = cplex.NumVarArray(nMonths, 0, System.Double.MaxValue); INumVar[][] use = new INumVar[nMonths][]; INumVar[][] buy = new INumVar[nMonths][]; INumVar[][] store = new INumVar[nMonths][]; for (int i = 0; i < nMonths; i++) { use[i] = cplex.NumVarArray(nProducts, 0.0, System.Double.MaxValue); buy[i] = cplex.NumVarArray(nProducts, 0.0, System.Double.MaxValue); store[i] = cplex.NumVarArray(nProducts, 0.0, 1000.0); } for (int p = 0; p < nProducts; p++) { store[nMonths-1][p].LB = 500.0; store[nMonths-1][p].UB = 500.0; } INumExpr profit = cplex.NumExpr(); for (int i = 0; i < nMonths; i++) { // Not more than 200 tons of vegetable oil can be refined cplex.AddLe(cplex.Sum(use[i][v1], use[i][v2]), 200.0); // Not more than 250 tons of non-vegetable oil can be refined cplex.AddLe(cplex.Sum(use[i][o1], use[i][o2], use[i][o3]), 250.0); // Constraints on food composition cplex.AddLe(cplex.Prod(3.0,produce[i]), cplex.Sum(cplex.Prod(8.8, use[i][v1]), cplex.Prod(6.1, use[i][v2]), cplex.Prod(2.0, use[i][o1]), cplex.Prod(4.2, use[i][o2]), cplex.Prod(5.0, use[i][o3]))); cplex.AddGe(cplex.Prod(6.0, produce[i]), cplex.Sum(cplex.Prod(8.8, use[i][v1]), cplex.Prod(6.1, use[i][v2]), cplex.Prod(2.0, use[i][o1]), cplex.Prod(4.2, use[i][o2]), cplex.Prod(5.0, use[i][o3]))); cplex.AddEq(produce[i], cplex.Sum(use[i])); // Raw oil can be stored for later use if (i == 0) { for (int p = 0; p < nProducts; p++) cplex.AddEq(cplex.Sum(500.0, buy[i][p]), cplex.Sum(use[i][p], store[i][p])); } else { for (int p = 0; p < nProducts; p++) cplex.AddEq(cplex.Sum(store[i-1][p], buy[i][p]), cplex.Sum(use[i][p], store[i][p])); } // Logical constraints: // The food cannot use more than 3 oils // (or at least two oils must not be used) cplex.AddGe(cplex.Sum(cplex.Eq(use[i][v1], 0), cplex.Eq(use[i][v2], 0), cplex.Eq(use[i][o1], 0), cplex.Eq(use[i][o2], 0), cplex.Eq(use[i][o3], 0)), 2); // When an oil is used, the quantity must be at least 20 tons for (int p = 0; p < nProducts; p++) cplex.Add(cplex.Or(cplex.Eq(use[i][p], 0), cplex.Ge(use[i][p], 20))); // If products v1 or v2 are used, then product o3 is also used cplex.Add(cplex.IfThen(cplex.Or(cplex.Ge(use[i][v1], 20), cplex.Ge(use[i][v2], 20)), cplex.Ge(use[i][o3], 20))); // Objective function profit = cplex.Sum (profit, cplex.Prod(150, produce[i])); profit = cplex.Diff(profit, cplex.ScalProd(cost[i], buy[i])); profit = cplex.Diff(profit, cplex.Prod(5, cplex.Sum(store[i]))); } cplex.AddMaximize(profit); if ( cplex.Solve() ) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" Maximum profit = " + cplex.ObjValue); for (int i = 0; i < nMonths; i++) { System.Console.WriteLine(" Month {0}", i); System.Console.Write(" . buy "); for (int p = 0; p < nProducts; p++) System.Console.Write("{0,8:F2} ", cplex.GetValue(buy[i][p])); System.Console.WriteLine(); System.Console.Write(" . use "); for (int p = 0; p < nProducts; p++) System.Console.Write("{0,8:F2} ", cplex.GetValue(use[i][p])); System.Console.WriteLine(); System.Console.Write(" . store "); for (int p = 0; p < nProducts; p++) System.Console.Write("{0,8:F2} ", cplex.GetValue(store[i][p])); System.Console.WriteLine(); } } cplex.End(); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("Concert exception caught: " + e); } }
static void Main(string[] args) { double[] price = { 170.0, 170.0, 170.0 }; double[] priceStorage = { 10.0, 10.0, 10.0 }; double[] hardness = { 8.4, 6.2, 2.0 }; double[] hardness3 = { 3, 3, 3 }; double[] hardness6 = { 6, 6, 6 }; double[][] oilCost = new double[2][]; oilCost[0] = new double[3] { 1.159550009798596e+02, 1.018115866059220e+02, 1.128780935294160e+02 }; oilCost[1] = new double[3] { 100, 1.067537671189185e+02, 1.098041326934309e+02 }; //oilCost = GenerateRandomVector(); INumVar[][] oilStore = new INumVar[3][]; INumVar[][] oilBuy = new INumVar[2][]; INumVar[][] oilProduce = new INumVar[2][]; // [month][A-C] Cplex cplex = new Cplex(); for (int i = 0; i < 2; i++) // Initialize oilBuy and oilProduce { oilBuy[i] = new INumVar[3]; oilProduce[i] = new INumVar[3]; } for (int i = 0; i < 3; i++) // Initialize oilStore { oilStore[i] = new INumVar[3]; for (int j = 0; j < 3; j++) { oilStore[i][j] = cplex.NumVar(0, 800); // Ograniczenia na pojemność magazynu } } for (int i = 0; i < 2; i++) // Ograniczenia na miesiące { for (int j = 0; j < 3; j++) // Ograniczenia na możliwości rafinacji { if (j != 2) { oilProduce[i][j] = cplex.NumVar(0, 220); // Rafinacja roślinnego } else { oilProduce[i][j] = cplex.NumVar(0, 270); // Rafinacja nie-roślinnego } oilBuy[i][j] = cplex.NumVar(0, 1070); } cplex.AddRange(0, cplex.Sum(oilProduce[i][0], oilProduce[i][1]), 220); cplex.AddGe(cplex.ScalProd(hardness, oilProduce[i]), cplex.ScalProd(hardness3, oilProduce[i])); // Hardness greater than 3 cplex.AddLe(cplex.ScalProd(hardness, oilProduce[i]), cplex.ScalProd(hardness6, oilProduce[i])); // Hardness less than 6 } for (int i = 0; i < 3; i++) // Ograniczenia na oleje { cplex.AddEq(oilStore[0][i], 200.0); // Ograniczenie na stan magazynu w grudniu cplex.AddEq(oilStore[2][i], 200.0); // Ograniczenie na stan magazynu w lutym cplex.AddEq(oilStore[1][i], cplex.Sum(cplex.Diff(oilBuy[0][i], oilProduce[0][i]), oilStore[0][i])); // (Kupowane + zmagazynowane - produkowane) w tym miesiacu = zmagazynowane w nastepnym miesiacu cplex.AddEq(oilStore[2][i], cplex.Sum(cplex.Diff(oilBuy[1][i], oilProduce[1][i]), oilStore[1][i])); } // Funkcja Celu: zyski ze sprzedaży - koszta magazynowania - koszta kupowania materiału do produkcji cplex.AddMaximize( cplex.Diff( cplex.Diff( cplex.Sum( cplex.ScalProd(price, oilProduce[0]), cplex.ScalProd(price, oilProduce[1])), cplex.Sum( cplex.ScalProd(priceStorage, oilStore[1]), cplex.ScalProd(priceStorage, oilStore[2]))), cplex.Sum( cplex.ScalProd(oilCost[0], oilBuy[0]), cplex.ScalProd(oilCost[1], oilBuy[1])))); if (cplex.Solve()) { System.Console.WriteLine(); System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(); System.Console.WriteLine(" = " + cplex.ObjValue); Console.WriteLine(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { Console.WriteLine(" oilCost[" + i + "][" + j + "] = " + oilCost[i][j]); } } Console.WriteLine(); for (int j = 0; j < 2; j++) { double hardnessTotal = 0; double sum = 0; for (int i = 0; i < 3; i++) { System.Console.WriteLine(" oilProduce[" + j + "][" + i + "] = " + cplex.GetValue(oilProduce[j][i])); hardnessTotal += cplex.GetValue(oilProduce[j][i]) * hardness[i]; sum += cplex.GetValue(oilProduce[j][i]); } System.Console.WriteLine(" hardnessTotal[" + j + "] = " + hardnessTotal / sum); Console.WriteLine(); } for (int j = 0; j < 2; j++) { for (int i = 0; i < 3; i++) { System.Console.WriteLine(" oilBuy[" + j + "][" + i + "] = " + cplex.GetValue(oilBuy[j][i])); } } Console.WriteLine(); for (int j = 0; j < 3; j++) { for (int i = 0; i < 3; i++) { System.Console.WriteLine(" oilStore[" + j + "][" + i + "] = " + cplex.GetValue(oilStore[j][i])); } } System.Console.WriteLine(); } Console.ReadKey(); }
/// <summary> /// The example's main function. /// </summary> public static void Main(string[] args) { int retval = 0; Cplex cplex = null; try { cplex = new Cplex(); /* ***************************************************************** * * * * S E T U P P R O B L E M * * * * We create the following problem: * * Minimize * * obj: 3x1 - x2 + 3x3 + 2x4 + x5 + 2x6 + 4x7 * * Subject To * * c1: x1 + x2 = 4 * * c2: x1 + x3 >= 3 * * c3: x6 + x7 <= 5 * * c4: -x1 + x7 >= -2 * * q1: [ -x1^2 + x2^2 ] <= 0 * * q2: [ 4.25x3^2 -2x3*x4 + 4.25x4^2 - 2x4*x5 + 4x5^2 ] + 2 x1 <= 9.0 * q3: [ x6^2 - x7^2 ] >= 4 * * Bounds * * 0 <= x1 <= 3 * * x2 Free * * 0 <= x3 <= 0.5 * * x4 Free * * x5 Free * * x7 Free * * End * * * * ***************************************************************** */ INumVar[] x = new INumVar[7]; x[0] = cplex.NumVar(0, 3, "x1"); x[1] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x2"); x[2] = cplex.NumVar(0, 0.5, "x3"); x[3] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x4"); x[4] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x5"); x[5] = cplex.NumVar(0, System.Double.PositiveInfinity, "x6"); x[6] = cplex.NumVar(System.Double.NegativeInfinity, System.Double.PositiveInfinity, "x7"); IRange[] linear = new IRange[4]; linear[0] = cplex.AddEq(cplex.Sum(x[0], x[1]), 4.0, "c1"); linear[1] = cplex.AddGe(cplex.Sum(x[0], x[2]), 3.0, "c2"); linear[2] = cplex.AddLe(cplex.Sum(x[5], x[6]), 5.0, "c3"); linear[3] = cplex.AddGe(cplex.Diff(x[6], x[0]), -2.0, "c4"); IRange[] quad = new IRange[3]; quad[0] = cplex.AddLe(cplex.Sum(cplex.Prod(-1, x[0], x[0]), cplex.Prod(x[1], x[1])), 0.0, "q1"); quad[1] = cplex.AddLe(cplex.Sum(cplex.Prod(4.25, x[2], x[2]), cplex.Prod(-2, x[2], x[3]), cplex.Prod(4.25, x[3], x[3]), cplex.Prod(-2, x[3], x[4]), cplex.Prod(4, x[4], x[4]), cplex.Prod(2, x[0])), 9.0, "q2"); quad[2] = cplex.AddGe(cplex.Sum(cplex.Prod(x[5], x[5]), cplex.Prod(-1, x[6], x[6])), 4.0, "q3"); cplex.AddMinimize(cplex.Sum(cplex.Prod(3.0, x[0]), cplex.Prod(-1.0, x[1]), cplex.Prod(3.0, x[2]), cplex.Prod(2.0, x[3]), cplex.Prod(1.0, x[4]), cplex.Prod(2.0, x[5]), cplex.Prod(4.0, x[6])), "obj"); /* ***************************************************************** * * * * O P T I M I Z E P R O B L E M * * * * ***************************************************************** */ cplex.SetParam(Cplex.Param.Barrier.QCPConvergeTol, 1e-10); cplex.Solve(); /* ***************************************************************** * * * * Q U E R Y S O L U T I O N * * * * ***************************************************************** */ double[] xval = cplex.GetValues(x); double[] slack = cplex.GetSlacks(linear); double[] qslack = cplex.GetSlacks(quad); double[] cpi = cplex.GetReducedCosts(x); double[] rpi = cplex.GetDuals(linear); double[] qpi = getqconstrmultipliers(cplex, xval, ZEROTOL, x, quad); // Also store solution in a dictionary so that we can look up // values by variable and not only by index. IDictionary <INumVar, System.Double> xmap = new Dictionary <INumVar, System.Double>(); for (int j = 0; j < x.Length; ++j) { xmap.Add(x[j], xval[j]); } /* ***************************************************************** * * * * C H E C K K K T C O N D I T I O N S * * * * Here we verify that the optimal solution computed by CPLEX * * (and the qpi[] values computed above) satisfy the KKT * * conditions. * * * * ***************************************************************** */ // Primal feasibility: This example is about duals so we skip this test. // Dual feasibility: We must verify // - for <= constraints (linear or quadratic) the dual // multiplier is non-positive. // - for >= constraints (linear or quadratic) the dual // multiplier is non-negative. for (int i = 0; i < linear.Length; ++i) { if (linear[i].LB <= System.Double.NegativeInfinity) { // <= constraint if (rpi[i] > ZEROTOL) { throw new System.SystemException("Dual feasibility test failed for row " + linear[i] + ": " + rpi[i]); } } else if (linear[i].UB >= System.Double.PositiveInfinity) { // >= constraint if (rpi[i] < -ZEROTOL) { throw new System.SystemException("Dual feasibility test failed for row " + linear[i] + ": " + rpi[i]); } } else { // nothing to do for equality constraints } } for (int i = 0; i < quad.Length; ++i) { if (quad[i].LB <= System.Double.NegativeInfinity) { // <= constraint if (qpi[i] > ZEROTOL) { throw new System.SystemException("Dual feasibility test failed for quad " + quad[i] + ": " + qpi[i]); } } else if (quad[i].UB >= System.Double.PositiveInfinity) { // >= constraint if (qpi[i] < -ZEROTOL) { throw new System.SystemException("Dual feasibility test failed for quad " + quad[i] + ": " + qpi[i]); } } else { // nothing to do for equality constraints } } // Complementary slackness. // For any constraint the product of primal slack and dual multiplier // must be 0. for (int i = 0; i < linear.Length; ++i) { if (System.Math.Abs(linear[i].UB - linear[i].LB) > ZEROTOL && System.Math.Abs(slack[i] * rpi[i]) > ZEROTOL) { throw new System.SystemException("Complementary slackness test failed for row " + linear[i] + ": " + System.Math.Abs(slack[i] * rpi[i])); } } for (int i = 0; i < quad.Length; ++i) { if (System.Math.Abs(quad[i].UB - quad[i].LB) > ZEROTOL && System.Math.Abs(qslack[i] * qpi[i]) > ZEROTOL) { throw new System.SystemException("Complementary slackness test failed for quad " + quad[i] + ": " + System.Math.Abs(qslack[i] * qpi[i])); } } for (int j = 0; j < x.Length; ++j) { if (x[j].UB < System.Double.PositiveInfinity) { double slk = x[j].UB - xval[j]; double dual = cpi[j] < -ZEROTOL ? cpi[j] : 0.0; if (System.Math.Abs(slk * dual) > ZEROTOL) { throw new System.SystemException("Complementary slackness test failed for column " + x[j] + ": " + System.Math.Abs(slk * dual)); } } if (x[j].LB > System.Double.NegativeInfinity) { double slk = xval[j] - x[j].LB; double dual = cpi[j] > ZEROTOL ? cpi[j] : 0.0; if (System.Math.Abs(slk * dual) > ZEROTOL) { throw new System.SystemException("Complementary slackness test failed for column " + x[j] + ": " + System.Math.Abs(slk * dual)); } } } // Stationarity. // The difference between objective function and gradient at optimal // solution multiplied by dual multipliers must be 0, i.E., for the // optimal solution x // 0 == c // - sum(r in rows) r'(x)*rpi[r] // - sum(q in quads) q'(x)*qpi[q] // - sum(c in cols) b'(x)*cpi[c] // where r' and q' are the derivatives of a row or quadratic constraint, // x is the optimal solution and rpi[r] and qpi[q] are the dual // multipliers for row r and quadratic constraint q. // b' is the derivative of a bound constraint and cpi[c] the dual bound // multiplier for column c. IDictionary <INumVar, System.Double> kktsum = new Dictionary <INumVar, System.Double>(); for (int j = 0; j < x.Length; ++j) { kktsum.Add(x[j], 0.0); } // Objective function. for (ILinearNumExprEnumerator it = ((ILinearNumExpr)cplex.GetObjective().Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = it.Value; } // Linear constraints. // The derivative of a linear constraint ax - b (<)= 0 is just a. for (int i = 0; i < linear.Length; ++i) { for (ILinearNumExprEnumerator it = ((ILinearNumExpr)linear[i].Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = kktsum[it.NumVar] - rpi[i] * it.Value; } } // Quadratic constraints. // The derivative of a constraint xQx + ax - b <= 0 is // Qx + Q'x + a. for (int i = 0; i < quad.Length; ++i) { for (ILinearNumExprEnumerator it = ((ILinearNumExpr)quad[i].Expr).GetLinearEnumerator(); it.MoveNext(); /* nothing */) { kktsum[it.NumVar] = kktsum[it.NumVar] - qpi[i] * it.Value; } for (IQuadNumExprEnumerator it = ((IQuadNumExpr)quad[i].Expr).GetQuadEnumerator(); it.MoveNext(); /* nothing */) { INumVar v1 = it.NumVar1; INumVar v2 = it.NumVar2; kktsum[v1] = kktsum[v1] - qpi[i] * xmap[v2] * it.Value; kktsum[v2] = kktsum[v2] - qpi[i] * xmap[v1] * it.Value; } } // Bounds. // The derivative for lower bounds is -1 and that for upper bounds // is 1. // CPLEX already returns dj with the appropriate sign so there is // no need to distinguish between different bound types here. for (int j = 0; j < x.Length; ++j) { kktsum[x[j]] = kktsum[x[j]] - cpi[j]; } foreach (INumVar v in x) { if (System.Math.Abs(kktsum[v]) > ZEROTOL) { throw new System.SystemException("Stationarity test failed at " + v + ": " + System.Math.Abs(kktsum[v])); } } // KKT conditions satisfied. Dump out the optimal solutions and // the dual values. System.Console.WriteLine("Optimal solution satisfies KKT conditions."); System.Console.WriteLine(" x[] = " + arrayToString(xval)); System.Console.WriteLine(" cpi[] = " + arrayToString(cpi)); System.Console.WriteLine(" rpi[] = " + arrayToString(rpi)); System.Console.WriteLine(" qpi[] = " + arrayToString(qpi)); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("IloException: " + e.Message); System.Console.WriteLine(e.StackTrace); retval = -1; } finally { if (cplex != null) { cplex.End(); } } System.Environment.Exit(retval); }
void solve() { Cplex Model = new Cplex(); // decision variables #region //x1-tjs (first stage t = 1),length of a collection period (in days) at collection point j during time period t //INumVar[][][] X1 = new INumVar[period][][]; //for (int i = 0; i < period; i++) //{ // X1[i] = new INumVar[cpoint][]; // for (int ii = 0; ii < cpoint; ii++) // { // X1[i][ii] = new INumVar[scenario]; // X1[i][ii] = Model.NumVarArray(scenario, 1, 7, NumVarType.Int); // } //} //x2-tpjks ,volume of products returned from collection point j to recycling center k during time period t INumVar[][][][][] X2 = new INumVar[period][][][][]; for (int a = 0; a < period; a++) { X2[a] = new INumVar[ptype][][][]; for (int aa = 0; aa < ptype; aa++) { X2[a][aa] = new INumVar[cpoint][][]; for (int bb = 0; bb < cpoint; bb++) { X2[a][aa][bb] = new INumVar[rcenter][]; for (int cc = 0; cc < rcenter; cc++) { X2[a][aa][bb][cc] = new INumVar[scenario]; X2[a][aa][bb][cc] = Model.NumVarArray(scenario, 0, System.Double.MaxValue, NumVarType.Int); } } } } //x3-tij ,Binary decision variable equals ‘1’ if customer i is allocated to collection point j during time period t and ‘0’ otherwise INumVar[][][] X3 = new INumVar[period][][]; for (int aa = 0; aa < period; aa++) { X3[aa] = new INumVar[customer][]; for (int bb = 0; bb < customer; bb++) { X3[aa][bb] = new INumVar[cpoint]; X3[aa][bb] = Model.NumVarArray(cpoint, 0.0, 1.0, NumVarType.Bool); } } //x4-tj ,Binary decision variable equals ‘1’ if collection point j is rented during time period t and ‘0’ otherwise INumVar[][] X4 = new INumVar[period][]; for (int i = 0; i < period; i++) { X4[i] = new INumVar[cpoint]; X4[i] = Model.NumVarArray(cpoint, 0.0, 1.0, NumVarType.Bool); } //x5-k ,Binary decision variable equals ‘1’ if recycling center k is established and ‘0’ otherwise INumVar[] X5 = new INumVar[rcenter]; X5 = Model.NumVarArray(rcenter, 0, 1, NumVarType.Bool); //x6 maximum capacity level option for recycling center k INumVar[] X6 = new INumVar[rcenter]; X6 = Model.NumVarArray(rcenter, 1, 3, NumVarType.Int); //X7-tjs Auxiliary variable x7 the frequency of recylce during a period //INumVar[][][] X7 = new INumVar[period][][]; //for (int i = 0; i < period; i++) //{ // X7[i] = new INumVar[cpoint][]; // for (int ii = 0; ii < cpoint; ii++) // { // X7[i][ii] = new INumVar[scenario]; // X7[i][ii] = Model.NumVarArray(scenario, 30, wday, NumVarType.Int); // } //} #endregion Double M = 100000; // constraints #region // formulation (4) INumExpr[] expr1 = new INumExpr[1]; for (int aa = 0; aa < period; aa++) { for (int bb = 0; bb < customer; bb++) { expr1[0] = X3[0][0][0]; for (int cc = 0; cc < cpoint; cc++) { expr1[0] = Model.Sum(expr1[0], X3[aa][bb][cc]); } expr1[0] = Model.Sum(expr1[0], Model.Prod(-1.0, X3[0][0][0])); Model.AddEq(expr1[0], 1); } } // formulation (5) INumExpr[] expr2 = new INumExpr[1]; INumExpr[] expr3 = new INumExpr[1]; for (int aa = 0; aa < period; aa++) { for (int bb = 0; bb < cpoint; bb++) { expr2[0] = X3[0][0][0]; expr3[0] = X4[0][0]; for (int cc = 0; cc < customer; cc++) { Model.Sum(expr2[0], X3[aa][cc][bb]); } expr2[0] = Model.Sum(expr2[0], Model.Prod(-1.0, X3[0][0][0])); expr3[0] = Model.Prod(M, X4[aa][bb]); expr3[0] = Model.Sum(expr3[0], Model.Prod(-1.0, X4[0][0])); Model.AddLe(expr2[0], expr3[0]); } } // formulation (6) INumExpr[] expr4 = new INumExpr[1]; INumExpr[] expr5 = new INumExpr[1]; INumExpr[] expr6 = new INumExpr[1]; for (int aa = 0; aa < period; aa++) { for (int cc = 0; cc < scenario; cc++) { for (int bb = 0; bb < cpoint; bb++) { expr5[0] = X3[0][0][0]; for (int dd = 0; dd < customer; dd++) { for (int ee = 0; ee < ptype; ee++) { expr5[0] = Model.Sum(expr5[0], Model.Prod(Model.Prod(r[dd, ee, aa, cc], X3[aa][dd][bb]), vlength)); } } expr5[0] = Model.Sum(expr5[0], Model.Prod(-1.0, X3[0][0][0])); expr6[0] = X2[0][0][0][0][0]; for (int ff = 0; ff < rcenter; ff++) { for (int ee = 0; ee < ptype; ee++) { expr6[0] = Model.Sum(expr6[0], X2[aa][ee][bb][ff][cc]); } } expr6[0] = Model.Sum(expr6[0], Model.Prod(-1.0, X2[0][0][0][0][0])); Model.AddEq(expr5[0], expr6[0]); } } } // formulation (7-1) INumExpr[] expr7 = new INumExpr[1]; for (int aa = 0; aa < period; aa++) { for (int bb = 0; bb < rcenter; bb++) { for (int cc = 0; cc < scenario; cc++) { for (int dd = 0; dd < cpoint; dd++) { expr7[0] = X2[0][0][0][0][0]; for (int ee = 0; ee < ptype; ee++) { expr7[0] = Model.Sum(expr7[0], X2[aa][ee][dd][bb][cc]); } expr7[0] = Model.Sum(expr7[0], Model.Prod(-1.0, X2[0][0][0][0][0])); Model.AddLe(expr7[0], Model.Prod(X5[bb], M)); } } } } // formulation (7-2) INumExpr[] expr71 = new INumExpr[1]; for (int aa = 0; aa < period; aa++) { for (int bb = 0; bb < rcenter; bb++) { for (int cc = 0; cc < scenario; cc++) { for (int dd = 0; dd < cpoint; dd++) { expr71[0] = X2[0][0][0][0][0]; for (int ee = 0; ee < ptype; ee++) { expr71[0] = Model.Sum(expr71[0], X2[aa][ee][dd][bb][cc]); } expr71[0] = Model.Sum(expr71[0], Model.Prod(-1.0, X2[0][0][0][0][0])); Model.AddLe(expr71[0], Model.Sum(Model.Prod(X6[bb], 1000), Model.Prod(Model.Sum(1, Model.Prod(X5[bb], -1)), M))); } } } } // formulation (8) INumExpr[] expr8 = new INumExpr[1]; for (int a = 0; a < period; a++) { expr8[0] = X4[0][0]; for (int b = 0; b < cpoint; b++) { expr8[0] = Model.Sum(expr8[0], X4[a][b]); } expr8[0] = Model.Sum(expr8[0], Model.Prod(-1.0, X4[0][0])); Model.AddGe(expr8[0], 1); } // formulation (9) INumExpr[] expr9 = new INumExpr[1]; expr9[0] = X5[0]; for (int a = 0; a < rcenter; a++) { expr9[0] = Model.Sum(expr9[0], X5[a]); } expr9[0] = Model.Sum(expr9[0], Model.Prod(-1.0, X5[0])); Model.AddGe(expr9[0], 1); // formulation (10) INumExpr[] expr10 = new INumExpr[1]; for (int a = 0; a < period; a++) { for (int b = 0; b < rcenter; b++) { for (int c = 0; c < scenario; c++) { for (int d = 0; d < cpoint; d++) { expr10[0] = X2[0][0][0][0][0]; for (int e = 0; e < ptype; e++) { expr10[0] = Model.Sum(expr10[0], X2[a][e][d][b][c]); } expr10[0] = Model.Sum(expr10[0], Model.Prod(-1.0, X2[0][0][0][0][0])); Model.AddGe(expr10[0], X5[b]); } } } } // formulation (11) for (int a = 0; a < period; a++) { for (int c = 0; c < customer; c++) { for (int b = 0; b < cpoint; b++) { Model.AddLe(Model.Prod(d1[c, b], X3[a][c][b]), l); } } } // formulation (12) for (int a = 0; a < period; a++) { for (int aa = 0; aa < ptype; aa++) { for (int b = 0; b < cpoint; b++) { for (int c = 0; c < rcenter; c++) { for (int d = 0; d < scenario; d++) { Model.AddGe(X2[a][aa][b][c][d], 0); } } } } } // #endregion //formulation (15) //formulation (1) objective function -1 // collection points rent cost INumExpr[] expr11 = new INumExpr[1]; for (int a = 0; a < period; a++) { expr11[0] = X4[0][0]; for (int b = 0; b < cpoint; b++) { expr11[0] = Model.Sum(expr11[0], Model.Prod(X4[a][b], e1[b])); } expr11[0] = Model.Sum(expr11[0], Model.Prod(-1.0, X4[0][0])); } INumExpr[] expr12 = new INumExpr[1]; INumExpr[] expr121 = new INumExpr[1]; for (int a = 0; a < period; a++) { for (int b = 0; b < rcenter; b++) { expr121[0] = X5[0]; for (int c = 0; c < cpoint; c++) { for (int d = 0; d < ptype; d++) { for (int e = 0; e < customer; e++) { expr12[0] = X2[0][0][0][0][0]; for (int f = 0; f < scenario; f++) { expr12[0] = Model.Sum(expr12[0], Model.Prod(Model.Prod(X2[a][d][c][b][f], e2[d, c, b]), wday / vlength)); } expr12[0] = Model.Sum(expr12[0], Model.Prod(-1.0, X2[0][0][0][0][0])); } } } expr121[0] = Model.Sum(expr121[0], Model.Prod(expr12[0], X5[b])); } } INumExpr[] expr13 = new INumExpr[1]; for (int a = 0; a < period; a++) { for (int b = 0; b < rcenter; b++) { expr13[0] = X5[0]; for (int bb = 0; bb < elevel; bb++) { expr13[0] = Model.Sum(expr13[0], Model.Prod(X5[b], e3[b, bb])); } expr13[0] = Model.Sum(expr13[0], Model.Prod(-1.0, X5[0])); } } Model.AddLe(Model.Prod(wday, Model.Sum(expr11[0], expr13[0])), e); //expr12[0], ,) // #endregion // //formulation (1) objective function -1 // #region INumExpr[] expr15 = new INumExpr[1]; expr15[0] = X4[0][0]; for (int i = 0; i < period; i++) { for (int ii = 0; ii < cpoint; ii++) { expr15[0] = Model.Sum(expr15[0], Model.Prod(a[ii], X4[i][ii])); } } expr15[0] = Model.Sum(expr15[0], Model.Prod(-1.0, X4[0][0])); // ok INumExpr[] expr17 = new INumExpr[1]; for (int a = 0; a < period; a++) { for (int aaa = 0; aaa < scenario; aaa++) { for (int bb = 0; bb < cpoint; bb++) { for (int bbb = 0; bbb < customer; bbb++) { expr17[0] = X3[0][0][0]; for (int aa = 0; aa < ptype; aa++) { expr17[0] = Model.Sum(expr17[0], Model.Prod(Model.Prod(r[bbb, aa, a, aaa] * b[aa], X3[a][bbb][bb]), (vlength + 1) * 0.5)); } expr17[0] = Model.Sum(expr17[0], Model.Prod(-1.0, X3[0][0][0])); } } } } INumExpr[] expr18 = new INumExpr[1]; INumExpr[] expr41 = new INumExpr[1]; expr18[0] = X5[0]; for (int a = 0; a < period; a++) { for (int aa = 0; aa < rcenter; aa++) { for (int bb = 0; bb < cpoint; bb++) { for (int b = 0; b < ptype; b++) { for (int aaa = 0; aaa < customer; aaa++) { expr41[0] = X2[0][0][0][0][0]; for (int bbb = 0; bbb < scenario; bbb++) { expr41[0] = Model.Sum(expr41[0], Model.Prod(Model.Prod(X2[a][b][bb][aa][bbb], z[bb, aa, b]), vlength)); } expr41[0] = Model.Sum(expr17[0], Model.Prod(-1.0, X2[0][0][0][0][0])); } } } expr18[0] = Model.Prod(expr41[0], X5[aa]); } } expr18[0] = Model.Sum(expr18[0], Model.Prod(-1.0, X5[0])); INumExpr[] expr19 = new INumExpr[1]; for (int i = 0; i < period; i++) { for (int ii = 0; ii < rcenter; ii++) { for (int iii = 0; iii < elevel; iii++) { expr19[0] = X5[0]; for (int iiii = 0; iiii < capacity; iiii++) { expr19[0] = Model.Sum(expr19[0], Model.Prod(q[ii, iii, iiii], X5[ii])); } } } } expr19[0] = Model.Sum(expr19[0], Model.Prod(-1.0, X5[0])); #endregion INumExpr[] expr21 = new INumExpr[1]; expr21[0] = Model.Prod(Model.Sum(expr15[0], Model.Prod(expr17[0], wday), expr18[0], expr19[0]), lambda); // INumExpr[] expr22 = new INumExpr[1]; expr22[0] = Model.Prod(Model.Sum(expr11[0], expr12[0], expr13[0]), delta); // Model.Prod(Model.Prod(wday, Model.Sum(expr11[0], expr12[0], expr13[0])),delta); Model.AddMinimize(Model.Sum(expr21[0], expr22[0])); // Model.ExportModel("RLND.LP"); if (Model.Solve()) { Console.WriteLine("statue=" + Model.GetStatus()); Console.WriteLine("obj=" + Model.ObjValue); Console.WriteLine("X2的结果"); for (int aa2 = 0; aa2 < period; aa2++) { for (int bb2 = 0; bb2 < ptype; bb2++) { for (int cc = 0; cc < cpoint; cc++) { for (int dd = 0; dd < rcenter; dd++) { for (int ee = 0; ee < scenario; ee++) { Console.WriteLine(Model.GetValue(X2[aa2][bb2][cc][dd][ee])); Console.WriteLine(); } } } } } //for (int a = 0; a < X6.Length; a++) //{ // Console.WriteLine("result[" + a + "] = " + Model.GetValue(X6[a])); //} //Console.WriteLine(); Model.End(); } else { Model.End(); Console.WriteLine(); Console.WriteLine("cannot be solved"); } }
/// <summary> /// return a list of words that can be played, left over letters are the last word /// </summary> /// <param name="chips">All of the chips to conisder, first ones are on the board</param> /// <param name="numberOnBoard">The number of leading chips are on the board already</param> /// <returns></returns> public static List <Chip[]> Solve(List <Chip> chips, int numberOnBoard, bool suppress = true) { if (chips == null || chips.Count == 0) { Utility.Warning("Chips is null or empty!"); return(null); } int chip_count = chips.Count; int word_count = chip_count / 3 + 1; Cplex model = new Cplex(); IIntVar[] X = model.BoolVarArray(chip_count); // should we place the ith chip IIntVar[][] Y = new IIntVar[chip_count][]; // which word do we place the ith chip on IIntVar[] WO = model.BoolVarArray(word_count); // flag for if the jth word is an order word or not IIntVar[] WC = model.BoolVarArray(word_count); // flag for if the jth word is a color word or not IIntVar[] WN = model.BoolVarArray(word_count); // flag for if the jth word is not used or is used IIntVar[][] UO = new IIntVar[word_count][]; // what is the number associated with this word (used only if a color word) IIntVar[][] UC = new IIntVar[word_count][]; // what is the color associated with this word (used only if a order word) IIntVar[][] PC = new IIntVar[word_count][]; // if i maps to word j and j is a color word, this will be 1 at [j][i] IIntVar[][] PO = new IIntVar[word_count][]; // if i maps to word j and j is a order word, this will be 1 at [j][i] (if and only if) // Initialize for (int i = 0; i < chip_count; i++) { Y[i] = model.BoolVarArray(word_count); } for (int i = 0; i < word_count; i++) { UC[i] = model.BoolVarArray(Chip.COLORCOUNT); } for (int i = 0; i < word_count; i++) { UO[i] = model.BoolVarArray(Chip.NUMBERCOUNT); } for (int i = 0; i < word_count; i++) { PC[i] = model.BoolVarArray(chip_count); } for (int i = 0; i < word_count; i++) { PO[i] = model.BoolVarArray(chip_count); } // for each word which chips map to it IIntVar[][] Yt = new IIntVar[word_count][]; for (int i = 0; i < word_count; i++) { Yt[i] = new IIntVar[chip_count]; for (int j = 0; j < chip_count; j++) { Yt[i][j] = Y[j][i]; } } // maximize the number of placed chips model.AddMaximize(model.Sum(X)); // if we place i, we need to map it to some word for (int i = 0; i < chip_count; i++) { model.AddLe(X[i], model.Sum(Y[i])); } // we can map to at most 1 value for (int i = 0; i < chip_count; i++) { model.AddLe(model.Sum(Y[i]), 1); } // if any chip maps to word j, turn the not used flag off for (int j = 0; j < word_count; j++) { for (int i = 0; i < chip_count; i++) { model.AddLe(Y[i][j], model.Diff(1, WN[j])); } } // if a word is used, make sure it has at least 3 chips for (int j = 0; j < word_count; j++) { model.AddLe(model.Prod(3, model.Diff(1, WN[j])), model.Sum(Yt[j])); } // first 'numberOnBoard' chips are on the board and thus must be placed for (int i = 0; i < numberOnBoard; i++) { model.AddEq(X[i], 1); } // each word is either an order word or a color word for (int i = 0; i < word_count; i++) { model.AddEq(model.Sum(WO[i], WC[i], WN[i]), 1); } // if i maps to word j and j is a color word make sure PC[j][i] is 1 for (int j = 0; j < word_count; j++) { for (int i = 0; i < chip_count; i++) { model.AddGe(model.Sum(1, PC[j][i]), model.Sum(WC[j], Y[i][j])); } } // if i maps to word j and j is a order word, PO will be 1 at [j][i] (if and only if) for (int j = 0; j < word_count; j++) { for (int i = 0; i < chip_count; i++) { model.AddGe(model.Sum(1, PO[j][i]), model.Sum(WO[j], Y[i][j])); model.AddLe(PO[j][i], WO[j]); model.AddLe(PO[j][i], Y[i][j]); } } // ************************************************ // ************ TYPE CONSTRAINTS ****************** // ************************************************ for (int i = 0; i < chip_count; i++) { for (int j = 0; j < word_count; j++) { // if this is a color word and a chip maps to it then the numbers of each chip on this word must match for (int k = 0; k < Chip.NUMBERCOUNT; k++) { var bnd = model.Sum(WO[j], model.Diff(1, Y[i][j])); model.AddLe(model.Diff(UO[j][k], chips[i].number[k] ? 1 : 0), bnd); model.AddLe(model.Diff(chips[i].number[k] ? 1 : 0, UO[j][k]), bnd); } // if this is a order word and a chip maps to it then the colors of each chip on this word must match for (int k = 0; k < Chip.COLORCOUNT; k++) { var bnd = model.Sum(WC[j], model.Diff(1, Y[i][j])); model.AddLe(model.Diff(UC[j][k], chips[i].color[k] ? 1 : 0), bnd); model.AddLe(model.Diff(chips[i].color[k] ? 1 : 0, UC[j][k]), bnd); } } } // if this is a color word, ensure that at most one of each color is allowed for (int j = 0; j < word_count; j++) { for (int k = 0; k < Chip.COLORCOUNT; k++) { int[] colstack = new int[chip_count]; for (int i = 0; i < chip_count; i++) { colstack[i] = chips[i].color[k] ? 1 : 0; } model.Add(model.IfThen(model.Eq(WC[j], 1), model.Le(model.ScalProd(colstack, PC[j]), 1))); } } // ensure that the numbers in an order word are sequential for (int j = 0; j < word_count; j++) { IIntVar[] V = model.BoolVarArray(Chip.NUMBERCOUNT); for (int k = 0; k < Chip.NUMBERCOUNT; k++) { int[] numstack = new int[chip_count]; for (int i = 0; i < chip_count; i++) { numstack[i] = chips[i].number[k] ? 1 : 0; } // if this is an order word put the binary numbers into a vector of flags for those numbers model.Add(model.IfThen(model.Eq(WO[j], 1), model.Eq(model.ScalProd(numstack, PO[j]), V[k]))); } // for each number either the next flag is strictly larger, meaning the start of the sequence // or every flag after a decrease is 0, the end of a sequence for (int i = 0; i < Chip.NUMBERCOUNT - 1; i++) { IIntVar Z = model.BoolVar(); model.AddLe(model.Diff(V[i], V[i + 1]), Z); for (int k = i + 1; k < Chip.NUMBERCOUNT; k++) { model.AddLe(V[k], model.Diff(1, Z)); } } } List <Chip[]> words = new List <Chip[]>(); if (suppress) { model.SetOut(null); } Utility.Log("Thinking..."); if (model.Solve()) { for (int j = 0; j < word_count; j++) { if (model.GetValue(WN[j]) > 0.5) { continue; } List <Chip> word = new List <Chip>(); double[] flags = model.GetValues(Yt[j]); for (int i = 0; i < chip_count; i++) { if (flags[i] > 0.5) { word.Add(chips[i]); } } // if this is a color word else it is an order word if (model.GetValue(WC[j]) > 0.5) { words.Add(word.OrderBy(p => Array.IndexOf(p.color, true)).ToArray()); } else { words.Add(word.OrderBy(p => Array.IndexOf(p.number, true)).ToArray()); } } } else { Utility.Warning("No possible moves found!"); } model.Dispose(); Chip[] notplayed = chips.Where(p => !words.Any(q => q.Contains(p))).ToArray(); words.Add(notplayed); return(words); }
private double one_tsp(int dim, int [][] matrix, int [] path) { int[] lo = new int[dim]; for (int i = 0; i < dim; i++) { lo[i] = 1; } Cplex cplex = new Cplex(); NumVarType varType = NumVarType.Bool; INumVar[][] x = new INumVar[dim][]; for (int i = 0; i < dim; i++) { x[i] = cplex.NumVarArray(dim, 0, 1); } for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { x[i][j] = cplex.BoolVar(); } } for (int j = 0; j < dim; j++) { INumExpr xcolSum = cplex.NumExpr(); for (int i = 0; i < dim; i++) { xcolSum = cplex.Sum(xcolSum, x[i][j]); } cplex.AddEq(lo[j], xcolSum); } varType = NumVarType.Float; INumVar[] u = new INumVar[dim]; for (int j = 0; j < dim; j++) { u[j] = cplex.NumVar(0, 100000); } for (int j = 1; j < dim; j++) { cplex.AddGe(u[j], 0); } for (int i = 1; i < dim; i++) { for (int j = 1; j < dim; j++) { if (i != j) { cplex.AddLe(cplex.Sum(cplex.Diff(u[i], u[j]), cplex.Prod(dim, x[i][j])), dim - 1); } } } for (int i = 0; i < dim; i++) { INumExpr xrowSum = cplex.NumExpr(); for (int j = 0; j < dim; j++) { xrowSum = cplex.Sum(xrowSum, x[i][j]); } cplex.AddEq(lo[i], xrowSum); } INumExpr costSum = cplex.NumExpr(); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { costSum = cplex.Sum(costSum, cplex.Prod(x[i][j], matrix[i][j])); } } cplex.AddMinimize(costSum); try { if (cplex.Solve()) { //MessageBox.Show("Solution status = " + cplex.GetStatus()); //MessageBox.Show("cost = " + cplex.ObjValue); int ipath = 0; int depo = -1; for (int i = dim - 1; i >= 0; i--) { for (int j = 0; j < dim; j++) { if (Convert.ToInt16(cplex.GetValue(x[i][j])) == 1) { depo = i; } } } path[ipath] = depo; ipath++; while (depo > -1) { for (int j = 0; j < dim; j++) { if (Convert.ToInt16(cplex.GetValue(x[path[ipath - 1]][j])) == 1) { path[ipath] = j; ipath++; if (j == depo) { depo = -1; } break; } } } return(cplex.ObjValue); } cplex.End(); } catch (ILOG.Concert.Exception ex) { System.Console.WriteLine("Concert Error: " + ex); } return(-1); }
public static Cplex Build_CLP1_Model(IALPFTMDP aff) { Cplex model = new Cplex(); INumVar[][] Var1 = new INumVar[aff.TimeHorizon][]; INumVar[] Var2 = model.NumVarArray(aff.TimeHorizon, 0, double.MaxValue); #region //////////////生成变量////////////// for (int i = 0; i < aff.TimeHorizon; i++) { Var1[i] = model.NumVarArray(aff.RS.Count, 0, double.MaxValue);// new INumVar[aff.DS.Count]; } #endregion #region //////////////生成约束////////////// for (int t = 0; t < aff.TimeHorizon; t++) { foreach (IALPDecision a in aff.DS) { INumExpr exp1 = model.NumExpr(); if (t < aff.TimeHorizon - 1) { exp1 = model.Sum(Var2[t], model.Prod(-1, Var2[t + 1])); foreach (IALPResource re in aff.RS) { if (a.UseResource(re)) { exp1 = model.Sum(exp1, Var1[t][aff.RS.IndexOf(re)], model.Prod(aff.Qti(t, re, a) - 1, Var1[t + 1][aff.RS.IndexOf(re)])); } } } else { exp1 = model.Sum(exp1, Var2[t]); foreach (IALPResource re in aff.RS) { if (a.UseResource(re)) { exp1 = model.Sum(exp1, Var1[t][aff.RS.IndexOf(re)]); } } } model.AddGe(exp1, aff.Rt(t, a)); } if (t < aff.TimeHorizon - 1) { foreach (IALPResource re in aff.RS) { INumExpr exp2 = model.NumExpr(); exp2 = model.Sum(Var1[t][aff.RS.IndexOf(re)], model.Prod(-1, Var1[t + 1][aff.RS.IndexOf(re)])); model.AddGe(exp2, 0); } INumExpr exp3 = model.NumExpr(); exp3 = model.Sum(exp3, Var2[t], model.Prod(-1, Var2[t + 1])); model.AddGe(exp3, 0); } } #endregion #region //////////////生成目标////////////// INumExpr exp5 = model.NumExpr(); exp5 = model.Sum(exp5, Var2[0]); foreach (IALPResource re in aff.RS) { exp5 = model.Sum(exp5, model.Prod((aff.InitialState as IALPState)[re], Var1[0][aff.RS.IndexOf(re)])); } IObjective cost = model.AddMinimize(exp5); #endregion return(model); }
public override void Work() { //获取求解设置 decimal terminalFactor = _ctx.GetParameter("TerminalFactor", 0.001m); int iteration = _ctx.GetParameter("Iteration", 10); int resolution = _ctx.GetParameter("Resolution", 60); decimal initMultipler = _ctx.GetParameter("InitMultiper", 0.1m); string objectiveType = _ctx.GetParameter("ObjectiveType", ""); // 相对-绝对时间转化器 DiscreteTimeAdapter adapter = new DiscreteTimeAdapter(_ctx.StartTime, _ctx.EndTime, resolution); // 路径集 Dictionary <CustomerArrival, List <TravelPath> > pathDict = new Dictionary <CustomerArrival, List <TravelPath> >(); #region 建立初始网络,搜索可行路径 //目标函数网络 var objgraph = ObjectNetworkFactory.Create(objectiveType, _ctx, adapter); //new ObjectTravelHyperNetwork(_ctx, adapter); objgraph.Build(); //基础网络 var basicGraph = new BasicTravelHyperNetwork(_ctx, adapter); basicGraph.Build(); SubTasks.Clear(); foreach (CustomerArrival customer in _ctx.Pal) { Task ta = factory.StartNew(() => { var ori = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).OriSta; var des = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).DesSta; var paths = DepthFirstSearcher.FindAllPaths(basicGraph, new TravelHyperNode() { Time = adapter.ConvertToDiscreteTime(customer.ArriveTime), Station = ori, Price = 0 }, new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 }); pathDict.Add(customer, new List <TravelPath>()); foreach (var path in paths) { pathDict[customer].Add(new TravelPath(basicGraph, path)); } }); SubTasks.Add(ta); } Task.WaitAll(SubTasks.ToArray()); #endregion #region 构建对偶问题 with CPLEX Cplex model = new Cplex(); model.SetOut(null); INumVar theta = model.NumVar(double.MinValue, double.MaxValue); //θ model.AddMaximize(theta); Dictionary <IServiceSegment, INumVar> dual_rho = _ctx.Wor.RailwayTimeTable.Trains .SelectMany(i => i.ServiceSegments).ToDictionary(i => i, i => model.NumVar(0, double.MaxValue)); Dictionary <CustomerArrival, Dictionary <TravelPath, INumVar> > dual_mu = new Dictionary <CustomerArrival, Dictionary <TravelPath, INumVar> >(); foreach (CustomerArrival customer in _ctx.Pal) { dual_mu.Add(customer, new Dictionary <TravelPath, INumVar>()); foreach (var path in pathDict[customer]) { dual_mu[customer].Add(path, model.NumVar(0, double.MaxValue)); } } Dictionary <IEdge <TravelHyperNode>, INumVar> dual_lambda = new Dictionary <IEdge <TravelHyperNode>, INumVar>(); foreach (CustomerArrival customer in _ctx.Pal) { foreach (var path in pathDict[customer]) { if (!dual_lambda.ContainsKey(path.ReservationArc)) { dual_lambda.Add(path.ReservationArc, model.NumVar(0, double.MaxValue)); } } } #endregion #region 变量与乘子 //决策变量 x Dictionary <CustomerArrival, TravelPath> x = new Dictionary <CustomerArrival, TravelPath>(); foreach (CustomerArrival customer in _ctx.Pal) { x.Add(customer, new TravelPath()); } //决策变量 w Dictionary <ITrainTrip, Dictionary <IRailwayStation, PricePath> > w = new Dictionary <ITrainTrip, Dictionary <IRailwayStation, PricePath> >(); foreach (var train in _ctx.Wor.RailwayTimeTable.Trains) { w.Add(train, new Dictionary <IRailwayStation, PricePath>()); foreach (var sta in _ctx.Wor.Net.StationCollection) { w[train].Add(sta, null); } } //辅助变量 y //记录每条弧在当前w的取值下是否可行(available),值为true = 可行;false = 不可行 //超出了y记录的reservation arc 不会有人走 Dictionary <IEdge <TravelHyperNode>, bool> y = new Dictionary <IEdge <TravelHyperNode>, bool>(); foreach (var p in pathDict.Values.SelectMany(i => i)) { if (p.ReservationArc != null && !y.ContainsKey(p.ReservationArc)) { y.Add(p.ReservationArc, false); } } //拉格朗日乘子 rho Dictionary <IServiceSegment, decimal> LM_rho = _ctx.Wor.RailwayTimeTable.Trains .SelectMany(i => i.ServiceSegments).ToDictionary(i => i, i => initMultipler); //拉格朗日乘子 rho 迭代方向 Dictionary <IServiceSegment, decimal> Grad_rho = _ctx.Wor.RailwayTimeTable.Trains .SelectMany(i => i.ServiceSegments).ToDictionary(i => i, i => initMultipler); //拉格朗日乘子 mu Dictionary <CustomerArrival, Dictionary <TravelPath, decimal> > LM_mu = new Dictionary <CustomerArrival, Dictionary <TravelPath, decimal> >(); foreach (CustomerArrival customer in _ctx.Pal) { LM_mu.Add(customer, new Dictionary <TravelPath, decimal>()); foreach (var path in pathDict[customer]) { LM_mu[customer].Add(path, initMultipler); } } //拉格朗日乘子 mu 迭代方向 Dictionary <CustomerArrival, Dictionary <TravelPath, decimal> > Grad_mu = new Dictionary <CustomerArrival, Dictionary <TravelPath, decimal> >(); foreach (CustomerArrival customer in _ctx.Pal) { Grad_mu.Add(customer, new Dictionary <TravelPath, decimal>()); foreach (var path in pathDict[customer]) { Grad_mu[customer].Add(path, initMultipler); } } //拉格朗日乘子 lambda Dictionary <IEdge <TravelHyperNode>, decimal> LM_lambda = new Dictionary <IEdge <TravelHyperNode>, decimal>(); //WARNING: 这里缺少了没有旅客选择的reservation arc foreach (CustomerArrival customer in _ctx.Pal) { foreach (var path in pathDict[customer]) { if (!LM_lambda.ContainsKey(path.ReservationArc)) { LM_lambda.Add(path.ReservationArc, initMultipler); } } } //拉格朗日乘子 lambda 迭代方向 Dictionary <IEdge <TravelHyperNode>, decimal> Grad_lambda = new Dictionary <IEdge <TravelHyperNode>, decimal>(); foreach (CustomerArrival customer in _ctx.Pal) { foreach (var path in pathDict[customer]) { if (!Grad_lambda.ContainsKey(path.ReservationArc)) { Grad_lambda.Add(path.ReservationArc, initMultipler); } } } #endregion decimal bigM1 = pathDict.Max(i => i.Value.Max(j => basicGraph.GetPathCost(j))); decimal bigM2 = _ctx.Pal.Count(); decimal bigM = Math.Max(bigM1, bigM2); decimal lowerBound = decimal.MinValue; decimal upperBound = decimal.MaxValue; bool flag = false;//对偶问题有解 PrintIterationInfo($"Iteration Number, Lower Bound, Upper Bound, Best Lower Bound, Best Upper Bound, Total Gap(%) "); for (int iter = 0; iter < iteration; iter++) { Log($"--------------第{iter}轮求解开始--------------"); bool hasFeasibleSolution = true; #region 求解LR问题 SubTasks.Clear(); foreach (CustomerArrival customer in _ctx.Pal)// 求解x { Task ta = factory.StartNew(() => { var graph = new LRxTravelHyperNetwork(_ctx, adapter, objgraph, customer, pathDict, LM_rho, LM_mu, LM_lambda); graph.Build(); var ori = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).OriSta; var des = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).DesSta; DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> dijkstra = new DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode>(graph, new TravelHyperNode() { Time = adapter.ConvertToDiscreteTime(customer.ArriveTime), Station = ori, Price = 0 }); //考虑该旅客到达时间 x[customer] = new TravelPath(graph, dijkstra.ShortestPathTo( new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 })); }); SubTasks.Add(ta); } foreach (var train in _ctx.Wor.RailwayTimeTable.Trains) { foreach (IRailwayStation station in _ctx.Wor.Net.StationCollection)// 求解w { Task ta = factory.StartNew(() => { var graph = DpnAlgorithm.BuildLRwGraph(_ctx, adapter, train, station, pathDict, basicGraph.LinkTrainDict, LM_mu, LM_lambda); DijkstraShortestPaths <DirectedWeightedSparseGraph <string>, string> dijkstra = new DijkstraShortestPaths <DirectedWeightedSparseGraph <string>, string>(graph, "Start");//考虑该旅客到达时间 var nodepath = dijkstra.ShortestPathTo("End"); if (nodepath == null) { throw new System.Exception("No path found"); } else { w[train][station] = new PricePath(graph, nodepath); } }); SubTasks.Add(ta); } } Task.WaitAll(SubTasks.ToArray()); foreach (var edge in y.Keys.ToArray())//更新y { var sta = edge.Source.Station; var train = basicGraph.GetTrainByReservationLink(edge); y[edge] = w[train][sta].GetWrapPoints(edge.Destination.Price, edge.Source.Time).Any(); } #endregion #region 计算拉格朗日函数值作为下界 decimal templowerBound = 0m; decimal templowerBound_part1 = 0m; decimal templowerBound_part2 = 0m; decimal templowerBound_part3 = 0m; decimal templowerBound_part4 = 0m; Dictionary <CustomerArrival, decimal> lbValueDic = new Dictionary <CustomerArrival, decimal>(); //1 计算在基础网络中的路径cost foreach (CustomerArrival customer in _ctx.Pal) { lbValueDic.Add(customer, objgraph.GetPathCost(x[customer])); templowerBound_part1 += lbValueDic[customer]; } //2计算BRUE项 templowerBound_part2 += _ctx.Pal.Sum(c => pathDict[c].Sum(p => { decimal secondItem = 0m; secondItem += basicGraph.GetPathCost(x[c]) - basicGraph.GetPathCost(p) - _ctx.SitaDic[c.Customer.MarSegID]; secondItem -= (p.ReservationArc != null && y[p.ReservationArc]) ? 0 : bigM; return(secondItem * LM_mu[c][p]); })); //3计算In-train Capacity项 Dictionary <IServiceSegment, int> ServiceDic = _ctx.Wor.RailwayTimeTable .Trains.SelectMany(i => i.ServiceSegments) .ToDictionary(i => i, i => 0);//当前service segment使用情况 foreach (var p in x.Values) { foreach (IServiceSegment seg in p.GetSegments(basicGraph)) { ServiceDic[seg] += 1; } } foreach (var train in _ctx.Wor.RailwayTimeTable.Trains) { foreach (var seg in train.ServiceSegments) { templowerBound_part3 += LM_rho[seg] * (ServiceDic[seg] - train.Carriage.Chairs.Count()); } } //4 计算reservation constraint 项 Dictionary <IEdge <TravelHyperNode>, int> reservationDic = new Dictionary <IEdge <TravelHyperNode>, int>(); foreach (var p in x.Values) { if (reservationDic.ContainsKey(p.ReservationArc)) { reservationDic[p.ReservationArc] += 1; } else { reservationDic.Add(p.ReservationArc, 1); } } foreach (var pair in y.Keys) { //y是所有的reservation 的集合 reservationDic 是已经使用的reservation 集合 var res = reservationDic.Keys.FirstOrDefault(i => i.Source == pair.Source && i.Destination == pair.Destination); templowerBound_part4 += LM_lambda[pair] * ((res != null ? reservationDic[res] : 0) - (y[pair] ? bigM : 0)); } templowerBound = templowerBound_part1 + templowerBound_part2 + templowerBound_part3 + templowerBound_part4; //Log($"Lower Bound = { Math.Round(templowerBound, 2)}," + // $"({ Math.Round(templowerBound_part1, 2) }" + // $"+{ Math.Round(templowerBound_part2, 2)}" + // $"+{ Math.Round(templowerBound_part3, 2)}" + // $"+{ Math.Round(templowerBound_part4, 2)})"); PrintLBSolution(DpnAlgorithm.GetTravelPathString(_ctx, adapter, objgraph, x, lbValueDic)); #endregion #region 更新乘子 if (flag) { decimal LagLowerBound = Convert.ToDecimal(model.GetValue(theta)); Log($"LagLower Bound = { LagLowerBound }"); Log($"Lower Bound = { templowerBound }"); lowerBound = Math.Max(lowerBound, templowerBound); decimal lagGap = LagLowerBound - templowerBound; if (lagGap <= 0)//判断拉格朗日对偶问题是否达到最优 { Log($"求解终止:对偶函数已最优。"); break; } else { /* 更新乘子值 */ foreach (var pair in dual_rho) { LM_rho[pair.Key] = Convert.ToDecimal(model.GetValue(pair.Value)); } foreach (var pair in dual_lambda) { LM_lambda[pair.Key] = Convert.ToDecimal(model.GetValue(pair.Value)); } foreach (CustomerArrival customer in _ctx.Pal) { foreach (var path in pathDict[customer]) { LM_mu[customer][path] = Convert.ToDecimal(model.GetValue(dual_mu[customer][path])); } } } } else /* 如果对偶问题无可行解,通过次梯度的方式更新乘子 */ { //decimal step = 1.618m / (iter + 1); //foreach (CustomerArrival c in _ctx.Pal)//更新mu //{ // foreach (TravelPath p in pathDict[c]) // { // Grad_mu[c][p] = basicGraph.GetPathCost(x[c]) - basicGraph.GetPathCost(p) - _ctx.SitaDic[c.Customer.MarSegID] // - ((p.ReservationArc != null && y[p.ReservationArc]) ? 0 : bigM); // LM_mu[c][p] = Math.Max(0, LM_mu[c][p] + step * Grad_mu[c][p]); // } //} //foreach (var pair in y.Keys) //更新lambda //{ // var res = reservationDic.Keys.FirstOrDefault(i => i.Source == pair.Source && i.Destination == pair.Destination); // Grad_lambda[pair] = ((res != null ? reservationDic[res] : 0) - (y[pair] ? bigM : 0)); // LM_lambda[pair] = Math.Max(0, LM_lambda[pair] + step * Grad_lambda[pair]); //} //foreach (var train in _ctx.Wor.RailwayTimeTable.Trains)//更新rho //{ // foreach (var seg in train.ServiceSegments) // { // Grad_rho[seg] = ServiceDic[seg] - train.Carriage.Chairs.Count(); // LM_rho[seg] = Math.Max(0, LM_rho[seg] + step * Grad_rho[seg]); // } //} } #endregion #region 求解拉格朗日对偶问题 /* 求解 几何乘子 */ // 增加 一个约束 INumExpr exp = model.NumExpr(); //2 计算BRUE项 foreach (var c in _ctx.Pal) { foreach (var p in pathDict[c]) { decimal secondItem = 0m; secondItem += basicGraph.GetPathCost(x[c]) - basicGraph.GetPathCost(p) - _ctx.SitaDic[c.Customer.MarSegID]; secondItem -= (p.ReservationArc != null && y[p.ReservationArc]) ? 0 : bigM; exp = model.Sum(exp, model.Prod(Convert.ToDouble(secondItem), dual_mu[c][p])); } } //3计算In-train Capacity项 (这里直接用了计算下界时候的 Service_dic foreach (var train in _ctx.Wor.RailwayTimeTable.Trains) { foreach (var seg in train.ServiceSegments) { exp = model.Sum(exp, model.Prod(Convert.ToDouble(ServiceDic[seg] - train.Carriage.Chairs.Count()), dual_rho[seg])); } } //4 计算reservation constraint 项 (这里直接用了计算下界时候的 reservationDic foreach (var pair in y.Keys) { var res = reservationDic.Keys.FirstOrDefault(i => i.Source == pair.Source && i.Destination == pair.Destination); exp = model.Sum(exp, model.Prod(Convert.ToDouble(((res != null ? reservationDic[res] : 0) - (y[pair] ? bigM : 0))), dual_lambda[pair])); } model.AddGe(model.Sum(Convert.ToDouble(templowerBound_part1), exp), theta); /* Trust-Region */ //var trExpr = model.Add() flag = model.Solve(); Log($"Is Dual Problem Feasible: { flag }"); #endregion #region 通过一个启发式规则计算上界(按照w模拟到达) var pathcost = lbValueDic.ToDictionary(i => i.Key, i => i.Value); var x_least = x.ToDictionary(i => i.Key, i => i.Value);//当前w下每个旅客的最短路径 var x_upperbound = x.ToDictionary(i => i.Key, i => i.Value); var x_controlled = x.ToDictionary(i => i.Key, i => i.Value); #region 1-构建当前y下的最优x值 SubTasks.Clear(); foreach (CustomerArrival customer in _ctx.Pal)// 求解x { Task ta = factory.StartNew(() => { var controlledLRxgraph = new ControlledLRxTravelHyperNetwork( _ctx, adapter, objgraph, customer, pathDict, LM_rho, LM_mu, LM_lambda, y); controlledLRxgraph.Build(); var ori = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).OriSta; var des = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).DesSta; TravelHyperNode startNode = new TravelHyperNode() { Time = adapter.ConvertToDiscreteTime(customer.ArriveTime), Station = ori, Price = 0 }; TravelHyperNode endNode = new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 }; DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> dijkstra = new DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> (controlledLRxgraph, startNode);//考虑该旅客到达时间 if (!dijkstra.HasPathTo(endNode)) { throw new System.Exception("没有路径!"); } else { x_controlled[customer] = new TravelPath(controlledLRxgraph, dijkstra.ShortestPathTo(endNode)); } }); SubTasks.Add(ta); } Task.WaitAll(SubTasks.ToArray()); #endregion # region 2-构建当前y下的出行最小值 var solutiongraph = new ControlledTravelHyperNetwork(_ctx, adapter, y); solutiongraph.Build(); Parallel.ForEach(_ctx.Pal, customer => //foreach (var customer in _ctx.Pal)//求此网络下每个旅客的最短路径 { var ori = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).OriSta; var des = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).DesSta; TravelHyperNode startNode = new TravelHyperNode() { Time = adapter.ConvertToDiscreteTime(customer.ArriveTime), Station = ori, Price = 0 }; TravelHyperNode endNode = new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 }; DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> dijkstra = new DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> (solutiongraph, startNode); if (!dijkstra.HasPathTo(endNode)) { throw new System.Exception("没有路径!"); } else { x_least[customer] = new TravelPath(solutiongraph, dijkstra.ShortestPathTo(endNode)); } }); #endregion #region 3-修复可行解 var solutiongraphTemp = new SimNetwork(_ctx, adapter, y);//建立仿真网络 solutiongraphTemp.Build(); foreach (var customer in _ctx.Pal) { x_upperbound[customer] = x_controlled[customer]; TravelPath path = x_controlled[customer]; if (!solutiongraphTemp.IsPathFeasible(path) || solutiongraphTemp.GetPathCost(path) > solutiongraph.GetPathCost(x_least[customer]) + _ctx.SitaDic[customer.Customer.MarSegID])//如果违反了容量约束或者BRUE约束 { var ori = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).OriSta; var des = (_ctx.Wor.Mar[customer.Customer.MarSegID] as IRailwayMarketSegment).DesSta; DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode> dijkstra = new DijkstraShortestPaths <DirectedWeightedSparseGraph <TravelHyperNode>, TravelHyperNode>(solutiongraphTemp, new TravelHyperNode() { Time = adapter.ConvertToDiscreteTime(customer.ArriveTime), Station = ori, Price = 0 }); //重新查找路径,如果存在路径 if (dijkstra.HasPathTo(new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 })) { x_upperbound[customer] = new TravelPath(solutiongraphTemp, dijkstra.ShortestPathTo(new TravelHyperNode() { Time = adapter.Horizon + 1440, Station = des, Price = 0 })); if (solutiongraphTemp.GetPathCost(x_upperbound[customer]) <= //满足BRUE约束 solutiongraph.GetPathCost(x_least[customer]) + _ctx.SitaDic[customer.Customer.MarSegID]) { path = x_upperbound[customer]; } else { hasFeasibleSolution = false; break; } } else { hasFeasibleSolution = false; break; } } pathcost[customer] = objgraph.GetPathCost(path); //加载路径 foreach (var seg in path.GetSegments(basicGraph)) { solutiongraphTemp.AddUsage(seg, 1); } } var tempUpperbound = _ctx.Pal.Sum(c => objgraph.GetPathCost(x_upperbound[c])); #endregion //如果有最优解再更新上界 bool hasBetterUpperbound = tempUpperbound < upperBound; if (hasFeasibleSolution) { upperBound = Math.Min(upperBound, tempUpperbound); } Log($"Upper Bound = { Math.Round(tempUpperbound, 2) },找到可行解 : { hasFeasibleSolution.ToString()}"); #endregion #region Terminatation 判定 Log($"Upper Bound = { tempUpperbound }"); decimal absoluteGap = 0; string gapStr = ""; //如果上限是无穷,那么此时gap也是无穷 if (upperBound == decimal.MaxValue || lowerBound == decimal.MinValue) { absoluteGap = decimal.MaxValue; gapStr = $"+∞"; } else { absoluteGap = upperBound - lowerBound; gapStr = $"{ Math.Round(absoluteGap, 2)}"; } if (absoluteGap < terminalFactor && absoluteGap > 0) { Log($"求解终止:Gap以满足终止条件,Gap={ absoluteGap }"); break; } Log($"Total Gap = { gapStr }"); #endregion #region 输出信息 //SendMessage($"#Iteration Number, Lower Bound, Upper Bound, Best Lower Bound, Best Upper Bound, Total Gap(%) "); PrintIterationInfo($"#{iter},{ Math.Round(templowerBound) },{ Math.Round(tempUpperbound) },{ Math.Round(lowerBound)}" + $",{ Math.Round(upperBound) },{ gapStr }"); string ss = "###,"; foreach (var s in LM_rho) { ss += ($"{s.Key.ToString()}:{ s.Value.ToString() },"); } PrintIterationInfo(ss); if (hasFeasibleSolution && hasBetterUpperbound) { ObjValue = pathcost.Sum(i => i.Value); PrintSolution( DpnAlgorithm.GetTravelPathString(_ctx, adapter, solutiongraph, x_upperbound, pathcost), DpnAlgorithm.GetPricingPathString(_ctx, adapter, w)); } #endregion Log($"--------------第{iter}轮求解结束--------------"); }
static void Main(string[] args) { try { string filename = "../../../../examples/data/etsp.dat"; if (args.Length > 0) { filename = args[0]; } Data data = new Data(filename); Cplex cplex = new Cplex(); // Create start variables INumVar[][] s = new INumVar[data.nJobs][]; for (int j = 0; j < data.nJobs; j++) { s[j] = cplex.NumVarArray(data.nResources, 0.0, Horizon); } // State precedence constraints for (int j = 0; j < data.nJobs; j++) { for (int i = 1; i < data.nResources; i++) { cplex.AddGe(s[j][i], cplex.Sum(s[j][i - 1], data.duration[j][i - 1])); } } // State disjunctive constraints for each resource for (int i = 0; i < data.nResources; i++) { int end = data.nJobs - 1; for (int j = 0; j < end; j++) { int a = data.activityOnResource[i][j]; for (int k = j + 1; k < data.nJobs; k++) { int b = data.activityOnResource[i][k]; cplex.Add(cplex.Or( cplex.Ge(s[j][a], cplex.Sum(s[k][b], data.duration[k][b])), cplex.Ge(s[k][b], cplex.Sum(s[j][a], data.duration[j][a])) )); } } } // The cost is the sum of earliness or tardiness costs of each job int last = data.nResources - 1; INumExpr costSum = cplex.NumExpr(); for (int j = 0; j < data.nJobs; j++) { double[] points = { data.dueDate[j] }; double[] slopes = { -data.earlinessCost[j], data.tardinessCost[j] }; costSum = cplex.Sum(costSum, cplex.PiecewiseLinear( cplex.Sum(s[j][last], data.duration[j][last]), points, slopes, data.dueDate[j], 0) ); } cplex.AddMinimize(costSum); cplex.SetParam(Cplex.Param.Emphasis.MIP, 4); if (cplex.Solve()) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" Optimal Value = " + cplex.ObjValue); } cplex.End(); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("Concert exception caught: " + e); } catch (InputDataReader.InputDataReaderException ex) { System.Console.WriteLine("Data Error: " + ex); } catch (System.IO.IOException ex) { System.Console.WriteLine("IO Error: " + ex); } }
static void Main(string[] args) { try { string filename = "../../../../examples/data/etsp.dat"; if ( args.Length > 0) filename = args[0]; Data data = new Data(filename); Cplex cplex = new Cplex(); // Create start variables INumVar[][] s = new INumVar[data.nJobs][]; for (int j = 0; j < data.nJobs; j++) s[j] = cplex.NumVarArray(data.nResources, 0.0, Horizon); // State precedence constraints for (int j = 0; j < data.nJobs; j++) { for (int i = 1; i < data.nResources; i++) cplex.AddGe(s[j][i], cplex.Sum(s[j][i-1], data.duration[j][i-1])); } // State disjunctive constraints for each resource for (int i = 0; i < data.nResources; i++) { int end = data.nJobs - 1; for (int j = 0; j < end; j++) { int a = data.activityOnResource[i][j]; for (int k = j + 1; k < data.nJobs; k++) { int b = data.activityOnResource[i][k]; cplex.Add(cplex.Or( cplex.Ge(s[j][a], cplex.Sum(s[k][b], data.duration[k][b])), cplex.Ge(s[k][b], cplex.Sum(s[j][a], data.duration[j][a])) )); } } } // The cost is the sum of earliness or tardiness costs of each job int last = data.nResources - 1; INumExpr costSum = cplex.NumExpr(); for (int j = 0; j < data.nJobs; j++) { double[] points = { data.dueDate[j] }; double[] slopes = { -data.earlinessCost[j], data.tardinessCost[j] }; costSum = cplex.Sum(costSum, cplex.PiecewiseLinear( cplex.Sum(s[j][last], data.duration[j][last]), points, slopes, data.dueDate[j], 0) ); } cplex.AddMinimize(costSum); cplex.SetParam(Cplex.Param.Emphasis.MIP, 4); if ( cplex.Solve() ) { System.Console.WriteLine("Solution status = " + cplex.GetStatus()); System.Console.WriteLine(" Optimal Value = " + cplex.ObjValue); } cplex.End(); } catch (ILOG.Concert.Exception e) { System.Console.WriteLine("Concert exception caught: " + e); } catch (InputDataReader.InputDataReaderException ex) { System.Console.WriteLine("Data Error: " + ex); } catch (System.IO.IOException ex) { System.Console.WriteLine("IO Error: " + ex); } }