Q ⟩ Matrix

Source code: Q-Matrix.js


Grid of numbers

A matrix is just a grid of numbers; rows and columns containing values. Matrices can be of any size. Here’s an example of a 3 × 2 matrix. It is 3 columns wide and 2 rows tall, containing the values 1 through 6.



When describing the dimensions of a matrix we always specify the number of rows first, then the number of columns. The above is an example of a 3 × 2 matrix, while below is a matrix containing similar data, but in a 2 × 3 configuration.

12
34
56

Order matters

Q thinks about matrices in row-major order. This means we read the values just as they are ordered above, starting with the top-most row, reading values from left to right, then proceeding to the next row down and repeating that process. Our choice of row-major order makes reading and writing matrix values more akin to reading and writing in English; easier to type and program here.


Vectors are slices

While a matrix is a two-dimensional grid of numbers, a vector is more like a slice of numbers—such as a “skinny” matrix that is only one column wide, or a “flat” matrix that is only one row high. Let’s look at some examples of matrices that are simultaneously vectors.


1234
Any “flat” matrix is
a row vector.
1
2
3
4
Any “skinny” matrix is
a column vector.
12
34
But matrices with
more than one column
or more than one row
are not vectors.

While the above 2 × 2 matrix is not a vector, you could say that it contains vectors: Two column vectors or two row vectors.

Because vectors are just a type of matrix we can add them, multiply them, and so on—just like any other matrix. Vectors will play a prominent role in defining qubits and expressing the state of a quantum circuit.

Complex numbers

Instead of just storing regular old numbers, our matrices are geared to store complex numbers. (This is because qubits are really just a pair of complex numbers that we store in a 1 × 2 matrix. So, yes—the example matrices above are actually all larger than qubits are!) In general, we don’t even have to think about the fact that our matrices are storing complex numbers because Q.Matrix is happy to accept regular JavaScript Number values as input—and Q.ComplexNumber will silently handle the conversion for us.


Constructor

Matrix Function([ size: Number ] or [ width: Number, height: Number ] or [ rows: arguments ]) => Q.Matrix
The Matrix class creates and operates on matrices of arbitrary dimensions. This is in contrast to some popular graphics libraries which optimize for specific sizes of matrices—with corresponding class names like Matrix3 (for 3 × 3 matrices) or Matrix4 (for 4 × 4 matrices). Q, meanwhile, is much more flexible. The constructor expects an argument list of equal-length arrays where each array represents a row of column values. Matrix then automatically determines the dimensions based on the number of arguments (rows) and length of each row (number of columns). The constructor will throw an error if the row lengths are not equal.

Upon creation Matrix converts all argument values of type Number to Q.ComplexNumber instances. Currently Matrix does not support recursion; a matrix cannot contain matrices as values. A matrix also cannot change its dimensions, making destructive properties that yield matrices of a different size (like multiply$, for example) impossible.


var a = new Q.Matrix(  
	[ 1, 2, 3 ],  
	[ 4, 5, 6 ])
123
456
  • rows
    Array The list of supplied arguments.
  • columns
    Array The list of getters and setters that operate on the rows property to appear as if this property contained actual values.
  • index
    Number An identification number assigned to the instance, used for minding the total number of instances created.

Import and export formats

Getting data in and out of any system can be laborious. With that in mind, Q.Matrix comes with helper methods for importing and exporting the following common formats:


Static properties

  • help
    Function ⇒ String Calls and returns the value of Q.help, passing Q.Matrix as the argument.
  • index
    Number The number of instances created so far.

Constants and constant creation

  • constants
    Object Constants are appended directly to the Q.Matrix object. For convenience they are also appended to this Q.Matrix.constants object to make looking up constants in the JavaScript console trivial, and to make iterating across all constants convenient via functions like Object.entries, Object.keys, Object.values, and so on. The intention that a property act as a constant is signaled by its labelling in all-uppercase.
  • createConstant
    Function( key: String, value: * ) Appends a property named by key with a value of value to both the Matrix object and its constants property.
  • createConstants
    Function( … ) Expects an even number of arguments. Will use each pair in the sequence of arguments to call createConstant.

