Skip to content

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

python
Qubit(qubit: int)

Parameters

ParameterTypeDescription
qubitintThe integer address (index) of the qubit.

Methods

MethodReturn TypeDescription
get_qubit_addr()intReturns 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

python
from pyqpanda3.core import Qubit

q0 = Qubit(0)
q1 = Qubit(1)

print(q0)               # Qubit(0)
print(int(q0))          # 0
print(q0.get_qubit_addr())  # 0

See Also

  • CBit -- Classical bit class.
  • QCircuit -- Circuits operate on qubit indices.

CBit

Represents a classical bit used to store measurement outcomes. Like Qubit, it is a lightweight handle identified by a numeric address.

Signature

python
CBit(addr: int)

Note: The parameter is positional only — keyword calling CBit(addr=0) is not supported.

Parameters

ParameterTypeDescription
addrintThe integer address (index) of the classical bit.

Methods

MethodReturn TypeDescription
get_cbit_addr()intReturns 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

python
from pyqpanda3.core import CBit

c0 = CBit(0)
c1 = CBit(1)

print(c0)               # CBit(0)
print(int(c0))          # 0
print(c0.get_cbit_addr())  # 0

See Also

  • Qubit -- Quantum bit class.
  • measure -- Measurement operations map qubits to classical bits.

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

python
Operation()

Attributes

AttributeTypeDescription
m_operation_typeOpTypeThe type of this operation (Gate, Measure, etc.).
m_target_qubitslist[int]Indices of target qubits.
m_control_qubitslist[int]Indices of control qubits.
m_measure_cbitslist[int]Classical bit indices associated with measurement.

Methods

MethodReturn TypeDescription
is_controlled()boolReturns True if this operation has at least one control qubit.

Examples

python
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())        # True

See Also

  • QGate -- Quantum gate class, inherits from Operation.
  • OpType -- Enumeration of operation types.

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.

python
# Typical construction via factory functions
gate = H(0)                    # single-qubit gate
gate = CNOT(0, 1)              # two-qubit gate
gate = RX(0, 3.14)             # parameterized gate

Methods

qubits_num

python
qubits_num() -> int

Returns the total number of qubits this gate acts on (both target and control qubits).

qubits

python
qubits() -> list[int]

Returns the target qubit indices.

control_qubits

python
control_qubits() -> list[int]

Returns the control qubit indices for this gate.

target_qubits

python
target_qubits() -> list[int]

Returns the target qubit indices.

dagger

python
dagger() -> QGate

Returns a new QGate that is the Hermitian conjugate (adjoint) of this gate. The original gate is not modified.

is_dagger

python
is_dagger() -> bool

Returns True if this gate is in its dagger (adjoint) form.

power

python
power(k: int) -> QGate

Returns a new gate representing this gate raised to the integer power k.

ParameterTypeDescription
kintThe exponent.

clear_control

python
clear_control() -> None

Removes all control qubits from this gate.

control

python
control(qubit: int) -> QGate
control(qubits: list[int]) -> QGate

Adds one or more control qubits to this gate. Returns a new QGate with the control qubits added. The original gate is not modified.

ParameterTypeDescription
qubitintA single control qubit index to add.
qubitslist[int]A list of control qubit indices to add.

matrix

python
matrix(expanded: bool = False) -> numpy.ndarray

Returns the matrix representation of this gate. When expanded is True, the matrix is expanded to the full qubit space including control qubits.

ParameterTypeDescription
expandedboolWhether to return the expanded matrix (default False).

gate_type

python
gate_type() -> GateType

Returns the GateType enum value for this gate.

remap

python
remap(mapping: dict[int, int]) -> QGate
remap(mapping: list[int]) -> QGate

Returns a new gate with qubit indices remapped according to the provided mapping.

