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); } }
public static GRBLinExpr Quicksum(this IEnumerable <GRBLinExpr> exprsToAdd) { GRBLinExpr expr = new GRBLinExpr(); foreach (var exprToAdd in exprsToAdd) { expr.Add(exprToAdd); } return(expr); }
internal void AddValueFunction(int userNum, float priority, Value valueFunction) { if (!Value.IsDefined(valueFunction)) { return; } var gurobiValue = ConvertToGurobi(valueFunction); _value += priority * gurobiValue; }
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 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"); } }
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"); } }
public void max_depot_nodes_per_period(int n_DepotNodes) { for (int t = 0; t < instanceGenerator.getInstanceConfig().time_periods; t++) { GRBLinExpr sum = 0; for (int j = 0; j < instanceGenerator.getInstanceConfig().n_depots; j++) { sum += variableGenerator.depot_usage[j, t]; } Model.AddConstr(sum <= instanceGenerator.getInstanceConfig().max_depot_nodes_per_period, String.Format("max_depot_nodes_per_period_t{0}", t)); } }
/// <summary> /// Santas are not able to beam and therefore, /// it needs a certain time to get from one visit to another /// except if distance is 0 /// </summary> private void CreateSantaNeedTimeBetweenVisitsConstraint() { #if DEBUG var constraintCounter = 0; #endif for (int day = 0; day < solverData.NumberOfDays; day++) { int slicesPerDay = solverData.SlicesPerDay[day]; for (int santa = 0; santa < solverData.NumberOfSantas; santa++) { for (int visit = 1; visit < solverData.NumberOfVisits; visit++) { for (int timeslice = 0; timeslice < slicesPerDay; timeslice++) { int numberOfBs = 0; var A = solverData.Variables.VisitsPerSanta[day][santa][visit][timeslice]; var B = new GRBLinExpr(0); for (int destination = 1; destination < solverData.NumberOfVisits; destination++) { var distance = solverData.Input.Distances[visit, destination]; // don't add unnecessary constraints if (distance <= 0) { continue; } // 1 because same timeslot is handled by another constraint for (int distCounter = 1; distCounter <= Math.Min(distance, slicesPerDay - timeslice - 1); distCounter++) { B += solverData.Variables.VisitsPerSanta[day][santa][destination][timeslice + distCounter]; numberOfBs++; } // A <= 1 - B would be easy but B can be greater than 0 and A has to be >= 0 // so we multiply A by numberOfBs, possible values are 0 (if A == 0) or numberOfBs (if A == 1) // if B == 0, A can be 1 (numberOfBs <= numberOfBs), else A has to be 0 (numberOfBs - (at least 1)) is smaller than numberOfBs } solverData.Model.AddConstr(numberOfBs * A <= numberOfBs - B, null); #if DEBUG constraintCounter++; #endif } } } } #if DEBUG Debug.WriteLine($"CreateSantaNeedTimeBetweenVisitsConstraint - added {constraintCounter} constraints"); #endif }
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); }
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); }
/// <summary> /// The the sum of all fields in SantaEnRoute that must be set, if santa visits the given visit /// A field in SantaEnRoute must be set if: /// - Santa is visiting visit /// - Santa is busy walking from home to visit /// - Santa is busy walking from visit to home /// </summary> /// <param name="day"></param> /// <param name="santa"></param> /// <param name="visit"></param> /// <param name="timesliceVisit"></param> /// <returns>sum of all fields that must be set and the number of fields</returns> private (GRBLinExpr, int) GetSumOfEnRoute(int day, int santa, int visit, int timesliceVisit) { var sum = new GRBLinExpr(0); var StartEndPoint = solverData.StartEndPoint; var timesliceFrom = Math.Max(0, timesliceVisit - solverData.Input.Distances[StartEndPoint, visit]); var timesliceTo = Math.Min(solverData.SlicesPerDay[day], timesliceVisit + solverData.Input.Distances[visit, StartEndPoint] + 1); for (int timeslice = timesliceFrom; timeslice < timesliceTo; timeslice++) { sum += solverData.Variables.SantaEnRoute[day][santa][timeslice]; } return(sum, timesliceTo - timesliceFrom); }
/// <summary> /// Each Visit is visited by exactly one Santa /// </summary> private void CreateOnlyOneSantaPerVisitConstraint() { for (int visit = 1; visit < solverData.NumberOfVisits; visit++) { // 1 = Z1 + Z2 + ... var sum = new GRBLinExpr(0); for (int santa = 0; santa < solverData.NumberOfSantas; santa++) { sum += solverData.Variables.SantaVisits[santa][visit]; } solverData.Model.AddConstr(1 == sum, null); } }
public void AddNutritionConstraints(GRBModel model) { // Nutrition constraints for (int i = 0; i < NumberOfCategories; ++i) { GRBLinExpr ntot = 0.0; for (int j = 0; j < numberOfFoodTypes; ++j) { ntot += nutritionValues[j, i] * boughtAmount[j]; } model.AddConstr(ntot == nutritionDecisionVariables[i], categories[i]); } }
public static GRBLinExpr SumL1(this List <GRBLinExpr> _expressions) { var res = new GRBLinExpr(); foreach (var v in _expressions) { if ((object)v != null) { res.Add(v); } } return(res); }
public static GRBLinExpr SumL1(this GRBVar[] _vars) { var res = new GRBLinExpr(); foreach (var v in _vars) { if ((object)v != null) { res.Add(v); } } return(res); }
public override bool SetObjFn(object solver, double[] row) { GRBModel grbSolver = solver as GRBModel; if (grbSolver == null) { return(false); } GRBLinExpr obj = new GRBLinExpr(); obj.AddTerms(row, grbSolver.GetVars()); grbSolver.SetObjective(obj, GRB.MINIMIZE); return(true); }
private void SantaVisitDuration() { foreach (var santa in Enumerable.Range(0, solverData.NumberOfSantas)) { var expr = new GRBLinExpr(0); foreach (var visit in Enumerable.Range(0, solverData.NumberOfVisits)) { expr += solverData.Variables.SantaVisit[santa][visit] * solverData.SolverInputData.VisitsDuration[visit]; } Model.AddConstr(solverData.Variables.SantaVisitTime[santa] == expr, null); } }
//MODIFY CONSTRAINTS private void btnModify_EditObj_ItemClick(object sender, ItemClickEventArgs e) { GRBLinExpr func = (GRBLinExpr)MyGlobals.model.GetObjective(); if (func.Size != 0) { Form frm = new FrmChangeObj(); frm.Show(); } else { MessageBox.Show("You have not added any objective function in your model!"); } }
//ANALYZE RESULTS private void btnView_Analyze_ItemClick(object sender, ItemClickEventArgs e) { GRBLinExpr func = (GRBLinExpr)MyGlobals.model.GetObjective(); if (func.Size != 0) { Form frm = new FrmAnalyze(); frm.Show(); } else { MessageBox.Show("Your Objective Function is not initialized. \nPlease build your model."); } }
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}]"); } }
private void UnAllowedTraverses() { var unAllowedTraverses = new GRBLinExpr(); for (int v = 0; v < _vehicles.Count; v++) { for (int s = 0; s < _vertices.Count; s++) { unAllowedTraverses += _vehicleTraverse[v][s][s] + _vehicleTraverse[v][s][0] + _vehicleTraverse[v][_vertices.Count - 1][s]; } } _model.AddConstr(unAllowedTraverses, GRB.EQUAL, 0.0, "_UnAllowedTraverses"); }
private void GenerateObj() { GRBLinExpr objExpr = 0; // maximizing the total amount of movements foreach (Movement m in DataRepository.MovementList) { if (m is TrainSegmentMovement) { objExpr += model.GetVarByName("x_" + m.ToString()); } } model.SetObjective(objExpr, GRB.MAXIMIZE); }
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(); }
private void StartVisitVistedByEveryUsedSanta() { foreach (var santa in Enumerable.Range(0, solverData.NumberOfSantas)) { var sumSantaVisit = new GRBLinExpr(0); for (var visit = 1; visit < solverData.NumberOfVisits; visit++) { Model.AddConstr(solverData.Variables.SantaVisit[santa][0] >= solverData.Variables.SantaVisit[santa][visit], null); sumSantaVisit += solverData.Variables.SantaVisit[santa][visit]; } Model.AddConstr(solverData.Variables.SantaVisit[santa][0] <= sumSantaVisit, null); } }
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 BuildObj_SG() { GRBLinExpr expr = 0; expr += SchemeDualValue * 1 + FADualValue * 0; foreach (Node n in Data.NodeSet) { expr += DualSolution[n] * Data.ServerCapacity * _grbModel_SchemeGenerateSub.GetVarByName("y_" + n.ID); } foreach (Node n in Data.NodeSet) { expr += -Data.ServerInstalationFee * _grbModel_SchemeGenerateSub.GetVarByName("y_" + n.ID); } _grbModel_SchemeGenerateSub.SetObjective(expr, GRB.MAXIMIZE); }
public override bool AddConstraint(object solver, double[] row, SolverAdapterConstraintTypes constr_type, double rh) { GRBModel grbSolver = solver as GRBModel; if (grbSolver == null) { return(false); } GRBLinExpr expr = 0.0; ind++; expr.AddTerms(row, grbSolver.GetVars()); grbSolver.AddConstr(expr, (char)GetAdaptedConstraintType(constr_type), rh, "R" + ind); return(true); }
GRBLinExpr[] SumOfPersonVarsPerPerson(GRBVar[,] vars) { GRBLinExpr[] sums = new GRBLinExpr[vars.GetLength(0)]; for (int person = 0; person < vars.GetLength(0); person++) { sums[person] = 0.0; for (int ts = 0; ts < vars.GetLength(1); ts++) { sums[person].AddTerm(1.0, vars[person, ts]); } } return(sums); }
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 VehiclesMustLeaveTheArrivingCustomer() { for (int v = 0; v < _vehicles.Count; v++) { for (int s = 1; s <= _vertices.Count - 2; s++) { var flow = new GRBLinExpr(); for (int e = 0; e < _vertices.Count; e++) { flow.Add(_vehicleTraverse[v][e][s] - _vehicleTraverse[v][s][e]); } _model.AddConstr(flow, GRB.EQUAL, 0.0, "_VehiclesMustLeaveTheArrivingCustomer"); } } }
public INumExpr() { this.expr = new GRBLinExpr(); }
public INumExpr(GRBLinExpr expr) { this.expr = expr; }
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; }
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); } }
public INumExpr(INumVar var) { this.expr = new GRBLinExpr(var.var); }
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); }
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; }
public Instance Match(Instance instance, string path, bool print) { try { LP = ""; if (!System.IO.Directory.Exists(path) && print) System.IO.Directory.CreateDirectory(path); GRBEnv env = new GRBEnv("mip1.log"); GRBModel model = new GRBModel(env); List<LPEdge> LPEdges = new List<LPEdge>(); if (print) { instance.Draw().Save(path + "/0Start.bmp"); } int EdgeCounter = 0; foreach (Instance.Applicant a in instance.Applicants) { EdgeCounter += a.Priorities.Count; foreach (Instance.Priority Prio in a.Priorities) { { LPEdges.Add(new LPEdge(a, instance.Posts[Prio.Target], Prio.Rank)); if (Prio.Rank == 0) instance.Posts[Prio.Target].IsF = 1; } } } // Create variables GRBVar[] Edges = new GRBVar[EdgeCounter]; for (int i = 0; i < Edges.Length; i++) { Edges[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "ve" + i.ToString()); } // Integrate new variables model.Update(); if (print) LP += "Applicant Matching Conditions:" + Environment.NewLine; foreach (Instance.Applicant a in instance.Applicants) { GRBLinExpr Temp = new GRBLinExpr(); for (int i = 0; i < LPEdges.Count; i++) { if (LPEdges[i].Applicant == a) { Temp += Edges[i]; if (print) LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + "; } } model.AddConstr(Temp == 1.0, "a" + a.ID.ToString()); if (print) LP += " = 1;" + Environment.NewLine; } if (print) LP += Environment.NewLine + "Post Matching Conditions:" + Environment.NewLine; foreach (Instance.Post p in instance.Posts) { GRBLinExpr Temp = new GRBLinExpr(); for (int i = 0; i < LPEdges.Count; i++) { if (LPEdges[i].Post == p) { Temp += Edges[i]; if (print) LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + "; } } model.AddConstr(Temp <= 1.0, "p" + p.ID.ToString()); if (print) LP += " <= 1;" + Environment.NewLine; } if (print) LP += Environment.NewLine + "First Choice Conditions:" + Environment.NewLine; for (int i = 0; i < LPEdges.Count; i++) { LPEdge le1 = LPEdges[i]; if (le1.Post.IsF == 1 && le1.Rank != 0) { model.AddConstr(Edges[i] <= 0, "s" + i.ToString()); if (print) LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") <= 0;" + Environment.NewLine; for (int j = 0; j < LPEdges[i].Applicant.Priorities.Count; j++) { if (LPEdges[i].Applicant.Priorities[j].Target == LPEdges[i].Post.ID && LPEdges[i].Rank == LPEdges[i].Applicant.Priorities[j].Rank) { LPEdges[i].Applicant.Priorities.RemoveAt(j); } } } } if (print) LP += Environment.NewLine + "Second Choice Conditions:" + Environment.NewLine; for (int i = 0; i < LPEdges.Count; i++) { LPEdge le1 = LPEdges[i]; foreach (LPEdge le2 in LPEdges) { if (le2 != le1 && le2.Post.IsF == 0 && le1.Applicant == le2.Applicant && le2.Rank != 0 && le2.Rank < le1.Rank) { model.AddConstr(Edges[i] <= 0, "s" + i.ToString()); if (print) LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") <= 0;" + Environment.NewLine; for (int j = 0; j < LPEdges[i].Applicant.Priorities.Count; j++) { if (LPEdges[i].Applicant.Priorities[j].Target == LPEdges[i].Post.ID && LPEdges[i].Rank == LPEdges[i].Applicant.Priorities[j].Rank) { LPEdges[i].Applicant.Priorities.RemoveAt(j); } } break; } } } if (print) LP += Environment.NewLine + "First Post Conditions:" + Environment.NewLine; foreach (Instance.Post p in instance.Posts) { if (p.IsF == 1) { GRBLinExpr Temp = new GRBLinExpr(); for (int i = 0; i < LPEdges.Count; i++) { if (LPEdges[i].Post == p) { Temp += Edges[i]; if (print) LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + "; } } model.AddConstr(Temp >= 1.0, "f" + p.ID.ToString()); if (print) LP += ">= 1;" + Environment.NewLine; } } // Optimize model model.Optimize(); if (print) { instance.Draw().Save(path + "/1Reduced.bmp"); } for (int i = 0; i < Edges.Length; i++) { if (Edges[i].Get(GRB.DoubleAttr.X) == 1) { instance.AddMatch(LPEdges[i].Post.ID, LPEdges[i].Applicant.ID); } } if (print) { instance.Draw().Save(path + "/2Matched.bmp"); } // Dispose of model and env model.Dispose(); env.Dispose(); return instance; } catch (GRBException e) { Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); return null; } }