Skip to content

Models

Bases: Module

Abstract physical model.

Subclasses are immutable equinox modules (JAX pytrees), so they can be jitted, vmapped and differentiated through.

Parameter contract (used by :class:~qenvs.wrappers.randomization.ParameterRandomization): a model declares its randomisable Hamiltonian parameters in :meth:parameter_specs and implements :meth:with_parameters (a pure function, safe inside jit and vmap). The default with_parameters replaces the fields of the same name, so a model whose parameters are fields only has to declare them. Dissipation rates and structural sizes are never declared: naming one raises an error with the reason (non_parameters maps such field names to the reason).

dim abstractmethod property

Hilbert-space dimension.

is_open property

Whether the model has dissipation.

n_controls property

Number of control channels.

battery_hamiltonian()

Energy-storage Hamiltonian H_B (ground energy 0); battery models override.

battery_reduced(qstate)

Reduced battery state and the battery Hamiltonian acting on it.

Energy and ergotropy of a battery are properties of the battery subsystem alone. Models with ancillas (a charger cavity, a bath mode) override this to partial-trace them out and return H_B on the battery space. The default returns the full state and :meth:battery_hamiltonian.

check_parameters(**values)

Validate concrete parameter values before and after applying them.

Before: every name is declared, every value is a finite real number inside the support of its :class:ParameterSpec. After: the drift Hamiltonian of with_parameters(**values) is Hermitian (relative tolerance HERMITIAN_CHECK_RTOL). Raises ValueError naming the offending parameter. Needs concrete values (call it outside jit).

controls() abstractmethod

Control operators H_k; the total Hamiltonian is H_0 + sum_k u_k(t) H_k.

correlation_observables()

Hermitian second-order observables of the "correlations" observation mode.

Default: none. Models define the second moments that matter for their task (the Dicke models give the six symmetrised second moments of the collective spin).

drift() abstractmethod

Drift (uncontrolled) Hamiltonian H_0.

evolve(state, hamiltonian, duration, *, method=None)

Evolve state under hamiltonian for duration and return the final state.

Uses the Schrodinger equation for closed models and the Lindblad master equation otherwise. Density matrices are always accepted.

The ODE method (adaptive Tsit5 by default) takes as many internal integration steps as needed inside duration: the agent's control period and the integrator's time step are independent. For piecewise constant Hamiltonians dynamiqs.method.Expm() is exact.

hamiltonian(amplitudes)

Constant total Hamiltonian for fixed control amplitudes of shape (n_controls,).

initial_state() abstractmethod

Initial state (ket for closed systems, density matrix otherwise).

jump_ops()

Lindblad jump operators. Empty list means closed (unitary) dynamics.

observables()

Named Hermitian observables reported by environments (may be empty).

parameter_specs()

Randomisable Hamiltonian parameters: name to :class:ParameterSpec (default: none).

parameter_values()

Current (nominal) value of every declared parameter, in the unit of its spec.

pwc_hamiltonian(times, amplitudes)

Piecewise-constant Hamiltonian.

Parameters:

Name Type Description Default
times Array

interval boundaries, shape (N + 1,).

required
amplitudes Array

control amplitudes, shape (n_controls, N).

required

with_parameters(**values)

Return a copy of the model with the named parameters replaced (pure, jit and vmap safe).

Only declared parameters (:meth:parameter_specs) may be named; anything else (a dissipation rate, levels, a typo) raises ValueError with the reason. The values are not range-checked here (they may be tracers); use :meth:check_parameters for concrete values. The default implementation swaps the fields of the same name with equinox.tree_at.

Declaration of one randomisable Hamiltonian parameter of a model.

Attributes:

Name Type Description
unit str

unit of the parameter value, for example "GHz" or "rad/ns". A distribution that states its own unit must agree with it.

support tuple[float, float]

closed interval (lo, hi) of physically valid values; an end may be infinite (a transmon anharmonicity lives in (-inf, 0], a coupling in [0, inf), a detuning on the whole real line).

w_ref float

model reference width in the unit of the parameter: a typical device to device or calibration to calibration spread. It is used only to normalise the oracle observation (value - nominal) / w_ref and as the recommended scale in the docs, never to draw samples. 0 means "no reference scale": such a parameter is left out of the oracle observation.

contains(value)

Whether value lies in the closed support interval.

Bases: Model

Driven qubit with optional T1/T_phi dissipation.

Attributes:

Name Type Description
omega0 float

qubit (battery) frequency, sets the energy unit of H_B.

detuning float

drive-qubit detuning Delta in the rotating frame.

gamma1 float

relaxation rate (0 = none).

gamma_phi float

pure dephasing rate (0 = none).

initial str

"ground" or "excited".

battery_hamiltonian()

H_B = omega0 |1><1| (ground energy set to zero).

parameter_specs()

detuning: (-inf, inf), reference width 0.05.

