QuantumCircuit#

class QuantumCircuit(num_qubits=0, num_clbits=0, name=None)[source]#

This class describes quantum circuits. Many of the attribute and method names are oriented at 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_qubitsinteger, optional

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

num_clbitsinteger, optional

The amount of classical bits. The default is 0.

namestring, optional

A name for the QuantumCircuit. The default will generated a generic name.

Examples

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

>>> from qrisp import QuantumCircuit
>>> qc_0 = QuantumCircuit(4, name = "fan out")
>>> 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(), 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 class method.

>>> 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.

QuantumCircuit.inverse()

Returns the inverse/daggered QuantumCircuit.

QuantumCircuit.extend(other[, translation_dic])

Extends self in-place by 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.

Evaluating QuantumCircuits#

QuantumCircuit.run([shots, backend])

Runs a QuantumCircuit on a given backend.

QuantumCircuit.statevector_array()

Performs a simulation of the statevector of self and returns a numpy array of complex numbers.

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

Returns the depth of the QuantumCircuit.

QuantumCircuit.t_depth([epsilon])

Estimates the T-depth of self.

QuantumCircuit.cnot_depth()

This function returns the CNOT-depth of an self.

QuantumCircuit.num_qubits()

Returns the amount of qubits.

QuantumCircuit.count_ops()

Counts the amount of operations of each kind.

QuantumCircuit.get_unitary([decimals])

Acquires the unitary matrix of the given QuantumCircuit as a Numpy array.

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

Compares the unitaries of two QuantumCircuits.

QuantumCircuit.to_latex(**kwargs)

Deploys the Qiskit circuit drawer to generate LaTeX output.

QuantumCircuit.qasm([formatted, filename, ...])

Returns the OpenQASM string of self.

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.from_qasm_str(qasm_string)

Loads a QuantumCircuit from a QASM String.

QuantumCircuit.from_qasm_file(filename)

Loads a QuantumCircuit from a QASM file.

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])

Instructs a measurement.

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.