跳转至

utility

QuICT.qcda.synthesis.quantum_state_preparation.schmidt_decompose

schmidt_decompose(state_vector: ndarray, A_qubits: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]

A quantum state \(|\psi\rangle\) of a composite system A, B could be decomposed as $$ |\psi\rangle = \sum \lambda_i |i_A\rangle |i_B\rangle, $$ where \(\lambda_i\) are non-negative real numbers, \(\sum \lambda_i^2 = 1\), while \(|i_A\rangle, |i_B\rangle\) are orthonormal states. Such decomposition is called Schmidt decomposition, the \(\lambda_i\) are called Schmidt coefficients, the number of non-zero \(\lambda_i\) is called Schmidt number, and \(|i_A\rangle, |i_B\rangle\) are called Schmidt bases.

In this function, we restrict \(A\) and \(B\) to be the first several qubits and the last several qubits respectively.

Parameters:

  • state_vector (ndarray) –

    the state vector of the given state

  • A_qubits (int) –

    the number of the first qubits corresponding to \(A\)

Returns:

  • Tuple[ndarray, ndarray, ndarray]

    Tuple[np.ndarray, np.ndarray, np.ndarray]: \(\lambda_i, |i_A\rangle, |i_B\rangle\) respectively

Source code in QuICT/qcda/synthesis/quantum_state_preparation/utility.py
def schmidt_decompose(state_vector: np.ndarray, A_qubits: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    r"""
    A quantum state $|\psi\rangle$ of a composite system A, B could be decomposed as
    $$
    |\psi\rangle = \sum \lambda_i |i_A\rangle |i_B\rangle,
    $$
    where $\lambda_i$ are non-negative real numbers, $\sum \lambda_i^2 = 1$,
    while $|i_A\rangle, |i_B\rangle$ are orthonormal states.
    Such decomposition is called Schmidt decomposition, the $\lambda_i$ are called Schmidt coefficients,
    the number of non-zero $\lambda_i$ is called Schmidt number,
    and $|i_A\rangle, |i_B\rangle$ are called Schmidt bases.

    In this function, we restrict $A$ and $B$ to be the first several qubits and the last several qubits respectively.

    Args:
        state_vector (np.ndarray): the state vector of the given state
        A_qubits (int): the number of the first qubits corresponding to $A$

    Returns:
        Tuple[np.ndarray, np.ndarray, np.ndarray]: $\lambda_i, |i_A\rangle, |i_B\rangle$ respectively
    """
    state_vector = np.array(state_vector)
    num_qubits = int(np.log2(state_vector.size))
    assert state_vector.ndim == 1 and 1 << num_qubits == state_vector.size,\
        ValueError('Quantum state should be an array with length 2^n')
    assert isinstance(A_qubits, int) and 0 < A_qubits and A_qubits < num_qubits,\
        ValueError('System A should have less qubits than total')
    B_qubits = num_qubits - A_qubits

    state_vector = state_vector.reshape(1 << A_qubits, 1 << B_qubits)
    U, d, V = np.linalg.svd(state_vector, full_matrices=False)
    return d, U.T, V