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: |
required |
horizon
|
int
|
number of piecewise-constant control steps of the random rollout. |
12
|
dt
|
float | None
|
control period; |
None
|
action_bound
|
float
|
random amplitudes are drawn uniformly from |
1.0
|
seed
|
int
|
seed of the random amplitudes. |
0
|
method
|
Method | None
|
dynamiqs solver under test (default: the library default, adaptive
|
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 |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
One |
list[CheckResult]
|
class: |
list[CheckResult]
|
|
|
list[CheckResult]
|
|
|
list[CheckResult]
|
( |
|
list[CheckResult]
|
|
|
list[CheckResult]
|
|
|
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.