Calcul de masortingce inverse Java

J’essaie de calculer la masortingce inverse en Java.

Je suis la méthode adjointe (premier calcul de la masortingce adjointe, puis transposition de cette masortingce et enfin multiplication pour l’inverse de la valeur du déterminant).

Cela fonctionne quand la masortingce n’est pas trop grosse. J’ai vérifié que pour les masortingces allant jusqu’à 12×12, le résultat est rapidement fourni. Toutefois, lorsque la masortingce est supérieure à 12×12, le temps nécessaire pour effectuer le calcul augmente de manière exponentielle.

La masortingce que j’ai besoin d’inverser est 19×19, et cela prend trop de temps. La méthode qui consum le plus de temps est la méthode utilisée pour le calcul du déterminant.

Le code que j’utilise est:

public static double determinant(double[][] input) { int rows = nRows(input); //number of rows in the masortingx int columns = nColumns(input); //number of columns in the masortingx double determinant = 0; if ((rows== 1) && (columns == 1)) return input[0][0]; int sign = 1; for (int column = 0; column < columns; column++) { double[][] submatrix = getSubmatrix(input, rows, columns,column); determinant = determinant + sign*input[0][column]*determinant(submatrix); sign*=-1; } return determinant; } 

Est-ce que quelqu’un sait comment calculer plus efficacement le déterminant d’une grande masortingce? Sinon, est-ce que quelqu’un sait comment calculer l’inverse d’une grande masortingce en utilisant un autre algorithme?

Merci

Exponentiellement? Non, je crois que l’inversion de la masortingce est O (N ^ 3).

Je recommanderais d’utiliser la décomposition de LU pour résoudre une équation masortingcielle. Vous n’avez pas à résoudre pour le déterminant lorsque vous l’utilisez.

Mieux encore, cherchez un forfait pour vous aider. JAMA vient à l’esprit.

Les formats 12×12 ou 19×19 ne sont pas de grandes masortingces. Il est courant de résoudre des problèmes avec des dizaines ou des centaines de milliers de degrés de liberté.

Voici un exemple pratique d’utilisation de JAMA. Vous devez avoir le bocal JAMA dans votre CLASSPATH lorsque vous comstackz et exécutez:

 package linearalgebra; import Jama.LUDecomposition; import Jama.Masortingx; public class JamaDemo { public static void main(Ssortingng[] args) { double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}}; // each array is a row in the masortingx double [] rhs = { 9, 1, 0 }; // rhs vector double [] answer = { 1, 2, 3 }; // this is the answer that you should get. Masortingx a = new Masortingx(values); a.print(10, 2); LUDecomposition luDecomposition = new LUDecomposition(a); luDecomposition.getL().print(10, 2); // lower masortingx luDecomposition.getU().print(10, 2); // upper masortingx Masortingx b = new Masortingx(rhs, rhs.length); Masortingx x = luDecomposition.solve(b); // solve Ax = b for the unknown vector x x.print(10, 2); // print the solution Masortingx residual = a.times(x).minus(b); // calculate the residual error double rnorm = residual.normInf(); // get the max error (yes, it's very small) System.out.println("residual: " + rnorm); } } 

Voici le même problème résolu avec Apache Commons Math, selon la recommandation de quant_dev:

 package linearalgebra; import org.apache.commons.math.linear.Array2DRowRealMasortingx; import org.apache.commons.math.linear.ArrayRealVector; import org.apache.commons.math.linear.DecompositionSolver; import org.apache.commons.math.linear.LUDecompositionImpl; import org.apache.commons.math.linear.RealMasortingx; import org.apache.commons.math.linear.RealVector; public class LinearAlgebraDemo { public static void main(Ssortingng[] args) { double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}}; double [] rhs = { 9, 1, 0 }; RealMasortingx a = new Array2DRowRealMasortingx(values); System.out.println("a masortingx: " + a); DecompositionSolver solver = new LUDecompositionImpl(a).getSolver(); RealVector b = new ArrayRealVector(rhs); RealVector x = solver.solve(b); System.out.println("solution x: " + x);; RealVector residual = a.operate(x).subtract(b); double rnorm = residual.getLInfNorm(); System.out.println("residual: " + rnorm); } } 

Adaptez-les à votre situation.

Je recommanderais d’utiliser Apache Commons Math 2.0 pour cela. JAMA est un projet mort. En réalité, ACM 2.0 a utilisé l’algèbre linéaire de JAMA et l’a développée davantage.

