quchip.engine.ir

IR types shared by engine responsibilities and backends.

This module is the contract between the engine and its backends. It defines four families of immutable, JAX-pytree-friendly types:

  1. Signal Program AST — subclasses of SignalNode (Constant, EnvelopeRef, Window, Shift, Scale, PolarScale, Add, Multiply, Conjugate, RealPart, Carrier). A pure functional description of a time-dependent scalar coefficient f(t) : . Every leaf that a user may sweep (envelope parameters, amplitudes, phases, carrier frequencies) is a pytree leaf so the whole program is differentiable through JAX.

  2. CanonicalOperator — backend-free operator storage in dense / CSR / DIA layouts plus subsystem metadata. Backends convert to and from this format.

  3. Hamiltonian terms — StaticTerm, DynamicTerm, and their EngineResult container.

  4. Solve requests — SolveProblem and SolveBatch, the frozen hand-offs to backends. backend selection is chip-owned and is explicitly forbidden from options.

A note on 2π: every operator here has already been scaled by 2π during engine assembly. Carrier frequencies are stored in angular units (rad/ns). IR consumers (backends, analyses) must not re-apply 2π.

Functions

decompose_carrier_bands(signal)

Rewrite signal into Σ_k envelope_k(t) · exp(i · freq_k · t) with carrier-free envelopes.

evaluate_signal_program(signal, t, *[, xp])

Evaluate a signal program at time(s) t (ns); xp defaults to NumPy.

signal_children(node)

Return the SignalProgram child nodes of node.

simplify_signal(signal)

Recursively simplify a signal program by canceling exact opposing carrier pairs.

Classes

Add(children)

CanonicalOperator(layout, values, shape, ...)

Backend-free operator with explicit dense/CSR/DIA payload and subsystem metadata.

Carrier(freq[, sign])

Oscillating carrier exp(sign · i · freq · t).

CarrierBand(envelope, freq)

One band of a carrier-normalized signal: envelope(t) · exp(i · freq · t).

CoefficientRef(coefficient)

Internal signal leaf backed by a public component-owned coefficient.

CollapseTerm(operator, rate, source, channel)

Backend-neutral Lindblad operator and its separate rate.

Conjugate(child)

Constant(value)

DriveOp(target_label, envelope[, freq, ...])

Drive operation scheduled on a device or a modulable coupling.

DroppedTerm(source, operator, reason[, ...])

Advisory record for a Hamiltonian term elided by an approximation.

DynamicTerm(operator, time_dependence[, ...])

Time-dependent Hamiltonian contribution operator · f(t).

EngineResult(static_terms, dynamic_terms[, ...])

Backend-agnostic time-dependent Hamiltonian passed to backends.

EnvelopeRef(envelope)

Reference to a pulse envelope evaluated at local time.

HamiltonianTemplate(resolved_frame, ...[, ...])

Chip-topology-invariant Hamiltonian skeleton.

ImagPart(child)

Imaginary quadrature of a complex analytic signal.

Multiply(children)

PolarScale(child, amplitude, theta)

Scale child by amplitude * exp(i * theta) (both are pytree leaves).

PortTerm(operator, rate, phase, ...[, ...])

Resolved input-output channel before the sqrt(rate) scaling.

RealPart(child)

ResolvedFrame(frequencies, demod_freqs, mode)

Resolved per-device frame information.

ScalarModulation(signal)

Typed wrapper marking a SignalProgram as a scalar modulation on a DynamicTerm.

Scale(child, factor)

Multiply child by a complex scalar factor.

Shift(child, delta_t)

Time-shift child by delta_t: child(t - delta_t).

SignalNode()

Base class for signal-program AST nodes.

SignalPower(child, exponent)

Pointwise power of a scalar signal program.

SignalProgram

SolveBatch(chip, problems[, params, shape, axes])

Explicit solve problems sharing one dispatch owner and sweep shape.

SolveProblem(chip, engine_result, ...[, ...])

Immutable simulation request handed from the chip pipeline to a backend.

StaticTerm(operator[, coefficient, origin, ...])

Time-independent Hamiltonian contribution.

SteadyStateProblem(chip, engine_result[, ...])

