/// <summary> /// Testa a solução do sistema de equações. /// </summary> /// <param name="matrix">A matriz dos coeficientes das variáveis.</param> /// <param name="independent">O vector dos coeficientes independentes.</param> /// <param name="solution">A solução do sistema simétrico.</param> private void TestSolution( IMathMatrix <CoeffType> matrix, IMathMatrix <CoeffType> independent, LinearSystemSolution <CoeffType> solution) { if (solution.Vector != null) { var vec = solution.Vector; var lines = matrix.GetLength(0); var columns = matrix.GetLength(1); for (var i = 0; i < lines; ++i) { var sum = this.ring.AdditiveUnity; for (var j = 0; j < columns; ++j) { var value = this.ring.Multiply( matrix[i, j], vec[j]); sum = this.ring.Add( sum, value); } if (!this.ring.Equals(sum, independent[i, 0])) { solution.Vector = null; solution.VectorSpaceBasis.Clear(); } } } }
/// <summary> /// Determina a solução de um sistema linear de equações. /// </summary> /// <remarks> /// A matriz e o vector independente são alterados durante o processo. /// </remarks> /// <param name="coefficientsMatrix">A matriz dos coeficientes.</param> /// <param name="independentVector">O vector independente.</param> /// <returns>A solução do sistema.</returns> public LinearSystemSolution <ElementType> Run( IMathMatrix <ElementType> coefficientsMatrix, IMathMatrix <ElementType> independentVector) { this.condensationAlgorithm.Run(coefficientsMatrix, independentVector); var result = new LinearSystemSolution <ElementType>(); var matrixLines = coefficientsMatrix.GetLength(0); var matrixColumns = coefficientsMatrix.GetLength(1); var currentPivotLine = 0; var currentPivotColumn = 0; var lastNonZeroColumn = -1; var independentSolutionVector = new ArrayMathVector <ElementType>(matrixColumns, this.field.AdditiveUnity); while (currentPivotLine < matrixLines && currentPivotColumn < matrixColumns) { var pivotValue = coefficientsMatrix[currentPivotLine, currentPivotColumn]; if (this.field.IsAdditiveUnity(pivotValue)) { if (this.field.IsAdditiveUnity(independentSolutionVector[currentPivotLine])) { var basisVector = new ArrayMathVector <ElementType>(matrixColumns, this.field.AdditiveUnity); basisVector[currentPivotColumn] = this.field.AdditiveInverse( this.field.MultiplicativeUnity); var i = currentPivotLine - 1; var j = lastNonZeroColumn; while (i >= 0 && j >= 0) { var linePivotValue = coefficientsMatrix[i, j]; if (this.field.IsMultiplicativeUnity(linePivotValue)) { basisVector[j] = coefficientsMatrix[i, currentPivotColumn]; --i; } --j; } result.VectorSpaceBasis.Add(basisVector); } else { result.Vector = null; result.VectorSpaceBasis.Clear(); return(result); } } else { lastNonZeroColumn = currentPivotColumn; independentSolutionVector[currentPivotColumn] = independentVector[currentPivotLine, 0]; ++currentPivotLine; } ++currentPivotColumn; } result.Vector = independentSolutionVector; return(result); }
/// <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> /// Processa as restantes matrizes. /// </summary> /// <param name="upperTriangMatrix">A matriz triangular superior.</param> /// <param name="diagMatrix">A matriz diagonal.</param> /// <param name="independent">O vector independente.</param> /// <param name="size">O tamanho das matrizes.</param> /// <param name="solution">A solução do sistema.</param> private void ProcessRemainingMatrices( IMathMatrix <CoeffType> upperTriangMatrix, IMathMatrix <CoeffType> diagMatrix, IMathVector <CoeffType> independent, int size, LinearSystemSolution <CoeffType> solution) { var field = this.decompositionAlgorithm.Field; var innerSize = size - 1; for (var i = innerSize; i >= 0; --i) { var diagValue = diagMatrix[i, i]; if (field.IsAdditiveUnity(diagValue)) { var basisVector = this.basisVectorFactory.Invoke( size, field.AdditiveUnity); var basisVal = field.MultiplicativeUnity; basisVector[i] = basisVal; for (var j = i - 1; j >= 0; --j) { if (!field.IsAdditiveUnity(diagMatrix[j, j])) { var curr = upperTriangMatrix[j, i]; curr = field.Multiply( curr, basisVal); curr = field.AdditiveInverse(curr); basisVector[j] = field.Add( basisVector[j], curr); } } solution.VectorSpaceBasis.Add(basisVector); } else { var value = independent[i]; if (!field.IsAdditiveUnity(value)) { for (var j = i - 1; j >= 0; --j) { if (!field.IsAdditiveUnity(diagMatrix[j, j])) { var curr = upperTriangMatrix[j, i]; curr = field.Multiply( curr, value); curr = field.AdditiveInverse(curr); independent[j] = field.Add( independent[j], curr); } } } var basis = solution.VectorSpaceBasis; var basisCount = basis.Count; for (var k = 0; k < basisCount; ++k) { var vec = basis[k]; var basisVal = vec[i]; if (!field.IsAdditiveUnity(basisVal)) { for (var j = i - 1; j >= 0; --j) { if (!field.IsAdditiveUnity(diagMatrix[j, j])) { var curr = upperTriangMatrix[j, i]; curr = field.Multiply( curr, basisVal); curr = field.AdditiveInverse(curr); vec[j] = field.Add( vec[j], curr); } } } } } } solution.Vector = independent; }
/// <summary> /// Obtém os valores da solução. /// </summary> /// <param name="solution">A solução do sistema modular.</param> /// <param name="matrixList">A matriz.</param> /// <param name="primesList">A lista dos números primos da base.</param> /// <param name="innerData">O número que está a ser factorizado.</param> /// <returns>Os factores.</returns> private Tuple <NumberType, NumberType> GetSolution( LinearSystemSolution <int> solution, List <int[]> matrixList, List <int> primesList, NumberType innerData) { var innerDataModularField = this.modularFieldFactory.CreateInstance(innerData); var countFactors = primesList.Count - 1; foreach (var solutionBase in solution.VectorSpaceBasis) { var firstValue = this.integerNumber.MultiplicativeUnity; var factorsCount = new Dictionary <int, int>(); for (int i = 0; i < matrixList.Count; ++i) { var currentMatrixLine = matrixList[i]; if (solutionBase[i] == 1) { firstValue = innerDataModularField.Multiply( firstValue, this.integerNumber.GetNorm(this.integerNumber.MapFrom(currentMatrixLine[currentMatrixLine.Length - 1]))); for (int j = 0; j < countFactors; ++j) { if (currentMatrixLine[j] != 0) { var countValue = 0; if (factorsCount.TryGetValue(primesList[j], out countValue)) { countValue += currentMatrixLine[j]; factorsCount[primesList[j]] = countValue; } else { factorsCount.Add(primesList[j], currentMatrixLine[j]); } } } } } var secondValue = this.integerNumber.MultiplicativeUnity; foreach (var factorCountKvp in factorsCount) { var primePower = MathFunctions.Power( this.integerNumber.MapFrom(factorCountKvp.Key), factorCountKvp.Value / 2, innerDataModularField); secondValue = innerDataModularField.Multiply( secondValue, primePower); } if (!this.integerNumber.Equals(firstValue, secondValue)) { var firstFactor = MathFunctions.GreatCommonDivisor( innerData, this.integerNumber.GetNorm(this.integerNumber.Add(firstValue, this.integerNumber.AdditiveInverse(secondValue))), this.integerNumber); if (!this.integerNumber.IsMultiplicativeUnity(firstFactor)) { var secondFactor = this.integerNumber.Quo(innerData, firstFactor); return(Tuple.Create(firstFactor, secondFactor)); } } } return(Tuple.Create(this.integerNumber.MultiplicativeUnity, innerData)); }