ParameterTypeDescription
mappingdict[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

python
parameters() -> list[float]

Returns the list of parameters for this gate (empty for non-parameterized gates).

set_parameters

python
set_parameters(params: list[float]) -> None

Sets the parameters for this gate.

ParameterTypeDescription
paramslist[float]The new parameter values.

name

python
name() -> str

Returns the name of this gate.

Examples

python
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


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

python
QCircuit()                    # empty circuit
QCircuit(qubits_num: int)     # circuit with a specified register size
QCircuit(circuit: QCircuit)   # copy constructor

Parameters

ParameterTypeDescription
qubits_numintNumber of qubits to allocate in the circuit register.
circuitQCircuitAn existing circuit to copy.

Methods

size

python
size() -> int

Returns the number of operations in the circuit.

append

python
append(gate: QGate) -> None
append(circuit: QCircuit) -> None

Appends a gate or another circuit to this circuit.

ParameterTypeDescription
gateQGateA quantum gate to append.
circuitQCircuitA circuit to append.

clear

python
clear() -> None

Removes all operations from this circuit.

matrix

python
matrix() -> numpy.ndarray

Returns the unitary matrix representation of the entire circuit.

qubits

python
qubits() -> list[int]

Returns the list of qubit indices used in this circuit.

target_qubits

python
target_qubits() -> list[int]

Returns the target qubit indices used in this circuit.

control_qubits

python
control_qubits() -> list[int]

Returns the control qubit indices used in this circuit.

dagger

python
dagger() -> QCircuit

Returns a new QCircuit where every gate is replaced by its Hermitian conjugate. The original circuit is not modified.

control

python
control(qubit: int) -> QCircuit
control(qubits: list[int]) -> QCircuit

Adds one or more control qubits to the entire circuit. Returns a new QCircuit. The original circuit is not modified.

ParameterTypeDescription
qubitintA single control qubit index to add.
qubitslist[int]A list of control qubit indices to add.

clear_control

python
clear_control() -> None

Removes all control qubits from this circuit.

set_name

python
set_name(name: str) -> None

Sets a custom name for the circuit.

ParameterTypeDescription
namestrThe name to assign.

name

python
name() -> str

Returns the name of the circuit.

operations

python
operations() -> list

Returns all operations in the circuit as a list (may contain QGate and nested QCircuit objects).

gate_operations

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

ParameterTypeDescription
only_q2boolIf True, return only two-qubit gates (default False).

num_2q_gate

python
num_2q_gate() -> int

Returns the count of two-qubit gates in the circuit.

depth

python
depth(only_q2: bool = False) -> int

Returns the circuit depth (number of sequential gate layers). When only_q2 is True, only two-qubit gates are considered.

ParameterTypeDescription
only_q2boolIf True, compute depth using only two-qubit gates (default False).

count_ops

python
count_ops(only_q2: bool = False) -> dict[str, int]

Returns a dictionary mapping gate names to their occurrence counts.

ParameterTypeDescription
only_q2boolIf True, count only two-qubit gates (default False).

get_register_size

python
get_register_size() -> int

Returns the size of the qubit register allocated for this circuit.

expand

python
expand() -> QCircuit

Returns a new circuit with all nested sub-circuits expanded into a flat gate sequence.

originir

python
originir(precision: int = 8) -> str

Returns the OriginIR string representation of the circuit.

ParameterTypeDescription
precisionintFloating-point precision for parameter values (default 8).

remap

python
remap(mapping: list[int]) -> QCircuit
remap(mapping: dict[int, int]) -> QCircuit

Returns a new circuit with qubit indices remapped according to the provided mapping.

ParameterTypeDescription
mappinglist[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.

python
circuit << gate         # append a QGate
circuit << other_circ   # append a QCircuit

Special Methods

  • __str__() -- Returns a text-based circuit diagram.
  • __lshift__() -- Implements the << operator for appending gates and circuits.

Examples

Basic circuit construction

python
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

python
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())               # 3

Composing circuits

python
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())  # 4

Analysis: depth and gate count

python
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

python
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

python
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

python
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

python
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

python
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 QCircuit

Parameters

ParameterTypeDescription
qubits_numintNumber of qubits to allocate.
progQProgAn existing program to copy.
originir_srcstrOriginIR source string or file path.
is_fileboolIf True, originir_src is treated as a file path (default False).
nodeQCircuitA circuit to initialize the program with.

Methods

qubits_num

python
qubits_num() -> int

Returns the number of qubits used in the program.

cbits_num

python
cbits_num() -> int

Returns the number of classical bits used in the program.

qubits

python
qubits() -> list[int]

Returns the qubit indices used in the program.

cbits

python
cbits() -> list[int]

