cqlib.circuits package

Subpackages

Submodules

cqlib.circuits.barrier module

This module provides the definition of the Barrier class, a part of the quantum circuit handling system within the cqlib framework. The Barrier class is used to create synchronization points in quantum circuits.

A barrier in quantum computing is crucial for preventing the quantum compiler from making certain optimizations that could change the intended execution order of operations. This is particularly important in scenarios where the sequence of quantum gates is critical for the algorithm’s correctness.

Classes:
Barrier: Implements a synchronization barrier across multiple qubits

within a quantum circuit.

Usage:

The Barrier class is typically used during the assembly of a quantum circuit where gate operations need strict adherence to their defined sequence. It ensures that all operations before the barrier are completed before any operations following the barrier begin execution.

class cqlib.circuits.barrier.Barrier(num_qubits: int, label: str | None = None)

Bases: Instruction

Represents a quantum barrier that prevents gate reordering by the compiler.

A barrier is used in quantum circuits to ensure that certain optimizations, such as gate reordering, do not alter the intended execution order across the specified qubits. This is crucial for maintaining the correct quantum state transformations when sequence-dependent gate operations are critical.

cqlib.circuits.circuit module

Quantum circuit

class cqlib.circuits.circuit.Circuit(qubits: Qubit | int | Sequence[Qubit | int], parameters: Sequence[Parameter | str] | None = None)

Bases: object

Represents a quantum circuit that can perform various quantum operations.

add_parameter(parameter: Parameter | str)

Adds a new parameter to the quantum circuit. If the parameter already exists, it raises an error.

Parameters:

parameter (Parameter | str) – The parameter to add, can be an instance of Parameter or a string name. If a string is provided, a new Parameter instance will be created from it.

add_qubit(qubit: Qubit | int)

Adds a qubit to the circuit, ensuring it does not already exist.

Parameters:

qubit (IntQubit) – The qubit to add, specified as an integer index or a Qubit object.

append(instruction: Instruction, qubits: Qubit | int | Sequence[Qubit | int])

append instruction to circuit

Parameters:
  • instruction (Instruction) – The instruction to be appended.

  • qubits (Qubits) – The qubit(s) to which the instruction is applied.

append_instruction_data(instruction_data: InstructionData)

append instruction_data to circuit

Parameters:

instruction_data (InstructionData) – The instruction_data to be appended.

as_str(qcis_compliant: bool = False)

Exports the circuit as a string format, with an option to make the output QCIS-compliant.

Parameters:

qcis_compliant (bool) – If True, the output will conform to QCIS standards; if False, it will retain the original format with composite gates.

assign_parameters(values: dict[str | cqlib.circuits.parameter.Parameter, float | int] | Sequence[float | int] | None = None, inplace: bool = False, cache_params: bool = False, **kwargs)

Sets the values of specified parameters in the quantum circuit. This method allows parameters to be set using a dictionary or directly via keyword arguments.

Args:
values (dict[str | Parameter, float | int], optional): A

dictionary where keys are parameters (either as Parameter objects or their string identifiers) and values are the numerical values (float or int) to set. If a parameter is specified as a string, it must be a valid identifier and already exist in the circuit’s parameter list.

inplace (bool): create new circuit or not? cache_params (bool): cache parameters or not? for SimpleSimulator value cache. **kwargs: Additional parameters and their values provided as

keyword arguments. This is useful for directly setting values when calling the method.

Example:
>>> from cqlib.circuits import Circuit, Parameter
>>> import numpy
>>> params = [Parameter(f'theta_{i}') for i in range(3)]
>>> circuit = Circuit(2, parameters=params)
>>> circuit.rx(0, params[0])
>>> circuit.ry(0, params[0] + params[1] * params[2])
>>> circuit.qcis
'RX Q0 theta_0
RY Q0 theta_0 + theta_1*theta_2’
>>> c1 = circuit.assign_parameters({'theta_0': 1, 'theta_1': 2, 'theta_2': 0.2})
>>> c1.qcis
RX Q0 1
RY Q0 1.4
>>> c2 = circuit.assign_parameters([0.1, 2, 0.2])
>>> c2.qcis
RX Q0 0.1
RY Q0 0.5
>>> c3 = circuit.assign_parameters(theta_0=1, theta_1=0.2, theta_2=0.3)
>>> c3.qcis
'RX Q0 1
RY Q0 1.06’
>>> c4 = circuit.assign_parameters(theta_1=2)
>>> c4.qcis
'RX Q0 theta_0
RY Q0 theta_0 + 2*theta_2’
>>> c5 = circuit.assign_parameters(numpy.array([1, 2, 0.2]))
>>> c5.qcis
'RX Q0 1

