quchip.results¶
Backend-agnostic simulation output containers.
Whatever backend produced the solver output (QuTiP, dynamiqs/JAX, …), users
interact only with SimulationResult and
SimulationBatchResult. Named expectation-value traces are exposed
as ObservableTrace, and raw backend output is wrapped into a
SimulationResult via wrap_solver_result(). A partitioned
solve (see quchip.engine.partitioned) combines its per-component
results into a PartitionedSimulationResult.
- class quchip.results.ObservableTrace(values, raw)[source]¶
Bases:
objectOne named expectation-value trace, with pre- and post-processing values.
- values¶
Post-processed expectation values over time (e.g. demodulated, phase-corrected, band-summed). This is what user code normally wants.
- Type:
Any
- raw¶
The same quantity before post-processing — useful for debugging frame conventions, band decomposition, and demodulation.
- Type:
Any
- class quchip.results.SimulationBatchResult(results, *, shape=None, axes=None)[source]¶
Bases:
objectOrdered, immutable batch of
SimulationResultwith stacked helpers.Returned by
solve_many()and by any sweep that solves many problems in one call. The batch preserves iteration order so that per-element results map one-to-one onto the inputs that produced them.The
final_*helpers stack along a new leading batch axis in the backend’s array module, and the grid-awareexpect()/population()acceptreduce='last'for a final-value slice, so a loss function that sums over the batch stays JAX-traceable end-to-end.- Parameters:
- property results: tuple[SimulationResult, ...]¶
Return the per-element
SimulationResultobjects in input order.
- with_sweep_metadata(*, shape, axes)[source]¶
Return an equivalent batch annotated with sweep-axis metadata.
- expect(key, index=None, *, reduce=None)[source]¶
Return expectation traces reshaped to the natural sweep grid.
- population(device, level=0, *, reduce=None)[source]¶
Return population traces reshaped to the natural sweep grid.
- Parameters:
device (str | BaseDevice)
level (int)
reduce (str | None)
- Return type:
- class quchip.results.SimulationResult(solver_result, backend, dims, *, device_info=None, observable_traces=None)[source]¶
Bases:
objectBackend-agnostic container for the output of one solve.
A
SimulationResultbundles everything a user needs after a solve finishes:times— the time grid the solver stored (ns).states— the list of stored states (kets or density matrices), orNoneifstore_stateswas off.solver— the name reported by the backend.stats— a plaindictof solver statistics.dims— the per-device Hilbert-space dimensions, in chip order.device_info—[(label, computational), …]for partial-trace helpers to resolve device indices by label or by object.
Expectation values live in
observable_traceswhene_opswas passed as a dict. Each entry is anObservableTraceor a list of them (list-valued observables, one per band, etc.).- Parameters:
solver_result (SolverResult)
backend (Backend)
observable_traces (dict[Any, ObservableTrace | list[ObservableTrace]] | None)
- property observable_traces: dict[Any, ObservableTrace | list[ObservableTrace]] | None¶
Return the dict of named
ObservableTraceentries, orNone.Nonewhene_opswas not passed as a dict. Visualization and analysis code that wants the full dict should read this property rather than the private_expect_dataattribute.
- expect(key, index=None)[source]¶
Return the full expectation-value array for observable key over
self.times.
- expect_final(key, index=None)[source]¶
Return the final expectation value for observable key (
self.expect(key)[-1]).
- expect_values(key, index=None)¶
Return the full expectation-value array for observable key over
self.times.
- overlap_array(target)[source]¶
Return the overlap with target at every stored time.
For ket trajectories returns
|<target|psi(t)>|**2; for density matrices returns<target|rho(t)|target>. Stays in the backend’s array module so the result is differentiable. One batched op over the leading time axis — no per-point loop.
- amplitude_array(target)[source]¶
Return the phase-sensitive complex projection
<target|psi(t)>for kets.Density-matrix trajectories raise
TypeError— there is no single phase-sensitive amplitude for a mixed state; useoverlap_array()instead. One batched op, no per-point loop.
- overlap(target)[source]¶
Wrap
overlap_array()for convenience.Returns a NumPy array under the QuTiP backend; under JAX (dynamiqs) returns the backend-native array so the call stays JIT/grad-friendly.
- state(t=None, *, dm=False)[source]¶
Return the state at time t (or final state if t is
None); optionally coerced to a DM.
- dm_at(t)[source]¶
Return the density matrix at the stored time nearest to t (ns) — promotes kets on demand.
- property final_state: Any¶
Return the final state — explicit
final_stateif stored, else the last stored trajectory entry.
- reduced_state(t, device)[source]¶
Partial-trace the state at time t down to device’s subspace.
- Parameters:
t (float)
device (str | BaseDevice)
- Return type:
- property populations: dict[tuple[int, ...], ndarray]¶
Return per-basis-state populations
|<n1, n2, ...|psi(t)>|**2over time.Returns a dict keyed by Fock tuple
(n1, n2, ..., nK)— one per computational basis vector of the full chip — mapping to a realnumpy.ndarrayof lengthlen(self.times).Requires
store_states; density-matrix trajectories are handled transparently by reading the diagonal of each timestep’s DM.
- population_array(device, level=0)[source]¶
Return the population of Fock level on device over time, in the backend’s array module.
- Parameters:
device (str | BaseDevice)
level (int)
- Return type:
- population(device, level=0)[source]¶
Wrap
population_array()for convenience.Returns a NumPy array under the QuTiP backend; under JAX (dynamiqs) returns the backend-native array so the call stays JIT/grad-friendly. Use
population_array()directly when you want to keep gradient flow regardless of context.- Parameters:
device (str | BaseDevice)
level (int)
- Return type:
- plot_populations(*, trace_out=None, computational=False, ax=None, **kwargs)[source]¶
Plot per-basis-state populations over time (delegates to
quchip.viz.plot_populations()).- Parameters:
trace_out (str | BaseDevice | list[str | BaseDevice] | None)
computational (bool)
ax (Any)
kwargs (Any)
- Return type:
- plot_state(index, *, trace_out=None, computational=False, mode='population', ax=None, **kwargs)[source]¶
Plot one stored state as populations or a density matrix (delegates to
quchip.viz.plot_state()).
- plot_expectation(*, keys=None, ax=None, **kwargs)[source]¶
Plot expectation-value traces over time (delegates to
quchip.viz.plot_expectation()).
- plot_wigner(index=-1, *, trace_out=None, ax=None, **kwargs)[source]¶
Plot the Wigner function of one stored state (delegates to
quchip.viz.plot_wigner()).- Parameters:
index (int)
trace_out (str | BaseDevice | list[str | BaseDevice] | None)
ax (Any)
kwargs (Any)
- Return type:
- check_truncation(*, threshold=0.001, top_levels=1)[source]¶
Emit a
UserWarningper device whose top-top_levelspopulation exceeds threshold.Uses the final stored state only — cheap, one full-chip diagonal read, no per-timestep loop, no partial traces. Silently no-ops when no final state is available (e.g.
store_statesandstore_final_stateboth disabled).Returns the per-device top-level population actually observed, keyed by device label, so callers can surface the numbers without re-parsing the warning text.
- class quchip.results.PartitionedSimulationResult(component_results, partition, key_plan)[source]¶
Bases:
objectResult of one partitioned solve: K component results + a key plan.
- property device_order: tuple[str, ...]¶
Return the parent chip’s original device-label order.
This is not the concatenation of each component’s labels (which follows connected-component discovery order and can interleave differently whenever the chip’s device order doesn’t already group each component’s members together) — it is the order
statesandfinal_stateare permuted into so they match the joint solve exactly.
- check_truncation(threshold=0.001)[source]¶
Run each component’s truncation check and merge the per-device results.
Mirrors
check_truncation()’s return shape (adictkeyed by device label) for duck-typing parity between a joint and a partitioned result.
- property states: list¶
Reconstruct the joint-state trajectory (ket trajectories only), in
device_order.Component states tensor together in connected-component discovery order, which can interleave differently from the parent chip’s own device order; each reconstructed step is permuted (
permute_state()) intodevice_orderso the result matches a joint solve of the original chip exactly.See also
final_state, which — unlike this accessor — intentionally also accepts density-matrix components: a tensor product of component density matrices is itself a valid joint state, whereas a per-step list of joint kets is only well-defined when every component stayed pure.
- property final_state: Any¶
Reconstruct the joint final state, in
device_order— a ket if every component stayed pure, otherwise a density matrix.When components disagree, every component is first promoted to a density matrix (
_promote_to_common_state_kind()) before tensoring, giving a valid joint density matrix. Components tensor together in connected-component discovery order, which can interleave differently from the parent chip’s own device order; the result is permuted (permute_state()) intodevice_orderso it matches a joint solve of the original chip exactly.
- quchip.results.wrap_solver_result(solver_result, problem, backend)[source]¶
Wrap a raw backend
SolverResultinto a user-facingSimulationResult.The engine-side
SolveProblemcarries the metadata needed to rebuild dict-form observables (build_observable_traces()) and to label devices for partial-trace helpers.- Parameters:
solver_result (SolverResult)
problem (SolveProblem)
backend (Backend)
- Return type:
Modules
Combined view over per-component solves of a partitioned chip. |
|
Backend-agnostic wrapper around solver output. |