Returns the classical bit indices used in the program.

operations

python
operations() -> list

Returns all operations in the program (gates, measurements, sub-programs, etc.).

gate_operations

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

ParameterTypeDescription
only_q2boolIf True, return only two-qubit gates (default False).

name

python
name() -> str

Returns the name of the program.

get_measure_nodes

python
get_measure_nodes() -> list

Returns all measurement nodes in the program.

flatten

python
flatten() -> QProg

Returns a new program with all nested sub-programs expanded into a flat sequence.

to_circuit

python
to_circuit() -> QCircuit

Converts the program to a QCircuit (excluding measurement operations).

count_ops

python
count_ops(only_q2: bool = False) -> dict[str, int]

Returns a dictionary mapping operation names to their counts.

ParameterTypeDescription
only_q2boolIf True, count only two-qubit gates (default False).

depth

python
depth(only_q2: bool = False) -> int

Returns the program depth (number of sequential gate layers).

ParameterTypeDescription
only_q2boolIf True, compute depth using only two-qubit gates (default False).

clear

python
clear() -> None

Removes all operations from the program.

append

python
append(gate: QGate) -> None
append(circuit: QCircuit) -> None
append(prog: QProg) -> None
append(measure: MeasureNode) -> None

Appends an operation to the program. Accepts gates, circuits, programs, and measurement nodes.

ParameterTypeDescription
gateQGateA quantum gate to append.
circuitQCircuitA circuit to append.
progQProgA program to append.
measureMeasureNodeA measurement node to append.

remap

python
remap(remap_qubits: list[int], remap_cbits: list[int]) -> QProg
remap(remap_qubits: dict[int, int], remap_cbits: dict[int, int] = {}) -> QProg

Returns a new program with qubit and classical bit indices remapped.

ParameterTypeDescription
remap_qubitslist[int] or dict[int, int]Mapping for qubit indices.
remap_cbitslist[int] or dict[int, int]Mapping for classical bit indices.

originir

python
originir(precision: int = 8) -> str

Returns the OriginIR string representation of the program.

ParameterTypeDescription
precisionintFloating-point precision for parameter values (default 8).

originbis

python
originbis() -> bytes

Returns the OriginBIS binary serialization of the program.

from_originbis

python
from_originbis(data: bytes) -> None

Deserializes the program from OriginBIS binary data.

ParameterTypeDescription
databytesOriginBIS binary data.

to_instruction

python
to_instruction(backend: str, offset: int = 1, is_scheduling: bool = False) -> str

Converts the program into a JSON instruction string compatible with the specified backend.

ParameterTypeDescription
backendstrThe chip backend name for instruction formatting.
offsetintQubit index offset (default 1).
is_schedulingboolWhether to include scheduling information (default False).

Operators

<< (left shift)

Appends a gate, circuit, program, or measurement node. Returns the program itself, enabling chaining.

python
prog << gate          # append a QGate
prog << circuit       # append a QCircuit
prog << other_prog    # append a QProg
prog << measure_node  # append a MeasureNode

Special Methods

  • __str__() -- Returns a text-based circuit diagram of the program.

Examples

Basic program with measurements

python
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

python
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

python
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

python
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

python
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

python
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

python
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

python
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))  # 1

See Also


draw_qprog

Draws a quantum program or circuit as a text diagram or LaTeX source. This function accepts both QProg and QCircuit objects.

Signature

python
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, ...) -> str

Parameters

ParameterTypeDefaultDescription
qprogQProgThe quantum program to draw
circuitQCircuitThe quantum circuit to draw
pPIC_TYPEPIC_TYPE.TEXTOutput format: PIC_TYPE.TEXT for ASCII text or PIC_TYPE.LATEX for LaTeX
expend_mapdict[str, int]{'all': 1}Map of qubit indices to expand (use {'all': 1} to expand all)
param_showboolFalseWhether to display gate parameter values in the output
with_logoboolFalseWhether to include the pyqpanda3 logo in the output
line_lengthint100Maximum characters per line in the text output
output_filestr''File path to save the output (empty string prints to console)
encodestr'utf-8'Character encoding for the output file

Returns

str — The rendered circuit diagram as a string.

Examples

python
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")

Released under the MIT License.