L’inversion de masortingce est très intensive en calcul. Comme le répond le duffymo, LU est un bon algorithme et il en existe d’autres variantes (QR, par exemple).

Malheureusement, vous ne pouvez pas vous débarrasser des calculs lourds … et peut-être que bottelneck est la méthode getSubmasortingx si vous n’utilisez pas une bibliothèque optimisée.

De plus, les structures masortingcielles spéciales (masortingces de bande, symésortinge, diagonalité, faible densité) ont un impact important sur les performances si elles sont sockets en compte dans les calculs. Votre kilométrage peut varier…

Vous ne voulez JAMAIS calculer une masortingce inverse de cette façon. Ok, le calcul de l’inverse lui-même doit être évité, car il est presque toujours préférable d’utiliser une factorisation telle qu’une LU.

Le calcul du déterminant à l’aide de calculs récursifs est une opération numériquement obscène. Il s’avère qu’un meilleur choix consiste à utiliser une factorisation de LU pour calculer un déterminant. Mais si vous avez la peine de calculer les facteurs LU, pourquoi voudriez-vous éventuellement calculer l’inverse? Vous avez déjà effectué le travail difficile en calculant les facteurs de LU.

Une fois que vous avez les facteurs LU, vous pouvez les utiliser pour effectuer une substitution en arrière.

Dans la mesure où une masortingce 19×19 étant volumineuse, elle n’est même pas proche de ce que je penserais de grosse.

La bibliothèque la4j (algèbre linéaire pour Java) prend en charge l’inversion de masortingce. Voici le bref exemple:

 Masortingx a = new Basic2DMasortingx(new double[][]{ { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 }, { 7.0, 8.0. 9.0 } }); Masortingx b = a.invert(Masortingces.DEFAULT_INVERTOR); // uses Gaussian Elimination 

Votre algorithme pour calculer un déterminant est en effet exponentiel. Le problème de base est que vous calculez à partir de la définition et que la définition simple conduit à une quantité exponentielle de sous-déterminants à calculer. Vous devez vraiment transformer la masortingce avant de calculer son déterminant ou son inverse. (J’ai pensé expliquer la programmation dynamic, mais ce problème ne peut pas être résolu par la programmation dynamic car le nombre de sous-problèmes est également exponentiel.)

La décomposition de LU, comme recommandé par d’autres, est un bon choix. Si vous débutez dans le calcul masortingciel, vous pouvez également vous intéresser à l’élimination gaussienne pour calculer les déterminants et les inverses, car cela pourrait être un peu plus facile à comprendre au début.

Et une chose à retenir dans l’inversion de masortingce est la stabilité numérique, car vous avez affaire à des nombres à virgule flottante. Tous les bons algorithmes incluent des permutations de lignes et / ou de colonnes pour choisir les pivots appropriés, comme on les appelle. Au moins dans l’élimination gaussienne, vous voulez permuter les colonnes à chaque étape de sorte que l’élément le plus grand en valeur absolue soit choisi comme pivot, car c’est le choix le plus stable.

Il est difficile de battre Matlab à leur jeu. Ils sont également prudents quant à la précision. Si vous avez les pivots 2.0 et 2.00001 – faites attention! Votre réponse pourrait être très imprécise. Découvrez également l’implémentation de Python (il est quelque part dans numpy / scipy …)

Devez-vous avoir une solution exacte? Un solveur approximatif ( Gauss-Seidel est très performant et facile à mettre en œuvre) fonctionnera probablement pour vous et convergera très rapidement. 19×19 est une masortingce assez petite. Je pense que le code de Gauss-Seidel que j’ai utilisé pourrait résoudre une masortingce de 128×128 en un clin d’œil (mais ne me citez pas dessus, cela fait longtemps).

Depuis que la bibliothèque ACM a été mise à jour au fil des ans, voici l’implémentation conforme à la dernière définition de l’inversion de masortingce.

 import org.apache.commons.math3.linear.Array2DRowRealMasortingx; import org.apache.commons.math3.linear.ArrayRealVector; import org.apache.commons.math3.linear.DecompositionSolver; import org.apache.commons.math3.linear.LUDecomposition; import org.apache.commons.math3.linear.RealMasortingx; import org.apache.commons.math3.linear.RealVector; public class LinearAlgebraDemo { public static void main(Ssortingng[] args) { double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}}; double [][] rhs = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; // Solving AB = I for given A RealMasortingx A = new Array2DRowRealMasortingx(values); System.out.println("Input A: " + A); DecompositionSolver solver = new LUDecomposition(A).getSolver(); RealMasortingx I = new Array2DRowRealMasortingx(rhs); RealMasortingx B = solver.solve(I); System.out.println("Inverse B: " + B); } } 

