filter_functions.util module
This module provides various helper functions.
Functions
abs2()Absolute value squared
get_indices_from_identifiers()The indices of a subset of identifiers within a list of identifiers.
tensor()Fast, flexible tensor product of an arbitrary number of inputs using
einsum()tensor_insert()For an array that is known to be a tensor product, insert arrays at a given position in the product chain
tensor_merge()For two arrays that are tensor products of known dimensions, merge them at arbitary positions in the product chain
tensor_transpose()For a tensor product, transpose the order of the constituents in the product chain
mdot()Multiple matrix product
adot()Accumulated matrix product
remove_float_errors()Set entries whose absolute value is below a certain threshold to zero
oper_equiv()Determine if two vectors or operators are equal up to a global phase
dot_HS()Hilbert-Schmidt inner product
get_sample_frequencies()Get frequencies with typical infrared and ultraviolet cutoffs for a
PulseSequenceprogressbar()A progress bar for loops. Uses tqdm if available and a simple custom one if not.
hash_array_along_axis()Return a list of hashes along a given axis
all_array_equal()Check if all arrays in an iterable are equal
Exceptions
CalculationErrorException raised if trying to fetch the pulse correlation function when it was not computed during concatenation
- abs2(x: ndarray) ndarray[source]
Fast function to calculate the absolute value squared,
\[|\cdot|^2 := \Re(\cdot)^2 + \Im(\cdot)^2\]Equivalent to:
np.abs(x)**2
- all_array_equal(it: Iterable) bool[source]
Return
Trueif all array elements ofitare equal by hashing the bytes representation of each array. Note that this is not thread-proof.
- dot_HS(U: ndarray | Qobj, V: ndarray | Qobj, eps: float | None = None) float | complex | ndarray[source]
Return the Hilbert-Schmidt inner product of U and V,
\[\langle U, V\rangle_\mathrm{HS} := \mathrm{tr}(U^\dagger V).\]- Parameters:
- U, V: qutip.Qobj or ndarray
Objects to compute the inner product of.
- eps: float
The floating point precision. The result is rounded to abs(int(np.log10(eps))) decimals if eps > 0.
- Returns:
- result: float, complex
The result rounded to precision eps.
Examples
>>> U, V = paulis[1:3] >>> dot_HS(U, V) 0.0 >>> dot_HS(U, U) 2.0
- get_sample_frequencies(pulse: PulseSequence, n_samples: int = 300, spacing: str = 'log', include_quasistatic: bool = False, omega_min: float | None = None, omega_max: float | None = None) ndarray[source]
Get n_samples sample frequencies spaced ‘linear’ or ‘log’.
The ultraviolet cutoff is taken to be one order of magnitude larger than the timescale of the pulse tau. In the case of log spacing, the values are clipped in the infrared at two orders of magnitude below the timescale of the pulse.
- Parameters:
- pulse: PulseSequence
The pulse to get frequencies for.
- n_samples: int, optional
The number of frequency samples. Default is 300.
- spacing: str, optional
The spacing of the frequencies. Either ‘log’ or ‘linear’, default is ‘log’.
- include_quasistatic: bool, optional
Include zero frequency. Default is False.
- omega_min, omega_max: float, optional
Minimum and maximum angular frequencies included (DC notwithstanding). Default to \(2\pi\times 10^{-2}/\tau\) and \(2\pi\times 10^{+1}/\Delta t_{\mathrm{min}}\).
- Returns:
- omega: ndarray
The angular frequencies.
- hash_array_along_axis(arr: ndarray, axis: int = 0) List[int][source]
Return the hashes of arr along the first axis
- oper_equiv(psi: ndarray | Qobj, phi: ndarray | Qobj, eps: float | None = None, normalized: bool = False) Tuple[bool, float][source]
Checks whether psi and phi are equal up to a global phase, i.e.
\[|\psi\rangle = e^{i\chi}|\phi\rangle \Leftrightarrow \langle \phi|\psi\rangle = e^{i\chi},\]and returns the phase. If the first return value is false, the second is meaningless in this context. psi and phi can also be operators.
- Parameters:
- psi, phi: qutip.Qobj or array_like
Vectors or operators to be compared
- eps: float
The tolerance below which the two objects are treated as equal, i.e., the function returns
Trueifabs(1 - modulus) <= eps.- normalized: bool
Flag indicating if psi and phi are normalized with respect to the Hilbert-Schmidt inner product
dot_HS().
Examples
>>> psi = paulis[1] >>> phi = paulis[1]*np.exp(1j*1.2345) >>> oper_equiv(psi, phi) (True, 1.2345)
- progressbar(iterable: Iterable, *args, **kwargs)[source]
Progress bar for loops. Uses tqdm.
Usage:
for i in progressbar(range(10)): do_something()
- remove_float_errors(arr: ndarray, eps_scale: float | None = None) ndarray[source]
Clean up arr by removing floating point numbers smaller than the dtype’s precision multiplied by eps_scale. Treats real and imaginary parts separately.
Obviously only works for arrays with norm ~1.
- tensor(*args, rank: int = 2, optimize: bool | str = False) ndarray[source]
Fast, flexible tensor product using einsum. The product is taken over the last rank axes and broadcast over the remaining axes which thus need to follow numpy broadcasting rules. Note that vectors are treated as rank 2 tensors with shape (1, x) or (x, 1).
For example, the following shapes are compatible:
rank == 2(e.g. matrices or vectors):(a, b, c, d, d), (a, b, c, e, e) -> (a, b, c, d*e, d*e) (a, b, c), (a, d, e) -> (a, b*d, c*e) (a, b), (c, d, e) -> (c, a*d, b*e) (1, a), (b, 1, c) -> (b, 1, a*c)
rank == 1:(a, b), (a, c) -> (a, b*c) (a, b, 1), (a, c) -> (a, b, c)
- Parameters:
- args: array_like
The elements of the tensor product
- rank: int, optional (default: 2)
The rank of the tensors. E.g., for a Kronecker product between two matrices
rank == 2. The remaining axes are broadcast over.- optimize: bool|str, optional (default: False)
Optimize the tensor contraction order. Passed through to
numpy.einsum().
See also
numpy.kronNumPy tensor product.
tensor_insertInsert array at given position in tensor product chain.
tensor_mergeMerge tensor product chains.
tensor_transposeTranspose the order of a tensor product chain.
Examples
>>> Z = np.diag([1, -1]) >>> np.array_equal(tensor(Z, Z), np.kron(Z, Z)) True
>>> A, B = np.arange(2), np.arange(2, 5) >>> tensor(A, B, rank=1) array([[0, 0, 0, 2, 3, 4]])
>>> args = np.random.randn(4, 10, 3, 2) >>> result = tensor(*args, rank=1) >>> result.shape == (10, 3, 2**4) True >>> result = tensor(*args, rank=2) >>> result.shape == (10, 3**4, 2**4) True
>>> A, B = np.random.randn(1, 3), np.random.randn(3, 4) >>> result = tensor(A, B) >>> result.shape == (1*3, 3*4) True
>>> A, B = np.random.randn(3, 1, 2), np.random.randn(2, 2, 2) >>> try: ... result = tensor(A, B, rank=2) ... except ValueError as err: # cannot broadcast over axis 0 ... print(err) Incompatible shapes (3, 1, 2) and (2, 2, 2) for tensor product of rank 2. >>> result = tensor(A, B, rank=3) >>> result.shape == (3*2, 1*2, 2*2) True
- tensor_insert(arr: ndarray, *args, pos: int | Sequence[int], arr_dims: Sequence[Sequence[int]], rank: int = 2, optimize: bool | str = False) ndarray[source]
For a tensor product arr, insert args into the product chain at pos. E.g, if \(\verb|arr|\equiv A\otimes B\otimes C\) and \(\verb|pos|\equiv 2\), the result will be the tensor product
\[A\otimes B\otimes\left[\bigotimes_{X\in\verb|args|}X\right] \otimes C.\]This function works in a similar way to
numpy.insert()and the following would be functionally equivalent in the case that the constituent tensors of the product arr are known:>>> tensor_insert(tensor(*arrs, rank=rank), *args, pos=pos, arr_dims=..., ... rank=rank)
>>> tensor(*np.insert(arrs, pos, args, axis=0), rank=rank)
- Parameters:
- arr: ndarray
The tensor product in whose chain the other args should be inserted
- *args: ndarray
The tensors to be inserted in the product chain
- pos: int|sequence of ints
The position(s) at which the args are inserted in the product chain. If an int and
len(args) > 1, it is repeated so that all args are inserted in a row. If a sequence, it should indicate the indices in the original tensor product chain that led to arr before which args should be inserted.- arr_dims: array_like, shape (rank, n_const)
The last rank dimensions of the n_const constituent tensors of the tensor product arr as a list of lists with the list at position i containing the i-th relevant dimension of all args. Since the remaing axes are broadcast over, their shape is irrelevant.
For example, if
arr = tensor(a, b, c, rank=2)anda,b,chave shapes(2, 3, 4), (5, 2, 2, 1), (2, 2),arr_dims = [[3, 2, 2], [4, 1, 2]].- rank: int, optional (default: 2)
The rank of the tensors. E.g., for a Kronecker product between two vectors,
rank == 1, and between two matricesrank == 2. The remaining axes are broadcast over.- optimize: bool|str, optional (default: False)
Optimize the tensor contraction order. Passed through to
numpy.einsum().
See also
numpy.insertNumPy array insertion with similar syntax.
numpy.kronNumPy tensor product.
tensor_insertInsert array at given position in tensor product chain.
tensor_mergeMerge tensor product chains.
tensor_transposeTranspose the order of a tensor product chain.
Examples
>>> I, X, Y, Z = paulis >>> arr = tensor(X, I) >>> r = tensor_insert(arr, Y, Z, arr_dims=[[2, 2], [2, 2]], pos=0) >>> np.allclose(r, tensor(Y, Z, X, I)) True >>> r = tensor_insert(arr, Y, Z, arr_dims=[[2, 2], [2, 2]], pos=1) >>> np.allclose(r, tensor(X, Y, Z, I)) True >>> r = tensor_insert(arr, Y, Z, arr_dims=[[2, 2], [2, 2]], pos=2) >>> np.allclose(r, tensor(X, I, Y, Z)) True
Other ranks and different dimensions:
>>> from numpy.random import randn >>> A, B, C = randn(2, 3, 1, 2), randn(2, 2, 2, 2), randn(3, 2, 1) >>> arr = tensor(A, C, rank=3) >>> r = tensor_insert(arr, B, pos=1, rank=3, ... arr_dims=[[3, 3], [1, 2], [2, 1]]) >>> np.allclose(r, tensor(A, B, C, rank=3)) True
>>> arrs, args = randn(2, 2, 2), randn(2, 2, 2) >>> arr_dims = [[2, 2], [2, 2]] >>> r = tensor_insert(tensor(*arrs), *args, pos=(0, 1), arr_dims=arr_dims) >>> np.allclose(r, tensor(args[0], arrs[0], args[1], arrs[1])) True >>> r = tensor_insert(tensor(*arrs), *args, pos=(0, 0), arr_dims=arr_dims) >>> np.allclose(r, tensor(*args, *arrs)) True >>> r = tensor_insert(tensor(*arrs), *args, pos=(1, 2), arr_dims=arr_dims) >>> np.allclose(r, tensor(*np.insert(arrs, (1, 2), args, axis=0))) True
- tensor_merge(arr: ndarray, ins: ndarray, pos: Sequence[int], arr_dims: Sequence[Sequence[int]], ins_dims: Sequence[Sequence[int]], rank: int = 2, optimize: bool | str = False) ndarray[source]
For two tensor products arr and ins, merge ins into the product chain at indices pos. E.g, if \(\verb|arr|\equiv A\otimes B\otimes C\), \(\verb|ins|\equiv D\otimes E\), and \(\verb|pos|\equiv [1, 2]\), the result will be the tensor product
\[A\otimes D\otimes B\otimes E\otimes C.\]This function works in a similar way to
numpy.insert()andtensor_insert().- Parameters:
- arr: ndarray
The tensor product in whose chain the other args should be inserted
- ins: ndarray
The tensor product to be inserted in the product chain
- pos: sequence of ints
The positions at which the constituent tensors of ins are inserted in the product chain. Should indicate the indices in the original tensor product chain that led to arr before which the constituents of ins should be inserted.
- arr_dims: array_like, shape (rank, n_const)
The last rank dimensions of the n_const constituent tensors of the tensor product arr as a list of lists with the list at position i containing the i-th relevant dimension of all args. Since the remaing axes are broadcast over, their shape is irrelevant.
For example, if
arr = tensor(a, b, c, rank=2)anda,b,chave shapes(2, 3, 4), (5, 2, 2, 1), (2, 2),arr_dims = [[3, 2, 2], [4, 1, 2]].- ins_dims: array_like, shape (rank, n_const)
The last rank dimensions of the n_const constituent tensors of the tensor product ins as a list of lists with the list at position i containing the i-th relevant dimension of ins. Since the remaing axes are broadcast over, their shape is irrelevant.
- rank: int, optional (default: 2)
The rank of the tensors. E.g., for a Kronecker product between two vectors,
rank == 1, and between two matricesrank == 2. The remaining axes are broadcast over.- optimize: bool|str, optional (default: False)
Optimize the tensor contraction order. Passed through to
numpy.einsum().
See also
numpy.insertNumPy array insertion with similar syntax.
numpy.kronNumPy tensor product.
tensorFast tensor product with broadcasting.
tensor_insertInsert array at given position in tensor product chain.
tensor_transposeTranspose the order of a tensor product chain.
Examples
>>> I, X, Y, Z = paulis >>> arr = tensor(X, Y, Z) >>> ins = tensor(I, I) >>> r1 = tensor_merge(arr, ins, pos=[1, 2], arr_dims=[[2]*3, [2]*3], ... ins_dims=[[2]*2, [2]*2]) >>> np.allclose(r1, tensor(X, I, Y, I, Z)) True >>> r2 = tensor_merge(ins, arr, pos=[0, 1, 2], arr_dims=[[2]*2, [2]*2], ... ins_dims=[[2]*3, [2]*3]) >>> np.allclose(r1, r2) True
tensor_insert()can provide the same functionality in some cases:>>> arr = tensor(Y, Z) >>> ins = tensor(I, X) >>> r1 = tensor_merge(arr, ins, pos=[0, 0], arr_dims=[[2]*2, [2]*2], ... ins_dims=[[2]*2, [2]*2]) >>> r2 = tensor_insert(arr, I, X, pos=[0, 0], arr_dims=[[2]*2, [2]*2]) >>> np.allclose(r1, r2) True
Also tensors of rank other than 2 and numpy broadcasting are supported:
>>> arr = np.random.randn(2, 10, 3, 4) >>> ins = np.random.randn(2, 10, 3, 2) >>> r = tensor_merge(tensor(*arr, rank=1), tensor(*ins, rank=1), [0, 1], ... arr_dims=[[4, 4]], ins_dims=[[2, 2]], rank=1) >>> np.allclose(r, tensor(ins[0], arr[0], ins[1], arr[1], rank=1)) True
- tensor_transpose(arr: ndarray, order: Sequence[int], arr_dims: Sequence[Sequence[int]], rank: int = 2) ndarray[source]
Transpose the order of a tensor product chain.
- Parameters:
- arr: ndarray
The tensor product whose chain should be reordered.
- order: sequence of ints
The transposition order. If
arr == tensor(A, B)andorder == (1, 0), the result will betensor(B, A).- arr_dims: array_like, shape (rank, n_const)
The last rank dimensions of the n_const constituent tensors of the tensor product arr as a list of lists with the list at position i containing the i-th relevant dimension of all args. Since the remaing axes are broadcast over, their shape is irrelevant.
For example, if
arr = tensor(a, b, c, rank=2)anda,b,chave shapes(2, 3, 4), (5, 2, 2, 1), (2, 2),arr_dims = [[3, 2, 2], [4, 1, 2]].- rank: int, optional (default: 2)
The rank of the tensors. E.g., for a Kronecker product between two vectors,
rank == 1, and between two matricesrank == 2. The remaining axes are broadcast over.
- Returns:
- transposed_arr: ndarray
The tensor product arr with its order transposed according to order
See also
numpy.insertNumPy array insertion with similar syntax.
numpy.kronNumPy tensor product.
tensorFast tensor product with broadcasting.
tensor_insertInsert array at given position in tensor product chain.
tensor_mergeMerge tensor product chains.
Examples
>>> I, X, Y, Z = paulis >>> arr = tensor(X, Y, Z) >>> transposed = tensor_transpose(arr, [1, 2, 0], arr_dims=[[2, 2, 2]]*2) >>> np.allclose(transposed, tensor(Y, Z, X)) True