/// <summary> /// This is final model to solve. You can see it is the same model except this is a MIP /// </summary> public void SolveFinalMIPModel() { SetCurrentToMaster(Domain.IntegerNonnegative); Model masterMIPModel = _context.CurrentModel; SimplexDirective simplex = new SimplexDirective(); Solution sol = _context.Solve(simplex); if (sol.Quality == SolverQuality.Optimal) { Console.WriteLine("\n**** Final Solution ****"); var goal = masterMIPModel.Goals.First().ToDouble(); PrintSolution(masterMIPModel.Decisions.First().GetValues(), goal, true); } //TODO: PrintSolution(masterMIPModel.Decisions.First().GetValues()) & Report report = sol.GetReport(ReportVerbosity.All) SHOW DIFF VALUES!!! //2nd appears to be more accurate Report report = sol.GetReport(ReportVerbosity.All); Console.WriteLine(report); }
/// <summary> /// Initially formulate the model as an LP /// Solve the LP model. If the model is solved to an optimal result, /// find the duals of the constraints. FindNewPattern() method uses duals and /// tries to find a new pattern. If a new pattern is found, it is added to the PatternRolls data. /// This model keeps on growing if there is a new pattern found in the FindNewPattern() method /// and resolved. This process continues until there is no new pattern /// </summary> /// <returns>Returns true if an optimal solution is found, otherwise false</returns> public bool SolveMasterModel() { SetCurrentToMaster(Domain.RealNonnegative); Model masterModel = _context.CurrentModel; SimplexDirective simplex = new SimplexDirective(); simplex.GetSensitivity = true; //setting this to true, generates shadow prices, needed to calc new pattern Solution sol = _context.Solve(simplex); //Check if the solution is optimal if (sol.Quality == SolverQuality.Optimal) { Report report = sol.GetReport(ReportVerbosity.All); //LinearReport has the Sensitivity report LinearReport lpReport = report as LinearReport; //Copying the duals from lpReport.GetShadowPrices //This is needed to match indexes (Roll Widths) in the SetRoll. For example: GetShadowPrices returns the keys as DemandConstraint(12), //but keys should just be 12 to match the indexes //Currently a limitation with our API //https://ideas.repec.org/p/fth/nesowa/96-18.html _shadowPrices.Clear(); foreach (KeyValuePair <string, Rational> pair in lpReport.GetShadowPrices(masterModel.Constraints.First())) { _shadowPrices.Add(new KeyValuePair <int, Rational>(GetIndexFromName(pair.Key), pair.Value)); } //we have defined a single decision with multiple values (how many cuts per pattern to reach demanded rolls) var goal = masterModel.Goals.First().ToDouble(); PrintSolution(masterModel.Decisions.First().GetValues(), goal, false); //Console.WriteLine(); //Console.WriteLine("Now totalRolls required to meet the demand:{0}", masterModel.Goals.First().ToDouble()); //Console.WriteLine(); return(true); } return(false); }
private void button_Click(object sender, RoutedEventArgs e) { context.ClearModel(); Model model = context.CreateModel(); List <Decision> decisions = new List <Decision>(); var formula = ""; string con = ""; foreach (var item in dataGridVars.Items) { string li = "L" + (item as Invester).Line; double maxValue = Double.Parse((item as Invester).MaxValue) * Double.Parse(Value.Text) / 100f; String contrain = li + " <= " + maxValue; ParseContrain(contrain); con += " " + li + " +"; Decision dc = new Decision(Domain.RealRange(0, maxValue), li); decisions.Add(dc); model.AddDecision(dc); } ParseContrain(con.Substring(0, con.Length - 1) + " >= " + Value.Text); foreach (var item in dataGridVars.Items) { formula += " " + Double.Parse((item as Invester).Interest) + " * L" + (item as Invester).Line; if ((item as Invester).Line <= dataGridVars.Items.Count - 1) { formula += " +"; } String contrain = "L" + (item as Invester).Line + " >= 0 "; ParseContrain(contrain); } TargetFormula = formula.Substring(1, formula.Length - 2); FormulaTB.Text = TargetFormula; foreach (var list in ListOfContrains) { string c = ""; for (int i = 0; i < list.Capacity; i++) { if (i != 0 && i < list.Capacity - 1) { c += list[i] >= 0 ? " + " : " - "; } if (i == list.Capacity - 1) { c += " " + listOfStringContrains[ListOfContrains.IndexOf(list)] + " " + list[i]; } else { c += Math.Abs(list[i]) + " * L" + i; } } model.AddConstraint("C" + ListOfContrains.IndexOf(list), c); Console.WriteLine(c); } model.AddGoal("Goal", GoalKind.Minimize, TargetFormula); var directive = new SimplexDirective() { IterationLimit = -1, TimeLimit = -1, Arithmetic = Arithmetic.Exact, GetSensitivity = true }; Solution solution = context.Solve(directive); Quality.Text = solution.Quality.ToString(); Console.WriteLine(solution.GetReport().ToString()); if (solution.Quality != SolverQuality.Optimal) { return; } context.PropagateDecisions(); for (int i = 0; i < decisions.Count; i++) { var old = (dataGridVars.Items[i] as Invester); old.SelectedValue = decisions[i].ToDouble().ToString(); dataGridVars.Items[i] = old; } dataGridVars.Items.Refresh(); dataGridVars.UpdateLayout(); }
public void getDemo() { Console.WriteLine("Enter the name of input file"); //Singleton Design Pattern var solver = SolverContext.GetContext(); // Create empty model var model = solver.CreateModel(); //get data string[] data; string input = Console.ReadLine(); //valid file name control try { new Info(input); } catch (ArgumentException e) { Console.WriteLine(e.Message + "\nProcess failed."); Console.ReadKey(); return; } Info info = new Info(input); //read data from file data = info.Read(); //all the information we put into the necessary collections info.allInfo(); //create variables Decision[] xs = new GetDecision().getX(data.Length - 1); Decision[] ys = new GetDecision().getY(data.Length - 1); //add xs and ys model.AddDecisions(xs); model.AddDecisions(ys); // I addded Wts and Zts List <Term> wt = info.addWt(xs); List <Term> zt = info.addZt(ys); //ı adeed constraints for (int i = 0; i < wt.Count; i++) { model.AddConstraint(("Constraint1_" + i), info.D[i] <= wt[i] + zt[i] + info.E[i]); } for (int i = 0; i < wt.Count; i++) { model.AddConstraint(("Constraint2_" + i), zt[i] <= 0.2 * (wt[i] + zt[i] + info.E[i])); } // I took the expression from term denominated of z equation model.AddGoal("Goal", GoalKind.Minimize, info.getGoalTerm(xs, ys)); //Report and solution part // SimplexDirective = Instruction, orders. It's about how you're going to work on what you want to figure out SimplexDirective simplex = new SimplexDirective(); Solution solution = solver.Solve(simplex); //print report Console.WriteLine("--------------------------------------------"); Report report = solution.GetReport(); Console.Write("{0}", report); Console.WriteLine("--------------------------------------------\n\n"); //our comment getFormat(); //I got the variables into an array double[] varResults = new double[xs.Length * 2]; int k = 0; foreach (Decision d in solution.Decisions) { varResults[k] = d.ToDouble(); k++; } double totalCost = 0.0; k = 0; int m = varResults.Length / 2; //using the array in the specified format for (int i = 0; i < varResults.Length / 2; i++) { Console.WriteLine("\n\n" + info.t[k] + ".year ->> (" + info.c[k] + " * " + varResults[k] + ") = " + info.c[k] * varResults[k]); Console.WriteLine(info.t[k] + ".year ->> (" + info.n[k] + " * " + varResults[m] + ") = " + info.n[k] * varResults[m]); Console.WriteLine(info.t[k] + ".year ->> " + ((info.c[k] * varResults[k]) + (info.n[k] * varResults[m])) + "\n\n"); totalCost += (info.c[k] * varResults[k]) + (info.n[k] * varResults[m]); k++; m++; } Console.WriteLine("\n\nFinal Total Cost = " + totalCost); Console.ReadKey(); }
private OptimizationModel Solve(OptimizationModel optimizationModel) { var furnances = optimizationModel.Furnaces; SolverContext context = SolverContext.GetContext(); Model model = context.CreateModel(); var furnancesSet = new Set(Domain.Any, "Furnances"); var parametersList = new List <Parameter>(); var gasExpenseBasePeriod = new Parameter(Domain.Real, "GasExpenseBasePeriod", furnancesSet); gasExpenseBasePeriod.SetBinding(furnances, "GasExpenseBasePeriod", "FurnanceId"); var minGasExpense = new Parameter(Domain.Real, "MinGasExpense", furnancesSet); minGasExpense.SetBinding(furnances, "MinGasExpense", "FurnanceId"); var maxGasExpense = new Parameter(Domain.Real, "MaxGasExpense", furnancesSet); maxGasExpense.SetBinding(furnances, "MaxGasExpense", "FurnanceId"); var coxExpenseBasePeriod = new Parameter(Domain.Real, "CoxExpenseBasePeriod", furnancesSet); coxExpenseBasePeriod.SetBinding(furnances, "CoxExpenseBasePeriod", "FurnanceId"); var coxReplacementEquivalent = new Parameter(Domain.Real, "CoxReplacementEquivalent", furnancesSet); coxReplacementEquivalent.SetBinding(furnances, "CoxReplacementEquivalent", "FurnanceId"); var ironPerformance = new Parameter(Domain.Real, "IronPerformance", furnancesSet); ironPerformance.SetBinding(furnances, "IronPerformance", "FurnanceId"); var theoreticTemperatureBasePeriod = new Parameter(Domain.Real, "TheoreticTemperatureBasePeriod", furnancesSet); theoreticTemperatureBasePeriod.SetBinding(furnances, "TheoreticTemperatureBasePeriod", "FurnanceId"); var minTemperature = new Parameter(Domain.Real, "MinTemperature", furnancesSet); minTemperature.SetBinding(furnances, "MinTemperature", "FurnanceId"); var maxTemperature = new Parameter(Domain.Real, "MaxTemperature", furnancesSet); maxTemperature.SetBinding(furnances, "MaxTemperature", "FurnanceId"); var deltaIronPerformanceGasChanged = new Parameter(Domain.Real, "DeltaIronPerformanceGasChanged", furnancesSet); deltaIronPerformanceGasChanged.SetBinding(furnances, "DeltaIronPerformanceGasChanged", "FurnanceId"); var deltaIronPerformanceCoxChanged = new Parameter(Domain.Real, "DeltaIronPerformanceCoxChanged", furnancesSet); deltaIronPerformanceCoxChanged.SetBinding(furnances, "DeltaIronPerformanceCoxChanged", "FurnanceId"); var deltaTemperatureGasChanged = new Parameter(Domain.Real, "DeltaTemperatureGasChanged", furnancesSet); deltaTemperatureGasChanged.SetBinding(furnances, "DeltaTemperatureGasChanged", "FurnanceId"); parametersList.Add(gasExpenseBasePeriod); parametersList.Add(minGasExpense); parametersList.Add(maxGasExpense); parametersList.Add(coxExpenseBasePeriod); parametersList.Add(coxReplacementEquivalent); parametersList.Add(ironPerformance); parametersList.Add(minTemperature); parametersList.Add(maxTemperature); parametersList.Add(theoreticTemperatureBasePeriod); parametersList.Add(deltaIronPerformanceGasChanged); parametersList.Add(deltaIronPerformanceCoxChanged); parametersList.Add(deltaTemperatureGasChanged); model.AddParameters(parametersList.ToArray()); Decision decision = new Decision(Domain.RealNonnegative, "decision", furnancesSet); model.AddDecision(decision); /*(koksekv*стоимость кокса - стоимость природного газа)*расход ту readjust*/ model.AddGoal("CokeSaving", GoalKind.Maximize, Model.Sum(Model.ForEach(furnancesSet, FurnanceId => (coxReplacementEquivalent[FurnanceId] * optimizationModel.CoxCost - optimizationModel.GasCost) * decision[FurnanceId]))); model.AddConstraint("RequiredIronPerformance", Model.Sum(Model.ForEach(furnancesSet, CalculatePerformanceConstraint)) >= optimizationModel.RequiredIronPerformance); // (расходПГ - расходБазовомПериоде)*ИзмПрЧугИзмПГ - ЭквЗамКокс*(расходПГ - расходБазовомПериоде)*ИзмПрЧугИзимКокса + ПрПоЧугБазовомПер Term CalculatePerformanceConstraint(Term FurnanceId) { var val = (decision[FurnanceId] - gasExpenseBasePeriod[FurnanceId]) * deltaIronPerformanceGasChanged[FurnanceId] - coxReplacementEquivalent[FurnanceId] * (decision[FurnanceId] - gasExpenseBasePeriod[FurnanceId]) * deltaIronPerformanceCoxChanged[FurnanceId] + ironPerformance[FurnanceId]; return(val); } model.AddConstraints("GasExpenseInterval", Model.ForEach(furnancesSet, FurnanceId => (minGasExpense[FurnanceId] <= decision[FurnanceId] <= maxGasExpense[FurnanceId]))); Term CalculateTemperatureConstraint(Term FurnanceId) { return(minTemperature[FurnanceId] <= ((decision[FurnanceId] - gasExpenseBasePeriod[FurnanceId]) * deltaTemperatureGasChanged[FurnanceId] + theoreticTemperatureBasePeriod[FurnanceId]) <= maxTemperature[FurnanceId]); } model.AddConstraints("TemperatureInterval", Model.ForEach(furnancesSet, CalculateTemperatureConstraint)); Term CalculateCoxSupplyConstraint(Term FurnanceId) { return(coxExpenseBasePeriod[FurnanceId] + 0.001 * (gasExpenseBasePeriod[FurnanceId] - decision[FurnanceId]) + coxReplacementEquivalent[FurnanceId]); } model.AddConstraint("CoxSupply", Model.Sum(Model.ForEach(furnancesSet, CalculateCoxSupplyConstraint)) <= optimizationModel.CoxSupply); model.AddConstraint("GasSupply", Model.Sum(Model.ForEach(furnancesSet, FurnanceId => decision[FurnanceId])) <= optimizationModel.GasSupply); SimplexDirective simplex = new SimplexDirective(); Solution solved = context.Solve(simplex); var report = solved.GetReport(); optimizationModel.OptimizedFunctionResult = solved.Goals.First().ToDouble(); var reportToString = report.ToString(); ViewBag.ReportToString = reportToString; var results = report.ToString().Split(new[] { "Decisions:" }, StringSplitOptions.None)[1].Split(':') .Select(line => line.Remove(line.IndexOf("\r", StringComparison.Ordinal))) .Where(line => !string.IsNullOrEmpty(line)).Select(Convert.ToDouble).ToList(); for (var index = 0; index < furnances.Count; index++) { var furnace = furnances[index]; furnace.GasExpenseToReadjust = results[index]; } return(optimizationModel); }
private void Solv_Click(object sender, EventArgs e) { //Coded by : Mohammed Al Sayed //Zagzig university ,Group B section 13 if (Objtxt.Text == "") { MessageBox.Show("Please Enter The Object Function", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } try { Objtxt.Text = Objtxt.Text.ToLower().TrimEnd(Environment.NewLine.ToCharArray());//triming newline at the end string objectfunction = Objtxt.Text; //begin Setting object function Model model = context.CreateModel();//Creating Linear Programming Model for (int i = 0; i < objectfunction.Length; i++) { //extracting Variables and adding decisions if (char.IsNumber(objectfunction[i]) && char.IsLetter(objectfunction[i + 1])) { objectfunction = objectfunction.Insert(i + 1, "*");//Parsing text into an acceptable Term like 2*x+3*y >> 2x become 2*x } else if (char.IsLetter(objectfunction[i])) { //Adding Decisions(Variables) into model model.AddDecision(new Decision(Domain.RealNonnegative, objectfunction[i].ToString()));//each literal represent a variable } } //end setting object function //begin SettingConstrains if (Cnstrntxt.Text == "") { MessageBox.Show("Please Enter The Constrains", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } Cnstrntxt.Text = Cnstrntxt.Text.ToLower().TrimEnd(Environment.NewLine.ToCharArray()); //removing newline at the end of the text string constrainsRaw = Cnstrntxt.Text; //parsing text into an acceptable MOL term ,, something like that 2*x+4*y a programatic equation for (int i = 0; i < constrainsRaw.Length - 1; i++) { if (char.IsNumber(constrainsRaw[i]) && char.IsLetter(constrainsRaw[i + 1])) //2X { constrainsRaw = constrainsRaw.Insert(i + 1, "*"); //2*x } } //spliting constrains string[] constrains = constrainsRaw.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i <= constrains.GetUpperBound(0); i++) { model.AddConstraint("Constrain_" + i.ToString(), constrains[i]);//each line represent a constrain } //end setting constrains //begin setting goal GoalKind goal; //defining a goal if (tpcom.SelectedIndex == 1) //goal type { goal = GoalKind.Minimize; } else { goal = GoalKind.Maximize; } model.AddGoal("target", goal, objectfunction); //end setting goal //begin solving SimplexDirective simplxReactor = new SimplexDirective(); ///solver object if (Chksensitivity.Checked) { simplxReactor.GetSensitivity = true; //sensitivity } if (ChkInfeasibility.Checked) { simplxReactor.GetInfeasibility = true; //infeasibility } if (cmbAlgorithm.SelectedIndex == 1) { simplxReactor.Algorithm = SimplexAlgorithm.Dual; //Algorithm used } Solution solution = context.Solve(simplxReactor); Report report = solution.GetReport(); //defining a report if (ChkFullReport.Checked) { txtreport.Text = report.ToString(); //presenting the report in report textbox } ResultTextbox.Text = ""; //removing old values if existed ResultTextbox.Text = solution.Goals.First().ToDouble().ToString(); VarResultTextbox.Text = ""; foreach (Decision d in model.Decisions) //adding decisions(variables) and they production size in variable textbox { VarResultTextbox.Text += d.Name + " = " + d.ToString() + Environment.NewLine; } //Duals aka shadow prices if (chkdual.Checked) { txtdual.Text = ""; //removing old values if existed LinearReport lin = ((LinearReport)solution.GetReport()); //generating a linear programming report out of the solution report foreach (Microsoft.SolverFoundation.Services.Constraint constraint in model.Constraints) //getting constrains from the model { foreach (var dual in lin.GetShadowPrices(constraint)) //getting the shadow prices for each constrain { txtdual.Text += dual.Key + " = " + dual.Value.ToDouble().ToString() + Environment.NewLine; } } } //end shadowprices //begin Sensitivity Analysis if (Chksensitivity.Checked) { txtbound.Text = ""; //removing old values if existed LinearReport lin = ((LinearReport)solution.GetReport()); //generating a linear programming report out of the solution report foreach (Microsoft.SolverFoundation.Services.Constraint constraint in model.Constraints) //getting constrains from the model { foreach (var bound in lin.GetConstraintBoundsSensitivity(constraint)) //getting the boundaries prices for each constrain { //parsing the boundaries into intervals //opening the interval if infinity existed txtbound.Text += bound.Key + " = " + bound.Value.Current.ToDouble().ToString() + Environment.NewLine + (Double.IsInfinity(bound.Value.Lower.ToDouble()) ? "]" : "[") + bound.Value.Lower.ToDouble().ToString() + " , " + bound.Value.Upper.ToDouble().ToString() + (Double.IsInfinity(bound.Value.Upper.ToDouble()) ? "[" : "]") + Environment.NewLine + Environment.NewLine ; } } } context.ClearModel();//killing the model object so we can create a new one //end solving //begin handling errors } catch (Exception ex) { context.ClearModel(); txtreport.Text = "An Error have occured If you're sure about you entries " + "Please Send this report to the programmer" + Environment.NewLine + Environment.NewLine; txtreport.Text += Objtxt.Text + Environment.NewLine + Environment.NewLine; txtreport.Text += Cnstrntxt.Text + Environment.NewLine + Environment.NewLine; txtreport.Text += ex.Message; txtreport.ForeColor = Color.Red; MessageBox.Show("Error,Please Check your entries" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } tabControl1.SelectedIndex = 1; //end handling errors }
public static TradeUpContract findBestContract(List<Skin> higherTier, List<Skin> lowerTier) { SolverContext context = SolverContext.GetContext(); Model model = context.CreateModel(); var targets = getDecisions(higherTier, 1); foreach(var decision in targets) { model.AddDecision(decision.Item1); } var decisions = getDecisions(lowerTier, 10); foreach (var decision in decisions) { model.AddDecision(decision.Item1); } List<string> basicConstraints = new List<string>(); foreach (var target in higherTier) { basicConstraints.Add(getBasicConstraints(target, 1)); } basicConstraints.Add(getBasicConstraints(lowerTier, 10)); int i = 0; foreach(var constraint in basicConstraints) { model.AddConstraint("basicConstraint" + i, constraint); i++; } List<string> complexConstraintsBase = getComplexConstraintsBase(lowerTier); List<string> complexConstraints = new List<string>(); foreach(var target in targets) { var constraintTemplate = "{0} - 1 + (({1}) / 10) * {2} + {3} <= {4}"; complexConstraints.Add( string.Format( constraintTemplate, getVariableName(target.Item2, target.Item3), string.Join(" + ",complexConstraintsBase), target.Item2.getFloatValueRange().ToString(CultureInfo.InvariantCulture), target.Item2.minFloatValue.ToString(CultureInfo.InvariantCulture), EnumUtil.getQualityBorder(target.Item3).ToString(CultureInfo.InvariantCulture))); } i = 0; foreach(var constraint in complexConstraints) { model.AddConstraint("ComplexConstraint"+i, constraint); i++; } string goal = generateGoal(targets, decisions); model.AddGoal("mainGoal", GoalKind.Maximize, goal); SimplexDirective directive = new SimplexDirective(); directive.Arithmetic = Arithmetic.Exact; Solution solution = context.Solve(directive); Report report = solution.GetReport(); //Console.WriteLine("x1: {0}, x: {1}", x1, x2, x3); //Console.WriteLine("Gain: {0}", goal); Console.Write("{0}", report); context.ClearModel(); var contract = new TradeUpContract(); foreach(var decision in decisions) { if(decision.Item1.ToDouble() > 0) { contract.tradeUpList.Add(new Tuple<Skin, Quality, int>(decision.Item2, decision.Item3, (int)Math.Round(decision.Item1.ToDouble()))); } } foreach (var target in targets) { if (target.Item1.ToDouble() > 0) { contract.resultsList.Add(new Tuple<Skin, Quality>(target.Item2, target.Item3)); } } contract.potentialGain = model.Goals.First().ToDouble() / contract.resultsList.Count; return contract; }
static void Sample1() { SolverContext context = SolverContext.GetContext(); Model model = context.CreateModel(); Decision x1 = new Decision(Domain.IntegerRange(0, 10), "x1"); Decision x2 = new Decision(Domain.IntegerRange(0, 10), "x2"); Decision x3 = new Decision(Domain.IntegerRange(0, 10), "x3"); Decision t1fn = new Decision(Domain.IntegerRange(0, 1), "t1fn"); Decision t1mw = new Decision(Domain.IntegerRange(0, 1), "t1mw"); Decision t1ft = new Decision(Domain.IntegerRange(0, 1), "t1ft"); Decision t2fn = new Decision(Domain.IntegerRange(0, 1), "t2fn"); Decision t2mw = new Decision(Domain.IntegerRange(0, 1), "t2mw"); Decision t2ft = new Decision(Domain.IntegerRange(0, 1), "t2ft"); Rational M = 100; //model.AddDecisions(x1, x2); model.AddDecisions(x1, x2, x3, t1fn, t1mw, t1ft, t2fn, t2mw, t2ft); model.AddConstraint("Row0", x1 + x2 + x3 == 10); model.AddConstraint("Quality1", t1fn + t1mw + t1ft == 1); model.AddConstraint("Quality2", t2fn + t2mw + t2ft == 1); //string fnTerm = "" //model.AddConstraint("Row1", (x1 * 0.035 + x2 * 0.11) / 10 <= 0.07); //target 1 model.AddConstraint("Target1FN", " t1fn - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) <= 0.07"); model.AddConstraint("Target1MW", " t1mw - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) <= 0.15"); model.AddConstraint("Target1FT", " t1ft - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) <= 0.35"); //target 2 model.AddConstraint("Target2FN", " t2fn - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) * 0.72 + 0.06 <= 0.07"); model.AddConstraint("Target2MW", " t2mw - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) * 0.72 + 0.06 <= 0.15"); model.AddConstraint("Target2FT", " t2ft - 1 + ((x1 * 0.035 + x2 * 0.11 + x3 * 0.25) / 10) * 0.72 + 0.06 <= 0.35"); //model.AddConstraint("Row2", mw * (x1 * 0.035 + x2 * 0.11) / 10 <= 0.15); //model.AddConstraint("Row2", x2 + z * 100 <= 100); Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, (t1fn * 120 + t1mw * 61 + t1ft * 34 + t2fn * 76 + t2mw * 61 + t2ft * 34) - (x1 * 9 + x2 * 8 + x3 * 5) * 2); //Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, // "Max[x1-0.07,0] * 4 - x1"); SimplexDirective directive = new SimplexDirective(); directive.Arithmetic = Arithmetic.Exact; Solution solution = context.Solve(directive); Report report = solution.GetReport(); Console.WriteLine("x1: {0}, x: {1}", x1, x2, x3); Console.WriteLine("Gain: {0}", goal); Console.Write("{0}", report); context.ClearModel(); }
public Solution alternative_solve(out Dictionary <Models.Shift, Decision> shiftsN, out Dictionary <Models.Shift, Decision> shiftsO) { SolverContext SC = SolverContext.GetContext(); Model model = SC.CreateModel(); var maxRq = HalfHourRequirements.Max(x => x.RequiredForce); shiftsN = shiftsO = null; //split shifts into two Dictionaries (each dict holds each Shift as key and the Decision variable as Value) var normal_shifts = new Dictionary <Models.Shift, Decision>(); //for normal shifts int i = 0; Shifts.ForEach(x => { Decision des = new Decision(Domain.IntegerRange(0, maxRq), string.Format("{0}_{1}", x.Name, i)); normal_shifts.Add(x, des); model.AddDecision(des); i++; }); var overtime_shifts = new Dictionary <Models.Shift, Decision>(); //for overtime shifts i = 0; OvertimeShifts.ForEach(x => { Decision des = new Decision(Domain.IntegerRange(0, maxRq), string.Format("{0}_{1}", x.Name, i)); overtime_shifts.Add(x, des); model.AddDecision(des); i++; }); List <Decision> excess = new List <Decision>(); //used to calculate sum of excess values HalfHourRequirements.ForEach(hh => { var ShiftsActive = new List <Decision>(); foreach (var entry in normal_shifts) { if (entry.Key.IncludesHalfHour(hh.Start)) { ShiftsActive.Add(entry.Value); excess.Add(entry.Value); } } foreach (var entry in overtime_shifts) { if (entry.Key.IncludesHalfHour(hh.Start)) { ShiftsActive.Add(entry.Value); excess.Add(entry.Value); } } //add constraint for sum of force of active shifts on that halfhour //if we need agents but no shifts exists for a halfhour, do not add a constraint if (ShiftsActive.Count > 0) { var sum_constr = new SumTermBuilder(ShiftsActive.Count); ShiftsActive.ForEach(s => sum_constr.Add(s)); var constr = sum_constr.ToTerm() >= hh.RequiredForce; model.AddConstraint(string.Format("_{0:hh}{0:mm}", hh.Start), constr); //constr = sum_constr.ToTerm() <= hh.RequiredForce * 2.0; //model.AddConstraint(string.Format("limitconst_for_{0:hh}{0:mm}", hh.Start), constr); } }); //Constrain maximum number of agents working 8hour shifts var max_agents_constraint = new SumTermBuilder(Shifts.Count); foreach (var entry in normal_shifts) { max_agents_constraint.Add(entry.Value); } var ma_constr = max_agents_constraint.ToTerm() <= MaxAgents; model.AddConstraint("Max_agents_constraint", ma_constr); //1st goal: Minimize overtime shifts (if work manageable by normal shifts, no overtime shifts will be used) var overtime_obj = new SumTermBuilder(OvertimeShifts.Count); foreach (var entry in overtime_shifts) { overtime_obj.Add(entry.Value); } model.AddGoal("Minimize_overtime", GoalKind.Minimize, overtime_obj.ToTerm()); //2st goal: Minimize normal shifts var normal_obj = new SumTermBuilder(Shifts.Count); foreach (var entry in normal_shifts) { normal_obj.Add(entry.Value); } model.AddGoal("Minimize_normal", GoalKind.Minimize, normal_obj.ToTerm()); //3rd goal: Try to minimize excess var sumReqs = HalfHourRequirements.Sum(x => x.RequiredForce); model.AddGoal("Minimize_excess", GoalKind.Minimize, Model.Sum(excess.ToArray()) - sumReqs); SimplexDirective simplex = new SimplexDirective(); Solution solution = SC.Solve(simplex); shiftsN = normal_shifts; shiftsO = overtime_shifts; return(solution); }