Circuits
Quantum circuit can be constructed easily when we have a circuit object to which we can apply gates by simply calling method like circuit.H(i=0). This functionality is provided in the LegacyCircuit classes, and packed together with the knowledge on how to sample the noisy gates as stochastic matrices from a specific gate set.
Usage
The class is easy to use besides one tricky detail. For each gatetime (timestep), one has to fill in all gates. For example, consider the two qubit case. We apply an X gate on qubit 0 and then a CNOT gate on both qubits with control on 0 and target on 1. Then we use the following code:
from quantum_gates.circuits import EfficientCircuit
from quantum_gates.gates import standard_gates
# The depth can be set arbitrarily for this circuit class.
circuit = EfficientCircuit(nqubit=2, depth=0, gates=standard_gates)
# First timestep -> Each qubit has to get a gate, this is why we apply even identities.
circuit.H(i=0, ...)
circuit.I(i=1)
# Second timestep -> All qubits received a gate, because CNOT is a two-qubit gate.
circuit.CNOT(i=0, k=1, ...)
# Evaluate the statevector
psi1 = circuit.statevector(psi0=np.array([1, 0, 0, 0]))
Not applying gates to each qubit will lead to errors.
Classes and Instances
- class quantum_gates.circuits.EfficientCircuit(nqubit: int, depth: int, gates: Gates)[source]
Bases:
AlternativeCircuit
Class with the same interface as Circuit but built on top of the AlternativeCircuit.
Separates the matrix products in chunks, and contracts them with the statevector.
- class quantum_gates.circuits.AlternativeCircuit(nqubit: int, gates: Gates, BackendClass: StandardBackend)[source]
Bases:
object
Allows to build a circuit and outsource the computations to an optimized backend.
In this version, we provide a backend for the evaluation of the tensor contractions that are performed in the creation of the propagator.
- Parameters:
nqubit (int) – Number of qubits.
gates (int) – Gateset from which the noisy quantum gates should be sampled.
backendClass (Union[StandardBackend, EfficientBackend]) – Backend for performing the computations.
BackendClass (StandardBackend)
Example
from quantum_gates.circuits import AlternativeCircuit from quantum_gates.backends import EfficientBackend from quantum_gates.gates import standard_gates circuit = AlternativeCircuit( nqubit=2, gates=standard_gates, BackendClass=EfficientBackend )
- apply(gate, i)[source]
Applies a single qubit gate to qubit i.
If the circuit snippet is full, then matrix product is appended and the bookkeeping is reset.
- statevector(psi0) array [source]
Compute the output statevector of the noisy quantum circuit, psi1 = U psi0.
- Return type:
array
- I(i: int)[source]
Apply identity gate on qubit i
- Parameters:
i (int) – index of the qubit
- Returns:
None
- bitflip(i: int, tm: float, rout: float)[source]
Apply bitflip noise gate on qubit i. Add before measurements or after initial state preparation.
- relaxation(i: int, Dt: float, T1: float, T2: float)[source]
Apply relaxation noise gate on qubit i. Add on idle-qubits.
- depolarizing(i: int, Dt: float, p: float)[source]
Apply depolarizing noise gate on qubit i. Add on idle-qubits.
- X(i: int, p: float, T1: float, T2: float) array [source]
Apply X single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- SX(i: int, p: float, T1: float, T2: float)[source]
Apply SX single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- CNOT(i: int, k: int, t_int: float, p_i_k: float, p_i: float, p_k: float, T1_ctr: float, T2_ctr: float, T1_trg: float, T2_trg: float)[source]
Apply CNOT two-qubit noisy quantum gate with depolarizing and relaxation errors on both qubits during the unitary evolution.
- Parameters:
i (int) – index of the control qubit (int)
k (int) – index of the target qubit (int)
t_int (float) – CNOT gate time in ns (double)
p_i_k (float) – CNOT depolarizing error probability (double)
p_i (float) – control single-qubit depolarizing error probability (double)
p_k (float) – target single-qubit depolarizing error probability (double)
T1_ctr (float) – control qubit’s amplitude damping time in ns (double)
T2_ctr (float) – control qubit’s dephasing time in ns (double)
T1_trg (float) – target qubit’s amplitude damping time in ns (double)
T2_trg (float) – target qubit’s dephasing time in ns (double)
- Returns:
None
- ECR(i: int, k: int, t_ecr: float, p_i_k: float, p_i: float, p_k: float, T1_ctr: float, T2_ctr: float, T1_trg: float, T2_trg: float)[source]
Apply ECR two-qubit noisy quantum gate with depolarizing and relaxation errors on both qubits during the unitary evolution.
- Parameters:
i (int) – index of the control qubit (int)
k (int) – index of the target qubit (int)
t_ecr (float) – ECR gate time in ns (double)
p_i_k (float) – ECR depolarizing error probability (double)
p_i (float) – control single-qubit depolarizing error probability (double)
p_k (float) – target single-qubit depolarizing error probability (double)
T1_ctr (float) – control qubit’s amplitude damping time in ns (double)
T2_ctr (float) – control qubit’s dephasing time in ns (double)
T1_trg (float) – target qubit’s amplitude damping time in ns (double)
T2_trg (float) – target qubit’s dephasing time in ns (double)
- Returns:
None
- class quantum_gates.circuits.Circuit(nqubit: int, depth: int, gates: Gates)[source]
Bases:
object
Class that allows to define custom noisy quantum circuit and apply it on a given initial quantum state.
Example
from quantum_gates.circuits import Circuit from quantum_gates.gates import standard_gates # The depth has to be set correctly for this class. circuit = Circuit(nqubit=2, depth=1, gates=standard_gates) # We apply gates for one timestep. circuit.X(i=0, ...) circuit.I(i=1) # Evaluate the statevector psi1 = circuit.statevector(psi0=np.array([1, 0, 0, 0])) # Gives [0, 0, 1, 0]
- j[source]
Index of the current matrix product during the building of a list of matrix products.
- Type:
- s[source]
Number of qubits on which gates were applied during this building of the current matrix product.
- Type:
- apply(gate, i)[source]
Apply an arbitrary single qubit gate.
- Parameters:
gate – single qubit gate to apply (array)
i – index of the qubit (int)
- Returns:
None
- statevector(psi0) array [source]
Compute the output statevector of the noisy quantum circuit
- Parameters:
psi0 – initial statevector, must be 1 x 2^n
- Returns:
output statevector
- Return type:
array
- I(i: int)[source]
Apply identity gate on qubit i
- Parameters:
i (int) – index of the qubit
- Returns:
None
- bitflip(i: int, tm: float, rout: float)[source]
Apply bitflip (bitflip) noise gate on qubit i. Add before measurements or after initial state preparation.
- relaxation(i: int, Dt: float, T1: float, T2: float)[source]
Apply relaxation noise gate on qubit i. Add on idle-qubits.
- depolarizing(i: int, Dt: float, p: float)[source]
Apply depolarizing noise gate on qubit i. Add on idle-qubits.
- X(i: int, p: float, T1: float, T2: float) array [source]
Apply X single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- SX(i: int, p: float, T1: float, T2: float)[source]
Apply SX single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- CNOT(i: int, k: int, t_int: float, p_i_k: float, p_i: float, p_k: float, T1_ctr: float, T2_ctr: float, T1_trg: float, T2_trg: float)[source]
Apply CNOT two-qubit noisy quantum gate with depolarizing and relaxation errors on both qubits during the unitary evolution.
- Parameters:
i (int) – index of the control qubit (int)
k (int) – index of the target qubit (int)
t_int (float) – CNOT gate time in ns (double)
p_i_k (float) – CNOT depolarizing error probability (double)
p_i (float) – control single-qubit depolarizing error probability (double)
p_k (float) – target single-qubit depolarizing error probability (double)
T1_ctr (float) – control qubit’s amplitude damping time in ns (double)
T2_ctr (float) – control qubit’s dephasing time in ns (double)
T1_trg (float) – target qubit’s amplitude damping time in ns (double)
T2_trg (float) – target qubit’s dephasing time in ns (double)
- Returns:
None
- ECR(i: int, k: int, t_ecr: float, p_i_k: float, p_i: float, p_k: float, T1_ctr: float, T2_ctr: float, T1_trg: float, T2_trg: float)[source]
Apply ECR two-qubit noisy quantum gate with depolarizing and relaxation errors on both qubits during the unitary evolution.
- Parameters:
i (int) – index of the control qubit (int)
k (int) – index of the target qubit (int)
t_ecr (float) – ECR gate time in ns (double)
p_i_k (float) – ECR depolarizing error probability (double)
p_i (float) – control single-qubit depolarizing error probability (double)
p_k (float) – target single-qubit depolarizing error probability (double)
T1_ctr (float) – control qubit’s amplitude damping time in ns (double)
T2_ctr (float) – control qubit’s dephasing time in ns (double)
T1_trg (float) – target qubit’s amplitude damping time in ns (double)
T2_trg (float) – target qubit’s dephasing time in ns (double)
- Returns:
None
- class quantum_gates.circuits.LegacyCircuit(n: int, d: int)[source]
Bases:
object
Allows to define custom noisy quantum circuit and apply it on a given initial quantum state.
Example
from quantum_gates.circuits import LegacyCircuit n = 2 # Number of qubits d = 1 # Depth of the circuit circuit = LegacyCircuit(n, d) # Apply gates circuit.X(i=0, p=..., T1=..., T2=...) circuit.I(i=1) # Statevector simulation psi0 = np.array([1, 0, 0, 0]) psi1 = circuit.statevector(psi0) # Gives [0 0 1 0]
- phi[source]
Phases of the qubits, this is kept track of because Rz gates are virtual in Qiskit.
- Type:
- apply(gate, i)[source]
Apply an arbitrary gate.
- Parameters:
gate – arbitrary gate to apply (array)
i – index of the qubit (int)
- Returns:
None
- statevector(psi0) array [source]
Compute the output statevector of the noisy quantum circuit.
- Parameters:
psi0 (np.array) – initial statevector, must be 1 x 2^n
- Returns:
Output statevector as array.
- Return type:
array
- I(i: int)[source]
Apply identity gate on qubit i.
- Parameters:
i (int) – Index of the qubit.
- Returns:
None
- bitflip(i: int, tm: float, rout: float)[source]
Apply bitflip (bitflip) noise gate on qubit i. Add before measurements or after initial state preparation.
- relaxation(i: int, Dt: float, T1: float, T2: float)[source]
Apply relaxation noise gate on qubit i. Add on idle-qubits.
- depolarizing(i: int, Dt: float, p: float)[source]
Apply depolarizing noise gate on qubit i. Add on idle-qubits.
- X(i: int, p: float, T1: float, T2: float) array [source]
Apply X single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- SX(i: int, p: float, T1: float, T2: float)[source]
Apply SX single-qubit noisy quantum gate with depolarizing and relaxation errors during the unitary evolution.
- CNOT(i: int, k: int, t_cnot: float, p_i_k: float, p_i: float, p_k: float, T1_ctr: float, T2_ctr: float, T1_trg: float, T2_trg: float)[source]
Apply CNOT two-qubit noisy quantum gate with depolarizing and relaxation errors on both qubits during the unitary evolution.
- Parameters:
i (int) – Index of the control qubit.
k (int) – Index of the target qubit.
t_cnot (float) – CNOT gate time in ns.
p_i_k (float) – CNOT depolarizing error probability.
p_i (float) – Control single-qubit depolarizing error probability.
p_k (float) – Target single-qubit depolarizing error probability.
T1_ctr (float) – Control qubit’s amplitude damping time in ns.
T2_ctr (float) – Control qubit’s dephasing time in ns.
T1_trg (float) – Target qubit’s amplitude damping time in ns.
T2_trg (float) – Target qubit’s dephasing time in ns.
- Returns:
None
Possible extensions
In the future, we could add checks that warns the user in case not all gates are applied.