Esempio n. 1
0
        public void RunTest_OneEquality()
        {
            var inputConstraintsMatrixText = "[[1,0,3],[0,2,2]]";
            var inputConstraintsVectorText = "[4,12,18]";
            var cost = new SimplexMaximumNumberField <double>(0, -18);
            var nonBasicVariables = new[] { 0, 1 };
            var basicVariables    = new[] { 2, 3, 4 };

            // Leitura da matriz das retrições.
            var doubleElementsParser   = new DoubleParser <string>();
            var inputConstraintsMatrix = TestsHelper.ReadMatrix <double>(
                3,
                2,
                inputConstraintsMatrixText,
                (i, j) => new ArrayMathMatrix <double>(i, j),
                doubleElementsParser,
                true);

            // Leitura do vector de restrições.
            var vectorFactory          = new ArrayVectorFactory <double>();
            var inputConstraintsVector = TestsHelper.ReadVector <double>(
                3,
                inputConstraintsVectorText,
                vectorFactory,
                doubleElementsParser,
                true);

            // Introdução da função objectivo.
            var inputObjectiveFunction = new ArrayMathVector <SimplexMaximumNumberField <double> >(2);

            inputObjectiveFunction[0] = new SimplexMaximumNumberField <double>(
                -3,
                -3);
            inputObjectiveFunction[1] = new SimplexMaximumNumberField <double>(
                -5,
                -2);

            // Objecto de entrada para o algoritmo do simplex.
            var simplexInput = new SimplexInput <double, SimplexMaximumNumberField <double> >(
                basicVariables,
                nonBasicVariables,
                inputObjectiveFunction,
                cost,
                inputConstraintsMatrix,
                inputConstraintsVector);

            var doubleField = new DoubleField();
            var target      = new SimplexAlgorithm <double>(Comparer <double> .Default, doubleField);
            var actual      = target.Run(simplexInput);

            // Verifica o custo
            Assert.AreEqual(36, actual.Cost);

            // Verifica a solução
            Assert.AreEqual(2, actual.Solution[0]);
            Assert.AreEqual(6, actual.Solution[1]);
        }
Esempio n. 2
0
        public void RunSimplexTest_NoFeasibleSolution()
        {
            var inputConstraintsMatrixText = "[[0.3,0.5,0.6],[0.1,0.5,0.4],[0,0,-1]]";
            var inputConstraintsVectorText = "[1.8,6,6]";
            var cost = new SimplexMaximumNumberField <double>(0, -12);
            var nonBasicVariables = new[] { 0, 1, 2 };
            var basicVariables    = new[] { 3, 4, 5 };

            // Leitura da matriz das retrições.
            var doubleElementsParser   = new DoubleParser <string>();
            var inputConstraintsMatrix = TestsHelper.ReadMatrix <double>(
                3,
                3,
                inputConstraintsMatrixText,
                (i, j) => new ArrayMathMatrix <double>(i, j),
                doubleElementsParser,
                true);

            // Leitura do vector de restrições.
            var vectorFactory          = new ArrayVectorFactory <double>();
            var inputConstraintsVector = TestsHelper.ReadVector <double>(
                3,
                inputConstraintsVectorText,
                vectorFactory,
                doubleElementsParser,
                true);

            // Introdução da função objectivo.
            var inputObjectiveFunction = new ArrayMathVector <SimplexMaximumNumberField <double> >(3);

            inputObjectiveFunction[0] = new SimplexMaximumNumberField <double>(
                0.4,
                -1.1);
            inputObjectiveFunction[1] = new SimplexMaximumNumberField <double>(
                0.5,
                -0.9);
            inputObjectiveFunction[2] = new SimplexMaximumNumberField <double>(
                0,
                1);

            // Objecto de entrada para o algoritmo do simplex.
            var simplexInput = new SimplexInput <double, SimplexMaximumNumberField <double> >(
                basicVariables,
                nonBasicVariables,
                inputObjectiveFunction,
                cost,
                inputConstraintsMatrix,
                inputConstraintsVector);

            var doubleField = new DoubleField();
            var target      = new SimplexAlgorithm <double>(Comparer <double> .Default, doubleField);
            var actual      = target.Run(simplexInput);

            // O problema tem uma solução cujo custo é inifito.
            Assert.IsFalse(actual.HasSolution);
        }
        /// <summary>
        /// Aplica o algoritmo sobre a matriz dos custos.
        /// </summary>
        /// <param name="costs">A matriz dos custos.</param>
        /// <param name="numberOfMedians">O número de medianas a serem escolhidas.</param>
        /// <returns>O resultado da relaxação.</returns>
        public CoeffType[] Run(SparseDictionaryMathMatrix <CoeffType> costs, int numberOfMedians)
        {
            if (costs == null)
            {
                throw new ArgumentNullException("costs");
            }
            else
            {
                var numberOfVertices  = costs.GetLength(1);
                var objectiveFunction = new List <SimplexMaximumNumberField <CoeffType> >();

                // A mediana que cobre todas as outras é ligeiramente diferente
                objectiveFunction.Add(new SimplexMaximumNumberField <CoeffType>(
                                          this.coeffsField.AdditiveUnity,
                                          this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity)));

                for (int i = 1; i < numberOfVertices; ++i)
                {
                    objectiveFunction.Add(new SimplexMaximumNumberField <CoeffType>(
                                              this.coeffsField.AdditiveUnity,
                                              this.coeffsField.AddRepeated(
                                                  this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity),
                                                  2)));
                }

                // Adiciona as variáveis x à função objectivo.
                var numberXVars = 0;
                foreach (var line in costs.GetLines())
                {
                    foreach (var column in line.Value.GetColumns())
                    {
                        if (line.Key != column.Key)
                        {
                            ++numberXVars;
                            var valueToAdd = new SimplexMaximumNumberField <CoeffType>(
                                column.Value,
                                this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity));
                            objectiveFunction.Add(valueToAdd);
                        }
                    }
                }

                // Cria a matriz das restrições e preenche-a com os valores correctos
                var constraintsNumber = numberXVars + numberOfVertices;
                var nonBasicVariables = new int[objectiveFunction.Count];
                var basicVariables    = new int[constraintsNumber];
                var linesLength       = nonBasicVariables.Length + basicVariables.Length;

                // Preence os vectores que permitem seleccionar as variáveis.
                this.FillVariablesSelectors(nonBasicVariables, basicVariables, linesLength);

                // Preencimento da matriz das restrições
                var constraintsMatrix = new ArrayMathMatrix <CoeffType>(
                    constraintsNumber,
                    constraintsNumber,
                    this.coeffsField.AdditiveUnity);

                var constraintLineNumber   = 0;
                var constraintXYLineNumber = 0;
                var unity           = this.coeffsField.MultiplicativeUnity;
                var inverseAdditive = this.coeffsField.AdditiveInverse(unity);
                foreach (var line in costs.GetLines())
                {
                    foreach (var column in line.Value.GetColumns())
                    {
                        if (line.Key != column.Key)
                        {
                            constraintsMatrix[constraintXYLineNumber, constraintLineNumber] = inverseAdditive;
                            constraintsMatrix[constraintXYLineNumber, constraintXYLineNumber + numberOfVertices] = unity;
                            ++constraintXYLineNumber;
                        }
                    }

                    ++constraintLineNumber;
                }

                var lastLine = constraintsNumber - 1;
                constraintsMatrix[lastLine, 0] = unity;
                constraintLineNumber           = numberXVars;
                for (int i = 1; i < numberOfVertices; ++i)
                {
                    constraintsMatrix[constraintLineNumber, i] = unity;
                    constraintsMatrix[lastLine, i]             = unity;
                    constraintXYLineNumber = numberOfVertices;
                    foreach (var lines in costs.GetLines())
                    {
                        foreach (var column in lines.Value.GetColumns())
                        {
                            if (lines.Key != column.Key)
                            {
                                if (column.Key == i)
                                {
                                    constraintsMatrix[constraintLineNumber, constraintXYLineNumber] = unity;
                                }

                                ++constraintXYLineNumber;
                            }
                        }
                    }

                    ++constraintLineNumber;
                }

                // Preenchimento do vector independente das restrições
                var vector = new ArrayMathVector <CoeffType>(constraintsNumber, this.coeffsField.AdditiveUnity);
                lastLine = constraintsNumber - 1;
                for (int i = numberXVars; i < lastLine; ++i)
                {
                    vector[i] = unity;
                }

                vector[lastLine] = this.conversion.InverseConversion(numberOfMedians);
                var sumVector = this.coeffsField.AdditiveUnity;
                for (int i = 0; i < vector.Length; ++i)
                {
                    sumVector = this.coeffsField.Add(sumVector, vector[i]);
                }

                sumVector = this.coeffsField.AdditiveInverse(sumVector);
                var simplexInput = new SimplexInput <CoeffType, SimplexMaximumNumberField <CoeffType> >(
                    basicVariables,
                    nonBasicVariables,
                    new ArrayMathVector <SimplexMaximumNumberField <CoeffType> >(objectiveFunction.ToArray()),
                    new SimplexMaximumNumberField <CoeffType>(this.coeffsField.AdditiveUnity, sumVector),
                    constraintsMatrix,
                    vector);

                var resultSimplexSol = this.simplexAlg.Run(simplexInput);
                var result           = new CoeffType[numberOfVertices];
                Array.Copy(resultSimplexSol.Solution, result, numberOfVertices);
                return(result);
            }
        }