Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | 445x 445x 445x 297x 297x 297x 187x 187x 124x 124x 3x 3x 124x 110x 110x 228x 103x 125x 110x 110x 110x 6x 104x 124x 124x 124x 124x 124x 24x 24x 24x 24x 24x 71x 71x 71x 8x 63x 3x 3x 3x 63x 63x 63x 63x 24x 47x 24x | import { Matrix } from "./matrix.mjs";
export class AugmentedMatrix {
/**
*
* @param {Matrix} leftHandSide
* @param {Matrix=} rightHandSide
*/
constructor(leftHandSide, rightHandSide) {
Iif (rightHandSide && leftHandSide.rows !== rightHandSide.rows) {
throw Error('The left hand side must have the same number of rows as the right hand side');
}
this._leftHandSide = leftHandSide;
this._rightHandSide = rightHandSide ?? new Matrix(leftHandSide.rows, 0);
}
/**
* Returns a view of the augmented matrix that only contains the selected row
* @param {number} row
* @returns {AugmentedMatrix}
*/
getRow(row) {
const leftHandSide = this._leftHandSide.slice(0, this._leftHandSide.cols, row, row + 1);
const rightHandSide = this._rightHandSide.slice(0, this._rightHandSide.cols, row, row + 1);
return new AugmentedMatrix(leftHandSide, rightHandSide);
}
/**
* Multiplies both sides of equation
* @param {number} factor
*/
multiply(factor) {
this._leftHandSide.multiply(factor, this._leftHandSide);
this._rightHandSide.multiply(factor, this._rightHandSide);
}
/**
*
* @param {AugmentedMatrix} other
*/
add(other) {
this._leftHandSide.add(other._leftHandSide, this._leftHandSide);
this._rightHandSide.add(other._rightHandSide, this._rightHandSide);
}
/**
*
* @param {number} rowOne
* @param {number} rowTwo
*/
rowSwap(rowOne, rowTwo) {
this._leftHandSide.rowSwap(rowOne, rowTwo);
this._rightHandSide.rowSwap(rowOne, rowTwo);
}
/**
* Deep copy of system
* @returns {AugmentedMatrix}
*/
copy() {
return new AugmentedMatrix(this._leftHandSide.copy(), this._rightHandSide.copy());
}
/**
* Clears out rows below or above pivot row.
* @param {number} pivot
* @param {'up'|'down'} direction the direction to go
*/
clearOutRows(pivot, direction) {
const delta = direction === 'up' ? -1 : 1;
/**
* @param {number} row
* @returns {boolean}
*/
const condition = (row) => {
if (direction === 'up') {
return row >= 0;
}
return row < this._leftHandSide.rows;
};
const pivotRowEquation = this.getRow(pivot);
const pivotValue = this._leftHandSide.get(pivot, pivot);
if (pivotValue < Number.EPSILON) {
return;
}
for (let targetRow = pivot+delta; condition(targetRow); targetRow += delta) {
const multiples = this._leftHandSide.get(pivot, targetRow) / pivotValue;
const targetRowEquation = this.getRow(targetRow);
const subtractOff = pivotRowEquation.copy();
subtractOff.multiply(-multiples);
targetRowEquation.add(subtractOff);
}
}
/**
* Performs Gauss Jordan Elimination on linear system
* @returns {{
* leftHandSide: Matrix,
* rightHandSide: Matrix,
* scaledDown: number,
* }}
*/
gje() {
const rightHandSide = this._rightHandSide;
const leftHandSide = this._leftHandSide;
let swaps = 0;
let totalScale = 1;
// put left matrix into row echelon
for (let row = 0; row < Math.min(leftHandSide.rows, leftHandSide.cols); row++) {
let scaleFactor = leftHandSide.get(row, row);
const pivot = leftHandSide.findFirstRowWithPivot(row);
if (pivot === undefined) {
// There's not a pivot for this row so no need to clear out the rows below
continue;
}
if (pivot !== row) {
swaps++;
this.rowSwap(row, pivot);
scaleFactor = leftHandSide.get(row, row);
}
totalScale *= scaleFactor;
const equation = this.getRow(row);
equation.multiply(1 / scaleFactor);
this.clearOutRows(row, 'down');
}
// convert left into reduced row echelon
for (let row = leftHandSide.rows - 1; row > 0; row--) {
this.clearOutRows(row, 'up');
}
return {
leftHandSide,
rightHandSide,
scaledDown: (-1) ** swaps * totalScale,
}
}
}
|