Simulators

Sometimes when we assemble algorithms, it is useful to check whether or not the resulting state is consistent with our expectation. As the state is not something we have access to with experiment, we need to use a simulator to obtain the exact final output state. In QURI Parts, a simulator is any function that work with the explicit state vector or density matrices.

Qulacs simulators​

In the quri_parts.qulacs.simulator module, we provide 3 simulator features for state vectors.

• evaluate_state_to_vector
• run_circuit
• get_marginal_probability

We introduce their functionalities in the following sections.

evaluate_state_to_vector​

evaluate_state_to_vector is a function that converts any non-parametric states into a QuantumStateVector with an empty circuit.

from quri_parts.qulacs.simulator import evaluate_state_to_vectorfrom quri_parts.core.state import quantum_state

Converts a ComputationalBasisState​

For example, bits = 2 = 0b10 represents $|10\rangle$. Note that vectors are arranged as follows: |00>, |01>, |10>, |11>, ... .

comp_state = quantum_state(n_qubits=2, bits=2)out_state = evaluate_state_to_vector(comp_state)print("State vector:")print(out_state.vector)print("")print("Circuit:")print(out_state.circuit.gates)
#output    State vector:    [0.+0.j 0.+0.j 1.+0.j 0.+0.j]        Circuit:    ()

Converts a GeneralCircuitQuantumState​

from quri_parts.circuit import QuantumCircuitcircuit = QuantumCircuit(2)circuit.add_H_gate(0)circuit.add_CNOT_gate(0, 1)bell_state = quantum_state(n_qubits=2, circuit=circuit)out_state = evaluate_state_to_vector(bell_state)print("State vector:")print(out_state.vector)print("")print("Circuit:")print(out_state.circuit.gates)
#output    State vector:    [0.70710678+0.j 0.        +0.j 0.        +0.j 0.70710678+0.j]        Circuit:    ()

Converts a QuantumStateVector​

import numpy as npfrom scipy.stats import unitary_groupcircuit = QuantumCircuit(2)circuit.add_H_gate(0)circuit.add_CNOT_gate(0, 1)init_state_vector = unitary_group.rvs(4)[:, 0]state = quantum_state(n_qubits=2, vector=init_state_vector, circuit=circuit)out_state = evaluate_state_to_vector(state)print("State vector:")print(out_state.vector)print("")print("Circuit:")print(out_state.circuit.gates)
#output    State vector:    [ 0.18421042+0.45591396j -0.29168606+0.44172833j -0.28458075+0.61735372j     -0.10691909+0.06678914j]        Circuit:    ()

run_circuit​

run_circuit is a function that acts a quantum circuit on a state vector represented by a numpy.array and returns the resulting state vector.

from quri_parts.qulacs.simulator import run_circuitn_qubits = 2circuit = QuantumCircuit(n_qubits)circuit.add_H_gate(0)circuit.add_CNOT_gate(0, 1)init_state_vector = unitary_group.rvs(2**n_qubits)[:, 0]out_state = run_circuit(circuit, init_state_vector)out_state
#output    array([0.43459926-0.04472012j, 0.18045739+0.10382554j,           0.5202943 -0.51833746j, 0.21666993+0.42361922j])

get_marginal_probability​

Sometimes we need to perform partial measurement to a state. get_marginal_probability returns the probability of obtaining the specified computational basis eigenstate after measuring a subset of the qubits. For example, for a state with 3 qubits, setting measured_values={0: 1, 2: 0} outputs the probability of obtaining 1 from the 0th qubit and 0 from the 2nd qubit. That is, the probability is obtained from the coefficients of $|001\rangle$ and $|011\rangle$.

from quri_parts.qulacs.simulator import get_marginal_probabilityn_qubits = 3init_state = unitary_group.rvs(2**n_qubits)[:, 0]state = quantum_state(n_qubits=n_qubits, vector=init_state)out_state = evaluate_state_to_vector(state)print("State vector:")print(out_state.vector)print("")print(    "Probability of measuring 1 from to 0th qubit and 0 from the 2nd qubit:",    get_marginal_probability(init_state, measured_values={0: 1, 2: 0}))
#output    State vector:    [-0.01264178-0.02125235j  0.3049721 -0.36580166j -0.25013693-0.26850866j      0.03871132-0.15817578j -0.27692887+0.45944717j -0.32775336+0.40284975j     -0.19829442-0.0291523j   0.1171112 -0.00301804j]        Probability of measuring 1 from to 0th qubit and 0 from the 2nd qubit: 0.2533369796205178

Stim simulators​

We also provide

• evaluate_state_to_vector
• run_circuit

in the quri_parts.stim.simulator module. The functionalities are the same as those in quri_parts.qulacs.simulator except that they only accept Clifford circuits and performs the circuit execution using Stim.