/// <summary> /// Basicly the same as DesiredOverlap but with unavailable /// </summary> /// <param name="model"></param> /// <param name="numberOfRoutes"></param> /// <param name="v"></param> /// <param name="w"></param> /// <param name="c"></param> /// <param name="unavailableDuration"></param> private void UnavailableOverlap(GRBModel model, int numberOfRoutes, GRBVar[][] v, GRBVar[][] w, GRBVar[][] c, GRBVar[][][] unavailableDuration, bool hardConstraint = false) { for (int s = 0; s < numberOfRoutes; s++) { var day = s / input.Santas.Length; var(dayStart, dayEnd) = input.Days[day]; var dayDuration = dayEnd - dayStart; for (int i = 1; i < visitDurations.Length; i++) { var visit = input.Visits[i - 1]; for (int d = 0; d < visit.Unavailable.Length; d++) { // check if unavailable is on this day var(unavailableFrom, unavailableTo) = visit.Unavailable[d]; if (unavailableTo < dayStart || unavailableFrom > dayEnd) { model.Remove(unavailableDuration[s][i][d]); unavailableDuration[s][i][d] = null; //model.AddConstr(unavailableDuration[s][i][d] == 0, GurobiVarName($"unavailalbe[{s}][{i}][{d}] == 0, outside of day")); continue; } // temp if (hardConstraint) { model.AddConstr(unavailableDuration[s][i][d] == 0, GurobiVarName($"unavailalbe[{s}][{i}][{d}] == 0, hard constraint")); } var maxUnavailableDuration = Math.Min(visit.Duration, unavailableTo - unavailableFrom); model.AddConstr(unavailableDuration[s][i][d] <= maxUnavailableDuration * v[s][i], GurobiVarName($"unavailable[{s}][{i}][{d}] only possible if v[{s}][{i}]")); var unavailableStart = model.AddVar(unavailableFrom - dayStart, dayDuration, 0, GRB.CONTINUOUS, GurobiVarName($"unavailableStart[{s}][{i}][{d}]")); var binHelperStart = model.AddVar(0, 1, 0, GRB.BINARY, GurobiVarName($"binHelperUnavailableStart[{s}][{i}][{d}]")); var visitStart = c[s][i]; model.AddConstr(unavailableStart >= visitStart, null); model.AddGenConstrIndicator(binHelperStart, 0, unavailableStart <= unavailableFrom - dayStart, null); model.AddGenConstrIndicator(binHelperStart, 1, unavailableStart <= visitStart, null); var unavailableEnd = model.AddVar(0, unavailableTo - dayStart, 0, GRB.CONTINUOUS, GurobiVarName($"unavailableEnd[{s}][{i}][{d}]")); var binHelperEnd = model.AddVar(0, 1, 0, GRB.BINARY, GurobiVarName($"binHelperUnavailableEnd[{s}][{i}][{d}]")); var visitEnd = visitStart + visit.Duration * v[s][i]; model.AddConstr(unavailableEnd <= visitEnd, GurobiVarName($"unavailableEnd[{s}[{i}][{d}] <= visitEnd")); model.AddGenConstrIndicator(binHelperEnd, 0, unavailableEnd >= unavailableTo - dayStart, null); model.AddGenConstrIndicator(binHelperEnd, 1, unavailableEnd >= visitEnd, null); model.AddConstr( unavailableDuration[s][i][d] >= unavailableEnd - unavailableStart, GurobiVarName($"unavailable overlap[{s}][{i}][{d}]")); } } } }
private void IncreasingC(GRBModel model, int numberOfRoutes, GRBVar[][] w, GRBVar[][] c, GRBVar[][] v) { for (int s = 0; s < numberOfRoutes; s++) { for (int i = 1; i < distances.GetLength(0); i++) { model.AddGenConstrIndicator(v[s][i], 0, c[s][i] == 0, GurobiVarName($"if v[{s}][{i}] == 0 c[{s}][{i}] == 0")); for (int k = 0; k < distances.GetLength(1); k++) { model.AddGenConstrIndicator(AccessW(w[s], k, i), 1, c[s][i] >= c[s][k] + distances[k, i] + visitDurations[k], GurobiVarName($"if w[{s}][{k},{i}] c[{s}][{i}] >= c[{s}][{k}]+ dist+duration")); } } } }
private void DesiredOverlap(GRBModel model, int numberOfRoutes, GRBVar[][] v, GRBVar[][] w, GRBVar[][] c, GRBVar[][][] desiredDuration) { for (int s = 0; s < numberOfRoutes; s++) { var day = s / input.Santas.Length; var(dayStart, dayEnd) = input.Days[day]; var dayDuration = dayEnd - dayStart; for (int i = 1; i < visitDurations.Length; i++) { var visit = input.Visits[i - 1]; for (int d = 0; d < visit.Desired.Length; d++) { var(desiredFrom, desiredTo) = visit.Desired[d]; // check if desired on day if (desiredTo < dayStart || desiredFrom > dayEnd) { model.Remove(desiredDuration[s][i][d]); desiredDuration[s][i][d] = null; //free up memory //model.AddConstr(desiredDuration[s][i][d] == 0, GurobiVarName($"desiredDuration[{s}][{i}][{d}] == 0, outside of day")); continue; } var maxDesiredDuration = Math.Min(visit.Duration, desiredTo - desiredFrom); model.AddConstr(desiredDuration[s][i][d] <= maxDesiredDuration * v[s][i], GurobiVarName($"desired[{s}][{i}][{d}] only possible if v[{s}][{i}]")); var desiredStart = model.AddVar(Math.Max(desiredFrom - dayStart, 0), dayDuration, 0, GRB.CONTINUOUS, GurobiVarName($"desiredStart[{s}][{i}][{d}]")); model.AddConstr(desiredStart >= c[s][i], GurobiVarName($"desiredStart[{s}[{i}][{d}] >= visitStart")); var desiredEnd = model.AddVar(0, desiredTo - dayStart, 0, GRB.CONTINUOUS, GurobiVarName($"desiredEnd[{s}][{i}][{d}]")); model.AddConstr(desiredEnd <= c[s][i] + visit.Duration * v[s][i], GurobiVarName($"desiredEnd[{s}[{i}][{d}] <= visitEnd")); var binDecisionVariable = model.AddVar(0, 1, 0, GRB.BINARY, GurobiVarName($"binDesiredDecisionVar[{s}][{i}][{d}]")); // if positive, duration = end -start model.AddGenConstrIndicator(binDecisionVariable, 0, desiredEnd - desiredStart >= 0, null); model.AddGenConstrIndicator(binDecisionVariable, 0, desiredDuration[s][i][d] == desiredEnd - desiredStart, null); // if negative, duration = 0 model.AddGenConstrIndicator(binDecisionVariable, 1, desiredEnd - desiredStart <= 0, null); model.AddGenConstrIndicator(binDecisionVariable, 1, desiredDuration[s][i][d] == 0, null); } } } }
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); } }