Skip to content

Validation

Shared types for physics validation checks.

CheckResult dataclass

Outcome of one validation check.

to_dict()

Plain-dict form for JSON output.

environment_info()

Versions and platform, reported next to validation numbers.

result(name, category, error, tol, detail, model='')

Build a :class:CheckResult from an absolute error and a tolerance.

skipped(name, category, tol, detail, model='')

A check that could not run (e.g. optional dependency missing); never counts as passed.

Generic checks for any model

Generic physics and numerics checks for any :class:~qenvs.models.Model.

:func:model_checks is the entry point used by qenvs validate --model and by :func:qenvs.toolkit.validate_model. It needs no closed-form answer, so it runs on models you wrote yourself (typically :class:~qenvs.models.custom.HamiltonianModel).

What the checks establish: the operators are Hermitian and consistently shaped, the initial state is valid, the integrator preserves the norm (closed) or keeps rho Hermitian, unit-trace and positive semidefinite (open) along a random piecewise-constant rollout through the real environment code, the default solver agrees with a much tighter one (and with the exact matrix exponential where that is cheap), QuTiP integrates the same matrices to the same states, and, if a battery Hamiltonian is given, the thermodynamic bounds 0 <= ergotropy <= energy - E_min hold.

What they cannot establish: that the matrices are the physics you meant. A sign error in a coupling, swapped controls, a reversed basis ordering or a wrong rate are valid physics of a different system and pass every check below. Without reference= the QuTiP check (named qutip_solver_cross_check) is built from the same matrices as the model, so it validates the solver stack, not the matrices; pass reference= (an independently built model of the intended physics) to cross-check the matrices too (qutip_cross_check). See docs/guides/custom-models.md.

Time step rule (dt=None): with b = action_bound,

w = ||H_0|| + b * sum_k ||H_k|| + sum_j ||L_j||^2,        dt = 1 / w,

with ||.|| the spectral (2-) norm and w = 0 mapped to dt = 1. w bounds the fastest rate in the dynamics, so each control interval rotates the state by about one radian at most and horizon steps span horizon / w. Models whose drift is much larger than the controls and rates (a lab-frame Hamiltonian) get a tiny dt and a short episode; pass dt explicitly for those.

Tolerances hold in float32 and float64 (see the constants below). The accuracy of the default adaptive solver (rtol = atol = 1e-6) sets the floor of the numerics checks, not the floating-point precision.

Tolerance scaling rule: the rollout-based checks (norm or density matrix, solver, QuTiP, battery consistency, ergotropy bounds) accumulate integrator error along the episode, so their tolerance is the base constant times

s = max(1, horizon * dt / (REFERENCE_STEPS * dt_default)),        REFERENCE_STEPS = 12,

with dt_default = default_dt(model, action_bound). s is the integrated time in units of the model's fastest rate: 1 for the default rollout (12 steps at the default dt), and proportional to the episode length or to a coarser dt beyond it. A valid model therefore passes at horizon=400 or dt = 3 * default; the static checks (structure, hermiticity, initial_state_valid) are not scaled. The reported tolerance is the scaled one and the detail states the factor.

EXPM_MAX_DIM_OPEN = 16 module-attribute

Largest Hilbert dimension for which the exact Liouvillian exponential is used (open).

JIT_MIN_HORIZON = 48 module-attribute

Rollouts longer than this compile the exact-propagator step instead of dispatching it eagerly.

N_RANDOM_STATES = 8 module-attribute

Random density matrices of the battery space added to the ergotropy bound check.

REFERENCE_STEPS = 12 module-attribute

Rollout length (the default horizon) at the default dt for which the base tolerances are calibrated; longer or coarser rollouts scale them (see the module doc).

TOL_CONSERVATION = 5e-05 module-attribute

Norm drift (closed) or Hermiticity, trace and negativity (open) along the rollout.

TOL_HERMITIAN = 1e-06 module-attribute

Relative asymmetry max|A - A^dag| / max|A| of the operators.

TOL_QUTIP = 5e-05 module-attribute

Maximum entry-wise state difference to QuTiP along the rollout.

TOL_SOLVER = 5e-05 module-attribute

Maximum entry-wise state difference between the method under test and a reference solver.

TOL_STATE = 1e-05 module-attribute

Norm, trace, Hermiticity and negativity of the initial state.

TOL_THERMO = 1e-05 module-attribute

Violation of 0 <= ergotropy <= energy - E_min, relative to the width of the H_B spectrum.

default_dt(model, action_bound=1.0)

Control period used by :func:model_checks when dt is not given (see module doc).

model_checks(model, *, horizon=12, dt=None, action_bound=1.0, seed=0, method=None, reference=None)

Run the generic physics and numerics checks on model.

Parameters:

Name Type Description Default
model Model

any :class:~qenvs.models.Model.

required
horizon int

number of piecewise-constant control steps of the random rollout.

12
dt float | None

control period; None chooses it from the operator norms (see the module docstring for the rule, also available as :func:default_dt).

None
action_bound float

random amplitudes are drawn uniformly from [-b, b].

1.0
seed int

seed of the random amplitudes.

0
method Method | None

dynamiqs solver under test (default: the library default, adaptive Tsit5). The convergence check compares it with a tight Tsit5 and, where cheap, with Expm.

None
reference Model | None

optional independently built model of the intended physics. When given, QuTiP integrates the reference's matrices and the result is compared with the dynamiqs rollout of model (check name qutip_cross_check); this is the only generic check that can detect a wrong operator (it needs you to have built the operator twice). Without it the check is named qutip_solver_cross_check and validates the solver only. An error is caught only if it moves the state by more than the tolerance over the episode, roughly rate * T * relative_error > tol (see the guide).

None

Returns:

Name Type Description
One list[CheckResult]

class:~qenvs.validation.core.CheckResult per check: structure,

list[CheckResult]

hermiticity, initial_state_valid, norm_conservation (closed) or

list[CheckResult]

density_matrix_valid (open), solver_convergence, the QuTiP check

list[CheckResult]

(qutip_solver_cross_check without reference, qutip_cross_check with it;

list[CheckResult]

skipped without QuTiP) and, when the model defines a battery Hamiltonian,

list[CheckResult]

battery_consistency and ergotropy_bounds. The rollout-based tolerances are

list[CheckResult]

scaled with the integrated time (see the module docstring).

tolerance_scale(model, horizon, dt, action_bound=1.0)

Factor max(1, horizon * dt / (REFERENCE_STEPS * default_dt)) on rollout tolerances.