Immutable static Lindblad request handed from a chip to its backend.

Window(child, start, stop)

Gate child to [start, stop]; zero outside.

class quchip.engine.ir.SignalNode[source]

Bases: object

Base class for signal-program AST nodes.

A node describes a time-dependent scalar f(t) : . Subclasses:

  • are @dataclass(frozen=True); every dataclass field is a JAX pytree child (registration happens automatically on subclass definition), so any field a user may sweep is differentiable;

  • name the fields that hold child nodes (or tuples of child nodes) in _signal_child_fields, which powers generic traversal (signal_children()) and rewriting (rebuild_children());

  • implement evaluate() — the node’s pointwise semantics;

  • override bands() when (and only when) the node interacts with Carrier leaves: the default treats any carrier-free subtree as a single zero-frequency band, which is exact for every envelope-like node.

signal_children()[source]

Return this node’s child nodes (flattening tuple-valued fields).

Return type:

tuple[SignalNode, …]

rebuild_children(transform)[source]

Reconstruct this node with transform applied to each child.

Non-child fields are preserved; nodes without children pass through untouched.

Parameters:

transform (Any)

Return type:

SignalNode

evaluate(t, *, xp)[source]

Evaluate the node at time(s) t (ns) in array namespace xp.

Parameters:
Return type:

Any

bands()[source]

Rewrite this subtree into carrier-normalized bands.

Default: a carrier-free subtree is exactly one zero-frequency band whose envelope is the subtree itself. Nodes whose subtrees may contain Carrier leaves must override this with their carrier algebra (see decompose_carrier_bands()).

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Constant(value: 'complex')[source]

Bases: SignalNode

Parameters:

value (complex)

value: complex
evaluate(t, *, xp)[source]

Return the constant value, broadcast to the shape of t.

Parameters:
Return type:

Any

bands()[source]

Return the single zero-frequency band carrying this constant.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.EnvelopeRef(envelope)[source]

Bases: SignalNode

Reference to a pulse envelope evaluated at local time.

Parameters:

envelope (Envelope)

envelope: Envelope
evaluate(t, *, xp)[source]

Return the referenced envelope’s complex value(t).

Parameters:
Return type:

Any

bands()[source]

Return the single zero-frequency band carrying this envelope.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.CoefficientRef(coefficient)[source]

Bases: SignalNode

Internal signal leaf backed by a public component-owned coefficient.

Parameters:

coefficient (TimeCoefficient)

coefficient: TimeCoefficient
evaluate(t, *, xp)[source]

Evaluate the node at time(s) t (ns) in array namespace xp.

Parameters:
Return type:

Any

class quchip.engine.ir.Window(child, start, stop)[source]

Bases: SignalNode

Gate child to [start, stop]; zero outside.

Parameters:
child: SignalNode
start: float
stop: float
evaluate(t, *, xp)[source]

Return the child value inside [start, stop] (ns), zero elsewhere.

Parameters:
Return type:

Any

bands()[source]

Return the child bands with the same time gate applied to each envelope.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Shift(child, delta_t)[source]

Bases: SignalNode

Time-shift child by delta_t: child(t - delta_t).

Parameters:
child: SignalNode
delta_t: float
evaluate(t, *, xp)[source]

Return the child evaluated at t - delta_t (ns).

Parameters:
Return type:

Any

bands()[source]

Return the child bands, each carrying the shift’s carrier phase.

A time shift distributes over bands and contributes the constant carrier phase exp(-i·freq·Δt) per band.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Scale(child, factor)[source]

Bases: SignalNode

Multiply child by a complex scalar factor.

Parameters:
child: SignalNode
factor: complex
evaluate(t, *, xp)[source]

Return the child value scaled by factor.

Parameters:
Return type:

Any

bands()[source]

Return the child bands with factor folded into each envelope.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.PolarScale(child, amplitude, theta)[source]

Bases: SignalNode

Scale child by amplitude * exp(i * theta) (both are pytree leaves).

Parameters:
child: SignalNode
amplitude: float
theta: float
evaluate(t, *, xp)[source]

Return the child value scaled by amplitude * exp(i * theta).