The detuning has no sign constraint. The reference width 0.05 is about 3% of the Rabi rate pi / T = 1.57 of the default pi pulse (T = 2): a visible but small error (about 1 - F = 1e-3), the scale of a calibration drift relative to the drive strength. Units are those of the model (omega0 = 1).

Bases: Model

Driven qubit battery with a thermal bath and pure dephasing.

Attributes:

Name Type Description
omega0 float

qubit (battery) frequency, sets the energy unit of H_B.

detuning float

drive-qubit detuning Delta in the rotating frame.

gamma1 float

bath coupling rate; the emission rate is gamma1 (n_th + 1) and the absorption rate gamma1 n_th (0 = no bath).

n_th float

Bose occupation of the bath at the qubit frequency (0 = zero temperature).

gamma_phi float

pure dephasing rate (0 = none).

initial str

"ground" (|0>) or "thermal" (Gibbs state of H_B at the bath occupation, p1 = n_th / (2 n_th + 1)).

thermal_population property

Excited-state population n_th / (2 n_th + 1) of the Gibbs state at the bath.

battery_hamiltonian()

H_B = omega0 |1><1| (ground energy set to zero).

parameter_specs()

detuning: (-inf, inf), reference width 0.05 (see :class:TwoLevel).

Bases: Model

N two-level cells collectively coupled to one cavity mode (Dicke / Tavis-Cummings).

Attributes:

Name Type Description
n_cells int

number of cells N (collective spin j = N/2).

n_photons int | None

initial cavity Fock number; None means n_cells (Ferraro protocol: as many photons as cells).

n_max int | None

Fock cutoff. None means n_photons for rwa=True (exact, since Tavis-Cummings conserves the excitation number) and n_photons + 4 for rwa=False (counter-rotating terms create photons; the user must check convergence in the cutoff).

omega0 float

cell transition frequency, energy unit of H_B.

omega_c float

cavity frequency (detuning omega_c - omega0).

rwa bool

True for Tavis-Cummings, False for the full Dicke model.

kappa float

cavity photon loss rate (jump sqrt(kappa) a).

gamma float

collective emission rate (jump sqrt(gamma) J-).

gamma_phi float

collective dephasing rate (jump sqrt(gamma_phi) Jz).

cutoff property

Fock cutoff n_max with its default resolved.

dim_battery property

Dimension of the symmetric spin subspace, N + 1.

dim_cavity property

Dimension of the truncated Fock space, n_max + 1.

j property

Collective spin j = N/2.

photons property

Initial cavity photon number (n_photons with its default resolved).

a()

Cavity annihilation operator 1 (x) a.

adag()

Cavity creation operator 1 (x) a^dag.

battery_hamiltonian()

H_B = omega0 (Jz + N/2) on the full space (0 all ground, N omega0 charged).

battery_reduced(qstate)

Reduced cell state tr_cavity(rho) and H_B on the Dicke space.

Energy and ergotropy are properties of the cells, so the cavity (subsystem 1) is traced out first. Evaluating the ergotropy on the full cells+cavity state with H_B (x) 1 would give ergotropy == energy for every pure global state (closed dynamics); on the reduced state it is strictly smaller whenever the cells are entangled with the cavity.

correlation_observables()

Second moments of the collective spin on the full (cells x cavity) space.

Jx2, Jy2, Jz2, JxJy, JyJz and JzJx, where the mixed ones are symmetrised, JxJy = (Jx Jy + Jy Jx)/2, so all six are Hermitian (checked).

excitation_number()

Total excitation number a^dag a + Jz + N/2 (conserved by Tavis-Cummings).

initial_state()

All cells in the ground state, cavity in Fock state |n_photons>.

jminus()

Collective lowering operator J- (x) 1.

jplus()

Collective raising operator J+ (x) 1.

jz()

Collective inversion Jz (x) 1 with eigenvalues -N/2, ..., N/2.

local_battery_hamiltonian()

H_B = omega0 (Jz + N/2) on the (N + 1)-dimensional Dicke space alone.

number()

Photon number a^dag a.

parameter_specs()

omega_c in [0, inf), reference width 0.05.

Units are those of the model (omega0 = omega_c = 1 by default). A frequency is non-negative. 0.05 is a 5% spread, the order of the frequency mismatch between an emitter ensemble and its cavity. omega0 is not declared in this release (it is also the energy unit of H_B; see non_parameters). It is a modest perturbation of the charging protocol: with the constant coupling g = 0.25 over the default episode (20 steps of 0.2, N = 3) the stored energy <H_B> changes from 2.582 to 2.568 for omega_c = 0.95 or 1.05 (0.5%) and to 2.527 for omega_c = 1.1; a pulse tuned for the nominal detuning loses more.

top_fock()

Projector 1 (x) |n_max><n_max| on the highest kept Fock level.

Its expectation value is the population at the Fock cutoff; a value that is not negligible means the truncation is affecting the dynamics (raise n_max).

Bases: Model

N cells collectively coupled to a cavity, with local and collective dissipation.

Attributes:

Name Type Description
n_cells int

number of cells N.

n_photons int | None

initial cavity Fock number; None means n_cells.

n_max int | None

Fock cutoff. None means n_photons for rwa=True (exact when pumping_local = 0: the Tavis-Cummings excitation number cannot exceed its initial value) and n_photons + 4 for rwa=False (not a convergence guarantee, see battery/Dicke-v0). With pumping_local > 0 the excitation number is unbounded (a pumped cell emits into the cavity and is pumped again), no finite cutoff is exact, and n_max must be given explicitly; check convergence with :meth:top_fock (info['top_fock']), e.g. by comparing n_max and n_max + 4.

omega0 float

cell transition frequency, energy unit of H_B.

omega_c float

cavity frequency.

rwa bool

True for Tavis-Cummings, False for the full Dicke model.

kappa float

cavity loss rate (jump sqrt(kappa) a).

gamma float

collective emission rate (jump sqrt(gamma) J-).

gamma_phi float

collective dephasing rate (jump sqrt(gamma_phi) Jz).

gamma_local float

per-cell emission rate (jump sqrt(gamma_local) sigma_- on each cell).

gamma_phi_local float

per-cell dephasing rate (jump sqrt(gamma_phi_local) sigma_z / 2; a single-cell coherence decays at gamma_phi_local / 2).

pumping_local float

per-cell incoherent pumping rate (jump sqrt(pumping_local) sigma_+).

cutoff property

Fock cutoff n_max with its default resolved.

n_photons for rwa=True (exact only without local pumping, which requires an explicit n_max) and n_photons + 4 for rwa=False (no convergence guarantee).

dim property

Dimension 2^N (n_max + 1) of the stored (Schur-basis) density matrix.

dim_cavity property

Dimension of the truncated Fock space, n_max + 1.

dim_cells property

Dimension of the full cell space, 2^N.

is_open property

Always True: the state is a density matrix even with every rate at zero.

j property

Largest collective spin N/2 (the symmetric sector).

layout property

Static index maps of the permutation-invariant representation.

liouvillian_dim property

Number of independent entries sum_j ((2j + 1)(n_max + 1))^2.

photons property

Initial cavity photon number (n_photons with its default resolved).

sectors property

(j, d_j) of every sector in storage order (j = N/2 first).

a()

Cavity annihilation operator 1 (x) a.

adag()

Cavity creation operator 1 (x) a^dag.

battery_hamiltonian()

H_B = omega0 (Jz + N/2) on the full stored space.

battery_reduced(qstate)

Full 2^N-dimensional cell state (cavity traced out) and H_B on it.

Both are written in the Schur basis; energy and ergotropy are basis independent, so they equal those of the cell state in the computational basis. The eigenvalues of the reduced state are those of every block sigma_j divided by d_j, each repeated d_j times (see :meth:ergotropy_from_blocks).

correlation_observables()

Second moments of the collective spin on the full 2^N (n_max + 1) stored space.

Jx2, Jy2, Jz2, JxJy, JyJz and JzJx (the mixed ones symmetrised, all Hermitian, checked), built from the collective operators in the Schur basis, so each is block diagonal with identical copies per sector.

dicke_density(qstate)

Cell state in the Dicke basis: block-diagonal (n_ds, n_ds), unit trace.

n_ds = sum_j (2j + 1); blocks sigma_j (cavity traced out) for j = N/2, N/2 - 1, ..., m ascending inside a block. This is the representation of Shammah et al. (2018) and QuTiP PIQS (which orders m descending inside a block).

dissipator()

Constant (collective + local) part of the Liouvillian on the compact vector.

The array is cached and shared between models with equal parameters, so it is read-only; copy it before modifying.

ergotropy_from_blocks(qstate)

Ergotropy of the full cell state from the Dicke blocks and their degeneracies.

Eigenvalues of every cell block sigma_j divided by d_j and repeated d_j times give the 2^N spectrum of the cell state; H_B has level k omega0 with multiplicity C(N, k). Equals the ergotropy of :meth:battery_reduced (checked in the validation).

evolve(state, hamiltonian, duration, *, method=None)

Exact step vec sigma -> expm(L(H) duration) vec sigma for a constant H.

method is ignored (the matrix exponential is exact for piecewise-constant controls); time-dependent Hamiltonians are rejected.

excitation_number()

a^dag a + Jz + N/2 (conserved by closed Tavis-Cummings dynamics only).

from_blocks(vec)

Stored density matrix (d_j copies of sigma_j / d_j) from the compact vector.

initial_state()

All cells ground (j = N/2, m = -N/2), cavity in |n_photons> (density matrix).

jminus()

Collective lowering operator J- (x) 1.

jplus()

Collective raising operator J+ (x) 1 in the stored basis.

jump_ops()

Not available: local jumps act across copies of the multiplicity space.

The dissipation enters :meth:evolve through :meth:liouvillian. Raising here prevents a generic solver from silently dropping the local processes.

jz()

Collective inversion Jz (x) 1.

liouvillian(hamiltonian)

Full Liouvillian -i [H, .] + D on the compact vector for a collective H.

H is given in the stored basis (e.g. model.hamiltonian(g)); only its sector blocks are used (a collective Hamiltonian is block diagonal with identical copies).

local_battery_hamiltonian()

H_B on the 2^N cell space (Schur basis).

Level k omega0 has multiplicity C(N, k).

number()

Photon number a^dag a.

parameter_specs()

omega_c in [0, inf), reference width 0.05.

Same declaration and justification as :meth:DickeBattery.parameter_specs (omega0 is not declared in this release).

symmetric_projector()

Projector on the symmetric sector j = N/2 (the subspace of battery/Dicke-v0).

Its trace is (N + 1) times the cavity dimension n_max + 1.

to_blocks(qstate)

Compact vector of the joint blocks sigma_j = d_j R_j (row-major, sum of traces 1).

top_fock()

Projector on the highest kept Fock level (Fock truncation monitor).

Its expectation value is the convergence diagnostic of the cutoff (info['top_fock'], the same name as in battery/Dicke-v0): a population that is not negligible means the truncation affects the dynamics, so raise n_max. It is the only guard when pumping_local > 0 or rwa=False.

Bases: Model

Lambda system |1> <-> |2> <-> |3> driven by pump and Stokes fields.

Attributes:

Name Type Description
delta_one_photon float

one-photon (pump) detuning Delta of |2>.

delta_two_photon float

two-photon detuning delta of |3>.

gamma float

total spontaneous-emission rate of |2> (0 = closed system). The decay branches equally into |1> and |3>; losses to states outside the Lambda manifold are not modelled.

initial str

"1", "2" or "3", the initially populated bare state.

controls()

[pump, Stokes]: (|1><2| + h.c.) / 2 and (|3><2| + h.c.) / 2.

drift()

Delta |2><2| + delta |3><3|.

jump_ops()

Spontaneous emission from |2> with equal branching into |1> and |3>.

observables()

Bare-state populations p1, p2, p3.

parameter_specs()

Both detunings: (-inf, inf); reference widths 0.05 and 0.01.

Units are those of the Rabi frequencies (the default bound is 1, T = 20). Adiabatic transfer tolerates a one-photon detuning of a few percent of the peak Rabi frequency, but is more sensitive to the two-photon detuning, which tilts the dark state; its reference width is therefore five times smaller. Measured on the reference STIRAP pulse of the default task: 1 - F is 3.6e-3 at nominal, 4.2e-3 for delta_one_photon = 0.05, 3.8e-3 for delta_two_photon = 0.01 and 9.7e-3 for delta_two_photon = 0.05.

Bases: Model

Multi-level transmon (Duffing oscillator) with I/Q drive and optional T1/T2.

UNITS: time in ns, angular frequency in rad/ns; the fields below are in GHz (ordinary frequency) and microseconds.

Attributes:

Name Type Description
levels int

number of transmon levels kept (>= 2; 3 captures leakage to |2>).

anharmonicity_ghz float

alpha / (2 pi) in GHz (transmon: negative, about -0.3).

detuning_ghz float

(f_q - f_d) in GHz, qubit frequency minus drive frequency.

t1_us float | None

energy relaxation time T1 in microseconds (None = no relaxation).

t2_us float | None

coherence time T2 in microseconds, T2 <= 2 T1 (None = no pure dephasing, i.e. T2 = 2 T1).

initial str

initial level as a string, '0' (ground) by default; used by environments to report observables of map(initial state).

alpha property

Anharmonicity in rad/ns.

delta property

Detuning f_q - f_d in rad/ns.

gamma1 property

Relaxation rate 1/T1 in 1/ns (0 if t1_us is None).

gamma_phi property

Pure dephasing rate 1/T_phi = 1/T2 - 1/(2 T1) in 1/ns (0 if t2_us is None).

from_properties(props, *, levels=3, detuning_ghz=0.0) classmethod

Build a transmon from device properties (explicit units or SI values).

props is a mapping with anharmonicity_ghz, t1_us, t2_us and frequency_ghz, or with the SI values (seconds and hertz, each either a bare number or a (value, timestamp) tuple) that Qiskit's BackendProperties.qubit_property(q) returned: 'T1', 'T2', 'frequency', 'anharmonicity'. Qiskit is not imported. The rotating-frame model does not use the qubit frequency (give the drive offset as detuning_ghz); read it with :func:qenvs.pulses.parse_properties if you want it as pulse metadata.

A missing anharmonicity keeps the model default and emits a UserWarning; missing t1_us / t2_us mean no dissipation from that source. T2 > 2 T1 raises ValueError. See :func:qenvs.pulses.parse_properties for the accepted keys.

number()

Number operator n = a^dag a.

parameter_specs()

detuning_ghz on the whole line and anharmonicity_ghz in (-inf, 0] (GHz).

Reference widths: 2 MHz for the detuning (frequency drift and two-level-system shifts of a fixed-frequency transmon between calibrations are of order 0.1 to a few MHz, against the 50 MHz Rabi bound of the gate tasks) and 5 MHz for the anharmonicity (about 1.5% of -340 MHz, the device-to-device spread of a fabricated junction). A transmon anharmonicity is negative, so a Gaussian offset needs a TruncatedNormal. At this width the anharmonicity barely changes the error of the reference X-gate pulse, so a robustness result under anharmonicity_ghz alone at w_ref is close to a null test; widen it deliberately if that axis is the point.

Bases: Model

Control and target transmon with exchange coupling, both driven at the target frequency.

UNITS: time in ns, angular frequency in rad/ns; the fields below are in GHz (ordinary frequency) and microseconds. Tensor order control (x) target.

Attributes:

Name Type Description
levels int

levels kept per transmon (>= 2; 3 captures leakage to |2>).

detuning_ghz float

f_c - f_t in GHz (bare control minus bare target frequency); the drive frequency is f_t.

anharmonicity_c_ghz float

control anharmonicity alpha_c / (2 pi) in GHz.

anharmonicity_t_ghz float

target anharmonicity alpha_t / (2 pi) in GHz.

coupling_ghz float

exchange coupling J / (2 pi) in GHz.

t1_c_us, t2_c_us

control T1 / T2 in microseconds (None: no such channel).

t1_t_us, t2_t_us

target T1 / T2 in microseconds.

initial str

initial computational state '00', '01', '10' or '11' (control digit first); environments report observables of map(initial).

alpha_c property

Control anharmonicity in rad/ns.

alpha_t property

Target anharmonicity in rad/ns.

computational_indices property

Indices of |00>, |01>, |10>, |11> (control digit first) in the d^2 basis.

coupling property

Exchange coupling J in rad/ns.

delta property

Detuning 2 pi (f_c - f_t) in rad/ns.

dressed_energies()

Drift eigenvalues assigned to |00>, |01>, |10>, |11> by maximal overlap (rad/ns).

Energies are in the common frame; E11 - E10 - E01 + E00 is frame independent.

frame_unitary(duration)

exp(+i Delta n_c T): common frame to bare qubit frames after T = duration ns.

numbers()

Number operators (n_c, n_t).

ops()

Dense ladder operators (a, b) of control and target on the d^2 space.

parameter_specs()

Both anharmonicities and the coupling, in GHz.

Supports: anharmonicities (-inf, 0], coupling [0, inf) (a negative exchange sign is a different device, not a variation of this one). Reference widths: 5 MHz for each anharmonicity and 0.3 MHz for the coupling (10% of the nominal 3 MHz, the usual fabrication spread of a capacitive coupling). The detuning is not declared in this release; see non_parameters for the reason.

static_zz()

Static ZZ rate zeta = E11 - E10 - E01 + E00 of the dressed states (rad/ns).

Exact diagonalisation of the undriven Hamiltonian; with H_ZZ = (zeta / 4) Z (x) Z this is the shift of the |11> energy relative to the uncoupled sum.

Bases: Model

Model defined by user supplied matrices: H(t) = H_0 + sum_k u_k(t) H_k plus Lindblad ops.

Build it with HamiltonianModel(...) or the equivalent :meth:from_operators; both validate their inputs (see the module docstring).

Parameters:

Name Type Description Default
drift object

drift Hamiltonian H_0, Hermitian (n, n).

required
controls object

control operators H_k; one operator, a sequence, or a (k, n, n) stack. At least one is required (the environments need an action space).

required
jump_ops object

Lindblad jump operators L_j (any square (n, n) matrices, absorbed rates included, i.e. pass sqrt(gamma) * L). Empty means closed dynamics.

()
initial_state object | None

normalised ket ((n,) or (n, 1)) or density matrix. Defaults to the basis state |0> (index 0).

None
observables Mapping[str, object] | None

mapping name to Hermitian operator, reported in info by the environments.

None
battery_hamiltonian object | None

Hermitian H_B on the full space, needed by :class:~qenvs.envs.BatteryCharging. The energy and ergotropy are evaluated on the full state; for a battery that is only one subsystem of a composite system subclass and override battery_reduced (see the custom-models guide).

None
battery_subsystems tuple[int, ...] | None

optional increasing tuple of retained tensor-factor indices. Supply with subsystem_hamiltonian instead of battery_hamiltonian.

None
subsystem_hamiltonian object | None

Hermitian Hamiltonian on the retained factors, ground energy zero. Energy agrees with its full-space embedding; ergotropy is computed after partial trace.

None
dims Sequence[int] | None

subsystem dimensions of a composite system, e.g. (2, 2) for two qubits (their product must be n). Inferred from QArray/Qobj inputs when omitted, else (n,). Needed for dq.ptrace on the model's states.

None
parameters Mapping[str, Sequence[object]] | None

named real drift parameters, mapping name to (nominal, operator, unit, support, w_ref): the drift becomes H_0 + sum_k p_k O_k. operator is Hermitian (n, n), unit a string, support the closed interval (lo, hi) of valid values (ends may be infinite) containing nominal, w_ref >= 0 the reference width of the oracle observation. See :class:~qenvs.models.base.ParameterSpec.

None

Raises:

Type Description
ValueError

on any violated construction guarantee, naming the operator.

Attributes:

Name Type Description
drift_matrix Array

stored H_0 as a complex array.

control_matrices Array

stored controls, shape (k, n, n).

jump_matrices Array

stored jump operators, shape (m, n, n).

initial_matrix Array

stored initial state, ket (n, 1) or density matrix (n, n).

observable_matrices dict[str, Array]

stored observables by name.

battery_matrix Array | None

stored H_B or None.

dims tuple[int, ...]

composite subsystem dimensions (static).

parameter_nominals dict[str, Array]

current values p_k of the parameter terms, by name.

parameter_matrices dict[str, Array]

operators O_k of the parameter terms, by name.

parameter_spec_items tuple[tuple[str, ParameterSpec], ...]

(name, ParameterSpec) pairs of the parameter terms (static).

is_open property

True when the model carries jump operators or a mixed (density-matrix) state.

battery_reduced(qstate)

Return the declared battery subsystem, or preserve the legacy full-state path.

drift()

H_0, plus sum_k p_k O_k over the parameter terms (names in sorted order).

evolve(state, hamiltonian, duration, *, method=None)

Evolve as :meth:Model.evolve, keeping the composite dims on the result.

dynamiqs 0.3.6 drops the subsystem dims of a density matrix integrated with Expm ((2, 2) becomes (4,)), which breaks ptrace and the lax.scan carry of an environment rollout; they are restored here.

from_operators(drift, controls, jump_ops=(), initial_state=None, observables=None, battery_hamiltonian=None, dims=None, parameters=None, *, battery_subsystems=None, subsystem_hamiltonian=None) classmethod

Build and validate a model from operators; see the class docstring for the arguments.

parameter_specs()

The parameter terms declared with parameters= (empty if there are none).

parameter_values()

Current values p_k of the parameter terms.

with_parameters(**values)

Copy with the named parameter terms set to values (pure, jit and vmap safe).

Pulses

Pulse I/O and device parameters for hardware toolchains.

A :class:Pulse is an immutable record of a piecewise-constant pulse as QEnvS produces it (the actions of a rollout): the samples, the sample period, the channel names, the units and the provenance. It serialises losslessly to JSON and NPZ, converts transmon amplitudes between rad/ns and MHz, refines a pulse exactly onto a finer sample grid (for example 2/9 ns) and pads it with zeros to the granularity of an arbitrary waveform generator.

UNITS: dt_ns is the sample period in nanoseconds for the transmon tasks (units 'rad/ns', amplitudes are angular frequencies Omega, the Rabi frequency is Omega / (2 pi)). For the tasks in units of the transition frequency (units 'dimensionless') the field keeps the name dt_ns but holds the dimensionless period in units of 1 / omega0; the MHz helpers refuse such pulses.

:func:parse_properties reads device parameters (frequency, anharmonicity, T1, T2) from a plain mapping with explicit units or with the SI values that Qiskit's BackendProperties.qubit_property returned; it is the engine behind :meth:qenvs.models.transmon.Transmon.from_properties. Nothing here imports Qiskit.

QEnvS does not model an AWG transfer function, does not calibrate amplitudes and does not talk to hardware; see docs/guides/pulses.md.

DeviceProperties dataclass

Device parameters in the units of :class:~qenvs.models.transmon.Transmon.

None means "not given". frequency_ghz is not used by the rotating-frame model (only the detuning from the drive matters); keep it as pulse metadata.

Pulse

Immutable piecewise-constant pulse.

Parameters:

Name Type Description Default
samples Any

amplitudes, shape (n, channels); copied to a read-only float64 array.

required
dt_ns float

sample period (ns for 'rad/ns' pulses), positive and finite.

required
channels Sequence[str] | None

one unique name per column; default 'u0', 'u1', ...

None
units str

'rad/ns' (transmon tasks), 'dimensionless' (omega0-unit tasks) or any other label; only 'rad/ns' supports the MHz helpers.

UNITS_RAD_PER_NS
metadata Mapping[str, Any] | None

JSON-compatible mapping (task id, task kwargs, qenvs version, fidelity, ...); deep-copied, so later changes of the argument do not leak in.

None

Attributes:

Name Type Description
samples ndarray

read-only (n, channels) float64 array.

metadata dict[str, Any]

a fresh deep copy on every access (the record itself cannot change).

channels property

Channel names, one per column.

dt_ns property

Sample period (ns for 'rad/ns' pulses).

duration_ns property

Total duration n_samples * dt_ns.

metadata property

Provenance and optional numbers; a fresh deep copy on every access.

n_channels property

Number of channels.

n_samples property

Number of samples.

samples property

Read-only (n, channels) float64 array.

units property

Units of the amplitudes: 'rad/ns' or 'dimensionless'.

area()

Per-channel area sum(samples) * dt_ns, shape (channels,) (rad for rad/ns).

On resonance a constant-phase drive with area theta on channel I rotates a two-level system by theta about x (pi for an X gate).

from_actions(actions, dt, *, task_id=None, task_kwargs=None, channels=None, units=None, **metadata) classmethod

Record the actions of a rollout (shape (horizon, action_dim)) as a pulse.

Parameters:

Name Type Description Default
actions Any

numpy or jax array of actions, (horizon, action_dim).

required
dt float

the control period of the environment (env.dt).

required
task_id str | None

registered task id; sets the units from registry[task_id].units ('rad/ns' when its time unit is ns, else 'dimensionless') and the default channel names (('I', 'Q') for a Transmon model with two controls, else 'u0', 'u1', ...).

None
task_kwargs Mapping[str, Any] | None

kwargs the task was made with, kept as provenance (must be JSON compatible).

None
channels Sequence[str] | None

explicit channel names.

None
units str | None

explicit units; defaults to the task's, or 'rad/ns' without a task id (the hardware units of the transmon tasks, assumed, not checked). Giving units that contradict the task raises ValueError.

None
**metadata Any

extra JSON-compatible provenance, e.g. fidelity=0.9999.

{}

The metadata always records the qenvs_version, plus task_id and task_kwargs when given. Float32 actions are widened to float64 exactly.

from_dict(data) classmethod

Inverse of :meth:to_dict; rejects unknown schemas and missing fields.

from_json(source) classmethod

Read a pulse from JSON text, a path to a JSON file or an already parsed mapping.

A str whose first non-blank character is { is JSON text; any other str and any path-like object is a file name.

from_npz(path) classmethod

Read an archive written by :meth:to_npz (allow_pickle=False).

from_rabi_mhz(rabi_mhz, dt_ns, *, channels=('I', 'Q'), **kwargs) classmethod

Build a 'rad/ns' pulse from Rabi frequencies in MHz (shape (n, channels)).

Inverse of :meth:rabi_mhz up to rounding. kwargs go to :meth:from_actions (task_id, task_kwargs, metadata); units is fixed to 'rad/ns'.

pad(n_samples=None, *, multiple=None)

Append zeros: to a total of n_samples samples, or to the next multiple.

Give exactly one of the two. pad(multiple=16) meets an AWG granularity of 16 samples. The padded pulse records the original length in metadata['unpadded_n_samples']; :meth:resample scales it, so resample first and pad second. The zeros are idle time: when a padded pulse is simulated, the drift (detuning, anharmonicity) and, in an open system, T1/T2 decay act during it, whereas hardware frame tracking does not.

rabi_mhz()

Rabi frequency in MHz of every sample, samples / (2 pi) * 1e3 ('rad/ns' only).

resample(sample_dt_ns)

Refine the pulse onto a finer grid by sample-and-hold; exact for piecewise-constant.

Every sample is repeated k = dt_ns / sample_dt_ns times and the new period is dt_ns / k. k must be an integer to within 1e-9 relative; a ratio below 1 (coarsening) or a non-integer ratio raises ValueError, because the held pulse would no longer be the same function of time. The metadata records the factor in metadata['resampled']; a task_kwargs entry still describes the original task. An existing metadata['unpadded_n_samples'] is multiplied by k so that it keeps counting samples of the new grid; the intended order is resample, then pad.

to_actions()

Writable float64 copy of the samples, shape (n, channels): env.rollout input.

to_dict()

JSON-compatible dictionary with 'schema': 'qenvs.pulse/v1'.

to_json(path=None, *, indent=None)

JSON text, written to path too if given.

The text is ASCII and floats use the shortest round-trip repr, so it is lossless.

to_npz(path, *, compressed=False)

Write a NumPy .npz archive (no pickle); float64 samples are stored bit-exactly.

A str or path is written as given (no .npz is appended behind your back); a binary file object is also accepted.

mhz_to_rad_per_ns(rabi_mhz)

Angular frequency in rad/ns of a Rabi frequency in MHz: 2 pi * rabi_mhz * 1e-3.

parse_properties(props)

Read device parameters from a mapping, with units in the key names or in SI.

Accepted keys (other keys, such as readout errors, are ignored):

  • explicit units: frequency_ghz, anharmonicity_ghz, t1_us, t2_us;
  • SI, as returned by Qiskit's BackendProperties.qubit_property(q), a mapping {'T1': (seconds, timestamp), 'T2': (seconds, timestamp), 'frequency': (Hz, timestamp), 'anharmonicity': (Hz, timestamp)}; every value may also be a bare number.

Qiskit is not imported; anything shaped like this works. Supplying the same quantity in both forms, a key such as t1_ms (a unit-suffixed name this function does not know), T2 > 2 T1, or a non-positive T1 or T2 raises an error instead of guessing.

rad_per_ns_to_mhz(omega)

Rabi frequency in MHz of an angular frequency omega in rad/ns: omega / (2 pi) * 1e3.

A constant Omega = pi / 20 rad/ns for 20 ns is a pi pulse and gives 25 MHz.

Gate fidelity tools

Gate targets and gate-quality measures for (possibly leaky) unitaries and channels.

Conventions:

  • Basis index 0 is the ground state, index 1 the excited state; a k-level target acts on the first k levels (the computational subspace) of a d-level system. Every fidelity and leakage function also accepts subspace: a sequence of k basis indices that span the computational subspace, in the order of the target's basis (for two qutrits in control (x) target order, (0, 1, 3, 4)). The default None means the first k levels.
  • Average gate fidelity is averaged over Haar-random pure inputs inside the computational subspace and compares with the ideal output (Wood and Gambetta, Phys. Rev. A 97, 032306 (2018), Eqs. (5)-(6))::

    F = [k (1 - L) + k^2 F_pro] / (k (k + 1)) = (k F_pro + 1 - L) / (k + 1)

with leakage rate L = Tr[(1 - P) E(P / k)] and process fidelity F_pro = (1/k^2) sum_ij <i| U_t^dag E(|i><j|) U_t |j>. For a unitary U this reduces to the closed form of Pedersen, Moller and Molmer, Phys. Lett. A 367, 47 (2007): F = [Tr(M M^dag) + |Tr M|^2] / (k (k + 1)) with M = P_k U_t^dag U P_k. Global phases are irrelevant; relative phases (including Z errors) count. * Superoperators use dynamiqs' column-stacking vectorisation, vec(rho)[i + d j] = rho[i, j] (checked against dq.vectorize and mesolve), so vec(U rho U^dag) = (conj(U) kron U) vec(rho).

All functions accept JAX arrays or dynamiqs QArray objects and broadcast over leading batch dimensions.

apply_superop(s, rho)

Apply a column-stacking superoperator s (d^2 x d^2) to rho (d x d).

average_gate_fidelity(u, target, *, subspace=None)

Average gate fidelity of a d-level unitary u against a k-level target.

F = [Tr(M M^dag) + |Tr M|^2] / (k (k + 1)), M = target^dag P u P (Pedersen et al. 2007), with P the projector on the first k levels or on the basis states listed in subspace (in the target's basis order). Population leaked out of the subspace lowers Tr(M M^dag) and |Tr M|. Equal to 1 iff u acts as target on the subspace up to a global phase. Batched over leading dimensions of u.

gate(name)

Named single-qubit target as a (2, 2) complex array (see :data:TARGETS).

leakage(u, k=2, *, subspace=None)

Leakage rate of a unitary out of the first k levels (or out of subspace).

L = 1 - (1/k) sum_{i,j<k} |u_ji|^2, evaluated as the equivalent (for unitary u) sum of leaked populations (1/k) sum_{i<k, j>=k} |u_ji|^2, which avoids cancellation when L is tiny and stays non-negative. When subspace is given, k = len(subspace) and the sums run over those indices and their complement.

rz(theta)

Rz(theta) = diag(exp(-i theta/2), exp(i theta/2)).

superop_average_gate_fidelity(s, target, *, subspace=None)

Average gate fidelity of a (leaky) channel s against a k-level target.

F = (k F_pro + 1 - L') / (k + 1) with 1 - L' = Tr[P E(P / k)] (Wood and Gambetta 2018, Eq. (6)), computed as an exact Haar average over pure inputs in the computational subspace (first k levels, or subspace). Equals :func:average_gate_fidelity for a unitary channel.

superop_leakage(s, k=2, *, subspace=None)

Leakage rate L = Tr[(1 - P) E(P / k)] of a channel (Wood and Gambetta 2018, Eq. (2)).

Equals 1 - Tr[P E(P / k)] for a trace-preserving map and reduces to :func:leakage for a unitary channel. P projects on the first k levels or, when given, on subspace (then k = len(subspace)).

superop_process_fidelity(s, target, *, subspace=None)

Process fidelity on the subspace (1/k^2) sum_ij <i|U_t^dag E(|i><j|) U_t|j>.

unitary_to_superop(u)

Column-stacking superoperator of rho -> u rho u^dag: conj(u) kron u.

Thermodynamic and information observables shared by models and environments.

energy(state, hamiltonian)

Mean energy tr(rho H) (real).

ergotropy(state, hamiltonian)

Maximum work extractable by a unitary (Allahverdyan et al., 2004).

E = tr(rho H) - min_U tr(U rho U^dag H), where the minimum is attained by the passive state: eigenvalues of rho in decreasing order paired with eigenvalues of H in increasing order.

fidelity(state, target)

State fidelity in [0, 1].

For a pure target (ket) this is <t|rho|t>, which equals the Uhlmann fidelity and, unlike the general square-root formula, has a finite gradient when state is a density matrix (the general formula differentiates sqrt of a rank-1 matrix and returns NaN). Mixed targets fall back to dynamiqs.fidelity.