Calcolare l’inversa di una matrice in JavaScript

L'inversa di una matrice gioca un ruolo cruciale in molte applicazioni dell'algebra lineare, dalla risoluzione di sistemi di equazioni lineari alla trasformazione di coordinate e oltre. Una matrice A è invertibile solo se esiste una matrice B tale che AB=BA=I, dove I è la matrice identità e il determinante di A non è zero.

In JavaScript, linguaggio senza una libreria matematica integrata per operazioni avanzate come l'inversione di matrici, possiamo implementare questa funzionalità da soli. Questa guida illustrerà come calcolare l'inversa di una matrice utilizzando JavaScript, partendo dai principi teorici fino all'implementazione pratica.

Fondamenti Teorici

Prima di immergerci nel codice, è importante comprendere il concetto di matrice inversa e i metodi per calcolarla. Un metodo comune per trovare l'inversa di una matrice è utilizzare la formula dell'aggiunta matriciale, che richiede il calcolo del determinante della matrice (che deve essere non nullo) e dei cofattori di ogni elemento della matrice.

Un'altra tecnica popolare è il metodo di eliminazione di Gauss-Jordan, che trasforma la matrice in una matrice identità attraverso una serie di operazioni elementari sulle righe, applicate simultaneamente a una matrice identità inizialmente accostata alla matrice di interesse. Il risultato finale sulla matrice identità originale sarà l'inversa della matrice di partenza.

Implementazione in JavaScript

L'implementazione dell'inversione di matrici in JavaScript può essere complessa, ma è fattibile. Mostreremo un approccio basato sul metodo di eliminazione di Gauss-Jordan per calcolare l'inversa di una matrice.

Prima di procedere con l'algoritmo, dobbiamo assicurarci che la matrice sia quadrata (necessaria per calcolare l'inversa) e che il suo determinante sia non nullo. Iniziamo definendo una funzione per verificare queste condizioni:

function isSquareAndNonSingular(matrix) {
	if (matrix.length === 0 || matrix.length !== matrix[0].length) {
		return false; // Non è quadrata
	}
	// Qui potresti inserire il calcolo del determinante per verificare se è non nullo
	return true; // Assumiamo per ora che sia non singolare
}

L'idea di base dell'algoritmo di Gauss-Jordan è di applicare operazioni elementari sulle righe fino a che la matrice originale A non è stata trasformata nella matrice identità I, e la matrice identità inizialmente accostata ad A sarà trasformata nell'inversa di A.

function calcolaInversa(matrice) {
	if (!isSquareAndNonSingular(matrice)) {
		throw new Error("La matrice deve essere quadrata e non singolare.");
	}

	let n = matrice.length;
	let identita = new Array(n).fill(null).map(() => new Array(n).fill(0));
	let copia = matrice.map(riga => [...riga]); // Copia della matrice originale

	// Inizializzazione della matrice identità
	for (let i = 0; i < n; i++) {
		identita[i][i] = 1;
	}

	// Applicazione dell'algoritmo di Gauss-Jordan
	for (let i = 0; i < n; i++) {
		// Ricerca dell'elemento massimo nella colonna corrente
		let maxEl = Math.abs(copia[i][i]);
		let maxRow = i;
		for (let k = i + 1; k < n; k++) {
			if (Math.abs(copia[k][i]) > maxEl) {
				maxEl = Math.abs(copia[k][i]);
					maxRow = k;
			}
		}

		// Scambio delle righe massime con la riga corrente
		[copia[i], copia[maxRow]] = [copia[maxRow], copia[i]];
		[identita[i], identita[maxRow]] = [identita[maxRow], identita[i]];

		// Rendi tutti gli elementi della colonna corrente eccetto l'elemento corrente uguali a zero
		for (let k = 0; k < n; k++) {
			let t = copia[k][i] / copia[i][i];
			if (k !== i) {
				for (let j = 0; j < n; j++) {
					copia[k][j] -= copia[i][j] * t;
						identita[k][j] -= identita[i][j] * t;
				}
			}
		}
	}

	// Normalizzazione delle righe
	for (let i = 0; i < n; i++) {
		let div = copia[i][i];
		for (let j = 0; j < n; j++) {
			identita[i][j] /= div;
				identita[i][j] = +identita[i][j].toFixed(2);
		}
	}

	return identita;
}

Considerazioni sull'efficienza

L'algoritmo di Gauss-Jordan, sebbene sia abbastanza diretto da implementare, non è il più efficiente per matrici di grandi dimensioni o in contesti ad alta performance. In tali casi, potrebbero essere preferibili metodi come la decomposizione LU o QR, che, tuttavia, richiedono una comprensione più approfondita e un'implementazione più complessa.

Conclusione

Calcolare l'inversa di una matrice in JavaScript è un'esercitazione utile per comprendere sia la teoria matematica sottostante sia le tecniche di programmazione avanzate. Mentre l'esempio fornito qui implementa un approccio relativamente semplice, esistono molte ottimizzazioni e miglioramenti possibili per gestire casi più complessi e matrici di grandi dimensioni.