// If the solution space is very large, this method will not return. // The most likely result is that it will exceed memory capacity // and then fail. As a result, we shouldn't use this method in // any production optimization. public IEnumerable <ProductionTarget> GetFeasibleTargets(double claySupply, double glazeSupply) { List <ProductionTarget> targets = new List <ProductionTarget>(); // Setup the Gurobi environment & Model GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); // Setup the decision variables GRBVar xS = CreateSmallVasesVariable(claySupply, model); GRBVar xL = CreateLargeVasesVariable(glazeSupply, model); model.Update(); // Create Constraints CreateConstraints(model, xS, xL, claySupply, glazeSupply); // Find the greatest number of small vases we can make var maxSmall = System.Math.Min(claySupply, glazeSupply); // Find the greatest number of large vases we can make var maxLarge = System.Math.Min(claySupply / 4.0, glazeSupply / 2.0); // Find all feasible combinations of small and large vases // Note: There are probably several better ways of doing this // that are more efficient and organic. For example, we could make // a tree that represents all of the possible decisions and let the // optimizer find the solutions from within that tree. var results = new List <ProductionTarget>(); for (int nSmall = 0; nSmall <= maxSmall; nSmall++) { for (int nLarge = 0; nLarge <= maxLarge; nLarge++) { // Force the solution to the target set of values var c1 = model.AddConstr(xS == nSmall, $"xS_Equals_{nSmall}"); var c2 = model.AddConstr(xL == nLarge, $"xL_Equals_{nLarge}"); model.Update(); // See if the solution is feasible with those values model.Optimize(); if (model.IsFeasible()) { results.Add(new ProductionTarget() { Small = nSmall, Large = nLarge }); } model.Remove(c1); model.Remove(c2); model.Update(); } } return(results); }
public static void Remove(this GRBModel model, IEnumerable <GRBSOS> constraints) { foreach (var constraint in constraints) { model.Remove(constraint); } }
public static void Remove(this GRBModel model, IEnumerable <GRBVar> variables) { foreach (var variable in variables) { model.Remove(variable); } }
/// <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}]")); } } } }
public override bool DelConstraint(object solver, int row) { GRBModel model = solver as GRBModel; if (model == null) { return(false); } model.Remove(model.GetConstrs()[row]); model.Update(); return(true); }
public override bool DelColumn(object solver, int column) { GRBModel model = solver as GRBModel; if (model == null) { return(false); } model.Remove(model.GetVars()[column]); model.Update(); return(true); }
private void ChangeNBreaksGurobi(GRBModel pModel, GRBLinExpr pTotalStepsConst, GRBVar[] pDecVar, int intNClasses, int intNFeatures) { try { Cs = new double[intNClasses + 1]; cbIdx = new int[intNClasses + 1]; // For Graph int intNDecVar = (intNFeatures * (intNFeatures + 1)) / 2; // Add L0_0 pModel.Remove(pModel.GetConstrByName("Nsteps")); pModel.AddConstr(pTotalStepsConst, GRB.EQUAL, intNClasses, "Nsteps"); //Solving pModel.Optimize(); //Add Results to CS array Cs[0] = arrEst[0]; //Estimate Array was sorted int intIdxCs = 0; if (pModel.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) { for (int i = 0; i < intNDecVar; i++) { if (pDecVar[i].Get(GRB.DoubleAttr.X) == 1) { intIdxCs++; string strName = pDecVar[i].Get(GRB.StringAttr.VarName); int intIndexUBar = strName.IndexOf("_"); string strTo = strName.Substring(intIndexUBar + 1); int intToValue = Convert.ToInt16(strTo); Cs[intIdxCs] = arrEst[intToValue - 1]; //Closed cbIdx[intIdxCs] = intToValue - 1; } } } txtObjValue.Text = pModel.Get(GRB.DoubleAttr.ObjVal).ToString("N5"); } catch (Exception ex) { MessageBox.Show(this.Handle.ToString() + " Error:" + ex.Message); return; } }
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 { // Create environment GRBEnv env = new GRBEnv(); // Create a new m GRBModel m = new GRBModel(env); double lb = 0.0, ub = GRB.INFINITY; GRBVar x = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x"); GRBVar y = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y"); GRBVar u = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "u"); GRBVar v = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "v"); // Set objective m.SetObjective(2 * x + y, GRB.MAXIMIZE); // Add linear constraint m.AddConstr(u + 4 * v <= 9, "l1"); // Approach 1) PWL constraint approach double intv = 1e-3; double xmax = Math.Log(9.0); int len = (int)Math.Ceiling(xmax / intv) + 1; double[] xpts = new double[len]; double[] upts = new double[len]; for (int i = 0; i < len; i++) { xpts[i] = i * intv; upts[i] = f(i * intv); } GRBGenConstr gc1 = m.AddGenConstrPWL(x, u, xpts, upts, "gc1"); double ymax = (9.0 / 4.0) * (9.0 / 4.0); len = (int)Math.Ceiling(ymax / intv) + 1; double[] ypts = new double[len]; double[] vpts = new double[len]; for (int i = 0; i < len; i++) { ypts[i] = i * intv; vpts[i] = g(i * intv); } GRBGenConstr gc2 = m.AddGenConstrPWL(y, v, ypts, vpts, "gc2"); // Optimize the model and print solution m.Optimize(); printsol(m, x, y, u, v); // Approach 2) General function constraint approach with auto PWL // translation by Gurobi // restore unsolved state and get rid of PWL constraints m.Reset(); m.Remove(gc1); m.Remove(gc2); m.Update(); GRBGenConstr gcf1 = m.AddGenConstrExp(x, u, "gcf1", ""); GRBGenConstr gcf2 = m.AddGenConstrPow(y, v, 0.5, "gcf2", ""); m.Parameters.FuncPieceLength = 1e-3; // Optimize the model and print solution m.Optimize(); printsol(m, x, y, u, v); // Zoom in, use optimal solution to reduce the ranges and use a smaller // pclen=1e-5 to solve it x.LB = Math.Max(x.LB, x.X - 0.01); x.UB = Math.Min(x.UB, x.X + 0.01); y.LB = Math.Max(y.LB, y.X - 0.01); y.UB = Math.Min(y.UB, y.X + 0.01); m.Update(); m.Reset(); m.Parameters.FuncPieceLength = 1e-5; // Optimize the model and print solution m.Optimize(); printsol(m, x, y, u, v); // Dispose of model and environment m.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
static void Main() { try { // Sample data // Sets of days and workers string[] Shifts = new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6", "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13", "Sun14" }; string[] Workers = new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" }; int nShifts = Shifts.Length; int nWorkers = Workers.Length; // Number of workers required for each shift double[] shiftRequirements = new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 }; // Amount each worker is paid to work one shift double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 }; // Worker availability: 0 if the worker is unavailable for a shift double[,] availability = new double[, ] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; // Model GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); model.ModelName = "assignment"; // Assignment variables: x[w][s] == 1 if worker w is assigned // to shift s. Since an assignment model always produces integer // solutions, we use continuous variables and solve as an LP. GRBVar[,] x = new GRBVar[nWorkers, nShifts]; for (int w = 0; w < nWorkers; ++w) { for (int s = 0; s < nShifts; ++s) { x[w, s] = model.AddVar(0, availability[w, s], pay[w], GRB.CONTINUOUS, Workers[w] + "." + Shifts[s]); } } // The objective is to minimize the total pay costs model.ModelSense = GRB.MINIMIZE; // Constraint: assign exactly shiftRequirements[s] workers // to each shift s for (int s = 0; s < nShifts; ++s) { GRBLinExpr lhs = 0.0; for (int w = 0; w < nWorkers; ++w) { lhs.AddTerm(1.0, x[w, s]); } model.AddConstr(lhs == shiftRequirements[s], Shifts[s]); } // Optimize model.Optimize(); int status = model.Status; if (status == GRB.Status.UNBOUNDED) { Console.WriteLine("The model cannot be solved " + "because it is unbounded"); return; } if (status == GRB.Status.OPTIMAL) { Console.WriteLine("The optimal objective is " + model.ObjVal); return; } if ((status != GRB.Status.INF_OR_UNBD) && (status != GRB.Status.INFEASIBLE)) { Console.WriteLine("Optimization was stopped with status " + status); return; } // Do IIS Console.WriteLine("The model is infeasible; computing IIS"); LinkedList <string> removed = new LinkedList <string>(); // Loop until we reduce to a model that can be solved while (true) { model.ComputeIIS(); Console.WriteLine("\nThe following constraint cannot be satisfied:"); foreach (GRBConstr c in model.GetConstrs()) { if (c.IISConstr == 1) { Console.WriteLine(c.ConstrName); // Remove a single constraint from the model removed.AddFirst(c.ConstrName); model.Remove(c); break; } } Console.WriteLine(); model.Optimize(); status = model.Status; if (status == GRB.Status.UNBOUNDED) { Console.WriteLine("The model cannot be solved " + "because it is unbounded"); return; } if (status == GRB.Status.OPTIMAL) { break; } if ((status != GRB.Status.INF_OR_UNBD) && (status != GRB.Status.INFEASIBLE)) { Console.WriteLine("Optimization was stopped with status " + status); return; } } Console.WriteLine("\nThe following constraints were removed " + "to get a feasible LP:"); foreach (string s in removed) { Console.Write(s + " "); } Console.WriteLine(); // Dispose of model and env model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
static void Main() { try { // Sample data // Sets of days and workers string[] Shifts = new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6", "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13", "Sun14" }; string[] Workers = new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" }; int nShifts = Shifts.Length; int nWorkers = Workers.Length; // Number of workers required for each shift double[] shiftRequirements = new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 }; // Amount each worker is paid to work one shift double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 }; // Worker availability: 0 if the worker is unavailable for a shift double[,] availability = new double[,] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; // Model GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); model.Set(GRB.StringAttr.ModelName, "assignment"); // Assignment variables: x[w][s] == 1 if worker w is assigned // to shift s. Since an assignment model always produces integer // solutions, we use continuous variables and solve as an LP. GRBVar[,] x = new GRBVar[nWorkers,nShifts]; for (int w = 0; w < nWorkers; ++w) { for (int s = 0; s < nShifts; ++s) { x[w,s] = model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS, Workers[w] + "." + Shifts[s]); } } // The objective is to minimize the total pay costs model.Set(GRB.IntAttr.ModelSense, 1); // Update model to integrate new variables model.Update(); // Constraint: assign exactly shiftRequirements[s] workers // to each shift s for (int s = 0; s < nShifts; ++s) { GRBLinExpr lhs = 0.0; for (int w = 0; w < nWorkers; ++w) lhs += x[w, s]; model.AddConstr(lhs == shiftRequirements[s], Shifts[s]); } // Optimize model.Optimize(); int status = model.Get(GRB.IntAttr.Status); if (status == GRB.Status.UNBOUNDED) { Console.WriteLine("The model cannot be solved " + "because it is unbounded"); return; } if (status == GRB.Status.OPTIMAL) { Console.WriteLine("The optimal objective is " + model.Get(GRB.DoubleAttr.ObjVal)); return; } if ((status != GRB.Status.INF_OR_UNBD) && (status != GRB.Status.INFEASIBLE)) { Console.WriteLine("Optimization was stopped with status " + status); return; } // Do IIS Console.WriteLine("The model is infeasible; computing IIS"); LinkedList<string> removed = new LinkedList<string>(); // Loop until we reduce to a model that can be solved while (true) { model.ComputeIIS(); Console.WriteLine("\nThe following constraint cannot be satisfied:"); foreach (GRBConstr c in model.GetConstrs()) { if (c.Get(GRB.IntAttr.IISConstr) == 1) { Console.WriteLine(c.Get(GRB.StringAttr.ConstrName)); // Remove a single constraint from the model removed.AddFirst(c.Get(GRB.StringAttr.ConstrName)); model.Remove(c); break; } } Console.WriteLine(); model.Optimize(); status = model.Get(GRB.IntAttr.Status); if (status == GRB.Status.UNBOUNDED) { Console.WriteLine("The model cannot be solved " + "because it is unbounded"); return; } if (status == GRB.Status.OPTIMAL) { break; } if ((status != GRB.Status.INF_OR_UNBD) && (status != GRB.Status.INFEASIBLE)) { Console.WriteLine("Optimization was stopped with status " + status); return; } } Console.WriteLine("\nThe following constraints were removed " + "to get a feasible LP:"); foreach (string s in removed) { Console.Write(s + " "); } Console.WriteLine(); // Dispose of model and env model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }