Circuit -- Qubit, CBit, Operation, QGate, QCircuit, QProg
API reference for quantum circuit construction in pyqpanda3. These classes form the core building blocks for describing quantum computations: qubit references, operations, gates, circuits, and programs.
Qubit
Represents a quantum bit (qubit) identified by a numeric address. Qubit objects serve as lightweight handles used when constructing gates and circuits.
Signature
Qubit(qubit: int)Parameters
| Parameter | Type | Description |
|---|---|---|
| qubit | int | The integer address (index) of the qubit. |
Methods
| Method | Return Type | Description |
|---|---|---|
get_qubit_addr() | int | Returns the address (index) of this qubit. |
Special Methods
__int__()-- Converts the qubit to its integer address.__repr__()-- Returns a string representation, e.g.Qubit(0).
Examples
from pyqpanda3.core import Qubit
q0 = Qubit(0)
q1 = Qubit(1)
print(q0) # Qubit(0)
print(int(q0)) # 0
print(q0.get_qubit_addr()) # 0See Also
CBit
Represents a classical bit used to store measurement outcomes. Like Qubit, it is a lightweight handle identified by a numeric address.
Signature
CBit(addr: int)Note: The parameter is positional only — keyword calling
CBit(addr=0)is not supported.
Parameters
| Parameter | Type | Description |
|---|---|---|
| addr | int | The integer address (index) of the classical bit. |
Methods
| Method | Return Type | Description |
|---|---|---|
get_cbit_addr() | int | Returns the address (index) of this classical bit. |
Special Methods
__int__()-- Converts the classical bit to its integer address.__repr__()-- Returns a string representation, e.g.CBit(0).
Examples
from pyqpanda3.core import CBit
c0 = CBit(0)
c1 = CBit(1)
print(c0) # CBit(0)
print(int(c0)) # 0
print(c0.get_cbit_addr()) # 0See Also
Operation
Base class for all operations in a quantum program. QGate inherits from Operation. An Operation carries metadata about its type, target qubits, control qubits, and associated classical bits (for measurement operations).
Signature
Operation()Attributes
| Attribute | Type | Description |
|---|---|---|
m_operation_type | OpType | The type of this operation (Gate, Measure, etc.). |
m_target_qubits | list[int] | Indices of target qubits. |
m_control_qubits | list[int] | Indices of control qubits. |
m_measure_cbits | list[int] | Classical bit indices associated with measurement. |
Methods
| Method | Return Type | Description |
|---|---|---|
is_controlled() | bool | Returns True if this operation has at least one control qubit. |
Examples
from pyqpanda3.core import H, CNOT
# H is a single-qubit gate (Operation subclass)
h_gate = H(0)
print(h_gate.m_operation_type) # OpType.Gate
print(h_gate.m_target_qubits) # [0]
print(h_gate.is_controlled()) # False
# CNOT is a two-qubit controlled gate
cnot = CNOT(0, 1)
print(cnot.m_control_qubits) # [0]
print(cnot.m_target_qubits) # [1]
print(cnot.is_controlled()) # TrueSee Also
QGate
Represents a quantum gate operation. QGate inherits from Operation and adds gate-specific functionality such as matrix representation, gate type, parameters, dagger and power operations, and control qubit management.
Signature
QGate instances are created through the module-level gate factory functions (e.g. H, X, CNOT, RX, etc.), not by directly calling the QGate constructor.
# Typical construction via factory functions
gate = H(0) # single-qubit gate
gate = CNOT(0, 1) # two-qubit gate
gate = RX(0, 3.14) # parameterized gateMethods
qubits_num
qubits_num() -> intReturns the total number of qubits this gate acts on (both target and control qubits).
qubits
qubits() -> list[int]Returns the target qubit indices.
control_qubits
control_qubits() -> list[int]Returns the control qubit indices for this gate.
target_qubits
target_qubits() -> list[int]Returns the target qubit indices.
dagger
dagger() -> QGateReturns a new QGate that is the Hermitian conjugate (adjoint) of this gate. The original gate is not modified.
is_dagger
is_dagger() -> boolReturns True if this gate is in its dagger (adjoint) form.
power
power(k: int) -> QGateReturns a new gate representing this gate raised to the integer power k.
| Parameter | Type | Description |
|---|---|---|
| k | int | The exponent. |
clear_control
clear_control() -> NoneRemoves all control qubits from this gate.
control
control(qubit: int) -> QGate
control(qubits: list[int]) -> QGateAdds one or more control qubits to this gate. Returns a new QGate with the control qubits added. The original gate is not modified.
| Parameter | Type | Description |
|---|---|---|
| qubit | int | A single control qubit index to add. |
| qubits | list[int] | A list of control qubit indices to add. |
matrix
matrix(expanded: bool = False) -> numpy.ndarrayReturns the matrix representation of this gate. When expanded is True, the matrix is expanded to the full qubit space including control qubits.
| Parameter | Type | Description |
|---|---|---|
| expanded | bool | Whether to return the expanded matrix (default False). |
gate_type
gate_type() -> GateTypeReturns the GateType enum value for this gate.
remap
remap(mapping: dict[int, int]) -> QGate
remap(mapping: list[int]) -> QGateReturns a new gate with qubit indices remapped according to the provided mapping.
| Parameter | Type | Description |
|---|---|---|
| mapping | dict[int, int] or list[int] | A dictionary mapping old qubit indices to new ones, or a list where position i gives the new index for qubit i. |
parameters
parameters() -> list[float]Returns the list of parameters for this gate (empty for non-parameterized gates).
set_parameters
set_parameters(params: list[float]) -> NoneSets the parameters for this gate.
| Parameter | Type | Description |
|---|---|---|
| params | list[float] | The new parameter values. |
name
name() -> strReturns the name of this gate.
Examples
from pyqpanda3.core import H, X, RX, CNOT
# Basic gate properties
h = H(0)
print(h.gate_type()) # GateType.H
print(h.qubits()) # [0]
print(h.qubits_num()) # 1
print(h.name()) # "H"
# Parameterized gate
rx = RX(0, 1.57)
print(rx.parameters()) # [1.57]
rx.set_parameters([3.14])
print(rx.parameters()) # [3.14]
# Dagger (adjoint)
h_dag = h.dagger()
print(h_dag.is_dagger()) # True
# Power
rx_squared = rx.power(2)
# Control qubits
cnot = CNOT(0, 1)
print(cnot.control_qubits()) # [0]
print(cnot.target_qubits()) # [1]
# Add control to a single-qubit gate
controlled_h = H(0).control(2)
print(controlled_h.control_qubits()) # [2]
# Add multiple controls
controlled_x = X(0).control([2, 3])
print(controlled_x.control_qubits()) # [2, 3]
# Clear controls
controlled_x.clear_control()
print(controlled_x.control_qubits()) # []
# Matrix representation
import numpy as np
mat = H(0).matrix()
print(mat.shape) # (2, 2)See Also
- Gates -- Full list of gate factory functions.
- GateType -- Gate type enumeration.
- Operation -- Base class.
QCircuit
Represents a quantum circuit: an ordered sequence of quantum gate operations. Circuits can be composed using the << operator and support operations such as dagger, control, depth analysis, and matrix computation.
Signature
QCircuit() # empty circuit
QCircuit(qubits_num: int) # circuit with a specified register size
QCircuit(circuit: QCircuit) # copy constructorParameters
| Parameter | Type | Description |
|---|---|---|
| qubits_num | int | Number of qubits to allocate in the circuit register. |
| circuit | QCircuit | An existing circuit to copy. |
Methods
size
size() -> intReturns the number of operations in the circuit.
append
append(gate: QGate) -> None
append(circuit: QCircuit) -> NoneAppends a gate or another circuit to this circuit.
| Parameter | Type | Description |
|---|---|---|
| gate | QGate | A quantum gate to append. |
| circuit | QCircuit | A circuit to append. |
clear
clear() -> NoneRemoves all operations from this circuit.
matrix
matrix() -> numpy.ndarrayReturns the unitary matrix representation of the entire circuit.
qubits
qubits() -> list[int]Returns the list of qubit indices used in this circuit.
target_qubits
target_qubits() -> list[int]Returns the target qubit indices used in this circuit.
control_qubits
control_qubits() -> list[int]Returns the control qubit indices used in this circuit.
dagger
dagger() -> QCircuitReturns a new QCircuit where every gate is replaced by its Hermitian conjugate. The original circuit is not modified.
control
control(qubit: int) -> QCircuit
control(qubits: list[int]) -> QCircuitAdds one or more control qubits to the entire circuit. Returns a new QCircuit. The original circuit is not modified.
| Parameter | Type | Description |
|---|---|---|
| qubit | int | A single control qubit index to add. |
| qubits | list[int] | A list of control qubit indices to add. |
clear_control
clear_control() -> NoneRemoves all control qubits from this circuit.
set_name
set_name(name: str) -> NoneSets a custom name for the circuit.
| Parameter | Type | Description |
|---|---|---|
| name | str | The name to assign. |
name
name() -> strReturns the name of the circuit.
operations
operations() -> listReturns all operations in the circuit as a list (may contain QGate and nested QCircuit objects).
gate_operations
gate_operations(only_q2: bool = False) -> list[QGate]Returns all gate-level operations, flattening nested circuits. When only_q2 is True, only two-qubit gates are returned.
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, return only two-qubit gates (default False). |
num_2q_gate
num_2q_gate() -> intReturns the count of two-qubit gates in the circuit.
depth
depth(only_q2: bool = False) -> intReturns the circuit depth (number of sequential gate layers). When only_q2 is True, only two-qubit gates are considered.
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, compute depth using only two-qubit gates (default False). |
count_ops
count_ops(only_q2: bool = False) -> dict[str, int]Returns a dictionary mapping gate names to their occurrence counts.
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, count only two-qubit gates (default False). |
get_register_size
get_register_size() -> intReturns the size of the qubit register allocated for this circuit.
expand
expand() -> QCircuitReturns a new circuit with all nested sub-circuits expanded into a flat gate sequence.
originir
originir(precision: int = 8) -> strReturns the OriginIR string representation of the circuit.
| Parameter | Type | Description |
|---|---|---|
| precision | int | Floating-point precision for parameter values (default 8). |
remap
remap(mapping: list[int]) -> QCircuit
remap(mapping: dict[int, int]) -> QCircuitReturns a new circuit with qubit indices remapped according to the provided mapping.
| Parameter | Type | Description |
|---|---|---|
| mapping | list[int] or dict[int, int] | A list or dictionary mapping old qubit indices to new ones. |
Operators
<< (left shift)
Appends a gate or circuit. Returns the circuit itself, enabling chaining.
circuit << gate # append a QGate
circuit << other_circ # append a QCircuitSpecial Methods
__str__()-- Returns a text-based circuit diagram.__lshift__()-- Implements the<<operator for appending gates and circuits.
Examples
Basic circuit construction
from pyqpanda3.core import QCircuit, H, X, CNOT, T
# Create an empty circuit
circ = QCircuit()
# Append gates using <<
circ << H(0) << CNOT(0, 1)
print(circ.size()) # 2
print(circ.qubits()) # [0, 1]Circuit with register size
from pyqpanda3.core import QCircuit, H, CNOT
circ = QCircuit(3)
circ << H(0) << CNOT(0, 1) << X(2)
print(circ.get_register_size()) # 3
print(circ.size()) # 3Composing circuits
from pyqpanda3.core import QCircuit, H, CNOT, T, S
# Sub-circuit A
sub_a = QCircuit()
sub_a << H(0) << CNOT(0, 1)
# Sub-circuit B
sub_b = QCircuit()
sub_b << T(0) << S(1)
# Combine using <<
full = QCircuit()
full << sub_a << sub_b
print(full.size()) # 4Analysis: depth and gate count
from pyqpanda3.core import QCircuit, H, CNOT, T
circ = QCircuit()
circ << H(0) << H(1) << CNOT(0, 1) << T(0) << T(1)
print(circ.depth()) # 3 (H layer, CNOT layer, T layer)
print(circ.depth(only_q2=True)) # 1 (only the CNOT layer)
print(circ.num_2q_gate()) # 1
print(circ.count_ops()) # {'H': 2, 'CNOT': 1, 'T': 2}Dagger and control
from pyqpanda3.core import QCircuit, H, CNOT, RX
circ = QCircuit()
circ << H(0) << CNOT(0, 1) << RX(1, 1.57)
# Dagger of the entire circuit
circ_dag = circ.dagger()
# Add a control qubit to the entire circuit
ctrl_circ = QCircuit()
ctrl_circ << H(0) << CNOT(0, 1)
ctrl_circ.control([2])
print(ctrl_circ.control_qubits()) # [2]Matrix representation
import numpy as np
from pyqpanda3.core import QCircuit, H, X
circ = QCircuit()
circ << H(0) << X(1)
mat = circ.matrix()
print(mat.shape) # (4, 4)OriginIR output
from pyqpanda3.core import QCircuit, H, CNOT, RX
circ = QCircuit()
circ << H(0) << CNOT(0, 1) << RX(1, 1.57)
print(circ.originir())Remap qubits
from pyqpanda3.core import QCircuit, H, CNOT
circ = QCircuit()
circ << H(0) << CNOT(0, 1)
# Remap: qubit 0 -> 2, qubit 1 -> 3
remapped = circ.remap([2, 3])
print(remapped.qubits()) # [2, 3]See Also
- QProg -- Quantum program (circuits plus measurements and control flow).
- QGate -- Quantum gate class.
- Gates -- Full list of gate factory functions.
- OriginIR -- OriginIR intermediate representation.
QProg
Represents a quantum program: a complete quantum computation that may include gates, circuits, measurements, and dynamic control flow (classical conditional branches and loops). QProg is the top-level container used when submitting programs to simulators or quantum hardware.
Signature
QProg() # empty program
QProg(qubits_num: int) # program with a specified number of qubits
QProg(prog: QProg) # copy constructor
QProg(originir_src: str, is_file: bool = False) # from OriginIR source or file
QProg(node: QCircuit) # from a QCircuitParameters
| Parameter | Type | Description |
|---|---|---|
| qubits_num | int | Number of qubits to allocate. |
| prog | QProg | An existing program to copy. |
| originir_src | str | OriginIR source string or file path. |
| is_file | bool | If True, originir_src is treated as a file path (default False). |
| node | QCircuit | A circuit to initialize the program with. |
Methods
qubits_num
qubits_num() -> intReturns the number of qubits used in the program.
cbits_num
cbits_num() -> intReturns the number of classical bits used in the program.
qubits
qubits() -> list[int]Returns the qubit indices used in the program.
cbits
cbits() -> list[int]Returns the classical bit indices used in the program.
operations
operations() -> listReturns all operations in the program (gates, measurements, sub-programs, etc.).
gate_operations
gate_operations(only_q2: bool = False) -> list[QGate]Returns all gate-level operations, flattening nested structures. When only_q2 is True, only two-qubit gates are returned.
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, return only two-qubit gates (default False). |
name
name() -> strReturns the name of the program.
get_measure_nodes
get_measure_nodes() -> listReturns all measurement nodes in the program.
flatten
flatten() -> QProgReturns a new program with all nested sub-programs expanded into a flat sequence.
to_circuit
to_circuit() -> QCircuitConverts the program to a QCircuit (excluding measurement operations).
count_ops
count_ops(only_q2: bool = False) -> dict[str, int]Returns a dictionary mapping operation names to their counts.
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, count only two-qubit gates (default False). |
depth
depth(only_q2: bool = False) -> intReturns the program depth (number of sequential gate layers).
| Parameter | Type | Description |
|---|---|---|
| only_q2 | bool | If True, compute depth using only two-qubit gates (default False). |
clear
clear() -> NoneRemoves all operations from the program.
append
append(gate: QGate) -> None
append(circuit: QCircuit) -> None
append(prog: QProg) -> None
append(measure: MeasureNode) -> NoneAppends an operation to the program. Accepts gates, circuits, programs, and measurement nodes.
| Parameter | Type | Description |
|---|---|---|
| gate | QGate | A quantum gate to append. |
| circuit | QCircuit | A circuit to append. |
| prog | QProg | A program to append. |
| measure | MeasureNode | A measurement node to append. |
remap
remap(remap_qubits: list[int], remap_cbits: list[int]) -> QProg
remap(remap_qubits: dict[int, int], remap_cbits: dict[int, int] = {}) -> QProgReturns a new program with qubit and classical bit indices remapped.
| Parameter | Type | Description |
|---|---|---|
| remap_qubits | list[int] or dict[int, int] | Mapping for qubit indices. |
| remap_cbits | list[int] or dict[int, int] | Mapping for classical bit indices. |
originir
originir(precision: int = 8) -> strReturns the OriginIR string representation of the program.
| Parameter | Type | Description |
|---|---|---|
| precision | int | Floating-point precision for parameter values (default 8). |
originbis
originbis() -> bytesReturns the OriginBIS binary serialization of the program.
from_originbis
from_originbis(data: bytes) -> NoneDeserializes the program from OriginBIS binary data.
| Parameter | Type | Description |
|---|---|---|
| data | bytes | OriginBIS binary data. |
to_instruction
to_instruction(backend: str, offset: int = 1, is_scheduling: bool = False) -> strConverts the program into a JSON instruction string compatible with the specified backend.
| Parameter | Type | Description |
|---|---|---|
| backend | str | The chip backend name for instruction formatting. |
| offset | int | Qubit index offset (default 1). |
| is_scheduling | bool | Whether to include scheduling information (default False). |
Operators
<< (left shift)
Appends a gate, circuit, program, or measurement node. Returns the program itself, enabling chaining.
prog << gate # append a QGate
prog << circuit # append a QCircuit
prog << other_prog # append a QProg
prog << measure_node # append a MeasureNodeSpecial Methods
__str__()-- Returns a text-based circuit diagram of the program.
Examples
Basic program with measurements
from pyqpanda3.core import QProg, H, CNOT, measure
prog = QProg()
prog << H(0) << CNOT(0, 1) << measure(0, 0) << measure(1, 1)
print(prog.qubits_num()) # 2
print(prog.cbits_num()) # 2
print(prog.qubits()) # [0, 1]
print(prog.cbits()) # [0, 1]Program from OriginIR
from pyqpanda3.core import QProg
# From an OriginIR string
ir_source = """
QINIT 2
CREG 2
H q[0]
CNOT q[0],q[1]
MEASURE q[0],c[0]
MEASURE q[1],c[1]
"""
prog = QProg(ir_source)
print(prog.originir())Program from a QCircuit
from pyqpanda3.core import QProg, QCircuit, H, CNOT, measure
circ = QCircuit()
circ << H(0) << CNOT(0, 1)
prog = QProg(circ)
prog << measure(0, 0) << measure(1, 1)Analysis: depth and gate counts
from pyqpanda3.core import QProg, H, CNOT, RX, T
prog = QProg()
prog << H(0) << H(1) << CNOT(0, 1) << RX(1, 0.5) << T(0)
print(prog.depth()) # 3
print(prog.depth(only_q2=True)) # 1
print(prog.count_ops()) # {'H': 2, 'CNOT': 1, 'RX': 1, 'T': 1}Flatten and convert to circuit
from pyqpanda3.core import QProg, QCircuit, H, CNOT
# Nested structure
sub = QCircuit()
sub << H(0) << CNOT(0, 1)
prog = QProg()
prog << sub << H(2)
# Flatten to a linear gate sequence
flat_prog = prog.flatten()
# Convert to a circuit (measurements excluded)
circ = prog.to_circuit()
print(circ.qubits()) # [0, 1, 2]Remap qubits and classical bits
from pyqpanda3.core import QProg, H, CNOT, measure
prog = QProg()
prog << H(0) << CNOT(0, 1) << measure(0, 0) << measure(1, 1)
# Remap using lists: qubit 0->3, 1->4; cbit 0->5, 1->6
remapped = prog.remap([3, 4], [5, 6])
print(remapped.qubits()) # [3, 4]
print(remapped.cbits()) # [5, 6]
# Remap using dictionaries
remapped2 = prog.remap({0: 3, 1: 4}, {0: 5, 1: 6})Export to backend instruction
from pyqpanda3.core import QProg, H, CNOT, measure
prog = QProg()
prog << H(0) << CNOT(0, 1) << measure(0, 0) << measure(1, 1)
json_instr = prog.to_instruction("origin_72", offset=1, is_scheduling=False)
print(json_instr)Get measurement nodes
from pyqpanda3.core import QProg, H, measure
prog = QProg()
prog << H(0) << measure(0, 0)
measure_nodes = prog.get_measure_nodes()
print(len(measure_nodes)) # 1See Also
- QCircuit -- Quantum circuit (gate-only container).
- QGate -- Quantum gate class.
- MeasureNode -- Measurement node class.
- Dynamic Circuit -- Conditional and loop constructs for
QProg. - OriginIR -- OriginIR intermediate representation.
- Simulator -- Run programs on simulators.
draw_qprog
Draws a quantum program or circuit as a text diagram or LaTeX source. This function accepts both QProg and QCircuit objects.
Signature
draw_qprog(qprog: QProg, p: PIC_TYPE = PIC_TYPE.TEXT, expend_map: dict[str, int] = {'all': 1}, param_show: bool = False, with_logo: bool = False, line_length: int = 100, output_file: str = '', encode: str = 'utf-8') -> str
draw_qprog(circuit: QCircuit, p: PIC_TYPE = PIC_TYPE.TEXT, ...) -> strParameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| qprog | QProg | — | The quantum program to draw |
| circuit | QCircuit | — | The quantum circuit to draw |
| p | PIC_TYPE | PIC_TYPE.TEXT | Output format: PIC_TYPE.TEXT for ASCII text or PIC_TYPE.LATEX for LaTeX |
| expend_map | dict[str, int] | {'all': 1} | Map of qubit indices to expand (use {'all': 1} to expand all) |
| param_show | bool | False | Whether to display gate parameter values in the output |
| with_logo | bool | False | Whether to include the pyqpanda3 logo in the output |
| line_length | int | 100 | Maximum characters per line in the text output |
| output_file | str | '' | File path to save the output (empty string prints to console) |
| encode | str | 'utf-8' | Character encoding for the output file |
Returns
str — The rendered circuit diagram as a string.
Examples
from pyqpanda3.core import draw_qprog, QProg, H, CNOT, PIC_TYPE
prog = QProg()
prog << H(0) << CNOT(0, 1)
# Draw as text (default)
text_output = draw_qprog(prog)
print(text_output)
# Draw as LaTeX
latex_output = draw_qprog(prog, PIC_TYPE.LATEX)
# Draw with parameter values shown
text_with_params = draw_qprog(prog, param_show=True)
# Save to file
draw_qprog(prog, output_file="circuit.txt")