Parameters:
Return type:

Any

bands()[source]

Return the child bands with the polar scale folded into each envelope.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Add(children: 'tuple[SignalNode, ...]')[source]

Bases: SignalNode

Parameters:

children (tuple[SignalNode, ...])

children: tuple[SignalNode, ...]
evaluate(t, *, xp)[source]

Return the sum of the children evaluated at t (ns).

Parameters:
Return type:

Any

bands()[source]

Return the concatenation of every child’s bands.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Multiply(children: 'tuple[SignalNode, ...]')[source]

Bases: SignalNode

Parameters:

children (tuple[SignalNode, ...])

children: tuple[SignalNode, ...]
evaluate(t, *, xp)[source]

Return the product of the children evaluated at t (ns).

Parameters:
Return type:

Any

bands()[source]

Return the frequency convolution: the Cartesian product of child bands.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Conjugate(child: 'SignalNode')[source]

Bases: SignalNode

Parameters:

child (SignalNode)

child: SignalNode
evaluate(t, *, xp)[source]

Return the complex conjugate of the child evaluated at t (ns).

Parameters:
Return type:

Any

bands()[source]

Return the child bands with each envelope conjugated and its frequency negated.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.RealPart(child: 'SignalNode')[source]

Bases: SignalNode

Parameters:

child (SignalNode)

child: SignalNode
evaluate(t, *, xp)[source]

Return the real part of the child evaluated at t (ns).

Parameters:
Return type:

Any

bands()[source]

Return each band split into ±freq halves via Re z = (z + z̄) / 2.

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.ImagPart(child)[source]

Bases: SignalNode

Imaginary quadrature of a complex analytic signal.

Parameters:

child (SignalNode)

child: SignalNode
evaluate(t, *, xp)[source]

Return the imaginary part of the child evaluated at t (ns).

Parameters:
Return type:

Any

bands()[source]

Split bands using Im z = (z - z_bar) / (2i).

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.SignalPower(child, exponent)[source]

Bases: SignalNode

Pointwise power of a scalar signal program.

Parameters:
child: SignalNode
exponent: Any
evaluate(t, *, xp)[source]

Evaluate the node at time(s) t (ns) in array namespace xp.

Parameters:
Return type:

Any

bands()[source]

Rewrite this subtree into carrier-normalized bands.

Default: a carrier-free subtree is exactly one zero-frequency band whose envelope is the subtree itself. Nodes whose subtrees may contain Carrier leaves must override this with their carrier algebra (see decompose_carrier_bands()).

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.Carrier(freq, sign=-1)[source]

Bases: SignalNode

Oscillating carrier exp(sign · i · freq · t).

freq is in angular units (rad/ns). The default sign = -1 matches the convention used in rotating-frame decompositions (Scully & Zubairy, Quantum Optics, §5), where a raising-type band on a detuning rotates as exp(−iΔt). Both fields are registered as pytree children (freq may be traced; sign is semantically a static ±1 — do not map over it).

Parameters:
freq: float
sign: Literal[-1, 1] = -1
evaluate(t, *, xp)[source]

Return exp(sign · i · freq · t) at time(s) t (ns).

Parameters:
Return type:

Any

bands()[source]

Return the single sign·freq band with a unit-constant envelope.

Return type:

tuple[CarrierBand, …]

quchip.engine.ir.SignalProgram

alias of SignalNode

class quchip.engine.ir.ScalarModulation(signal)[source]

Bases: object

Typed wrapper marking a SignalProgram as a scalar modulation on a DynamicTerm.

Parameters:

signal (SignalNode)

signal: SignalNode
quchip.engine.ir.signal_children(node)[source]

Return the SignalProgram child nodes of node.

Dispatches to SignalNode.signal_children(); a ScalarModulation wrapper contributes its signal. EnvelopeRef.envelope is an Envelope, not a SignalProgram child, and so is not returned here.

Parameters:

node (Any)

Return type:

tuple

quchip.engine.ir.evaluate_signal_program(signal, t, *, xp=None)[source]

Evaluate a signal program at time(s) t (ns); xp defaults to NumPy.

Parameters:
Return type:

Any

