Exemple #1
0
        public SimplexResult Solve(SimplexTuple tuple)
        {
            var multiplier = 1;
            if (tuple.Type == ObjectiveFunctionType.Min) multiplier *= -1;
            var standartTuple = (new SimplexInputBuilder()).ConvertToStandartForm(tuple);
            var bInternal = InitializeSimplex(tuple);

            iteration = 0;
            var columns = Enumerable.Range(0, tuple.ObjFuncCoeffs.Count).ToArray();
            var AB = standartTuple.EqualityCoeffs.Extract(bInternal.InequalityIndexes, columns);
            var bB = standartTuple.FreeTerms.Extract(bInternal.InequalityIndexes);

            var vector = SolveInternal(standartTuple.EqualityCoeffs, standartTuple.FreeTerms, standartTuple.ObjFuncCoeffs,
                                       bInternal, AB, bB);
            //Multiply result to -1 if we have min function at start
            var optimalValue = multiplier*(standartTuple.ObjFuncCoeffs.ToRowMatrix()*vector)[0];

            return new SimplexResult {OptimalValue = optimalValue, OptimalVector = vector, Iteration = iteration};
        }
Exemple #2
0
        internal StartingBasis InitializeSimplex(SimplexTuple tuple)
        {
            var negativeCount = tuple.FreeTerms.Count(x => x < 0);
            int varCount = tuple.ObjFuncCoeffs.Count;

            var startingEq = new List<int>(varCount);
            for (int i = 0; i < tuple.EqualityCoeffs.RowCount; i++)
            {
                var row = tuple.EqualityCoeffs.Row(i);
                if (row.Count(x => x.FloatEquals(-1)) == 1
                    && row.Count(x => x.FloatEquals(0)) == (varCount - 1)
                    && startingEq.Count < varCount)
                    startingEq.Add(i);
            }
            //If min index > 0 -> all free terms are positive.
            //This means that basis just zero variables and indexes of that inequalities
            if (negativeCount == 0)
            {
                return new StartingBasis
                    {
                        InequalityIndexes = startingEq.ToArray(),
                        FeasibleBasis = new double[varCount]
                    };
            }

            //Create auxilary problem
            var auxObjFunc = new List<double>(varCount + negativeCount);
            auxObjFunc.AddRange(tuple.ObjFuncCoeffs.Select(ofc => 0).Select(dummy => (double) dummy));

            var auxA = tuple.EqualityCoeffs.Clone();
            var auxb = tuple.FreeTerms.Clone();
            int rowCount = tuple.EqualityCoeffs.RowCount;
            //for each negative index we should go with added slack variable
            //TODO: work with Dense/Sparse vectors
            for (int i = 0; i < tuple.EqualityCoeffs.RowCount; i++)
            {
                if (tuple.FreeTerms[i] >= 0) continue;
                //add a new slack variable to obj function with coeff -1
                auxObjFunc.Add(-1);
                //add new column for that variable
                var zeroVector = new DenseVector(rowCount);
                zeroVector[i] = -1;
                auxA = auxA.InsertColumn(varCount++, zeroVector);
                //add new row for this variable
                var nonNegativeRow = new DenseVector(varCount);
                nonNegativeRow[varCount - 1] = -1;
                auxA = auxA.InsertRow(rowCount, nonNegativeRow);
                var zeroFreeTerm = new DenseVector(new[] {0.0});
                auxb = auxb.ToColumnMatrix().InsertRow(rowCount, zeroFreeTerm).Column(0);
                rowCount++;
                //add top constraint to this variable
                var freeTermRow = new DenseVector(varCount);
                freeTermRow[varCount - 1] = 1;
                auxA = auxA.InsertRow(rowCount, freeTermRow);
                var newFreeTerm = new DenseVector(new[] {-tuple.FreeTerms[i]});
                auxb = auxb.ToColumnMatrix().InsertRow(rowCount, newFreeTerm).Column(0);
                startingEq.Add(rowCount);
                rowCount++;
            }

            var auxBasis = new StartingBasis
                {
                    InequalityIndexes = startingEq.ToArray(),
                    FeasibleBasis = new double[varCount]
                };

            iteration = 0;
            var columns = Enumerable.Range(0, varCount).ToArray();
            //TODO: work with Dense/Sparse vectors
            var auxAb = ((DenseMatrix) auxA).Extract(startingEq.ToArray(), columns);
            var auxbB = ((DenseVector) auxb).Extract(startingEq.ToArray());

            Vector vector = SolveInternal((DenseMatrix) auxA, (DenseVector) auxb, new DenseVector(auxObjFunc.ToArray()),
                                          auxBasis, auxAb, auxbB);

            for (int k = tuple.ObjFuncCoeffs.Count; k < varCount; k++)
                if (!vector[k].FloatEquals(0))
                    throw new SimplexException("Problem is unsolvable");

            var basis = vector.Take(tuple.ObjFuncCoeffs.Count).ToArray();
            var indexes =
                auxBasis.InequalityIndexes.Where(x => x < tuple.EqualityCoeffs.RowCount).Take(tuple.ObjFuncCoeffs.Count).ToArray();

            return new StartingBasis
                {
                    InequalityIndexes = indexes,
                    FeasibleBasis = basis
                };
        }
        public SimplexTuple ConvertToStandartForm(SimplexTuple tuple)
        {
            if (tuple.Type == ObjectiveFunctionType.Min)
            {
                tuple.ObjFuncCoeffs *= -1;
                tuple.ObjFuncFreeTerm *= -1;
                tuple.Type = ObjectiveFunctionType.Max;
            }
            int length = tuple.EquationTypes.Count;
            for (int i = 0; i < length; i++)
            {
                var equation = tuple.EquationTypes[i];
                if (equation == EquationType.MoreOrEqual)
                {
                    tuple.EqualityCoeffs.SetRow(i, -1*tuple.EqualityCoeffs.Row(i));
                    tuple.FreeTerms[i] *= -1;
                    tuple.EquationTypes[i] = EquationType.LessOrEqual;
                }
                if (equation == EquationType.Equal)
                {
                    tuple.EquationTypes[i] = EquationType.LessOrEqual;
                    var additionalRow = tuple.EqualityCoeffs.Row(i).Clone();
                    tuple.EqualityCoeffs = (DenseMatrix) tuple.EqualityCoeffs.InsertRow(i + 1, additionalRow);
                    tuple.EquationTypes.Insert(i + 1, EquationType.MoreOrEqual);
                    var val = tuple.FreeTerms[i];
                    var freeTerms = tuple.FreeTerms.ToList();
                    freeTerms.Insert(i + 1, val);
                    tuple.FreeTerms = new DenseVector(freeTerms.ToArray());
                    length++;
                }
            }

            return tuple;
        }