Matrices#

This module provides core functions for constructing matrices in quantum mechanics:

from qhronology.mechanics.matrices import vector_basis, ket, bra, quantum_object, encode, decode_slow, decode, decode_fast, decode_multiple

Functions#

vector_basis(
dim: int,
numerical: bool | None = None,
array: bool | None = None,
) list[mat | arr][source]#

Creates an ordered list of column vectors that form an orthonormal basis for a dim-dimensional Hilbert space.

Parameters:
  • dim (int) – The dimensionality of the vector basis. Must be a non-negative integer.

  • numerical (bool) – Whether to cast the vector elements as floating-point values (True) (if possible) or exact values (False). Defaults to False.

  • array (bool) – Whether to cast the vectors as NumPy arrays (True) or SymPy matrices (False). Defaults to False.

Returns:

list[mat | arr] – An ordered list of basis vectors.

Examples

>>> vector_basis(2)
[Matrix([
 [1],
 [0]]),
 Matrix([
 [0],
 [1]])]
>>> vector_basis(3)
[Matrix([
 [1],
 [0],
 [0]]),
 Matrix([
 [0],
 [1],
 [0]]),
 Matrix([
 [0],
 [0],
 [1]])]
ket(
spec: int | list[int],
dim: int | None = None,
numerical: bool | None = None,
array: bool | None = None,
) mat | arr[source]#

Creates a normalized ket (column) basis vector corresponding to the (multipartite) computational-basis value(s) of spec in a dim-dimensional Hilbert space.

In mathematical notation, spec describes the value of the ket vector, e.g., a spec of [i,j,k] corresponds to the ket vector \(\ket{i,j,k}\) (for some non-negative integers i, j, and k).

Parameters:
  • spec (int | list[int]) – A non-negative integer or a list of such types.

  • dim (int) – The dimensionality of the vector. Must be a non-negative integer. Defaults to 2.

  • numerical (bool) – Whether to cast the vector elements as floating-point values (True) (if possible) or exact values (False). Defaults to False.

  • array (bool) – Whether to cast the vector as a NumPy array (True) or SymPy matrix (False). Defaults to False.

Returns:

mat | arr – A normalized column vector.

Examples

>>> ket(0)
Matrix([
[1],
[0]])
>>> ket(1)
Matrix([
[0],
[1]])
>>> ket([2, 1], dim=3)
Matrix([
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[1],
[0]])
bra(
spec: int | list[int],
dim: int | None = None,
numerical: bool | None = None,
array: bool | None = None,
) mat | arr[source]#

Creates a normalized bra (row) basis vector corresponding to the (multipartite) computational-basis value(s) of spec in a dim-dimensional dual Hilbert space.

In mathematical notation, spec describes the value of the bra vector, e.g., a spec of [i,j,k] corresponds to the bra vector \(\bra{i,j,k}\) (for some non-negative integers i, j, and k).

Parameters:
  • spec (int | list[int]) – A non-negative integer or a list of such types.

  • dim (int) – The dimensionality of the vector. Must be a non-negative integer. Defaults to 2.

  • numerical (bool) – Whether to cast the vector elements as floating-point values (True) (if possible) or exact values (False). Defaults to False.

  • array (bool) – Whether to cast the vector as a NumPy array (True) or SymPy matrix (False). Defaults to False.

Returns:

mat | arr – A normalized row vector.

Examples

>>> bra(0)
Matrix([[1, 0]])
>>> bra(1)
Matrix([[0, 1]])
>>> bra([0, 2], dim=3)
Matrix([[0, 0, 1, 0, 0, 0, 0, 0, 0]])
quantum_object(
spec: mat | arr | list[list[num | expr | str]] | list[tuple[num | expr | str, int | list[int]]],
form: str | None = None,
kind: str | None = None,
dim: int | None = None,
numerical: bool | None = None,
array: bool | None = None,
) mat | arr[source]#

Constructs a dim-dimensional matrix or vector representation of a quantum object from a given specification spec.

