Skip to content

propaq.circuits

Circuit and rotation representations for both bases, the Qiskit and Cirq converters, and the registry for overriding a gate's decomposition.

See the circuits and gates guide.

circuits

Circuit representations and gate parameterizations for propaq.

Classes:

Name Description
PauliCircuit

Class representing a circuit in the Pauli representation.

MajoranaCircuit

Class representing a circuit in the Majorana representation.

SurrogatePauliCircuit

A Pauli circuit whose gates carry symbolic parameter indices instead of angles.

SurrogateMajoranaCircuit

A Majorana circuit whose gates carry symbolic parameter indices instead of angles.

PauliRotation

Class representing a gate in the Pauli representation, parameterized by a Pauli string and a rotation angle.

MajoranaRotation

Class representing a gate in the Majorana representation, parameterized by a Majorana monomial and a rotation angle.

SurrogateRotation

A Pauli rotation gate parameterized by either a symbolic parameter index

SurrogateMajoranaRotation

A Majorana rotation gate parameterized by either a symbolic parameter

AbstractRotation

A gate parameterized by a basis element and a rotation angle:

AbstractCircuit

A circuit as a list of layers of rotations, where a layer's rotations can be applied in parallel.

GateDecompositionWarning

Emitted when a gate is decomposed into native rotations via transpilation.

GateValidationError

Raised when a custom-registered gate's terms_fn disagrees with propaq's own

ParamSource

Describes how one propaq surrogate parameter slot is evaluated.

Functions:

Name Description
register_qiskit_gate

Registers a custom generator-based decomposition for the Qiskit instruction named

register_cirq_gate

Registers a custom generator-based decomposition for the given Cirq gate type,

pauli_rotation_generator

Build the (generator, unit coefficient) pair for an n-qubit Pauli label, for

Attributes:

Name Type Description
GateRep

Public alias of _Rep, for type-hinting a custom terms_fn's rep parameter.

GateRep module-attribute

GateRep = _Rep

Public alias of _Rep, for type-hinting a custom terms_fn's rep parameter.

PauliCircuit

PauliCircuit(rotations_or_layers: list[PauliRotation] | list[list[PauliRotation]])

Class representing a circuit in the Pauli representation.

The circuit is represented as a list of layers, where each layer is a list of gates that can be applied in parallel.

Construct a PauliCircuit from a list of rotations or a list of layers of rotations.

Methods:

Name Description
from_generators_and_angles

Construct a PauliCircuit from lists of generators and angles.

from_qiskit

Construct a PauliCircuit from a Qiskit QuantumCircuit.

from_cirq

Construct a PauliCircuit from a Cirq Circuit.

inverse

Return a new PauliCircuit with reversed order and negated angles (U-dagger).

Attributes:

Name Type Description
layers list[list[PauliRotation]]

The layers of the circuit, where each layer is a list of parameterized gates that can be applied in parallel.

rotations list[PauliRotation]

The flat list of all rotations in the circuit, in the order they are applied.

layers property

layers: list[list[PauliRotation]]

The layers of the circuit, where each layer is a list of parameterized gates that can be applied in parallel.

rotations property

rotations: list[PauliRotation]

The flat list of all rotations in the circuit, in the order they are applied.

from_generators_and_angles classmethod

from_generators_and_angles(generators: list[PauliString], angles: list[float])

Construct a PauliCircuit from lists of generators and angles.

Parameters:

Name Type Description Default
generators list[PauliString]

A list of PauliStrings.

required
angles list[float]

A list of angles.

required

Returns:

Type Description

A PauliCircuit initialized with the given generators and angles.

from_qiskit classmethod

from_qiskit(qc: QuantumCircuit) -> PauliCircuit

Construct a PauliCircuit from a Qiskit QuantumCircuit.

Gates in the native rotation basis (xx_plus_yy, p, rz, rx, ry, cp, x, swap) are converted directly. Any other gate is decomposed via Qiskit's transpiler into that basis first (see propaq.circuits._gates), which works for arbitrary unitary gates, including multi-qubit UnitaryGates, at the cost of a UserWarning and however many rotations the decomposition produces.

Parameters:

Name Type Description Default
qc QuantumCircuit

A Qiskit QuantumCircuit to convert.

required

Returns:

Type Description
PauliCircuit

A PauliCircuit initialized with the given Qiskit circuit.

from_cirq classmethod

from_cirq(circuit: Circuit) -> PauliCircuit

