/// <summary> /// Obtém o vector dual. /// </summary> /// <param name="nonBasicCostsIndices">Os índices dos valores com custos relativos às variáveis básicas.</param> /// <param name="inverseMatrix">A matriz da base inversa.</param> /// <param name="objectiveFunction">O vector que representa a função objectivo.</param> /// <param name="basicVariables">As variáveis básicas.</param> /// <returns>O vector dual utilizado para determinar os valores dos custos.</returns> private SimplexMaximumNumberField <CoeffType>[] ComputeDualVector( SortedSet <int> nonBasicCostsIndices, ISquareMathMatrix <CoeffType> inverseMatrix, IMathVector <SimplexMaximumNumberField <CoeffType> > objectiveFunction, int[] basicVariables) { var result = new SimplexMaximumNumberField <CoeffType> [basicVariables.Length]; var dimension = basicVariables.Length; Parallel.For(0, dimension, i => { var sum = new SimplexMaximumNumberField <CoeffType>(this.coeffsField.AdditiveUnity, this.coeffsField.AdditiveUnity); foreach (var index in nonBasicCostsIndices) { var objectiveValue = objectiveFunction[basicVariables[index]]; var finitePart = objectiveValue.FinitePart; var bigPart = objectiveValue.BigPart; var inverseMatrixEntry = inverseMatrix[index, i]; finitePart = this.coeffsField.Multiply( inverseMatrixEntry, this.coeffsField.AdditiveInverse(objectiveValue.FinitePart)); bigPart = this.coeffsField.Multiply( inverseMatrixEntry, this.coeffsField.AdditiveInverse(objectiveValue.BigPart)); sum.Add(finitePart, bigPart, this.coeffsField); } result[i] = sum; }); return(result); }
/// <summary> /// Permite criar uma instância de entrada para o algoritmo do simplex na forma normal. /// A base pode corresponder a uma instância que resultou da aplicação do algoritmo. /// </summary> /// <param name="basicVariables">O conjunto de variáveis básicas.</param> /// <param name="nonBasicVariables">O conjunto de variáveis não-básicas.</param> /// <param name="objectiveFunction">Os coeficientes da função objectivo.</param> /// <param name="cost">O custo.</param> /// <param name="constraintsMatrix">A matriz das restrições.</param> /// <param name="constraintsVector">O vector das restrições.</param> /// <param name="inverseBasisMatrix">A matriz de base inversa que é utilizada durante o processo algorítmico.</param> /// /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception> /// <exception cref="ArgumentException"> /// Se as dimensões dos argumentos não definirem correctamente um problema. /// </exception> public RevisedSimplexInput( int[] basicVariables, int[] nonBasicVariables, IMathVector <ObjectiveCoeffType> objectiveFunction, ObjectiveCoeffType cost, IMathMatrix <ConstraintsType> constraintsMatrix, IMathVector <ConstraintsType> constraintsVector, ISquareMathMatrix <ConstraintsType> inverseBasisMatrix) : base( basicVariables, nonBasicVariables, objectiveFunction, cost, constraintsMatrix, constraintsVector) { if (inverseBasisMatrix == null) { throw new ArgumentNullException("The basis matrix must not be null."); } else if (inverseBasisMatrix.GetLength(0) != ConstraintsMatrix.GetLength(0)) { throw new ArgumentException("The dimension of basis matrix must match the number of lines in constraints matrix."); } else { this.inverseBasisMatrix = inverseBasisMatrix; } }
/// <summary> /// Obtém o vector dual. /// </summary> /// <param name="nonBasicCostsIndices">Os índices dos valores com custos relativos às variáveis básicas.</param> /// <param name="inverseMatrix">A matriz da base inversa.</param> /// <param name="objectiveFunction">O vector que representa a função objectivo.</param> /// <param name="basicVariables">As variáveis básicas.</param> /// <returns>O vector dual utilizado para determinar os valores dos custos.</returns> private CoeffType[] ComputeDualVector( SortedSet <int> nonBasicCostsIndices, ISquareMathMatrix <CoeffType> inverseMatrix, IMathVector <CoeffType> objectiveFunction, int[] basicVariables) { var result = new CoeffType[basicVariables.Length]; var dimension = basicVariables.Length; Parallel.For(0, dimension, i => { var sum = this.coeffsField.AdditiveUnity; foreach (var index in nonBasicCostsIndices) { var objectiveValue = objectiveFunction[basicVariables[index]]; var valueToAdd = inverseMatrix[index, i]; valueToAdd = this.coeffsField.Multiply( valueToAdd, this.coeffsField.AdditiveInverse(objectiveValue)); sum = this.coeffsField.Add(sum, valueToAdd); } result[i] = sum; }); return(result); }
/// <summary> /// Testa a deomposição sequencial relativa à matriz. /// </summary> /// <param name="target">O algoritmo.</param> /// <param name="matrix">A matriz.</param> private void TestDecomposition( ATriangDiagSymmMatrixDecomp <Fraction <int> > target, ISquareMathMatrix <Fraction <int> > matrix) { // Execução do algoritmo. var decomposition = target.Run( matrix); // Calcula o valor esperado. var matrixFactory = new ArrayMathMatrixFactory <Fraction <int> >(); var matrixMultiplicaton = new MatrixMultiplicationOperation <Fraction <int> >( matrixFactory, target.Field, target.Field); var actual = new TransposeMatrix <Fraction <int> >(decomposition.UpperTriangularMatrix) as IMatrix <Fraction <int> >; actual = matrixMultiplicaton.Multiply(actual, decomposition.DiagonalMatrix); actual = matrixMultiplicaton.Multiply(actual, decomposition.UpperTriangularMatrix); // Valida as asserções. Assert.AreEqual(matrix.GetLength(0), actual.GetLength(0)); Assert.AreEqual(matrix.GetLength(1), actual.GetLength(1)); for (int i = 0; i < actual.GetLength(0); ++i) { for (int j = 0; j < actual.GetLength(1); ++j) { Assert.AreEqual(matrix[i, j], actual[i, j]); } } }
/// <summary> /// Determina a próxima variável de saída. /// </summary> /// <remarks> /// Esta função permite fazer um pré-cálculo do vector eta, sendo o respectivo contentor de dados /// passado como argumento. /// </remarks> /// <param name="enteringVariable">A variável de entrada.</param> /// <param name="constraintsMatrix">A matriz das restrições.</param> /// <param name="constraintsVector">O vector das restrições.</param> /// <param name="inverseBasisMatrix">A matriz das bases inversa.</param> /// <param name="etaVector">O contentor do vector eta.</param> /// <returns>A próxima variável de saída.</returns> private int GetNextLeavingVariable( int enteringVariable, IMathMatrix <CoeffType> constraintsMatrix, CoeffType[] constraintsVector, ISquareMathMatrix <CoeffType> inverseBasisMatrix, CoeffType[] etaVector) { // Calcula os coeficientes e coloca-os no vector eta. this.ComputeVariableCoefficients( enteringVariable, constraintsMatrix, inverseBasisMatrix, etaVector); var result = -1; var value = this.coeffsField.AdditiveUnity; // Estabelece o primeiro valor para futura comparação. var constraintsLength = constraintsMatrix.GetLength(0); var index = 0; while (index < constraintsLength && result == -1) { var currentValue = etaVector[index]; if (this.coeffsComparer.Compare(currentValue, this.coeffsField.AdditiveUnity) > 0) { value = this.coeffsField.Multiply( constraintsVector[index], this.coeffsField.MultiplicativeInverse(currentValue)); result = index; } ++index; } if (result != -1) { for (; index < constraintsLength; ++index) { var currentValue = etaVector[index]; if (this.coeffsComparer.Compare(currentValue, this.coeffsField.AdditiveUnity) > 0) { currentValue = this.coeffsField.Multiply( constraintsVector[index], this.coeffsField.MultiplicativeInverse(currentValue)); if (this.coeffsComparer.Compare(currentValue, value) < 0) { result = index; value = currentValue; } } } } return(result); }
/// <summary> /// Actualiza as entradas da matriz inversa. /// </summary> /// <param name="leavingVariableIndex">O índice da variável de saída.</param> /// <param name="inverseMatrix">A matriz inversa.</param> /// <param name="etaVector">O vector eta.</param> private void UpdateInverseMatrix( int leavingVariableIndex, ISquareMathMatrix <CoeffType> inverseMatrix, CoeffType[] etaVector) { // Actualiza o valor de eta var multiplicativeInverse = this.coeffsField.MultiplicativeInverse(etaVector[leavingVariableIndex]); Parallel.For(0, leavingVariableIndex, i => { var value = this.coeffsField.Multiply(etaVector[i], multiplicativeInverse); etaVector[i] = this.coeffsField.AdditiveInverse(value); }); etaVector[leavingVariableIndex] = multiplicativeInverse; var length = etaVector.Length; Parallel.For(leavingVariableIndex + 1, length, i => { var value = this.coeffsField.Multiply(etaVector[i], multiplicativeInverse); etaVector[i] = this.coeffsField.AdditiveInverse(value); }); // Actualiza a matriz inversa Parallel.For(0, leavingVariableIndex, i => { inverseMatrix.CombineLines( i, leavingVariableIndex, this.coeffsField.MultiplicativeUnity, etaVector[i], this.coeffsField); }); Parallel.For(leavingVariableIndex + 1, length, i => { inverseMatrix.CombineLines( i, leavingVariableIndex, this.coeffsField.MultiplicativeUnity, etaVector[i], this.coeffsField); }); inverseMatrix.ScalarLineMultiplication(leavingVariableIndex, etaVector[leavingVariableIndex], this.coeffsField); }
/// <summary> /// Calcula o vector dos termos independentes actual. /// </summary> /// <param name="inverseMatrix">A matriz inversa.</param> /// <param name="constraintsVector">O vector dos termos independentes original.</param> /// <param name="result">O contentor para os resultados.</param> private void ComputeConstraintsVector( ISquareMathMatrix <CoeffType> inverseMatrix, IMathVector <CoeffType> constraintsVector, CoeffType[] result) { var basicLength = inverseMatrix.GetLength(0); var inverseSparseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>; if (inverseSparseMatrix == null) { Parallel.For(0, basicLength, i => { var sum = this.coeffsField.AdditiveUnity; for (int j = 0; j < basicLength; ++j) { var valueToAdd = constraintsVector[j]; valueToAdd = this.coeffsField.Multiply(valueToAdd, inverseMatrix[i, j]); sum = this.coeffsField.Add(sum, valueToAdd); } result[i] = sum; }); } else { Parallel.For(0, basicLength, i => { result[i] = this.coeffsField.AdditiveUnity; }); Parallel.ForEach(inverseSparseMatrix.GetLines(), inverseLine => { var sum = this.coeffsField.AdditiveUnity; var columns = inverseLine.Value.GetColumns(); foreach (var columnKvp in columns) { var valueToAdd = constraintsVector[columnKvp.Key]; valueToAdd = this.coeffsField.Multiply(valueToAdd, columnKvp.Value); sum = this.coeffsField.Add(sum, valueToAdd); } result[inverseLine.Key] = sum; }); } }
/// <summary> /// Executa o algorimtmo que permite determinar a solução do sistema simétrico /// com base na decomposição LDL^T. /// </summary> /// <param name="first">A matriz dos coeficientes das variáveis.</param> /// <param name="second">O vector dos coeficientes independentes.</param> /// <returns>A solução do sistema.</returns> public LinearSystemSolution <CoeffType> Run( ISquareMathMatrix <CoeffType> first, IMathMatrix <CoeffType> second) { if (first == null) { throw new ArgumentNullException("first"); } else if (second == null) { throw new ArgumentNullException("second"); } else { var size = first.GetLength(0); if (second.GetLength(0) != size) { throw new ArgumentException( "The number of columns in coefficients matrix must equal the number of lines in independent vector."); } else { var result = new LinearSystemSolution <CoeffType>(); var decompRes = this.decompositionAlgorithm.Run( first); var indSol = this.ProcessFirstMatrix( decompRes.UpperTriangularMatrix, second, size); if (this.ProcessDiagonal(decompRes.DiagonalMatrix, indSol, size)) { this.ProcessRemainingMatrices( decompRes.UpperTriangularMatrix, decompRes.DiagonalMatrix, indSol, size, result); } return(result); } } }
/// <summary> /// Cria uma instância de objectos do tipo <see cref="LinearDecompositionInput{ConstraintsType, ObjectiveCoeffType}"/> /// </summary> /// <param name="initialDecompositionPoints">As estimativas iniciais relativas ao problema da decomposição.</param> /// <param name="objectiveFunction">A função objectivo.</param> /// <param name="cost">O custo inicial.</param> /// <param name="masterConstraints">As restrições do problema principal.</param> /// <param name="decomposedConstraints">As restrições dos vários problemas decompostos.</param> /// <param name="inverseBasisMatrix">A matriz de base inversa.</param> public LinearDecompositionInput( IMathVector <ObjectiveCoeffType>[] initialDecompositionPoints, IMathVector <ObjectiveCoeffType> objectiveFunction, ObjectiveCoeffType cost, LinearConstraintsInput <ConstraintsType> masterConstraints, LinearConstraintsInput <ConstraintsType>[] decomposedConstraints, ISquareMathMatrix <ConstraintsType> inverseBasisMatrix) { this.ValidateArguments( initialDecompositionPoints, objectiveFunction, cost, masterConstraints, decomposedConstraints, inverseBasisMatrix); this.initialDecompositionPoints = initialDecompositionPoints; this.objectiveFunction = objectiveFunction; this.cost = cost; this.masterConstraints = masterConstraints; this.decomposedConstraints = decomposedConstraints; this.inverseBasisMatrix = inverseBasisMatrix; }
/// <summary> /// Calcula os coeficientes da variável de entrada e coloca-os no vector eta. /// </summary> /// <param name="enteringVariable">A variável de entrada.</param> /// <param name="constraintsMatrix">A matriz das restrições.</param> /// <param name="inverseMatrix">A matriz inversa.</param> /// <param name="etaVector">O vector eta.</param> private void ComputeVariableCoefficients( int enteringVariable, IMathMatrix <CoeffType> constraintsMatrix, ISquareMathMatrix <CoeffType> inverseMatrix, CoeffType[] etaVector) { var length = constraintsMatrix.GetLength(1); if (enteringVariable >= length) // A matriz das restrições contém a identidade como entrada. { var entryIndex = enteringVariable - length; // O vector conterá a entrada respectiva na matriz inversa. var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>; length = etaVector.Length; if (sparseInverseMatrix == null) { Parallel.For(0, length, i => { etaVector[i] = inverseMatrix[i, entryIndex]; }); } else { Parallel.For(0, length, i => { etaVector[i] = this.coeffsField.AdditiveUnity; }); foreach (var line in sparseInverseMatrix.GetLines()) { etaVector[line.Key] = line.Value[entryIndex]; } } } else { length = inverseMatrix.GetLength(0); var sparseContraintsMatrix = constraintsMatrix as ISparseMathMatrix <CoeffType>; if (sparseContraintsMatrix == null) { var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>; if (sparseInverseMatrix == null) { Parallel.For(0, length, i => { var sum = this.coeffsField.AdditiveUnity; for (int j = 0; j < length; ++j) { var valueToAdd = inverseMatrix[i, j]; valueToAdd = this.coeffsField.Multiply( valueToAdd, constraintsMatrix[j, enteringVariable]); sum = this.coeffsField.Add(sum, valueToAdd); } etaVector[i] = sum; }); } else { Parallel.For(0, length, i => { etaVector[i] = this.coeffsField.AdditiveUnity; }); var inverseMatrixLines = sparseInverseMatrix.GetLines(); Parallel.ForEach(inverseMatrixLines, lineKvp => { var sum = this.coeffsField.AdditiveUnity; foreach (var columnKvp in lineKvp.Value.GetColumns()) { var valueToAdd = constraintsMatrix[columnKvp.Key, enteringVariable]; valueToAdd = this.coeffsField.Multiply(valueToAdd, columnKvp.Value); sum = this.coeffsField.Add(sum, valueToAdd); } etaVector[lineKvp.Key] = sum; }); } } else { var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>; if (sparseInverseMatrix == null) { Parallel.For(0, length, i => { var sum = this.coeffsField.AdditiveUnity; var constraintsMatrixLines = sparseContraintsMatrix.GetLines(); foreach (var constraintsLine in constraintsMatrixLines) { var j = constraintsLine.Key; var valueToAdd = default(CoeffType); if (constraintsLine.Value.TryGetColumnValue(enteringVariable, out valueToAdd)) { valueToAdd = this.coeffsField.Multiply(valueToAdd, inverseMatrix[i, j]); sum = this.coeffsField.Add(sum, valueToAdd); } } etaVector[i] = sum; }); } else { Parallel.For(0, length, i => { etaVector[i] = this.coeffsField.AdditiveUnity; }); Parallel.ForEach(sparseInverseMatrix.GetLines(), inverseMatrixLine => { var sum = this.coeffsField.AdditiveUnity; var constraintsMatrixLines = sparseContraintsMatrix.GetLines(); foreach (var constraintsLine in constraintsMatrixLines) { var j = constraintsLine.Key; var inverseValue = default(CoeffType); if (inverseMatrixLine.Value.TryGetColumnValue(j, out inverseValue)) { var constraintsValue = default(CoeffType); if (constraintsLine.Value.TryGetColumnValue(enteringVariable, out constraintsValue)) { var valueToAdd = this.coeffsField.Multiply(inverseValue, constraintsValue); sum = this.coeffsField.Add(sum, valueToAdd); } } } etaVector[inverseMatrixLine.Key] = sum; }); } } } }
/// <summary> /// Determina o polinómio característico de uma matriz. /// </summary> /// <param name="data">A matriz.</param> /// <returns>O polinómio característico.</returns> public UnivariatePolynomialNormalForm <ElementType> Run(ISquareMathMatrix <ElementType> data) { if (data == null) { return(new UnivariatePolynomialNormalForm <ElementType>(this.variableName)); } else { var lines = data.GetLength(0); if (lines == 0) { return(new UnivariatePolynomialNormalForm <ElementType>(this.variableName)); } else if (lines == 1) { var entry = data[0, 0]; var result = new UnivariatePolynomialNormalForm <ElementType>( this.ring.MultiplicativeUnity, 1, this.variableName, this.ring); result = result.Add(this.ring.AdditiveInverse(entry), 0, this.ring); return(result); } else if (lines == 2) { var variablePol = new UnivariatePolynomialNormalForm <ElementType>( this.ring.MultiplicativeUnity, 1, this.variableName, this.ring); var firstDiagonalElement = variablePol.Add( this.ring.AdditiveInverse(data[0, 0]), this.ring); var secondDiagonalElement = variablePol.Add( this.ring.AdditiveInverse(data[1, 1]), this.ring); var result = firstDiagonalElement.Multiply(secondDiagonalElement, this.ring); result = result.Add( this.ring.AdditiveInverse(this.ring.Multiply(data[0, 1], data[1, 0])), this.ring); return(result); } else { var matrixFactory = new ArrayMathMatrixFactory <ElementType>(); var matrixMultiplicator = new MatrixMultiplicationOperation <ElementType>( matrixFactory, this.ring, this.ring); var subMatrixSequence = new IntegerSequence(); var singleValueSequence = new IntegerSequence(); IMatrix <ElementType> multiplicationMatrix = new ArrayMathMatrix <ElementType>( lines + 1, lines, this.ring.AdditiveUnity); subMatrixSequence.Add(1, lines - 1); singleValueSequence.Add(0); this.FillMultiplicationMatrix( data, data[0, 0], subMatrixSequence, singleValueSequence, matrixMultiplicator, multiplicationMatrix); var currentDimension = 1; while (currentDimension < lines - 1) { subMatrixSequence.Clear(); singleValueSequence.Clear(); subMatrixSequence.Add(currentDimension + 1, lines - 1); singleValueSequence.Add(currentDimension); var otherLines = lines - currentDimension; var otherMultiplicationMatrix = new ArrayMathMatrix <ElementType>( otherLines + 1, otherLines, this.ring.AdditiveUnity); this.FillMultiplicationMatrix( data, data[currentDimension, currentDimension], subMatrixSequence, singleValueSequence, matrixMultiplicator, otherMultiplicationMatrix); multiplicationMatrix = matrixMultiplicator.Multiply( multiplicationMatrix, otherMultiplicationMatrix); ++currentDimension; } var lastOtherMultiplicationMatrix = new ArrayMathMatrix <ElementType>( 2, 1, this.ring.AdditiveUnity); lastOtherMultiplicationMatrix[0, 0] = this.ring.MultiplicativeUnity; lastOtherMultiplicationMatrix[1, 0] = this.ring.AdditiveInverse(data[currentDimension, currentDimension]); multiplicationMatrix = matrixMultiplicator.Multiply( multiplicationMatrix, lastOtherMultiplicationMatrix); var result = new UnivariatePolynomialNormalForm <ElementType>( multiplicationMatrix[0, 0], lines, this.variableName, this.ring); for (int i = 1; i <= lines; ++i) { result = result.Add(multiplicationMatrix[i, 0], lines - i, this.ring); } return(result); } } }
/// <summary> /// Obtém a decomposição de uma matriz M=LDL^* onde L é uma matriz triangular e D é uma matriz diagonal. /// </summary> /// <param name="matrix">A matriz.</param> /// <returns>As matrizes triangular e diagonal.</returns> public override TriangDiagSymmMatrixDecompResult <CoeffType> Run( ISquareMathMatrix <CoeffType> matrix) { if (matrix == null) { throw new ArgumentNullException("matrix"); } else { var matrixDimension = matrix.GetLength(0); var triangularMatrix = this.upperTriangularMatrixFactory.Invoke( matrixDimension, this.field.AdditiveUnity); var diagonalMatrix = this.diagonalMatrixFactory.Invoke( matrixDimension, this.field.AdditiveUnity); for (int i = 0; i < matrixDimension; ++i) { var diagonalTask = new Task(() => { var sumValue = this.field.AdditiveUnity; for (int j = 0; j < i; ++j) { var diag = diagonalMatrix[j, j]; if (!this.field.IsAdditiveUnity(diag)) { var value = triangularMatrix[j, i]; value = this.field.Multiply(value, value); value = this.field.Multiply(value, diag); sumValue = this.field.Add(sumValue, value); } } sumValue = this.field.Add( matrix[i, i], this.field.AdditiveInverse(sumValue)); diagonalMatrix[i, i] = sumValue; }); var triangularTask = new Task(() => { Parallel.For(i + 1, matrixDimension, (j, state) => { var sumValue = this.field.AdditiveUnity; for (int k = 0; k < i; ++k) { var value = triangularMatrix[k, i]; value = this.field.Multiply(value, triangularMatrix[k, j]); value = this.field.Multiply(value, diagonalMatrix[k, k]); sumValue = this.field.Add(sumValue, value); } triangularMatrix[i, j] = this.field.Add( matrix[i, j], this.field.AdditiveInverse(sumValue)); }); }); diagonalTask.Start(); triangularTask.Start(); Task.WaitAll(new[] { diagonalTask, triangularTask }); var diagonalValue = diagonalMatrix[i, i]; if (!this.field.IsAdditiveUnity(diagonalValue)) { triangularMatrix.ScalarLineMultiplication( i, this.field.MultiplicativeInverse(diagonalMatrix[i, i]), this.field); } triangularMatrix[i, i] = this.field.MultiplicativeUnity; } return(new TriangDiagSymmMatrixDecompResult <CoeffType>( triangularMatrix, diagonalMatrix)); } }
/// <summary> /// Obtém a decomposição de uma matriz M=LDL^* onde L é uma matriz triangular e D é uma matriz diagonal. /// </summary> /// <remarks> /// Caso a matriz não seja simétrica, é considerada a matriz simétrica cujas entradas acima da diagonal /// conicidam com as entradas respectivas da matriz original. /// </remarks> /// <param name="data">A matriz.</param> /// <returns>As matrizes triangular e diagonal.</returns> public abstract TriangDiagSymmMatrixDecompResult <CoeffType> Run( ISquareMathMatrix <CoeffType> data);
/// <summary> /// Valida a integridade dos dados nos argumentos. /// </summary> /// <param name="initialDecompositionPoints">As estimativas iniciais relativas ao problema da decomposição.</param> /// <param name="objectiveFunction">A função objectivo.</param> /// <param name="cost">O custo inicial.</param> /// <param name="masterConstraints">As restrições do problema principal.</param> /// <param name="decomposedConstraints">As restrições dos vários problemas decompostos.</param> /// <param name="inverseBasisMatrix">A matriz de base inversa.</param> private void ValidateArguments( IMathVector <ObjectiveCoeffType>[] initialDecompositionPoints, IMathVector <ObjectiveCoeffType> objectiveFunction, ObjectiveCoeffType cost, LinearConstraintsInput <ConstraintsType> masterConstraints, LinearConstraintsInput <ConstraintsType>[] decomposedConstraints, ISquareMathMatrix <ConstraintsType> inverseBasisMatrix) { if (initialDecompositionPoints == null) { throw new ArgumentNullException("initialDecompositionPoints"); } else if (objectiveFunction == null) { throw new ArgumentNullException("objectiveFunction"); } else if (cost == null) { throw new ArgumentNullException("cost"); } else if (masterConstraints == null) { throw new ArgumentNullException("masterConstraints"); } else if (decomposedConstraints == null) { throw new ArgumentNullException("decomposedConstraints"); } else if (inverseBasisMatrix == null) { throw new ArgumentNullException("inverseBasisMatrix"); } else if (initialDecompositionPoints.Length != decomposedConstraints.Length) { throw new ArgumentException( "The number of initial problem points must match the number of decomposition problem constraints."); } else { var length = decomposedConstraints.Length; for (int i = 0; i < length; ++i) { var currentDecomposedConstraint = decomposedConstraints[i]; var currentPoint = initialDecompositionPoints[i]; if (currentDecomposedConstraint == null) { throw new ArgumentException("Null decomposition constraints aren't allowed."); } else if (currentPoint == null) { throw new ArgumentException("Null initial points aren't allowed."); } else { var constraintColumnsLength = currentDecomposedConstraint.ConstraintsMatrix.GetLength(1); if (initialDecompositionPoints.Length != constraintColumnsLength) { throw new ArgumentException( "The number of initial points coordinates must match the number of columns of the decomposition problem constraints matrix."); } } } } }