matrices.md (14143B)
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 Note that the dimensions themselves do not have a meaning attached. 188 When creating and printing a two dimensional matrix, the first dimension is 189 normally rendered as the _column_, and the second dimension is rendered as 190 the _row_. For example: 191 192 ```js 193 console.table(math.zeros([2, 4])) 194 // 0 0 0 0 195 // 0 0 0 0 196 ``` 197 198 If you have a matrix where the first dimension means `x` and the second 199 means `y`, this will look confusing since `x` is printed as _column_ 200 (vertically) and `y` as _row_ (horizontally). 201 202 203 ## Resizing 204 205 Matrices can be resized using their `resize` function. This function is called 206 with an Array with the new size as the first argument, and accepts an optional 207 default value. By default, new entries will be set to `0`, but it is possible 208 to pass a different default value like `null` to clearly indicate that 209 the entries haven't been explicitly set. 210 211 ```js 212 const a = math.matrix() // Matrix, size [0], [] 213 a.resize([2, 3]) // Matrix, size [2, 3], [[0, 0, 0], [0, 0, 0]] 214 a.resize([2, 2, 2]) // Matrix, size [2, 2, 2], 215 // [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] 216 217 const b = math.matrix() 218 b.resize([3], 7) // Matrix, size [3], [7, 7, 7] 219 b.resize([5], 9) // Matrix, size [5], [7, 7, 7, 9, 9] 220 b.resize([2]) // Matrix, size [2], [7, 7] 221 ``` 222 223 224 Outer dimensions of a matrix can be squeezed using the function `squeeze`. When 225 getting or setting a subset in a matrix, the subset is automatically squeezed 226 or unsqueezed. 227 228 ```js 229 // squeeze a matrix 230 const a = [[[0, 1, 2]]] 231 math.squeeze(a) // [0, 1, 2] 232 math.squeeze([[3]]) // 3 233 234 // subsets are automatically squeezed 235 const b = math.matrix([[0, 1], [2, 3]]) 236 b.subset(math.index(1, 0)) // 2 237 ``` 238 239 240 ## Getting or replacing subsets 241 242 Subsets of a matrix can be retrieved or replaced using the function `subset`. 243 Matrices have a `subset` function, which is applied to the matrix itself: 244 `Matrix.subset(index [, replacement])`. For both matrices and arrays, 245 the static function `subset(matrix, index [, replacement])` can be used. 246 When parameter `replacement` is provided, the function will replace a subset 247 in the matrix, and if not, a subset of the matrix will be returned. 248 249 A subset can be defined using an `Index`. An `Index` contains a single value 250 or a set of values for each dimension of a matrix. An `Index` can be 251 created using the function `index`. 252 Matrix indexes in math.js are zero-based, like most programming languages 253 including JavaScript itself. 254 255 Note that mathematical applications like Matlab and Octave work differently, 256 as they use one-based indexes. 257 258 ```js 259 // create some matrices 260 const a = [0, 1, 2, 3] 261 const b = [[0, 1], [2, 3]] 262 const c = math.zeros(2, 2) 263 const d = math.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) 264 const e = math.matrix() 265 266 // get a subset 267 math.subset(a, math.index(1)) // 1 268 math.subset(a, math.index([2, 3])) // Array, [2, 3] 269 math.subset(a, math.index(math.range(0,4))) // Array, [0, 1, 2, 3] 270 math.subset(b, math.index(1, 0)) // 2 271 math.subset(b, math.index(1, [0, 1])) // Array, [2, 3] 272 math.subset(b, math.index([0, 1], 0)) // Matrix, [[0], [2]] 273 274 // get a subset 275 d.subset(math.index([1, 2], [0, 1])) // Matrix, [[3, 4], [6, 7]] 276 d.subset(math.index(1, 2)) // 5 277 278 // replace a subset. The subset will be applied to a clone of the matrix 279 math.subset(b, math.index(1, 0), 9) // Array, [[0, 1], [9, 3]] 280 math.subset(b, math.index(2, [0, 1]), [4, 5]) // Array, [[0, 1], [2, 3], [4, 5]] 281 282 // replace a subset. The subset will be applied to the matrix itself 283 c.subset(math.index(0, 1),1) // Matrix, [[0, 1], [0, 0]] 284 c.subset(math.index(1, [0, 1]), [2, 3]) // Matrix, [[0, 1], [2, 3]] 285 e.resize([2, 3], 0) // Matrix, [[0, 0, 0], [0, 0, 0]] 286 e.subset(math.index(1, 2), 5) // Matrix, [[0, 0, 0], [0, 0, 5]] 287 ``` 288 289 ## Iterating 290 291 Matrices contain functions `map` and `forEach` to iterate over all elements of 292 the (multidimensional) matrix. The callback function of `map` and `forEach` has 293 three parameters: `value` (the value of the currently iterated element), 294 `index` (an array with the index value for each dimension), and `matrix` (the 295 matrix being iterated). This syntax is similar to the `map` and `forEach` 296 functions of native JavaScript Arrays, except that the index is no number but 297 an Array with numbers for each dimension. 298 299 ```js 300 const a = math.matrix([[0, 1], [2, 3], [4, 5]]) 301 302 // The iteration below will output the following in the console: 303 // value: 0 index: [0, 0] 304 // value: 1 index: [0, 1] 305 // value: 2 index: [1, 0] 306 // value: 3 index: [1, 1] 307 // value: 4 index: [2, 0] 308 // value: 5 index: [2, 1] 309 a.forEach(function (value, index, matrix) { 310 console.log('value:', value, 'index:', index) 311 }) 312 313 // Apply a transformation on the matrix 314 const b = a.map(function (value, index, matrix) { 315 return math.multiply(math.sin(value), math.exp(math.abs(value))) 316 }) 317 console.log(b.format(5)) // [[0, 2.2874], [6.7188, 2.8345], [-41.32, -142.32]] 318 319 // Create a matrix with the cumulative of all elements 320 let count = 0 321 const cum = a.map(function (value, index, matrix) { 322 count += value 323 return count 324 }) 325 console.log(cum.toString()) // [[0, 1], [3, 6], [10, 15]] 326 ``` 327 328 ## Storage types 329 330 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. 331 332 Math.js supports two type of matrices: 333 334 - Dense matrix (`'dense'`, `default`) A regular, dense matrix, supporting multi-dimensional matrices. This is the default matrix type. 335 - Sparse matrix (`'sparse'`): A two dimensional sparse matrix implementation. 336 337 The type of matrix can be selected when creating a matrix using the construction functions `matrix`, `diag`, `identity`, `ones`, and `zeros`. 338 339 ```js 340 // create sparse matrices 341 const m1 = math.matrix([[0, 1], [0, 0]], 'sparse') 342 const m2 = math.identity(1000, 1000, 'sparse') 343 ``` 344 345 ## API 346 347 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: 348 349 - Functions like `math.matrix` and `math.sparse`, `math.ones`, `math.zeros`, and `math.identity` to create a matrix. 350 - Functions like `math.subset` and `math.index` to get or replace a part of a matrix 351 - Functions like `math.transpose` and `math.diag` to manipulate matrices. 352 353 A full list of matrix functions is available on the [functions reference page](../reference/functions.md#matrix-functions). 354 355 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. 356 357 - [DenseMatrix](../reference/classes/densematrix.md) 358 - [SparseMatrix](../reference/classes/sparsematrix.md)