quchip.engine.ir.simplify_signal(signal)[source]

Recursively simplify a signal program by canceling exact opposing carrier pairs.

Parameters:

signal (SignalNode)

Return type:

SignalNode

class quchip.engine.ir.CarrierBand(envelope, freq)[source]

Bases: object

One band of a carrier-normalized signal: envelope(t) · exp(i · freq · t).

decompose_carrier_bands() rewrites any SignalProgram into a sum of these bands, where envelope is guaranteed carrier-free (no Carrier leaves) and therefore slow, and freq is the angular band frequency (rad/ns, sign folded in, JAX-traceable). Backends use this to keep the fast oscillation analytic while sampling only the slow envelope — exact regardless of how resonant the carrier is, unlike pre-sampling the whole product.

Parameters:
envelope: SignalNode
freq: Any
quchip.engine.ir.decompose_carrier_bands(signal)[source]

Rewrite signal into Σ_k envelope_k(t) · exp(i · freq_k · t) with carrier-free envelopes.

This is the scalar-coefficient analogue of the operator band decomposition in quchip.engine.bands: every Carrier leaf is pulled out into a band frequency, leaving a slow, carrier-free envelope per band. The rewrite is exact and follows the carrier algebra, implemented node-locally in each SignalNode.bands():

  • Carrier(freq, sign) → one band (1, sign·freq).

  • Conjugate → conjugate the envelope, flip the band frequency.

  • RealPart → split each band into ±freq (Re z = (z+z̄)/2).

  • Multiply → frequency convolution (Cartesian product of bands).

  • Add → concatenate bands.

  • Scale / PolarScale / Window / Shift → distribute over bands (Shift also contributes the constant phase exp(-i·freq·Δt)).

All frequency arithmetic stays in JAX-traceable terms (no float(), no branching on traced values).

Parameters:

signal (SignalNode)

Return type:

tuple[CarrierBand, …]

class quchip.engine.ir.CanonicalOperator(layout, values, shape, dims, basis, subsystem_labels, indices=None, indptr=None, offsets=None, tag=None)[source]

Bases: object

Backend-free operator with explicit dense/CSR/DIA payload and subsystem metadata.

For dense the payload is the full 2D matrix; for csr it is the 1D nonzero value array paired with indices/indptr; for dia it is a 2D (n_diags, n_cols) array paired with offsets. dims must multiply to shape[0] and subsystem_labels names each subsystem.

Parameters:
layout: Literal['dense', 'csr', 'dia']
values: Any
shape: tuple[int, int]
dims: tuple[int, ...]
basis: str
subsystem_labels: tuple[str, ...]
indices: Any | None = None
indptr: Any | None = None
offsets: Any | None = None
tag: str | None = None
property is_sparse: bool

True for the csr / dia layouts, False for dense.

classmethod from_dense(values, *, dims, basis, subsystem_labels, tag=None)[source]
Parameters:
Return type:

CanonicalOperator

classmethod from_csr(values, indices, indptr, *, shape, dims, basis, subsystem_labels, tag=None)[source]
Parameters:
Return type:

CanonicalOperator

classmethod from_dia(values, offsets, *, shape, dims, basis, subsystem_labels, tag=None)[source]
Parameters:
Return type:

CanonicalOperator

with_metadata(*, dims=None, basis=None, subsystem_labels=None, tag=None)[source]

Return a metadata-adjusted copy (payload unchanged).

Parameters:
Return type:

CanonicalOperator

diagonal()[source]

Return the main diagonal without materializing a sparse matrix.

Return type:

Any

to_dense()[source]

Materialize the payload as a dense shape-sized matrix.

Vectorized and array-namespace-preserving (JAX-safe): a traced JAX payload yields a JAX array via .at[].set / .add, a concrete NumPy payload yields a NumPy array. Callers that need a guaranteed concrete NumPy matrix must wrap the result in np.asarray(..., dtype=complex) themselves.

Return type:

Any

fingerprint()[source]

Batching key: value-sensitive, with an automatic tracer-safe fallback.

