quchip.backend.dynamiqs¶
Dynamiqs backend: JAX-native solver for differentiable, vmappable simulation.
This backend wraps dynamiqs (which builds on JAX) to supply:
Full JAX traceability. Every operator, state, and signal program evaluates inside JAX, so gradients flow through frame resolution, carrier phases, envelope parameters, crosstalk mixing, and dissipator strengths.
Native batched solves. A typed
SolveBatchis stacked along a batch axis and integrated with native Dynamiqs integrators undervmapinsolve_batch(). Structurally heterogeneous batches fail loudly, with no silent sequential fallback, so the caller can regroup them withquchip.engine.solve_many().
References
Guilmin et al. — dynamiqs: an open-source Python library for GPU-accelerated and differentiable simulation of quantum systems (2024)
Bradbury et al. — JAX: composable transformations of Python+NumPy programs (2018)
Lindblad — Commun. Math. Phys. 48, 119 (1976)
Classes
Concrete backend backed by dynamiqs + JAX. |
- class quchip.backend.dynamiqs.DynamiqsBackend[source]¶
Bases:
BackendConcrete backend backed by dynamiqs + JAX. Operators/states are
QArray.Example
>>> from quchip.backend.dynamiqs import DynamiqsBackend >>> backend = DynamiqsBackend() >>> a = backend.destroy(3) >>> n = backend.matmul(backend.dag(a), a) >>> float(backend.to_array(n)[2, 2].real) 2.0
- property array_module: Any¶
Return the array module used by backend-aware numeric code.
Returns
numpyfor CPU-only backends andjax.numpyfor JAX-traceable backends. Engine code that must stay differentiable (signal evaluation, frame assembly) routes array operations through this module, so the dynamiqs backend stays JAX-traceable end to end.
- to_array(op)[source]¶
Return a dense array (native to
array_module) for op.- Parameters:
op (Operator) – Backend-native operator.
- overlap(a, b)[source]¶
Return the scalar inner product ⟨a|b⟩ for two kets.
- Parameters:
a (State) – Kets in the same Hilbert space, where the first is conjugated.
b (State) – Kets in the same Hilbert space, where the first is conjugated.
- norm(state_or_op)[source]¶
Return the native dynamiqs norm with its default PSD assumption.
- Parameters:
state_or_op (QArray) – Ket or bra for the Euclidean norm, or a positive-semidefinite matrix for its real trace. General indefinite operators are outside this hook’s matrix convention.
- Returns:
Native scalar. Traced inputs keep their gradients.
- Return type:
jax.Array
- trace(op)[source]¶
Return the scalar trace
Tr(op).- Parameters:
op (Operator) – Backend-native operator.
- eager_operators()[source]¶
Temporarily use dense Dynamiqs operators, then restore the global layout.
- destroy(n)[source]¶
Build the annihilation operator \(\hat a\) for an n-level Fock space.
- Parameters:
n (int) – Positive Hilbert-space dimension. Number states go from 0 to n - 1.
- create(n)[source]¶
Build the creation operator \(\hat a^\dagger\) for an n-level Fock space.
- Parameters:
n (int) – Positive Hilbert-space dimension. Number states go from 0 to n - 1.
- number(n)[source]¶
Build the number operator \(\hat n = \hat a^\dagger \hat a\).
- Parameters:
n (int) – Positive Hilbert-space dimension. Number states go from 0 to n - 1.
- identity(n)[source]¶
Build the identity operator for an n-level space.
- Parameters:
n (int) – Positive Hilbert-space dimension. Number states go from 0 to n - 1.
- diag(values, dims=None)[source]¶
Build a backend-native sparse-DIA diagonal operator from main-diagonal values.
Overrides the protocol default to keep the operator in sparse-DIA layout, even when values is a JAX tracer.
- Parameters:
values (array_like) – Main-diagonal entries, flattened in input order.
dims (list or None, default None) – Subsystem dimensions as in from_array. None uses one subsystem.
See also
- from_array(data, dims=None)[source]¶
Construct a native operator from a dense matrix.
dims accepts quchip’s row/col layout (
[[row_dims], [col_dims]]) or a flat list.Nonemeans a single subsystem of sizedata.shape[0].- Parameters:
data (array_like) – Dense matrix in the requested tensor-product basis.
dims (list or None, default None) – Subsystem dimensions, flat or [[row_dims], [column_dims]]. None treats the row space as one subsystem.
- to_canonical_operator(op)[source]¶
Serialize a native operator into the backend-agnostic canonical IR.
- Parameters:
op (Operator) – Backend-native operator.
- from_canonical_operator(canonical)[source]¶
Reconstruct a native operator from the canonical IR payload.
- Parameters:
canonical (CanonicalOperator) – Backend-neutral matrix payload with its tensor dimensions and basis metadata.
- coerce_operator(op)[source]¶
Coerce an array-like local operator into backend-native form.
Mirrors
coerce_state()for operators. Device-side accessors for physical coupling (for example,charge_coupling_operator()) return dense, trace-safe arrays, not backend-native operators. Composition entry points (tensor(),dag()) send their operands through this hook, so both forms compose freely. A backend whose native operators are already arrays overrides this method with a trace-safe passthrough.- Parameters:
op (Operator) – Backend-native operator.
- dag(op)[source]¶
Return the Hermitian conjugate
op†.- Parameters:
op (Operator) – Backend-native operator.
- eigenenergies(op)[source]¶
Return the ascending eigenvalues of a Hermitian operator.
- Parameters:
op (Operator) – Hermitian operator to diagonalize.
- eigensystem_data(op)[source]¶
Return ascending eigenvalues, stacked eigenvector matrix, and lazy eigenstates.
- Parameters:
op (Operator) – Hermitian operator to diagonalize.
- expect(op, state)[source]¶
Return the expectation value ⟨state|op|state⟩ for a ket or a density matrix.
- Parameters:
op (Operator) – Observable with the same tensor dimensions as state.
state (State) – Ket or density matrix, not normalized by the method.
- ptrace(state, keep, dims)[source]¶
Reduce a composite state onto subsystem(s) keep with a partial trace.
- stack_states(states)[source]¶
Stack the saved states of a trajectory into a single
(T, …)array.The default densifies each state and applies
np.stackalong a new leading time axis. A backend whose solver already returns a stacked native state (dynamiqs) overrides this method with a no-op pass-through.- Parameters:
states (sequence of State) – Saved states in time order, with matching shapes and tensor dimensions.
- expect_over_time(op, stacked_states)[source]¶
Return ⟨op⟩(t) for every save point, as one
(T,)array inarray_module.Accepts a ket stack
(T, n, 1)(returns ⟨ψ|op|ψ⟩) or a density-matrix stack(T, n, n)(returnsTr(op·ρ)). One matrix product replaces the per-pointexpectloop. Every intermediate stays inarray_module, so the JAX backend keeps the trace differentiable.- Parameters:
op (Operator) – Observable in the tensor-product basis of the states.
stacked_states (array_like) – Backend-stacked kets or density matrices from stack_states.
- ptrace_over_time(stacked_states, keep, dims)[source]¶
Reduce onto subsystem(s) keep at every save point, and return a
(T, k, k)DM stack.Accepts a ket or DM trajectory and uses no per-point Python loop.
- matmul(a, b)[source]¶
Multiply operators, keeping a product of sparse-DIA factors sparse.
Concrete factors multiply on the host. Traced sparse-DIA factors multiply their diagonals directly.
- Parameters:
a (Operator) – Left and right matrix factors with compatible dimensions.
b (Operator) – Left and right matrix factors with compatible dimensions.
- linear_combination(terms)[source]¶
Accumulate scalar multiples of operators into one qarray, on the host when every term is concrete.
Sparse-DIA terms sum their diagonals into a sparse-DIA result. A sum that includes a dense term is dense, as in qarray arithmetic. Batched operators or coefficients use qarray arithmetic.
- Parameters:
terms (sequence of (scalar, Operator)) – At least one coefficient and operator pair on a common space.
- tensor(*operators)[source]¶
Return the tensor product of operators, and keep the subsystem dims metadata.
- Parameters:
*operators (Operator) – Factors in tensor-product order.
- embed_two_body(op_ab, index_a, index_b, dims)[source]¶
Embed a two-body operator on devices index_a ⊗ index_b into the full space.
Handles the subsystem SWAP when
index_a > index_band the identity-padding for non-adjacent devices. Backends with sparse layouts do not materialize the dense full matrix.- Parameters:
- tensor_states(*states)[source]¶
Return the tensor product of states (defaults to
tensor()).- Parameters:
*states (State) – Factors in tensor-product order.
- coherent(n, alpha)[source]¶
Build the coherent state \(|\alpha\rangle\) truncated to n Fock levels.
Built from the analytic series \(|\alpha\rangle = e^{-|\alpha|^2/2} \sum_k \alpha^k/\sqrt{\Gamma(k+1)}\,|k\rangle\).
- state_to_dm(state)[source]¶
Return a density matrix, or pass state through if state is already one.
- Parameters:
state (State) – Ket or density matrix to inspect or convert.
- is_ket(state)[source]¶
Return whether state is a ket (flat or column vector) rather than a density matrix.
- Parameters:
state (State) – Ket or density matrix to inspect or convert.
- is_native_state(state)[source]¶
Return whether state is already represented by this backend.
- Parameters:
state (State) – Ket or density matrix to inspect or convert.
- resolve_solver_options(options, *, metadata, tlist)[source]¶
Validate dynamiqs integration options and fill the default step budget.
- Parameters:
options (dict) – Supported keys:
method(native deterministic dynamiqs method),gradient(native gradient configuration),max_steps(integer ceiling),progress_meter,store_states, andstore_final_state.nstepsaliasesmax_steps.progress_baraliasesprogress_meter. Do not supply an alias and its canonical key together. Set tolerances on the nativemethodobject. With an explicit method, set its step limit there instead of also passingmax_stepshere. Monte Carlo methods and unrecognized keys are rejected.metadata (dict) – Lowering hints, which include ordinary-GHz spectral/carrier bounds.
tlist (array_like) – Save-time grid in ns used to estimate integration budgets.
- Returns:
Copied options with missing integration defaults filled.
- Return type:
- coerce_state(state, dims=None)[source]¶
Convert a foreign-native state into this backend’s native form.
The solve boundary calls this method so that a per-call
backend=override (seeQuantumSequence.simulate()) accepts initial states built under another backend. For example, a QuTiPQobjfromchip.state(...)given to a dynamiqs gradient solve. Default: pass through unchanged.dimsare the chip’s subsystem levels, for backends whose state type carries tensor structure.
- sesolve(H, psi0, tlist, e_ops=None, options=None)[source]¶
Solve the Schrödinger equation \(i\hbar \partial_t |\psi\rangle = H |\psi\rangle\).
- Parameters:
H (Any) – Native Hamiltonian (
Qobj/QobjEvoor dynamiqsTimeQArray).psi0 (Any) – Initial ket.
tlist (Any) – Save times in ns.
e_ops (list[Any] | None) – Optional observables. The solver accumulates ⟨ψ|Oᵢ|ψ⟩ along the trajectory.
options (dict[str, Any] | None) – Backend-specific options dict. For the supported keys, see each backend’s
resolve_solver_options.
- mesolve(H, rho0, tlist, c_ops=None, e_ops=None, options=None)[source]¶
Solve the Lindblad master equation (Lindblad 1976; Breuer & Petruccione 2002).
Integrates \(\dot\rho = -i[H,\rho] + \sum_k \mathcal D[L_k]\rho\) with \(\mathcal D[L]\rho = L\rho L^\dagger - \tfrac12\{L^\dagger L, \rho\}\).
- Parameters:
H (object) – Native Hamiltonian, already scaled to angular frequency in rad/ns. Do not multiply by 2*pi again.
rho0 (State) – Initial density matrix, or a ket that the concrete solver accepts.
tlist (array_like, shape (nt,)) – Save times in ns, strictly increasing.
c_ops (list of Operator or None, default None) – Collapse operators including square-root rates in 1/sqrt(ns). None gives no dissipators.
e_ops (list of Operator or None, default None) – Observables in output order. None requests no expectation traces.
options (dict or None, default None) – Native integration options. See the concrete backend’s resolve_solver_options method.
- Returns:
Saved states, expectation traces and solver diagnostics.
- Return type:
- steadystate(problem, *, prepared=None, guess=None)[source]¶
Solve a static Lindblad generator by a trace-constrained JAX solve.
- Parameters:
problem (SteadyStateProblem) – Captured static model, observables, and stationary solver options.
prepared (PreparedStationary or None, default None) – Matching prepared generator.
Nonebuilds it.guess (QArray or None, default None) – Accepted for the backend protocol. The solve and its uniqueness check always run, so the state stays differentiable.
- Returns:
Stationary density matrix and convergence diagnostics.
- Return type:
Notes
problem.optionsaccepts onlymethod="direct"andrank_tolerance(singular-value cutoff, default automatic). A nonunique stationary kernel gives a NaN state, so inspect the returned nullity.
- stationary_bytes(engine_result)[source]¶
Return the estimated peak bytes of the dense stationary solve, with its generator.
- Parameters:
engine_result (EngineResult) – Captured static Hamiltonian and collapse channels.
- linear_response(problem)[source]¶
Solve one passive-linear input-output problem in the backend’s native arrays.
- Parameters:
problem (LinearResponseProblem) – Captured passive-linear model, selected ports, probe frequencies, and incident amplitudes.
- Returns:
Scattering response, internal amplitudes and numerical diagnostics.
- Return type:
- coherence_response(problem)[source]¶
Solve a frequency response on adjacent excitation-sector coherences.
- Parameters:
problem (CoherenceResponseProblem) – Sector Hamiltonians, channels and frozen-reference probe sources.
- stationary_resolvent(engine_result, sources, observables, frequencies, *, prepared=None)[source]¶
Evaluate trace-zero stationary resolvents in native backend arrays.
For each ordinary-GHz offset
f, form and factor the trace-constrained shifted Liouvillian once, then solve(L + i 2π f) X = sourcewithTr(X) = 0for every named source column. ReturnTr(observable X)keyed by(source, observable). The engine supplies canonical operators. The backend owns Liouvillian construction, factorization, and solves.- Parameters:
engine_result (EngineResult) – Captured static operating point.
sources (tuple of (str, CanonicalOperator)) – Named source columns for the constrained linear systems.
observables (tuple of (str, CanonicalOperator)) – Named operators evaluated against each solution.
frequencies (array_like) – Offset frequencies in ordinary GHz.
prepared (PreparedStationary or None, default None) – Matching prepared generator.
Nonebuilds it.
- Returns:
Arrays keyed by (source_name, observable_name), indexed by frequency.
- Return type:
- stationary_propagate(engine_result, initial, observables, times, *, prepared=None)[source]¶
Propagate an operator under a static Liouvillian and evaluate observables.
initialdoes not have to be a normalized density matrix. This supports quantum-regression queries, and the backend keeps ownership of the propagation algorithm and the numerical Liouvillian.- Parameters:
engine_result (EngineResult) – Captured static operating point.
initial (CanonicalOperator) – Initial operator. Regression queries need neither normalization nor positivity.
observables (tuple of (str, CanonicalOperator)) – Named operators evaluated after propagation.
times (array_like) – Propagation delays in ns.
prepared (PreparedStationary or None, default None) – Matching prepared generator.
Nonebuilds it.
- Returns:
Observable names mapped to arrays indexed by delay.
- Return type:
- solve_problem(problem)[source]¶
Lower and solve a
SolveProblem(the single-element entry point).Delegates to
SolveProblem.solver_name(). It usessesolveonly for a ket with no collapse operators andmesolveotherwise, unlessproblem.solverforces a choice.- Parameters:
problem (SolveProblem) – Complete captured Hamiltonian, initial state, time grid, observables and solver settings.
- Returns:
Native solver payload for the requested calculation.
- Return type:
- trajectory_view(native, problem, *, index, states, deterministic)[source]¶
Read one view of a native stochastic result of this backend.
- Parameters:
native (object) – Native stochastic result that
solve_problem()returned.problem (SolveProblem) – Captured request, with its solver, state storage and native options.
index (int or None) – Kept trajectory, or
Nonefor the native ensemble average.states (bool) – Whether to read the saved states.
deterministic (bool) – Whether to read the deterministic no-click run instead.
- Returns:
Expectation values, state history and final state. Each entry is
Nonewhen the native result does not keep it.- Return type:
- trajectory_records(native, problem)[source]¶
Read the diffusive measurement currents of a native stochastic result.
- Parameters:
native (object) – Native stochastic result that
solve_problem()returned.problem (SolveProblem) – Captured request, with its solver and native options.
- Returns:
Currents of shape
(runs, channels, intervals), or(runs, channels, 2, intervals)for heterodyne detection, and the sampling of the signal in each interval:"start","middle","end"or"mean".- Return type:
- trajectory_clicks(native, problem)[source]¶
Read the jump events of a native stochastic result.
- Parameters:
native (object) – Native stochastic result that
solve_problem()returned.problem (SolveProblem) – Captured request, with its solver and native options.
- Returns:
For each run, its click times and the native jump-operator index of each click; the sampling weight of each run; the weight of the no-click run that the native sampling solves apart; and whether each run filled its native click buffer.
- Return type:
- trajectory_run_expect(native, problem)[source]¶
Read the expectation values of every kept run of a native stochastic result.
- Parameters:
native (object) – Native stochastic result that
solve_problem()returned.problem (SolveProblem) – Captured request, with its native expectation operators.
- Returns:
One array of shape
(runs, times)for each native expectation operator.- Return type:
- prepare_hamiltonian(engine_result, tlist=None)[source]¶
Convert a
EngineResultinto a dynamiqs native RHS.Static terms are summed as qarrays. Dynamic terms with
ScalarModulationtime-dependence are wrapped withdynamiqs.modulatedand a JAX-traceable_SignalCallable.tlistpasses through in metadata but is not used for sampling, because Dynamiqs evaluates callables on the integrator’s adaptive grid.- Parameters:
engine_result (EngineResult) – Captured engine Hamiltonian and channels in solver units.
tlist (array_like) – Requested save times in ns, used by native time-dependent lowering.
- Returns:
Native right-hand side and numerical integration hints.
- Return type:
- prepare_batch(batch)[source]¶
Lower compatible problems into stable leaves for one vmapped solve.
For each dynamic slot, the per-element
ScalarModulationsignals are stacked leaf-by-leaf along a leading batch axis (jnp.stackon matching pytree leaves).- Raises:
ValueError – If a slot contains heterogeneous pytree structures (cannot be stacked) or a non-
ScalarModulationtime dependence.- Parameters:
batch (SolveBatch) – Batch of captured problems with compatible save grids.
- Returns:
Eager, native-vectorized, or deferred representation selected by this backend.
- Return type:
- solve_batch(batch, *, progress=True, max_workers=None)[source]¶
Solve a
SolveBatchwith a single native dynamiqs vmap.Raises
RuntimeError, with no silent fallback, when the batch is not structurally homogeneous. Callers with heterogeneous inputs should regroup throughquchip.engine.solve_many().- Parameters:
batch (SolveBatch) – Captured problems and batch parameter values.
progress (bool, default True) – Request a batch progress display.
max_workers (int or None, default None) – Accepted for the backend protocol. The vmapped solve runs in this process.
- Returns:
Results in batch order.
- Return type:
list of SolverResult