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.

Parameters:
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
)
nqubit[source]

Number of qubits.

Type:

int

gates[source]

Gateset from which the noisy quantum gates should be sampled.

Type:

int

phi[source]

Phases of the qubits.

Type:

list[float]

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

Rz(i: int, theta: float)[source]

Update the phase to implement virtual Rz(theta) gate on qubit i

Parameters:
  • i (int) – index of the qubit

  • theta (float) – angle of rotation on the Bloch sphere

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.

Parameters:
  • i (int) – index of the qubit

  • tm (float) – measurement time in ns

  • rout (float) – readout error

Returns:

None

relaxation(i: int, Dt: float, T1: float, T2: float)[source]

Apply relaxation noise gate on qubit i. Add on idle-qubits.

Parameters:
  • i (int) – index of the qubit

  • Dt (float) – idle time in ns

  • T1 (float) – qubit’s amplitude damping time in ns

  • T2 (float) – qubit’s dephasing time in ns

Returns:

None

depolarizing(i: int, Dt: float, p: float)[source]

Apply depolarizing noise gate on qubit i. Add on idle-qubits.

Parameters:
  • i (int) – index of the qubit

  • Dt (float) – idle time in ns

  • p (float) – single-qubit depolarizing error probability

Returns:

None

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.

Parameters:
  • i (int) – index of the qubit

  • p (float) – single-qubit depolarizing error probability

  • T1 (float) – qubit’s amplitude damping time in ns

  • T2 (float) – qubit’s dephasing time in ns

Returns:

None

Return type:

array

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.

Parameters:
  • i (int) – index of the qubit

  • p (float) – single-qubit depolarizing error probability

  • T1 (float) – qubit’s amplitude damping time in ns

  • T2 (float) – qubit’s dephasing time in ns

Returns:

None

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 (int)

  • k (int) – index of the target qubit (int)

  • t_cnot (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

reset()[source]

Reset the circuit to the initial state.

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.

Parameters:
  • n (int) – Number of qubits.

  • d (int) – Depth of the circuit.

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]
nqubit[source]

Number of qubits.

Type:

int

depth[source]

Depth of the circuit.

Type:

int

j[source]

Index of the timestep which we currently apply gates on.

Type:

int

s[source]

Number of qubits already treated in the current timestep.

Type:

in

phi[source]

Phases of the qubits, this is kept track of because Rz gates are virtual in Qiskit.

Type:

list

circuit[source]

Representation of the circuit, contains the sampled gates.

Type:

list[list[np.array]]

display()[source]

Display the noisy quantum circuit.

Returns:

None

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

Rz(i: int, theta: float)[source]

Update the phase to implement virtual Rz(theta) gate on qubit i.

Parameters:
  • i (int) – Index of the qubit.

  • theta (float) – Angle of rotation on the Bloch sphere.

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.

Parameters:
  • i (int) – Index of the qubit

  • tm (float) – Measurement time in ns.

  • rout (float) – Readout error

Returns:

None

relaxation(i: int, Dt: float, T1: float, T2: float)[source]

Apply relaxation noise gate on qubit i. Add on idle-qubits.

Parameters:
  • i (int) – Index of the qubit.

  • Dt (int) – Idle time in ns.

  • T1 (int) – Qubit’s amplitude damping time in ns.

  • T2 (int) – Qubit’s dephasing time in ns.

Returns:

None

depolarizing(i: int, Dt: float, p: float)[source]

Apply depolarizing noise gate on qubit i. Add on idle-qubits.

Parameters:
  • i (int) – Index of the qubit.

  • Dt (float) – Idle time in ns.

  • p (float) – Single-qubit depolarizing error probability.

Returns:

None

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.

Parameters:
  • i (int) – Index of the qubit.

  • p (float) – Single-qubit depolarizing error probability.

  • T1 (float) – Qubit’s amplitude damping time in ns.

  • T2 (float) – Qubit’s dephasing time in ns.

Returns:

None

Return type:

array

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.

Parameters:
  • i (int) – Index of the qubit.

  • p (float) – Single-qubit depolarizing error probability.

  • T1 (float) – Qubit’s amplitude damping time in ns.

  • T2 (float) – Qubit’s dephasing time in ns.

Returns:

None

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.