Two crosstalk-rebuilt operators carrying the same coefficients collapse to the same key so they batch into one solve slot. Under jax.jit the payload is a tracer (possibly hidden inside a backend qarray wrapper, e.g. dynamiqs SparseDIAQArray); contains_tracer() detects that and the key falls back to layout + shape/dtype structure only, so tobytes() is never called on a tracer and two equivalent traced operators in different batch slots still produce identical keys.

Return type:

tuple

class quchip.engine.ir.StaticTerm(operator, coefficient=1.0, origin='device', metadata=<factory>)[source]

Bases: object

Time-independent Hamiltonian contribution.

The operator payload has already been scaled by 2π during engine assembly; backends must not re-apply it. coefficient multiplies operator and may be a concrete scalar or a JAX tracer (sweeps over static couplings, detunings, etc.). origin is purely advisory metadata.

Parameters:
operator: CanonicalOperator
coefficient: complex = 1.0
origin: Literal['device', 'coupling', 'drive', 'crosstalk', 'flux', 'port'] = 'device'
metadata: dict[str, Any]
class quchip.engine.ir.DynamicTerm(operator, time_dependence, origin='drive', tag=None)[source]

Bases: object

Time-dependent Hamiltonian contribution operator · f(t).

f(t) is wrapped in ScalarModulation, which each backend lowers into its native coefficient representation (QuTiP callback, dynamiqs sampled array, etc.). The operator is 2π-scaled already (see module docstring). tag is an optional human label; it does not participate in physics.

Parameters:
operator: CanonicalOperator
time_dependence: ScalarModulation
origin: Literal['device', 'coupling', 'drive', 'crosstalk', 'flux', 'port'] = 'drive'
tag: str | None = None
class quchip.engine.ir.CollapseTerm(operator, rate, source, channel, parameter_paths=())[source]

Bases: object

Backend-neutral Lindblad operator and its separate rate.

Parameters:
operator: CanonicalOperator
rate: Any
source: str
channel: str
parameter_paths: tuple[str, ...] = ()
latex()[source]

Render this collapse channel as an opaque named operator.

Return type:

str

class quchip.engine.ir.PortTerm(operator, rate, phase, frame_frequency, label, parameter_paths=())[source]

Bases: object

Resolved input-output channel before the sqrt(rate) scaling.

Parameters:
operator: CanonicalOperator
rate: Any
phase: Any
frame_frequency: Any
label: str
parameter_paths: tuple[str, ...] = ()
class quchip.engine.ir.DroppedTerm(source, operator, reason, band_weights=None, amplitude=None, frequency=None)[source]

Bases: object

Advisory record for a Hamiltonian term elided by an approximation.

Emitted by physics components (couplings, drives, …) whose local Hamiltonian routines discard terms under an approximation such as the rotating-wave approximation. Assembly aggregates these records into EngineResult.dropped_terms so callers can audit what was silently removed — in particular, compare each dropped band’s amplitude against its oscillation frequency, the smallness ratio that governs RWA validity (leading correction ∼ amplitude²/frequency, the Bloch–Siegert scale).

The string fields are static and value-free. amplitude and frequency hold raw numeric values in GHz ordinary frequency — possibly JAX-traced; they are never formatted or branched on during assembly. band_weights is static structure (excitation-change weights, one per mode the operator acts on) that assembly uses to resolve frequency from the frame without the owner knowing frame references.

Parameters:
  • source (str) – Label of the owning component (coupling / drive / …) that dropped the term.

  • operator (str) – Human-readable operator string (e.g. "a_q0 · a_q1").

  • reason (str) – Short reason (e.g. "counter-rotating under RWA").

  • band_weights (tuple[int, ...] | None) – Excitation-change weights of the dropped band, one per endpoint mode in the owner’s declared order (e.g. (-1, -1) for a·b). None when not applicable.

  • amplitude (Any | None) – Static prefactor of the dropped term in GHz (e.g. the coupling g); possibly traced. None when the prefactor is time-dependent (drive envelopes) or unknown.

  • frequency (Any | None) – Oscillation frequency of the dropped band in the assembly frame, GHz, positive; possibly traced. None until resolved (assembly fills it from the frame and band_weights).

