1 | # Matrices
|
2 |
|
3 | Math.js supports multi dimensional matrices and arrays. Matrices can be
|
4 | created, manipulated, and used in calculations. Both regular JavaScript
|
5 | arrays as well as the matrix type implemented by math.js can be used
|
6 | interchangeably in all relevant math.js functions. math.js supports both
|
7 | dense and sparse matrices.
|
8 |
|
9 |
|
10 | ## Arrays and matrices
|
11 |
|
12 | Math.js supports two types of matrices:
|
13 |
|
14 | - `Array`, a regular JavaScript array. A multi dimensional array can be created
|
15 | by nesting arrays.
|
16 | - `Matrix`, a matrix implementation by math.js. A `Matrix` is an object wrapped
|
17 | around a regular JavaScript `Array`, providing utility functions for easy
|
18 | matrix manipulation such as `subset`, `size`, `resize`, `clone`, and more.
|
19 |
|
20 | In most cases, the type of matrix output from functions is determined by the
|
21 | function input: An `Array` as input will return an `Array`, a `Matrix` as input
|
22 | will return a `Matrix`. In case of mixed input, a `Matrix` is returned.
|
23 | For functions where the type of output cannot be determined from the
|
24 | input, the output is determined by the configuration option `matrix`,
|
25 | which can be a string `'Matrix'` (default) or `'Array'`.
|
26 |
|
27 | ```js
|
28 | // create an array and a matrix
|
29 | const array = [[2, 0], [-1, 3]] // Array
|
30 | const matrix = math.matrix([[7, 1], [-2, 3]]) // Matrix
|
31 |
|
32 | // perform a calculation on an array and matrix
|
33 | math.square(array) // Array, [[4, 0], [1, 9]]
|
34 | math.square(matrix) // Matrix, [[49, 1], [4, 9]]
|
35 |
|
36 | // perform calculations with mixed array and matrix input
|
37 | math.add(array, matrix) // Matrix, [[9, 1], [-3, 6]]
|
38 | math.multiply(array, matrix) // Matrix, [[14, 2], [-13, 8]]
|
39 |
|
40 | // create a matrix. Type of output of function ones is determined by the
|
41 | // configuration option `matrix`
|
42 | math.ones(2, 3) // Matrix, [[1, 1, 1], [1, 1, 1]]
|
43 | ```
|
44 |
|
45 |
|
46 | ## Creation
|
47 |
|
48 | A matrix can be created from an array using the function `math.matrix`. The
|
49 | provided array can contain nested arrays in order to create a multi-dimensional matrix. When called without arguments, an empty matrix will be
|
50 | created.
|
51 |
|
52 | ```js
|
53 | // create matrices
|
54 | math.matrix() // Matrix, size [0]
|
55 | math.matrix([0, 1, 2]) // Matrix, size [3]
|
56 | math.matrix([[0, 1], [2, 3], [4, 5]]) // Matrix, size [3, 2]
|
57 | ```
|
58 |
|
59 | Math.js supports regular Arrays. Multiple dimensions can be created
|
60 | by nesting Arrays in each other.
|
61 |
|
62 | ```js
|
63 | // create arrays
|
64 | [] // Array, size [0]
|
65 | [0, 1, 2] // Array, size [3]
|
66 | [[0, 1], [2, 3], [4, 5]] // Array, size [3, 2]
|
67 | ```
|
68 |
|
69 | Matrices can contain different types of values: numbers, complex numbers,
|
70 | units, or strings. Different types can be mixed together in a single matrix.
|
71 |
|
72 | ```js
|
73 | // create a matrix with mixed types
|
74 | const a = math.matrix([2.3, 'hello', math.complex(3, -4), math.unit('5.2 mm')])
|
75 | a.subset(math.index(1)) // 'hello'
|
76 | ```
|
77 |
|
78 |
|
79 | There are a number of functions to create a matrix with a specific size and
|
80 | content: `ones`, `zeros`, `identity`.
|
81 |
|
82 | ```js
|
83 | // zeros creates a matrix filled with zeros
|
84 | math.zeros(3) // Matrix, size [3], [0, 0, 0]
|
85 | math.zeros(3, 2) // Matrix, size [3, 2], [[0, 0], [0, 0], [0, 0]]
|
86 | math.zeros(2, 2, 2) // Matrix, size [2, 2, 2],
|
87 | // [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
|
88 |
|
89 | // ones creates a matrix filled with ones
|
90 | math.ones(3) // Matrix, size [3], [1, 1, 1]
|
91 | math.multiply(math.ones(2, 2), 5) // Matrix, size [2, 2], [[5, 5], [5, 5]]
|
92 |
|
93 | // identity creates an identity matrix
|
94 | math.identity(3) // Matrix, size [3, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
95 | math.identity(2, 3) // Matrix, size [2, 3], [[1, 0, 0], [0, 1, 0]]
|
96 | ```
|
97 |
|
98 |
|
99 | The functions `ones`, `zeros`, and `identity` also accept a single array
|
100 | or matrix containing the dimensions for the matrix. When the input is an Array,
|
101 | the functions will output an Array. When the input is a Matrix, the output will
|
102 | be a Matrix. Note that in case of numbers as arguments, the output is
|
103 | determined by the option `matrix` as discussed in section
|
104 | [Arrays and matrices](#arrays-and-matrices).
|
105 |
|
106 | ```js
|
107 | // Array as input gives Array as output
|
108 | math.ones([2, 3]) // Array, size [3, 2], [[1, 1, 1], [1, 1, 1]]
|
109 | math.ones(math.matrix([2, 3])) // Matrix, size [3, 2], [[1, 1, 1], [1, 1, 1]]
|
110 | ```
|
111 |
|
112 | Ranges can be created using the function `range`. The function `range` is
|
113 | called with parameters start and end, and optionally a parameter step.
|
114 | The start of the range is included, the end of the range is excluded.
|
115 |
|
116 | ```js
|
117 | math.range(0, 4) // [0, 1, 2, 3]
|
118 | math.range(0, 8, 2) // [0, 2, 4, 6]
|
119 | math.range(3, -1, -1) // [3, 2, 1, 0]
|
120 | ```
|
121 |
|
122 |
|
123 | ## Calculations
|
124 |
|
125 | All relevant functions of math.js support matrices and arrays.
|
126 |
|
127 | ```js
|
128 | // perform a calculation on a matrix
|
129 | const a = math.matrix([1, 4, 9, 16, 25]) // Matrix, [1, 4, 9, 16, 25]
|
130 | math.sqrt(a) // Matrix, [1, 2, 3, 4, 5]
|
131 |
|
132 | // perform a calculation on an array
|
133 | const b = [1, 2, 3, 4, 5]
|
134 | math.factorial(b) // Array, [1, 2, 6, 24, 120]
|
135 |
|
136 | // multiply an array with a matrix
|
137 | const c = [[2, 0], [-1, 3]] // Array
|
138 | const d = math.matrix([[7, 1], [-2, 3]]) // Matrix
|
139 | math.multiply(c, d) // Matrix, [[14, 2], [-13, 8]]
|
140 |
|
141 | // add a number to a matrix
|
142 | math.add(c, 2) // Array, [[4, 2], [1, 5]]
|
143 |
|
144 | // calculate the determinant of a matrix
|
145 | math.det(c) // 6
|
146 | math.det(d) // 23
|
147 | ```
|
148 |
|
149 |
|
150 | ## Size and Dimensions
|
151 |
|
152 | Math.js uses geometric dimensions:
|
153 |
|
154 | - A scalar is zero-dimensional.
|
155 | - A vector is one-dimensional.
|
156 | - A matrix is two or multi-dimensional.
|
157 |
|
158 | The size of a matrix can be calculated with the function `size`. Function `size`
|
159 | returns a `Matrix` or `Array`, depending on the configuration option `matrix`.
|
160 | Furthermore, matrices have a function `size` as well, which always returns
|
161 | an Array.
|
162 |
|
163 | ```js
|
164 | // get the size of a scalar
|
165 | math.size(2.4) // Matrix, []
|
166 | math.size(math.complex(3, 2)) // Matrix, []
|
167 | math.size(math.unit('5.3 mm')) // Matrix, []
|
168 |
|
169 | // get the size of a one-dimensional matrix (a vector) and a string
|
170 | math.size([0, 1, 2, 3]) // Array, [4]
|
171 | math.size('hello world') // Matrix, [11]
|
172 |
|
173 | // get the size of a two-dimensional matrix
|
174 | const a = [[0, 1, 2, 3]] // Array
|
175 | const b = math.matrix([[0, 1, 2], [3, 4, 5]]) // Matrix
|
176 | math.size(a) // Array, [1, 4]
|
177 | math.size(b) // Matrix, [2, 3]
|
178 |
|
179 | // matrices have a function size (always returns an Array)
|
180 | b.size() // Array, [2, 3]
|
181 |
|
182 | // get the size of a multi-dimensional matrix
|
183 | const c = [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]
|
184 | math.size(c) // Array, [2, 2, 3]
|
185 | ```
|
186 |
|
187 |
|
188 | ## Resizing
|
189 |
|
190 | Matrices can be resized using their `resize` function. This function is called
|
191 | with an Array with the new size as the first argument, and accepts an optional
|
192 | default value. By default, new entries will be set to `0`, but it is possible
|
193 | to pass a different default value like `null` to clearly indicate that
|
194 | the entries haven't been explicitly set.
|
195 |
|
196 | ```js
|
197 | const a = math.matrix() // Matrix, size [0], []
|
198 | a.resize([2, 3]) // Matrix, size [2, 3], [[0, 0, 0], [0, 0, 0]]
|
199 | a.resize([2, 2, 2]) // Matrix, size [2, 2, 2],
|
200 | // [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
|
201 |
|
202 | const b = math.matrix()
|
203 | b.resize([3], 7) // Matrix, size [3], [7, 7, 7]
|
204 | b.resize([5], 9) // Matrix, size [5], [7, 7, 7, 9, 9]
|
205 | b.resize([2]) // Matrix, size [2], [7, 7]
|
206 | ```
|
207 |
|
208 |
|
209 | Outer dimensions of a matrix can be squeezed using the function `squeeze`. When
|
210 | getting or setting a subset in a matrix, the subset is automatically squeezed
|
211 | or unsqueezed.
|
212 |
|
213 | ```js
|
214 | // squeeze a matrix
|
215 | const a = [[[0, 1, 2]]]
|
216 | math.squeeze(a) // [0, 1, 2]
|
217 | math.squeeze([[3]]) // 3
|
218 |
|
219 | // subsets are automatically squeezed
|
220 | const b = math.matrix([[0, 1], [2, 3]])
|
221 | b.subset(math.index(1, 0)) // 2
|
222 | ```
|
223 |
|
224 |
|
225 | ## Getting or replacing subsets
|
226 |
|
227 | Subsets of a matrix can be retrieved or replaced using the function `subset`.
|
228 | Matrices have a `subset` function, which is applied to the matrix itself:
|
229 | `Matrix.subset(index [, replacement])`. For both matrices and arrays,
|
230 | the static function `subset(matrix, index [, replacement])` can be used.
|
231 | When parameter `replacement` is provided, the function will replace a subset
|
232 | in the matrix, and if not, a subset of the matrix will be returned.
|
233 |
|
234 | A subset can be defined using an `Index`. An `Index` contains a single value
|
235 | or a set of values for each dimension of a matrix. An `Index` can be
|
236 | created using the function `index`.
|
237 | Matrix indexes in math.js are zero-based, like most programming languages
|
238 | including JavaScript itself.
|
239 |
|
240 | Note that mathematical applications like Matlab and Octave work differently,
|
241 | as they use one-based indexes.
|
242 |
|
243 | ```js
|
244 | // create some matrices
|
245 | const a = [0, 1, 2, 3]
|
246 | const b = [[0, 1], [2, 3]]
|
247 | const c = math.zeros(2, 2)
|
248 | const d = math.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
|
249 | const e = math.matrix()
|
250 |
|
251 | // get a subset
|
252 | math.subset(a, math.index(1)) // 1
|
253 | math.subset(a, math.index([2, 3])) // Array, [2, 3]
|
254 | math.subset(a, math.index(math.range(0,4))) // Array, [0, 1, 2, 3]
|
255 | math.subset(b, math.index(1, 0)) // 2
|
256 | math.subset(b, math.index(1, [0, 1])) // Array, [2, 3]
|
257 | math.subset(b, math.index([0, 1], 0)) // Matrix, [[0], [2]]
|
258 |
|
259 | // get a subset
|
260 | d.subset(math.index([1, 2], [0, 1])) // Matrix, [[3, 4], [6, 7]]
|
261 | d.subset(math.index(1, 2)) // 5
|
262 |
|
263 | // replace a subset. The subset will be applied to a clone of the matrix
|
264 | math.subset(b, math.index(1, 0), 9) // Array, [[0, 1], [9, 3]]
|
265 | math.subset(b, math.index(2, [0, 1]), [4, 5]) // Array, [[0, 1], [2, 3], [4, 5]]
|
266 |
|
267 | // replace a subset. The subset will be applied to the matrix itself
|
268 | c.subset(math.index(0, 1),1) // Matrix, [[0, 1], [0, 0]]
|
269 | c.subset(math.index(1, [0, 1]), [2, 3]) // Matrix, [[0, 1], [2, 3]]
|
270 | e.resize([2, 3], 0) // Matrix, [[0, 0, 0], [0, 0, 0]]
|
271 | e.subset(math.index(1, 2), 5) // Matrix, [[0, 0, 0], [0, 0, 5]]
|
272 | ```
|
273 |
|
274 | ## Iterating
|
275 |
|
276 | Matrices contain functions `map` and `forEach` to iterate over all elements of
|
277 | the (multidimensional) matrix. The callback function of `map` and `forEach` has
|
278 | three parameters: `value` (the value of the currently iterated element),
|
279 | `index` (an array with the index value for each dimension), and `matrix` (the
|
280 | matrix being iterated). This syntax is similar to the `map` and `forEach`
|
281 | functions of native JavaScript Arrays, except that the index is no number but
|
282 | an Array with numbers for each dimension.
|
283 |
|
284 | ```js
|
285 | const a = math.matrix([[0, 1], [2, 3], [4, 5]])
|
286 |
|
287 | // The iteration below will output the following in the console:
|
288 | // value: 0 index: [0, 0]
|
289 | // value: 1 index: [0, 1]
|
290 | // value: 2 index: [1, 0]
|
291 | // value: 3 index: [1, 1]
|
292 | // value: 4 index: [2, 0]
|
293 | // value: 5 index: [2, 1]
|
294 | a.forEach(function (value, index, matrix) {
|
295 | console.log('value:', value, 'index:', index)
|
296 | })
|
297 |
|
298 | // Apply a transformation on the matrix
|
299 | const b = a.map(function (value, index, matrix) {
|
300 | return math.multiply(math.sin(value), math.exp(math.abs(value)))
|
301 | })
|
302 | console.log(b.format(5)) // [[0, 2.2874], [6.7188, 2.8345], [-41.32, -142.32]]
|
303 |
|
304 | // Create a matrix with the cumulative of all elements
|
305 | let count = 0
|
306 | const cum = a.map(function (value, index, matrix) {
|
307 | count += value
|
308 | return count
|
309 | })
|
310 | console.log(cum.toString()) // [[0, 1], [3, 6], [10, 15]]
|
311 | ```
|
312 |
|
313 | ## Storage types
|
314 |
|
315 | Math.js supports both dense matrices as well as sparse matrices. Sparse matrices are efficient for matrices largely containing zeros. In that case they save a lot of memory, and calculations can be much faster than for dense matrices.
|
316 |
|
317 | Math.js supports two type of matrices:
|
318 |
|
319 | - Dense matrix (`'dense'`, `default`) A regular, dense matrix, supporting multi-dimensional matrices. This is the default matrix type.
|
320 | - Sparse matrix (`'sparse'`): A two dimensional sparse matrix implementation.
|
321 |
|
322 | The type of matrix can be selected when creating a matrix using the construction functions `matrix`, `diag`, `identity`, `ones`, and `zeros`.
|
323 |
|
324 | ```js
|
325 | // create sparse matrices
|
326 | const m1 = math.matrix([[0, 1], [0, 0]], 'sparse')
|
327 | const m2 = math.identity(1000, 1000, 'sparse')
|
328 | ```
|
329 |
|
330 | ## API
|
331 |
|
332 | All relevant functions in math.js support Matrices and Arrays. Functions like `math.add` and `math.subtract`, `math.sqrt` handle matrices element wise. There is a set of functions specifically for creating or manipulating matrices, such as:
|
333 |
|
334 | - Functions like `math.matrix` and `math.sparse`, `math.ones`, `math.zeros`, and `math.identity` to create a matrix.
|
335 | - Functions like `math.subset` and `math.index` to get or replace a part of a matrix
|
336 | - Functions like `math.transpose` and `math.diag` to manipulate matrices.
|
337 |
|
338 | A full list of matrix functions is available on the [functions reference page](../reference/functions.md#matrix-functions).
|
339 |
|
340 | Two types of matrix classes are available in math.js, for storage of dense and sparse matrices. Although they contain public functions documented as follows, using the following API directly is *not* recommended. Prefer using the functions in the "math" namespace wherever possible.
|
341 |
|
342 | - [DenseMatrix](../reference/classes/densematrix.md)
|
343 | - [SparseMatrix](../reference/classes/sparsematrix.md)
|