Pour ceux qui recherchent une inversion masortingcielle (pas rapide), voir https://github.com/rchen8/Algorithms/blob/master/Masortingx.java .

 import java.util.Arrays; public class Masortingx { private static double determinant(double[][] masortingx) { if (masortingx.length != masortingx[0].length) throw new IllegalStateException("invalid dimensions"); if (masortingx.length == 2) return masortingx[0][0] * masortingx[1][1] - masortingx[0][1] * masortingx[1][0]; double det = 0; for (int i = 0; i < matrix[0].length; i++) det += Math.pow(-1, i) * matrix[0][i] * determinant(minor(matrix, 0, i)); return det; } private static double[][] inverse(double[][] matrix) { double[][] inverse = new double[matrix.length][matrix.length]; // minors and cofactors for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[i].length; j++) inverse[i][j] = Math.pow(-1, i + j) * determinant(minor(matrix, i, j)); // adjugate and determinant double det = 1.0 / determinant(matrix); for (int i = 0; i < inverse.length; i++) { for (int j = 0; j <= i; j++) { double temp = inverse[i][j]; inverse[i][j] = inverse[j][i] * det; inverse[j][i] = temp * det; } } return inverse; } private static double[][] minor(double[][] matrix, int row, int column) { double[][] minor = new double[matrix.length - 1][matrix.length - 1]; for (int i = 0; i < matrix.length; i++) for (int j = 0; i != row && j < matrix[i].length; j++) if (j != column) minor[i < row ? i : i - 1][j < column ? j : j - 1] = matrix[i][j]; return minor; } private static double[][] multiply(double[][] a, double[][] b) { if (a[0].length != b.length) throw new IllegalStateException("invalid dimensions"); double[][] matrix = new double[a.length][b[0].length]; for (int i = 0; i < a.length; i++) { for (int j = 0; j < b[0].length; j++) { double sum = 0; for (int k = 0; k < a[i].length; k++) sum += a[i][k] * b[k][j]; matrix[i][j] = sum; } } return matrix; } private static double[][] rref(double[][] matrix) { double[][] rref = new double[matrix.length][]; for (int i = 0; i < matrix.length; i++) rref[i] = Arrays.copyOf(matrix[i], matrix[i].length); int r = 0; for (int c = 0; c < rref[0].length && r < rref.length; c++) { int j = r; for (int i = r + 1; i < rref.length; i++) if (Math.abs(rref[i][c]) > Math.abs(rref[j][c])) j = i; if (Math.abs(rref[j][c]) < 0.00001) continue; double[] temp = rref[j]; rref[j] = rref[r]; rref[r] = temp; double s = 1.0 / rref[r][c]; for (j = 0; j < rref[0].length; j++) rref[r][j] *= s; for (int i = 0; i < rref.length; i++) { if (i != r) { double t = rref[i][c]; for (j = 0; j < rref[0].length; j++) rref[i][j] -= t * rref[r][j]; } } r++; } return rref; } private static double[][] transpose(double[][] matrix) { double[][] transpose = new double[matrix[0].length][matrix.length]; for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[i].length; j++) transpose[j][i] = matrix[i][j]; return transpose; } public static void main(String[] args) { // example 1 - solving a system of equations double[][] a = { { 1, 1, 1 }, { 0, 2, 5 }, { 2, 5, -1 } }; double[][] b = { { 6 }, { -4 }, { 27 } }; double[][] matrix = multiply(inverse(a), b); for (double[] i : matrix) System.out.println(Arrays.toString(i)); System.out.println(); // example 2 - example 1 using reduced row echelon form a = new double[][]{ { 1, 1, 1, 6 }, { 0, 2, 5, -4 }, { 2, 5, -1, 27 } }; matrix = rref(a); for (double[] i : matrix) System.out.println(Arrays.toString(i)); System.out.println(); // example 3 - solving a normal equation for linear regression double[][] x = { { 2104, 5, 1, 45 }, { 1416, 3, 2, 40 }, { 1534, 3, 2, 30 }, { 852, 2, 1, 36 } }; double[][] y = { { 460 }, { 232 }, { 315 }, { 178 } }; matrix = multiply( multiply(inverse(multiply(transpose(x), x)), transpose(x)), y); for (double[] i : matrix) System.out.println(Arrays.toString(i)); } }