quchip.engine.stage4_problem

Stage 4: pack stage outputs + collapse operators into a frozen SolveProblem.

Responsibilities

  • Ensure the chip is dressed and run stage 1 (resolve_frame()).

  • Run stage 3 (decompose_eops()) to flatten e_ops into solver-ready bands.

  • Collect and embed every Lindblad collapse operator contributed by devices, drive lines, and couplings (see _collect_c_ops()).

  • Run stage 2 (build_hamiltonian_description()) for each variant and pack into a single SolveProblem, or merge homogeneous variants into a SolveBatch (N identical skeletons with per-element ScalarModulation signals).

Collapse operators enter the standard Lindblad master equation dρ/dt = −i[H, ρ] + Σₖ D[Lₖ]ρ. Rates are stored in 1/ns.

Functions

build_solve_batch_from_descriptions(context, ...)

Merge N homogeneous HamiltonianDescription`s into one :class:`SolveBatch.

build_solve_problem(chip, drive_ops, tlist, *)

Run stages 1-4 end-to-end and return a frozen SolveProblem.

prepare_solve_problem_context(chip, tlist, *)

Resolve the frame, normalize e_ops, collect c_ops, and prepare a default state.

solve_problem_list(problems, backend, *[, ...])

Group problems by shared operator skeleton and dispatch as :class:`SolveBatch`es.

validate_drive_ops_window(drive_ops, tlist)

Validate every DriveOp in drive_ops against _validate_drive_op_window().

Classes

PrematerializedState(state)

Adapter giving an already-built state the materialize() surface.

SolveProblemContext(chip, tlist, c_ops, ...)

Shared solve metadata reused across a homogeneous problem batch.

class quchip.engine.stage4_problem.SolveProblemContext(chip, tlist, c_ops, e_ops, e_ops_meta, resolved_frame, solver, options, default_initial_state)[source]

Bases: object

Shared solve metadata reused across a homogeneous problem batch.

Built once by prepare_solve_problem_context() so sweep points can skip redundant collapse-operator collection and e_ops normalization.

Parameters:
  • chip (Chip)

  • tlist (Any)

  • c_ops (tuple[Any, ...])

  • e_ops (Any)

  • e_ops_meta (Any)

  • resolved_frame (Any)

  • solver (str | None)

  • options (dict[str, Any])

  • default_initial_state (Any)

chip: Chip
tlist: Any
c_ops: tuple[Any, ...]
e_ops: Any
e_ops_meta: Any
resolved_frame: Any
solver: str | None
options: dict[str, Any]
default_initial_state: Any
classmethod from_problem(ref)[source]

Reconstruct a shared context from an existing SolveProblem.

Mirrors SolveBatch.element(): it lifts a single concrete problem back into the context shape so a homogeneous group of problems can be re-batched. The reference problem’s already-built initial_state is wrapped in a PrematerializedState (no chip ground state is recomputed), and options is defensively copied.

Parameters:

ref (SolveProblem)

Return type:

SolveProblemContext

quchip.engine.stage4_problem.validate_drive_ops_window(drive_ops, tlist)[source]

Validate every DriveOp in drive_ops against _validate_drive_op_window().

Parameters:
Return type:

None

quchip.engine.stage4_problem.prepare_solve_problem_context(chip, tlist, *, solver=None, options=None, e_ops=None, drive_ops=None)[source]

Resolve the frame, normalize e_ops, collect c_ops, and prepare a default state.

The dressed dict-keyed analysis is deliberately not triggered here: anything downstream that needs dressed quantities must use the array-only kernel (chip.freq, chip.energy, etc.) so this stage stays JAX-traceable. The default initial state is computed lazily via a thunk so callers that always pass initial_state never pay for it (and so the thunk’s eager dict-based state construction never runs under jax.jit).

tlist is validated by _validate_tlist(). When drive_ops is given, each entry’s pulse window is checked against tlist via validate_drive_ops_window(); omit it (the default) when the caller validates its own per-variant drive ops elsewhere (see build_batch()).

Parameters:
Return type:

SolveProblemContext

class quchip.engine.stage4_problem.PrematerializedState(state)[source]

Bases: object

Adapter giving an already-built state the materialize() surface.

Used where a SolveProblemContext is assembled from an existing SolveProblem (whose initial_state is already a concrete ket/DM) rather than from a chip.

Parameters:

state (Any)

materialize()[source]
Return type:

Any

quchip.engine.stage4_problem.build_solve_batch_from_descriptions(context, descriptions, *, initial_states=None)[source]

Merge N homogeneous HamiltonianDescription`s into one :class:`SolveBatch.

All descriptions must share static_terms identity, the same number of dynamic terms, and matching operator payloads per slot (by identity or by canonical fingerprint — crosstalk rebuilds equal-by-value operators on every instantiation). initial_states=None fills every element with context.default_initial_state.

Parameters:
Return type:

SolveBatch

quchip.engine.stage4_problem.build_solve_problem(chip, drive_ops, tlist, *, solver=None, options=None, e_ops=None, initial_state=None)[source]

Run stages 1-4 end-to-end and return a frozen SolveProblem.

Equivalent to prepare_solve_problem_context() followed by build_hamiltonian_description(). For many variants sharing one chip configuration, prefer that two-step form with build_solve_batch_from_descriptions().

Parameters:
  • chip (Chip)

  • drive_ops (list[DriveOp])

  • tlist (Any)

  • solver (str | None)

  • options (dict | None)

  • e_ops (dict | None)

  • initial_state (Any | None)

Return type:

SolveProblem

quchip.engine.stage4_problem.solve_problem_list(problems, backend, *, progress=True)[source]

Group problems by shared operator skeleton and dispatch as :class:`SolveBatch`es.

Problems that share an operator skeleton are merged into one batched solve; those that cannot be structurally batched fall back to per-problem backend.solve_problem calls.

Grouping is a two-stage filter. The cheap identity-based prefilter here (_skeleton_prefilter_key()) buckets problems by id() of their shared operators/metadata so that obviously-incompatible problems are never compared by value. The canonical by-value compatibility check is intentionally a separate concern that lives inside build_solve_batch_from_descriptions() (operator fingerprint): the prefilter is an identity prefilter, the fingerprint is the value check. Returns a SimulationBatchResult.

Parameters:
Return type:

Any