RY Q0 1.4’

This method updates the internal dictionary of parameters to reflect the new values, allowing these parameters to be used with their new values in subsequent operations within the circuit.

barrier(*qubits: Qubit | int)

Inserts a barrier into the circuit that affects all specified qubits. A barrier ensures that no optimizations or rearrangements are done across this point in the circuit, maintaining the order of operations.

Parameters:

qubits (IntQubit) – The qubits to which the barrier is applied.

barrier_all()

Insert barrier instruction for all qubits in the circuit.

ccx(control_qubit_1: Qubit | int, control_qubit_2: Qubit | int, target_qubit: Qubit | int)

Applies the CCX gate (Toffoli gate, controlled-controlled-X) using two control qubits and one target qubit.

Parameters:
  • control_qubit_1 (IntQubit) – The first control qubit.

  • control_qubit_2 (IntQubit) – The second control qubit.

  • target_qubit (IntQubit) – The target qubit where the X operation is applied conditionally.

property circuit_data

Circuit data

copy() Circuit

Copy the circuit.

crx(control_qubit: Qubit | int, target_qubit: Qubit | int, theta: float | Parameter)

Applies the controlled-RX gate (controlled rotation around the X-axis) between two qubits.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the rotation is applied.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

cry(control_qubit: Qubit | int, target_qubit: Qubit | int, theta: float | Parameter)

Applies the controlled-RY gate (controlled rotation around the Y-axis) between two qubits.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the rotation is applied.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

crz(control_qubit: Qubit | int, target_qubit: Qubit | int, theta: float | Parameter)

Applies the controlled-RZ gate (controlled rotation around the Z-axis) between two qubits.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the rotation is applied.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

cx(control_qubit: Qubit | int, target_qubit: Qubit | int)

Applies the CX gate (controlled-X, CNOT) between a control qubit and a target qubit.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the NOT operation is applied conditionally.

cy(control_qubit: Qubit | int, target_qubit: Qubit | int)

Applies the CY (Controlled-Y) gate to the specified control and target qubits.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the CY operation is applied conditionally.

cz(control_qubit: Qubit | int, target_qubit: Qubit | int)

Applies the CZ gate (controlled-Z) between a control qubit and a target qubit.

Parameters:
  • control_qubit (IntQubit) – The control qubit.

  • target_qubit (IntQubit) – The target qubit where the Z operation is applied conditionally.

depth() int

Max length of critical path

draw(category='text', qubit_order: list[int | cqlib.circuits.qubit.Qubit] | None = None, **kwargs)

Draws the quantum circuit in the specified format.

Parameters:
  • category (str) – The type of drawing to produce. Supported categories are: - ‘text’: Draws the circuit as ASCII art. - ‘mpl’: Draws the circuit using Matplotlib for a graphical representation.

  • qubit_order (list[int | Qubit], optional) – A list specifying the order of qubits in the output. If None, the default order is used.

  • **kwargs – Additional keyword arguments that are passed to the specific drawing function.

Returns:

  • For ‘text’, it returns a string representing the circuit in text format.

  • For ‘mpl’, it typically displays or returns a Matplotlib figure object.

Return type:

The return value depends on the selected category

Raises:

ValueError – If an unsupported category is provided.

fsim(qubit1: Qubit | int, qubit2: Qubit | int, theta: float | Parameter | None = None, phi: float | Parameter | None = None)

Applies the FSIM gate (fermionic simulation gate) to two specified qubits.

