Better Gaussian elimination & vector class
This commit is contained in:
parent
d0e27ea7da
commit
fb615bd304
|
@ -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);
|
||||
});
|
84
matrix.ts
84
matrix.ts
|
@ -122,7 +122,6 @@ export class Matrix {
|
|||
let pivot_index = -1;
|
||||
for(let i=0; i<this.rows; i++) {
|
||||
for(let j=0; j<this.cols; j++) {
|
||||
console.log(this.matrix[i][j], pivot_index);
|
||||
if(this.matrix[i][j] == 0) {
|
||||
if(j > 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<pivots.length; i++) {
|
||||
if(pivots[i] < pivots[i-1]) new_matrix.unshift(matrix[i]);
|
||||
else new_matrix.push(matrix[i]);
|
||||
if(pivots[i] < pivots[i-1]) new_matrix.unshift(m[i]);
|
||||
else new_matrix.push(m[i]);
|
||||
}
|
||||
this.matrix.set(...new_matrix);
|
||||
return new Matrix(...new_matrix);
|
||||
}
|
||||
|
||||
solve() {
|
||||
for(let v_offset=0; v_offset<this.matrix.rows; v_offset++) {
|
||||
this.sort();
|
||||
let matrix = this.matrix.matrix;
|
||||
let h_offset = this.matrix.pivots()[v_offset];
|
||||
let first_number = matrix[v_offset][h_offset];
|
||||
for(let i=1+v_offset; i<matrix.length; i++) {
|
||||
let n = -matrix[i][h_offset]/first_number;
|
||||
this.matrix.matrix[i] = matrix[i].map((c, j) => c + n*matrix[v_offset][j]);
|
||||
static ge(matrix: Matrix): Matrix {
|
||||
for(let v_offset=0; v_offset<matrix.rows; v_offset++) {
|
||||
matrix = this.sort(matrix);
|
||||
let m = matrix.matrix;
|
||||
let h_offset = matrix.pivots()[v_offset];
|
||||
let first_number = m[v_offset][h_offset];
|
||||
for(let i=1+v_offset; i<matrix.rows; i++) {
|
||||
let n = -m[i][h_offset]/first_number;
|
||||
m[i] = m[i].map((c, j) => 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<solved_matrix.rows; row++) {
|
||||
let col = pivots[row];
|
||||
let pivot = solved_matrix.matrix[row][col];
|
||||
results.push(solved_matrix.matrix[row][solved_matrix.cols-1]/pivot);
|
||||
}
|
||||
if(results.filter(n => isNaN(n)).length == 0) return results;
|
||||
else return solved_matrix;
|
||||
}
|
||||
|
||||
}
|
30
vector.ts
Normal file
30
vector.ts
Normal file
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue