231 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			231 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | ||
|  | id: 5a23c84252665b21eecc7e77 | ||
|  | title: Gaussian elimination | ||
|  | challengeType: 5 | ||
|  | forumTopicId: 302272 | ||
|  | dashedName: gaussian-elimination | ||
|  | --- | ||
|  | 
 | ||
|  | # --description--
 | ||
|  | 
 | ||
|  | Write a function to solve \\(Ax = b\\) using Gaussian elimination then backwards substitution. | ||
|  | 
 | ||
|  | \\(A\\) being an \\(n \\times n\\) matrix. Also, \\(x\\) and \\(b\\) are \\(n\\) by 1 vectors. | ||
|  | 
 | ||
|  | To improve accuracy, please use partial pivoting and scaling. | ||
|  | 
 | ||
|  | # --hints--
 | ||
|  | 
 | ||
|  | `gaussianElimination` should be a function. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert(typeof gaussianElimination == 'function'); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[1,1],[1,-1]], [5,1])` should return an array. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert( | ||
|  |   Array.isArray( | ||
|  |     gaussianElimination( | ||
|  |       [ | ||
|  |         [1, 1], | ||
|  |         [1, -1] | ||
|  |       ], | ||
|  |       [5, 1] | ||
|  |     ) | ||
|  |   ) | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[1,1],[1,-1]], [5,1])` should return `[ 3, 2 ]`. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual( | ||
|  |   gaussianElimination( | ||
|  |     [ | ||
|  |       [1, 1], | ||
|  |       [1, -1] | ||
|  |     ], | ||
|  |     [5, 1] | ||
|  |   ), | ||
|  |   [3, 2] | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[2,3],[2,1]] , [8,4])` should return `[ 1, 2 ]`. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual( | ||
|  |   gaussianElimination( | ||
|  |     [ | ||
|  |       [2, 3], | ||
|  |       [2, 1] | ||
|  |     ], | ||
|  |     [8, 4] | ||
|  |   ), | ||
|  |   [1, 2] | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[1,3],[5,-2]], [14,19])` should return `[ 5, 3 ]`. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual( | ||
|  |   gaussianElimination( | ||
|  |     [ | ||
|  |       [1, 3], | ||
|  |       [5, -2] | ||
|  |     ], | ||
|  |     [14, 19] | ||
|  |   ), | ||
|  |   [5, 3] | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[1,1],[5,-1]] , [10,14])` should return `[ 4, 6 ]`. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual( | ||
|  |   gaussianElimination( | ||
|  |     [ | ||
|  |       [1, 1], | ||
|  |       [5, -1] | ||
|  |     ], | ||
|  |     [10, 14] | ||
|  |   ), | ||
|  |   [4, 6] | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | `gaussianElimination([[1,2,3],[4,5,6],[7,8,8]] , [6,15,23])` should return `[ 1, 1, 1 ]`. | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual( | ||
|  |   gaussianElimination( | ||
|  |     [ | ||
|  |       [1, 2, 3], | ||
|  |       [4, 5, 6], | ||
|  |       [7, 8, 8] | ||
|  |     ], | ||
|  |     [6, 15, 23] | ||
|  |   ), | ||
|  |   [1, 1, 1] | ||
|  | ); | ||
|  | ``` | ||
|  | 
 | ||
|  | # --seed--
 | ||
|  | 
 | ||
|  | ## --seed-contents--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function gaussianElimination(A,b) { | ||
|  | 
 | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | # --solutions--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function gaussianElimination(A, b) { | ||