Parameters:
  • qubit1 (IntQubit) – The first qubit to apply the FSIM gate.

  • qubit2 (IntQubit) – The second qubit to apply the FSIM gate.

  • theta (float | Parameter) – Phase angle theta.

  • phi (float | Parameter) – Phase angle phi.

h(qubit: Qubit | int)

Applies the Hadamard gate (H) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the Hadamard gate.

i(qubit: Qubit | int, t: int)

Applies the I gate to a specified qubit.

Parameters:
  • qubit (IntQubit) – The qubit to apply the Hadamard gate.

  • t (int) – The duration the gate acts, in integer units of 0.5 ns.

insert(instruction: Instruction, qubits: Qubit | int | Sequence[Qubit | int], index: int | None = None)

Insert an instruction into the circuit at a specified index.

Parameters:
  • instruction (Instruction) – The instruction to be inserted.

  • qubits (Qubits) – The qubit(s) to which the instruction is applied.

  • index (int, optional) – The index at which to insert the instruction. Defaults to None, which appends at the end.

property instruction_sequence: list[cqlib.circuits.instruction_data.InstructionData]

Accesses the list of all instruction data objects stored in the circuit.

Returns:

The sequence of instructions added to the circuit,

each represented by an InstructionData object.

Return type:

list[InstructionData]

classmethod load(qcis: str) Circuit

Loads a quantum circuit from a QCIS string.

Parameters:

qcis (str) – A string containing quantum circuit instructions, where each line represents a circuit operation. The format for each line is “GATE QUBITS [PARAMETERS]”, e.g., “H Q0 Q1”, “CX Q0 Q1”, “RZ Q0 0.5”.

Returns:

A quantum circuit object constructed based on the input string.

Return type:

Circuit

Raises:

ValueError – If the input string is improperly formatted or contains unknown gate operations.

Example

>>> circuit_description = "H Q0\nCX Q0 Q1\nM Q0"
>>> c = Circuit.load(circuit_description)
>>> print(c)
Circuit with 3 instructions
measure(qubits: Qubit | int | Sequence[Qubit | int])

Measures the specified qubits and collapses their quantum state into classical bits.

Parameters:

qubits (Qubits) – The qubits to measure, can be a single qubit or a list of qubits.

measure_all()

Measures all qubits in the circuit that have not yet been measured.

property num_qubits: int

Return number of qubits.

property parameters: list[cqlib.circuits.parameter.Parameter]

Retrieves a list of all parameters currently in the quantum circuit.

Returns:

A list containing the parameters used in the circuit.

Return type:

list[Parameter]

property parameters_value: dict[cqlib.circuits.parameter.Parameter, Union[float, int]]

Retrieves a list of all parameters currently in the quantum circuit.

Returns:

parameters

Return type:

dict[Parameter, Union[float, int]]

property qcis: str

Generates a qcis string of all instructions in the circuit.

property qubits: list[cqlib.circuits.qubit.Qubit]

circuit qubits

qubits_path() dict[cqlib.circuits.qubit.Qubit, list[cqlib.circuits.instruction_data.InstructionData]]

Constructs a path of operations for each qubit.

rx(qubit: Qubit | int, theta: float | Parameter)
Applies the RX gate (rotation around the X-axis) to a specified

qubit with a given angle.

Parameters:
  • qubit (IntQubit) – The qubit to apply the RX gate.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

rxy(qubit: Qubit | int, phi: float | Parameter, theta: float | Parameter)
Applies the RX gate (rotation around the X-axis) to a specified

qubit with a given angle.