Construct a PauliCircuit from a Cirq Circuit.

Gates in the native rotation basis (ZPowGate, XPowGate, YPowGate, CZPowGate, SWAP, PhasedISwapPowGate) are converted directly. Any other gate is decomposed via Cirq's own decomposition protocol into that basis first (see propaq.circuits._cirq_gates), which works for arbitrary unitary gates.

Requires the optional cirq dependency: pip install propaq[cirq].

Parameters:

Name Type Description Default
circuit Circuit

A Cirq Circuit to convert. Qubits are indexed by their sorted order (sorted(circuit.all_qubits())), not by any coordinate value.

required

Returns:

Type Description
PauliCircuit

A PauliCircuit initialized with the given Cirq circuit.

inverse

inverse() -> PauliCircuit

Return a new PauliCircuit with reversed order and negated angles (U-dagger).

MajoranaCircuit

MajoranaCircuit(rotations_or_layers: list[MajoranaRotation] | list[list[MajoranaRotation]], n_modes: int)

Class representing a circuit in the Majorana representation.

The circuit is represented as a list of layers, where each layer is a list of gates that can be applied in parallel.

Construct a MajoranaCircuit from a list of rotations or a list of layers of rotations.

Methods:

Name Description
from_generators_and_angles

Construct a MajoranaCircuit from lists of generators and angles.

from_qiskit

Construct a MajoranaCircuit from a Qiskit QuantumCircuit.

from_cirq

Construct a MajoranaCircuit from a Cirq Circuit.

from_ffsim_orbital_rotation

Construct a MajoranaCircuit from an ffsim orbital rotation

from_ffsim_diag_coulomb_evolution

Construct a MajoranaCircuit from an ffsim diagonal Coulomb evolution

from_ffsim_ucj

Construct a MajoranaCircuit from an ffsim spin-balanced UCJ operator.

from_ffsim_uccsd

Construct a MajoranaCircuit from an ffsim restricted UCCSD operator, as a

inverse

Return a new MajoranaCircuit with reversed order and negated angles (U-dagger).

Attributes:

Name Type Description
n_modes int

The number of Majorana modes in the circuit.

layers list[list[MajoranaRotation]]

The layers of the circuit, where each layer is a list of parameterized gates that can be applied in parallel.

rotations list[MajoranaRotation]

The flat list of all rotations in the circuit, in the order they are applied.

n_modes instance-attribute

n_modes: int = n_modes

The number of Majorana modes in the circuit.

layers property

layers: list[list[MajoranaRotation]]

The layers of the circuit, where each layer is a list of parameterized gates that can be applied in parallel.

rotations property

rotations: list[MajoranaRotation]

The flat list of all rotations in the circuit, in the order they are applied.

from_generators_and_angles classmethod

from_generators_and_angles(generators: list[MajoranaMonomial], angles: list[float], n_modes: int)

Construct a MajoranaCircuit from lists of generators and angles.

Parameters:

Name Type Description Default
generators list[MajoranaMonomial]

A list of MajoranaMonomials.

required
angles list[float]

A list of angles.

required
n_modes int

The number of Majorana modes in the system.

required

Returns:

Type Description

A MajoranaCircuit initialized with the given generators and angles.

from_qiskit classmethod

from_qiskit(qc: QuantumCircuit, n_modes: int)

Construct a MajoranaCircuit from a Qiskit QuantumCircuit.

Gates in the native rotation basis (xx_plus_yy, p, rz, rx, ry, cp, x, swap) are converted directly. Any other gate is decomposed via Qiskit's transpiler into that basis first (see propaq.circuits._gates), which works for arbitrary unitary gates, including multi-qubit UnitaryGates, at the cost of a UserWarning and however many rotations the decomposition produces.

Parameters:

Name Type Description Default
qc QuantumCircuit

A Qiskit QuantumCircuit to convert.

required
n_modes int

The number of Majorana modes in the system.

required

Returns:

Type Description

A MajoranaCircuit initialized with the given Qiskit circuit.

from_cirq classmethod

from_cirq(circuit: Circuit, n_modes: int)

Construct a MajoranaCircuit from a Cirq Circuit.

Gates in the native rotation basis (ZPowGate, XPowGate, YPowGate, CZPowGate, SWAP, PhasedISwapPowGate) are converted directly. Any other gate is decomposed via Cirq's own decomposition protocol into that basis first (see propaq.circuits._cirq_gates), which works for arbitrary unitary gates.

