quchip.sweep¶
Declarative parameter sweeps for chip studies.
This module provides the user-facing sweep abstractions and a dressed-spectrum sweep driver:
Sweepdeclares a 1-D axis of values for a single named parameter. MultipleSweepaxes compose as a Cartesian product.ZippedSweep(built withSweep.zip()) pairs axes element-wise rather than expanding the product, which is the right shape for correlated scans (e.g. frequency and drive amplitude moved together along a calibration trace).SpectrumSweepwalks a sweep grid, dresses the chip at each point viaChip.dress(), and records eigenvalues and bare→dressed label assignments into aSpectrumSweepResult.
Sweep values are stored in their native physical units (GHz for
frequencies, ns for times, mK for temperatures). Sweep
preserves JAX arrays verbatim so downstream code can differentiate
through swept values when desired; everything else is promoted to
np.ndarray so len and indexing behave predictably.
The dressed-spectrum machinery here computes eigenvalues and overlaps of the lab-frame chip Hamiltonian; for a general reference on the dressed-state picture of coupled circuit qubits, see Blais, Grimsmo, Girvin & Wallraff, Circuit quantum electrodynamics, Rev. Mod. Phys. 93, 025005 (2021).
Classes
|
Sequential dressed-spectrum sweep driver. |
|
Dressed-spectrum data collected across a |
|
Declarative 1-D sweep axis over a named parameter. |
|
Element-wise pairing of sweep axes. |
- class quchip.sweep.ZippedSweep(sweeps)[source]¶
Bases:
objectElement-wise pairing of sweep axes.
Built via
Sweep.zip(). All bundled axes must share the samesize; iteration steps through them together, producing one parameter dict per element rather than a Cartesian-product grid.
- class quchip.sweep.Sweep(values, *, name=None)[source]¶
Bases:
objectDeclarative 1-D sweep axis over a named parameter.
valuesare in the swept parameter’s own physical units (the package-wide contract: GHz for frequencies and couplings, ns for times, mK for temperatures).valuesmay be a Python sequence, a NumPy array, or a JAX array; JAX arrays are preserved as-is so any consumer that threads the sweep through a JAX-traced path keeps full differentiability. Non-JAX inputs are normalized throughnumpy.asarray()for uniformlen/indexing behavior.Examples
>>> import numpy as np >>> from quchip.sweep import Sweep >>> freqs = Sweep(np.linspace(4.9, 5.1, 5), name="freq") >>> freqs.size 5 >>> drives = Sweep([0.01, 0.02, 0.03], name="amp") >>> points = Sweep.expand([freqs, drives]) >>> len(points) 15
- Parameters:
values (Any)
name (str | None)
- static zip(*sweeps)[source]¶
Pair axes for element-wise iteration.
At least two sweeps are required; all sweeps must have equal size. A
ValueErroris raised otherwise.- Parameters:
*sweeps (Sweep) – Two or more
Sweepaxes to bundle element-wise. Theirnameattributes must all be distinct — aZippedSweepwith repeated axis names raisesValueErrorwhen it is later enumerated (expand(),SpectrumSweep).- Returns:
Bundle iterated element-wise instead of taken in Cartesian product with other axes.
- Return type:
- static expand(axes)[source]¶
Expand sweep axes into a flat list of parameter dicts.
The Cartesian product of independent
Sweepaxes is taken;ZippedSweepbundles remain element-wise. The return order is the grid’s C-order (last axis varies fastest).This is the params-only view of
_iter_axis_points()— the single enumeration code path — with the grid coordinates dropped.- Parameters:
axes (Sequence[Sweep | ZippedSweep]) –
Sweepand/orZippedSweepaxes. Every axis name (including each member of a zipped bundle) must be unique acrossaxes, elseValueErroris raised — a repeated name would silently overwrite itself in each point’s parameter dict.- Returns:
One parameter dict per grid point, length equal to the product of the independent axes’ sizes (zipped bundles contribute their shared size once).
- Return type:
- class quchip.sweep.SpectrumSweepResult(device_labels, bare_labels, eigenvalues, dressed_indices, assignment_overlaps, overlap_threshold, params, eigenvector_matrices=None, eigenstates=None)[source]¶
Bases:
objectDressed-spectrum data collected across a
SpectrumSweepgrid.- Parameters:
- device_labels¶
Device labels of the underlying chip, ordered as the chip’s tensor-product order (
devices).
- bare_labels¶
Tuple of bare-state labels (one tuple of occupation numbers per device) that the sweep tracks.
- eigenvalues¶
(*grid_shape, n_evals)array of eigenvalues in GHz, one row per sweep point.- Type:
- dressed_indices¶
(*grid_shape, n_bare)array giving the dressed-state index assigned to each bare label at each sweep point, orNaNwhen no confident assignment is found.- Type:
- assignment_overlaps¶
(*grid_shape, n_bare)overlap weights accompanyingdressed_indices.- Type:
- overlap_threshold¶
Minimum overlap below which an assignment is treated as unreliable and returned as
NaN.- Type:
- params¶
Object array of parameter dicts, one per grid point.
- Type:
- eigenvector_matrices¶
Optional object array of dressed eigenvector matrices (one per grid point), produced when
store_eigenstates=True.- Type:
numpy.ndarray | None
- eigenstates¶
Optional object array of dressed eigenstates aligned with
eigenvector_matrices.- Type:
numpy.ndarray | None
- dressed_index(device_states=None, /, **device_state_kwargs)[source]¶
Dressed-state indices across the sweep for one bare label.
Entries where the assignment overlap falls below
overlap_threshold(or was never found) are returned asNaN.- Parameters:
device_states (Mapping[str, int] | None) – Mapping from device (label or object) to occupation number, resolved via
bare_label_from_mapping(); devices left unspecified default to Fock index 0. Mutually exclusive withdevice_state_kwargs.**device_state_kwargs (int) – Keyword form of
device_states(device label as keyword).
- Returns:
Floating-point array of shape
shape(the sweep grid, excluding the bare-label axis). Floating dtype is required to represent unreliable or missing assignments asNaN— a grid point whose overlap with this bare label falls belowoverlap_threshold, or where no dressed state was assigned to it at all.- Return type:
Examples
>>> # Track the bare |1, 0> state across a sweep >>> # result.dressed_index({qubit_a: 1, qubit_b: 0})
- energy_by_bare_label(device_states=None, /, **device_state_kwargs)[source]¶
Dressed energies (GHz) traced out for one bare label across the sweep.
Invalid points inherit the
NaNmask fromdressed_index().- Parameters:
device_states (Mapping[str, int] | None) – Mapping from device (label or object) to occupation number; see
dressed_index(). Mutually exclusive withdevice_state_kwargs.**device_state_kwargs (int) – Keyword form of
device_states(device label as keyword).
- Returns:
Floating-point array of shape
shape, in GHz. Entries wheredressed_index()returnsNaN(overlap belowoverlap_threshold, or no assignment found) areNaN.- Return type:
- state_components_at(point, state=None, /, *, n_components=5, **device_state_kwargs)[source]¶
Top-
n_componentsbare-state probabilities of a dressed eigenstate.statemay either be an explicit dressed index (int) or a bare-label specification that is resolved via the same overlap-based map used bydressed_index(). Requires the sweep to have been run withstore_eigenstates=True.Returns a dict mapping bare labels to squared-amplitude probabilities, ordered from largest to smallest.
- class quchip.sweep.SpectrumSweep(chip, axes, *, update_fn, evals_count=None, store_eigenstates=False, overlap_threshold=0.5)[source]¶
Bases:
objectSequential dressed-spectrum sweep driver.
At each grid point the chip is cloned via
Chip.updated(),update_fnmutates the clone with the swept values, andChip.dress()computes the lab-frame dressed spectrum. The per-point eigenvalues and overlap-based bare→dressed assignments are collected into aSpectrumSweepResult.This is the standard tool for two-tone spectroscopy maps, avoided crossings, and any study that requires following dressed states across parameter space. See Blais, Grimsmo, Girvin & Wallraff, Rev. Mod. Phys. 93, 025005 (2021), for the dressed-state picture; the overlap-based labeling follows the usual practice of assigning a dressed eigenstate to the bare state with which it has maximum overlap.
Examples
>>> # Sweep a qubit frequency and record dressed levels >>> # sweep = SpectrumSweep( >>> # chip, >>> # [Sweep(np.linspace(4.8, 5.2, 41), name="freq")], >>> # update_fn=lambda c, p: setattr(c.device(qubit), "frequency", p["freq"]), >>> # ) >>> # result = sweep.run()
- Parameters: