qiskit-documentation/docs/api/qiskit/0.44/circuit.mdx

338 lines
20 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: circuit
description: API reference for qiskit.circuit
in_page_toc_min_heading_level: 2
python_api_type: module
python_api_name: qiskit.circuit
---
<span id="module-qiskit.circuit" />
<span id="qiskit-circuit" />
<span id="quantum-circuits-qiskit-circuit" />
# Quantum Circuits
<span id="module-qiskit.circuit" />
`qiskit.circuit`
## Overview
The fundamental element of quantum computing is the **quantum circuit**. A quantum circuit is a computational routine consisting of coherent quantum operations on quantum data, such as qubits. It is an ordered sequence of quantum gates, measurements and resets, which may be conditioned on real-time classical computation. A set of quantum gates is said to be universal if any unitary transformation of the quantum data can be efficiently approximated arbitrarily well as a sequence of gates in the set. Any quantum program can be represented by a sequence of quantum circuits and classical near-time computation.
In Qiskit, this core element is represented by the [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") class. Below is an example of a quantum circuit that makes a three-qubit GHZ state defined as:
$$
|\psi\rangle = \left(|000\rangle+|111\rangle\right)/\sqrt{2}
$$
```python
from qiskit import QuantumCircuit
# Create a circuit with a register of three qubits
circ = QuantumCircuit(3)
# H gate on qubit 0, putting this qubit in a superposition of |0> + |1>.
circ.h(0)
# A CX (CNOT) gate on control qubit 0 and target qubit 1 generating a Bell state.
circ.cx(0, 1)
# CX (CNOT) gate on control qubit 0 and target qubit 2 resulting in a GHZ state.
circ.cx(0, 2)
# Draw the circuit
circ.draw('mpl')
```
![../\_images/circuit-1.png](/images/api/qiskit/0.44/circuit-1.png)
## Supplementary Information
### Quantum Circuit with conditionals
When building a quantum circuit, there can be interest in applying a certain gate only if a classical register has a specific value. This can be done with the [`InstructionSet.c_if()`](qiskit.circuit.InstructionSet#c_if "qiskit.circuit.InstructionSet.c_if") method.
In the following example, we start with a single-qubit circuit formed by only a Hadamard gate ([`HGate`](qiskit.circuit.library.HGate "qiskit.circuit.library.HGate")), in which we expect to get $|0\rangle$ and $|1\rangle$ with equal probability.
```python
from qiskit import BasicAer, transpile, QuantumRegister, ClassicalRegister, QuantumCircuit
qr = QuantumRegister(1)
cr = ClassicalRegister(1)
qc = QuantumCircuit(qr, cr)
qc.h(0)
qc.measure(0, 0)
qc.draw('mpl')
```
![../\_images/circuit-2.png](/images/api/qiskit/0.44/circuit-2.png)
```python
backend = BasicAer.get_backend('qasm_simulator')
tqc = transpile(qc, backend)
counts = backend.run(tqc).result().get_counts()
print(counts)
```
```python
{'0': 524, '1': 500}
```
Now, we add an [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") only if the value of the [`ClassicalRegister`](qiskit.circuit.ClassicalRegister "qiskit.circuit.ClassicalRegister") is 0. That way, if the state is $|0\rangle$, it will be changed to $|1\rangle$ and if the state is $|1\rangle$, it will not be changed at all, so the final state will always be $|1\rangle$.
```python
from qiskit import BasicAer, transpile, QuantumRegister, ClassicalRegister, QuantumCircuit
qr = QuantumRegister(1)
cr = ClassicalRegister(1)
qc = QuantumCircuit(qr, cr)
qc.h(0)
qc.measure(0, 0)
qc.x(0).c_if(cr, 0)
qc.measure(0, 0)
qc.draw('mpl')
```
![../\_images/circuit-3.png](/images/api/qiskit/0.44/circuit-3.png)
```python
backend = BasicAer.get_backend('qasm_simulator')
tqc = transpile(qc, backend)
counts = backend.run(tqc).result().get_counts()
print(counts)
```
```python
{'1': 1024}
```
### Quantum Circuit Properties
When constructing quantum circuits, there are several properties that help quantify the “size” of the circuits, and their ability to be run on a noisy quantum device. Some of these, like number of qubits, are straightforward to understand, while others like depth and number of tensor components require a bit more explanation. Here we will explain all of these properties, and, in preparation for understanding how circuits change when run on actual devices, highlight the conditions under which they change.
Consider the following circuit:
```python
from qiskit import QuantumCircuit
qc = QuantumCircuit(12)
for idx in range(5):
qc.h(idx)
qc.cx(idx, idx+5)
qc.cx(1, 7)
qc.x(8)
qc.cx(1, 9)
qc.x(7)
qc.cx(1, 11)
qc.swap(6, 11)
qc.swap(6, 9)
qc.swap(6, 10)
qc.x(6)
qc.draw('mpl')
```
![../\_images/circuit-4.png](/images/api/qiskit/0.44/circuit-4.png)
From the plot, it is easy to see that this circuit has 12 qubits, and a collection of Hadamard, CNOT, X, and SWAP gates. But how to quantify this programmatically? Because we can do single-qubit gates on all the qubits simultaneously, the number of qubits in this circuit is equal to the **width** of the circuit:
```python
qc.width()
```
```python
12
```
We can also just get the number of qubits directly:
```python
qc.num_qubits
```
```python
12
```
<Admonition title="Important" type="danger">
For a quantum circuit composed from just qubits, the circuit width is equal to the number of qubits. This is the definition used in quantum computing. However, for more complicated circuits with classical registers, and classically controlled gates, this equivalence breaks down. As such, from now on we will not refer to the number of qubits in a quantum circuit as the width.
</Admonition>
It is also straightforward to get the number and type of the gates in a circuit using [`QuantumCircuit.count_ops()`](qiskit.circuit.QuantumCircuit#count_ops "qiskit.circuit.QuantumCircuit.count_ops"):
```python
qc.count_ops()
```
```python
OrderedDict([('cx', 8), ('h', 5), ('x', 3), ('swap', 3)])
```
We can also get just the raw count of operations by computing the circuits [`QuantumCircuit.size()`](qiskit.circuit.QuantumCircuit#size "qiskit.circuit.QuantumCircuit.size"):
```python
qc.size()
```
```python
19
```
A particularly important circuit property is known as the circuit **depth**. The depth of a quantum circuit is a measure of how many “layers” of quantum gates, executed in parallel, it takes to complete the computation defined by the circuit. Because quantum gates take time to implement, the depth of a circuit roughly corresponds to the amount of time it takes the quantum computer to execute the circuit. Thus, the depth of a circuit is one important quantity used to measure if a quantum circuit can be run on a device.
The depth of a quantum circuit has a mathematical definition as the longest path in a directed acyclic graph (DAG). However, such a definition is a bit hard to grasp, even for experts. Fortunately, the depth of a circuit can be easily understood by anyone familiar with playing [Tetris](https://en.wikipedia.org/wiki/Tetris). Lets see how to compute this graphically:
![../\_images/depth.gif](/images/api/qiskit/0.44/depth.gif)
We can verify our graphical result using [`QuantumCircuit.depth()`](qiskit.circuit.QuantumCircuit#depth "qiskit.circuit.QuantumCircuit.depth"):
```python
qc.depth()
```
```python
9
```
## Quantum Circuit API
### Quantum Circuit Construction
| | |
| --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit")(\*regs\[, name, global\_phase, ...]) | Create a new circuit. |
| [`QuantumRegister`](qiskit.circuit.QuantumRegister "qiskit.circuit.QuantumRegister")(\[size, name, bits]) | Implement a quantum register. |
| [`Qubit`](qiskit.circuit.Qubit "qiskit.circuit.Qubit")(\[register, index]) | Implement a quantum bit. |
| [`ClassicalRegister`](qiskit.circuit.ClassicalRegister "qiskit.circuit.ClassicalRegister")(\[size, name, bits]) | Implement a classical register. |
| [`Clbit`](qiskit.circuit.Clbit "qiskit.circuit.Clbit")(\[register, index]) | Implement a classical bit. |
| [`AncillaRegister`](qiskit.circuit.AncillaRegister "qiskit.circuit.AncillaRegister")(\[size, name, bits]) | Implement an ancilla register. |
| [`AncillaQubit`](qiskit.circuit.AncillaQubit "qiskit.circuit.AncillaQubit")(\[register, index]) | A qubit used as ancillary qubit. |
| [`CircuitInstruction`](qiskit.circuit.CircuitInstruction "qiskit.circuit.CircuitInstruction")(operation\[, qubits, clbits]) | A single instruction in a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"), comprised of the `operation` and various operands. |
| [`Register`](qiskit.circuit.Register "qiskit.circuit.Register")(\[size, name, bits]) | Implement a generic register. |
| [`Bit`](qiskit.circuit.Bit "qiskit.circuit.Bit")(\[register, index]) | Implement a generic bit. |
### Gates and Instructions
| | |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate")(name, num\_qubits, params\[, label]) | Unitary gate. |
| [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate")(name, num\_qubits, params\[, ...]) | Controlled unitary gate. |
| [`Delay`](qiskit.circuit.Delay "qiskit.circuit.Delay")(duration\[, unit]) | Do nothing and just delay/wait/idle for a specified duration. |
| [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction")(name, num\_qubits, num\_clbits, params) | Generic quantum instruction. |
| [`InstructionSet`](qiskit.circuit.InstructionSet "qiskit.circuit.InstructionSet")(\*\[, resource\_requester]) | Instruction collection, and their contexts. |
| [`Operation`](qiskit.circuit.Operation "qiskit.circuit.Operation")() | Quantum Operation Interface Class. |
| [`EquivalenceLibrary`](qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary")(\*\[, base]) | A library providing a one-way mapping of Gates to their equivalent implementations as QuantumCircuits. |
### Control Flow Operations
| | |
| --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp")(name, num\_qubits, num\_clbits, ...) | Abstract class to encapsulate all control flow operations. |
| [`IfElseOp`](qiskit.circuit.IfElseOp "qiskit.circuit.IfElseOp")(condition, true\_body\[, false\_body, ...]) | A circuit operation which executes a program (`true_body`) if a provided condition (`condition`) evaluates to true, and optionally evaluates another program (`false_body`) otherwise. |
| [`WhileLoopOp`](qiskit.circuit.WhileLoopOp "qiskit.circuit.WhileLoopOp")(condition, body\[, label]) | A circuit operation which repeatedly executes a subcircuit (`body`) until a condition (`condition`) evaluates as False. |
| [`ForLoopOp`](qiskit.circuit.ForLoopOp "qiskit.circuit.ForLoopOp")(indexset, loop\_parameter, body\[, ...]) | A circuit operation which repeatedly executes a subcircuit (`body`) parameterized by a parameter `loop_parameter` through the set of integer values provided in `indexset`. |
| [`SwitchCaseOp`](qiskit.circuit.SwitchCaseOp "qiskit.circuit.SwitchCaseOp")(target, cases, \*\[, label]) | A circuit operation that executes one particular circuit block based on matching a given `target` against an ordered list of `values`. |
| [`BreakLoopOp`](qiskit.circuit.BreakLoopOp "qiskit.circuit.BreakLoopOp")(num\_qubits, num\_clbits\[, label]) | A circuit operation which, when encountered, jumps to the end of the nearest enclosing loop. |
| [`ContinueLoopOp`](qiskit.circuit.ContinueLoopOp "qiskit.circuit.ContinueLoopOp")(num\_qubits, num\_clbits\[, label]) | A circuit operation which, when encountered, moves to the next iteration of the nearest enclosing loop. |
The [`SwitchCaseOp`](qiskit.circuit.SwitchCaseOp "qiskit.circuit.SwitchCaseOp") also understands a special value:
<Attribute id="qiskit.circuit.CASE_DEFAULT" isDedicatedPage={true}>
A special object that represents the “default” case of a switch statement. If you use this as a case target, it must be the last case, and will match anything that wasnt already matched. For example:
```python
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit import SwitchCaseOp, CASE_DEFAULT
body0 = QuantumCircuit(2, 2)
body0.x(0)
body1 = QuantumCircuit(2, 2)
body1.z(0)
body2 = QuantumCircuit(2, 2)
body2.cx(0, 1)
qr, cr = QuantumRegister(2), ClassicalRegister(2)
qc = QuantumCircuit(qr, cr)
qc.switch(cr, [(0, body0), (1, body1), (CASE_DEFAULT, body2)], qr, cr)
```
When using the builder interface of [`QuantumCircuit.switch()`](qiskit.circuit.QuantumCircuit#switch "qiskit.circuit.QuantumCircuit.switch"), this can also be accessed as the `DEFAULT` attribute of the bound case-builder object, such as:
```python
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
qr, cr = QuantumRegister(2), ClassicalRegister(2)
qc = QuantumCircuit(qr, cr)
with qc.switch(cr) as case:
with case(0):
qc.x(0)
with case(1):
qc.z(0)
with case(case.DEFAULT):
qc.cx(0, 1)
```
</Attribute>
### Parametric Quantum Circuits
| | |
| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter")(name\[, uuid]) | Parameter Class for variable parameters. |
| [`ParameterVector`](qiskit.circuit.ParameterVector "qiskit.circuit.ParameterVector")(name\[, length]) | ParameterVector class to quickly generate lists of parameters. |
| [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression")(symbol\_map, expr) | ParameterExpression class to enable creating expressions of Parameters. |
### Random Circuits
#### random\_circuit
<Function id="qiskit.circuit.random.random_circuit" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/circuit/random/utils.py" signature="qiskit.circuit.random.random_circuit(num_qubits, depth, max_operands=4, measure=False, conditional=False, reset=False, seed=None)">
Generate random circuit of arbitrary size and form.
This function will generate a random circuit by randomly selecting gates from the set of standard gates in [`qiskit.extensions`](extensions#module-qiskit.extensions "qiskit.extensions"). For example:
```python
from qiskit.circuit.random import random_circuit
circ = random_circuit(2, 2, measure=True)
circ.draw(output='mpl')
```
![../\_images/circuit-5.png](/images/api/qiskit/0.44/circuit-5.png)
**Parameters**
* **num\_qubits** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.12)")) number of quantum wires
* **depth** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.12)")) layers of operations (i.e. critical path length)
* **max\_operands** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.12)")) maximum qubit operands of each gate (between 1 and 4)
* **measure** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")) if True, measure all qubits at the end
* **conditional** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")) if True, insert middle measurements and conditionals
* **reset** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")) if True, insert middle resets
* **seed** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.12)")) sets random seed (optional)
**Returns**
constructed circuit
**Return type**
[QuantumCircuit](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit")
**Raises**
[**CircuitError**](#qiskit.circuit.CircuitError "qiskit.circuit.CircuitError") when invalid options given
</Function>
### Exceptions
Almost all circuit functions and methods will raise a [`CircuitError`](#qiskit.circuit.CircuitError "qiskit.circuit.CircuitError") when encountering an error that is particular to usage of Qiskit (as opposed to regular typing or indexing problems, which will typically raise the corresponding standard Python error).
#### CircuitError
<Class id="qiskit.circuit.CircuitError" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/circuit/exceptions.py" signature="qiskit.circuit.CircuitError(*message)" modifiers="exception">
Base class for errors raised while processing a circuit.
Set the error message.
</Class>