Requires the optional cirq dependency: pip install propaq[cirq].

Parameters:

Name Type Description Default
circuit Circuit

A Cirq Circuit to convert. Qubits are indexed by their sorted order (sorted(circuit.all_qubits())), not by any coordinate value.

required
n_modes int

The number of Majorana modes in the system.

required

Returns:

Type Description

A MajoranaCircuit initialized with the given Cirq circuit.

from_ffsim_orbital_rotation classmethod

from_ffsim_orbital_rotation(mat: ndarray | tuple[ndarray | None, ndarray | None], norb: int, n_modes: int)

Construct a MajoranaCircuit from an ffsim orbital rotation (ffsim.apply_orbital_rotation).

Requires the optional ffsim dependency: pip install propaq[ffsim].

Parameters:

Name Type Description Default
mat ndarray | tuple[ndarray | None, ndarray | None]

The unitary orbital rotation matrix, or a (mat_alpha, mat_beta) pair for independent per-spin rotations. Use None for a spin sector to leave it untouched.

required
norb int

The number of spatial orbitals.

required
n_modes int

The number of Majorana modes in the system (4 * norb for a spinful system).

required

Returns:

Type Description

A MajoranaCircuit implementing the orbital rotation.

from_ffsim_diag_coulomb_evolution classmethod

from_ffsim_diag_coulomb_evolution(mat: ndarray | tuple[ndarray | None, ndarray | None, ndarray | None], time: float, norb: int, n_modes: int, orbital_rotation: ndarray | tuple[ndarray | None, ndarray | None] | None = None)

Construct a MajoranaCircuit from an ffsim diagonal Coulomb evolution (ffsim.apply_diag_coulomb_evolution).

Requires the optional ffsim dependency: pip install propaq[ffsim].

Parameters:

Name Type Description Default
mat ndarray | tuple[ndarray | None, ndarray | None, ndarray | None]

The diagonal Coulomb matrix, or a (mat_aa, mat_ab, mat_bb) triple. Use None for an entry to omit that spin interaction.

required
time float

The evolution time.

required
norb int

The number of spatial orbitals.

required
n_modes int

The number of Majorana modes in the system (4 * norb for a spinful system).

required
orbital_rotation ndarray | tuple[ndarray | None, ndarray | None] | None

