private void BreakHandling(GRBModel model, int numberOfRoutes, GRBVar[][] v) { for (int i = 1; i < visitDurations.Length; i++) { if (!input.Visits[i - 1].IsBreak) { continue; } var visit = input.Visits[i - 1]; var breakRoutes = new List <int>(); for (var day = 0; day < input.Days.Length; day++) { var s = visit.SantaId + day * input.Santas.Length; model.AddGenConstrOr(v[s][i], v[s].Take(i - 1).Skip(1).ToArray(), null); // assignment if used breakRoutes.Add(s); } // break cannot be visited by another santa foreach (var nonBreakRoute in Enumerable.Range(0, numberOfRoutes).Except(breakRoutes)) { model.AddConstr(v[nonBreakRoute][i] == 0, null); } } }
//linearize a condition f. For example, f=k1+k2*k3+k4, it would return f=u1+u2+u3, where u1=k1, u2=k2*k3, u3=k4 //Furthermore, this function could identify if f has a constant term. If so, it would mark out that f has a constant term in the array consflag. static public List <GRBVar> LinearConstrain(GRBModel m, GRBVar[] Uvar, GRBVar[] UFvar, UInt32[, ,] ConS, int[] conlen, int ind, GRBVar[] keyvar, GRBVar[] ivvar, int[] loc1, GRBVar[] kvf, GRBVar[] vvf, GRBVar[] Wvar, int[] locw, List <GRBVar> LinFlagRes) { List <GRBVar> LinVar = new List <GRBVar>() { }; List <GRBVar> LinVarFlag = new List <GRBVar>() { }; List <GRBVar> TempVarFlag = new List <GRBVar>() { }; //store the flag variables of the variables appearing in a monimial List <GRBVar> TempVar = new List <GRBVar>() { }; //store the assignment variables of the variables appearing in a monimial int weight = 0; int i, j, k; int t; int loc = 0; int locf = 0; int loc_w = locw[0]; loc = loc1[0]; locf = loc1[1]; for (j = 0; j < conlen[ind]; j++) { //for the j-th monomial //Cons[ind,j,0-2]stores the iv variable appearing in the monimial //Cons[ind,j,3-5]stores the key variable appearing in the monimial weight = 0; TempVar.Clear(); TempVarFlag.Clear(); for (i = 0; i < 96; i++) { t = (int)((ConS[ind, j, (i >> 5)] >> (i & 0x1f)) & 0x01); weight = weight + t; if (t == 1) { TempVar.Add(ivvar[i]); TempVarFlag.Add(vvf[i]); } } for (i = 0; i < 96; i++) { t = (int)((ConS[ind, j, (i >> 5) + 3] >> (i & 0x1f)) & 0x01); weight = weight + t; if (t == 1) { TempVar.Add(keyvar[i]); TempVarFlag.Add(kvf[i]); } } //if weight ==1, it is a monomial of degree one, then we only replace it with a new variable if (weight == 1) { m.AddConstr(Uvar[loc] == TempVar[0], "SingleBit" + loc.ToString()); m.AddConstr(UFvar[locf] == TempVarFlag[0], "SingleBit" + loc.ToString()); LinVar.Add(Uvar[loc]); LinFlagRes.Add(UFvar[locf]); loc++; locf++; } //if weight>1, then it is a nonlinear monomial and we should linearize it accroding to the rule of AND in our paper. if (weight > 1) { GRBVar[] PickVars = new GRBVar[TempVar.Count]; for (i = 0; i < TempVar.Count; i++) { PickVars[i] = TempVar[i]; //Wvar[loc_w+i]= TempVar[i]^TempVarFlag[i] GRBVar[] tempor = new GRBVar[2] { TempVar[i], TempVarFlag[i] }; m.AddGenConstrOr(Wvar[loc_w + i], tempor, "tempor" + i.ToString());//变元与变元的标志相或 } GRBVar[] tempm = new GRBVar[TempVar.Count]; //Wvar[loc_w+l]=min(Wvar[loc_w],Wvar[loc_w+1],...,Wvar[loc_w+l-1]), where l is the number variables appearing in the monomial for (i = 0; i < TempVar.Count; i++) { tempm[i] = Wvar[loc_w + i]; } loc_w = loc_w + TempVar.Count; m.AddGenConstrMin(Wvar[loc_w], tempm, 1, "linmin" + loc_w.ToString()); loc_w++; for (i = 0; i < TempVar.Count; i++) { tempm[i] = TempVarFlag[i]; } //Wvar[loc_w]=max(TempVarFlag[0],TempVarFlag[1],...,TempVarFlag[l-1]), where l is the number variables appearing in the monomial m.AddGenConstrMax(Wvar[loc_w], tempm, 0, "linmaxFlag" + loc_w.ToString()); loc_w++; GRBVar[] tempminFlag = new GRBVar[2] { Wvar[loc_w - 1], Wvar[loc_w - 2] }; //UFvar[loc] is the final flag variable of the monomial m.AddGenConstrMin(UFvar[locf], tempminFlag, 1, "minFlag" + loc.ToString()); //Uvar[loc] is the final assignment variable of the monomial m.AddGenConstrMin(Uvar[loc], PickVars, 0, "Linearity" + loc.ToString()); LinVar.Add(Uvar[loc]); LinFlagRes.Add(UFvar[locf]); loc++; locf++; } } loc1[0] = loc; loc1[1] = locf; locw[0] = loc_w; return(LinVar); }
static void Main() { try { // Example data: // e.g. {0, n+1, 2} means clause (x0 or ~x1 or x2) int[,] Clauses = new int[, ] { { 0, n + 1, 2 }, { 1, n + 2, 3 }, { 2, n + 3, 0 }, { 3, n + 0, 1 }, { n + 0, n + 1, 2 }, { n + 1, n + 2, 3 }, { n + 2, n + 3, 0 }, { n + 3, n + 0, 1 } }; int i, status; // Create environment GRBEnv env = new GRBEnv("genconstr_cs.log"); // Create initial model GRBModel model = new GRBModel(env); model.ModelName = "genconstr_cs"; // Initialize decision variables and objective GRBVar[] Lit = new GRBVar[NLITERALS]; GRBVar[] NotLit = new GRBVar[NLITERALS]; for (i = 0; i < NLITERALS; i++) { Lit[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("X{0}", i)); NotLit[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("notX{0}", i)); } GRBVar[] Cla = new GRBVar[NCLAUSES]; for (i = 0; i < NCLAUSES; i++) { Cla[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("Clause{0}", i)); } GRBVar[] Obj = new GRBVar[NOBJ]; for (i = 0; i < NOBJ; i++) { Obj[i] = model.AddVar(0.0, 1.0, 1.0, GRB.BINARY, string.Format("Obj{0}", i)); } // Link Xi and notXi GRBLinExpr lhs; for (i = 0; i < NLITERALS; i++) { lhs = new GRBLinExpr(); lhs.AddTerm(1.0, Lit[i]); lhs.AddTerm(1.0, NotLit[i]); model.AddConstr(lhs, GRB.EQUAL, 1.0, string.Format("CNSTR_X{0}", i)); } // Link clauses and literals for (i = 0; i < NCLAUSES; i++) { GRBVar[] clause = new GRBVar[3]; for (int j = 0; j < 3; j++) { if (Clauses[i, j] >= n) { clause[j] = NotLit[Clauses[i, j] - n]; } else { clause[j] = Lit[Clauses[i, j]]; } } model.AddGenConstrOr(Cla[i], clause, string.Format("CNSTR_Clause{0}", i)); } // Link objs with clauses model.AddGenConstrMin(Obj[0], Cla, GRB.INFINITY, "CNSTR_Obj0"); lhs = new GRBLinExpr(); for (i = 0; i < NCLAUSES; i++) { lhs.AddTerm(1.0, Cla[i]); } model.AddGenConstrIndicator(Obj[1], 1, lhs, GRB.GREATER_EQUAL, 4.0, "CNSTR_Obj1"); // Set global objective sense model.ModelSense = GRB.MAXIMIZE; // Save problem model.Write("genconstr_cs.mps"); model.Write("genconstr_cs.lp"); // Optimize model.Optimize(); // Status checking status = model.Status; if (status == GRB.Status.INF_OR_UNBD || status == GRB.Status.INFEASIBLE || status == GRB.Status.UNBOUNDED) { Console.WriteLine("The model cannot be solved " + "because it is infeasible or unbounded"); return; } if (status != GRB.Status.OPTIMAL) { Console.WriteLine("Optimization was stopped with status {0}", status); return; } // Print result double objval = model.ObjVal; if (objval > 1.9) { Console.WriteLine("Logical expression is satisfiable"); } else if (objval > 0.9) { Console.WriteLine("At least four clauses can be satisfied"); } else { Console.WriteLine("Not even three clauses can be satisfied"); } // Dispose of model and environment model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: {0}. {1}", e.ErrorCode, e.Message); } }