Constants — Example matrices

  • IDENTITY_2X2
    Q.Matrix Initialized as Q.Matrix.createIdentity( 2 ). Described by the following matrix:
    10
    01
  • IDENTITY_3X3
    Q.Matrix Initialized as Q.Matrix.createIdentity( 3 ). Described by the following matrix:
    100
    010
    001
  • IDENTITY_4X4
    Q.Matrix Initialized as Q.Matrix.createIdentity( 4 ). Described by the following matrix:
    1000
    0100
    0010
    0001
  • CONSTANT0_2X2
    Q.Matrix Initialized as
    
    new Q.Matrix(
    	[ 1, 1 ],
    	[ 0, 0 ])
    
    Described by the following matrix:
    11
    00
  • CONSTANT1_2X2
    Q.Matrix Initialized as
    
    new Q.Matrix(
    	[ 0, 0 ],
    	[ 1, 1 ])
    
    Described by the following matrix:
    00
    11
  • NEGATION_2X2
    Q.Matrix Initialized as
    
    new Q.Matrix(
    	[ 0, 1 ],
    	[ 1, 0 ])
    
    Described by the following matrix:
    01
    10
  • TEST_MAP_9X9
    Q.Matrix Initialized as
    
    new Q.Matrix(
    	[ 11, 21, 31, 41, 51, 61, 71, 81, 91 ],
    	[ 12, 22, 32, 42, 52, 62, 72, 82, 92 ],
    	[ 13, 23, 33, 43, 53, 63, 73, 83, 93 ],
    	[ 14, 24, 34, 44, 54, 64, 74, 84, 94 ],
    	[ 15, 25, 35, 45, 55, 65, 75, 85, 95 ],
    	[ 16, 26, 36, 46, 56, 66, 76, 86, 96 ],
    	[ 17, 27, 37, 47, 57, 67, 77, 87, 97 ],
    	[ 18, 28, 38, 48, 58, 68, 78, 88, 98 ],
    	[ 19, 29, 39, 49, 59, 69, 79, 89, 99 ])
    
    Described by the following matrix:
    11 21 31 41 51 61 71 81 91
    12 22 32 42 52 62 72 82 92
    13 23 33 43 53 63 73 83 93
    14 24 34 44 54 64 74 84 94
    15 25 35 45 55 65 75 85 95
    16 26 36 46 56 66 76 86 96
    17 27 37 47 57 67 77 87 97
    18 28 38 48 58 68 78 88 98
    19 29 39 49 59 69 79 89 99

Static inspection

  • isMatrixLike
    Function( object: * ) ⇒ Boolean Returns true if object is an instance of Q.Matrix or if Q.Matrix is in object’s prototype chain, otherwise returns false.
  • getWidth
    Function( m: Q.Matrix ) ⇒ Number Returns the number of columns in this matrix.
  • getHeight
    Function( m: Q.Matrix ) ⇒ Number Returns the number of rows in this matrix.
  • haveEqualDimensions
    Function( a: Q.Matrix, b: Q.Matrix ) ⇒ Boolean Returns true if both matrices have the same number of rows and the same number of columns, otherwise returns false.
  • isWithinRange
    Function( n: Number, minimum: Number, maximum: Number ) ⇒ Boolean Returns true if n is an integer, and is greater than or equal to minimum, and is less than or equal to maximum, otherwise returns false. Used to determine if a value is a valid row or column number.

Creation from description

  • createSquare
    Function([ size: Number = 2[, f: Function = function(){ return 0 }]]) ⇒ Q.Matrix Creates a square matrix of width and height equal to size. f is invoked for each cell of the matrix and is passed two arguments, x: Number and y: Number, which correspond to the address of the cell. The result of f is then assigned to that cell. Returns the resulting matrix.
  • createZero
    Function( size: Number ) ⇒ Q.Matrix Calls createSquare with the passed size argument, but no function argument, to yield a matrix of all zeros. Returns the resulting matrix.
  • createOne
    Function( size: Number ) ⇒ Q.Matrix Calls createSquare with the passed size argument, and an f argument that invariably returns 1, to yield a matrix of all ones. Returns the resulting matrix.
  • createIdentity
    Function( size: Number ) ⇒ Q.Matrix Calls createSquare with the passed size argument, and an f argument that yields an identity matrix. Returns the resulting matrix.

Creation from data import

  • fromArray
    Function( array: Array ) ⇒ Q.Matrix Ingests matrix data from an Array of values where each element represents a row that is itself an Array of values, and returns the result. Note how this differs from the Matrix constructor which uses the function’s Array-like arguments list directly.
  • fromXsv
    Function( input: String, rowSeparator: String, valueSeparator: String ) ⇒ Q.Matrix Ingests matrix data from a String of values that are sepearated in to rows by rowSeparator and separated in to values (columns) by valueSeparator, and returns the result.
  • fromCsv
    Function( csv: String ) ⇒ Q.Matrix Ingests matrix data from a String of comma-separated-values and returns the result.
  • fromTsv
    Function( tsv: String ) ⇒ Q.Matrix Ingests matrix data from a String of tab-separated-values and returns the result.
  • fromHtml
    Function( html: String ) ⇒ Q.Matrix Ingests matrix data from a String of HTML table code and returns the result.

Static maths

  • add
    Function( a: Q.Matrix, b: Q.Matrix ) ⇒ Q.Matrix Adds the two supplied matrices together and returns the result.
  • multiplyScalar
    Function( a: Q.Matrix, b: Number ) ⇒ Q.Matrix Multiplies the supplied matrix by the supplied scalar and returns the result.
  • multiply
    Function( a: Q.Matrix, b: Q.Matrix ) ⇒ Q.Matrix Multiplies the two supplied matrices together and returns the result.
  • multiplyTensor
    Function( a: Q.Matrix, b: Q.Matrix ) ⇒ Q.Matrix Returns the tensor product of the two supplied matrices.

Prototype properties