Parameters:
  • spec

    The specification of the quantum object. Provides a description of the object’s values in a standard dim-dimensional basis. Can be one of:

    • a SymPy matrix (mat)

    • a NumPy array (arr)

    • a list of lists of numerical, symbolic, or string expressions that collectively describe a vector or (square) matrix (list[list[num | expr | str]])

    • a list of 2-tuples of numerical, symbolic, or string coefficients paired their respective number-basis specification (list[tuple[num | expr | str, int | list[int]]])

  • form (str) – A string specifying the form for the quantum object to take. Can be either of "vector" or "matrix". Defaults to "matrix".

  • kind (str) – A string specifying the kind for the quantum object to take. Can be either of "mixed" or "pure". Defaults to "mixed".

  • dim (int) – The dimensionality of the quantum object’s Hilbert space. Must be a non-negative integer. Defaults to 2.

  • numerical (bool) – Whether to cast the matrix elements as floating-point values (True) (if possible) or exact values (False). Defaults to False.

  • array (bool) – Whether to cast the matrix as a NumPy array (True) or SymPy matrix (False). Defaults to False.

Returns:

mat | arr – The matrix or vector representation of the quantum object.

Examples

>>> quantum_object(
...     spec=[("a", [0]), ("b", [1])],
...     form="vector",
...     kind="pure",
...     dim=2,
... )
Matrix([
[a],
[b]])
>>> quantum_object(
...     spec=[("a", [0]), ("b", [1])],
...     form="matrix",
...     kind="pure",
...     dim=2,
... )
Matrix([
[a*conjugate(a), a*conjugate(b)],
[b*conjugate(a), b*conjugate(b)]])
>>> quantum_object(
...     spec=[("a", [0]), ("b", [1])],
...     form="matrix",
...     kind="mixed",
...     dim=2,
... )
Matrix([
[a, 0],
[0, b]])
>>> quantum_object(
...     spec=[("a", [0]), ("b", [1]), ("c", [2])],
...     form="vector",
...     kind="pure",
...     dim=3,
... )
Matrix([
[a],
[b],
[c]])
>>> quantum_object(
...     spec=[("a", [0, 0]), ("b", [1, 1])],
...     form="vector",
...     kind="pure",
...     dim=2,
... )
Matrix([
[a],
[0],
[0],
[b]])
>>> quantum_object(
...     spec=[["a", "b"], ["c", "d"]],
...     form="matrix",
...     kind="mixed",
...     dim=2,
... )
Matrix([
[a, b],
[c, d]])
>>> matrix = sp.Matrix([["a", "b"], ["c", "d"]])
>>> quantum_object(
...     spec=matrix,
...     form="matrix",
...     kind="mixed",
...     dim=2,
... )
Matrix([
[a, b],
[c, d]])
>>> quantum_object(
...     spec=[(1/sp.sqrt(2), [0]), (1/sp.sqrt(2), [1])],
...     form="vector",
...     kind="pure",
...     dim=2,
...     numerical=True,
...     array=True,
... )
array([[0.70710678+0.j],
       [0.70710678+0.j]])
>>> quantum_object(
...     spec=[
...         (sp.Rational(1, 3), [0]),
...         (sp.Rational(1, 3), [1]),
...         (sp.Rational(1, 3), [2]),
...     ],
...     form="matrix",
...     kind="mixed",
...     dim=3,
...     numerical=True,
...     array=True,
... )
array([[0.33333333+0.j, 0.        +0.j, 0.        +0.j],
       [0.        +0.j, 0.33333333+0.j, 0.        +0.j],
       [0.        +0.j, 0.        +0.j, 0.33333333+0.j]])
encode(
integer: int,
num_systems: int | None = None,
dim: int | None = None,
numerical: bool | None = None,
array: bool | None = None,
reverse: bool | None = None,
output_list: bool | None = None,
) mat | arr[source]#

Encodes a non-negative integer as a single quantum state vector (ket).

This is a kind of unsigned integer encoding. It creates a base-dim numeral system representation of integer as an (ordered) list of encoded digits. Returns this list if output_list is True, otherwise returns the corresponding ket vector (i.e., a ket vector with a spec of these digits).

Parameters:
  • integer (int) – The non-negative integer to be encoded.

  • num_systems (int) – The number of systems (e.g., qubits) necessary to represent the integer in the encoding. Must be a non-negative integer. If None, it automatically increases to the smallest possible number of systems with which the given integer can be encoded.

  • dim (int) – The dimensionality (or base) of the encoding. Must be a non-negative integer. Defaults to 2.

  • numerical (bool) – Whether to cast the vector elements as floating-point values (True) (if possible) or exact values (False). Defaults to False.

  • array (bool) – Whether to cast the vector as a NumPy array (True) or SymPy matrix (False). Defaults to False.

  • reverse (bool) –

    Whether to reverse the ordering of the resulting encoded state.

    • If reverse is False, the significance of the digits decreases along the list (i.e., the least-significant digit is last).

    • If reverse is True, the significance of the digits increases along the list (i.e., the least-significant digit is first).

    Defaults to False.

  • output_list (bool) – Whether to output a list of encoded digits instead of an encoded state. Defaults to False.

