示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        public DenseMatrix createMatrix(Model model)
        {
            int numConstraints = model.Constraints.Count;
            int numDecisionVars = model.Goal.Coefficients.Length;
            int varCounter = numDecisionVars;
            //  matrix(rows, columns)
            DenseMatrix coefficients = new DenseMatrix(numConstraints, numDecisionVars);
            DenseMatrix artificialVars = new DenseMatrix(numConstraints, 1);
            var constraintCounter = 0;
            this.rhsValues = new DenseVector(numConstraints);
            this.basics = new List<int>();
            this.artificialRows = new List<int>();
            foreach (var constraint in model.Constraints) {
                rhsValues[constraintCounter] = constraint.Value;

                // if the constraint RHS is negative, invert the coefficients and flip the inequality sign
                if (constraint.Value < 0)
                {
                    for (int i = 0; i< model.Goal.Coefficients.Length; i++) {
                        model.Goal.Coefficients[i] = model.Goal.Coefficients[i] * -1;
                    }
                    if (constraint.Relationship == Relationship.LessThanOrEquals)
                    {
                        constraint.Relationship = Relationship.GreaterThanOrEquals;
                    }
                    else if (constraint.Relationship == Relationship.GreaterThanOrEquals)
                    {
                        constraint.Relationship = Relationship.LessThanOrEquals;
                    }
                    // also flip the rhs value which we already put in the array for the simplex setup
                    rhsValues[constraintCounter] = rhsValues[constraintCounter] * -1;
                }

                coefficients.SetRow(constraintCounter, 0, constraint.Coefficients.Length, new DenseVector(constraint.Coefficients));
                // if it's a less than, add a slack column to the coefs matrix
                if (constraint.Relationship == Relationship.LessThanOrEquals)
                {
                    DenseVector slack = DenseVector.Create(model.Constraints.Count, delegate(int s) { return 0; });
                    slack.At(constraintCounter, 1);
                    coefficients = (DenseMatrix)coefficients.Append(slack.ToColumnMatrix());

                    this.basics.Add(varCounter);
                }
                else
                {
                    // Need to add an artificial variable for >= and = constraints

                    DenseVector surplus = DenseVector.Create(model.Constraints.Count, delegate(int s) { return 0; });
                    surplus.At(constraintCounter, -1);
                    coefficients = (DenseMatrix)coefficients.Append(surplus.ToColumnMatrix());

                    DenseVector artificial = DenseVector.Create(model.Constraints.Count, delegate(int s) { return 0; });
                    artificial.At(constraintCounter, 1);
                    artificialVars = (DenseMatrix)artificialVars.Append(artificial.ToColumnMatrix());

                    // Keeps track of the rows with artificial variable, for setting w
                    artificialRows.Add(constraintCounter);
                }
                varCounter++;
                constraintCounter++;
            }

            // put the constraints and stuff into the matrix
            if (artificialVars.ColumnCount > 1)
            {
                artificialVars = (DenseMatrix)artificialVars.SubMatrix(0, artificialVars.RowCount, 1, artificialVars.ColumnCount - 1);

                for (int i = coefficients.ColumnCount; i < coefficients.ColumnCount + artificialVars.ColumnCount; i++)
                {
                    this.basics.Add(i);
                }

                coefficients = (DenseMatrix)coefficients.Append(artificialVars);

                numArtificial = artificialVars.ColumnCount;
            }
            else
            {
                numArtificial = 0;
            }

            return coefficients;
        }
示例#4
0
        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);
        }
示例#5
0
        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;
        }