|  |   // Lower Upper Decomposition | ||
|  |   function ludcmp(A) { | ||
|  |     // A is a matrix that we want to decompose into Lower and Upper matrices. | ||
|  |     var d = true | ||
|  |     var n = A.length | ||
|  |     var idx = new Array(n) // Output vector with row permutations from partial pivoting | ||
|  |     var vv = new Array(n) // Scaling information | ||
|  | 
 | ||
|  |     for (var i=0; i<n; i++) { | ||
|  |         var max = 0 | ||
|  |         for (var j=0; j<n; j++) { | ||
|  |             var temp = Math.abs(A[i][j]) | ||
|  |             if (temp > max) max = temp | ||
|  |         } | ||
|  |         if (max == 0) return // Singular Matrix! | ||
|  |         vv[i] = 1 / max // Scaling | ||
|  |     } | ||
|  | 
 | ||
|  |         var Acpy = new Array(n) | ||
|  |         for (var i=0; i<n; i++) { | ||
|  |             var Ai = A[i] | ||
|  |             let Acpyi = new Array(Ai.length) | ||
|  |             for (j=0; j<Ai.length; j+=1) Acpyi[j] = Ai[j] | ||
|  |             Acpy[i] = Acpyi | ||
|  |         } | ||
|  |         A = Acpy | ||
|  | 
 | ||
|  |     var tiny = 1e-20 // in case pivot element is zero | ||
|  |     for (var i=0; ; i++) { | ||
|  |         for (var j=0; j<i; j++) { | ||
|  |             var sum = A[j][i] | ||
|  |             for (var k=0; k<j; k++) sum -= A[j][k] * A[k][i]; | ||
|  |             A[j][i] = sum | ||
|  |         } | ||
|  |         var jmax = 0 | ||
|  |         var max = 0; | ||
|  |         for (var j=i; j<n; j++) { | ||
|  |             var sum = A[j][i] | ||
|  |             for (var k=0; k<i; k++) sum -= A[j][k] * A[k][i]; | ||
|  |             A[j][i] = sum | ||
|  |             var temp = vv[j] * Math.abs(sum) | ||
|  |             if (temp >= max) { | ||
|  |                 max = temp | ||
|  |                 jmax = j | ||
|  |             } | ||
|  |         } | ||
|  |         if (i <= jmax) { | ||
|  |             for (var j=0; j<n; j++) { | ||
|  |                 var temp = A[jmax][j] | ||
|  |                 A[jmax][j] = A[i][j] | ||
|  |                 A[i][j] = temp | ||
|  |             } | ||
|  |             d = !d; | ||
|  |             vv[jmax] = vv[i] | ||
|  |         } | ||
|  |         idx[i] = jmax; | ||
|  |         if (i == n-1) break; | ||
|  |         var temp = A[i][i] | ||
|  |         if (temp == 0) A[i][i] = temp = tiny | ||
|  |         temp = 1 / temp | ||
|  |         for (var j=i+1; j<n; j++) A[j][i] *= temp | ||
|  |     } | ||
|  |     return {A:A, idx:idx, d:d} | ||
|  |   } | ||
|  | 
 | ||
|  |   // Lower Upper Back Substitution | ||
|  |   function lubksb(lu, b) { | ||
|  |     // solves the set of n linear equations A*x = b. | ||
|  |     // lu is the object containing A, idx and d as determined by the routine ludcmp. | ||
|  |     var A = lu.A | ||
|  |     var idx = lu.idx | ||
|  |     var n = idx.length | ||
|  | 
 | ||
|  |         var bcpy = new Array(n) | ||
|  |         for (var i=0; i<b.length; i+=1) bcpy[i] = b[i] | ||
|  |         b = bcpy | ||
|  | 
 | ||
|  |     for (var ii=-1, i=0; i<n; i++) { | ||
|  |         var ix = idx[i] | ||
|  |         var sum = b[ix] | ||
|  |         b[ix] = b[i] | ||
|  |         if (ii > -1) | ||
|  |             for (var j=ii; j<i; j++) sum -= A[i][j] * b[j] | ||
|  |         else if (sum) | ||
|  |             ii = i | ||
|  |         b[i] = sum | ||
|  |     } | ||
|  |     for (var i=n-1; i>=0; i--) { | ||
|  |         var sum = b[i] | ||
|  |         for (var j=i+1; j<n; j++) sum -= A[i][j] * b[j] | ||
|  |         b[i] = sum / A[i][i] | ||
|  |     } | ||
|  |     return b // solution vector x | ||
|  |   } | ||
|  | 
 | ||
|  |     var lu = ludcmp(A) | ||
|  |     if (lu === undefined) return // Singular Matrix! | ||
|  |     return lubksb(lu, b) | ||
|  | } | ||
|  | ``` |