quairkit.qinfo.linalg

quairkit.qinfo.linalg.abs_norm(mat)

Tool for calculation of matrix norm.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

matrix

Returns:

norm of input matrix

Return type:

float

Examples

abs_nor = abs_norm(eye(2) / 2)
print(f'The abs norm is:\n{abs_nor}')
The abs norm is:
0.7071067690849304
quairkit.qinfo.linalg.block_enc_herm(mat, num_block_qubits=1)

Generate a (qubitized) block encoding of Hermitian mat.

Parameters:
mat : ndarray | Tensor

matrix to be block encoded

num_block_qubits : int

ancilla qubits used in block encoding

Returns:

a unitary that is a block encoding of mat.

Return type:

ndarray | Tensor

Examples

block_enc = block_enc_herm(x())
print(f'The block encoding of X is:\n{block_enc}')
The block encoding of X is:
tensor([[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
        [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
        [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j]])
quairkit.qinfo.linalg.create_matrix(linear_map, input_dim, input_dtype=None)

Create a matrix representation of a linear map without needing to specify the output dimension.

This function constructs a matrix representation for a given linear map and input dimension.

Parameters:
linear_map : Callable[[Tensor | ndarray], Tensor | ndarray]

A function representing the linear map, which takes an input_dim-dimensional vector and returns a vector.

input_dim : int

The dimension of the input space.

input_dtype : dtype | None

The dtype of the input. Defaults to None.

Returns:

A matrix representing the linear map.

Raises:

RuntimeWarning – the input linear_map may not be linear.

Return type:

ndarray | Tensor

Examples

def f(X):
    return X[0] + X[1]

mat_repr = create_matrix(f, input_dim=2)
print(f'The matrix representation is:\n{mat_repr}')
The matrix representation is:
tensor([1.+0.j, 1.+0.j])
quairkit.qinfo.linalg.dagger(mat)

Tool for calculation of matrix dagger.

Parameters:
mat : ndarray | Tensor

matrix

Returns:

The dagger of matrix

Return type:

ndarray | Tensor

Examples

dag = dagger(t())
print(f'The dagger of this matrix is:\n{dag}')
The dagger of this matrix is:
tensor([[1.0000-0.0000j, 0.0000-0.0000j],
        [0.0000-0.0000j, 0.7071-0.7071j]])
quairkit.qinfo.linalg.direct_sum(A, B)

Calculate the direct sum of A and B.

Parameters:
A : ndarray | Tensor

\(m \times n\) matrix

B : ndarray | Tensor

\(p \times q\) matrix

Returns:

A direct sum of A and B, with shape \((m + p) \times (n + q)\)

Return type:

ndarray | Tensor

Examples

dir_sum = direct_sum(x(), y())
print(f'The direct sum is:\n{dir_sum}')
The direct sum is:
tensor([[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
        [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, -0.-1.j],
        [0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j]])
quairkit.qinfo.linalg.gradient(loss_function, var, n)

Compute the gradient of a given loss function with respect to its input variable.

Parameters:
loss_function : Callable[[Tensor], Tensor]

A loss function to compute the gradient.

var : ndarray | Tensor

A vector of shape (m, 1) as the input variables for the loss function.

n : int

The number of iterations for gradient computation.

Returns:

The gradient vector of shape (m, 1).

Return type:

torch.Tensor

Examples

def quadratic_loss(x: torch.Tensor) -> torch.Tensor:
    # loss function is: L(x) = x₁² + 2x₂² + 3x₃²
    return x[0]**2 + 2 * x[1]**2 + 3 * x[2]**3

var = torch.tensor([[1.0], [2.0], [3.0]], requires_grad=True)
grad = gradient(quadratic_loss, var, n=1)

print(f"Input variable is:\n{var}")
print(f"Computed gradient is:\n{grad}")
Input variable is:
tensor([[1.],
        [2.],
        [3.]], requires_grad=True)
Computed gradient is:
tensor([[ 2.],
        [ 8.],
        [81.]], grad_fn=<CopySlices>)
quairkit.qinfo.linalg.hessian(loss_function, var)

Compute the Hessian matrix of a given loss function with respect to its input variables.

Parameters:
loss_function : Callable[[Tensor], Tensor]

The loss function to compute the Hessian.

var : ndarray | Tensor

A matrix of shape (n, m) as input variables for the loss function.

Returns:

Hessian matrix of shape (m, n, n).

Return type:

torch.Tensor

Examples

def quadratic_loss(x: torch.Tensor) -> torch.Tensor:
    # loss function is: L(x) = x₁² + 2x₂² + 3x₃²
    return x[0]**2 + 2 * x[1]**2 + 3 * x[2]**3

var = torch.tensor([[1.0], [2.0], [3.0]], requires_grad=True)
hes = hessian(quadratic_loss, var)

print(f"Input variable is:\n{var}")
print(f"Computed Hessian is:\n{hes}")
Input variable is:
tensor([[1.],
        [2.],
        [3.]], requires_grad=True)
Computed Hessian is:
tensor([[[ 2.,  0.,  0.],
         [ 0.,  4.,  0.],
         [ 0.,  0., 54.]]])
quairkit.qinfo.linalg.herm_transform(fcn, mat, ignore_zero=False)

Function transformation for a Hermitian matrix.

Parameters:
fcn : Callable[[float], float]

A function \(f\) that can be expanded by Taylor series.

mat : ndarray | Tensor | PureState | MixedState

Hermitian matrix \(H\).

ignore_zero : bool | None

Whether to ignore eigenspaces with zero eigenvalue. Defaults to False.

Returns:

\(f(H)\)

Return type:

ndarray | Tensor

Examples

fH = herm_transform(math.exp, eye(2))
print(f'The result is:\n{fH}')
The result is:
tensor([[2.7183+0.j, 0.0000+0.j],
        [0.0000+0.j, 2.7183+0.j]])
quairkit.qinfo.linalg.kron_power(matrix, n)

Calculate the Kronecker product of identical matrices.

Parameters:
matrix : ndarray | Tensor | PureState | MixedState

The matrix to be powered.

n : int

The number of identical matrices.

Returns:

Kronecker product of n identical matrices.

Return type:

ndarray | Tensor

Examples

kp = kron_power(x(), 2)
print(f'The Kronecker product of 2 X is:\n{kp}')
The Kronecker product of 2 X is:
tensor([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
        [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
        [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
        [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])
quairkit.qinfo.linalg.logm(mat)

Calculate the logarithm of a matrix.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

Input matrix.

Returns:

The matrix of natural base logarithms.

Return type:

ndarray | Tensor

Examples

lgm = logm(x())
print(f'The log of X is:\n{lgm}')
The log of X is:
tensor([[-1.8562e-16+1.5708j,  1.8562e-16-1.5708j],
        [ 1.8562e-16-1.5708j, -1.8562e-16+1.5708j]])
quairkit.qinfo.linalg.nkron(matrix_1st, *args)

Calculate the Kronecker product of matrices.

Parameters:
matrix_1st : ndarray | Tensor | PureState | MixedState

The first matrix.

args : ndarray | Tensor | PureState | MixedState

Other matrices.

Returns:

Kronecker product of the given matrices.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

A = random_state(1)
B = random_state(1)
C = random_state(1)
result = nkron(A, B, C)
print(f'The result is:\n{result}')
The result is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2, 2, 2]
 System sequence: [0, 1, 2]
[[ 0.02+0.j    0.01-0.01j -0.01+0.j   -0.-0.01j  0.04+0.04j  0.05-0.01j
  -0.04-0.03j -0.04+0.02j]
 [ 0.01+0.01j  0.01-0.j   -0.01-0.01j -0.01+0.j   -0.01+0.05j  0.04+0.03j
  -0.-0.04j -0.03-0.02j]
 [-0.01-0.j   -0.01+0.01j  0.02+0.j    0.01-0.02j -0.03-0.04j -0.04+0.j
   0.06+0.06j  0.07-0.02j]
 [-0.-0.01j -0.01-0.j    0.01+0.02j  0.02-0.j    0.02-0.04j -0.02-0.03j
  -0.01+0.08j  0.05+0.05j]
 [ 0.04-0.04j -0.01-0.05j -0.03+0.04j  0.02+0.04j  0.21-0.j    0.1-0.16j
  -0.16+0.03j -0.06+0.14j]
 [ 0.05+0.01j  0.04-0.03j -0.04-0.j   -0.02+0.03j  0.1+0.16j  0.18-0.j
  -0.11-0.11j -0.14+0.03j]
 [-0.04+0.03j -0.-0.04j  0.06-0.06j -0.01-0.08j -0.16-0.03j -0.11+0.11j
   0.29-0.j    0.15-0.23j]
 [-0.04-0.02j -0.03+0.02j  0.07+0.02j  0.05-0.05j -0.06-0.14j -0.14-0.03j
   0.15+0.23j  0.25-0.j  ]]
-----------------------------------------------------
quairkit.qinfo.linalg.NKron(matrix_1st, *args)

Calculate the Kronecker product of matrices.

Parameters:
matrix_1st : ndarray | Tensor | PureState | MixedState

The first matrix.

args : ndarray | Tensor | PureState | MixedState

Other matrices.

Returns:

Kronecker product of the given matrices.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

A = random_state(1)
B = random_state(1)
C = random_state(1)
result = nkron(A, B, C)
print(f'The result is:\n{result}')
The result is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2, 2, 2]
 System sequence: [0, 1, 2]
[[ 0.02+0.j    0.01-0.01j -0.01+0.j   -0.-0.01j  0.04+0.04j  0.05-0.01j
  -0.04-0.03j -0.04+0.02j]
 [ 0.01+0.01j  0.01-0.j   -0.01-0.01j -0.01+0.j   -0.01+0.05j  0.04+0.03j
  -0.-0.04j -0.03-0.02j]
 [-0.01-0.j   -0.01+0.01j  0.02+0.j    0.01-0.02j -0.03-0.04j -0.04+0.j
   0.06+0.06j  0.07-0.02j]
 [-0.-0.01j -0.01-0.j    0.01+0.02j  0.02-0.j    0.02-0.04j -0.02-0.03j
  -0.01+0.08j  0.05+0.05j]
 [ 0.04-0.04j -0.01-0.05j -0.03+0.04j  0.02+0.04j  0.21-0.j    0.1-0.16j
  -0.16+0.03j -0.06+0.14j]
 [ 0.05+0.01j  0.04-0.03j -0.04-0.j   -0.02+0.03j  0.1+0.16j  0.18-0.j
  -0.11-0.11j -0.14+0.03j]
 [-0.04+0.03j -0.-0.04j  0.06-0.06j -0.01-0.08j -0.16-0.03j -0.11+0.11j
   0.29-0.j    0.15-0.23j]
 [-0.04-0.02j -0.03+0.02j  0.07+0.02j  0.05-0.05j -0.06-0.14j -0.14-0.03j
   0.15+0.23j  0.25-0.j  ]]
-----------------------------------------------------
quairkit.qinfo.linalg.p_norm(mat, p)

Calculate the Schatten p-norm of a matrix.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

matrix

p : ndarray | Tensor | Iterable[float] | float

p-norm parameter

Returns:

p-norm of input matrix

Return type:

ndarray | Tensor

Examples

p_nor = p_norm(x(), p=2)
print(f'The 2-norm of X is:\n{p_nor}')
The 2-norm of X is:
1.4142135381698608
quairkit.qinfo.linalg.partial_trace(state, trace_idx, system_dim=2)

Calculate the partial trace of the quantum state.

Parameters:
state : ndarray | Tensor | PureState | MixedState

Input quantum state.

trace_idx : List[int] | int

The system indices to be traced out.

system_dim : List[int] | int

The dimension of all systems. Defaults to the qubit case.

Returns:

Partial trace of the quantum state with arbitrarily selected subsystem.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

pt = partial_trace(bell_state(2), 0, [2, 2])
print(f'The partial trace of Bell state is:\n{pt}')
The partial trace of Bell state is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2]
 System sequence: [0]
[[0.5+0.j 0. +0.j]
 [0. +0.j 0.5+0.j]]
-----------------------------------------------------
quairkit.qinfo.linalg.partial_trace_discontiguous(state, preserve_qubits=None)

Calculate the partial trace of the quantum state with arbitrarily selected subsystem.

Parameters:
state : ndarray | Tensor | PureState | MixedState

Input quantum state.

preserve_qubits : List[int]

Remaining qubits; if None, all qubits are preserved.

Returns:

Partial trace of the quantum state with arbitrarily selected subsystem.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

ptdis = partial_trace_discontiguous(bell_state(2), [0])
print(f'The partial trace of Bell state is:\n{ptdis}')
The partial trace of Bell state is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2]
 System sequence: [0]
[[0.5+0.j 0. +0.j]
 [0. +0.j 0.5+0.j]]
-----------------------------------------------------
quairkit.qinfo.linalg.partial_transpose(state, transpose_idx, system_dim=2)

Calculate the partial transpose \(\rho^{T_A}\) of the input quantum state.

Parameters:
state : ndarray | Tensor | PureState | MixedState

Input quantum state.

transpose_idx : List[int] | int

The system indices to be transposed.

system_dim : List[int] | int

The dimension of all systems. Defaults to the qubit case.

Returns:

The partial transpose of the input quantum state.

Return type:

ndarray | Tensor

Examples

pt = partial_transpose(bell_state(2), [0])
print(f'The partial transpose of Bell state is:\n{pt}')
The partial transpose of Bell state is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2, 2]
 System sequence: [0, 1]
[[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0.5+0.j 0. +0.j]
 [0. +0.j 0.5+0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0.5+0.j]]
-----------------------------------------------------
quairkit.qinfo.linalg.pauli_decomposition(mat)

Decompose the matrix by the Pauli basis.

Parameters:
mat : ndarray | Tensor

The matrix to be decomposed.

Returns:

A list of coefficients corresponding to the Pauli basis.

Return type:

ndarray | Tensor

Examples

pauli_dec = pauli_decomposition(random_state(1).density_matrix)
print(f'The decomposition is:\n{pauli_dec}')
The decomposition is:
tensor([ 0.7071+0.j,  0.5076+0.j,  0.4494+0.j, -0.0572+0.j])
quairkit.qinfo.linalg.permute_systems(state, perm_list, system_dim=2)

Permute quantum systems based on a permutation list.

Parameters:
state : ndarray | Tensor | PureState | MixedState

A matrix representation of a quantum state.

perm_list : List[int]

The permutation list. For example, [0, 2, 1, 3] will swap the 2nd and 3rd subsystems.

system_dim : List[int] | int

A list of dimension sizes of each subsystem.

Returns:

The permuted matrix.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

result = permute_systems(random_state(3), [2, 1, 0])
print(f'The permuted matrix is:\n{result}')
The permuted matrix is:
-----------------------------------------------------
 Backend: density_matrix
 System dimension: [2, 2, 2]
 System sequence: [0, 1, 2]
[[ 0.06+0.j   -0.02+0.j   -0.02-0.07j -0.03-0.j    0.06+0.01j -0.02+0.03j
  -0.01-0.06j  0.01+0.01j]
 [-0.02-0.j    0.13+0.j   -0.05+0.01j -0.02-0.01j  0.06-0.06j -0.01-0.03j
  -0.+0.08j   0.03-0.03j]
 [-0.02+0.07j -0.05-0.01j  0.24+0.j    0.06+0.03j -0.09+0.05j  0.01-0.05j
   0.04-0.05j -0.13+0.04j]
 [-0.03+0.j   -0.02+0.01j  0.06-0.03j  0.1+0.j    -0.07+0.02j  0.02-0.05j
  -0.01+0.01j -0.03+0.j  ]]
-----------------------------------------------------
quairkit.qinfo.linalg.prob_sample(distribution, shots=1024, binary=True, proportional=False)

Sample from a probability distribution.

Parameters:
distribution : ndarray | Tensor

The probability distribution.

shots : int

The number of shots. Defaults to 1024.

binary : bool

Whether the sampled result is recorded as binary. Defaults to True.

proportional : bool

Whether the counts are shown in proportion.

Returns:

A dictionary containing the ordered sampled results and their counts.

Return type:

Dict[str, int | float]

Examples

dist = torch.abs(haar_state_vector(3))
result = prob_sample(dist / torch.sum(dist))
print(f'The sample result is:\n{result}')
The sample result is:
{'0': tensor([1024, 1024, 1024])}
quairkit.qinfo.linalg.schmidt_decompose(psi, sys_A=None)

Calculate the Schmidt decomposition of a quantum state.

For a state \(\lvert\psi\rangle=\sum_i c_i \lvert i_A\rangle\otimes\lvert i_B \rangle\).

Parameters:
psi : ndarray | Tensor | PureState | MixedState

State vector form of the quantum state, with shape \((2**n)\).

sys_A : List[int]

Qubit indices to be included in subsystem A. By default, the first half of the qubits belong to subsystem A.

Returns:

  • A one-dimensional array of Schmidt coefficients with shape (k).

  • A high-dimensional array of bases for subsystem A with shape (k, 2**m, 1).

  • A high-dimensional array of bases for subsystem B with shape (k, 2**m, 1).

Return type:

A tuple containing

Examples

# Example usage (assuming a proper state vector 'psi'):
c, u, v = schmidt_decompose(psi)
print("Schmidt coefficients:", c)
print("Subsystem A bases:", u)
print("Subsystem B bases:", v)
Schmidt coefficients: tensor([...])
Subsystem A bases: tensor([...])
Subsystem B bases: tensor([...])
quairkit.qinfo.linalg.sqrtm(mat)

Calculate the square root of a matrix.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

Input matrix.

Returns:

The square root of the matrix.

Return type:

ndarray | Tensor

Examples

sqrt = sqrtm(x())
print(f'The square root of X is:\n{sqrt}')
The square root of X is:
tensor([[0.5000+0.5000j, 0.5000-0.5000j],
        [0.5000-0.5000j, 0.5000+0.5000j]])
quairkit.qinfo.linalg.trace(mat, axis1=-2, axis2=-1)

Return the sum along the diagonals of the tensor.

If \(mat\) is a 2-D tensor, the sum along its diagonal is returned. For tensors with more than two dimensions, the axes specified by axis1 and axis2 determine the 2-D sub-tensors whose traces will be taken.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

Input tensor from which the diagonal is taken.

axis1 : int

The first axis for the 2-D sub-tensor. Defaults to -2.

axis2 : int

The second axis for the 2-D sub-tensor. Defaults to -1.

Returns:

The trace (sum along the diagonal) of the tensor.

Return type:

ndarray | Tensor

Examples

tr = trace(x())
print(f'The trace of X is:\n{tr}')
The trace of X is:
0j
quairkit.qinfo.linalg.trace_norm(mat)

Calculate the trace norm of a matrix.

Parameters:
mat : ndarray | Tensor | PureState | MixedState

matrix

Returns:

Trace norm of the input matrix

Return type:

ndarray | Tensor

Examples

tr_norm = trace_norm(x())
print(f'The trace norm of X is:\n{tr_norm}')
The trace norm of X is:
2.0