跳转至

UnitarySimulator

QuICT.simulation.unitary.UnitarySimulator

UnitarySimulator(device: str = 'CPU', precision: str = 'double', hidden_empty_qubits: bool = False, ignore_last_measure: bool = True)

Algorithms to calculate the unitary matrix of a quantum circuit, and simulate.

Parameters:

  • device (str, default: 'CPU' ) –

    The device type, one of [CPU, GPU]. Defaults to "CPU".

  • precision (str, default: 'double' ) –

    The precision for the unitary matrix. Defaults to "double".

  • hidden_empty_qubits (bool, default: False ) –

    Whether ignore the empty qubits or not, default to False.

Source code in QuICT/simulation/unitary/unitary_simulator.py
def __init__(
    self,
    device: str = "CPU",
    precision: str = "double",
    hidden_empty_qubits: bool = False,
    ignore_last_measure: bool = True,
):
    """
    Args:
        device (str, optional): The device type, one of [CPU, GPU]. Defaults to "CPU".
        precision (str, optional): The precision for the unitary matrix. Defaults to "double".
        hidden_empty_qubits (bool, optional): Whether ignore the empty qubits or not, default to False.
    """
    assert device in ["CPU", "GPU"], ValueError("UnitarySimulation.device", "[CPU, GPU]", device)
    self._device = device
    assert precision in ["single", "double"], \
        ValueError("UnitarySimulation.precision", "[single, double]", precision)
    self._precision = precision
    self._gate_calculator = GateSimulator(self._device, self._precision)
    self._vector = None
    self._hidden_empty_qubits = hidden_empty_qubits
    self._ignore_last_measure = ignore_last_measure

run

run(circuit: Union[ndarray, Circuit], quantum_state: ndarray = None, use_previous: bool = False) -> np.ndarray

Simulation by given unitary matrix or circuit

Parameters:

  • circuit (Union[ndarray, Circuit]) –

    The unitary matrix or the circuit for simulation

  • quantum_state (ndarray, default: None ) –

    The initial quantum state vector.

  • use_previous (bool, default: False ) –

    whether using previous state vector. Defaults to False.

Returns:

  • ndarray

    np.ndarray: The state vector after simulation

Source code in QuICT/simulation/unitary/unitary_simulator.py
def run(
    self,
    circuit: Union[np.ndarray, Circuit],
    quantum_state: np.ndarray = None,
    use_previous: bool = False
) -> np.ndarray:
    """ Simulation by given unitary matrix or circuit

    Args:
        circuit (Union[np.ndarray, Circuit]): The unitary matrix or the circuit for simulation
        quantum_state (ndarray): The initial quantum state vector.
        use_previous (bool, optional): whether using previous state vector. Defaults to False.

    Returns:
        np.ndarray: The state vector after simulation
    """
    # Step 1: Generate the unitary matrix of the given circuit
    if isinstance(circuit, (Circuit, CompositeGate)):
        self._qubits_num = circuit.width()
        self._used_qubits = circuit._gates.qubits
        circuit.precision = self._precision
        if self._hidden_empty_qubits and self._qubits_num != len(circuit._gates.qubits):
            self._qubits_num = len(circuit._gates.qubits)
            if isinstance(circuit, Circuit):
                circuit = circuit.to_compositegate() & list(range(self._qubits_num))
            else:
                circuit & list(range(self._qubits_num))

        self._unitary_matrix = circuit.matrix(self._device)
    else:
        row = circuit.shape[0]
        self._qubits_num = int(np.log2(row))
        self._unitary_matrix = self._gate_calculator.normalized_matrix(circuit, self._qubits_num)
        self._ignore_last_measure = False
        self._hidden_empty_qubits = False

    if self._ignore_last_measure:
        _, self._measured_q_order = circuit.gates_without_last_measure()

    # Step 2: Prepare the state vector
    self._original_state_vector = None
    if quantum_state is not None:
        self._vector = self._gate_calculator.dot(
            self._unitary_matrix,
            self._gate_calculator.normalized_state_vector(quantum_state, self._qubits_num)
        )
    elif not use_previous:
        self._vector = self._unitary_matrix[:, 0]

    return self._vector

sample

sample(shots: int = 1, target_qubits: list = None, extra_output: bool = False, seed: int = -1) -> dict

Sample the measured result from current state vector, please first run simulator.run().

Parameters:

  • shots (int, default: 1 ) –

    The sample times for current state vector.

  • target_qubits (list, default: None ) –

    The List of target sample qubits.

  • extra_output (bool, default: False ) –

    Output with extra info: measured qubits (list), and samples (list)

Returns:

  • dict

    List[int]: The measured result list with length equal to 2 ** self._qubits

Source code in QuICT/simulation/unitary/unitary_simulator.py
def sample(self, shots: int = 1, target_qubits: list = None, extra_output: bool = False, seed: int = -1) -> dict:
    """ Sample the measured result from current state vector, please first run simulator.run().

    Args:
        shots (int): The sample times for current state vector.
        target_qubits (list): The List of target sample qubits.
        extra_output (bool): Output with extra info: measured qubits (list), and samples (list)

    Returns:
        List[int]: The measured result list with length equal to 2 ** self._qubits
    """
    assert (self._vector is not None), \
        SampleBeforeRunError("StateVectorSimulation sample without run any circuit.")

    state_dict = defaultdict(int)
    target_qubits = self._regularized_target_qubits(target_qubits)
    sample_result = self._gate_calculator.sample_for_statevector_cdf(
        shots, self._qubits_num, self._vector, target_qubits, seed=seed
    )
    for res in sample_result:
        state_dict[res] += 1

    if not extra_output:
        return state_dict
    else:
        normalize_res, normalize_qorder, normalize_sample = self._sample_normalize(
            state_dict, sample_result, target_qubits
        )

        return normalize_res, normalize_qorder, normalize_sample