source: str
operator: str
reason: str
band_weights: tuple[int, ...] | None = None
amplitude: Any = None
frequency: Any = None
class quchip.engine.ir.EngineResult(static_terms, dynamic_terms, dims=(), metadata=<factory>, dropped_terms=(), collapse_terms=(), port_terms=(), bases=<factory>, authored=None, resolved_frame=None, approximation=None)[source]

Bases: object

Backend-agnostic time-dependent Hamiltonian passed to backends.

Represents

\[H(t) \;=\; \sum_s c_s \, O_s \;+\; \sum_d O_d \, f_d(t)\]

where each static / dynamic operator already carries 2π and each f_d(t) is a ScalarModulation over a SignalProgram AST. metadata carries advisory solver hints (e.g. max_carrier_freq_ghz, max_step_ns); a backend may consult them or apply an equivalent numerical strategy of its own, but remains responsible for resolving finite-support dynamics — a finite-width pulse must not be silently skipped by an adaptive integrator that never samples it. dropped_terms records any terms that owning components elided under an approximation (RWA, etc.) — advisory metadata for auditing, never consumed by backends.

Parameters:
static_terms: tuple[StaticTerm, ...]
dynamic_terms: tuple[DynamicTerm, ...]
dims: tuple[int, ...] = ()
metadata: dict[str, Any]
dropped_terms: tuple[DroppedTerm, ...] = ()
collapse_terms: tuple[CollapseTerm, ...] = ()
port_terms: tuple[PortTerm, ...] = ()
bases: Mapping[str, Any]
authored: Any = None
resolved_frame: Any = None
approximation: Any = None
hamiltonian()[source]

Return the exact canonical Hamiltonian as an inspectable expression.

This view is derived from the same terms backends receive. Matrix leaves remain opaque, while each dynamic coefficient renders as a named function of time.

Return type:

PhysicsExpr

latex()[source]

Render the canonical Hamiltonian with named time functions.

Return type:

str

dropped_terms_summary()[source]

Format dropped_terms as a multi-line human-readable string.

Traced amplitude / frequency values print as traced rather than being concretized.

Return type:

str

class quchip.engine.ir.HamiltonianTemplate(resolved_frame, approximation, dims, static_terms=(), invariant_dynamic_terms=(), drive_terms=(), reference_drive_ops=(), dropped_terms=(), weight_zero_drops=(), static_spectral_bound_ghz=None, collapse_terms=(), port_terms=(), bases=<factory>, authored=None)[source]

Bases: object

Chip-topology-invariant Hamiltonian skeleton.

Contains:

  • static_terms — already assembled H₀ and any static (same-frame) coupling folds.

  • invariant_dynamic_terms — dynamic terms whose signal programs do not depend on drive variants (e.g. band-decomposed couplings), already simplified at template-compile time.

  • drive_terms — pre-embedded, 2π-scaled drive bands (CompiledDriveTerm) ready for per-variant reinstantiation.

  • collapse_terms — canonical component-owned Lindblad operators.

  • reference_drive_ops — the structural yardstick used by instantiate_engine_result() to reject drive-ops that change the template’s skeleton (device, drive, envelope type, or drive type).

Sweep leaves (envelope parameters, drive frequencies, phases, frame scalars) are not in the template; they rebuild on every instantiation.

Parameters:
resolved_frame: Any
approximation: Any
dims: tuple[int, ...]
static_terms: tuple[Any, ...] = ()
invariant_dynamic_terms: tuple[Any, ...] = ()
drive_terms: tuple[Any, ...] = ()
reference_drive_ops: tuple[Any, ...] = ()
dropped_terms: tuple[Any, ...] = ()
weight_zero_drops: tuple[Any, ...] = ()

Single-tone weight-zero bands dropped structurally under RWA during engine assembly. time (_compile_drive_terms()). The drop decision needs no drive frequency; resolving each entry into a DroppedTerm does, so this stays a pointer (tuple[assembly._StructuralDrop, ...]) until instantiation.

static_spectral_bound_ghz: float | None = None

