Skip to content

API reference

This page is generated from the public Python package. The source docstrings are the contract for signatures, return values, errors, complexity notes, and small executable examples.

The homepage and concepts pages explain how the pieces fit together; use this page when you already know the object or method you want to look up.

The classical-shadow surface is available at the top level through Snapshots, StabilizerState, PauliSnapshotArrays, CliffordSnapshotArrays, and shadow_bound. Their docstrings specify the sampling protocols, array shapes, estimator restrictions, and memory/ordering contracts.

tencirpauli

Public Python API for TenCirPauli.

__version__: str = '0.5.0' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

DEFAULT_MAX_BYTES = 16 * 1024 * 1024 * 1024 module-attribute

HybridTerm = _base.HybridTerm module-attribute

__all__ = ['DEFAULT_MAX_BYTES', 'AdditiveCharge', 'AdditiveSymmetryAnalysis', 'BosonOperator', 'BosonTerm', 'BosonWord', 'COOMatrix', 'CSRMatrix', 'CanonicalizationResult', 'ChargeSector', 'CliffordSnapshotArrays', 'ComputationalBasisState', 'FermionOperator', 'FermionQubitMapping', 'FermionTerm', 'FermionWord', 'GeneralCommutingGroupingResult', 'HybridOperator', 'HybridTerm', 'MVPPlan', 'MajoranaOperator', 'MajoranaProduct', 'MajoranaTerm', 'MajoranaWord', 'OperatorSpace', 'PauliOperator', 'PauliPhase', 'PauliProduct', 'PauliSnapshotArrays', 'PauliTerm', 'PauliWord', 'ProductBlochState', 'ProfiledExpectation', 'PropagationBatch', 'PropagationBatchValueAndGradient', 'PropagationChannelParameter', 'PropagationCircuit', 'PropagationCircuitValueAndGradient', 'PropagationProfile', 'PropagationValueAndGradient', 'QWCGroupingResult', 'QuditProduct', 'QuditWeylOperator', 'QuditWeylTerm', 'QuditWeylWord', 'SPPSCircuit', 'SPPSEstimate', 'SPPSValueEstimate', 'Snapshots', 'StabilizerCode', 'StabilizerErrorKind', 'StabilizerState', 'U1Circuit', 'U1CircuitValueAndGradient', 'U1Sector', 'Z2SymmetryAnalysis', 'ZeroState', '__version__', 'backend_mvp', 'shadow_bound'] module-attribute

AdditiveCharge

Immutable exact integer-valued diagonal charge on an OperatorSpace.

The mapping arguments use local-axis indices as dictionary keys. Their values define the contribution of that axis to the charge on an occupation-basis state::

Q = offset + sum(fermion_weight[m] * n_m)
            + sum(boson_weight[m] * n_m)
            + sum(qubit_level_charge[j, level_j])
            + sum(qudit_weight[j] * spin_z_level[j])

fermions={mode: weight} assigns weight * n_mode with n_mode in {0, 1}. bosons={mode: weight} assigns weight * n_mode with an arbitrary non-negative boson occupation. qubits={index: (level_0, level_1)} explicitly assigns the two charge values for the computational basis levels |0> and |1>. Unlisted axes have zero weight. offset is added once to every basis-state eigenvalue, so bosons={0: -1}, offset=1 represents 1 - n_0.

qudits={site: weight} multiplies the canonical integer-normalized spin-z spectrum: for odd dimension d it is (d - 1) / 2, ..., -(d - 1) / 2; for even d it is d - 1, d - 3, ..., -(d - 1). Arbitrary per-level boson or qudit lookup tables are not part of this API.

This class represents an exact additive charge and the condition [operator, Q] = 0. It is not a modular occupation-parity constraint and it is not a Pauli Z2SymmetryAnalysis. Charges are the input to :meth:sector and :func:analyze_charge.

layout_fingerprint: Tuple[Tuple[str, int, int], ...] property

Return the axis layout required by operators using this charge.

The fingerprint is deterministic and can be compared with another operator-space fingerprint before constructing a sector.