Returns:

  • mat | arr – A normalized column vector (if output_list is False).

  • list[int] – An ordered list of the encoded digits (if output_list is True).

Examples

>>> encode(3, num_systems=2)
Matrix([
[0],
[0],
[0],
[1]])
>>> encode(7, num_systems=2, dim=3)
Matrix([
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[1],
[0]])
>>> encode(264, num_systems=3, dim=10, output_list=True)
[2, 6, 4]
>>> encode(115, num_systems=8, output_list=True)
[0, 1, 1, 1, 0, 0, 1, 1]
>>> encode(115, num_systems=8, output_list=True, reverse=True)
[1, 1, 0, 0, 1, 1, 1, 0]
decode_slow(
matrix: mat | arr | QuantumObject,
dim: int | None = None,
reverse: bool | None = None,
) int[source]#

Decodes a quantum matrix or vector state to an unsigned integer.

This only makes sense if the input state has exactly one non-zero entry.

Parameters:
  • matrix (mat | arr | QuantumObject) – The quantum (matrix or vector) state to be decoded.

  • dim (int) – The dimensionality (or base) of the encoding. Must be a non-negative integer. Defaults to 2.

  • reverse (bool) –

    Whether to reverse the digit ordering of the encoded state prior to decoding.

    • If reverse is False, the significance of the digits should decrease along the list (i.e., the least-significant digit is last).

    • If reverse is True, the significance of the digits should increase along the list (i.e., the least-significant digit is first).

    Defaults to False.

Returns:

int – The decoded (unsigned) integer.

Note

The current method by which this particular implementation operates is accurate but slow. For a faster algorithm, use the decode_fast() function.

Note

This function can also be called using the alias decode().

Examples

>>> decode_slow(encode(64))
64
>>> matrix = sp.Matrix([0, 0, 0, 0, 1, 0, 0, 0])
>>> decode_slow(matrix)
4
decode(
matrix: mat | arr | QuantumObject,
dim: int | None = None,
reverse: bool | None = None,
) int#

An alias for the decode_slow() function.

decode_fast(
matrix: mat | arr | QuantumObject,
dim: int | None = None,
) int[source]#

Decodes a quantum matrix or vector state to an unsigned integer.

This only makes sense if the input state has exactly one non-zero entry.

Parameters:
  • matrix (mat | arr | QuantumObject) – The quantum (matrix or vector) state to be decoded.

  • dim (int) – The dimensionality (or base) of the encoding. Must be a non-negative integer. Defaults to 2.

Returns:

int – The decoded (unsigned) integer.

Note

The current method by which this particular implementation operates is fast but may be inaccurate (due to some computational shortcuts that may not work in all cases). For a slower but accurate algorithm, use the decode_slow() function.

Note

The output cannot be reversed like in decode_slow().

Examples

>>> decode_fast(encode(2048))
2048
>>> matrix = sp.Matrix([0, 0, 1, 0, 0, 0, 0])
>>> decode_fast(matrix, dim=3)
2
decode_multiple(
matrix: mat | arr | QuantumObject,
dim: int | None = None,
reverse: bool | None = None,
) list[tuple[int, num | expr]][source]#

Decodes a quantum matrix or vector state to one or more unsigned integers with their respective probabilities.

This only makes sense if the input state is both equiprobabilistic and non-symbolic.

Parameters:
  • matrix (mat | arr | QuantumObject) – The quantum (matrix or vector) state to be decoded.

  • dim (int) – The dimensionality (or base) of the encoding. Must be a non-negative integer. Defaults to 2.

  • reverse (bool) –

    Whether to reverse the digit ordering of the encoded state prior to decoding.

    • If reverse is False, the significance of the digits should decrease along the list (i.e., the least-significant digit is last).

    • If reverse is True, the significance of the digits should increase along the list (i.e., the least-significant digit is first).

    Defaults to False.

Returns:

list[tuple[int, num | expr]] – The list of tuples of pairs of decoded (unsigned) integers and their corresponding probabilities.

Examples

>>> a, b = sp.symbols("a, b")
>>> matrix = a * encode(0) + b * encode(1)
>>> decode_multiple(matrix)
[(0, a*conjugate(a)), (1, b*conjugate(b))]
>>> matrix = sp.Matrix(["x", 0, 0, "y"])
>>> decode_multiple(matrix)
[(0, x*conjugate(x)), (3, y*conjugate(y))]