QuantumCircuit#

class QuantumCircuit(num_qubits: int = 0, num_clbits: int = 0)[source]#

This class describes quantum circuits. Many of the attribute and method names are oriented toward the Qiskit QuantumCircuit class in order to provide a high degree of compatibility.

QuantumCircuits can be visualized by calling print on them.

Qrisp QuantumCircuits can be quickly generated out of existing Qiskit QuantumCircuits with the from_qiskit method.

Parameters:
num_qubitsint, optional

The amount of qubits this QuantumCircuit is initialized with. The default is 0.

num_clbitsint, optional

The amount of classical bits. The default is 0.

Examples

We create a QuantumCircuit containing a so-called fan-out gate:

>>> from qrisp import QuantumCircuit
>>> qc_0 = QuantumCircuit(4)
>>> qc_0.cx(0, range(1,4))
>>> print(qc_0)
qb_0: ──■────■────■──
      ┌─┴─┐  │    │
qb_1: ┤ X ├──┼────┼──
      └───┘┌─┴─┐  │
qb_2: ─────┤ X ├──┼──
           └───┘┌─┴─┐
qb_3: ──────────┤ X ├
                └───┘

Note that the cx gate appending method (like all other gate appending methods) can be called with integers, Qubit objects, lists of integers or lists of Qubit objects.

We now turn this QuantumCircuit into a gate and append to another QuantumCircuit to generate a GHZ state:

>>> qc_1 = QuantumCircuit(4)
>>> qc_1.h(0)
>>> qc_1.append(qc_0.to_gate(name="fan-out"), qc_1.qubits)
>>> print(qc_1)
      ┌───┐┌──────────┐
qb_4: ┤ H ├┤0         ├
      └───┘│          │
qb_5: ─────┤1         ├
           │  fan-out │
qb_6: ─────┤2         ├
           │          │
qb_7: ─────┤3         ├
           └──────────┘

Finally, we add a measurement and evaluate the circuit:

>>> qc_1.measure(qc_1.qubits)
>>> print(qc_1)
      ┌───┐┌──────────┐┌─┐
qb_4: ┤ H ├┤0         ├┤M├─────────
      └───┘│          │└╥┘┌─┐
qb_5: ─────┤1         ├─╫─┤M├──────
           │  fan-out │ ║ └╥┘┌─┐
qb_6: ─────┤2         ├─╫──╫─┤M├───
           │          │ ║  ║ └╥┘┌─┐
qb_7: ─────┤3         ├─╫──╫──╫─┤M├
           └──────────┘ ║  ║  ║ └╥┘
cb_0: ══════════════════╩══╬══╬══╬═
                           ║  ║  ║
cb_1: ═════════════════════╩══╬══╬═
                              ║  ║
cb_2: ════════════════════════╩══╬═
                                 ║
cb_3: ═══════════════════════════╩═
>>> qc_1.run(shots = 1000)
{'0000': 500, '1111': 500}

Converting from Qiskit

We construct the very same fan-out QuantumCircuit in Qiskit:

>>> from qiskit import QuantumCircuit as QiskitQuantumCircuit
>>> qc_2 = QiskitQuantumCircuit(4)
>>> qc_2.cx(0, range(1,4))
>>> print(qc_2)
q_0: ──■────■────■──
     ┌─┴─┐  │    │
q_1: ┤ X ├──┼────┼──
     └───┘┌─┴─┐  │
q_2: ─────┤ X ├──┼──
          └───┘┌─┴─┐
q_3: ──────────┤ X ├
               └───┘

To acquire the Qrisp QuantumCircuit we call the from_qiskit method. Note that we don’t need to create a QuantumCircuit object first as this is a classmethod.

>>> qrisp_qc_2 = QuantumCircuit.from_qiskit(qc_2)
>>> print(qrisp_qc_2)
 qb_8: ──■────■────■──
       ┌─┴─┐  │    │
 qb_9: ┤ X ├──┼────┼──
       └───┘┌─┴─┐  │
qb_10: ─────┤ X ├──┼──
            └───┘┌─┴─┐
qb_11: ──────────┤ X ├
                 └───┘

Abstract Parameters

Abstract parameters are represented by SymPy symbols in Qrisp.

We create a QuantumCircuit with some abstract parameters and bind them subsequently.

>>> from qrisp import QuantumCircuit
>>> from sympy import symbols
>>> qc = QuantumCircuit(3)

Create some SymPy symbols and use them as abstract parameters for phase gates:

>>> abstract_parameters = symbols("a b c")
>>> for i in range(3): qc.p(abstract_parameters[i], i)

Create the substitution dictionary and bind the parameters:

>>> subs_dic = {abstract_parameters[i] : i for i in range(3)}
>>> bound_qc = qc.bind_parameters(subs_dic)
>>> print(bound_qc)
      ┌──────┐
qb_0: ┤ P(0) ├
      ├──────┤
qb_1: ┤ P(1) ├
      ├──────┤
qb_2: ┤ P(2) ├
      └──────┘

Methods#

Constructing QuantumCircuits#

QuantumCircuit.append(operation_or_instruction)

Method for appending Operation or Instruction objects to the QuantumCircuit.

QuantumCircuit.to_op([name])

Method to return an Operation object generated out of this QuantumCircuit.

QuantumCircuit.to_gate([name])

Similar to to_op but raises an exception if self contains classical bits (like the Qiskit equivalent).

QuantumCircuit.add_qubit([qubit])

Adds a Qubit to the QuantumCircuit.

QuantumCircuit.add_clbit([clbit])

Adds a classical bit to the QuantumCircuit.

QuantumCircuit.copy()

Returns a copy of the given QuantumCircuit.

QuantumCircuit.clearcopy()

Returns a copy of the given QuantumCircuit but without any data (i.e. just the Qubits and Clbits).

QuantumCircuit.inverse()

Generates the inverse of this QuantumCircuit by applying the inverse gates in reversed order.

QuantumCircuit.extend(other[, translation_dic])

Extends this QuantumCircuit in-place by appending instructions from another QuantumCircuit.

QuantumCircuit.bind_parameters(subs_dic)

Returns a QuantumCircuit where the abstract parameters in subs_dic are bound to their specified values.

QuantumCircuit.transpile([transpilation_level])

Transpiles the QuantumCircuit in the sense that there are no longer any synthesized gate objects.

QuantumCircuit.control(amount)

Returns a controlled version of this QuantumCircuit.

QuantumCircuit.compose(other[, qubits, ...])

Composes this QuantumCircuit with another QuantumCircuit by appending the other to self.

Evaluating QuantumCircuits#

QuantumCircuit.run([shots, backend])

Executes a QuantumCircuit on a backend and returns the measurement results.

QuantumCircuit.statevector_array()

Simulates the circuit and returns its statevector as a NumPy array of complex amplitudes.

QuantumCircuit.depth([depth_indicator, ...])

Returns the depth of the QuantumCircuit.

QuantumCircuit.t_depth([epsilon])

Estimates the T-depth of this QuantumCircuit.

QuantumCircuit.cnot_depth()

Returns the CNOT depth of this QuantumCircuit.

QuantumCircuit.num_qubits()

Returns the number of qubits in this QuantumCircuit.

QuantumCircuit.count_ops()

Counts the amount of operations of each kind.

QuantumCircuit.get_unitary([decimals])

Return the unitary matrix of this QuantumCircuit as a NumPy array.

QuantumCircuit.compare_unitary(other[, ...])

Compares the unitaries of two QuantumCircuits.

QuantumCircuit.get_depth_dic()

Returns the depth of each qubit in this QuantumCircuit.

QuantumCircuit.cnot_count()

Returns the number of two-qubit Pauli-axis controlled gates (CX, CY, CZ) in this QuantumCircuit.

QuantumCircuit.to_latex(**kwargs)

Deploys the Qiskit circuit drawer to generate LaTeX output.

QuantumCircuit.to_qasm2([formatted, ...])

Returns the OpenQASM 2.0 string of this QuantumCircuit.

QuantumCircuit.to_qasm3([formatted, ...])

Returns the OpenQASM 3.0 string of this QuantumCircuit.

QuantumCircuit.qasm(**kwargs)

Alias for to_qasm2().

Interfacing#

QuantumCircuit.from_qiskit(qiskit_qc)

Class method to create QuantumCircuits from Qiskit QuantumCircuits.

QuantumCircuit.to_qiskit()

Method to convert the given QuantumCircuit to a Qiskit QuantumCircuit.

QuantumCircuit.to_pennylane()

Method to convert the given QuantumCircuit to a Pennylane Circuit.

QuantumCircuit.to_pytket()

Method to convert the given QuantumCircuit to a PyTket Circuit.

QuantumCircuit.to_stim([...])

