---
title: Construct circuits
description: How to construct and visualize quantum circuits in Qiskit.
source: https://quantum.cloud.ibm.com/docs/en/guides/construct-circuits
---

# 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.5.1
```

This page takes a closer look at the [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#qubits) attribute, which is a list of [`Qubits`](/docs/api/qiskit/circuit#qiskit.circuit.Qubit) in order from the least significant bit $q_0$ to the most significant bit $q_n$.

```python
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`](/docs/api/qiskit/circuit#qiskit.circuit.QuantumRegister) and [`ClassicalRegister`](/docs/api/qiskit/circuit#qiskit.circuit.ClassicalRegister) can also be named.

```python
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 register=(2, "qreg1"), index=0>,
 <Qubit register=(2, "qreg1"), index=1>,
 <Qubit register=(1, "qreg2"), index=0>]
```

You can find a qubit's index and register by using the circuit's [`find_bit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#qiskit.circuit.QuantumCircuit.find_bit) method and its attributes.

```python
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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#data) attribute. The following cell output shows `data` is a list of [`CircuitInstruction`](/docs/api/qiskit/qiskit.circuit.CircuitInstruction) objects, each of which has an `operation` attribute, and a `qubits` attribute.

```python
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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#draw) method, which returns a visualization of a circuit. See [Visualize circuits](/docs/guides/visualize-circuits) for different ways of displaying quantum circuits.

```python
qc.draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/43a57258-3e33-4071-8a48-2bf127c8a5be-0.svg)

Circuit instruction objects can contain "definition" circuits that describe the instruction in terms of more fundamental instructions. For example, the [X-gate](/docs/api/qiskit/qiskit.circuit.library.XGate) is defined as a specific case of the [U3-gate](/docs/api/qiskit/qiskit.circuit.library.U3Gate), a more general single-qubit gate.

```python
# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/653e2427-e301-4d2f-84de-1959185ace8e-0.svg)

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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) methods often mutate the existing object.

### What is circuit depth?

The [depth()](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#qiskit.circuit.QuantumCircuit.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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#h) and [`QuantumCircuit.cx`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#cx) add specific instructions to circuits. To add instructions to a circuit more generally, use the [`append`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#append) method. This takes an instruction and a list of qubits to apply the instruction to. See the [Circuit Library API documentation](/docs/api/qiskit/circuit_library) for a list of supported instructions.

```python
from qiskit.circuit.library import HGate

qc = QuantumCircuit(1)
qc.append(
    HGate(),  # New HGate instruction
    [0],  # Apply to qubit 0
)
qc.draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/66813cae-9841-47ea-96b7-8fd7b82e9759-0.svg)

To combine two circuits, use the [`compose`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#compose) method. This accepts another [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) and an optional list of qubit mappings.

> **Note**
>
> The [`compose`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#compose) method returns a new circuit and does **not** mutate either circuit it acts on. To mutate the circuit on which you're calling the [`compose`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#compose) method, use the argument `inplace=True`.

```python
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:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/29152dfa-2275-4bc4-aadb-82185b9e0e86-0.svg)

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`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#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.

```python
inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/81b682dd-45cb-4492-809e-d9e8ebbf5600-0.svg)

If your circuit is unitary, you can convert it to a [`Gate`](/docs/api/qiskit/qiskit.circuit.Gate)  by using the [`to_gate`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#to_gate) method. [`Gate`](/docs/api/qiskit/qiskit.circuit.Gate) objects are specific types of instructions that have some extra features, such as the [`control`](/docs/api/qiskit/qiskit.circuit.Gate#control) method, which adds a quantum control.

```python
gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/ed362e64-d6a4-4dfd-a5cf-5e6bdc7a81b5-0.svg)

To see what's going on, you can use the [`decompose`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#decompose) method to expand each instruction into its definition.

> **Note**
>
> The [`decompose`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#decompose) method returns a new circuit and does **not** mutate the circuit it acts on.

```python
qc_a.decompose().draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/3c0633db-929b-4428-a888-7a3d493bd6dd-0.svg)

## 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](/docs/guides/get-started-with-sampler) primitive, measurements are required. However, circuits submitted to an [Estimator](/docs/guides/get-started-with-estimator) primitive must not contain measurements.

Qubits can be measured using three methods: [`measure`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#qiskit.circuit.QuantumCircuit.measure), [`measure_all`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#measure_all) and [`measure_active`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#measure_active). To learn how to visualize measured results, see the [Visualize results](/docs/guides/visualize-results) page.

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

2. `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 $q_i$ is stored in cbit $meas_i$). It also adds a barrier before the measurement.

3. `QuantumCircuit.measure_active` : similar to `measure_all`, but measures only qubits that have operations.

```python
qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/0cdb2273-0.svg)

```python
qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/6f33698c-0.svg)

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

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/ca3f225f-0.svg)

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

```python
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:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/a580552c-d585-4047-99f0-32aafd06e4f3-0.svg)

The following cell creates many variations of this circuit and displays one of the variations.

```python
circuits = []
for value in range(100):
    circuits.append(qc.assign_parameters({angle: value}))

circuits[0].draw("mpl")
```

Output:

![Output of the previous code cell](https://quantum.cloud.ibm.com/docs/images/guides/construct-circuits/extracted-outputs/85af6231-921a-4130-99d3-f6998f761df8-0.svg)

You can find a list of a circuit's undefined parameters in its `parameters` attribute.

```python
qc.parameters
```

Output:

```
ParameterView([Parameter(angle)])
```

### Change a parameter's name

By default, parameter names for a parameterized circuit are prefixed by `x`- for example, `x[0]`. You can change the names after they are defined, as shown in the following example.

```python
from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector

# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)

# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)

# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)
```

## Next steps

> **Recommendations**
>
> - To learn about near-term quantum algorithms, take the [Variational algorithm design](/learning/courses/variational-algorithm-design) course.
> - See an example of circuits being used in the [Grover's Algorithm](/docs/tutorials/grovers-algorithm) tutorial.
> - Work with simple circuits using [IBM Quantum Composer](/docs/guides/composer).