as_operator(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> _StructuredOperator

Materialize the charge generator as a structured operator.

Returns:

Type Description
_StructuredOperator

A canonical operator whose diagonal eigenvalue on each basis state

_StructuredOperator

is the charge value. The result preserves the charge's operator

_StructuredOperator

space and deterministic term ordering.

Raises:

Type Description
MemoryError

If the estimated operator workspace exceeds max_bytes.

as_pauli() -> PauliOperator

Materialize a pure-qubit charge as a Pauli operator.

The qubit level pair (level_0, level_1) is decomposed into an identity coefficient and a Z coefficient. Fermion, boson, and qudit charges are rejected because they are not Pauli operators.

sector(value: int, *, boson_cutoffs: Optional[Mapping[object, object]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'ChargeSector'

Select one exact charge value as a reusable finite sector plan.

Parameters:

Name Type Description Default
value int

Required charge eigenvalue.

required
boson_cutoffs Optional[Mapping[object, object]]

Optional inclusive upper occupation bound for each boson mode. Every boson mode must have a finite cutoff when a finite sector basis is needed.

None
max_bytes Optional[int]

Best-effort bound for the rank/unrank plan workspace.

DEFAULT_MAX_BYTES

Returns:

Name Type Description
A 'ChargeSector'

class:ChargeSector with deterministic mixed-radix ordering.

Examples:

>>> import tencirpauli as tcp
>>> space = tcp.OperatorSpace(qubits=2)
>>> charge = tcp.AdditiveCharge(space, qubits={0: (0, 1), 1: (0, 1)})
>>> charge.sector(1).dimension
2

AdditiveSymmetryAnalysis

Lightweight exact commutator result for one additive charge.

is_conserved is true exactly when the analyzed operator commutes with the diagonal charge, [operator, charge] = 0, after native canonicalization and aggregation. commutator_term_count is the number of surviving canonical terms in that commutator; zero therefore means exact cancellation, not merely a small numerical residual. This result describes additive-charge conservation only and does not discover Pauli Z2 generators or occupation-parity sectors.

ChargeSector

Immutable rank/unrank plan for simultaneous additive charge constraints.

Each constraint is a (AdditiveCharge, target_value) pair. The sector enumerates only finite occupation-basis states of the common :class:~tencirpauli.OperatorSpace whose additive charge eigenvalues equal all requested targets. The basis rows contain one local occupation per operator-space axis, ordered as fermions, bosons, qubits, then qudits; boson axes require inclusive finite cutoffs.

The ordering is operator_space_axis0_msb_mixed_radix and is shared by rank, unrank, basis_states and restricted matrix targets. ChargeSector is an occupation-space restriction, not Pauli Z2 tapering: it does not accept Pauli generators, remove qubits, or transform a non-diagonal stabilizer. An operator passed to restrict_charge must preserve every selected charge sector.

rank(occupations: Sequence[object]) -> int

Return the deterministic rank of a selected basis occupation.

Parameters:

Name Type Description Default
occupations Sequence[object]

One non-negative occupation per OperatorSpace axis, in local_dimensions order.

required

Returns:

Type Description
int

An integer in [0, dimension). No basis array is materialized.

Raises:

Type Description
ValueError

If the occupations have the wrong length, exceed a local dimension, or violate any charge constraint.

unrank(index: int) -> Tuple[int, ...]

Return the occupation tuple at a deterministic sector index.

Parameters:

Name Type Description Default
index int

Zero-based index in the restricted sector ordering.

required

Returns:

Type Description
int

One occupation per operator-space axis. This operation does not

...

materialize any preceding basis state.

Raises:

Type Description
IndexError

If index is outside [0, dimension).

basis_states(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Materialize all selected occupations as a read-only uint64 array.

The result has shape (dimension, len(local_dimensions)) and follows the same ordering as :meth:rank and :meth:unrank. This is an explicit potentially large allocation; use max_bytes to guard it.

GeneralCommutingGroupingResult dataclass

A deterministic algebraic commuting partition.

Terms in each group commute as operators, but the result intentionally does not provide a common tensor-product measurement basis. Use this mode for algebraic grouping or downstream measurement schemes that handle general commuting sets separately.

QWCGroupingResult dataclass

A deterministic qubit-wise commuting measurement partition.

groups contains indices into the canonical operator terms. bases gives the required single-qubit basis code per group, where 0 means identity and 1/2/3 mean X/Y/Z. Use :meth:reconstruct to convert computational-basis samples after that basis rotation into term values.

reconstruct(group_index: int, bitstrings: np.ndarray[Any, Any]) -> np.ndarray[Any, Any]

Reconstruct eigenvalues for one QWC group from rotated samples.

Parameters:

Name Type Description Default
group_index int

Index of the group whose terms should be reconstructed.

required
bitstrings ndarray[Any, Any]

A C-contiguous numpy.int8 array with shape (shots, nqubits) after applying the group's basis rotations. Values must be binary; validation runs in Rust.

required

Returns:

Type Description
ndarray[Any, Any]

An int8 array of shape (shots, group_size) containing

ndarray[Any, Any]

eigenvalues in {-1, +1}, in canonical term order.

Raises:

Type Description
IndexError

If group_index is not a valid group.

TypeError

If bitstrings is not a C-contiguous numpy.int8 array.

ValueError

If the sample shape or binary-value contract is invalid.

COOMatrix dataclass

Deterministic coordinate-format sparse matrix arrays.

row, column and data have equal length, and shape gives the logical matrix shape. Entries are already aggregated and ordered by the producing operator. Use :meth:to_scipy for SciPy sparse interop.

value: np.ndarray[Any, Any] property

Return data under the conventional sparse-matrix name value.

to_scipy() -> Any

Convert to a SciPy COO matrix.

CSRMatrix dataclass

Deterministic compressed-sparse-row matrix arrays.

indptr, indices and data follow the standard CSR contract and shape gives the logical matrix shape. Use :meth:to_scipy for SciPy sparse interop.

value: np.ndarray[Any, Any] property

Return data under the conventional sparse-matrix name value.

to_scipy() -> Any

Convert to a SciPy CSR matrix.

MVPPlan

Bases: Protocol

Minimal common protocol for public matrix-free operator plans.

MajoranaOperator

Immutable deterministic sparse operator in the Majorana algebra.

Input products are canonicalized, duplicate words are aggregated, exact zero coefficients are removed, and surviving terms are sorted lexicographically by generator indices. A MajoranaOperator with n_modes represents n_modes complex-fermion modes and 2*n_modes Majorana generators; indices 2*m and 2*m + 1 belong to complex mode m.

Additive particle-number or spin charges are defined on that underlying fermion-mode layout, so use :meth:to_fermion before calling analyze_charge or restrict_charge. For Pauli Z2 symmetry discovery and tapering, map directly with :meth:map_fermions and then use :meth:~tencirpauli.PauliOperator.find_z2_symmetries or :meth:~tencirpauli.PauliOperator.taper_z2. These are distinct from an occupation-parity sector; the current Majorana facade has no separate direct parity-sector restriction.

terms: Tuple[MajoranaTerm, ...] property

Return immutable nonzero terms in deterministic lexicographic order.

term_count: int property

Return the number of nonzero canonical terms.

from_terms(n_modes: int, terms: Iterable[Tuple[Sequence[object], complex]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator' classmethod

Construct from arbitrary raw Majorana factor sequences.

Each input term is (indices, coefficient). Repeated indices are reduced with the exact Majorana sign before duplicate words are aggregated.

from_indices(n_modes: int, indices: Sequence[object], coefficient: complex = 1.0, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator' classmethod

Construct one operator term from an arbitrary generator sequence.

Examples:

>>> import tencirpauli as tcp
>>> operator = tcp.MajoranaOperator.from_indices(1, [0, 1])
>>> operator.term_count
1

to_dict() -> Dict[Tuple[int, ...], complex]

Return canonical index tuples without constructing Majorana terms.

add(other: 'MajoranaOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return the exact canonical sum of two equal-mode operators.

scale(coefficient: complex, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return a new operator with every coefficient multiplied by coefficient.

multiply(other: 'MajoranaOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return the exact product and aggregate equal output words.

commutator(other: 'MajoranaOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return the exact commutator self * other - other * self.

anticommutator(other: 'MajoranaOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return the exact anticommutator self * other + other * self.

adjoint(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Return the exact coefficient-conjugated operator adjoint.

is_hermitian(tolerance: float = 0.0) -> bool

Return whether the operator equals its adjoint within tolerance.

to_fermion(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> FermionOperator

Expand exactly into the canonical ladder-operator algebra.

Each degree-d Majorana word can produce up to 2**d fermion branches. The expansion is guarded by max_bytes before native allocation and returns a canonical :class:FermionOperator.

map_fermions(mapping: Union[str, Any] = 'jordan_wigner', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Any

Map directly to qubits through a named or reusable mapping plan.

mapping may be "jordan_wigner", "parity", "bravyi_kitaev", or a :class:FermionQubitMapping instance. The Majorana expansion is handled in one batched path.

compile(target: str, *, storage: Literal['lazy', 'eager'] = 'lazy', mapping: Union[str, Any] = 'jordan_wigner', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Any

Compile a mapped Majorana operator to a named Hamiltonian target.

Supported targets are the same as :meth:PauliOperator.compile after mapping: dense, coo, csr, native_mvp, and backend_mvp. The mapping name and source term count are attached to reusable plan metadata.

MajoranaProduct dataclass

Coefficient-free result of a canonical Majorana word product.

MajoranaTerm dataclass

One canonical Majorana word and its complex coefficient.

MajoranaWord dataclass

Canonical phase-free product of Majorana generators.

Majorana indices use 2 * mode for the creation-like generator and 2 * mode + 1 for the annihilation-like generator. indices is strictly increasing; raw products should be constructed with :meth:from_indices so the fermionic sign is retained.

degree: int property

Return the number of generators in the canonical word.

is_identity: bool property

Return whether this word contains no Majorana generator.

from_indices(n_modes: int, indices: Sequence[object]) -> 'MajoranaProduct' classmethod

Canonicalize a raw generator sequence and retain its fermionic sign.

Returns a :class:MajoranaProduct because sorting and cancelling repeated generators can contribute a sign of +1 or -1.

multiply(other: 'MajoranaWord') -> 'MajoranaProduct'

Multiply two canonical words and return the canonical sign.

adjoint() -> 'MajoranaProduct'

Return the word adjoint and its exact reversal sign.

FermionQubitMapping

Immutable occupation-encoding plan for JW, parity, or BK mapping.

The plan maps n_modes fermion occupations to the same number of qubits over GF(2), and stores the inverse transform plus a deterministic CNOT synthesis. Public mapped operators use mode-zero-increasing ordering and the qubit0_msb_matrix basis convention.

name: str property

Return the stable mapping name.

encoding_matrix: np.ndarray[Any, Any] property

Return the read-only binary matrix for q = B n (mod 2).

inverse_encoding_matrix: np.ndarray[Any, Any] property

Return the read-only inverse transform from qubits to occupations.

cnot_operations: Tuple[Tuple[int, int], ...] property

Return deterministic (control, target) CNOT provenance.

clifford_operations: np.ndarray[Any, Any] property

Return the read-only CNOT array in synthesis order.

jordan_wigner(n_modes: int, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionQubitMapping' classmethod

Build the identity occupation encoding used by Jordan-Wigner.

n_modes determines both the fermion-mode and qubit counts. max_bytes guards the mapping matrices and native plan workspace.

parity(n_modes: int, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionQubitMapping' classmethod

Build the prefix-parity occupation encoding.

bravyi_kitaev(n_modes: int, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionQubitMapping' classmethod

Build the deterministic Fenwick-interval Bravyi-Kitaev encoding.

from_name(name: str, n_modes: int, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionQubitMapping' classmethod

Build a mapping plan from jordan_wigner, parity, or bravyi_kitaev.

encode_occupation(occupation: Sequence[int]) -> Tuple[int, ...]

Encode one binary occupation vector with the frozen GF(2) convention.

Parameters:

Name Type Description Default
occupation Sequence[int]

Length-n_modes sequence containing only 0 and 1.

required

Returns:

Type Description
Tuple[int, ...]

The encoded length-nqubits binary vector.

map_pauli(operator: PauliOperator, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> PauliOperator

Conjugate a pure fermion-axis Pauli operator by the mapping CNOTs.

The returned operator has n_modes qubits, exact conjugation signs, deterministic term ordering, and aggregated duplicate words.

map_fermion_operator(operator: Any, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> PauliOperator

Map a pure FermionOperator to a canonical Pauli operator.

Fermion ladder products are expanded through one batched Jordan-Wigner path and then conjugated by this mapping's encoding.

Examples:

>>> import tencirpauli as tcp
>>> number = tcp.FermionOperator.from_terms(
...     1, [(((0, "create"), (0, "annihilate")), 1.0)]
... )
>>> mapped = tcp.FermionQubitMapping.jordan_wigner(1).map_fermion_operator(number)
>>> mapped.nqubits
1

map_majorana_operator(operator: Any, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> PauliOperator

Map a Majorana operator without materializing a fermion expansion.

This is the preferred path for Majorana input because the native batch kernel aggregates mapped words directly and preserves exact signs.

map_hybrid(operator: HybridOperator, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Union[HybridOperator, PauliOperator]

Map only the fermion axes of a compatible hybrid operator.

Boson, qubit, and qudit axes remain in their original operator-space ordering. A pure-qubit result is returned as :class:PauliOperator; mixed results remain :class:HybridOperator.

CanonicalizationResult dataclass

Deterministic batch canonicalization with backend reduction metadata.

PauliOperator dataclass

Deterministic sparse Pauli operator with exact-zero aggregation.

Terms are canonicalized on construction, duplicate words are aggregated, exact zeros are removed, and surviving terms are sorted deterministically. All matrix and MVP targets use the package's documented qubit ordering and honor the best-effort max_bytes guard.

terms: Tuple[PauliTerm, ...] property

Return canonical terms, materializing a native result on demand.

term_count: int property

Return the number of nonzero canonical algebraic terms.

empty(nqubits: int) -> 'PauliOperator' classmethod

Construct the additive identity on nqubits.

from_terms(nqubits: int, terms: Iterable[Tuple[PauliInput, complex]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator' classmethod

Construct and canonicalize mixed string, code, or word terms.

Each term is (word, coefficient) where word may be an IXYZ string, a code sequence, or a :class:PauliWord. All words must have width nqubits.

Examples:

>>> import tencirpauli as tcp
>>> operator = tcp.PauliOperator.from_terms(
...     2, [("XX", 0.5), ("YY", 0.5)]
... )
>>> operator.compile("dense").shape
(4, 4)

from_code_arrays(structures: Sequence[Sequence[int]], coefficients: Sequence[complex], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator' classmethod

Construct from a batch of code rows and complex coefficients.

This is the preferred constructor for large array-backed inputs because it makes one coarse-grained native canonicalization call.

canonicalize_batch(nqubits: int, terms: Iterable[Tuple[PauliInput, complex]]) -> CanonicalizationResult classmethod

Canonicalize a batch while retaining reduction mapping and phases.

Code-array and string inputs are phase-free, so every returned phase multiplier is PauliPhase.PLUS_ONE. Exact-zero aggregated keys are retained here for backend structural plans; from_terms removes them for static operators.

canonicalize_code_arrays(structures: Sequence[Sequence[int]], coefficients: Sequence[complex]) -> CanonicalizationResult classmethod

Canonicalize code arrays without per-term Python object conversion.

canonicalize_code_arrays_numpy(structures: Sequence[Sequence[int]], coefficients: Sequence[complex]) -> CanonicalizationArrayResult classmethod

Return contiguous canonicalization arrays without Python term objects.

from_strings(terms: Iterable[Tuple[str, complex]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator' classmethod

Construct an operator from strings, inferring the common qubit count.

to_dict() -> Dict[str, complex]

Return canonical Pauli strings and coefficients without term objects.

add(other: 'PauliOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Add two operators and aggregate exact duplicate keys.

scale(scalar: complex, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Multiply all coefficients by a finite complex scalar.

multiply(other: 'PauliOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Multiply operators, absorbing exact Pauli phases into coefficients.

commutator(other: 'PauliOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Return self * other - other * self.

anticommutator(other: 'PauliOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Return self * other + other * self.

adjoint(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Return the coefficient-conjugated adjoint operator.

is_hermitian(tolerance: float = 0.0) -> bool

Validate Hermiticity using an explicit non-negative tolerance.

analyze_charge(charge: 'AdditiveCharge', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'AdditiveSymmetryAnalysis'

Analyze exact additive-charge conservation using [H, Q].

charge must be a matching pure-qubit AdditiveCharge. This method checks a diagonal integer-valued charge and is separate from :meth:find_z2_symmetries, which discovers Pauli generators that may be non-diagonal in the computational basis.

conserves(charge: 'AdditiveCharge', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> bool

Return whether this Pauli operator exactly conserves charge.

restrict_charge(sector: Union['ChargeSector', 'U1Sector'], *, storage: 'ChargeStorage' = 'lazy', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Union['ChargeRestrictedOperator', 'U1RestrictedOperator']

Restrict an exactly conserved Pauli operator to an occupation sector.

U1Sector and equivalent canonical qubit-number charge sectors use the packed U(1) backend. The default CPU-native storage is lazy. This keeps computational-basis states satisfying additive charge targets; it is not Pauli Z2 Clifford tapering and does not remove qubits.

group_commuting(mode: str = 'qubit_wise', algorithm: str = 'largest_first', max_matrix_entries: int = 10000000) -> 'GroupingResult'

Return a deterministic QWC or general-commuting grouping result.

Examples:

>>> import tencirpauli as tcp
>>> operator = tcp.PauliOperator.from_terms(2, [("XX", 1.0), ("ZZ", 1.0)])
>>> result = operator.group_commuting(mode="qubit_wise")
>>> result.term_count
2

find_z2_symmetries(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'Z2SymmetryAnalysis'

Discover deterministic Pauli Z2 generators of this operator.

Every returned generator squares to identity and commutes with the complete Pauli operator. The generators can contain X and Y factors, so this is a Pauli-space symmetry search rather than a search for diagonal occupation charges. Fermionic operators should be mapped to a chosen Pauli encoding before using this method.

taper_z2(sector: Sequence[int], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Find Pauli Z2 symmetries and taper a selected eigenvalue sector.

This is a convenience composition of find_z2_symmetries().tapering_plan(sector).transform_operator(self). It changes Pauli basis and removes qubits; it does not select an additive occupation sector or automatically combine with one.

restrict_u1(sector: 'U1Sector', *, storage: 'ChargeStorage' = 'lazy', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'U1RestrictedOperator'

Deprecated alias for :meth:restrict_charge with a U1Sector.

compatibility_matrix(mode: str = 'qubit_wise', max_entries: int = 10000000) -> np.ndarray[Any, Any]

Return a bounded dense matrix, limited by compatibility entries.

incompatibility_edges(mode: str = 'qubit_wise', max_edges: int = 10000000) -> Tuple[Tuple[int, int], ...]

Return streaming edges, limited by the number of output edges.

dense(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Materialize a bounded complex128 dense Hamiltonian matrix.

coo(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'COOMatrix'

Compile deterministic, duplicate-aggregated COO arrays.

csr(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'CSRMatrix'

Compile deterministic CSR arrays from the canonical COO stream.

mvp(state: Sequence[complex], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Apply the Hamiltonian to a one-dimensional complex128 state.

backend_mvp_plan(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'BackendMVPPlan'

Compile a versioned pure-array plan for backend execution.

native_mvp_plan(*, storage: "Literal['lazy', 'eager']" = 'lazy', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'NativeMVPPlan'

Compile a reusable Rust-native matrix-free MVP plan.

to_scipy_linear_operator(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Any

Compile one native MVP plan and expose it to SciPy.

compile(target: str, *, storage: "Literal['lazy', 'eager']" = 'lazy', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'CompileResult'

Compile one named Hamiltonian target.

Supported targets are "dense", "coo", "csr", "native_mvp", and "backend_mvp". Dense and sparse targets materialize arrays; MVP targets return reusable plans.

tensor_product(other: 'PauliOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'PauliOperator'

Return the ordinary tensor product with left axes first.

PauliPhase

Bases: IntEnum

Exact phase labels returned by phase-free Pauli multiplication.

The integer values encode +1, +i, -1, and -i in that order. Use :attr:value_complex when a numerical coefficient is needed.

value_complex: complex property

Return the enumerated phase as a Python complex scalar.

PauliProduct dataclass

Result of multiplying two phase-free Pauli words.

PauliTerm dataclass

One canonical Pauli word and its complex128-compatible coefficient.

PauliWord dataclass

A phase-free Pauli word using external codes 0=I, 1=X, 2=Y, 3=Z.

The packed representation uses qubit zero as its least-significant bit; matrix-producing APIs explicitly convert that layout to TensorCircuit's qubit-zero-is-MSB convention. Words are immutable and canonical, so their packed arrays can be safely reused as dictionary keys and native inputs.

weight: int property

Return the number of non-identity sites.

support: Tuple[int, ...] property

Return non-identity qubit indices in ascending order.

from_codes(codes: Sequence[int]) -> 'PauliWord' classmethod

Construct one word from ordered 0..3 I/X/Y/Z codes.

The input order is public qubit order, with qubit zero first. The returned word stores the equivalent packed symplectic representation.

from_string(value: str) -> 'PauliWord' classmethod

Construct one word from an IXYZ string in qubit order.

batch_from_codes(nqubits: int, structures: Iterable[Sequence[int]]) -> Tuple['PauliWord', ...] classmethod

Convert many same-width code rows with one native batch call.

Each structure must have length nqubits and contain only integer codes 0..3. Results preserve input order.

to_codes() -> Tuple[int, ...]

Return immutable external codes in public qubit order.

to_string() -> str

Return the canonical IXYZ string in public qubit order.

symplectic_inner_product(other: 'PauliWord') -> int

Return the binary symplectic inner product in {0, 1}.

A result of 1 means the words anticommute; 0 means they commute. Both words must have the same qubit count.

commutes_with(other: 'PauliWord') -> bool

Return whether two equal-width Pauli words commute.

multiply(other: 'PauliWord') -> PauliProduct

Multiply words and return the phase-free result plus exact phase.

The returned :class:PauliProduct keeps the phase separate, so a caller can apply it to a numerical coefficient without losing the canonical word representation.

adjoint() -> 'PauliWord'

Return the adjoint; every phase-free basis word is Hermitian.

ComputationalBasisState dataclass

A computational-basis product state in qubit order.

ProductBlochState dataclass

Pure or mixed tensor-product single-qubit Bloch vectors.

ProfiledExpectation dataclass

Expectation value paired with a propagation profile.

PropagationBatch

Propagate independent observables over one shared immutable program.

All observables must use the tape's qubit count. Batch execution amortizes tape handling while preserving one output row per input observable.

expectations(parameters: Sequence[float] | np.ndarray[Any, Any]) -> np.ndarray[Any, Any]

Return one real expectation for each observable.

The result is a read-only float64 vector with shape (observable_count,) and deterministic observable order.

values_and_gradients(parameters: Sequence[float] | np.ndarray[Any, Any], *, checkpoint_interval: Optional[int] = None) -> PropagationBatchValueAndGradient

Return values and row-wise frozen-support reverse gradients.

The returned values has shape (observable_count,) and gradients has shape (observable_count, nparameters). Support decisions and truncation branches are those of the forward execution.

PropagationBatchValueAndGradient dataclass

Values and row-wise frozen-support gradients for independent observables.

PropagationProfile dataclass

Structural and timing metadata from one explicit profile call.

PropagationValueAndGradient dataclass

A scalar expectation and its frozen-support reverse gradient.

ZeroState dataclass

The computational product state |0...0>.

PropagationChannelParameter dataclass

Public metadata for one channel scalar occurrence.

PropagationCircuit

Bases: _CircuitBuilder

Deterministic Pauli-propagation circuit facade.

PropagationCircuitValueAndGradient dataclass

Circuit value with separate rotation and channel gradients.

StabilizerCode dataclass

Immutable Rust-native analysis of a qubit stabilizer code space.

StabilizerCode represents a 2**nlogical-dimensional code space, not a pure :class:StabilizerState. Canonical logical representatives are deterministic algebraic representatives; they are not minimum-weight or geometry-aware operators.

qubit_order: QubitOrder property

Return the fixed public qubit ordering.

syndrome_order: SyndromeOrder property

Return the original input-check syndrome ordering.

from_generators(nqubits: int, generators: Iterable[PauliWord], *, signs: Optional[Sequence[int]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'StabilizerCode' classmethod

Construct from same-width signed phase-free Pauli generators.

from_symplectic(x: object, z: object, *, signs: Optional[Sequence[int]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'StabilizerCode' classmethod

Construct from binary symplectic check arrays with shape (m, n).

from_css(x_checks: object, z_checks: object, *, x_signs: Optional[Sequence[int]] = None, z_signs: Optional[Sequence[int]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'StabilizerCode' classmethod

Construct from X-only rows followed by Z-only rows.

check_weights() -> np.ndarray[Any, Any]

Return weights of the original ordered checks.

qubit_degrees() -> np.ndarray[Any, Any]

Return original-check incidence counts for each qubit.

check_arrays() -> StabilizerCheckArrays

Materialize owned packed signed checks in caller order.

check_relations(*, packed: bool = False) -> np.ndarray[Any, Any]

Return a deterministic basis of signed-check relations.

logical_operator_arrays() -> LogicalOperatorArrays

Materialize flat packed logical X/Z representatives.

logical_operators() -> Tuple[Tuple[PauliWord, ...], Tuple[PauliWord, ...]]

Explicitly materialize logical representatives as PauliWord values.

syndrome(error: PauliWord) -> Tuple[int, ...]

Return the syndrome in the original supplied-check order.

syndrome_many(errors: PauliBatchInput, *, packed: bool = False, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Return one unpacked or packed syndrome row for every input error.

classify(error: PauliWord) -> ErrorClassification

Classify one phase-free Pauli error.

classify_many(errors: PauliBatchInput, *, packed_syndromes: bool = False, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> ErrorClassificationBatch

Classify a batch with one coarse native call.

analyze_error_set(errors: PauliBatchInput, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> ErrorSetAnalysis

Check joint correctability of a supplied finite error set.

analyze_corrections(errors: PauliBatchInput, corrections: PauliBatchInput, *, packed_syndromes: bool = False, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> CorrectionAnalysis

Classify residuals using the fixed convention correction * error.

StabilizerErrorKind

Bases: IntEnum

Classification codes used by singular and batched analysis.

CliffordSnapshotArrays dataclass

Owned packed global-Clifford frame and outcome arrays.

frame_x_words and frame_z_words have shape (nsettings * nqubits, ceil(nqubits / 64)); consecutive rows form one signed commuting frame per setting. frame_signs has shape (nsettings, nqubits) with values +1 or -1, and outcomes has shape (nsettings, repeats, nqubits). frame_version is 1. Arrays are C-contiguous, read-only, and use q0_first order.

PauliSnapshotArrays dataclass

Owned setting-major local-Pauli snapshot arrays.

bases has shape (nsettings, nqubits) and uses codes 1=X, 2=Y, and 3=Z. outcomes has shape (nsettings, repeats, nqubits) and contains binary computational-basis outcomes. Arrays are C-contiguous, read-only, and use q0_first order.

Snapshots

Immutable Rust-owned classical-shadow snapshots.

nsettings is the number of independently randomized settings and repeats is the number of outcomes retained under each setting; shots is their checked product. The recommended default is repeats=1 because randomized-setting variance is not reduced by repeating a setting. Local-Pauli dense sampling amortizes one basis rotation over repeats, while global-Clifford dense sampling performs a fresh conditional Pauli-projection sequence for every repeat.

protocol: Protocol property

Sampling protocol, either "pauli" or "clifford".

nqubits: int property

Number of measured qubits.

nsettings: int property

Number of independent randomized measurement settings.

repeats: int property

Number of conditional outcomes retained per setting.

shots: int property

Total number of retained outcomes, equal to nsettings * repeats.

qubit_order: QubitOrder property

Qubit ordering used by all public arrays and estimators.

from_pauli_measurements(bases: object, outcomes: object, *, qubit_order: QubitOrder = 'q0_first', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'Snapshots' classmethod

Import local-Pauli measurements in setting-major form.

bases has shape (nsettings, nqubits) with codes 1=X, 2=Y, 3=Z. outcomes has shape (nsettings, repeats, nqubits) or a flat per-shot shape (nsettings, nqubits). Floating-point arrays are rejected.

from_clifford_measurements(frame_x_words: object, frame_z_words: object, frame_signs: object, outcomes: object, *, nqubits: int, frame_version: Literal[1] = 1, qubit_order: QubitOrder = 'q0_first', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'Snapshots' classmethod

Import version-1 packed signed commuting Clifford generators.

Frame rows are (nsettings*nqubits, ceil(nqubits/64)) and signs are (nsettings, nqubits); outcomes are setting-major with shape (nsettings, repeats, nqubits). Construction validates padding, commutation, independence, signs, and binary outcomes once.

sample(state: Union[object, 'StabilizerState'], *, nsettings: int, protocol: Protocol = 'pauli', repeats: int = 1, seed: Optional[int] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'Snapshots' classmethod

Sample complete-statevector or stabilizer snapshots natively.

nsettings counts independent randomized settings; repeats counts conditional outcomes per setting and shots is nsettings * repeats. repeats=1 is recommended for linear estimators, shadow Rényi-2, and global Clifford because increasing settings reduces ensemble variance. Dense local-Pauli sampling costs one basis transform per setting plus outcome draws; dense global Clifford costs a fresh O(nqubits * 2**nqubits) conditional projection sequence per outcome. Stabilizer inputs use tableau kernels.

to_arrays() -> Union[PauliSnapshotArrays, CliffordSnapshotArrays]

Return owned, C-contiguous, read-only raw snapshot arrays.

expectation(observable: Union[PauliWord, PauliTerm, PauliOperator], *, blocks: int = 1, return_blocks: bool = False) -> Union[float, np.ndarray[Any, Any]]

Estimate one Hermitian observable by setting-level averaging.

blocks=1 returns the arithmetic mean; blocks>1 partitions complete settings into balanced contiguous blocks and returns the median of their block means. Repeats are averaged inside each setting first. The default returns a scalar; return_blocks=True returns a float64 array of shape (blocks,). Local-Pauli variance grows with observable weight, while global-Clifford variance can be preferable for dense observables; global Clifford is not uniformly lower-variance.

estimate_many(observables: Sequence[Union[PauliWord, PauliTerm, PauliOperator]], *, blocks: int = 1, return_blocks: bool = False) -> np.ndarray[Any, Any]

Estimate many Hermitian targets in one native call.

Setting-level values are formed after averaging repeats. blocks=1 returns an array of shape (nobservables,); blocks>1 returns their elementwise median-of-means. With return_blocks=True the shape is (blocks, nobservables) and each operator sum is combined before block reduction. Local-Pauli variance grows with observable weight, while global-Clifford variance can be preferable for dense observables; global Clifford is not uniformly lower-variance.

energy(hamiltonian: PauliOperator, *, blocks: int = 1, return_blocks: bool = False) -> Union[float, np.ndarray[Any, Any]]

Alias of :meth:expectation for an exactly Hermitian Hamiltonian.

rdm(*, subsystem_to_keep: Optional[Sequence[int]] = None, subsystems_to_trace_out: Optional[Sequence[int]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Return the arithmetic-mean reduced snapshot estimator.

User order is preserved for subsystem_to_keep; a trace-out selector uses the q0-first complement. Only the requested square subsystem is materialized. Empty and full subsystems are valid.

renyi_entropy(*, subsystem_to_keep: Optional[Sequence[int]] = None, subsystems_to_trace_out: Optional[Sequence[int]] = None, alpha: int = 2, method: Literal['shadow', 'randomized_measurement'] = 'shadow', blocks: int = 1, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> float

Estimate Rényi-2 using a shadow U-statistic or distinct repeats.

alpha=2 is the only supported order. method='shadow' uses cross-setting pairs and requires at least two settings per block; its setting matrices are streamed one block at a time. The 'randomized_measurement' method is local-Pauli-only, requires repeats>=2, excludes self-pairs, and follows the collision scale R=Theta(sqrt(2**k)) as a pilot heuristic. Purity is median-reduced before applying -log. max_bytes is a best-effort workspace guard.

energy_variance(hamiltonian: PauliOperator, *, blocks: int = 1, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> float

Estimate <H**2>-<H>**2 with a cross-setting square.

Each block requires at least two complete randomized settings. The finite-sample result is returned unchanged, including negative values; duplicate Pauli products and workspace checks are performed in Rust.

fidelity(target: 'StabilizerState', *, blocks: int = 1, return_blocks: bool = False) -> Union[float, np.ndarray[Any, Any]]

Estimate fidelity to a same-width stabilizer target.

Fidelity is supported only for global-Clifford snapshots. It is a linear setting-level estimator with the same mean, median-of-means, and return-shape semantics as :meth:expectation. Use :meth:fidelity_statevector for an arbitrary pure dense target.

fidelity_statevector(target: object, *, blocks: int = 1, return_blocks: bool = False) -> Union[float, np.ndarray[Any, Any]]

Estimate fidelity to an arbitrary same-width pure statevector.

This estimator is supported only for global-Clifford snapshots. Unlike :meth:fidelity, it cannot use a stabilizer-overlap shortcut: native post-processing enumerates the nonzero amplitudes of each stabilizer snapshot and performs a dense overlap with target. The estimator therefore costs O(nsettings * 2**nqubits) after snapshots have been collected, while requiring only the supplied target vector rather than materializing one full statevector per snapshot.

StabilizerState

Immutable pure stabilizer state backed by a native tableau.

A state stores exactly nqubits independent signed commuting Pauli generators. It can be sampled by Snapshots.sample() without creating a dense statevector, and its tableau can be exported only through the owned read-only arrays returned by :meth:to_tableau.

nqubits: int property

Number of qubits represented by the tableau.

zero_state(nqubits: int) -> 'StabilizerState' classmethod

Construct the computational |0...0> stabilizer state.

from_generators(generators: Sequence[Tuple[PauliWord, int]]) -> 'StabilizerState' classmethod

Construct a state from (generator, sign) pairs.

The sequence must contain exactly nqubits same-width PauliWord generators. Signs are eigenvalues and must be +1 or -1; the native tableau validator checks commutation, independence, and the canonical Pauli representation.

from_tableau(x_words: object, z_words: object, signs: object) -> 'StabilizerState' classmethod

Construct a state from packed tableau arrays.

x_words and z_words must have shape (nqubits, ceil(nqubits / 64)) and unsigned-64-bit integer entries; signs must have shape (nqubits,) and contain only +1 or -1. Inputs are copied into the native tableau after boundary validation.

from_clifford_tape(tape: object) -> 'StabilizerState' classmethod

Apply a parameter-free supported Clifford GateTape to |0>.

The tape must contain only X, Y, Z, H, S, Sdg, CNOT, CZ, or SWAP gates with concrete angles absent. The complete tape is validated and executed in one native call.

to_tableau() -> Tuple[np.ndarray[Any, Any], np.ndarray[Any, Any], np.ndarray[Any, Any]]

Return owned read-only (x_words, z_words, signs) arrays.

SPPSEstimate dataclass

One fixed-budget or adaptive SPPS estimate.

value_standard_error uses the usual finite-sample sample-variance estimator of the sampled path distribution (with an N-1 denominator).

SPPSValueEstimate dataclass

One value-only stochastic Pauli-path estimate.

value_standard_error uses the usual finite-sample sample-variance estimator of the sampled path distribution (with an N-1 denominator).

SPPSCircuit

Bases: _CircuitBuilder

TensorCircuit-style builder for fixed-budget stochastic estimation.

BosonOperator

Bases: _StructuredOperator

Immutable symbolic boson operator with infinite-Fock CCR semantics.

Finite matrix and MVP targets require explicit per-mode occupation cutoffs; symbolic algebra itself remains cutoff-free.

from_terms(n_modes: int, terms: Iterable[Tuple[Sequence[Tuple[int, str]], complex]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'BosonOperator' classmethod

Construct and CCR-canonicalize raw ordered boson factors.

multiply(other: '_StructuredOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> '_StructuredOperator'

Multiply two boson operators while retaining CCR contractions.

compile(target: str, *, storage: Literal['lazy', 'eager'] = 'lazy', boson_cutoffs: Mapping[object, object], max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> CompileResult

Compile a boson operator with its required finite cutoffs.

BosonTerm dataclass

One canonical boson word and its complex coefficient.

BosonWord dataclass

Canonical normal-ordered bosonic power blocks.

Each block is (mode, creation_power, annihilation_power). Raw products should be constructed through :class:BosonOperator so CCR contractions are retained exactly.

is_identity: bool property

Whether the word contains no bosonic ladder factors.

factors: Tuple[Tuple[int, str], ...] property

Expand canonical power blocks into raw ladder factors.

adjoint() -> 'BosonOperator'

Return the coefficient-free adjoint word as an operator.

multiply(other: 'BosonWord') -> 'BosonOperator'

Multiply two words and retain all CCR contraction terms.

FermionOperator

Bases: _StructuredOperator

Immutable canonical fermionic operator governed by CAR.

Raw ladder products are expanded and aggregated exactly. Use :meth:map_fermions for a Pauli representation or :meth:compile for a matrix/MVP target.

from_terms(n_modes: int, terms: Iterable[Tuple[Sequence[Tuple[int, str]], complex]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionOperator' classmethod

Construct and CAR-canonicalize raw ordered fermion factors.

Each term is (factors, coefficient) with factors such as (mode, "create") and (mode, "annihilate"). Equal canonical words are aggregated and exact zero coefficients are removed.

Examples:

>>> import tencirpauli as tcp
>>> number = tcp.FermionOperator.from_terms(
...     1, [(((0, "create"), (0, "annihilate")), 1.0)]
... )
>>> number.term_count
1

from_integrals(one_body: np.ndarray[Any, Any], two_body: np.ndarray[Any, Any], *, constant: complex = 0.0, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionOperator' classmethod

Construct a canonical spin-orbital molecular Hamiltonian.

one_body[p, q] and two_body[p, q, r, s] use the fixed convention from a†_p a_q and a†_p a†_q a_s a_r. The native importer applies the two-body factor of one half exactly once.

multiply(other: '_StructuredOperator', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> '_StructuredOperator'

Multiply two fermion operators while retaining CAR contractions.

map_fermions(mapping: Union[str, 'FermionQubitMapping'] = 'jordan_wigner', *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> PauliOperator

Map the fermion operator to a canonical Pauli operator.

mapping may be a supported mapping name or a reusable :class:FermionQubitMapping. The result has one qubit per fermion mode and includes exact Jordan-Wigner/CNOT conjugation phases.

compile(target: str, *, storage: Literal['lazy', 'eager'] = 'lazy', mapping: Union[str, 'FermionQubitMapping'] = 'jordan_wigner', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> CompileResult

Compile a Fermion operator, keeping raw masks for native MVP.

The default native-MVP route uses direct CAR descriptors in the Jordan--Wigner occupation-basis order. Call :meth:map_fermions first to force a Pauli mapping.

to_majorana(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'MajoranaOperator'

Convert this canonical fermion operator to the Majorana and charge algebra.

FermionTerm dataclass

One canonical fermion word and its complex coefficient.

FermionWord dataclass

Canonical fermionic monomial creations * annihilations.

Creation modes are stored in increasing order and annihilation modes in decreasing order. Use :meth:from_factors for arbitrary raw products so CAR contractions and signs are canonicalized.

is_identity: bool property

Whether the word contains no fermionic ladder factors.

parity: int property

Return the fermion-number parity of the word.

factors: Tuple[Tuple[int, str], ...] property

Return the canonical raw factor sequence.

from_factors(n_modes: int, factors: Sequence[Tuple[int, str]], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'FermionOperator' classmethod

Construct and canonicalize one raw fermion word.

adjoint() -> 'FermionOperator'

Return the coefficient-free adjoint word as an operator.

multiply(other: 'FermionWord') -> 'FermionOperator'

Multiply two words and retain all CAR contraction terms.

HybridOperator

Bases: _StructuredOperator

Immutable mixed-domain operator with canonical domain factors.

Hybrid terms may combine fermion, boson, qubit, and qudit factors. Fermion mapping and finite boson cutoffs are explicit at compilation time.

compile(target: str, *, storage: Literal['lazy', 'eager'] = 'lazy', mapping: Union[str, 'FermionQubitMapping'] = 'jordan_wigner', boson_cutoffs: Optional[Mapping[object, object]] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> CompileResult

Compile a hybrid operator with optional explicit Fermion mapping.

The default native-MVP route retains raw Fermion descriptors; calling :meth:map_fermions first selects mapped-Pauli execution instead.

OperatorSpace

Immutable ordered logical subsystem layout for structured operators.

Axes are ordered as fermions, bosons, qubits, then uniform-dimension qudits. This ordering controls term serialization, mixed-radix basis ordering, embedding, tensor products, and finite matrix targets.

Examples:

>>> import tencirpauli as tcp
>>> space = tcp.OperatorSpace(fermions=1, qubits=1)
>>> operator = space.fermion.create(0) * space.qubit.z(0)
>>> operator.term_count
1

axes: Tuple[Tuple[str, int, int], ...] property

Return ordered (domain, index, local-dimension) descriptors.

layout_fingerprint: Tuple[Tuple[str, int, int], ...] property

Return the immutable compatibility fingerprint for this layout.

local_dimensions: Tuple[int, ...] property

Return finite local dimensions, rejecting uncut boson axes.

fermion: '_FermionFactory' property

Return factories for fermion creation and annihilation.

boson: '_BosonFactory' property

Return factories for boson creation and annihilation.

qubit: '_QubitFactory' property

Return factories for physical Pauli X, Y, and Z factors.

qudit: '_QuditFactory' property

Return the direct-convention Weyl factory.

builder() -> 'OperatorBuilder'

Create a mutable batched builder for this immutable space.

embed(operator: '_StructuredOperator', **maps: object) -> '_StructuredOperator'

Embed an operator into this space with explicit domain index maps.

Each supplied map is a source-to-target index mapping for one of fermions, bosons, qubits, or qudits. Unmapped domains must be empty; no implicit axis matching is performed.

QuditProduct dataclass

A Weyl word together with its modular phase exponent.

QuditWeylOperator

Bases: _StructuredOperator

Immutable uniform-dimension direct-convention Weyl operator.

Factors use X^a Z^b with exponents reduced modulo the common local dimension. Matrix targets use deterministic qudit-zero-MSB mixed-radix ordering.

from_terms(dimension: int, terms: Iterable[Tuple[Sequence[Tuple[int, int, int]], complex]], *, n_sites: Optional[int] = None, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'QuditWeylOperator' classmethod

Construct a modular X^a Z^b operator and aggregate phases.

compile(target: str, *, storage: Literal['lazy', 'eager'] = 'lazy', max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> CompileResult

Compile a uniform-dimension Weyl operator.

QuditWeylTerm dataclass

One direct-convention Weyl word and its complex coefficient.

QuditWeylWord dataclass

Direct-convention X**a Z**b word with modular exponents.

Exponents are reduced modulo dimension and triples are sorted by site. Multiplication returns a :class:QuditProduct with the modular phase exponent kept separate from the canonical word.

is_identity: bool property

Whether every site carries the identity Weyl factor.

n_sites: int property

Return one past the largest explicitly stored site index.

multiply(other: 'QuditWeylWord') -> 'QuditProduct'

Multiply words and return the modular phase exponent separately.

commutes_with(other: 'QuditWeylWord') -> bool

Check the exact modular Weyl commutation condition.

adjoint() -> 'QuditProduct'

Return the adjoint word and its modular phase exponent.

U1Sector dataclass

Fixed-Hamming-weight basis with TensorCircuit integer ordering.

dimension: int property

Number of basis states, C(nqubits, particle_number).

rank(bitstring: int | Sequence[int]) -> int

Return the ascending-basis rank without materializing the basis.

unrank(index: int) -> Tuple[int, ...]

Return the occupation bits at a restricted index.

The tuple is always ordered from qubit zero to qubit nqubits - 1; unlike the historical API, its type does not depend on system width.

basis_states(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Return read-only uint8 basis rows in restricted-sector order.

basis_words_packed(*, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> np.ndarray[Any, Any]

Return the advanced packed uint64 U(1) basis representation.

Z2SymmetryAnalysis dataclass

Deterministic, exactly validated Pauli Z2 symmetry analysis.

The input is a Pauli Hamiltonian. A discovered generator S satisfies S**2 = I and commutes with every Hamiltonian term, so its eigenvalue labels sectors by +1 or -1. Generators may contain X and Y factors and therefore need not be diagonal in the computational or occupation basis. For a fermionic source, choose a fermion-to-qubit encoding first (Jordan--Wigner, parity, or Bravyi--Kitaev), then call find_z2_symmetries on the resulting :class:PauliOperator.

This is a Pauli stabilizer symmetry, not an additive occupation charge and not an occupation-parity sector. constraint_rank is the GF(2) null-space dimension of the symmetry constraint matrix and can exceed the number of mutually commuting generators selected for tapering. rank is the number of selected commuting generators.

rank: int property

Return selected commuting-generator count.

This is len(generators) and is distinct from constraint_rank (the GF(2) null-space dimension) and from ChargeSector.rank or U1Sector.rank (basis-state indices).

tapering_plan(sector: Sequence[int]) -> 'Z2TaperingPlan'

Build a reusable Clifford plan for selected Pauli eigenvalues.

sector[i] selects the +1 or -1 eigenvalue of generators[i]. The returned plan applies a Clifford change of Pauli basis, substitutes those selected eigenvalues, and removes the corresponding qubits. It does not construct an occupation-space ChargeSector.

U1Circuit

Lazy circuit that preserves a fixed particle-number sector.

Construct with particle_number and optionally an occupied basis initialization or an explicit restricted-sector initial_state. Gates are diagonal or particle-number preserving, and execution is deferred until a state, probability, or expectation terminal is requested.

Examples:

>>> import tencirpauli as tcp
>>> circuit = tcp.U1Circuit(2, particle_number=1)
>>> circuit.rz(0, 0.2)
>>> circuit.probability().shape
(2,)

angle_count: int property

Return the number of gradient-supported gate-angle occurrences.

dimension: int property

Return C(nqubits, particle_number), the sector dimension.

rz(i: int, theta: Angle = 0.0) -> None

Append an RZ gate with a concrete or JAX-traced radian angle.

rzz(i: int, j: int, theta: Angle = 0.0) -> None

Append an RZZ gate with a concrete or JAX-traced radian angle.

cz(i: int, j: int) -> None

Append a controlled-Z gate on two distinct qubits.

cphase(i: int, j: int, theta: Angle = 0.0) -> None

Append a controlled-phase gate with a concrete or JAX-traced angle.

swap(i: int, j: int) -> None

Append a SWAP gate on two distinct qubits.

iswap(i: int, j: int, theta: Angle = 1.0) -> None

Append an iSWAP interpolation using the normalized angle convention.

diagonal(*indices: int, diagonal: Optional[Sequence[complex] | np.ndarray[Any, Any]] = None, diag: Optional[Sequence[complex] | np.ndarray[Any, Any]] = None) -> None

Append a static diagonal gate on the selected qubits.

The payload must contain exactly 2**len(indices) finite complex values. diagonal and its compatibility alias diag are mutually exclusive.

state() -> np.ndarray[Any, Any]

Return the final state in restricted-sector ordering.

probability() -> np.ndarray[Any, Any]

Return probabilities in restricted-sector ordering.

state_full() -> np.ndarray[Any, Any]

Return the final state expanded to the full computational basis.

probability_full() -> np.ndarray[Any, Any]

Expand and return probabilities over the full computational basis.

expectation(observable: PauliOperator) -> complex

Return a complex expectation for an arbitrary Pauli observable.

value_and_grad(observable: PauliOperator) -> U1CircuitValueAndGradient

Return a real value and exact gradient for an exactly Hermitian observable.

The returned owned array is read-only float64 with one entry per gate-angle occurrence. ValueError is raised for a non-Hermitian observable. The reverse pass uses inverse-gate replay with a constant number of sector state vectors and therefore has no propagation-style checkpoint interval.

expectation_jax(observable: PauliOperator) -> Any

Return a JAX scalar with one native callback and a custom VJP.

from_circuit(circuit: Any, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'U1Circuit' classmethod

Convert a supported TensorCircuit U(1) circuit.

inverse() -> 'U1Circuit'

Return a copy with the gate sequence inverted.

append(other: 'U1Circuit') -> 'U1Circuit'

Return the concatenation of two compatible U1 circuits.

to_qir() -> list[dict[str, object]]

Serialize the circuit to deterministic JSON-like gate records.

from_qir(qir: Sequence[Mapping[str, object]], circuit_params: Mapping[str, object], *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> 'U1Circuit' classmethod

Restore supported QIR gates; iSWAP angles use the normalized convention.

U1CircuitValueAndGradient dataclass

Real expectation value and exact native adjoint gradient.

backend_mvp(plan: BackendMVPPlan, coefficients: Optional[Sequence[complex]] = None, backend: Any = None, *, max_bytes: Optional[int] = DEFAULT_MAX_BYTES) -> Any

Return a TensorCircuit-backend MVP callable for a pure-array plan.

The returned callable accepts a flat or local-rank state. Binary Pauli plans use packed masks; uniform Weyl plans use factorized phase-and-cyclic-shift operations directly on the backend tensor. Plan structure is fixed before tracing; coefficients may be replaced by a backend tensor for a differentiable parameter buffer.

shadow_bound(observables: Union[PauliWord, Sequence[PauliWord], np.ndarray[Any, Any]], epsilon: float, delta: float = 0.01) -> Tuple[int, int]

Return the TensorCircuit-compatible local-Pauli shadow budget.

For L words of maximum weight w, the result is (nsettings, blocks) with blocks=ceil(2 log(2L/delta)) and settings_per_block=ceil(34*3**w/epsilon**2). This coefficient-free bound is for simultaneous Pauli words and does not accept a PauliOperator Hamiltonian.