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]); }
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); } }