Method to convert the given QuantumCircuit to a Stim Circuit.

QuantumCircuit.from_qasm_str(qasm_string)

Loads a QuantumCircuit from a QASM String.

QuantumCircuit.from_qasm_file(filename)

Loads a QuantumCircuit from a QASM file.

QuantumCircuit.to_cirq()

Method to convert the given QuantumCircuit to a Cirq Circuit.

Operation application methods#

Note

Each Qubit and Clbit parameter in these methods can be replaced by an integer, a list of integers or a list of Qubit/Clbit objects.

>>> from qrisp import QuantumCircuit
>>> qc = QuantumCircuit(5)
>>> qc.cx(qc.qubits[1:], qc.qubits[0])
>>> qc.x([0,1,2,3])
>>> print(qc)
      ┌───┐┌───┐     ┌───┐┌───┐┌───┐
qb_0: ┤ X ├┤ X ├─────┤ X ├┤ X ├┤ X ├
      └─┬─┘└─┬─┘┌───┐└─┬─┘└─┬─┘└───┘
qb_1: ──■────┼──┤ X ├──┼────┼───────
             │  ├───┤  │    │
qb_2: ───────■──┤ X ├──┼────┼───────
                └───┘  │    │  ┌───┐
qb_3: ─────────────────■────┼──┤ X ├
                            │  └───┘
qb_4: ──────────────────────■───────

QuantumCircuit.measure(qubits[, clbits])

Append a measurement instruction to the circuit.

QuantumCircuit.parity(clbits[, expectation, ...])

Append a parity (XOR) check over classical bits to the circuit.

QuantumCircuit.cx(qubits_0, qubits_1)

Instruct a CX-gate.

QuantumCircuit.cy(qubits_0, qubits_1)

Instruct a CY-gate.

QuantumCircuit.cz(qubits_0, qubits_1)

Instruct a CZ-gate.

QuantumCircuit.h(qubits)

Instruct a Hadamard-gate.

QuantumCircuit.x(qubits)

Instruct a Pauli-X-gate.

QuantumCircuit.y(qubits)

Instruct a Pauli-Y-gate.

QuantumCircuit.z(qubits)

Instruct a Pauli-Z-gate.

QuantumCircuit.mcx(control_qubits, target_qubits)

Instruct a multi-controlled X-gate.

QuantumCircuit.ccx(ctrl_qubit_0, ...[, method])

Instruct a Toffoli-gate.

QuantumCircuit.rx(phi, qubits)

Instruct a parametrized RX-gate.

QuantumCircuit.ry(phi, qubits)

Instruct a parametrized RY-gate.

QuantumCircuit.rz(phi, qubits)

Instruct a parametrized RZ-gate.

QuantumCircuit.p(phi, qubits)

Instruct a phase-gate.

QuantumCircuit.cp(phi, qubits_0, qubits_1)

Instruct a controlled phase-gate.

QuantumCircuit.u3(theta, phi, lam, qubits)

Instruct a U3-gate from given Euler angles.

QuantumCircuit.swap(qubits_0, qubits_1)

Instruct a SWAP-gate.

QuantumCircuit.t(qubits)

Instruct a T-gate.

QuantumCircuit.t_dg(qubits)

Instruct a dagger T-gate.

QuantumCircuit.s(qubits)

Instruct an S-gate.

QuantumCircuit.s_dg(qubits)

Instruct a daggered S-gate.

QuantumCircuit.sx(qubits)

Instruct a SX-gate.

QuantumCircuit.sx_dg(qubits)

Instruct a daggered SX-gate.

QuantumCircuit.rxx(phi, qubits_0, qubits_1)

Instruct an RXX-gate.

QuantumCircuit.rzz(phi, qubits_0, qubits_1)

Instruct an RZZ-gate.

QuantumCircuit.xxyy(phi, beta, qubits_0, ...)

Instruct an XXYY-gate.

QuantumCircuit.reset(qubits)

Instruct a reset.

QuantumCircuit.unitary(unitary_array, qubits)

Instruct a U3-gate from a given U3 matrix.

QuantumCircuit.gphase(phi, qubits)

Instruct a global phase.

QuantumCircuit.id(qubits)

Instruct an identity gate.

QuantumCircuit.crx(phi, qubits_0, qubits_1)

Instruct a controlled rx-gate.

QuantumCircuit.barrier([qubits, clbits])

Instruct a Barrier onto the given Qubit.

QuantumCircuit.r(phi, theta, qubits)