Matrices and systems
Matrix holds fractions, PolyMatrix holds polynoms, and LinearSystem solves systems of linear equations.
import {Matrix, PolyMatrix, LinearSystem} from 'pimath'Matrix
Build a matrix
new Matrix([[1, 2], [3, 4]]).display // ((1,2),(3,4))
new Matrix('((1,2),(3,4))').display // ((1,2),(3,4))
new Matrix(2, 3).display // ((0,0,0),(0,0,0))
new Matrix(2).display // ((0,0),(0,0))
Matrix.fromVectors(new Vector(1, 2), new Vector(3, 4)).display // ((1,3),(2,4))Rows of different lengths throw a DimensionError. Each vector given to fromVectors is a column.
new Matrix([[1, 2], [3]]) // throws DimensionErrorIndices are zero-based.
const M = new Matrix([[1, 2], [3, 4]])
M.dimension // { rows: 2, cols: 2 }
M.values[1][0].display // 3
M.rows.length // 2
M.cols[1].map(f => f.display) // [ '2', '4' ]
M.aij(0, 1).display // 2
M.aij(5, 5) // null
M.setValue(0, 0, 9).display // ((9,2),(3,4))values, rows and cols give copies. setValue throws an IndexError outside of the matrix.
Operations
Operations modify the matrix and return it. A dimension mismatch throws a DimensionError.
new Matrix([[1, 2], [3, 4]]).add(new Matrix([[1, 1], [1, 1]])).display // ((2,3),(4,5))
new Matrix([[1, 2], [3, 4]]).subtract(new Matrix([[1, 1], [1, 1]])).display // ((0,1),(2,3))
new Matrix([[1, 2], [3, 4]]).multiply(2).display // ((2,4),(6,8))
new Matrix([[1, 2], [3, 4]]).multiply(new Matrix([[0, 1], [1, 0]])).display // ((2,1),(4,3))
new Matrix([[1, 2], [3, 4]]).pow(2).display // ((7,10),(15,22))
new Matrix([[1, 2], [3, 4]]).opposite().display // ((-1,-2),(-3,-4))
new Matrix([[1, 2], [3, 4]]).transpose().display // ((1,3),(2,4))
new Matrix([[1, 2], [3, 4]]).inverse().display // ((-2,1),(3/2,-1/2))transpose, rowEchelonForm and reducedRowEchelonForm return a new matrix. inverse throws a MathError when the matrix is not invertible, so test it first.
new Matrix([[1, 2], [3, 4]]).canBeInverted() // true
new Matrix([[1, 2], [2, 4]]).canBeInverted() // false
new Matrix([[1, 2], [3, 4]]).canBeMultiplied(new Matrix(3, 1)) // falseDeterminant, rank and reduction
const M = new Matrix([[1, 2], [3, 4]])
M.determinant().display // -2
M.cofactor(0, 0).display // 4
M.rank() // 2
M.isSquare() // true
new Matrix([[1, 2], [3, 4]]).reducedRowEchelonForm().display // ((1,0),(0,1))
new Matrix([[2, 4], [1, 3]]).rowEchelonForm().display // ((1,2),(0,1))determinant throws a DimensionError for a matrix that is not square. cofactor(i, j) is the signed minor.
Display
const M = new Matrix([[1, 2], [3, 4]])
M.display // ((1,2),(3,4))
M.asBmatrix.display // [(1,2),(3,4)]
M.asVmatrix.display // |(1,2),(3,4)|tex writes a pmatrix environment. The delimiter options asPmatrix (default), asBmatrix, asBraceMatrix, asVmatrix and asDoubleVmatrix are chainable and stay set.
M.tex
// \begin{pmatrix}
// 1 & 2\\
// 3 & 4\\
// \end{pmatrix}withPartition(c) draws a vertical bar before column c, as in an augmented matrix. withDigits(n) shows decimals.
new Matrix([[1, 2, 3], [4, 5, 6]]).withPartition(2).display // ((1,2|3),(4,5|6))
new Matrix([[1, 2], [3, 4]]).multiply('1/3').withDigits(2).display // ((0.33,0.67),(1.00,1.33))Compare and test
new Matrix([[1, 0], [0, 1]]).isOne() // true
new Matrix(2, 2).isZero() // true
new Matrix([[1, 2], [3, 4]]).isEqual(new Matrix([[1, 2], [3, 4]])) // trueGo through the entries
new Matrix([[1, 2], [3, 4]]).map(a => a.value) // [ [ 1, 2 ], [ 3, 4 ] ]
new Matrix([[1, 2], [3, 4]]).flat().map(a => a.display) // [ '1', '2', '3', '4' ]forEach(callback) calls callback(entry, row, column) on the real entries, which can be modified.
PolyMatrix
A PolyMatrix is built like a Matrix and has the same methods, with polynomial entries.
const P = new PolyMatrix([['x', 1], [2, 'x+1']])
P.display // ((x,1),(2,x+1))
P.determinant().display // x^(2)+x-2
PolyMatrix.fromValues([[2, 1], [1, 2]]).characteristic_polynom('k').display // k^(2)-4k+3characteristic_polynom(variable) is the polynom det(A - kI), where variable names the unknown (k by default). PolyMatrix.fromMatrix(M) converts a Matrix.
LinearSystem
A LinearSystem is built from equations written as strings, or from Equation objects.
const S = new LinearSystem('x+y=3', 'x-y=1')
S.display // {(x,+y,=,3),(x,-y,=,1):}
S.variables // [ 'x', 'y' ]
S.solve().map(s => s.display) // [ '2', '1' ]
S.isSolvable() // trueThe solutions come in the order of variables. solve() uses Gauss-Jordan elimination.
- A single solution gives one
Solutionper variable. - A system with no solution gives an empty array.
- A system with infinitely many solutions gives one infinite
Solutionper variable.
new LinearSystem('x+y=3', 'x+y=5').solve().length // 0
new LinearSystem('x+y=3', '2x+2y=6').solve().map(s => s.value) // [ Infinity, Infinity ]
LinearSystem.solutionAsDisplay(new LinearSystem('x+y=3', 'x-y=1').solve()) // (2;1)Build from numbers
new LinearSystem().fromComponents([[1, 1, 3], [1, -1, 1]], 'xy').display // {(x,+y,=,3),(x,-y,=,1):}Each row holds the coefficients of the variables, then the constant of the right member. fromMatrix, fromVectors and fromEquations do the same from other inputs, and replace the equations of the system.
Work step by step
For a lesson on elimination, the system offers the elementary operations. They modify the system.
const S = new LinearSystem('x+y=3', 'x-y=1')
S.multiply(2, 0).display // {(2x,+2y,=,6),(x,-y,=,1):}
S.add(new Equation('x-y=1'), 0).display // {(3x,+y,=,7),(x,-y,=,1):}
S.subtract(new Equation('x-y=1'), 1).display // {(3x,+y,=,7),(,,=,0):}mergeEquations({id, factor}, {id, factor}) returns the combination of two equations without changing the system, and solve_compute_factors(variable) suggests the factors that eliminate a variable. matrix gives the coefficients and the constants, and toAugmentedMatrix() the matrix [A|b].
const [A, b] = new LinearSystem('x+y=3', 'x-y=1').matrix
A.display // ((1,1),(1,-1))
b.display // ((3,1))Members
Matrix
Constructors
new Matrix()new Matrix(rows: number, cols?: number)new Matrix(value: string)new Matrix(values: InputAlgebra<Fraction>[][])
Static members
| Member | Description |
|---|---|
fromString(value: string): Matrix | Build a matrix from its display string, such as "((1,2),(3,4))". |
fromValues(values: InputAlgebra<Fraction>[][]): Matrix | Build a matrix from an array of rows. Throws: {DimensionError} if the rows do not all have the same length. |
fromDimensions(rows: number, cols?: number): Matrix | Build a zero matrix. Without cols, the matrix is square. |
fromVectors(...vectors: Vector[]): Matrix | Build a matrix whose columns are the given vectors. Throws: {DimensionError} if the vectors do not all have the same dimension. |
Properties and getters
| Member | Description |
|---|---|
tex: string | LaTeX output: a pmatrix environment by default, one row per line. With a partition (withPartition), an array with a vertical bar. An empty matrix gives an empty string. |
display: string | Text output such as ((1,2),(3,4)). The outer brackets follow the delimiter option, and a partition adds a |. This is the format read by parse. |
asBmatrix: Matrix | Delimiter option: square brackets. Chainable, persistent. |
asBraceMatrix: Matrix | Delimiter option: braces. Chainable, persistent. |
cols: Fraction[][] | The columns, as an array of arrays (copies of the values). |
dimension: { rows: number; cols: number; } | Number of rows and columns, as {rows, cols}. |
asPmatrix: Matrix | Delimiter option: round brackets (default). Chainable, persistent. |
asVmatrix: Matrix | Delimiter option: single vertical bars, as for a determinant. Chainable, persistent. |
asDoubleVmatrix: Matrix | Delimiter option: double vertical bars. Chainable, persistent. |
rows: Fraction[][] | The rows, as an array of arrays (copies of the values). |
values: Fraction[][] | The entries, as an array of rows (copies of the values). |
Methods
| Member | Description |
|---|---|
parse(value: string | Vector[] | InputAlgebra<Fraction>[][]): Matrix | Replace the content with a display string ("((1,2),(3,4))"), an array of rows, or vectors (one per column). Throws: {DimensionError} if the rows (or the vectors) do not all have the same length. |
copy(value: AbstractMatrix<Fraction>): Matrix | Copy the values and the partition of another matrix into this one. |
clone(): Matrix | A full duplicate of the values and of the partition. The delimiter option (asBmatrix...) is not kept. |
add(value: AbstractMatrix<Fraction>): Matrix | Add a matrix of the same dimensions, term by term. Throws: {DimensionError} if the dimensions differ. |
aij(i: number, j: number): Fraction | null | Returns element at position (i, j), or null if the index is out of bounds. |
canBeAdded(matrix: AbstractMatrix<Fraction>): boolean | True when both matrices have the same dimensions. |
canBeInverted(): boolean | True when the matrix is square and its determinant is not zero. |
canBeMultiplied(matrix: AbstractMatrix<Fraction>): boolean | True when the number of columns of this matrix equals the number of rows of matrix. |
cofactor(row: number, column: number): Fraction | The cofactor of the entry at row, column: the determinant of the matrix without that row and column, times (-1)^(row+column). |
determinant(): Fraction | Determinant, by cofactor expansion along the first row. Throws: {DimensionError} if the matrix is not square. |
flat(): Fraction[] | All the values in a single array, row by row. |
forEach(callback: (aij: Fraction, row: number, column: number) => void): void | Call callback(value, row, column) for each entry. The entries are the real objects: they can be modified. |
inverse(): Matrix | Inverts this matrix in place. Throws: {MathError} if the matrix is not invertible (singular or non-square) |
isEqual(value: AbstractMatrix<Fraction>): boolean | True when both matrices have the same dimensions and equal entries. |
isOne(): boolean | True for an identity matrix. |
isSquare(): boolean | True when there are as many rows as columns. |
isZero(): boolean | True when every entry is zero. |
isConsistent(): boolean | Returns true if the augmented matrix [A|b] has a consistent system of equations. A row [0…0 | c≠0] after row reduction signals inconsistency. Always returns true when no partition has been set. |
map<U>(callback: (aij: Fraction, row: number, column: number) => U): U[][] | Build an array of rows from callback(value, row, column). |
multiply(value: InputValue<Fraction> | AbstractMatrix<Fraction>): Matrix | Multiply by a scalar (every entry), or by a matrix (this × value, which replaces the content). Throws: {DimensionError} if the dimensions are incompatible for a matrix product. |
one(): Matrix | Set the diagonal to one and every other entry to zero. |
opposite(): Matrix | Change the sign of every entry. |
pow(value: number): Matrix | Raise to a non-negative integer power. The power 0 gives the identity. Throws: {InvalidArgumentError} if value is negative or not an integer.; {DimensionError} if the matrix is not square and the power is 2 or more. |
rank(): number | Returns the rank of this matrix — the number of non-zero rows after reduction to row echelon form. |
reduce(): Matrix | Reduce every entry. |
reducedRowEchelonForm(): Matrix | Returns a new matrix in reduced row echelon form (Gauss-Jordan). Each pivot column has exactly one non-zero entry (value 1). Does not modify the receiver. |
rowEchelonForm(): Matrix | Returns a new matrix in row echelon form (forward Gauss elimination). The matrix is upper-triangular with each pivot normalised to 1. Does not modify the receiver. |
setValue(row: number, column: number, value: InputValue<Fraction>): Matrix | Replace the entry at row, column. Throws: {IndexError} if the position is outside of the matrix. |
subtract(value: AbstractMatrix<Fraction>): Matrix | Subtract a matrix of the same dimensions, term by term. Throws: {DimensionError} if the dimensions differ. |
withDigits(digits: number | null): Matrix | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
transpose(): Matrix | Returns a new matrix that is the transpose of this one. Does not modify the receiver. |
withPartition(col: number): Matrix | Sets the column index that separates the coefficient columns from the augmented column(s) in display and tex output. A | separator is inserted before column col. The partition persists until overwritten. Throws: {IndexError} if col is not strictly between 0 and the column count |
zero(): Matrix | Set every entry to zero. |
PolyMatrix
Constructors
new PolyMatrix()new PolyMatrix(rows: number, cols?: number)new PolyMatrix(value: string)new PolyMatrix(values: InputAlgebra<Polynom>[][])
Static members
| Member | Description |
|---|---|
fromString(value: string): PolyMatrix | Build a matrix from its display string, such as "((x,1),(2,x+1))". |
fromValues(values: InputAlgebra<Polynom>[][]): PolyMatrix | Build a matrix from an array of rows. Throws: {DimensionError} if the rows do not all have the same length. |
fromDimensions(rows: number, cols?: number): PolyMatrix | Build a zero matrix. Without cols, the matrix is square. |
fromVectors(...vectors: Vector[]): PolyMatrix | Build a matrix whose columns are the given vectors. Throws: {DimensionError} if the vectors do not all have the same dimension. |
fromMatrix(m: Matrix): PolyMatrix | Creates a PolyMatrix from a Matrix by converting each Fraction entry to a constant Polynom. |
Properties and getters
| Member | Description |
|---|---|
tex: string | LaTeX output: a pmatrix environment by default, one row per line. With a partition (withPartition), an array with a vertical bar. An empty matrix gives an empty string. |
display: string | Text output such as ((1,2),(3,4)). The outer brackets follow the delimiter option, and a partition adds a |. This is the format read by parse. |
asBmatrix: PolyMatrix | Delimiter option: square brackets. Chainable, persistent. |
asBraceMatrix: PolyMatrix | Delimiter option: braces. Chainable, persistent. |
cols: Polynom[][] | The columns, as an array of arrays (copies of the values). |
dimension: { rows: number; cols: number; } | Number of rows and columns, as {rows, cols}. |
asPmatrix: PolyMatrix | Delimiter option: round brackets (default). Chainable, persistent. |
asVmatrix: PolyMatrix | Delimiter option: single vertical bars, as for a determinant. Chainable, persistent. |
asDoubleVmatrix: PolyMatrix | Delimiter option: double vertical bars. Chainable, persistent. |
rows: Polynom[][] | The rows, as an array of arrays (copies of the values). |
values: Polynom[][] | The entries, as an array of rows (copies of the values). |
Methods
| Member | Description |
|---|---|
characteristic_polynom(variable?: string): Polynom | Computes the characteristic polynomial det(A − λI) of this matrix. Throws: {DimensionError} if the matrix is not square |
parse(value: string | Vector[] | InputAlgebra<Polynom>[][]): PolyMatrix | Replace the content with a display string ("((1,2),(3,4))"), an array of rows, or vectors (one per column). Throws: {DimensionError} if the rows (or the vectors) do not all have the same length. |
copy(value: AbstractMatrix<Polynom>): PolyMatrix | Copy the values and the partition of another matrix into this one. |
clone(): PolyMatrix | A full duplicate of the values and of the partition. The delimiter option (asBmatrix...) is not kept. |
add(value: AbstractMatrix<Polynom>): PolyMatrix | Add a matrix of the same dimensions, term by term. Throws: {DimensionError} if the dimensions differ. |
aij(i: number, j: number): Polynom | null | Returns element at position (i, j), or null if the index is out of bounds. |
canBeAdded(matrix: AbstractMatrix<Polynom>): boolean | True when both matrices have the same dimensions. |
canBeInverted(): boolean | True when the matrix is square and its determinant is not zero. |
canBeMultiplied(matrix: AbstractMatrix<Polynom>): boolean | True when the number of columns of this matrix equals the number of rows of matrix. |
cofactor(row: number, column: number): Polynom | The cofactor of the entry at row, column: the determinant of the matrix without that row and column, times (-1)^(row+column). |
determinant(): Polynom | Determinant, by cofactor expansion along the first row. Throws: {DimensionError} if the matrix is not square. |
flat(): Polynom[] | All the values in a single array, row by row. |
forEach(callback: (aij: Polynom, row: number, column: number) => void): void | Call callback(value, row, column) for each entry. The entries are the real objects: they can be modified. |
inverse(): PolyMatrix | Inverts this matrix in place. Throws: {MathError} if the matrix is not invertible (singular or non-square) |
isEqual(value: AbstractMatrix<Polynom>): boolean | True when both matrices have the same dimensions and equal entries. |
isOne(): boolean | True for an identity matrix. |
isSquare(): boolean | True when there are as many rows as columns. |
isZero(): boolean | True when every entry is zero. |
isConsistent(): boolean | Returns true if the augmented matrix [A|b] has a consistent system of equations. A row [0…0 | c≠0] after row reduction signals inconsistency. Always returns true when no partition has been set. |
map<U>(callback: (aij: Polynom, row: number, column: number) => U): U[][] | Build an array of rows from callback(value, row, column). |
multiply(value: InputValue<Polynom> | AbstractMatrix<Polynom>): PolyMatrix | Multiply by a scalar (every entry), or by a matrix (this × value, which replaces the content). Throws: {DimensionError} if the dimensions are incompatible for a matrix product. |
one(): PolyMatrix | Set the diagonal to one and every other entry to zero. |
opposite(): PolyMatrix | Change the sign of every entry. |
pow(value: number): PolyMatrix | Raise to a non-negative integer power. The power 0 gives the identity. Throws: {InvalidArgumentError} if value is negative or not an integer.; {DimensionError} if the matrix is not square and the power is 2 or more. |
rank(): number | Returns the rank of this matrix — the number of non-zero rows after reduction to row echelon form. |
reduce(): PolyMatrix | Reduce every entry. |
reducedRowEchelonForm(): PolyMatrix | Returns a new matrix in reduced row echelon form (Gauss-Jordan). Each pivot column has exactly one non-zero entry (value 1). Does not modify the receiver. |
rowEchelonForm(): PolyMatrix | Returns a new matrix in row echelon form (forward Gauss elimination). The matrix is upper-triangular with each pivot normalised to 1. Does not modify the receiver. |
setValue(row: number, column: number, value: InputValue<Polynom>): PolyMatrix | Replace the entry at row, column. Throws: {IndexError} if the position is outside of the matrix. |
subtract(value: AbstractMatrix<Polynom>): PolyMatrix | Subtract a matrix of the same dimensions, term by term. Throws: {DimensionError} if the dimensions differ. |
withDigits(digits: number | null): PolyMatrix | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
transpose(): PolyMatrix | Returns a new matrix that is the transpose of this one. Does not modify the receiver. |
withPartition(col: number): PolyMatrix | Sets the column index that separates the coefficient columns from the augmented column(s) in display and tex output. A | separator is inserted before column col. The partition persists until overwritten. Throws: {IndexError} if col is not strictly between 0 and the column count |
zero(): PolyMatrix | Set every entry to zero. |
LinearSystem
Constructors
new LinearSystem(...values: (string \| Equation)[])
Static members
| Member | Description |
|---|---|
solutionAsDisplay(value: Solution[]): string | Text form of a solution of a system: (2;1). |
solutionAsTex(value: Solution[]): string | LaTeX form of a solution of a system: \left( 2 ; 1 \right). |
Properties and getters
| Member | Description |
|---|---|
tex: string | LaTeX rendering of the current state (terminal output, not chainable). |
display: string | ASCIIMath rendering of the current state (terminal output, not chainable). |
equations: Equation[] | The equations, as copies. Setting the property replaces them and updates the variables. |
matrix: [Matrix, Vector] | The system as [A, b]: the matrix of the coefficients and the vector of the constants. |
variables: string[] | The variables of the system, sorted. Setting the property accepts a string of letters or an array. |
Methods
| Member | Description |
|---|---|
parse(...inputs: (string | Equation)[]): LinearSystem | Replace the equations with strings or equations. Throws: {ParseError} if a string has no equation sign. |
fromEquations(...equations: Equation[]): LinearSystem | Replace the equations. The variables are those found in them, in alphabetical order. |
fromComponents(matrix: InputValue<Fraction>[][], variables?: string): LinearSystem | Replace the equations from rows of numbers: the coefficients of the variables, then the constant of the right member. [[1, 1, 3], [1, -1, 1]] is x+y=3 and x-y=1. Throws: {DimensionError} if there is no row, or the rows have different lengths. |
fromMatrix(value: Matrix, variables?: string): LinearSystem | Replace the equations from a matrix, read as in fromComponents. |
fromVectors(...vectors: Vector[]): LinearSystem | Replace the equations from vectors: each vector is a column, the last one holds the constants. |
copy(): LinearSystem | Copy the mathematical state of another instance into this (display state is NOT transferred — the receiver keeps its own formatting). Entry point used when constructing/parsing from a same-type input. Distinct from clone. Classes without a real implementation throw NotImplementedError. |
clone(): LinearSystem | Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy. |
withDigits(digits: number | null): LinearSystem | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
add(value: InputValue<LinearSystem | Equation | Polynom>, index?: number): LinearSystem | Add a system to this one, equation by equation. With an equation, a polynom or a number, add it to the equation at position index. Throws: {DimensionError} if the systems do not have the same number of equations.; {IndexError} if index is missing or out of range. |
buildTex(equations: Equation[], operators?: (string[])[]): string | Builds the LaTeX \left\{...\right. representation from an explicit equation list. Called by tex with the reordered clone. Pass equations directly when generating a step-by-step derivation on a non-standard equation list. |
degree(variable?: string): Fraction | Highest degree of the equations. |
evaluate(): number | Fraction | Not implemented. Throws: {NotImplementedError} always. |
hasVariable(variable: string): boolean | True when the variable appears in the system. |
isEqual(value: LinearSystem): boolean | True when both systems have the same equations, in the same order. |
isSolvable(): boolean | True when the system has exactly one solution: it is consistent and its rank equals the number of variables. |
toAugmentedMatrix(): Matrix | Builds the augmented matrix [A|b] for this system and marks the partition at the variable count, enabling isConsistent() and reducedRowEchelonForm() to interpret the coefficient vs. constant parts. |
mergeEquations(equation1: { id: number; factor: InputValue<Fraction>; }, equation2: { id: number; factor: number; }): Equation | A new equation: the first equation times its factor, plus the second equation times its factor. The system is not modified. |
multiply(value: InputValue<Fraction> | InputValue<Fraction>[], index?: number): LinearSystem | Multiply the equation at position index by a number, or every equation by the matching number of an array. Throws: {DimensionError} if the array does not have one value per equation.; {IndexError} if a single value is given without a valid index. |
reduce(): LinearSystem | Reduce every equation. |
reorder(): LinearSystem | Put the variables on the left and the constant on the right in every equation. |
solve(): Solution[] | Solves the system by Gauss-Jordan elimination on the augmented matrix. - Unique solution: one Solution per variable, in variables order. - No solution: returns []. - Infinite solutions: one Solution per variable with .value === Infinity. |
solve_compute_factors(variable: string): [{ id: number; factor: number; }, { id: number; factor: number; }][] | For each pair of equations (i, j), computes LCM-based multipliers that eliminate variable by linear combination. The factors satisfy f_i·coeff_i + f_j·coeff_j = 0. Pairs are sorted by |f_i| + |f_j| (smallest multipliers first). Requires that all variable terms are on the left side of each equation. |
subtract(value: InputValue<LinearSystem | Equation | Polynom>, index?: number): LinearSystem | Subtract a system from this one, equation by equation. With an equation, a polynom or a number, subtract it from the equation at position index. Throws: {DimensionError} if the systems do not have the same number of equations.; {IndexError} if index is missing or out of range. |