diff --git a/__tests__/matrix.ts b/__tests__/matrix.ts index 5b1f4de..1f47b8c 100644 --- a/__tests__/matrix.ts +++ b/__tests__/matrix.ts @@ -32,13 +32,11 @@ test('Multiply (B, A, C)', () => { expect(B.mul(A).eq(C)).toBe(false); }); -let D = new GaussianElimination( - new Matrix( - [1, 2, -1, 1, 2], - [2, 5, 0, 1, 5], - [3, 7, -1, 3, 9], - [1, 3, 1, 1, 5] - ) +let D = new Matrix( + [1, 2, -1, 1, 2], + [2, 5, 0, 1, 5], + [3, 7, -1, 3, 9], + [1, 3, 1, 1, 5] ); let D_solved = new Matrix( @@ -49,14 +47,12 @@ let D_solved = new Matrix( ); test('Gaussian elimination (D)', () => { - expect(D.solve().eq(D_solved)).toBe(true); + expect(GaussianElimination.ge(D).eq(D_solved)).toBe(true); }); -let E = new GaussianElimination( - new Matrix( - [1, 1, 3], - [2, -1, 4] - ) +let E = new Matrix( + [1, 1, 3], + [2, -1, 4] ); let E_solved = new Matrix( @@ -65,23 +61,52 @@ let E_solved = new Matrix( ); test('Gaussian elimination (E)', () => { - expect(E.solve().eq(E_solved)).toBe(true); + expect(GaussianElimination.ge(E).eq(E_solved)).toBe(true); }); let F = new Matrix( + [2, 1, -1, 8], + [-3, -1, 2, -11], + [-2, 1, 2, -3] +); + +let F_solved = new Matrix( + [2, 0, 0, 4], + [0, 0.5, 0, 1.5], + [0, 0, -1, 1] +); + +let F_results = GaussianElimination.solve(F); + +test('Gauss-Jordan elimination (F)', () => { + expect(GaussianElimination.gje(F).eq(F_solved)).toBe(true); +}); + +test('Only one result of Gauss-Jordan elimination (F)', () => { + expect(F_results instanceof Matrix).toBe(false); +}); + +test('Results of Gauss-Jordan elimination (F)', () => { + [2, 3, -1].forEach((result, i) => { + if(F_results instanceof Matrix) throw("Result is matrix!"); + expect(result == F_results[i]).toBe(true); + }); +}); + +let G = new Matrix( [1, 1, 1], [0, 2, 4], [0, 0, 5], ); -let G = new Matrix( +let I = new Matrix( [1, 0, 0], [5, 2, 0], [4, 8, 5], ); test('Upper triangular matrix (F)', () => { - expect(F.is_triangular()).toBe(true); + expect(G.is_triangular()).toBe(true); }); test('Upper triangular matrix (A)', () => { @@ -89,5 +114,5 @@ test('Upper triangular matrix (A)', () => { }); test('Lower triangular matrix (G)', () => { - expect(G.is_triangular(TriangularForm.LOWER)).toBe(true); + expect(I.is_triangular(TriangularForm.LOWER)).toBe(true); }); \ No newline at end of file diff --git a/matrix.ts b/matrix.ts index fdec8d6..cac67bb 100644 --- a/matrix.ts +++ b/matrix.ts @@ -122,7 +122,6 @@ export class Matrix { let pivot_index = -1; for(let i=0; i pivot_index) pivot_index = j; } else if(pivot_index >= j) return false; @@ -155,46 +154,77 @@ export class Matrix { return pivots; } + remove_row(row: number) { + let m = [...this.matrix]; + m.splice(row, 1); this.set(...m); + } + } -export class GaussianElimination { +export abstract class GaussianElimination { - matrix: Matrix; - - constructor(matrix: Matrix) { - this.matrix = matrix; + static make_pivot_1(row: number[]) { + let d = 0; + return row.map((n, i) => { + if(n != 0 && !d) d = n; + return d && n ? n / d : 0; + }); } - sort() { - let matrix = this.matrix.matrix; - let new_matrix = [matrix[0]]; - let pivots = this.matrix.pivots(); + static sort(matrix: Matrix) { + let m = matrix.matrix; + let new_matrix = [m[0]]; + let pivots = matrix.pivots(); for(let i=1; i c + n*matrix[v_offset][j]); + static ge(matrix: Matrix): Matrix { + for(let v_offset=0; v_offset c + n*m[v_offset][j]); } } - return this.matrix; + return matrix; } - mul_row(index: number, number: number, replace: boolean = false) { - let row = this.matrix.matrix[index].map(original => number * original); - if(replace) this.matrix.matrix[index] = row; - return row; + static gje(matrix: Matrix): Matrix { + matrix = this.ge(matrix); + let pivots = matrix.pivots(); + for(let v_offset=matrix.rows-1; v_offset>0; v_offset--) { + let m = matrix.matrix; + let h_offset = pivots[v_offset]; + if(h_offset >= matrix.cols) continue; + let first_number = m[v_offset][h_offset]; + for(let i=v_offset-1; i>=0; i--) { + let n = -m[i][h_offset]/first_number; + m[i] = m[i].map((c, j) => c + n*m[v_offset][j]); + } + } + return matrix; + } + + static solve(matrix: Matrix): number[] | Matrix { + let solved_matrix = this.gje(matrix); + let pivots = solved_matrix.pivots(); + let results: number[] = []; + solved_matrix.matrix = solved_matrix.matrix.map(GaussianElimination.make_pivot_1); + for(let row=0; row isNaN(n)).length == 0) return results; + else return solved_matrix; } } \ No newline at end of file diff --git a/vector.ts b/vector.ts new file mode 100644 index 0000000..ef1f3d2 --- /dev/null +++ b/vector.ts @@ -0,0 +1,30 @@ +import { GaussianElimination, Matrix, RawMatrix } from "./matrix"; + +export class Vector extends Matrix { + + constructor(...coords: number[]) { + let rm: RawMatrix = coords.map(c => [c]); + super(...rm); + } + + coords() { + return this.matrix.map(row => row[0]); + } + +} + +export class LinearIndependence { + + vectors: Vector[]; + + constructor(...v: Vector[]) { + this.vectors = v; + } + + check(): [boolean, (number[] | Matrix)] { + let rows = this.vectors.map(v => [...v.coords(), 0]); + let result = GaussianElimination.solve(new Matrix(...rows)); + return [!(result instanceof Matrix), result]; + } + +} \ No newline at end of file