public void DegeneracyTest() { #region Arrange var target = new Solver(); var lc1 = new LinearConstraint() { Coefficients = new double[3] { 1, 1, 0 }, Relationship = Relationship.LessThanOrEquals, Value = 1 }; var lc2 = new LinearConstraint() { Coefficients = new double[3] { 0, -1, 1 }, Relationship = Relationship.LessThanOrEquals, Value = 0 }; var constraints = new List<LinearConstraint>() { lc1, lc2 }; var goal = new Goal() { Coefficients = new double[3] { 1, 1, 1 }, ConstantTerm = 0 }; var model = new Model() { Constraints = constraints, Goal = goal, GoalKind = GoalKind.Maximize }; var expected = new Solution() { Decisions = new double[3] { 0, 1, 1 }, Quality = SolutionQuality.Optimal, AlternateSolutionsExist = false, OptimalValue = 2 }; #endregion //Act var actual = target.Solve(model); //Assert CollectionAssert.AreEqual(expected.Decisions, actual.Decisions); Assert.AreEqual(expected.Quality, actual.Quality); Assert.AreEqual(expected.AlternateSolutionsExist, actual.AlternateSolutionsExist); }
public void Simple2PhaseFromPaper() { #region Arrange var target = new Solver(); var lc1 = new LinearConstraint() { Coefficients = new double[2] { 1, 1 }, Relationship = Relationship.GreaterThanOrEquals, Value = 4 }; var lc2 = new LinearConstraint() { Coefficients = new double[2] { 1, -1 }, Relationship = Relationship.GreaterThanOrEquals, Value = 1 }; var lc3 = new LinearConstraint() { Coefficients = new double[2] { -1, 2 }, Relationship = Relationship.GreaterThanOrEquals, Value = -1 }; var constraints = new List<LinearConstraint>() { lc1, lc2, lc3 }; var goal = new Goal() { Coefficients = new double[2] { 1, 2 }, ConstantTerm = 0 }; var model = new Model() { Constraints = constraints, Goal = goal, GoalKind = GoalKind.Minimize }; var expected = new Solution() { Decisions = new double[2] { 3, 1 }, Quality = SolutionQuality.Optimal, AlternateSolutionsExist = false, OptimalValue = 5 }; #endregion //Act var actual = target.Solve(model); //Assert CollectionAssert.AreEqual(expected.Decisions, actual.Decisions); Assert.AreEqual(expected.Quality, actual.Quality); Assert.AreEqual(expected.AlternateSolutionsExist, actual.AlternateSolutionsExist); }
public void TwoPhaseClassTest() { #region Arrange var target = new Solver(); var lc1 = new LinearConstraint() { Coefficients = new double[2] { 1, 1 }, Relationship = Relationship.LessThanOrEquals, Value = 35 }; var lc2 = new LinearConstraint() { Coefficients = new double[2] { 1, 2 }, Relationship = Relationship.LessThanOrEquals, Value = 38 }; var lc3 = new LinearConstraint() { Coefficients = new double[2] { 2, 2 }, Relationship = Relationship.LessThanOrEquals, Value = 50 }; var constraints = new List<LinearConstraint>() { lc1, lc2, lc3 }; var goal = new Goal() { Coefficients = new double[2] { 350, 450 }, ConstantTerm = 0 }; var model = new Model() { Constraints = constraints, Goal = goal, GoalKind = GoalKind.Maximize }; var expected = new Solution() { Decisions = new double[2] { 12, 13 }, Quality = SolutionQuality.Optimal, AlternateSolutionsExist = false, OptimalValue = 10050 // 12*350 + 13*450 }; var actual = target.Solve(model); #endregion ////Act ////Assert CollectionAssert.AreEqual(expected.Decisions, actual.Decisions); Assert.AreEqual(expected.Quality, actual.Quality); Assert.AreEqual(expected.AlternateSolutionsExist, actual.AlternateSolutionsExist); }
public Solution Solve(Model model) { DenseVector testVect = DenseVector.Create(10, delegate(int s) { return s; }); DenseMatrix coefficients = createMatrix(model); //gets the coefficients from the goal DenseVector objFunCoeffs = new DenseVector(model.Goal.Coefficients); //adds zeroes for the surplus/slack/artificial variables DenseVector objFunValues = DenseVector.Create((coefficients.ColumnCount), delegate(int s) { return 0; }); objFunValues.SetSubVector(0, objFunCoeffs.Count, objFunCoeffs); //flips the sign of everything if (model.GoalKind == GoalKind.Maximize) { objFunValues = DenseVector.Create((coefficients.ColumnCount), delegate(int s) { return -objFunValues[s]; }); } //here so I don't have to pass the model in :) numConstraints = model.Constraints.Count; //Maybe I could be smarter about where I put this (at the end of createMatrix?) //take care of artificial variable stuff if(numArtificial > 0) { //adds the z row to the coefficients matrix //adds the column first coefficients = (DenseMatrix)coefficients.Append(DenseVector.Create((coefficients.RowCount), delegate(int s) { return 0; }).ToColumnMatrix()); coefficients = (DenseMatrix)coefficients.InsertRow(coefficients.RowCount, DenseVector.Create(coefficients.ColumnCount, delegate(int s) { if (s == coefficients.ColumnCount - 1) return 1; else return -objFunValues[s]; })); //adds a 0 to match the z row rhsValues = DenseVector.Create(rhsValues.Count + 1, delegate(int s) { if (s == rhsValues.Count) { return model.Goal.ConstantTerm; } else { return rhsValues[s]; } }); //changes the objFunValues to be the w thingy objFunValues = DenseVector.Create(coefficients.ColumnCount, delegate(int s) { double sum = 0; //minus 1 because we also added a column for z if (s < coefficients.ColumnCount - numArtificial - 1) { //calculate each w row entry by foreach (int index in artificialRows) { sum += coefficients[index, s]; } return sum; } else { return 0; } }); //z is now a basic variable?? basics.Add(coefficients.ColumnCount - 1); printMat(coefficients); //solves it for that optimize(coefficients, objFunValues, true); basics.Remove(coefficients.ColumnCount - 1); //gets rid of the last value rhsValues = (DenseVector)rhsValues.SubVector(0, (rhsValues.Count - 1)); //chops off the z row and the artificial variables coefficients = (DenseMatrix)coefficients.SubMatrix(0, coefficients.RowCount - 1, 0, coefficients.ColumnCount - 1 - numArtificial); } printMat(coefficients); optimize(coefficients, objFunValues, false); /* * To find the solution: * The first columns in the mattress (that aren't * ssa variables) should be basic variables * Find what the final value is by finding their indices * in basics and then the value at that index in xprimes * should be what you're looking for I think * At least it's somewhere in xprimes */ double[] solution = new double[model.Goal.Coefficients.Length]; double op = model.Goal.ConstantTerm; for(int i = 0; i < solution.Length; i++) { solution[i] = xPrime[basics.IndexOf(i), 0]; op += solution[i] * model.Goal.Coefficients[i]; } Solution sol = new Solution() { Decisions = solution, OptimalValue = op, AlternateSolutionsExist = false, Quality = SolutionQuality.Optimal }; return sol; }