Self inspection

  • isValidRow
    Function( rowIndex: Number ) ⇒ Boolean Returns true if rowIndex is greater than or equal to zero and is less than the height of this matrix, otherwise returns false. Will return a Boolean value, thereby halting “Fluent interface” method chaining for this instance.
  • isValidColumn
    Function( columnIndex: Number ) ⇒ Boolean Returns true if columnIndex is greater than or equal to zero and is less than the width of this matrix, otherwise returns false. Will return a Boolean value, thereby halting “Fluent interface” method chaining for this instance.
  • isValidAddress
    Function( x: Number, y: Number ) ⇒ Boolean Returns true if x is a valid row index and y is a valid column index, otherwise returns false. Will return a Boolean value, thereby halting “Fluent interface” method chaining for this instance.
  • getWidth
    Function ⇒ Number Calls and returns the value of Q.Matrix.getWidth, passing itself as the argument. Will return a Number value, thereby halting “Fluent interface” method chaining for this instance.
  • getHeight
    Function ⇒ Number Calls and returns the value of Q.Matrix.getHeight, passing itself as the argument. Will return a Number value, thereby halting “Fluent interface” method chaining for this instance.

Data export (non-destructive)

  • read
    Function( x: Number, y: Number ) ⇒ Q.ComplexNumber Returns the value of this matrix’s cell at row y and column x. Equivalent to this.columns[ x ][ y ] or this.rows[ y ][ x ] but with safety mechanisms. Will return a Number value, thereby halting “Fluent interface” method chaining for this instance.
  • clone
    Function ⇒ Q.Matrix Returns a new instance with the value for rows copied from this instance. The constructor will populate the values for columns as well.
  • toArray
    Function ⇒ Array Returns the value of this instance’s rows property. Will return an Array value, thereby halting “Fluent interface” method chaining for this instance.
  • toXsv
    Function( rowSeparator: String, valueSeparator: String ) ⇒ String Returns the value of this matrix expressed as a String delimited by the supplied arguments. Will return a String value, thereby halting “Fluent interface” method chaining for this instance.
  • toCsv
    Function ⇒ String Creates a comma-separated-values table and returns it as a String. Will return a String value, thereby halting “Fluent interface” method chaining for this instance.
  • toTsv
    Function ⇒ String Creates a tab-separated-values table and returns it as a String. Will return a String value, thereby halting “Fluent interface” method chaining for this instance.
  • toHtml
    Function ⇒ String Creates HTML table code and returns it as a String. Will return a String value, thereby halting “Fluent interface” method chaining for this instance.
  • toDom
    Function ⇒ DocumentFragment Arriving soon. Will return a DocumentFragment value, thereby halting “Fluent interface” method chaining for this instance.

Data import (destructive)

  • write$
    Function( x: Number, y: Number, n: Number or Q.ComplexNumber ) ⇒ Q.Matrix Writes a value, n, to the specified cell address of this matrix. Equivalent to this.columns[ x ][ y ] = n, or this.rows[ y ][ x ] = n, but with safety checks.
  • copy$
    Function( m: Q.Matrix ) ⇒ Q.Matrix Copies the value for rows from the supplied argument, m, if m is a matrix of equal dimensions to this instance, otherwise returns Q.error.
  • fromArray$
    Function( array: Array ) ⇒ Q.Matrix Passes the supplied array argument to the fromArray static method, then uses copy$ to copy that result in to this instance.
  • fromCsv$
    Function( csv: String ) ⇒ Q.Matrix Passes the supplied csv argument to the fromCsv static method, then uses copy$ to copy that result in to this instance.
  • fromTsv$
    Function( tsv: String ) ⇒ Q.Matrix Passes the supplied tsv argument to the fromTsv static method, then uses copy$ to copy that result in to this instance.
  • fromHtml$
    Function( html: String ) ⇒ Q.Matrix Passes the supplied html argument to the fromHtml static method, then uses copy$ to copy that result in to this instance.

Maths operations (non-destructive)

  • add
    Function( otherMatrix: Q.Matrix ) ⇒ Q.Matrix Passes this instance as the first argument and otherMatrix as the second argument to the add static method and returns the result.
  • multiplyScalar
    Function( scalar: Number ) ⇒ Q.Matrix Passes this instance as the first argument and otherMatrix as the second argument to the multiplyScalar static method and returns the result.
  • multiply
    Function( otherMatrix: Q.Matrix ) ⇒ Q.Matrix Passes this instance as the first argument and otherMatrix as the second argument to the multiply static method and returns the result.
  • multiplyTensor
    Function( otherMatrix: Q.Matrix ) ⇒ Q.Matrix Passes this instance as the first argument and otherMatrix as the second argument to the multiplyTensor static method and returns the result.

Maths operations (destructive)

  • add$
    Function( otherMatrix: Q.Matrix ) ⇒ Q.Matrix Calls the add instance method with otherMatrix as an argument and copies the result to this instance.
  • multiplyScalar$
    Function( otherMatrix: Q.Matrix ) ⇒ Q.Matrix Calls the multiplyScalar instance method with otherMatrix as an argument and copies the result to this instance.