Advisory spectral-bound hint (ordinary GHz) for the static terms. Computed once at template compile — the static terms are invariant across a sweep, so re-materializing their dense diagonal on every instantiation is wasted work. None when empty, oversized, or not fully concrete (a traced coefficient stays dynamic). Only the variant-specific carrier-frequency hint is recomputed per instantiation.

collapse_terms: tuple[Any, ...] = ()
port_terms: tuple[Any, ...] = ()
bases: Mapping[str, Any]
authored: Any = None
quchip.engine.ir.FrameSpec: TypeAlias
class quchip.engine.ir.ResolvedFrame(frequencies, demod_freqs, mode)[source]

Bases: object

Resolved per-device frame information.

Describes the rotating-frame transformation applied uniformly to the chip:

  • frequencies[label] — the per-device integration-frame frequency ω_frame in GHz. The static Hamiltonian gets the counter-term −Σᵢ ω_frame,ᵢ nᵢ.

  • demod_freqs[label] = reference_freq ω_frame — the demodulation frequency used post-solve to rotate expectations back into the user’s control frame. reference_freq is the device attribute (see reference_freq); it merely defaults to the dressed drive frequency when not set explicitly.

  • mode — one of "lab" / "rotating" / "float" / "dict".

Parameters:
frequencies: dict[str, Any]
demod_freqs: dict[str, Any]
mode: str
class quchip.engine.ir.SolveProblem(chip, engine_result, initial_state, tlist, e_ops=None, e_ops_meta=None, resolved_frame=None, solver=None, options=<factory>)[source]

Bases: object

Immutable simulation request handed from the chip pipeline to a backend.

Bundles the EngineResult (Hamiltonian and collapse terms), an initial_state, solver time grid, decomposed e_ops + their BandMeta, the ResolvedFrame, and solver options. chip owns backend selection, so options must not contain a "backend" key (enforced in __post_init__). e_ops_meta is the metadata observable reconstruction uses to recombine flattened band expectations back into dict-keyed observables.

Parameters:
chip: Any
engine_result: Any
initial_state: Any
tlist: Any
e_ops: Any = None
e_ops_meta: Any = None
resolved_frame: Any = None
solver: str | None = None
options: dict[str, Any]
class quchip.engine.ir.SteadyStateProblem(chip, engine_result, e_ops=None, e_ops_meta=None, resolved_frame=None, options=<factory>)[source]

Bases: object

Immutable static Lindblad request handed from a chip to its backend.

Parameters:
chip: Any
engine_result: EngineResult
e_ops: Any = None
e_ops_meta: Any = None
resolved_frame: Any = None
options: dict[str, Any]
class quchip.engine.ir.SolveBatch(chip, problems, params=None, shape=(), axes=())[source]

Bases: object

Explicit solve problems sharing one dispatch owner and sweep shape.

Parameters:
chip: Any
problems: tuple[SolveProblem, ...]
params: Any = None
shape: tuple[int, ...] = ()
axes: tuple[tuple[str, Any], ...] = ()
property batch_size: int
property initial_states: tuple[Any, ...]
property tlist: Any
signals_for(slot)[source]

Return one dynamic slot across all batch points.

Parameters:

slot (int)

Return type:

tuple[ScalarModulation, …]

params_at(point)[source]

Return sweep values at one grid coordinate.

Parameters:

point (int | tuple[int, ...])

Return type:

dict[str, Any]

element(index)[source]
Parameters:

index (int)

Return type:

SolveProblem

class quchip.engine.ir.DriveOp(target_label, envelope, freq=None, start_time=0.0, phase_offset=0.0, drive_label='')[source]

Bases: object

Drive operation scheduled on a device or a modulable coupling.

freq is in GHz; None selects flux drive (or baseband edge pump). start_time and phase_offset apply in the control frame. drive_label resolves the drive in the chip’s control equipment (e.g. "charge_0"). target_label resolves in the chip’s device or coupling label space.

The pulse window [start_time, start_time + envelope.duration] must overlap the solve tlist with positive measure — a window that only touches a tlist endpoint contributes no evolution and is rejected (prepare_solve_problem_context()).

Parameters:
target_label: str
envelope: Envelope
freq: float | None = None
start_time: float = 0.0
phase_offset: float = 0.0
drive_label: str = ''