public Reporte(Simplex sollutions) { _sollutions = sollutions; SimplexSolverParams solverParams = new SimplexSolverParams(); solverParams.GetSensitivityReport = true; _sollutions.Solver.Solve(solverParams); _reportSensitivity = _sollutions.Solver.GetReport(LinearSolverReportType.Sensitivity); _sensitivityReport = _reportSensitivity as ILinearSolverSensitivityReport; }
public void Get() { SimplexSolver solver = new SimplexSolver(); double[] estimatedProfitOfProjectX = new double[] { 1, 1.8, 1.6, 0.8, 1.4 }; double[] capitalRequiredForProjectX = new double[] { 6, 12, 10, 4, 8 }; double availableCapital = 20; int[] chooseProjectX = new int[5]; int profit; solver.AddRow("profit", out profit); solver.AddGoal(profit, 0, false); int expenditure; solver.AddRow("expenditure", out expenditure); solver.SetBounds(expenditure, 0, availableCapital); for (int i = 0; i < 5; i++) { solver.AddVariable(string.Format("project{0}", i), out chooseProjectX[i]); solver.SetBounds(chooseProjectX[i], 0, 1); solver.SetIntegrality(chooseProjectX[i], true); solver.SetCoefficient(profit, chooseProjectX[i], estimatedProfitOfProjectX[i]); solver.SetCoefficient(expenditure, chooseProjectX[i], capitalRequiredForProjectX[i]); } SimplexSolverParams param = new SimplexSolverParams(); param.MixedIntegerGenerateCuts = true; solver.Solve(param); Console.WriteLine(solver.MipResult); for (int i = 0; i < 5; i++) { Console.WriteLine("Project {0} is {1} selected.", i, solver.GetValue(chooseProjectX[i]) == 1 ? "" : "not "); } Console.WriteLine("The estimated total profit is: ${0} million.", (double)solver.GetValue(profit).ToDouble()); Console.WriteLine("The total expenditure is: ${0} million.", solver.GetValue(expenditure).ToDouble()); }
/// <summary> /// Solves a sample (randomly generated?) cutting stock problem. /// Given a bolt of cloth of fixed width, and demand for cut strips of the cloth, determine the min "loss" cut patterns to use and how many /// of them. /// Loss is defined as the scrap thrown away. /// It is acceptable to have extra cut widths made. They do not contribute to the cost. (this may be unrealistic in the real world) /// Solver runs by 1st creating an enumeration of possible cut patterns using a CspSolver, then choosing between the patterns and selecting a qty of the patterns such that the /// amount of scrap is minimized and all demand is met using the SimplexSolver MIP code. /// /// In an industrial case, there would likely be more constraints in the generation of the cut patterns. There can be other restrictions such as "these can't be done together" /// or "these MUST be done together (matching pattern or color?)". This can easily be added to the CspSolver model. /// Also, there are likely other characteristics of the cuts or the master problem which would need adaptations. /// /// Further, the limit on the columns generated is implemented in a very arbitrary order. It is more likely that some ordering of the /// value of the columns is needed. In most industrial occurances, the dual variables from the LP relaxation would likely be used to /// guide the generation of columns in an interative fasion rather than a one-time shot at the beginning. /// /// YMMV /// </summary> public static void ShortCuttingStock() { Console.WriteLine("*** Short Cutting Stock ***"); int NumItems = 5; // how many cut widths to generate int ClothWidth = 40; // width of the stock to cut the widths from double efficiency = 0.7; // reject cut patterns less than this % used of the clothwidth int maxPatterns = 100; // max # of patterns to generate bool verbose = true; // set this to true if you want some (useful?) output bool saveMpsFile = false; // set this to true if you want it to save an mps file in c:\\temp\\cutstock.mps int itemSizeMin = 5; // minimum size for random generation of cut int itemSizeMax = 10; // maximum size for random generation of cut int itemDemandMin = 10; // minimum random demand for each cut int itemDemandMax = 40; // maximum random demand for each cut int seed = 12447; // use System.DateTime.Now.Millisecond; instead if you want a random problem. if (verbose) { System.Console.WriteLine(String.Format("Random seed={0}\tmaxWidth={1}", seed, ClothWidth)); } Random rand = new Random(seed); int[] cuts = new int[NumItems]; int[] demand = new int[NumItems]; // item weights and demands for (int cnt = 0; cnt < NumItems; cnt++) { cuts[cnt] = rand.Next(itemSizeMin, itemSizeMax);; demand[cnt] = rand.Next(itemDemandMin, itemDemandMax); if (verbose) { System.Console.WriteLine(String.Format("item[{0}]\tweight={1}\tdemand={2}", cnt, cuts[cnt], demand[cnt])); } } List <int[]> patterns; SolveKnapsack(maxPatterns, cuts, ClothWidth, efficiency, out patterns); SimplexSolver solver2 = new SimplexSolver(); int vId = 0; int[] usage = new int[patterns.Count]; // construct rows that make sure that the demand is met for each kind of cut for (int cnt = 0; cnt < NumItems; cnt++) { solver2.AddRow(String.Format("item{0}", cnt), out vId); solver2.SetBounds(vId, demand[cnt], Rational.PositiveInfinity); } int patCnt = 0; if (verbose) { System.Console.WriteLine(String.Format("Generated {0} patterns", patterns.Count)); } // set usage coeffs (A matrix entries) -- put the patterns as columns in the MIP. Dictionary <int, int> patIdForCol = new Dictionary <int, int>(); foreach (int[] pattern in patterns) { int pId = 0; String varName = String.Format("Pattern{0}", patCnt); solver2.AddVariable(varName, out pId); patIdForCol[pId] = patCnt; solver2.SetIntegrality(pId, true); solver2.SetBounds(pId, 0, Rational.PositiveInfinity); for (int cnt = 0; cnt < NumItems; cnt++) { solver2.SetCoefficient(cnt, pId, pattern[cnt]); // set the coefficient in the matrix // accumulate the quantity used for this pattern. It will be used to figure out the scrap later. usage[patCnt] += pattern[cnt] * cuts[cnt]; } patCnt++; } // set objective coeffs. --- the cost is the scrap solver2.AddRow("Scrap", out vId); for (int cnt = 0; cnt < patterns.Count; cnt++) { int colId = solver2.GetIndexFromKey(String.Format("Pattern{0}", cnt)); solver2.SetCoefficient(vId, colId, (ClothWidth - usage[cnt])); } solver2.AddGoal(vId, 0, true); // invoke the IP solver. SimplexSolverParams parms = new SimplexSolverParams(); parms.MixedIntegerGenerateCuts = true; parms.MixedIntegerPresolve = true; if (saveMpsFile) { MpsWriter writer = new MpsWriter(solver2); using (TextWriter textWriter = new StreamWriter(File.OpenWrite("c:\\temp\\cutstock.mps"))) { writer.WriteMps(textWriter, true); } } solver2.Solve(parms); if (solver2.LpResult == LinearResult.Optimal && solver2.MipResult == LinearResult.Optimal) { //Rational[] solutionVals = solver2.GetValues(); int goalIndex = 0; // output if desired. if (verbose) { System.Console.WriteLine("Solver complete, printing cut plan."); foreach (int cnt in solver2.VariableIndices) { Rational val = solver2.GetValue(cnt); if (val != 0) { if (solver2.IsGoal(cnt)) { goalIndex = cnt; System.Console.WriteLine(String.Format("Goal:{0}\t: {1}\t", val, solver2.GetKeyFromIndex(cnt))); } else if (solver2.IsRow(cnt)) { System.Console.WriteLine(String.Format("{0}:\tValue= {1}\t", solver2.GetKeyFromIndex(cnt), val)); } else { System.Console.Write(String.Format("{0}\tQuantity={1}:\t", solver2.GetKeyFromIndex(cnt), val)); for (int cnt2 = 0; cnt2 < NumItems; cnt2++) { System.Console.Write(String.Format("{0} ", patterns[patIdForCol[cnt]][cnt2])); } System.Console.WriteLine(String.Format("\tUsage:{0} / {2} efficiency={1}%", usage[cnt - NumItems], (int)(100 * (double)usage[cnt - NumItems] / (double)ClothWidth), ClothWidth)); } } } System.Console.WriteLine(String.Format("Total scrap={0}", solver2.GetSolutionValue(goalIndex))); } } else { System.Console.WriteLine("Generated problem is infeasible. It is likely that more generated columns are needed."); } Console.WriteLine(); }
public List <Bag.Item> LinearProgramming(List <Item> items) { List <Bag.Item> choosenItems = new List <Bag.Item>(); int itemsCount = items.Count; double capacity = MaxWeightAllowed; SimplexSolver solver = new SimplexSolver(); //double[] estimatedProfitOfProjectX = new double[] { 1, 1.8, 1.6, 0.8, 1.4 }; //double[] capitalRequiredForProjectX = new double[] { 6, 12, 10, 4, 8 }; //double availableCapital = 20; //int[] chooseProjectX = new int[5]; double[] values = new double[itemsCount]; double[] weights = new double[itemsCount]; for (int i = 0; i < itemsCount; i++) { values[i] = items[i].Value; weights[i] = items[i].Weight; } int[] chosenItems = new int[itemsCount]; //int profit; //solver.AddRow("profit", out profit); //solver.AddGoal(profit, 0, false); int MaximumValue; solver.AddRow("MaximumValue", out MaximumValue); solver.AddGoal(MaximumValue, 0, false); //int expenditure; //solver.AddRow("expenditure", out expenditure); //solver.SetBounds(expenditure, 0, availableCapital); int MaximumWeight; solver.AddRow("MaximumWeight", out MaximumWeight); solver.SetBounds(MaximumWeight, 0, capacity); //for (int i = 0; i < 5; i++) //{ // solver.AddVariable(string.Format("project{0}", i), // out chooseProjectX[i]); // solver.SetBounds(chooseProjectX[i], 0, 1); // solver.SetIntegrality(chooseProjectX[i], true); // solver.SetCoefficient(profit, chooseProjectX[i], // estimatedProfitOfProjectX[i]); // solver.SetCoefficient(expenditure, chooseProjectX[i], // capitalRequiredForProjectX[i]); //} for (int i = 0; i < itemsCount; i++) { solver.AddVariable(string.Format("Item{0}", i), out chosenItems[i]); solver.SetBounds(chosenItems[i], 0, 1); solver.SetIntegrality(chosenItems[i], true); solver.SetCoefficient(MaximumValue, chosenItems[i], values[i]); solver.SetCoefficient(MaximumWeight, chosenItems[i], weights[i]); } //SimplexSolverParams param = new SimplexSolverParams(); //param.MixedIntegerGenerateCuts = true; //solver.Solve(param); SimplexSolverParams param = new SimplexSolverParams(); param.MixedIntegerGenerateCuts = true; solver.Solve(param); //Console.WriteLine(solver.MipResult); //for (int i = 0; i < 5; i++) //{ // Console.WriteLine("Project {0} is {1} selected.", i, // solver.GetValue(chooseProjectX[i]) == 1 ? "" : "not "); //} //Console.WriteLine("The estimated total profit is: ${0} million.", // (double)solver.GetValue(profit).ToDouble()); //Console.WriteLine("The total expenditure is: ${0} million.", // solver.GetValue(expenditure).ToDouble()); //string result = ""; for (int i = 0; i < itemsCount; i++) { if (solver.GetValue(chosenItems[i]) == 1) { //result += "Selected Item " + i + " "; choosenItems.Add(items[i]); } } //result += " value "+(double)solver.GetValue(MaximumValue).ToDouble()+ " weight "+ solver.GetValue(MaximumWeight).ToDouble(); return(choosenItems); }
protected static void CCN_Simplex() { int param1 = ReadSelectionInt("Max agents", 100, min: 1, max: 1000); var param3 = ReadSelectionInt("Max time\"", 120, min: 10, max: 1200); //Set agent shifts var solveShifts = new CSP.ShiftsPlanner(param1); TimeSpan ts8h = GetTimeSpanHours(8); TimeSpan ts9h = GetTimeSpanHours(9); TimeSpan ts10h = GetTimeSpanHours(10); TimeSpan ts30mi = GetTimeSpanMinutes(30); var shifts = new List <CSP.Models.Shift>(); shifts.Add(new CSP.Models.Shift(name: "A", start: GetTimeSpanHours(7), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "G", start: GetTimeSpanHours(8), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "B", start: GetTimeSpanHours(9), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "I", start: GetTimeSpanHours(10), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "E", start: GetTimeSpanHours(11), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "D", start: GetTimeSpanHours(13), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "C", start: GetTimeSpanHours(15), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "CL", start: GetTimeSpanHours(16), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "H", start: GetTimeSpanHours(17), duration: ts8h)); shifts.Add(new CSP.Models.Shift(name: "A++", start: GetTimeSpanHours(7), duration: ts10h)); shifts.Add(new CSP.Models.Shift(name: "B+", start: GetTimeSpanHours(9), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "B++", start: GetTimeSpanHours(9), duration: ts10h)); shifts.Add(new CSP.Models.Shift(name: "I+", start: GetTimeSpanHours(10), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "I++", start: GetTimeSpanHours(10), duration: ts10h)); shifts.Add(new CSP.Models.Shift(name: "E+", start: GetTimeSpanHours(11), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "E++", start: GetTimeSpanHours(11), duration: ts10h)); shifts.Add(new CSP.Models.Shift(name: "+D", start: GetTimeSpanHours(12), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "D++", start: GetTimeSpanHours(13), duration: ts10h)); shifts.Add(new CSP.Models.Shift(name: "C+", start: GetTimeSpanHours(15), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "CL+", start: GetTimeSpanHours(16), duration: ts9h)); shifts.Add(new CSP.Models.Shift(name: "++H", start: GetTimeSpanHours(15), duration: ts10h)); solveShifts.Shifts = shifts; //Set requirements per shift int[] liveData = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 6, 7, 9, 11, 22, 25, 21, 32, 44, 38, 33, 48, 41, 54, 50, 42, 43, 45, 60, 62, 56, 44, 33, 22, 11, 18, 16, 24, 28, 6, 12, 15, 8, 6 }; var requirements = new List <CSP.Models.HalfHourRequirement>(); TimeSpan ts = GetTimeSpanHours(0); for (int i = 0; i < liveData.Length; i++) { requirements.Add(new CSP.Models.HalfHourRequirement(start: ts, requiredForce: liveData[i])); ts = ts.Add(ts30mi); } solveShifts.HalfHourRequirements = requirements; //pair shifts with vids Dictionary <CSP.Models.Shift, int> shiftsX; int vidGoal; var SX = solveShifts.PrepareSimplexSolver(maxAgents: param1, shiftsExt: out shiftsX, vidGoal: out vidGoal); var sxParams = new SimplexSolverParams(); ILinearSolution solution = null; Task taskSolve = new Task(() => { solution = SX.Solve(sxParams); }); Stopwatch timer = new Stopwatch(); timer.Start(); taskSolve.Start(); TimeSpan limit = new TimeSpan(hours: 0, minutes: 0, seconds: param3); while (!taskSolve.IsCompleted) { Console.SetCursorPosition(0, Console.CursorTop); Console.Write(" {0:hh}:{0:mm}:{0:ss}", timer.Elapsed); Thread.Sleep(millisecondsTimeout: 500); } Console.WriteLine("\n"); timer.Stop(); if (solution.Result == LinearResult.Feasible || solution.Result == LinearResult.Optimal) { Console.WriteLine(" solved as {1} after {0}", timer.Elapsed, solution.Result); Console.WriteLine("Goal: {0}", solution.GetValue(vidGoal).ToDouble()); List <CSP.Models.ShiftForce> shiftsForce = new List <CSP.Models.ShiftForce>(); foreach (var shift in shiftsX) { var force = solution.GetValue(shift.Value).ToDouble(); shiftsForce.Add(new CSP.Models.ShiftForce(shift: shift.Key, force: (int)force)); } solveShifts.ShowSolution(1, shiftsForce, showAgents: true, showSlots: true); } else { Console.WriteLine(" no solved :: {1} after {0}", timer.Elapsed, solution.Result); } }