Parameters:
  • qubit (IntQubit) – The qubit to apply the RX gate.

  • phi (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

ry(qubit: Qubit | int, theta: float | Parameter)

Applies the RY gate (rotation around the Y-axis) to a specified qubit with a given angle.

Parameters:
  • qubit (IntQubit) – The qubit to apply the RY gate.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

rz(qubit: Qubit | int, theta: float | Parameter)

Applies the RZ gate (rotation around the Z-axis) to a specified qubit with a given angle.

Parameters:
  • qubit (IntQubit) – The qubit to apply the RZ gate.

  • theta (Union[float, Parameter]) – The rotation angle in radians or as a symbolic parameter.

s(qubit: Qubit | int)

Applies the S gate (phase gate) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the S gate.

sd(qubit: Qubit | int)

Applies the S-dagger gate (inverse S gate) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the S-dagger gate.

swap(qubit1: Qubit | int, qubit2: Qubit | int)

Applies the SWAP gate to exchange the states of two specified qubits.

Parameters:
  • qubit1 (IntQubit) – The first qubit.

  • qubit2 (IntQubit) – The second qubit.

t(qubit: Qubit | int)

Applies the T gate (π/8 gate) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the T gate.

td(qubit: Qubit | int)

Applies the TD gate (-π/8 gate) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the T gate.

to_qasm2() str

Convert the Circuit object to an OpenQASM 2.0 formatted string.

Example

>>> circuit = Circuit(1)
>>> circuit.h(0)
>>> # Add gates and operations to the circuit
>>> qasm_code = circuit.to_qasm2()
>>> print(qasm_code)
u(qubit: Qubit | int, theta: float | Parameter, phi: float | Parameter, lam: float | Parameter)

Applies the U gate to a specified qubit.

Parameters:
  • qubit (IntQubit) – The target qubit to which the U gate is applied.

  • theta (float | Parameter) – The rotation angle theta (θ) around the Bloch sphere.

  • phi (float | Parameter) – The phase angle phi (φ) for the first Z-axis rotation.

  • lam (float | Parameter) – The phase angle lambda (λ) for the final Z-axis rotation.

x(qubit: Qubit | int)

Applies the X gate (Pauli X, flip gate) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the X gate.

x2m(qubit: Qubit | int)

Applies the X2M gate to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the X2M gate.

x2p(qubit: Qubit | int)

Applies the X2P gate to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the X2P gate.

xy(qubit: Qubit | int, theta: float | Parameter)

Applies the XY gate (generalized rotation around an axis in the XY plane) to a specified qubit.

Parameters:
  • qubit (IntQubit) – The qubit to apply the XY gate.

  • theta (Union[float, Parameter]) – The rotation angle around the XY axis.

xy2m(qubit: Qubit | int, theta: float | Parameter)

Applies the XY2M gate to a specified qubit.

Parameters:
  • qubit (IntQubit) – The qubit to apply the XY2M gate.

  • theta (Union[float, Parameter]) – The rotation angle for the root operation.

xy2p(qubit: Qubit | int, theta: float | Parameter)

Applies the XY2P gate to a specified qubit.

Parameters:
  • qubit (IntQubit) – The qubit to apply the XY2P gate.

  • theta (Union[float, Parameter]) – The rotation angle for the root operation.

y(qubit: Qubit | int)

Applies the Y gate (Pauli Y) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the Y gate.

y2m(qubit: Qubit | int)

Applies the Y2M gate to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the Y2M gate.

y2p(qubit: Qubit | int)

Applies the Y2P gate to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the Y2P gate.

z(qubit: Qubit | int)

Applies the Z gate (Pauli Z) to a specified qubit.

Parameters:

qubit (IntQubit) – The qubit to apply the Z gate.

cqlib.circuits.dag module

Circuits as Directed Acyclic Graphs.

cqlib.circuits.dag.circuit_to_dag(circuit: Circuit) PyDiGraph

Convert a quantum circuit into a Directed Acyclic Graph (DAG).

Each operation in the circuit is added as a node in the DAG. Directed edges are created between nodes to maintain the operational dependencies determined by the qubits each operation acts upon. This ensures that operations are ordered correctly relative to the qubits they use.

Parameters:

circuit (Circuit) – The quantum circuit to convert, containing a sequence of operations.

Returns:

The directed acyclic graph representation of the circuit.

Return type:

nx.DiGraph

cqlib.circuits.dag.dag_to_circuit(dag: PyDiGraph) Circuit

Converts a Directed Acyclic Graph (DAG) back into a quantum circuit. The DAG is expected to have nodes representing quantum operations (InstructionData) and edges defining the order of these operations.

Parameters:

dag (nx.DiGraph) – The DAG to convert, where nodes are operations and edges represent execution dependency.

Returns:

A quantum circuit reconstructed from the DAG.

Return type:

Circuit

cqlib.circuits.dag.topological_layers(graph: PyDiGraph) list[list[rustworkx.NodeIndices | int]]

Perform topological sorting to decompose a directed acyclic graph (DAG) into layers of nodes.

This function implements a Kahn’s algorithm-based approach to determine the hierarchical layers of nodes in a DAG. Each layer contains nodes that can be processed simultaneously in dependency resolution scenarios.

Parameters:

graph (PyDiGraph) – The input directed acyclic graph represented as a PyDiGraph object from the rustworkx library.

Returns:

A list of lists where each inner list represents

a layer of node IDs.

Return type:

list[list[NodeIndices]]

cqlib.circuits.dag.topological_sort(graph, /)

Return the topological sort of node indices from the provided graph

Parameters:

graph (PyDiGraph) – The DAG to get the topological sort on

Returns:

A list of node indices topologically sorted.

Return type:

NodeIndices

Raises:

DAGHasCycle – if a cycle is encountered while sorting the graph

cqlib.circuits.instruction module

Generic quantum instruction.

class cqlib.circuits.instruction.Instruction(name: str, num_qubits: int, params: List[Parameter | float | complex] | None = None, label: str | None = None)

Bases: object

Generic quantum instruction.

copy() Instruction

Copy the Instruction.

is_supported_by_qcis = True
to_qcis(qubits: Sequence)

Prevents usage of this method for instructions that QCIS supports.

Do not call this method if QCIS supports the instruction. Instead, override this method to provide the necessary implementation for instructions that QCIS does not support.

Parameters:

qubits (list | tuple) – Qubits affected by this instruction.

Raises:
  • RuntimeError – If called for an instruction that QCIS supports.

  • NotImplementedError – If called for an instruction that QCIS does

  • not support, and you have not provided an implementation.

cqlib.circuits.instruction_data module

Generic quantum instruction data.

class cqlib.circuits.instruction_data.InstructionData(instruction: Instruction, qubits: Sequence[Bit])

Bases: NamedTuple

InstructionData represents a quantum instruction, including the type of instruction and the qubits it affects.

instruction: Instruction

Alias for field number 0

qubits: Sequence[Bit]

Alias for field number 1

cqlib.circuits.measure module

Measure gate.

class cqlib.circuits.measure.Measure(label: str | None = None)

Bases: Instruction

Represents a measurement instruction in a quantum circuit.

cqlib.circuits.parameter module

parameters in the quantum circuit

class cqlib.circuits.parameter.Parameter(symbol: str | Parameter | Expr)

Bases: object

Instruction Parameter Class.

Represents a symbolic parameter within a quantum circuit. It supports arithmetic operations and symbolic manipulations using the sympy library.

property base_params
Returns the base parameters as a list of Parameter instances, extracting symbols

if the parameter is a compound expression.

Returns:

A list of base parameters.

Return type:

List[Parameter]

copy() Parameter

copy the Parameter.

exp()

Calculate the exponent of this parameter (e^parameter).

Returns:

A new Parameter instance representing the exponential

of the original parameter.

Return type:

Parameter

property symbol: Symbol

Returns the sympy symbol associated with this Parameter.

Returns:

The sympy expression of the symbol.

Return type:

Expr

value(params: dict) Expr | Any

Evaluate the parameter symbol with specific numerical values provided in a dictionary.

This method uses lambdify to ensure that if the input values are PyTorch tensors, the operations are performed using PyTorch’s backend, preserving the computational graph and gradients.

Parameters:

params (dict) – A dictionary mapping parameter objects or their string representations to numerical values.

Returns:

The result of the symbol after substitution. If inputs are Tensors, returns a Tensor.

Return type:

Expr | Any

cqlib.circuits.qubit module

Quantum bit.

class cqlib.circuits.qubit.Qubit(index: int)

Bases: Bit

Quantum bit.

cqlib.circuits.utils module

utils

Module contents

Quantum Circuit Module