protected override void AddGRBConstrPowerBalance() { this.NodalPowerBalance = new GRBConstr[MyPowerSystem.Nodes.Count]; int load_shed_counter = 0; for (int i = 0; i < MyPowerSystem.Nodes.Count; i++) { Node node = MyPowerSystem.Nodes[i]; GRBLinExpr powerBalanceLHS = new GRBLinExpr(); foreach (GeneratingUnit gen in node.GeneratingUnits) { powerBalanceLHS.AddTerm(1, this.PGen[gen.Id]); } foreach (TransmissionLine tl in node.IncomingTransmissionLines) { powerBalanceLHS.AddTerm(+1, PFlow[PFlow_TLsIDs[tl.Id]]); //incoming power flow } foreach (TransmissionLine tl in node.OutgoingTransmissionLines) { powerBalanceLHS.AddTerm(-1, PFlow[PFlow_TLsIDs[tl.Id]]); //outgoing power flow } GRBLinExpr powerBalanceRHS = new GRBLinExpr(); powerBalanceRHS.AddConstant(node.TotalLoad * LoadBlock.LoadMultiplier); if (node.TotalLoad > 0) { powerBalanceRHS.AddTerm(-1, LoadShed[load_shed_counter]); load_shed_counter++; } this.NodalPowerBalance[i] = MyGrbModel.AddConstr(powerBalanceLHS, GRB.EQUAL, powerBalanceRHS, "PowerBalanceNode" + i); } }
private void btnModelo2_Click(object sender, EventArgs e) { GRBEnv Ambinte = new GRBEnv(); GRBModel Modelo = new GRBModel(Ambinte); Random Aleatorio = new Random(4); int m = 1600; GRBVar[,] X = new GRBVar[m, m]; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { X[i, j] = Modelo.AddVar(0, 1, Aleatorio.Next(1, 20), GRB.BINARY, "x_" + i.ToString() + "_" + j.ToString()); } } Modelo.ModelSense = GRB.MAXIMIZE; GRBLinExpr Expressao = new GRBLinExpr(); for (int i = 0; i < m; i++) { Expressao.Clear(); for (int j = 0; j < m; j++) { Expressao.AddTerm(1, X[i, j]); } Modelo.AddConstr(Expressao == 1, "Vendedor_" + i); } for (int j = 0; j < m; j++) { Expressao.Clear(); for (int i = 0; i < m; i++) { Expressao.AddTerm(1, X[i, j]); } Modelo.AddConstr(Expressao == 1, "Regiao_" + j); } Stopwatch Cronometro = new Stopwatch(); Cronometro.Start(); Modelo.Optimize(); Cronometro.Stop(); MessageBox.Show("O valor do lucro é: " + Modelo.ObjVal.ToString()); MessageBox.Show("O tempo para resolver foi de: " + Cronometro.ElapsedMilliseconds.ToString() + " ms"); MessageBox.Show("Se quiser saber a alocação que gera esse lucro é só me pagar"); //for (int j = 0; j < m; j++) //{ // for (int i = 0; i < m; i++) // { // if(X[i,j].X>0) // { // MessageBox.Show("O vendedor " + i + " é alocado para a região " + j); // } // } //} Modelo.Write("C:\\Teste\\Modelo2.lp"); }
private void CreateConstraintSessionsMustBeInDifferentTimeslots(int session1Index, int session2Index, int timeslotCount, int roomCount) { for (int t = 0; t < timeslotCount; t++) { GRBLinExpr expr = 0.0; for (int r = 0; r < roomCount; r++) { expr.AddTerm(1.0, _v[session1Index, r, t]); expr.AddTerm(1.0, _v[session2Index, r, t]); } _model.AddConstr(expr <= 1.0, $"x[{session1Index},*,{t}]_NotEqual_x[{session2Index},*,{t}]"); Console.WriteLine($"x[{session1Index},*,{t}]_NotEqual_x[{session2Index},*,{t}]"); } }
static void SolveDual(GRBEnv env, HashSet <string> nodes_set, List <Arc> arcs) { GRBModel dual = new GRBModel(env); Star forward_stars = new Star(); Star reverse_stars = new Star(); GetStars(nodes_set, arcs, forward_stars, reverse_stars); Dictionary <Arc, GRBVar> arc_traversed = new Dictionary <Arc, GRBVar>(); foreach (Arc a in arcs) { arc_traversed[a] = dual.AddVar(0, 1, a.length, GRB.CONTINUOUS, "arc_traversed." + a.source + "." + a.dest); } dual.Update(); Dictionary <string, GRBConstr> flow_balance = new Dictionary <string, GRBConstr>(); foreach (string node in nodes_set) { GRBLinExpr lhs = new GRBLinExpr(); List <Arc> forward_star = forward_stars[node]; List <Arc> reverse_star = reverse_stars[node]; Console.WriteLine("node " + node); Console.Write("Forward star: "); foreach (Arc a in forward_star) { Console.Write(a.dest + ' '); // lhs -= arc_traversed[a]; lhs.AddTerm(-1, arc_traversed[a]); } Console.Write("\nReverse star: "); foreach (Arc a in reverse_star) { Console.Write(a.source + ' '); lhs.AddTerm(1, arc_traversed[a]); } Console.WriteLine(""); flow_balance[node] = dual.AddConstr(lhs, 'E', 0, "flow_balance." + node); } dual.Update(); flow_balance[ORIGIN].Set(GRB.DoubleAttr.RHS, -1); flow_balance[DESTINATION].Set(GRB.DoubleAttr.RHS, 1); dual.Optimize(); foreach (var pair in arc_traversed) { Console.WriteLine("Arc {0}:{1} traversed = {2}", pair.Key.source, pair.Key.dest, pair.Value.Get(GRB.DoubleAttr.X)); } Console.WriteLine("length of shortest path = " + dual.Get(GRB.DoubleAttr.ObjVal)); dual.Dispose(); }
// Subtour elimination callback. Whenever a feasible solution is found, // find the smallest subtour, and add a subtour elimination // constraint if the tour doesn't visit every node. protected override void Callback() { try { if (where == GRB.Callback.MIPSOL) { // Found an integer feasible solution - does it visit every node? int n = vars.GetLength(0); int[] tour = findsubtour(GetSolution(vars)); if (tour.Length < n) { // Add subtour elimination constraint GRBLinExpr expr = 0; for (int i = 0; i < tour.Length; i++) { for (int j = i + 1; j < tour.Length; j++) { expr.AddTerm(1.0, vars[tour[i], tour[j]]); } } AddLazy(expr <= tour.Length - 1); } } } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); Console.WriteLine(e.StackTrace); } }
/// <summary> /// Cria todas as restrições relativas às horas regulares de trabalho disponíveis /// </summary> /// <param name="entrada">Instância de <see cref="EntradaViewModel"/> contendo os dados informados na planilha de dados</param> private void CriaRestricaoHE(EntradaViewModel entrada) { foreach (var diaSemana in Enum.GetValues(typeof(DiaDaSemana))) { var diaSemanaEnum = (DiaDaSemana)diaSemana; var expressaoLinear = new GRBLinExpr(); var cargaHorariaExtraDisponivelDiaria = entrada.CargaHorariaExtraDisponivel[diaSemanaEnum]; entrada.Produtos.ForEach(produto => { var taxaProducao = produto.GetTaxaUnidadeHora(); var variavelProduto = _varArray[produto.GetNomeVariavel(diaSemanaEnum, true)]; expressaoLinear.AddTerm(taxaProducao, variavelProduto); }); _grbModel.AddConstr( expressaoLinear, GRB.LESS_EQUAL, cargaHorariaExtraDisponivelDiaria, $"HorasExtrasDisponiveis[{diaSemana}]" ); } }
GRBLinExpr SumOfVars(GRBVar[] vars) { GRBLinExpr sum = 0.0; for (int person = 0; person < vars.Length; person++) { sum.AddTerm(1, vars[person]); } return(sum); }
public static GRBLinExpr Quicksum(this IEnumerable <GRBVar> varsToAdd) { GRBLinExpr expr = new GRBLinExpr(); foreach (var varToAdd in varsToAdd) { expr.AddTerm(1.0, varToAdd); } return(expr); }
private void CreateObjective(IEnumerable <MenuItem> items) { // Minimize the cost of the items that have been selected GRBLinExpr expr = 0.0; foreach (var item in items) { expr.AddTerm(item.Cost, _v[item.Id]); } _model.SetObjective(expr, GRB.MINIMIZE); }
private void AllVehiclesMustEndAtTheDepot() { for (int v = 0; v < _vehicles.Count; v++) { var vehicleEnd = new GRBLinExpr(); for (int s = 0; s < _vertices.Count; s++) { vehicleEnd.AddTerm(1.0, _vehicleTraverse[v][s][_vertices.Count - 1]); } _model.AddConstr(vehicleEnd, GRB.EQUAL, 1.0, "_AllVehiclesMustEndAtTheDepot"); } }
private void AllVehiclesMustStartFromTheDepot() { for (int v = 0; v < _vehicles.Count; v++) { var vehicleStart = new GRBLinExpr(); for (int e = 0; e < _vertices.Count; e++) { vehicleStart.AddTerm(1.0, _vehicleTraverse[v][0][e]); } _model.AddConstr(vehicleStart, GRB.EQUAL, 1.0, "_AllVehiclesMustStartFromTheDepot"); } }
public override bool SetObj(object solver, int Column, double Value) { GRBModel grbSolver = solver as GRBModel; if (grbSolver == null) { return(false); } GRBLinExpr exp = grbSolver.GetObjective() as GRBLinExpr; exp.AddTerm(Value, exp.GetVar(Column)); return(true); }
GRBLinExpr SumOfAllVars(GRBVar[,] vars) { GRBLinExpr sum = 0.0; for (int person = 0; person < vars.GetLength(0); person++) { for (int i = 0; i < vars.GetLength(1); i++) { sum.AddTerm(1, vars[person, i]); } } return(sum); }
private void CreateConstraints(double totalPrice, IEnumerable <MenuItem> items) { // Total price of items selected, must be exactly 15.05 GRBLinExpr expr = 0.0; foreach (var item in items) { expr.AddTerm(item.Price, _v[item.Id]); } _model.AddConstr(expr == totalPrice, $"Sum_Prices_Equal_{totalPrice}"); Console.WriteLine($"Sum_Prices_Equals_{totalPrice}"); _model.Update(); }
/// <summary> /// Cria função objetivo /// </summary> /// <param name="entrada">Instância de <see cref="EntradaViewModel"/> contendo os dados informados na planilha de dados</param> private void CriaFuncaoObjetivo(EntradaViewModel entrada) { //Cria objeto de expressão linear para podermos gerar uma expressão linear de forma dinâmica var expressaoObjetivo = new GRBLinExpr(); entrada.Produtos.ForEach(produto => { var custoHR = produto.CustoRegular; var custoHE = produto.CustoHoraExtra; foreach (var diaSemana in Enum.GetValues(typeof(DiaDaSemana))) { var diaSemanaEnum = (DiaDaSemana)diaSemana; var qtdeProdutoHR = _varArray[produto.GetNomeVariavel(diaSemanaEnum)]; expressaoObjetivo.AddTerm(custoHR, qtdeProdutoHR); var qtdeProdutoHE = _varArray[produto.GetNomeVariavel(diaSemanaEnum, true)]; expressaoObjetivo.AddTerm(custoHE, qtdeProdutoHE); } }); _grbModel.SetObjective(expressaoObjetivo, GRB.MINIMIZE); }
private void VehiclesLoadUpCapacity() { for (int v = 0; v < _vehicles.Count; v++) { var vehicleCapacity = new GRBLinExpr(); for (int s = 1; s <= _vertices.Count - 2; s++) { for (int e = 0; e < _vertices.Count; e++) { vehicleCapacity.AddTerm(_vertices[s].Demand, _vehicleTraverse[v][s][e]); } } _model.AddConstr(vehicleCapacity, GRB.LESS_EQUAL, _vehicles[v].Capacity, "_VehiclesLoadUpCapacity"); } }
private void EachCustomerMustBeVisitedOnce() { for (int s = 1; s <= _vertices.Count - 2; s++) { var customerVisit = new GRBLinExpr(); for (int v = 0; v < _vehicles.Count; v++) { for (int e = 0; e < _vertices.Count; e++) { customerVisit.AddTerm(1.0, _vehicleTraverse[v][s][e]); } } _model.AddConstr(customerVisit, GRB.EQUAL, 1.0, "_EachCustomerMustVisitedOnce"); } }
private void CreateObjective() { _cost = new GRBLinExpr(); for (int v = 0; v < _vehicles.Count; v++) { for (int s = 0; s < _vertices.Count; s++) { for (int e = 0; e < _vertices.Count; e++) { var distance = Helpers.CalculateDistance(_vertices[s], _vertices[e]); _cost.AddTerm(distance, _vehicleTraverse[v][s][e]); } } } _model.SetObjective(_cost, GRB.MINIMIZE); }
private void AddObjective(GRBModel model, GRBVar[,,] seated) { var expr = new GRBLinExpr(); for (int x = 0; x < Cinema.Width; x++) { for (int y = 0; y < Cinema.Height; y++) { for (int g = 0; g < Cinema.TotalNumberOfGroups; g++) { expr.AddTerm(Cinema.GroupSizes[g], seated[x, y, g]); } } } model.SetObjective(expr, GRB.MAXIMIZE); }
// availabilities of instructors GRBLinExpr SumProduct(GRBVar[,] vars, Instructor[] instructors) { GRBLinExpr result = 0.0; for (int person = 0; person < vars.GetLength(0); person++) { for (int i = 0; i < vars.GetLength(1); i++) { double coefficient = 0.0; if (instructors[person].Availability[i] == false) { coefficient = Scores.SupervisorNotAvailable; } result.AddTerm(coefficient, vars[person, i]); } } return(result); }
//model y=x1+x2 static public void AddCons2Vars(GRBModel m, List <GRBVar> pickvars) { double[,] coeff = new double[4, 4] { { 1, 1, -1, 0 }, { 1, -1, 1, 0 }, { -1, 1, 1, 0 }, { -1, -1, -1, 2 } }; GRBLinExpr lincon = new GRBLinExpr(); int i = 0, j = 0; for (i = 0; i < 4; i++) { lincon.Clear(); for (j = 0; j < 3; j++) { lincon.AddTerm(coeff[i, j], pickvars[j]); } lincon.AddConstant(coeff[i, 3]); m.AddConstr(lincon >= 0, "conslin2"); } }
protected void AddGRBConstrDCPowerFlow() { this.DCPowerFlow = new GRBConstr[MyPowerSystem.TransmissionLines.Count]; for (int t = 0; t < MyPowerSystem.TransmissionLines.Count; t++) { TransmissionLine tl = MyPowerSystem.TransmissionLines[t]; GRBLinExpr powerFlowLHS = new GRBLinExpr(); powerFlowLHS.AddTerm(1, this.PFlow[t]); GRBLinExpr powerFlowRHS = new GRBLinExpr(); powerFlowRHS.AddTerm(+tl.SusceptanceMho, this.BusAngle[tl.NodeFromID]); powerFlowRHS.AddTerm(-tl.SusceptanceMho, this.BusAngle[tl.NodeToID]); this.DCPowerFlow[t] = MyGrbModel.AddConstr(powerFlowLHS, GRB.EQUAL, powerFlowRHS, "PowerFlowTL" + t); } }
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); } }
private void RunOptimization() { GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); List <List <GRBVar> > varsFromElements = new List <List <GRBVar> >(); //Variables: LoD for each element with their respective utility value for (var i = 0; i < _model.Elements.Count; i++) { var element = _model.Elements[i]; var allLoads = CalcUtil.GetAllCognitiveLoadsForElement(element); List <GRBVar> varsCurrentElement = new List <GRBVar>(); for (var j = 0; j < allLoads.Count; j++) { //Fix element and current LoD if flag is set, i.e. lower and upper bound are 1.0 var lowerBound = element.FixateElement && (j + 1) == element.CurrentLevelOfDetail ? 1.0 : 0.0; //Omit element if omit-flag is set, ie lower and upper bound are 0.0 var upperBound = !element.OmitElement ? 1.0 : 0.0; //Disable changing the LoD by more than 1, ie set upper bound to 0.0 (except if element is fixated) var absLoDDifference = Math.Abs(element.CurrentLevelOfDetail - 1 - j); if (lowerBound < 1.0 && absLoDDifference > 1) { upperBound = 0.0; } GRBVar eLod = model.AddVar(lowerBound, upperBound, CalcUtil.GetObjectiveForElement(element, j + 1, _model), GRB.BINARY, "e_" + i + "_lod_" + j); varsCurrentElement.Add(eLod); } varsFromElements.Add(varsCurrentElement); } //Constraint: overall cognitive load must be below user's cognitive capacity GRBLinExpr lhs = 0.0; for (var i = 0; i < _model.Elements.Count; i++) { var element = _model.Elements[i]; var allLoads = CalcUtil.GetAllCognitiveLoadsForElement(element); for (var j = 0; j < allLoads.Count; j++) { var load = allLoads[j] + CalcUtil.GetTimeDependentCognitiveLoadOnsetPenalty(element, _model); lhs.AddTerm(load, varsFromElements[i][j]); } } model.AddConstr(lhs, GRB.LESS_EQUAL, _model.UserModel.CognitiveCapacity, "c_cog"); //Constraint: constraints to number of available slots lhs = 0.0; for (var i = 0; i < _model.Elements.Count; i++) { for (var j = 0; j < _model.Elements[i].MaxLevelOfDetail; j++) { lhs.AddTerm(1.0, varsFromElements[i][j]); } } model.AddConstr(lhs, GRB.GREATER_EQUAL, _model.NumMinPlacementSlots, "c_slots_min"); model.AddConstr(lhs, GRB.LESS_EQUAL, _model.NumMaxPlacementSlots, "c_slots_max"); //Constraint: only 1 LoD per Element for (var i = 0; i < _model.Elements.Count; i++) { lhs = 0.0; for (var j = 0; j < _model.Elements[i].MaxLevelOfDetail; j++) { lhs.AddTerm(1.0, varsFromElements[i][j]); } model.AddConstr(lhs, GRB.LESS_EQUAL, 1.0, "c" + i + "_lod"); } model.ModelSense = GRB.MAXIMIZE; model.Optimize(); var status = model.Status; _model.IsFeasible = !(status == GRB.Status.INF_OR_UNBD || status == GRB.Status.INFEASIBLE || status == GRB.Status.UNBOUNDED); if (_model.IsFeasible) { UpdateModels(model, varsFromElements); StoreAllSolutions(model); } else { Console.WriteLine(@"The model cannot be solved because it is infeasible or unbounded"); } model.Dispose(); env.Dispose(); }
static void Main() { try { // Nutrition guidelines, based on // USDA Dietary Guidelines for Americans, 2005 // http://www.health.gov/DietaryGuidelines/dga2005/ string[] Categories = new string[] { "calories", "protein", "fat", "sodium" }; int nCategories = Categories.Length; double[] minNutrition = new double[] { 1800, 91, 0, 0 }; double[] maxNutrition = new double[] { 2200, GRB.INFINITY, 65, 1779 }; // Set of foods string[] Foods = new string[] { "hamburger", "chicken", "hot dog", "fries", "macaroni", "pizza", "salad", "milk", "ice cream" }; int nFoods = Foods.Length; double[] cost = new double[] { 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59 }; // Nutrition values for the foods double[,] nutritionValues = new double[, ] { { 410, 24, 26, 730 }, // hamburger { 420, 32, 10, 1190 }, // chicken { 560, 20, 32, 1800 }, // hot dog { 380, 4, 19, 270 }, // fries { 320, 12, 10, 930 }, // macaroni { 320, 15, 12, 820 }, // pizza { 320, 31, 12, 1230 }, // salad { 100, 8, 2.5, 125 }, // milk { 330, 8, 10, 180 } // ice cream }; // Model GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); model.ModelName = "diet"; // Create decision variables for the nutrition information, // which we limit via bounds GRBVar[] nutrition = new GRBVar[nCategories]; for (int i = 0; i < nCategories; ++i) { nutrition[i] = model.AddVar(minNutrition[i], maxNutrition[i], 0, GRB.CONTINUOUS, Categories[i]); } // Create decision variables for the foods to buy GRBVar[] buy = new GRBVar[nFoods]; for (int j = 0; j < nFoods; ++j) { buy[j] = model.AddVar(0, GRB.INFINITY, cost[j], GRB.CONTINUOUS, Foods[j]); } // The objective is to minimize the costs model.ModelSense = GRB.MINIMIZE; // Nutrition constraints for (int i = 0; i < nCategories; ++i) { GRBLinExpr ntot = 0.0; for (int j = 0; j < nFoods; ++j) { ntot.AddTerm(nutritionValues[j, i], buy[j]); } model.AddConstr(ntot == nutrition[i], Categories[i]); } // Solve model.Optimize(); PrintSolution(model, buy, nutrition); Console.WriteLine("\nAdding constraint: at most 6 servings of dairy"); model.AddConstr(buy[7] + buy[8] <= 6.0, "limit_dairy"); // Solve model.Optimize(); PrintSolution(model, buy, nutrition); // Dispose of model and env model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
static void Main(string[] args) { //for (int i = 0; i < 26; i++) // Console.Write(3*i + ","); //Console.ReadKey(); GRBEnv env = new GRBEnv("Kreyium.log"); int round = 892; GRBModel model = new GRBModel(env); int[] pos = new int[7] { 65, 92, 161, 176, 242, 287, 415 }; //7个输出位置 GRBVar[] s = model.AddVars(544, GRB.BINARY); for (int i = 0; i < 544; i++) { s[i].VarName = "var" + i.ToString(); //288个寄存器,命名为var0-var288 } char[] FlagS = new char[544]; //288个寄存器的Flag GRBVar[] NewVars = model.AddVars(34 * round, GRB.BINARY); for (int i = 0; i < NewVars.Length; i++) { NewVars[i].VarName = "y" + i.ToString(); //每过一次更新许需要加30个变量,总共为30*round,命名为y0-y300*round } char[] FlagNewVars = new char[34 * round]; //新加变量的Flag GRBVar[] IV = model.AddVars(128, GRB.BINARY); for (int i = 0; i < 128; i++) { IV[i].VarName = "IV" + i.ToString();//128个IV变量 } GRBVar[] Key = model.AddVars(128, GRB.BINARY); for (int i = 0; i < 128; i++) { Key[i].VarName = "Key" + i.ToString();//128个Key变量 } // List<uint> cube = new List<uint>() { 1, 3, 5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 26, 28, 31, 33, 35, 37, 39, 41, 43, 46, // 48, 50, 52, 54, 61, 63, 65, 67, 69, 71, 73, 76, 78, 80, 82, 84, 86, 88, 90, 92, 95, // 97, 99, 101, 103, 106, 108, 110, 112, 114, 116, 118, 120, 125, 127};//cube变量 //dcc19 // List<uint> cube = new List<uint>() { 0,2,4,6,8,10,12,15,17,19,21,24,26,28,30,32,34,36,39,41,43,45,47,49,52,54,56,58, // 60,62,67,69,71,73,75,80,82,84,86,89,91,93,95,97,99,102,104,106,108,110,112,114, // 117,119,121,123};//cube变量 //List<uint> cube = new List<uint>() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 43, 45, 46, 47, 48, 49, 50, 51, 52, 54, 56, 59, 61, 63, 65, 67, 69, 71, 74, 76, 78, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127}; //dis880 try 892 //List<uint> cube =new List<uint>(){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,29,31,33,35,37,39,41,44,46,48,50,52,54,56,59,61,63,65,67,69,72,74,76,78,80,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}; List <uint> cube = new List <uint>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 37, 39, 41, 43, 44, 45, 46, 47, 48, 49, 50, 52, 54, 57, 59, 61, 63, 65, 67, 69, 72, 74, 76, 78, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 }; List <int> keyset = new List <int>() { }; for (int i = 0; i < 128; i++) { keyset.Add(i); } for (int i = 0; i < cube.Count(); i++) { Console.Write(cube[i] + " "); } Console.WriteLine(); List <UInt32> Noncube = new List <uint>() { 0x0, 0x0, 0x0, 0x0 }; GRBLinExpr ChooseKey = new GRBLinExpr();//超多项式中可能含有的密钥变量集合 int VarNumber = 0; initial(model, s, FlagS, cube, Noncube, keyset, ChooseKey, IV, Key);//初始化设置 for (int i = 1; i <= round; i++) { Triviumcore(model, s, FlagS, NewVars, FlagNewVars, ref VarNumber); } for (int i = 0; i < 544; i++) { if (!pos.Contains(i)) { model.AddConstr(s[i] == 0, "a" + i.ToString()); } } GRBLinExpr expr = new GRBLinExpr(); for (int i = 0; i < 7; i++) { expr.AddTerm(1.0, s[pos[i]]); } model.AddConstr(expr == 1, "t1"); model.Optimize(); if (model.SolCount > 0) { Console.WriteLine(model.ObjVal); } else { Console.WriteLine("************************************"); Console.WriteLine("Model is infeasible!!!"); Console.WriteLine("************************************"); } model.Dispose(); env.Dispose(); Console.ReadKey(); }
private void CreateConstraints(IEnumerable <Session> sessions, IEnumerable <Room> rooms, int timeslotCount) { int sessionCount = sessions.Count(); int roomCount = rooms.Count(); // Each room can have no more than 1 session per timeslot for (int r = 0; r < roomCount; r++) { for (int t = 0; t < timeslotCount; t++) { GRBLinExpr expr = 0.0; for (int s = 0; s < sessionCount; s++) { expr.AddTerm(1.0, _v[s, r, t]); } _model.AddConstr(expr <= 1.0, $"x[*,{r},{t}]_LessEqual_1"); Console.WriteLine($"x[*,{r},{t}]_LessEqual_1"); } } // Each session must be assigned to exactly 1 room/timeslot combination for (int s = 0; s < sessionCount; s++) { GRBLinExpr expr = 0.0; for (int r = 0; r < roomCount; r++) { for (int t = 0; t < timeslotCount; t++) { expr.AddTerm(1.0, _v[s, r, t]); } } _model.AddConstr(expr == 1.0, $"x[{s},*,*]_Equals_1"); Console.WriteLine($"x[{s},*,*]_Equals_1"); } // No room can be assigned to a session in a timeslot // during which it is not available foreach (var room in rooms) { int roomIndex = _roomIds.IndexOfValue(room.Id).Value; foreach (var uts in room.UnavailableForTimeslots) { int utsi = _timeslotIds.IndexOfValue(uts).Value; GRBLinExpr expr = 0.0; for (int s = 0; s < sessionCount; s++) { expr.AddTerm(1.0, _v[s, roomIndex, utsi]); } _model.AddConstr(expr == 0.0, $"x[*,{roomIndex},{utsi}]_Equals_0"); Console.WriteLine($"x[*,{roomIndex},{utsi}]_Equals_0"); } } // Sessions cannot be assigned to a timeslot during which // any presenter is unavailable foreach (var session in sessions) { int sessionIndex = _sessionIds.IndexOfValue(session.Id).Value; List <int> unavailableTimeslotIndexes = new List <int>(); foreach (var presenter in session.Presenters) { foreach (var unavailableTimeslot in presenter.UnavailableForTimeslots) { int timeslotIndex = _timeslotIds.IndexOfValue(unavailableTimeslot).Value; unavailableTimeslotIndexes.Add(timeslotIndex); } } if (unavailableTimeslotIndexes.Any()) { GRBLinExpr expr = 0.0; foreach (var utsi in unavailableTimeslotIndexes.Distinct()) { for (int r = 0; r < roomCount; r++) { expr.AddTerm(1.0, _v[sessionIndex, r, utsi]); } } _model.AddConstr(expr == 0, $"PresentersUnavailable_Session[{sessionIndex}"); Console.WriteLine($"PresentersUnavailable_Session[{sessionIndex}"); } } // A speaker can only be involved with 1 session per timeslot var speakerIds = sessions.SelectMany(s => s.Presenters.Select(p => p.Id)).Distinct(); foreach (int speakerId in speakerIds) { var pIds = sessions.Where(s => s.Presenters.Select(p => p.Id).Contains(speakerId)).Select(s => s.Id).ToArray(); for (int i = 0; i < pIds.Length - 1; i++) { for (int j = i + 1; j < pIds.Length; j++) { int session1Index = _sessionIds.IndexOfValue(pIds[i]).Value; int session2Index = _sessionIds.IndexOfValue(pIds[j]).Value; CreateConstraintSessionsMustBeInDifferentTimeslots(session1Index, session2Index, timeslotCount, roomCount); } } } // The value of s[i] must be equal to the index of the timeslot // that session i is assigned to for (int i = 0; i < sessionCount; i++) { GRBLinExpr expr = 0.0; for (int t = 0; t < timeslotCount; t++) { for (int r = 0; r < roomCount; r++) { expr.AddTerm(t, _v[i, r, t]); } } _model.AddConstr(_s[i] == expr, $"s[{i}]_Equals_Timeslot_x[{i},*,*]"); Console.WriteLine($"s[{i}]_Equals_Timeslot"); } // All sessions with dependencies on session S must be scheduled // later (with a higher index value) than session S foreach (var session in sessions) { int sessionIndex = _sessionIds.IndexOfValue(session.Id).Value; foreach (var dependentSession in session.Dependencies) { int dependentSessionIndex = _sessionIds.IndexOfValue(dependentSession.Id).Value; _model.AddConstr((_s[dependentSessionIndex] + 1) <= _s[sessionIndex], $"s[{dependentSessionIndex}]_GreaterThan_s[{sessionIndex}]"); Console.WriteLine($"s[{dependentSessionIndex}]_GreaterThan_s[{sessionIndex}]"); } } _model.Update(); }
public static Graph RunSolver(Graph graph) { GRBEnv env = new GRBEnv(); env.Set(GRB.IntParam.OutputFlag, 0); env.Set(GRB.IntParam.LogToConsole, 0); env.Set(GRB.IntParam.Presolve, 2); env.Set(GRB.DoubleParam.Heuristics, 0.0); GRBModel model = new GRBModel(env); GRBVar[] variables = new GRBVar[graph.NumberOfEdges]; model.SetCallback(new LPSolverCallback()); Dictionary<Edge, GRBVar> edgeVars = new Dictionary<Edge, GRBVar>(); // Add variables to the LP model for (int i = 0; i < graph.NumberOfEdges; i++) { variables[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "x_" + i); edgeVars.Add(graph.Edges[i], variables[i]); } model.Update(); // Add constraints to the LP model Console.Write("\rRunning LP. Creating constraints...\r"); //var nonTerminals = graph.Vertices.Except(graph.Terminals).ToList(); ulong conNr = 0; //var terminalCombinations = new List<List<Vertex>>(); // Assume, without loss of generality, that Terminals[0] is the root, and thus is always included int rootNr = 1; foreach (var rootTerminal in graph.Terminals) //var rootTerminal = graph.Terminals[0]; { Console.Write("\rRunning LP. Creating constraints... {0}/{1}\r", rootNr, graph.Terminals.Count); foreach (var combination in GetBFS(graph, rootTerminal)) { var nodes = combination.ToList(); //new HashSet<Vertex>(combination); if (nodes.Count == graph.NumberOfVertices || graph.Terminals.All(nodes.Contains)) continue; //Debug.WriteLine("Combination: {0}", string.Join(" ", nodes)); //for (int i = 1; i <= nodes.Count; i++) { var edges = nodes//.Take(i) .SelectMany(graph.GetEdgesForVertex) .Distinct() .Where(x => x.WhereOne(y => !nodes.Contains(y))); GRBLinExpr expression = 0; foreach (var edge in edges) expression.AddTerm(1, edgeVars[edge]); model.AddConstr(expression >= 1.0, "subset_" + conNr); conNr++; if (conNr % 100000 == 0) { //model = model.Presolve(); //Pre-solve the model every 1000 constraints. int constrBefore = model.GetConstrs().Length, varsBefore = model.GetVars().Length; Debug.WriteLine("Presolve called."); var presolved = model.Presolve(); Debug.WriteLine("Model has {0} constraints, {1} variables. Presolve has {2} constraints, {3} variables", constrBefore, varsBefore, presolved.GetConstrs().Length, presolved.GetVars().Length); } } } //Debug.WriteLine(" "); //Debug.WriteLine(" "); rootNr++; } //terminalCombinations.Add(new List<Vertex>(new[] { graph.Terminals[0] })); //for (int j = 1; j < graph.Terminals.Count - 1; j++) // terminalCombinations.AddRange(new Combinations<Vertex>(graph.Terminals.Skip(1), j).Select(combination => combination.Union(new[] { graph.Terminals[0] }).ToList())); //long nonTerminalSetsDone = 0; //long nonTerminalSets = 0; //for (int i = 0; i <= nonTerminals.Count; i++) // nonTerminalSets += Combinations<Vertex>.NumberOfCombinations(nonTerminals.Count, i); //for (int i = 0; i <= nonTerminals.Count; i++) //{ // foreach (var nonTerminalSet in new Combinations<Vertex>(nonTerminals, i)) // { // foreach (var nodes in (from a in terminalCombinations // select new HashSet<Vertex>(a.Union(nonTerminalSet)))) // { // var edges = nodes.SelectMany(graph.GetEdgesForVertex) // .Distinct() // .Where(x => x.WhereOne(y => !nodes.Contains(y))); // GRBLinExpr expression = 0; // foreach (var edge in edges) // expression.AddTerm(1, edgeVars[edge]); // model.AddConstr(expression >= 1.0, "subset_" + conNr); // conNr++; // } // nonTerminalSetsDone++; // if (nonTerminalSetsDone % 100 == 0) // Console.Write("\rRunning LP. Creating constraints... {0}/{1} ({2:0.000}%)\r", nonTerminalSetsDone, nonTerminalSets, nonTerminalSetsDone * 100.0 / nonTerminalSets); // } //} // Solve the LP model Console.Write("\rRunning LP. Creating objective & updating... \r"); GRBLinExpr objective = new GRBLinExpr(); for (int i = 0; i < graph.NumberOfEdges; i++) objective.AddTerm(graph.Edges[i].Cost, variables[i]); model.SetObjective(objective, GRB.MINIMIZE); Console.Write("\rRunning LP. Tuning... \r"); model.Tune(); Debug.WriteLine("Presolve called."); model.Presolve(); Console.Write("\rRunning LP. Solving... \r"); Debug.WriteLine("Optimize called."); model.Optimize(); Graph solution = graph.Clone(); HashSet<Edge> includedEdges = new HashSet<Edge>(); for (int i = 0; i < solution.NumberOfEdges; i++) { var value = variables[i].Get(GRB.DoubleAttr.X); if (value == 1) includedEdges.Add(solution.Edges[i]); } foreach (var edge in solution.Edges.ToList()) if (!includedEdges.Contains(edge)) solution.RemoveEdge(edge); Console.Write("\r \r"); return solution; }
static void Main() { try { // Warehouse demand in thousands of units double[] Demand = new double[] { 15, 18, 14, 20 }; // Plant capacity in thousands of units double[] Capacity = new double[] { 20, 22, 17, 19, 18 }; // Fixed costs for each plant double[] FixedCosts = new double[] { 12000, 15000, 17000, 13000, 16000 }; // Transportation costs per thousand units double[,] TransCosts = new double[, ] { { 4000, 2000, 3000, 2500, 4500 }, { 2500, 2600, 3400, 3000, 4000 }, { 1200, 1800, 2600, 4100, 3000 }, { 2200, 2600, 3100, 3700, 3200 } }; // Number of plants and warehouses int nPlants = Capacity.Length; int nWarehouses = Demand.Length; // Model GRBEnv env = new GRBEnv(); GRBModel model = new GRBModel(env); model.ModelName = "facility"; // Plant open decision variables: open[p] == 1 if plant p is open. GRBVar[] open = new GRBVar[nPlants]; for (int p = 0; p < nPlants; ++p) { open[p] = model.AddVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p); } // Transportation decision variables: how much to transport from // a plant p to a warehouse w GRBVar[,] transport = new GRBVar[nWarehouses, nPlants]; for (int w = 0; w < nWarehouses; ++w) { for (int p = 0; p < nPlants; ++p) { transport[w, p] = model.AddVar(0, GRB.INFINITY, TransCosts[w, p], GRB.CONTINUOUS, "Trans" + p + "." + w); } } // The objective is to minimize the total fixed and variable costs model.ModelSense = GRB.MINIMIZE; // Production constraints // Note that the right-hand limit sets the production to zero if // the plant is closed for (int p = 0; p < nPlants; ++p) { GRBLinExpr ptot = 0.0; for (int w = 0; w < nWarehouses; ++w) { ptot.AddTerm(1.0, transport[w, p]); } model.AddConstr(ptot <= Capacity[p] * open[p], "Capacity" + p); } // Demand constraints for (int w = 0; w < nWarehouses; ++w) { GRBLinExpr dtot = 0.0; for (int p = 0; p < nPlants; ++p) { dtot.AddTerm(1.0, transport[w, p]); } model.AddConstr(dtot == Demand[w], "Demand" + w); } // Guess at the starting point: close the plant with the highest // fixed costs; open all others // First, open all plants for (int p = 0; p < nPlants; ++p) { open[p].Start = 1.0; } // Now close the plant with the highest fixed cost Console.WriteLine("Initial guess:"); double maxFixed = -GRB.INFINITY; for (int p = 0; p < nPlants; ++p) { if (FixedCosts[p] > maxFixed) { maxFixed = FixedCosts[p]; } } for (int p = 0; p < nPlants; ++p) { if (FixedCosts[p] == maxFixed) { open[p].Start = 0.0; Console.WriteLine("Closing plant " + p + "\n"); break; } } // Use barrier to solve root relaxation model.Parameters.Method = GRB.METHOD_BARRIER; // Solve model.Optimize(); // Print solution Console.WriteLine("\nTOTAL COSTS: " + model.ObjVal); Console.WriteLine("SOLUTION:"); for (int p = 0; p < nPlants; ++p) { if (open[p].X > 0.99) { Console.WriteLine("Plant " + p + " open:"); for (int w = 0; w < nWarehouses; ++w) { if (transport[w, p].X > 0.0001) { Console.WriteLine(" Transport " + transport[w, p].X + " units to warehouse " + w); } } } else { Console.WriteLine("Plant " + p + " closed!"); } } // Dispose of model and env model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
static void Main(string[] args) { GRBEnv env = new GRBEnv("TJLinearCharacter.log"); GRBModel model = new GRBModel(env); //declare the iv variables and key variables GRBVar[] keyvar = model.AddVars(80, GRB.BINARY); //declare the assignment variables of key variables GRBVar[] ivvar = model.AddVars(80, GRB.BINARY); //declare the assignment variables of iv variables GRBVar[] kvf = model.AddVars(80, GRB.BINARY); //declare the flag variables of key variables GRBVar[] vvf = model.AddVars(80, GRB.BINARY); //declare the flag variables of iv variables GRBVar[] Uvar = model.AddVars(8000, GRB.BINARY); //interval assignment variables used to long XOR expression into short ones y=k1+k2+k3+k4--> u1=k1+k2, u2=k3+k4, y=u1+u2 GRBVar[] Vvar = model.AddVars(8000, GRB.INTEGER); //interval variables GRBVar[] Wvar = model.AddVars(8000, GRB.BINARY); //interval variables GRBVar[] UFvar = model.AddVars(8000, GRB.BINARY); //UFvar[i] is the flag variables corresponding to Uvar[i] GRBVar[] NUvar = model.AddVars(8000, GRB.BINARY); //NUvar[i]= 1-Uvar[i] GRBVar[] NUFvar = model.AddVars(8000, GRB.BINARY); //NUFvar[i]= 1-UFvar[i] GRBVar[] Consvar = model.AddVars(8000, GRB.BINARY); //constant variables GRBVar[] bvar = model.AddVars(8000, GRB.BINARY); //b variables int i, j, k; int loc0 = 0, loc1 = 0, loc2 = 0, loc3 = 0, loc4 = 0, locb = 0; int locf = 0; int con = 0; // name all the variables used in this MILP model for (i = 0; i < keyvar.Length; i++) { keyvar[i].VarName = "k" + i.ToString(); ivvar[i].VarName = "v" + i.ToString(); kvf[i].VarName = "kf" + i.ToString(); vvf[i].VarName = "vf" + i.ToString(); } for (i = 0; i < Uvar.Length; i++) { Uvar[i].VarName = "U" + i.ToString(); Wvar[i].VarName = "W" + i.ToString(); UFvar[i].VarName = "UF" + i.ToString(); Vvar[i].VarName = "V" + i.ToString(); NUvar[i].VarName = "NU" + i.ToString(); NUFvar[i].VarName = "NUF" + i.ToString(); bvar[i].VarName = "b" + i.ToString(); Consvar[i].VarName = "cons" + i.ToString(); } UInt32[, ,] ConS = new UInt32[1000, 200, 6];//used to store the conditions derived to control the propagation of difference int[] conlen = new int[1000]; int[] consflag = new int[1000]; int[] rec_loc1 = new int[1000]; int[] rec_locf = new int[1000]; //the number of the conditions int consnum = 652; int[] loc = new int[2]; int[] locw = new int[1]; int[] condiassig = new int[consnum]; int[] condiflag = new int[consnum]; GRBLinExpr Tar = new GRBLinExpr();//declare the target linear expression, which is used as the objective function List <int> indlist = new List <int>() { }; List <GRBVar> Varlist = new List <GRBVar>() { }; List <GRBVar> VarlistCopy = new List <GRBVar>() { }; List <GRBVar> VarFlaglist = new List <GRBVar>() { }; //List<GRBVar> VarFlaglistCopy = new List<GRBVar>() { }; StreamWriter sw = new StreamWriter("FinalCons.txt"); //the index of cube variables List <int> cube = new List <int>() { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78 }; //set the state of cube variables to \delta for (i = 0; i < cube.Count; i++) { model.AddConstr(vvf[cube[i]] == 1, "iniiv" + (cube[i]).ToString()); } //set the contraints between an assigment variable and the corresponding flag variable for (i = 0; i < 80; i++) { model.AddConstr(keyvar[i] <= 1 - kvf[i], "keyflagrel"); model.AddConstr(ivvar[i] <= 1 - vvf[i], "ivflagrel"); } model.Update(); //read the derived constraints from the file ReadCondition(ConS, conlen, consflag); Console.Write("ReadConditionDone\n"); //model each condition for (i = 0; i < consnum; i++) { loc[0] = loc1; loc[1] = locf; VarFlaglist.Clear(); Varlist.Clear(); //linearize a condition and return a list of involved variables. //In this condition, for condition f, it would linearize it and would return the assignment/flag variable of each monomial in f; //In paticular, Uvar[0],Uvar[1],...,Uvar[m-1] are the assignment variables of the linearized monomials //UFvar[0],UFvar[1],...,UFvar[m-1] are the flag variables of the linearized monomials //For eaxmple, for a condition f=k1+k2*k3+k4, it can be linearized as f=u1+u2+u3 where u2=k2k3. //Then, Varlist[0],Varlist[1],Varlist[2] are assignment variables of u1,u2,u3 //and VarFlaglist[0],VarFlaglist[1],...,VarFlaglist[2] are the flag variables of u1,u2,u3 Varlist = LinearConstrain(model, Uvar, UFvar, ConS, conlen, i, keyvar, ivvar, loc, kvf, vvf, Wvar, locw, VarFlaglist); loc1 = loc[0]; locf = loc[1]; //here a condition f is linearized and so it is the XOR of several variables. //in the following, we would determine the assigment varible and flag variable of f // and we denote the assigment variable and flag variable of f by f_av and f_fv respectively for short. //The target expression 'Tar' is determined according to the assigment variable and flag variable of each condition f //In particular, Tar= sum(f in Conset) f_av +(-10000)*f_fv, where Conset is the set of conditions. //If the size of f is 1(excluding the constant), namely f consists of only one variable, then we do not need extra operations. if (Varlist.Count == 1) { //if consflag[i]=1, then it means that there is a constant 1 in f. //In this case, we add (-1.0*f_av) to Tar and increase con by 1 which is added to Tar in the end. if (consflag[i] == 1) { Tar.AddTerm(-1.0, Varlist[0]); con++; } else { Tar.AddTerm(1.0, Varlist[0]); } //add -10000*f_fv to Tar Tar.AddTerm(-10000, VarFlaglist[0]); rec_loc1[i] = loc1; rec_locf[i] = locf; } //If f is the XOR of two variables(assumin that f=u1+u2+c), where c is a constant in {0,1}. //then we shoule calclate f_av and f_fv according to (u1_av, u2_av) and (u1_fv, u2_fv). if (Varlist.Count == 2) { VarlistCopy.Clear(); GRBVar[] VarFlaglistCopy = new GRBVar[3]; GRBVar[] Vartemplist = new GRBVar[4]; //copy Varlist/VarFlaglist to VarlistCopy/VarFlaglistCopy for (j = 0; j < Varlist.Count(); j++) { VarlistCopy.Add(Varlist[j]); VarFlaglistCopy[j] = VarFlaglist[j]; } VarlistCopy.Add(Uvar[loc1]); //model u1_av+u2_av. Here, VarlistCopy[0]and VarlistCoyp[1] are u1_av and u2_av respectively. AddCons2Vars(model, VarlistCopy); //model u1_av+u2_av+c. if consflag[i]=1, then c is 1. In this case, we add an constant variable Consvar[loc0] to the model //and model u1_av+u2_av+c. if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; //Console.WriteLine("*****\n" + loc1 + "\n******\n" + loc0 + "\n*****\n"); loc1++; AddCons2Vars(model, VarlistCopy); } //until now, Uvar[loc1] is corresponding to beta_d in Proposition 2 of our paper. //Then, we shall show how to obtain the final assignment/flag variable of f. //UF flip the variables model.AddConstr(NUvar[loc3++] == 1 - VarFlaglist[0], "Flip1" + (loc3).ToString()); model.AddConstr(NUvar[loc3++] == 1 - VarFlaglist[1], "Flip2" + (loc3).ToString()); VarFlaglistCopy[0] = NUvar[loc3 - 1]; VarFlaglistCopy[1] = VarFlaglist[0]; //Vvar[loc2++]=min(1 - VarFlaglist[1], VarFlaglist[0]). Vvar[loc2] corresponds to T_j in Proposition 2. model.AddGenConstrMin(Vvar[loc2++], VarFlaglistCopy, 1000, "FlagTransOxr1" + loc2.ToString()); VarFlaglistCopy[0] = NUvar[loc3 - 2]; VarFlaglistCopy[1] = VarFlaglist[1]; //Vvar[loc2++]=min(1 - VarFlaglist[0], VarFlaglist[1]). Vvar[loc2] corresponds to T_j in Proposition 2. model.AddGenConstrMin(Vvar[loc2++], VarFlaglistCopy, 1000, "FlagTransOxr2" + loc2.ToString()); //UFvar[loc1]=Vvar[loc2-1]+Vvar[loc2-2], UFvar[loc1] is the flag variable of f // model.AddConstr(UFvar[loc1] == Vvar[loc2 - 1] + Vvar[loc2 - 2], "FlagTransOxr3" + loc2.ToString()); for (j = 0; j < Varlist.Count; j++) { Vartemplist[j] = Vvar[loc2 - 1 - j]; } //UFvar[locf]=max(Vvar[loc2],Vvar[loc2-1],...,). is equivalent to UFvar[locf]= Vvar[loc2]+Vvar[loc2-1]+...+ //since only one of Vvar[loc2],Vvar[loc2-1],..., is equal to 1. //UFvar[locf] is the flag variable of f, corresponding to F_d in Proposition 2. model.AddGenConstrMax(UFvar[locf], Vartemplist, 0, "FlagTransXor-2" + loc2.ToString()); //NUFvar[loc4] =1-UFvar[loc1] and increase loc4 by 1. NUFvar[loc4] corresponds to 1-F_d in Proposition 2. model.AddConstr(NUFvar[loc4++] == 1 - UFvar[locf], "Flip3" + loc4.ToString()); //max(u1_fv,u2_fv). bvar[locb] corresponds to b_d in Proposition 2. VarFlaglistCopy[0] = VarFlaglist[0]; VarFlaglistCopy[1] = VarFlaglist[1]; model.AddGenConstrMax(bvar[locb++], VarFlaglistCopy, 0, "maxfv" + locb.ToString()); //NUFvar[loc4] =1-bvar[locb++] and increase loc4 by 1. NUFvar[loc4] corresponds to 1-b_d in Proposition 2. model.AddConstr(NUFvar[loc4++] == 1 - bvar[locb - 1], "Flip3" + loc4.ToString()); VarFlaglistCopy[0] = NUFvar[loc4 - 1]; //corresponding to 1-F_d VarFlaglistCopy[1] = NUFvar[loc4 - 2]; //corresponding to 1-b_d VarFlaglistCopy[2] = Uvar[loc1]; //corresponding to beta_d loc1++; //Uvar[loc1]=min(NUFvar[loc4-1],NUFvar[loc4-2],loc1), is the assigment variable of f. model.AddGenConstrMin(Uvar[loc1], VarFlaglistCopy, 1000, "minav" + loc1.ToString()); //model.Update(); Tar.AddTerm(1.0, Uvar[loc1]); Tar.AddTerm(-10000, UFvar[locf]); rec_loc1[i] = loc1; rec_locf[i] = locf; loc1++; locf++; } //in this case, assume that f=u1+u2+u3+c if (Varlist.Count == 3) { VarlistCopy.Clear(); GRBVar[] VarFlaglistCopy = new GRBVar[4]; GRBVar[] VarFlaglistCopy2 = new GRBVar[4]; GRBVar[] Vartemplist = new GRBVar[4]; for (j = 0; j < Varlist.Count(); j++) { VarlistCopy.Add(Varlist[j]); VarFlaglistCopy[j] = VarFlaglist[j]; } VarlistCopy.Add(Uvar[loc1]); //Uvar[loc1]=u1+u2+u3 AddCons3Vars(model, VarlistCopy); //model.AddGenConstrMax(UFvar[loc1], VarFlaglistCopy, 0, "TransFlagXor" + loc1.ToString()); //if c==1, namely f has the constant term 1, U[loc1+1]=Uvar[loc]+1 if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; loc1++; AddCons2Vars(model, VarlistCopy); } //filp every variable, for (j = 0; j < Varlist.Count; j++) { model.AddConstr(NUvar[loc3++] == 1 - VarFlaglistCopy[j], "Flip" + j.ToString()); } // for (j = 0; j < Varlist.Count; j++) { for (k = 0; k < Varlist.Count; k++) { if (k != j) { Vartemplist[k] = NUvar[loc3 - 1 - (Varlist.Count - 1 - k)]; } else { Vartemplist[k] = VarFlaglistCopy[k]; } } //Vvar[loc2]=min(1-VarFlaglistCopy[0],1-VarFlaglistCopy[2],...,VarFlaglistCopy[j],1-VarFlaglistCopy[j],...) model.AddGenConstrMin(Vvar[loc2++], Vartemplist, 1000, "FlagTransOxr1" + loc2.ToString()); } for (j = 0; j < Varlist.Count; j++) { Vartemplist[j] = Vvar[loc2 - 1 - j]; } //Since only one of Vvar[loc2 - 1],Vvar[loc2 - 2],..., is equal to 0 and the remainings are equal to 0s, //UFvar[loc1]=max(Vvar[loc2 - 1],Vvar[loc2 - 2],...,) is equivalently to UFvar[loc1]=Vvar[loc2 - 1]+Vvar[loc2 - 2]+...+ //UFvar[loc1]is the fianl flag variable of f model.AddGenConstrMax(UFvar[locf], Vartemplist, 0, "FlagTransXor-2" + loc2.ToString()); //NUFvar[loc4] =1-UFvar[loc1] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - UFvar[locf], "Flip3" + loc4.ToString()); //max(u1_fv,u2_fv,u3_fv) VarFlaglistCopy[0] = VarFlaglist[0]; VarFlaglistCopy[1] = VarFlaglist[1]; VarFlaglistCopy[2] = VarFlaglist[2]; model.AddGenConstrMax(bvar[locb++], VarFlaglistCopy, 0, "maxfv" + locb.ToString()); //NUFvar[loc4] =1-bvar[locb++] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - bvar[locb - 1], "Flip3" + loc4.ToString()); VarFlaglistCopy2[0] = NUFvar[loc4 - 1]; VarFlaglistCopy2[1] = NUFvar[loc4 - 2]; VarFlaglistCopy2[2] = Uvar[loc1]; loc1++; //Uvar[loc1]=min(NUFvar[loc4-1],NUFvar[loc4-2],loc1), is the assigment variable of f. model.AddGenConstrMin(Uvar[loc1], VarFlaglistCopy2, 1000, "min_av" + loc1.ToString()); Tar.AddTerm(1.0, Uvar[loc1]); Tar.AddTerm(-10000, UFvar[locf]); rec_loc1[i] = loc1; rec_locf[i] = locf; loc1++; locf++; } //assuming f=u1+u2+u3+u4+c if (Varlist.Count == 4) { List <GRBVar> templist = new List <GRBVar>() { }; GRBVar[] VarFlaglistCopy = new GRBVar[5]; GRBVar[] VarFlaglistCopy2 = new GRBVar[5]; GRBVar[] Vartemplist = new GRBVar[5]; for (j = 0; j < Varlist.Count(); j++) { VarFlaglistCopy[j] = VarFlaglist[j]; } templist.Add(Varlist[0]); templist.Add(Varlist[1]); templist.Add(Uvar[loc1]); AddCons2Vars(model, templist); templist.Clear(); loc1++; templist.Add(Varlist[2]); templist.Add(Varlist[3]); templist.Add(Uvar[loc1]); AddCons2Vars(model, templist); templist.Clear(); loc1++; templist.Add(Uvar[loc1 - 2]); templist.Add(Uvar[loc1 - 1]); templist.Add(Uvar[loc1]); AddCons2Vars(model, templist); //if c==1 if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; loc1++; AddCons2Vars(model, VarlistCopy); } for (j = 0; j < Varlist.Count; j++) { model.AddConstr(NUvar[loc3++] == 1 - VarFlaglistCopy[j], "Flip" + j.ToString()); } for (j = 0; j < Varlist.Count; j++) { for (k = 0; k < Varlist.Count; k++) { if (k != j) { Vartemplist[k] = NUvar[loc3 - 1 - (Varlist.Count - 1 - k)]; } else { Vartemplist[k] = VarFlaglistCopy[k]; } } model.AddGenConstrMin(Vvar[loc2++], Vartemplist, 1000, "FlagTransOxr1" + loc2.ToString()); } for (j = 0; j < Varlist.Count; j++) { Vartemplist[j] = Vvar[loc2 - 1 - j]; } model.AddGenConstrMax(UFvar[locf], Vartemplist, 0, "FlagTransXor-2" + loc2.ToString()); //NUFvar[loc4] =1-UFvar[loc1] and increase loc4 by 1 model.AddConstr(NUFvar[loc4] == 1 - UFvar[locf], "Flip3" + loc4.ToString()); loc4++; //max(u1_fv,u2_fv,u3_fv,u4_fv) VarFlaglistCopy[0] = VarFlaglist[0]; VarFlaglistCopy[1] = VarFlaglist[1]; VarFlaglistCopy[2] = VarFlaglist[2]; VarFlaglistCopy[3] = VarFlaglist[3]; model.AddGenConstrMax(bvar[locb++], VarFlaglistCopy, 0, "maxfv" + locb.ToString()); //NUFvar[loc4] =1-bvar[locb++] and increase loc4 by 1 model.AddConstr(NUFvar[loc4] == 1 - bvar[locb - 1], "Flip4" + loc4.ToString()); loc4++; //VarFlaglistCopy.Initialize(); VarFlaglistCopy2[0] = NUFvar[loc4 - 1]; VarFlaglistCopy2[1] = NUFvar[loc4 - 2]; VarFlaglistCopy2[2] = Uvar[loc1]; loc1++; //Uvar[loc1]=min(NUFvar[loc4-1],NUFvar[loc4-2],loc1), is the assigment variable of f. model.AddGenConstrMin(Uvar[loc1], VarFlaglistCopy2, 1000, "min_av" + loc1.ToString()); //Tar=Tar+assigment variable +(-10000)*flag variable Tar.AddTerm(1.0, Uvar[loc1]); Tar.AddTerm(-10000, UFvar[locf]); rec_loc1[i] = loc1; rec_locf[i] = locf; loc1++; locf++; } //assuming f=u1+u2+u3+u4+u5+c if (Varlist.Count == 5) { List <GRBVar> templist = new List <GRBVar>() { }; GRBVar[] VarFlaglistCopy = new GRBVar[6]; GRBVar[] VarFlaglistCopy2 = new GRBVar[6]; GRBVar[] Vartemplist = new GRBVar[6]; for (j = 0; j < Varlist.Count(); j++) { VarFlaglistCopy[j] = VarFlaglist[j]; } templist.Add(Varlist[0]); templist.Add(Varlist[1]); templist.Add(Uvar[loc1]); AddCons2Vars(model, templist); templist.Clear(); loc1++; templist.Add(Varlist[2]); templist.Add(Varlist[3]); templist.Add(Varlist[4]); templist.Add(Uvar[loc1]); AddCons3Vars(model, templist); templist.Clear(); loc1++; templist.Add(Uvar[loc1 - 2]); templist.Add(Uvar[loc1 - 1]); templist.Add(Uvar[loc1]); AddCons2Vars(model, templist); if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; loc1++; AddCons2Vars(model, VarlistCopy); } for (j = 0; j < Varlist.Count; j++) { model.AddConstr(NUvar[loc3++] == 1 - VarFlaglistCopy[j], "Flip" + j.ToString()); } //flip and calculate Tj for (j = 0; j < Varlist.Count; j++) { for (k = 0; k < Varlist.Count; k++) { if (k != j) { Vartemplist[k] = NUvar[loc3 - 1 - (Varlist.Count - 1 - k)]; } else { Vartemplist[k] = VarFlaglistCopy[k]; } } model.AddGenConstrMin(Vvar[loc2++], Vartemplist, 1000, "FlagTransOxr1" + loc2.ToString()); } // for (j = 0; j < Varlist.Count; j++) { Vartemplist[j] = Vvar[loc2 - 1 - j]; } model.AddGenConstrMax(UFvar[locf], Vartemplist, 0, "FlagTransXor-2" + loc2.ToString()); //NUFvar[loc4] =1-UFvar[loc1] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - UFvar[locf], "Flip3" + loc4.ToString()); //max(u1_fv,u2_fv,u3_fv,u4_fv,u5_fv) VarFlaglistCopy[0] = VarFlaglist[0]; VarFlaglistCopy[1] = VarFlaglist[1]; VarFlaglistCopy[2] = VarFlaglist[2]; VarFlaglistCopy[3] = VarFlaglist[3]; VarFlaglistCopy[4] = VarFlaglist[4]; model.AddGenConstrMax(bvar[locb++], VarFlaglistCopy, 0, "maxfv" + locb.ToString()); //NUFvar[loc4] =1-bvar[locb++] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - bvar[locb - 1], "Flip4" + loc4.ToString()); VarFlaglistCopy2[0] = NUFvar[loc4 - 1]; VarFlaglistCopy2[1] = NUFvar[loc4 - 2]; VarFlaglistCopy2[2] = Uvar[loc1]; loc1++; //Uvar[loc1]=min(NUFvar[loc4-1],NUFvar[loc4-2],loc1), is the assigment variable of f. model.AddGenConstrMin(Uvar[loc1], VarFlaglistCopy2, 1000, "min_av" + loc1.ToString()); Tar.AddTerm(1.0, Uvar[loc1]); Tar.AddTerm(-10000, UFvar[locf]); rec_loc1[i] = loc1; rec_locf[i] = locf; loc1++; locf++; } //Console.WriteLine("5: " +loc1); //assuming that f=u1+u2+u3+u4+u5...+um+c, where m>5. if (Varlist.Count > 5) { int length; length = Varlist.Count; List <GRBVar> curvarlist = new List <GRBVar>() { }; GRBVar[] VarFlaglistCopy = new GRBVar[Varlist.Count + 1]; GRBVar[] VarFlaglistCopy2 = new GRBVar[Varlist.Count + 1]; GRBVar[] Vartemplist = new GRBVar[Varlist.Count + 1]; for (j = 0; j < Varlist.Count; j++) { curvarlist.Add(Varlist[j]); VarFlaglistCopy[j] = VarFlaglist[j]; } //model f=u1+u2+...+un. The method used here is a slight differnt from that presented in the paper. //The method used here is more convenient for coding. while (length > 3) { List <GRBVar> nextvarlist = new List <GRBVar>() { }; List <GRBVar> templist = new List <GRBVar>() { }; // templist.Add(curvarlist[0]); templist.Add(curvarlist[1]); templist.Add(curvarlist[2]); templist.Add(Uvar[loc1]); AddCons3Vars(model, templist); for (j = 3; j < curvarlist.Count; j++) { nextvarlist.Add(curvarlist[j]); } nextvarlist.Add(Uvar[loc1]); curvarlist.Clear(); for (j = 0; j < nextvarlist.Count; j++) { curvarlist.Add(nextvarlist[j]); } length = curvarlist.Count; loc1++; } if (length == 2) { curvarlist.Add(Uvar[loc1]); AddCons2Vars(model, curvarlist); //if c==1, then we need xor one more constant if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; loc1++; AddCons2Vars(model, VarlistCopy); } } if (length == 3) { curvarlist.Add(Uvar[loc1]); AddCons3Vars(model, curvarlist); //if c==1, then we need xor one more constant if (consflag[i] == 1) { model.AddConstr(Consvar[loc0++] == 1, "Flip" + j.ToString()); VarlistCopy[0] = Uvar[loc1]; VarlistCopy[1] = Consvar[loc0 - 1]; VarlistCopy[2] = Uvar[loc1 + 1]; loc1++; AddCons2Vars(model, VarlistCopy); } } for (j = 0; j < Varlist.Count; j++) { model.AddConstr(NUvar[loc3++] == 1 - VarFlaglistCopy[j], "Flip" + j.ToString()); } for (j = 0; j < Varlist.Count; j++) { for (k = 0; k < Varlist.Count; k++) { if (k != j) { Vartemplist[k] = NUvar[loc3 - 1 - (Varlist.Count - 1 - k)]; } else { Vartemplist[k] = VarFlaglistCopy[k]; } } model.AddGenConstrMin(Vvar[loc2++], Vartemplist, 1000, "FlagTransOxr1" + loc2.ToString()); } for (j = 0; j < Varlist.Count; j++) { Vartemplist[j] = Vvar[loc2 - 1 - j]; } model.AddGenConstrMax(UFvar[locf], Vartemplist, 0, "FlagTransXor-2" + loc2.ToString()); //NUFvar[loc4] =1-UFvar[loc1] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - UFvar[locf], "Flip3" + loc4.ToString()); //bvar[locb]=max(u1_fv,u2_fv,u3_fv,u4_fv,...,un_fv) and increase locb by 1 for (j = 0; j < VarFlaglist.Count; j++) { VarFlaglistCopy[j] = VarFlaglist[j]; } model.AddGenConstrMax(bvar[locb++], VarFlaglistCopy, 0, "maxfv" + locb.ToString()); //NUFvar[loc4] =1-bvar[locb++] and increase loc4 by 1 model.AddConstr(NUFvar[loc4++] == 1 - bvar[locb - 1], "Flip4" + loc4.ToString()); VarFlaglistCopy2[0] = NUFvar[loc4 - 1]; VarFlaglistCopy2[1] = NUFvar[loc4 - 2]; VarFlaglistCopy2[2] = Uvar[loc1]; loc1++; //Uvar[loc1]=min(NUFvar[loc4-1],NUFvar[loc4-2],loc1), is the assigment variable of f. model.AddGenConstrMin(Uvar[loc1], VarFlaglistCopy2, 1000, "min_av" + loc1.ToString()); Tar.AddTerm(1.0, Uvar[loc1]); Tar.AddTerm(-10000, UFvar[locf]); rec_loc1[i] = loc1; rec_locf[i] = locf; loc1++; locf++; } } // GRBLinExpr keyspace = new GRBLinExpr(); for (i = 0; i < 80; i++) { keyspace.AddTerm(1.0, kvf[i]); } Tar.AddConstant((double)con); //Add the condition that Tar>=0. It gurantees that there is not any condition whose flag variable is equal to 1. model.AddConstr(Tar == 3, "finalcons"); model.SetObjective(keyspace, GRB.MAXIMIZE); //Set the objective function of the model. //model.SetObjective(Tar, GRB.MINIMIZE); model.Optimize(); //output the states of key variables and iv variables if (model.SolCount > 0) { sw.WriteLine("****************************Conditions on single key/iv variables***************************\n"); Console.Write("Free Key bits:\n"); sw.Write("Free Key bits:\n"); for (i = 0; i < 80; i++) { if ((keyvar[i].X == 0) && (kvf[i].X == 1)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); Console.Write("Key bits set to 1:\n"); sw.Write("Key bits set to 1:\n"); for (i = 0; i < 80; i++) { if ((keyvar[i].X == 1) && (kvf[i].X == 0)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); Console.Write("Key bits set 0:\n"); sw.Write("Key bits set 0:\n"); for (i = 0; i < 80; i++) { if ((keyvar[i].X == 0) && (kvf[i].X == 0)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); //for (i = 0; i < loc2; i++) //{ // if (Vvar[i].X > 1) // { // Console.Write(Vvar[i].VarName + " " + Vvar[i].X + "\n"); // } //} Console.WriteLine("*******************************************************\n"); sw.WriteLine("*******************************************************\n"); Console.Write("Free Iv bits:\n"); sw.Write("Free Iv bits:\n"); for (i = 0; i < 80; i++) { if ((ivvar[i].X == 0) && (vvf[i].X == 1)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); Console.Write("Iv bits set to 1:\n"); sw.Write("Iv bits set to 1:\n"); for (i = 0; i < 80; i++) { if ((ivvar[i].X == 1) && (vvf[i].X == 0)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); Console.Write("Iv bits set to 0:\n"); sw.Write("Iv bits set to 0:\n"); for (i = 0; i < 80; i++) { if ((ivvar[i].X == 0) && (vvf[i].X == 0)) { Console.Write(i + ","); sw.Write(i + ","); } } Console.WriteLine(); sw.WriteLine(); double aa = Tar.Value; Console.WriteLine("*****************The number of 1's*****************"); Console.WriteLine(aa); Console.WriteLine("***************************************************"); sw.WriteLine("***********************The assigment/flag variable of key and iv variables***********************"); for (i = 0; i < 80; i++) { Console.Write(keyvar[i].VarName + "= " + keyvar[i].X + " " + kvf[i].VarName + "= " + kvf[i].X + "\n"); sw.Write(keyvar[i].VarName + "= " + keyvar[i].X + " " + kvf[i].VarName + "= " + kvf[i].X + "\n"); } Console.WriteLine("*******************************"); for (i = 0; i < 80; i++) { Console.Write(ivvar[i].VarName + "= " + ivvar[i].X + " " + vvf[i].VarName + "= " + vvf[i].X + "\n"); sw.Write(ivvar[i].VarName + "= " + ivvar[i].X + " " + vvf[i].VarName + "= " + vvf[i].X + "\n"); } Console.WriteLine(); // StreamReader rw = new StreamReader("ConSet.txt"); sw.WriteLine("***************The concrete conditions****************"); for (j = 0; j < consnum; j++) { string onecon = rw.ReadLine(); sw.WriteLine(onecon + "=" + Uvar[rec_loc1[j]].X); } sw.Close(); } }
public HttpResponseMessage Optimize(string RunName) { using (var dbConn = new ApplicationDbContext()) { //Variables for students, semesters, courses, and course/semester offerings students = dbConn.StudentPreferences.Where(m => m.IsActive == true).Include(m => m.Courses).Include(m => m.Student.CompletedCourses).OrderByDescending(m => m.Student.CompletedCourses.Count()).ToArray(); crssems = dbConn.CourseSemesters.Where(m => m.IsActive == true).Include(m => m.Course).Include(m => m.Semester).ToArray(); courses = crssems.Select(m => m.Course).Distinct().ToArray(); sems = crssems.Select(m => m.Semester).Distinct().OrderBy(m => m.Type).OrderBy(m => m.Year).ToArray(); var completed = dbConn.CompletedCourses.ToList(); try { GRBEnv env = new GRBEnv("mip1.log"); GRBModel model = new GRBModel(env); model.Set(GRB.StringAttr.ModelName, "Course Optimizer"); GRBVar[,] slacks = new GRBVar[courses.Length, sems.Length]; //Assignment of student, course, and semester. Student must have a desire to take the coure, has not taken the course, and the course is offered to be included GRBVar[,,] CourseAllocation = new GRBVar[students.Length, courses.Length, sems.Length]; for (int i = 0; i < students.Length; i++) { for (int j = 0; j < courses.Length; j++) { for (int k = 0; k < sems.Length; k++) { if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID) && crssems.Contains(crssems.SingleOrDefault(m => m.Course == courses[j] && m.Semester == sems[k]))) CourseAllocation[i, j, k] = model.AddVar(0, 1, 1, GRB.BINARY, "students." + (i + 1).ToString() + "_Course." + (j + 1).ToString() + "_Semester." + (k + 1).ToString()); else CourseAllocation[i, j, k] = model.AddVar(0, 0, 1, GRB.BINARY, "students." + (i + 1).ToString() + "_Course." + (j + 1).ToString() + "_Semester." + (k + 1).ToString()); } } } model.Set(GRB.IntAttr.ModelSense, 1); model.Update(); //MUST TAKE DESIRED COURSE ONLY ONCE //Constrains the students to only take courses they desire once and for when the course is offered and does not allow a repeat of a course in another semester for (int i = 0; i < students.Length; i++) { for (int j = 0; j < courses.Length; j++) { if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID)) { GRBLinExpr constStudentDesiredCourses = 0.0; for (int k = 0; k < sems.Length; k++) { if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year)) constStudentDesiredCourses.AddTerm(1.0, CourseAllocation[i, j, k]); } String sStudentDesiredCourses = "DesiredCourse." + j + 1 + "_Student." + i + 1; model.AddConstr(constStudentDesiredCourses == 1, sStudentDesiredCourses); } } //MAX COURSES PER SEMESTER //Constrains the students to only have a maximum number of 2 courses per semester. for (int k = 0; k < sems.Length; k++) { GRBLinExpr constMaxPerSem = 0.0; for (int j = 0; j < courses.Length; j++) { if (!completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID) && (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year))) constMaxPerSem.AddTerm(1, CourseAllocation[i, j, k]); } String sCourseSem = "maxCourseStudent." + i + 1 + "_Semester." + k + 1; model.AddConstr(constMaxPerSem <= MAX_COURSES_PER_SEMESTER, sCourseSem); } //PREREQUISITES //Constrains the students to take prerequisite courses prior to taking a course that needs the prerequisite for (int j = 0; j < courses.Length; j++) { if (courses[j].Prerequisites.Any() && students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID)) { foreach (var prereq in courses[j].Prerequisites) { int prereqIndex = Array.IndexOf(courses, prereq); GRBLinExpr coursePrereqConst1 = 0.0; GRBLinExpr coursePrereqConst2 = 0.0; if (!completed.Any(m => m.GaTechId == students[i].GaTechId && m.Course.ID == prereq.ID)) { for (int k = 0; k < sems.Length; k++) { if (prereqIndex >= 0) { coursePrereqConst1.AddTerm(k + 1, CourseAllocation[i, prereqIndex, k]); coursePrereqConst2.AddTerm(k, CourseAllocation[i, j, k]); } } } model.AddConstr(coursePrereqConst1, GRB.LESS_EQUAL, coursePrereqConst2, "PREREQ_Student" + i + "_Course+" + j + "_Prereq" + prereqIndex); } } } } //SENIORITY //Students are already ordered from dB query by seniority in descending order and puts a preference to senior students over the next student that desires that //same course with less seniority. for (int j = 0; j < courses.Length; j++) { for (int i = 0; i < students.Length - 1; i++) { if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID)) { int SemsRemain = (students[i].Courses.Count - students[i].Student.CompletedCourses.Count) / 2 + (students[i].Courses.Count - students[i].Student.CompletedCourses.Count) % 2; for (int n = i + 1; n < students.Length; n++) { if (students[n].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[n].GaTechId && courses[j].ID == m.Course_ID)) { GRBLinExpr seniority = 0.0; for (int k = 0; k < sems.Length; k++) { if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year)) { if (k <= SemsRemain) { seniority.AddTerm(1.0, CourseAllocation[i, j, k]); seniority.AddTerm(-1.0, CourseAllocation[n, j, k]); } else { seniority.AddTerm(-1.0, CourseAllocation[i, j, k]); seniority.AddTerm(1.0, CourseAllocation[n, j, k]); } } } model.AddConstr(seniority, GRB.GREATER_EQUAL, 0, "Seniority for Student." + students[i] + "_Course." + courses[j]); break; } } } } } //Add the slack variable for all semester & course offerings then constrain the maximum number of students //to take a couse in a semester. for (int k = 0; k < sems.Length; k++) { for (int j = 0; j < courses.Length; j++) { if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year)) { slacks[j, k] = model.AddVar(0, GRB.INFINITY, 0, GRB.INTEGER, sems[k].Type.ToString() + "." + sems[k].Year.ToString() + "." + courses[j].Name + ".Slacks"); GRBLinExpr constMaxStudCrsSem = 0.0; for (int i = 0; i < students.Length; i++) { if (!completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID)) constMaxStudCrsSem.AddTerm(1.0, CourseAllocation[i, j, k]); } model.Update(); constMaxStudCrsSem.AddTerm(-1.0, slacks[j, k]); model.AddConstr(constMaxStudCrsSem <= crssems.Single(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year).StudentLimit, sems[k].Type.ToString() + "." + sems[k].Year.ToString() + "." + courses[j].Name); } } } //Add total slack to the optimization model for all courses in the semesters they are offered. GRBVar totSlack = model.AddVar(0, GRB.INFINITY, 0, GRB.INTEGER, "totSlack"); GRBLinExpr lhs = new GRBLinExpr(); lhs.AddTerm(-1.0, totSlack); for (int j = 0; j < courses.Length; j++) { for (int k = 0; k < sems.Length; k++) { if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year)) lhs.AddTerm(1.0, slacks[j, k]); } } model.Update(); model.AddConstr(lhs, GRB.EQUAL, 0, "totSlack"); // Objective: minimize the total slack GRBLinExpr obj = new GRBLinExpr(); obj.AddTerm(1.0, totSlack); model.SetObjective(obj); //Optimize the model to minimize the total slack and maximize students to course offerings based on input variables and constraints. model.Optimize(); //Write Results optimization results to database writeResults(CourseAllocation, students, courses, sems, crssems, dbConn, Convert.ToInt32(model.Get(GRB.DoubleAttr.ObjVal)), RunName); //Clean-Up model.Dispose(); env.Dispose(); } catch (Exception e) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An Error occured while running the optimization."); } } return Request.CreateResponse(HttpStatusCode.OK); }
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 }; // 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. This is no longer a pure assignment model, so we must // use binary variables. 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], 0, GRB.BINARY, Workers[w] + "." + Shifts[s]); } } // Slack variables for each shift constraint so that the shifts can // be satisfied GRBVar[] slacks = new GRBVar[nShifts]; for (int s = 0; s < nShifts; ++s) { slacks[s] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, Shifts[s] + "Slack"); } // Variable to represent the total slack GRBVar totSlack = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "totSlack"); // Variables to count the total shifts worked by each worker GRBVar[] totShifts = new GRBVar[nWorkers]; for (int w = 0; w < nWorkers; ++w) { totShifts[w] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, Workers[w] + "TotShifts"); } GRBLinExpr lhs; // Constraint: assign exactly shiftRequirements[s] workers // to each shift s, plus the slack for (int s = 0; s < nShifts; ++s) { lhs = new GRBLinExpr(); lhs.AddTerm(1.0, slacks[s]); for (int w = 0; w < nWorkers; ++w) { lhs.AddTerm(1.0, x[w, s]); } model.AddConstr(lhs == shiftRequirements[s], Shifts[s]); } // Constraint: set totSlack equal to the total slack lhs = new GRBLinExpr(); for (int s = 0; s < nShifts; ++s) { lhs.AddTerm(1.0, slacks[s]); } model.AddConstr(lhs == totSlack, "totSlack"); // Constraint: compute the total number of shifts for each worker for (int w = 0; w < nWorkers; ++w) { lhs = new GRBLinExpr(); for (int s = 0; s < nShifts; ++s) { lhs.AddTerm(1.0, x[w, s]); } model.AddConstr(lhs == totShifts[w], "totShifts" + Workers[w]); } // Objective: minimize the total slack model.SetObjective(1.0 * totSlack); // Optimize int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts); if (status != GRB.Status.OPTIMAL) { return; } // Constrain the slack by setting its upper and lower bounds totSlack.UB = totSlack.X; totSlack.LB = totSlack.X; // Variable to count the average number of shifts worked GRBVar avgShifts = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "avgShifts"); // Variables to count the difference from average for each worker; // note that these variables can take negative values. GRBVar[] diffShifts = new GRBVar[nWorkers]; for (int w = 0; w < nWorkers; ++w) { diffShifts[w] = model.AddVar(-GRB.INFINITY, GRB.INFINITY, 0, GRB.CONTINUOUS, Workers[w] + "Diff"); } // Constraint: compute the average number of shifts worked lhs = new GRBLinExpr(); for (int w = 0; w < nWorkers; ++w) { lhs.AddTerm(1.0, totShifts[w]); } model.AddConstr(lhs == nWorkers * avgShifts, "avgShifts"); // Constraint: compute the difference from the average number of shifts for (int w = 0; w < nWorkers; ++w) { model.AddConstr(totShifts[w] - avgShifts == diffShifts[w], Workers[w] + "Diff"); } // Objective: minimize the sum of the square of the difference from the // average number of shifts worked GRBQuadExpr qobj = new GRBQuadExpr(); for (int w = 0; w < nWorkers; ++w) { qobj.AddTerm(1.0, diffShifts[w], diffShifts[w]); } model.SetObjective(qobj); // Optimize status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts); if (status != GRB.Status.OPTIMAL) { return; } // Dispose of model and env model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
protected static bool dense_optimize(GRBEnv env, int rows, int cols, double[] c, // linear portion of objective function double[,] Q, // quadratic portion of objective function double[,] A, // constraint matrix char[] sense, // constraint senses double[] rhs, // RHS vector double[] lb, // variable lower bounds double[] ub, // variable upper bounds char[] vtype, // variable types (continuous, binary, etc.) double[] solution) { bool success = false; try { GRBModel model = new GRBModel(env); // Add variables to the model GRBVar[] vars = model.AddVars(lb, ub, null, vtype, null); model.Update(); // Populate A matrix for (int i = 0; i < rows; i++) { GRBLinExpr expr = new GRBLinExpr(); for (int j = 0; j < cols; j++) if (A[i,j] != 0) expr.AddTerm(A[i,j], vars[j]); // Note: '+=' would be much slower model.AddConstr(expr, sense[i], rhs[i], ""); } // Populate objective GRBQuadExpr obj = new GRBQuadExpr(); if (Q != null) { for (int i = 0; i < cols; i++) for (int j = 0; j < cols; j++) if (Q[i,j] != 0) obj.AddTerm(Q[i,j], vars[i], vars[j]); // Note: '+=' would be much slower for (int j = 0; j < cols; j++) if (c[j] != 0) obj.AddTerm(c[j], vars[j]); // Note: '+=' would be much slower model.SetObjective(obj); } // Solve model model.Optimize(); // Extract solution if (model.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) { success = true; for (int j = 0; j < cols; j++) solution[j] = vars[j].Get(GRB.DoubleAttr.X); } model.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } return success; }
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"); model.ComputeIIS(); Console.WriteLine("\nThe following constraint(s) " + "cannot be satisfied:"); foreach (GRBConstr c in model.GetConstrs()) { if (c.IISConstr == 1) { Console.WriteLine(c.ConstrName); } } // 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 int groundSetSize = 10; double[] objCoef = new double[] { 32, 32, 15, 15, 6, 6, 1, 1, 1, 1 }; double[] knapsackCoef = new double[] { 16, 16, 8, 8, 4, 4, 2, 2, 1, 1 }; double Budget = 33; int e, status, nSolutions; // Create environment GRBEnv env = new GRBEnv("poolsearch_cs.log"); // Create initial model GRBModel model = new GRBModel(env); model.ModelName = "poolsearch_cs"; // Initialize decision variables for ground set: // x[e] == 1 if element e is chosen GRBVar[] Elem = model.AddVars(groundSetSize, GRB.BINARY); model.Set(GRB.DoubleAttr.Obj, Elem, objCoef, 0, groundSetSize); for (e = 0; e < groundSetSize; e++) { Elem[e].VarName = string.Format("El{0}", e); } // Constraint: limit total number of elements to be picked to be at most // Budget GRBLinExpr lhs = new GRBLinExpr(); for (e = 0; e < groundSetSize; e++) { lhs.AddTerm(knapsackCoef[e], Elem[e]); } model.AddConstr(lhs, GRB.LESS_EQUAL, Budget, "Budget"); // set global sense for ALL objectives model.ModelSense = GRB.MAXIMIZE; // Limit how many solutions to collect model.Parameters.PoolSolutions = 1024; // Limit the search space by setting a gap for the worst possible solution that will be accepted model.Parameters.PoolGap = 0.10; // do a systematic search for the k-best solutions model.Parameters.PoolSearchMode = 2; // save problem model.Write("poolsearch_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 best selected set Console.WriteLine("Selected elements in best solution:"); Console.Write("\t"); for (e = 0; e < groundSetSize; e++) { if (Elem[e].X < .9) { continue; } Console.Write("El{0} ", e); } Console.WriteLine(); // Print number of solutions stored nSolutions = model.SolCount; Console.WriteLine("Number of solutions found: {0}", nSolutions); // Print objective values of solutions for (e = 0; e < nSolutions; e++) { model.Parameters.SolutionNumber = e; Console.Write("{0} ", model.PoolObjVal); if (e % 15 == 14) { Console.WriteLine(); } } Console.WriteLine(); // Print fourth best set if available if (nSolutions >= 4) { model.Parameters.SolutionNumber = 3; Console.WriteLine("Selected elements in fourth best solution:"); Console.Write("\t"); for (e = 0; e < groundSetSize; e++) { if (Elem[e].Xn < .9) { continue; } Console.Write("El{0} ", e); } Console.WriteLine(); } model.Dispose(); env.Dispose(); } catch (GRBException e) { Console.WriteLine("Error code: {0}. {1}", e.ErrorCode, e.Message); } }