Construct circuits
Package versions
The code on this page was developed using the following requirements. We recommend using these versions or newer.
qiskit[all]~=2.1.1
This page takes a closer look at the QuantumCircuit
class in the Qiskit SDK, including some more advanced methods you can use to create quantum circuits.
What is a quantum circuit?
A simple quantum circuit is a collection of qubits and a list of instructions that act on those qubits. To demonstrate, the following cell creates a new circuit with two new qubits, then displays the circuit's qubits
attribute, which is a list of Qubits
in order from the least significant bit to the most significant bit .
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.qubits
Output:
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]
Multiple QuantumRegister
and ClassicalRegister
objects can be combined to create a circuit. Every QuantumRegister
and ClassicalRegister
can also be named.
from qiskit.circuit import QuantumRegister, ClassicalRegister
qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits
combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubits
Output:
[Qubit(QuantumRegister(2, 'qreg1'), 0),
Qubit(QuantumRegister(2, 'qreg1'), 1),
Qubit(QuantumRegister(1, 'qreg2'), 0)]
You can find a qubit's index and register by using the circuit's find_bit
method and its attributes.
desired_qubit = qr2[0] # Qubit 0 of register 'qreg2'
print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)
Output:
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]
Adding an instruction to the circuit appends the instruction to the circuit's data
attribute. The following cell output shows data
is a list of CircuitInstruction
objects, each of which has an operation
attribute, and a qubits
attribute.
qc.x(0) # Add X-gate to qubit 0
qc.data
Output:
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]
The easiest way to view this information is through the draw
method, which returns a visualization of a circuit. See Visualize circuits for different ways of displaying quantum circuits.
qc.draw("mpl")
Output:
Circuit instruction objects can contain "definition" circuits that describe the instruction in terms of more fundamental instructions. For example, the X-gate is defined as a specific case of the U3-gate, a more general single-qubit gate.
# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")
Output:
Instructions and circuits are similar in that they both describe operations on bits and qubits, but they have different purposes:
- Instructions are treated as fixed, and their methods will usually return new instructions (without mutating the original object).
- Circuits are designed to be built over many lines of code, and
QuantumCircuit
methods often mutate the existing object.
What is circuit depth?
The depth() of a quantum circuit is a measure of the number of “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 rest of this page illustrates how to manipulate quantum circuits.
Build circuits
Methods such as QuantumCircuit.h
and QuantumCircuit.cx
add specific instructions to circuits. To add instructions to a circuit more generally, use the append
method. This takes an instruction and a list of qubits to apply the instruction to. See the Circuit Library API documentation for a list of supported instructions.
from qiskit.circuit.library import HGate
qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")
Output:
To combine two circuits, use the compose
method. This accepts another QuantumCircuit
and an optional list of qubit mappings.
qc_a = QuantumCircuit(4)
qc_a.x(0)
qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)
# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")
Output:
You might also want to compile circuits into instructions to keep your circuits organized. You can convert a circuit to an instruction by using the to_instruction
method, then append this to another circuit as you would any other instruction. The circuit drawn in the following cell is functionally equivalent to the circuit drawn in the previous cell.
inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")
Output:
If your circuit is unitary, you can convert it to a Gate
by using the to_gate
method. Gate
objects are specific types of instructions that have some extra features, such as the control
method, which adds a quantum control.
gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")
Output:
To see what's going on, you can use the decompose
method to expand each instruction into its definition.
The decompose
method returns a new circuit and does not mutate the circuit it acts on.
qc_a.decompose().draw("mpl")
Output:
Measure qubits
Measurements are used to sample the states of individual qubits and transfer the results to a classical register. Note that if you are submitting circuits to a Sampler primitive, measurements are required. However, circuits submitted to an Estimator primitive must not contain measurements.
Qubits can be measured using three methods: measure
, measure_all
and measure_active
. To learn how to visualize measured results, see the Visualize results page.
-
QuantumCircuit.measure
: measures each qubit in the first argument onto the classical bit given as the second argument. This method allows full control over where the measurement result is stored. -
QuantumCircuit.measure_all
: takes no argument and can be used for quantum circuits without pre-defined classical bits. It creates classical wires and stores measurement results in order. For example, measurement of qubit is stored in cbit ). It also adds a barrier before the measurement. -
QuantumCircuit.measure_active
: similar tomeasure_all
, but measures only qubits that have operations.
qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)
Output:

qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)
Output:

qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)
Output:

Parameterized circuits
Many near-term quantum algorithms involve executing many variations of a quantum circuit. Since constructing and optimizing large circuits can be computationally expensive, Qiskit supports parameterized circuits. These circuits have undefined parameters, and their values do not need to be defined until just before executing the circuit. This lets you move circuit construction and optimization out of the main program loop. The following cell creates and displays a parameterized circuit.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter
angle = Parameter("angle") # undefined number
# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)
qc.draw("mpl")
Output:
The following cell creates many variations of this circuit and displays one of the variations.
circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))
circuits[0].draw("mpl")
Output:
You can find a list of a circuit's undefined parameters in its parameters
attribute.
qc.parameters
Output:
ParameterView([Parameter(angle)])
Forgotten the method name? Try asking Qiskit Code Assistant.
# Assign all parameters in qc to 0
New to the code assistant? See Qiskit Code Assistant for installation and usage. Note this is an experimental feature and only available to IBM Quantum™ Premium Plan users.
Next steps
- To learn about near-term quantum algorithms, take the Variational algorithm design course.
- See an example of circuits being used in the Grover's Algorithm tutorial.
- Work with simple circuits using IBM Quantum Composer.