An optional orbital rotation sandwiching the evolution (same conventions as from_ffsim_orbital_rotation's mat).

None

Returns:

Type Description

A MajoranaCircuit implementing the (rotated) diagonal Coulomb evolution.

from_ffsim_ucj classmethod

from_ffsim_ucj(op: UCJOpSpinBalanced, n_modes: int)

Construct a MajoranaCircuit from an ffsim spin-balanced UCJ operator.

Parameters:

Name Type Description Default
op UCJOpSpinBalanced

The UCJOpSpinBalanced to convert.

required
n_modes int

The number of Majorana modes in the system (4 * op.norb).

required

Returns:

Type Description

A MajoranaCircuit implementing the UCJ operator.

from_ffsim_uccsd classmethod

from_ffsim_uccsd(op: UCCSDOpRestricted, n_modes: int)

Construct a MajoranaCircuit from an ffsim restricted UCCSD operator, as a single first-order Trotter step of its generator T - T^dagger.

NOTE: This is an approximation, not the exact UCCSD operator.

Parameters:

Name Type Description Default
op UCCSDOpRestricted

The UCCSDOpRestricted (or UCCSDOpRestrictedReal) to convert.

required
n_modes int

The number of Majorana modes in the system (4 * norb).

required

Returns:

Type Description

A MajoranaCircuit implementing one Trotter step of the UCCSD operator.

inverse

inverse()

Return a new MajoranaCircuit with reversed order and negated angles (U-dagger).

SurrogatePauliCircuit

SurrogatePauliCircuit(layers: list[list[SurrogateRotation]])

A Pauli circuit whose gates carry symbolic parameter indices instead of angles.

Produced from a PauliCircuit (via from_pauli_circuit) or from bare generators (via from_generators_and_param_indices). Feed it to PauliSurrogatePropagator.build to compile a PauliSurrogateModel.

param_index values are user-assigned integers; params[i] at evaluate time is the angle for parameter index i. Multiple rotations may share the same index, meaning they share a single parameter.

Attributes:

Name Type Description
n_params int

Total number of distinct parameter indices used (max index + 1).

parameter_sources list[ParamSource]

One ParamSource per parameter index, populated by from_qiskit; empty for circuits built via the other constructors.

qiskit_parameters tuple

Distinct Parameters used, in first-seen order; populated by from_qiskit.

Construct a SurrogatePauliCircuit from a list of layers of surrogate rotations.

Methods:

Name Description
from_pauli_circuit

Construct from a PauliCircuit and a matching list of parameter indices.

from_generators_and_param_indices

Construct from lists of generators and corresponding parameter indices.

from_qiskit

Construct a SurrogatePauliCircuit from a Qiskit QuantumCircuit, which may

from_cirq

Construct a SurrogatePauliCircuit from a Cirq Circuit, which may be

layers property

layers: list[list[SurrogateRotation]]

Layers of surrogate rotations (same structure as PauliCircuit.layers).

rotations property

rotations: list[SurrogateRotation]

Flat list of all surrogate rotations in circuit order.

n_params property

n_params: int

Total number of distinct parameter indices (max param_index + 1).

from_pauli_circuit classmethod

from_pauli_circuit(circuit: PauliCircuit, param_indices: list[int | None]) -> SurrogatePauliCircuit

Construct from a PauliCircuit and a matching list of parameter indices.

Parameters:

Name Type Description Default
circuit PauliCircuit

A PauliCircuit whose rotations will be given symbolic indices.

required
param_indices list[int | None]

One entry per rotation in circuit.rotations order. An integer assigns that rotation a symbolic index; None keeps the rotation's own numeric angle from circuit instead.

required

Returns:

Type Description
SurrogatePauliCircuit

A SurrogatePauliCircuit with the same layer structure.

from_generators_and_param_indices classmethod

from_generators_and_param_indices(generators: list[PauliString], param_indices: list[int]) -> SurrogatePauliCircuit

Construct from lists of generators and corresponding parameter indices.

Each generator becomes a single-gate layer (no parallelism assumed).

Parameters:

Name Type Description Default
generators list[PauliString]

Pauli strings for each gate.

required
param_indices list[int]

Symbolic parameter index for each gate.

required

Returns:

Type Description
SurrogatePauliCircuit

A SurrogatePauliCircuit with one gate per layer.

from_qiskit classmethod

from_qiskit(qc: QuantumCircuit) -> SurrogatePauliCircuit

Construct a SurrogatePauliCircuit from a Qiskit QuantumCircuit, which may be parameterized with qiskit.circuit.Parameters. Each gate angle may be any affine (real-linear) combination of Parameters, e.g. 2*theta + phi + 1.

Gates in the native rotation basis (xx_plus_yy, p, rz, rx, ry, cp, x, swap) are converted directly. Any other gate is decomposed via Qiskit's transpiler into that basis first (see propaq.circuits._gates), which works for arbitrary unitary gates as long as any free Parameters survive the decomposition affinely, at the cost of a UserWarning and however many rotations the decomposition produces.

Parameters:

Name Type Description Default
qc QuantumCircuit

A Qiskit QuantumCircuit to convert.

required

Returns:

Type Description
SurrogatePauliCircuit

A SurrogatePauliCircuit. parameter_sources (length n_params) and

SurrogatePauliCircuit

qiskit_parameters (distinct Parameters used) are populated for later

SurrogatePauliCircuit

binding of qiskit Parameter values to param_index slots.

from_cirq classmethod

from_cirq(circuit: Circuit) -> SurrogatePauliCircuit

Construct a SurrogatePauliCircuit from a Cirq Circuit, which may be parameterized with sympy.Symbols. Each gate angle may be any affine (real-linear) combination of symbols, e.g. 2*theta + phi + 1.

Gates in the native rotation basis (ZPowGate, XPowGate, YPowGate, CZPowGate, SWAP, PhasedISwapPowGate) are converted directly. Any other gate is decomposed via Cirq's own decomposition protocol into that basis first (see propaq.circuits._cirq_gates), which works for arbitrary unitary gates as long as any free symbols survive the decomposition affinely.

Requires the optional cirq dependency: pip install propaq[cirq].

Parameters:

Name Type Description Default
circuit Circuit

A Cirq Circuit to convert. Qubits are indexed by their sorted order (sorted(circuit.all_qubits())), not by any coordinate value.

required

Returns:

Type Description
SurrogatePauliCircuit

A SurrogatePauliCircuit. parameter_sources (length n_params) and

SurrogatePauliCircuit

qiskit_parameters (distinct sympy Symbols used) are populated for

SurrogatePauliCircuit

later binding of symbol values to param_index slots.

SurrogateMajoranaCircuit

SurrogateMajoranaCircuit(layers: list[list[SurrogateMajoranaRotation]], n_modes: int)

A Majorana circuit whose gates carry symbolic parameter indices instead of angles.

Produced from a MajoranaCircuit (via from_majorana_circuit) or from bare generators (via from_generators_and_param_indices). Feed it to MajoranaSurrogatePropagator.build to compile a MajoranaSurrogateModel.

Attributes:

Name Type Description
n_modes

The number of Majorana modes (carried from the source circuit).

n_params int

Total number of distinct parameter indices used (max index + 1).

parameter_sources list[ParamSource]

One ParamSource per parameter index, populated by from_qiskit; empty for circuits built via the other constructors.

qiskit_parameters tuple

Distinct Parameters used, in first-seen order; populated by from_qiskit.

Construct a SurrogateMajoranaCircuit from a list of layers of surrogate rotations.

Methods:

Name Description
from_majorana_circuit

Construct from a MajoranaCircuit and a matching list of parameter indices.

from_generators_and_param_indices

Construct from lists of generators and corresponding parameter indices.

from_qiskit

Construct a SurrogateMajoranaCircuit from a Qiskit QuantumCircuit, which may

from_cirq

Construct a SurrogateMajoranaCircuit from a Cirq Circuit, which may be

layers property

layers: list[list[SurrogateMajoranaRotation]]

Layers of surrogate rotations.

rotations property

rotations: list[SurrogateMajoranaRotation]

Flat list of all surrogate rotations in circuit order.

n_params property

n_params: int

Total number of distinct parameter indices (max param_index + 1).

from_majorana_circuit classmethod

from_majorana_circuit(circuit: MajoranaCircuit, param_indices: list[int | None]) -> SurrogateMajoranaCircuit

Construct from a MajoranaCircuit and a matching list of parameter indices.

Parameters:

Name Type Description Default
circuit MajoranaCircuit

A MajoranaCircuit whose rotations will be given symbolic indices.

required
param_indices list[int | None]

One entry per rotation in circuit.rotations order. An integer assigns that rotation a symbolic index; None keeps the rotation's own numeric angle from circuit instead.

required

Returns:

Type Description
SurrogateMajoranaCircuit

A SurrogateMajoranaCircuit with the same layer structure.

from_generators_and_param_indices classmethod

from_generators_and_param_indices(generators: list[MajoranaMonomial], param_indices: list[int], n_modes: int) -> SurrogateMajoranaCircuit

Construct from lists of generators and corresponding parameter indices.

Parameters:

Name Type Description Default
generators list[MajoranaMonomial]

Majorana monomials for each gate.

required
param_indices list[int]

Symbolic parameter index for each gate.

required
n_modes int

Number of Majorana modes in the system.

required

Returns:

Type Description
SurrogateMajoranaCircuit

A SurrogateMajoranaCircuit with one gate per layer.

from_qiskit classmethod

from_qiskit(qc: QuantumCircuit, n_modes: int) -> SurrogateMajoranaCircuit

Construct a SurrogateMajoranaCircuit from a Qiskit QuantumCircuit, which may be parameterized with qiskit.circuit.Parameters. Each gate angle may be any affine (real-linear) combination of Parameters, e.g. 2*theta + phi + 1.

Gates in the native rotation basis (xx_plus_yy, p, rz, rx, ry, cp, x, swap) are converted directly. Any other gate is decomposed via Qiskit's transpiler into that basis first (see propaq.circuits._gates), which works for arbitrary unitary gates as long as any free Parameters survive the decomposition affinely, at the cost of a UserWarning and however many rotations the decomposition produces.

Parameters:

Name Type Description Default
qc QuantumCircuit

A Qiskit QuantumCircuit to convert.

required
n_modes int

The number of Majorana modes in the system.

required

Returns:

Type Description
SurrogateMajoranaCircuit

A SurrogateMajoranaCircuit. parameter_sources (length n_params) and

SurrogateMajoranaCircuit

qiskit_parameters (distinct Parameters used) are populated for later

SurrogateMajoranaCircuit

binding of qiskit Parameter values to param_index slots.

from_cirq classmethod

from_cirq(circuit: Circuit, n_modes: int) -> SurrogateMajoranaCircuit

Construct a SurrogateMajoranaCircuit from a Cirq Circuit, which may be parameterized with sympy.Symbols. Each gate angle may be any affine (real-linear) combination of symbols, e.g. 2*theta + phi + 1.

Gates in the native rotation basis (ZPowGate, XPowGate, YPowGate, CZPowGate, SWAP, PhasedISwapPowGate) are converted directly. Any other gate is decomposed via Cirq's own decomposition protocol into that basis first (see propaq.circuits._cirq_gates), which works for arbitrary unitary gates as long as any free symbols survive the decomposition affinely.

Requires the optional cirq dependency: pip install propaq[cirq].

Parameters:

Name Type Description Default
circuit Circuit

A Cirq Circuit to convert. Qubits are indexed by their sorted order (sorted(circuit.all_qubits())), not by any coordinate value.

required
n_modes int

The number of Majorana modes in the system.

required

Returns:

Type Description
SurrogateMajoranaCircuit

A SurrogateMajoranaCircuit. parameter_sources (length n_params) and

SurrogateMajoranaCircuit

qiskit_parameters (distinct sympy Symbols used) are populated for

SurrogateMajoranaCircuit

later binding of symbol values to param_index slots.

PauliRotation

PauliRotation(generator: GeneratorT, angle: float, is_intermediate: bool = False, qiskit_gate_idx: int | None = None)

Bases: AbstractRotation[PauliString]

Class representing a gate in the Pauli representation, parameterized by a Pauli string and a rotation angle.

The gate parameterization is given by:

\[ G = e^{-i \theta P / 2} \]

where \(P\) is a Pauli string and \(\theta\) is the rotation angle in radians (the same half-angle convention as Qiskit's RZ/CP gate parameters, enforced by the propagator regardless of what a naive dense-matrix exponential of \(P\) alone would suggest).

Construct a rotation from a generator and an angle.

Attributes:

Name Type Description
angle float

The rotation angle \(\theta\) in radians.

is_intermediate bool

Whether this rotation is an intermediate parameterization that should not

qiskit_gate_idx int | None

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

generator PauliString

The Pauli string \(P\) that generates the rotation.

angle instance-attribute

angle: float = angle

The rotation angle \(\theta\) in radians.

is_intermediate instance-attribute

is_intermediate: bool = is_intermediate

Whether this rotation is an intermediate parameterization that should not be truncated after. For example, if a particle number-conserving gate is divided into two rotations, the first rotation is intermediate and should not be truncated after, since this would potentially break the symmetry.

qiskit_gate_idx instance-attribute

qiskit_gate_idx: int | None = qiskit_gate_idx

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

generator instance-attribute

generator: PauliString

The Pauli string \(P\) that generates the rotation.

MajoranaRotation

MajoranaRotation(generator: GeneratorT, angle: float, is_intermediate: bool = False, qiskit_gate_idx: int | None = None)

Bases: AbstractRotation[MajoranaMonomial]

Class representing a gate in the Majorana representation, parameterized by a Majorana monomial and a rotation angle.

The gate parameterization is given by:

\[ G = e^{-i \theta M / 2} \]

where \(M\) is a Majorana monomial and \(\theta\) is the rotation angle in radians.

Construct a rotation from a generator and an angle.

Attributes:

Name Type Description
angle float

The rotation angle \(\theta\) in radians.

is_intermediate bool

Whether this rotation is an intermediate parameterization that should not

qiskit_gate_idx int | None

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

generator MajoranaMonomial

The Majorana monomial \(M\) that generates the rotation.

angle instance-attribute

angle: float = angle

The rotation angle \(\theta\) in radians.

is_intermediate instance-attribute

is_intermediate: bool = is_intermediate

Whether this rotation is an intermediate parameterization that should not be truncated after. For example, if a particle number-conserving gate is divided into two rotations, the first rotation is intermediate and should not be truncated after, since this would potentially break the symmetry.

qiskit_gate_idx instance-attribute

qiskit_gate_idx: int | None = qiskit_gate_idx

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

generator instance-attribute

generator: MajoranaMonomial

The Majorana monomial \(M\) that generates the rotation.

SurrogateRotation

SurrogateRotation(generator: PauliString, param_index: int | None = None, angle: float | None = None, is_intermediate: bool = False, qiskit_gate_idx: int | None = None)

A Pauli rotation gate parameterized by either a symbolic parameter index or a concrete numeric angle, depending on which one is given.

If param_index is not None, the surrogate propagator records which trig factors each term accumulates without binding to a specific angle value, resolved later at SurrogateModel.evaluate time. If angle is not None, cos/sin of the angle are computed immediately during propagation and folded directly into each term's scalar, exactly like PauliRotation's numeric propagation. Exactly one of the two must be given.

Attributes:

Name Type Description
generator PauliString

The Pauli string generating the rotation.

param_index int | None

Index into the parameter vector supplied at evaluate time, or None if angle is given instead.

angle float | None

A concrete rotation angle baked in at build time, or None if param_index is given instead.

is_intermediate bool

Whether this gate is intermediate (controls truncation).

qiskit_gate_idx int | None

Index of the originating Qiskit gate, or None.

Construct a SurrogateRotation from a generator and either a parameter index or an angle.

SurrogateMajoranaRotation

SurrogateMajoranaRotation(generator: MajoranaMonomial, param_index: int | None = None, angle: float | None = None, is_intermediate: bool = False, qiskit_gate_idx: int | None = None)

A Majorana rotation gate parameterized by either a symbolic parameter index or a concrete numeric angle, depending on which one is given.

If param_index is not None, the surrogate propagator records which trig factors each term accumulates without binding to a specific angle value, resolved later at SurrogateModel.evaluate time. If angle is not None, cos/sin of the angle are computed immediately during propagation and folded directly into each term's scalar, exactly like MajoranaRotation's numeric propagation. Exactly one of the two must be given.

Attributes:

Name Type Description
generator MajoranaMonomial

The Majorana monomial generating the rotation.

param_index int | None

Index into the parameter vector supplied at evaluate time, or None if angle is given instead.

angle float | None

A concrete rotation angle baked in at build time, or None if param_index is given instead.

is_intermediate bool

Whether this gate is intermediate (controls truncation).

qiskit_gate_idx int | None

Index of the originating Qiskit gate, or None.

Construct a SurrogateMajoranaRotation from a generator and either a parameter index or an angle.

AbstractRotation

AbstractRotation(generator: GeneratorT, angle: float, is_intermediate: bool = False, qiskit_gate_idx: int | None = None)

Bases: Generic[GeneratorT]

A gate parameterized by a basis element and a rotation angle:

\[ G = e^{-i \theta g / 2} \]

where \(g\) is the generator and \(\theta\) is the angle in radians.

Construct a rotation from a generator and an angle.

Attributes:

Name Type Description
generator GeneratorT

The generator \(g\) that parameterizes the rotation.

angle float

The rotation angle \(\theta\) in radians.

is_intermediate bool

Whether this rotation is an intermediate parameterization that should not

qiskit_gate_idx int | None

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

generator instance-attribute

generator: GeneratorT = generator

The generator \(g\) that parameterizes the rotation.

angle instance-attribute

angle: float = angle

The rotation angle \(\theta\) in radians.

is_intermediate instance-attribute

is_intermediate: bool = is_intermediate

Whether this rotation is an intermediate parameterization that should not be truncated after. For example, if a particle number-conserving gate is divided into two rotations, the first rotation is intermediate and should not be truncated after, since this would potentially break the symmetry.

qiskit_gate_idx instance-attribute

qiskit_gate_idx: int | None = qiskit_gate_idx

Index of the originating Qiskit gate in the source circuit, or None for non-Qiskit circuits.

AbstractCircuit

AbstractCircuit(rotations_or_layers: list[RotationT] | list[list[RotationT]])

Bases: Generic[RotationT]

A circuit as a list of layers of rotations, where a layer's rotations can be applied in parallel.

Construct a circuit from a list of rotations or a list of layers of rotations.

Methods:

Name Description
append

Append a rotation to the circuit.

inverse

Return a new circuit with reversed layer order and negated angles (U-dagger).

Attributes:

Name Type Description
layers list[list[RotationT]]

The layers of the circuit, where each layer's gates can be applied in parallel.

rotations list[RotationT]

The flat list of all rotations in the circuit, in the order they are applied.

layers property

layers: list[list[RotationT]]

The layers of the circuit, where each layer's gates can be applied in parallel.

rotations property

rotations: list[RotationT]

The flat list of all rotations in the circuit, in the order they are applied.

append

append(rotation: RotationT, *, new_layer: bool = True) -> None

Append a rotation to the circuit.

Parameters:

Name Type Description Default
rotation RotationT

The rotation to append.

required
new_layer bool

If True (default), the rotation starts its own layer; if False, it is added to the last existing layer.

True

inverse

inverse() -> AbstractCircuit[RotationT]

Return a new circuit with reversed layer order and negated angles (U-dagger).

GateDecompositionWarning

Bases: UserWarning

Emitted when a gate is decomposed into native rotations via transpilation.

Suppressed by default since decomposition can happen often (e.g. inside a hot loop or surrogate build) and is expected behavior, not a bug. Re-enable it with warnings.filterwarnings("always", category=propaq.circuits.GateDecompositionWarning).

GateValidationError

Bases: Exception

Raised when a custom-registered gate's terms_fn disagrees with propaq's own decomposition path for the same gate.

ParamSource dataclass

ParamSource(parameter: Parameter | None, scale: float)

Describes how one propaq surrogate parameter slot is evaluated.

If parameter is not None, the slot's value at evaluate time is scale * value_of(parameter). If parameter is None, the slot is a fixed constant equal to scale, independent of any Qiskit Parameter.

Attributes:

Name Type Description
parameter Parameter | None

The Qiskit Parameter this slot tracks, or None for a fixed constant.

scale float

The affine coefficient applied to parameter's value (or the constant itself).

register_qiskit_gate

register_qiskit_gate(name: str, terms_fn: QiskitTermsFn, *, validate: bool = True) -> None

Registers a custom generator-based decomposition for the Qiskit instruction named name, bypassing propaq's transpile-based decomposition fallback for that gate.

terms_fn(instr, q_indices, width, rep) -> list[list[tuple[generator, angle]]] must return the same shape as propaq's own built-in dispatch branches (see e.g. the "cp" case in propaq.circuits._gates.gate_terms), built via helpers such as propaq.circuits.pauli_rotation_generator. It must be correctly parametric in width/q_indices rather than hardcoding absolute qubit positions - _decompose's recursive sub-instruction handling relies on the same contract.

Parameters:

Name Type Description Default
name str

The Qiskit instruction name to override (e.g. "cp").

required
terms_fn QiskitTermsFn

The generator-based decomposition function, called as terms_fn(instr, q_indices, width, rep).

required
validate bool

Whether to check terms_fn's output against propaq's built-in dispatch (GateValidationError on mismatch) the first time this gate is dispatched, to catch a malformed decomposition early.

True

register_cirq_gate

register_cirq_gate(gate_type: type, terms_fn: CirqTermsFn, *, validate: bool = True) -> None

Registers a custom generator-based decomposition for the given Cirq gate type, bypassing propaq's cirq.decompose fallback for that gate. Matched by exact type(op.gate), not isinstance/subclass, registering a base class will not also match its subclasses.

terms_fn(op, q_indices, width, rep) -> list[list[tuple[generator, angle]]] must return the same shape as propaq's own built-in dispatch branches (see e.g. the ZZPowGate case in propaq.circuits._cirq_gates.cirq_gate_terms), built via helpers such as propaq.circuits.pauli_rotation_generator. It must be correctly parametric in width/q_indices rather than hardcoding absolute qubit positions.

Parameters:

Name Type Description Default
gate_type type

The exact Cirq gate type to override (matched by type(op.gate), not isinstance/subclass).

required
terms_fn CirqTermsFn

The generator-based decomposition function, called as terms_fn(op, q_indices, width, rep).

required
validate bool

Whether to check terms_fn's output against propaq's built-in dispatch (GateValidationError on mismatch) the first time this gate is dispatched, to catch a malformed decomposition early.

True

pauli_rotation_generator

pauli_rotation_generator(rep: _Rep, label: str) -> tuple[Any, float]

Build the (generator, unit coefficient) pair for an n-qubit Pauli label, for use in a custom terms_fn passed to register_qiskit_gate/register_cirq_gate. Works for both the Pauli and Majorana representations.

Parameters:

Name Type Description Default
rep _Rep

The representation to build the generator in; should be the rep argument terms_fn itself was called with.

required
label str

An n-qubit Pauli label, e.g. "XIZ".

required

Returns:

Type Description
Any

A (generator, unit_coefficient) pair, where generator is a term in

float

rep.termsum_cls and unit_coefficient is its coefficient for a unit

tuple[Any, float]

rotation angle.