quchip.control

Classical control surface: lines, signal chain, and envelopes.

class quchip.control.BaseDrive(target=None, *, label=None, rwa=None)[source]

Bases: Registrable

Base class for classical control lines driving a single device.

Drives own their local Hamiltonian contribution and are auto-labelled from their _type_prefix (e.g. charge_0, flux_0) unless label is given. Subclasses are auto-registered for serialization via the shared Registrable mixin.

Parameters:
  • target (BaseDevice | None) – Device to attach this drive to. May be connected later via connect().

  • label (str | None) – Optional explicit label; otherwise auto-generated.

  • rwa (bool | None) – Per-drive RWA override. None means follow the chip-level setting.

Examples

>>> from quchip import DuffingTransmon, ChargeDrive
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3)
>>> drive = ChargeDrive(target=q)
>>> drive.device_label == q.label
True
target_kind: ClassVar[str] = 'device'

"device" for drives targeting a device (the default), "edge" for drives targeting a coupling (see ParametricDrive).

Type:

Structural dispatch key for equipment/chip/sequence code

connect(device)[source]

Attach (or re-attach) this drive to device.

If the drive was previously attached to another device, it is detached from that device’s _connected_drives list so that only the new attachment is visible on the chip.

Parameters:

device (BaseDevice)

Return type:

None

property device_label: str | None

Label of the connected device, or None if unconnected.

property target_label: str | None

Label of this drive’s target, or None if unconnected.

Device-target drives (target_kind == "device") alias device_label; ParametricDrive overrides this to resolve its coupling target instead.

collapse_operators(device)[source]

Lindblad collapse operators contributed by this drive.

Default: none. Override to model drive-induced dissipation (e.g. photon loss on a drive line).

Parameters:

device (BaseDevice)

Return type:

list[Any]

local_channels(device)[source]

Return the Hamiltonian channels this drive exposes on device.

A simple single-channel drive declares _coupling_protocol, _coupling_accessor, _fallback, and _modulation; this method then dispatches generically — the device’s physical coupling operator when it conforms to the Protocol, the structural fallback otherwise. Returned operators are in the device’s local basis (no chip-wide embedding). Drives with a non-standard decomposition override this method instead.

Parameters:

device (BaseDevice)

Return type:

list[DriveChannel]

physics_notes()[source]

Return human-readable declarations of this drive’s approximations.

Returns the shared target/RWA lines plus this drive’s _coupling_note when declared. Subclasses with extra notes super().physics_notes() and append their own. Aggregated by Chip.physics_notes().

Return type:

list[str]

signal_spec(drive_op, device)[source]

Build the frame-agnostic signal spec for one scheduled pulse.

Parameters:
  • drive_op (DriveOp) – Scheduled pulse with envelope, start time, phase offset, and (for microwave drives) carrier frequency. Typed as Any because DriveOp lives in the engine IR, which drives must not import.

  • device (BaseDevice) – Target device. Unused in the default implementation, kept as an extension hook so subclasses can emit device-aware specs (e.g. flux-tunable drives that query the device’s tuning curve).

Returns:

Frame-agnostic description of the pulse — envelope, start time, duration, phase offset, and carrier frequency (or None for baseband drives) — built directly from drive_op, with no frame or IR commitment.

Return type:

DriveSignalSpec

Notes

The default implementation produces a DriveSignalSpec describing a phase-rotated, time-shifted, finite-duration envelope. Stage 2 of the engine turns the spec into the raw SignalProgram Scale(Shift(Window(env, 0, duration), start), exp(i·phi)) before applying the modulation dispatch.

copy(*, target=None)[source]

Return a shallow copy, optionally rebound to a new target.

Parameters:

target (BaseDevice | None)

Return type:

BaseDrive

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

class quchip.control.SignalTransform[source]

Bases: Registrable, ABC

Abstract base for signal-map transforms, auto-registered for serialization.

The type registry, the {"type": ...} to_dict() stamp, and the from_dict dispatch are owned by the shared Registrable mixin; the parameter-less default reconstruction (cls()) covers transforms that carry no persisted state, while payload-carrying transforms override to_dict() / from_dict().

abstractmethod apply(signals)[source]

Return the transformed signal map.

Parameters:

signals (dict[tuple[str, int], SignalNode])

Return type:

dict[tuple[str, int], SignalNode]

referenced_lines()[source]

Return control-line labels referenced by this transform.

Return type:

tuple[str, …]

without_line(line)[source]

Return this transform without line, or None when it must be dropped.

Parameters:

line (str)

Return type:

SignalTransform | None

class quchip.control.Crosstalk(source, victim, beta, theta=0.0, delay=0.0)[source]

Bases: SignalTransform

Linear crosstalk from a source drive line onto a victim line.

For each scheduled operation on the source line, adds

\[\beta\, e^{i\theta}\, s_\mathrm{src}(t - \Delta t)\]

onto the victim line, where \(s_\mathrm{src}\) is the source’s raw line signal — the frame-agnostic, carrier-free envelope signal the signal chain operates on, before stage 2 attaches any carrier or RWA modulation. Fidelity to classical microwave crosstalk is preserved downstream instead: stage 2 builds the victim’s Hamiltonian term using the source drive’s own carrier frequency for the leaked entry, not the victim’s, so a leaked pulse still lands at the source’s frequency (Balewski et al., arXiv:2502.05362, Eq. (3); Sheldon et al., PRA 93, 060302 (2016); Sarovar et al., Quantum 4, 321 (2020)). The delay shifts the baseband envelope; the carrier-phase part of a physical path delay (\(2\pi f \tau\)) belongs in theta.

Parameters:
  • source (str | BaseDrive) – Source drive or its label.

  • victim (str | BaseDrive) – Victim drive or its label.

  • beta (float) – Leakage amplitude (dimensionless).

  • theta (float) – Phase shift applied to the leaked signal, radians.

  • delay (float) – Time shift of the leaked signal relative to the source, ns.

source: str
victim: str
beta: float
theta: float = 0.0
delay: float = 0.0
apply(signals)[source]

Add the phase-rotated, delayed source signal onto the victim line.

Parameters:

signals (dict[tuple[str, int], SignalNode])

Return type:

dict[tuple[str, int], SignalNode]

referenced_lines()[source]

Return control-line labels referenced by this transform.

Return type:

tuple[str, …]

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct from to_dict() output.

On the registry root, dispatch to the concrete subclass named by data["type"] (forwarding *args / **kwargs). On a concrete subclass, defer to _from_dict_payload(). Concrete subclasses that carry payload override this method directly.

Parameters:

d (dict[str, Any])

Return type:

Crosstalk

class quchip.control.Delay(line, delta_t)[source]

Bases: SignalTransform

Shift every signal on line in time by delta_t ns.

Parameters:
line: str
delta_t: float
apply(signals)[source]

Time-shift every signal on line by delta_t ns.

Parameters:

signals (dict[tuple[str, int], SignalNode])

Return type:

dict[tuple[str, int], SignalNode]

referenced_lines()[source]

Return control-line labels referenced by this transform.

Return type:

tuple[str, …]

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct from to_dict() output.

On the registry root, dispatch to the concrete subclass named by data["type"] (forwarding *args / **kwargs). On a concrete subclass, defer to _from_dict_payload(). Concrete subclasses that carry payload override this method directly.

Parameters:

d (dict[str, Any])

Return type:

Delay

class quchip.control.Gain(line, factor)[source]

Bases: SignalTransform

Scale every signal on line by a complex factor.

Parameters:
line: str
factor: complex
apply(signals)[source]

Scale every signal on line by the complex factor.

Parameters:

signals (dict[tuple[str, int], SignalNode])

Return type:

dict[tuple[str, int], SignalNode]

referenced_lines()[source]

Return control-line labels referenced by this transform.

Return type:

tuple[str, …]

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct from to_dict() output.

On the registry root, dispatch to the concrete subclass named by data["type"] (forwarding *args / **kwargs). On a concrete subclass, defer to _from_dict_payload(). Concrete subclasses that carry payload override this method directly.

Parameters:

d (dict[str, Any])

Return type:

Gain

class quchip.control.DriveSignalSpec(envelope, start_time, duration, phase_offset, drive_freq)[source]

Bases: object

Frame-agnostic description of one scheduled drive pulse.

The spec carries everything the engine needs to build the raw line signal and later compose it with the frame + carrier during modulation — expressed in ordinary GHz (frequencies) and ns (times), with no IR references.

Parameters:
  • envelope (BaseEnvelope) – Pulse envelope reference. Its waveform(t) is called at evaluation time; all differentiable pulse parameters live as leaves on the envelope (quchip.control.envelopes).

  • start_time (float) – Onset of the pulse in ns.

  • duration (float) – Envelope duration in ns (the pulse is zero outside [start_time, start_time + duration]).

  • phase_offset (float) – Phase rotation applied to the raw line signal, in radians.

  • drive_freq (float | None) – Microwave carrier frequency in ordinary GHz for DriveModulation.SINGLE_TONE channels; None for baseband (DriveModulation.DIRECT_REAL) drives.

envelope: BaseEnvelope
start_time: float
duration: float
phase_offset: float
drive_freq: float | None
class quchip.control.DriveModulation(value)[source]

Bases: Enum

How a drive channel’s operator is time-modulated.

  • SINGLE_TONE — microwave IQ-style carrier mixing. In the lab frame the raw signal is mixed with exp(-i·2π·ν_d·t) and projected to its real part; under RWA the signal is decomposed into co- and counter-rotating components per Fourier band (Krantz et al. 2019, Eq. 89–90).

  • DIRECT_REAL — real-valued baseband coupling (no carrier, no RWA), appropriate for flux-like drives (Koch et al. 2007, Sec. II; Krantz et al. 2019, Sec. V.A on flux tunability).

  • EDGE_PUMP — real pump δ(t) on a modulable coupling’s strength: baseband δ(t) = Re s(t) when the scheduled op has no carrier, single-tone δ(t) = Re[s(t)·e^{-i·2π·ν_d·t}] when it does. The tone is never RWA-split — the coupling’s parametric hook already selected the retained operator structure (Didier et al., PRA 97, 022330 (2018) on parametric gate activation).

The engine dispatches on this tag in a single code path; adding a new modulation kind is an infrastructure change, not a per-drive special case.

SINGLE_TONE = 'single_tone'
DIRECT_REAL = 'direct_real'
EDGE_PUMP = 'edge_pump'
class quchip.control.ChargeDrive(target=None, *, label=None, rwa=None)[source]

Bases: BaseDrive

Microwave charge drive on a transmon-like device.

Contributes the standard charge-coupling Hamiltonian

\[H_d(t) = \epsilon(t)\, i(\hat a - \hat a^\dagger)\]

with \(\epsilon(t)\) the (real-projected) mixed signal built by the SINGLE_TONE dispatch in stage 2. This is the canonical transmon microwave drive (Koch et al., PRA 76, 042319 (2007); Krantz et al., APR 6, 021318 (2019), Eq. 90).

Examples

>>> from quchip import DuffingTransmon, ChargeDrive, Gaussian
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3)
>>> drive = ChargeDrive(target=q)
>>> channels = drive.local_channels(q)
>>> len(channels) == 1
True
Parameters:
class quchip.control.DriveChannel(operator, modulation)[source]

Bases: object

One Hamiltonian channel exposed by a drive on a target device.

A channel pairs a local-basis operator with a DriveModulation tag that tells the engine how the channel’s coefficient is built from the drive’s line signal. A drive may expose multiple channels if, for example, it contributes both in-phase and quadrature couplings.

Parameters:
operator: Any
modulation: DriveModulation
class quchip.control.FluxDrive(target=None, *, label=None, rwa=None)[source]

Bases: BaseDrive

Real-valued flux drive coupling to \(\hat n\).

Uses DIRECT_REAL — no carrier, no RWA — as appropriate for a baseband flux line that modulates the device frequency through its number operator (Koch et al. 2007, Sec. II; Krantz et al. 2019, Sec. V.A on flux tunability).

The rwa kwarg is rejected: applying RWA to a baseband drive is ill-defined.

Examples

>>> from quchip import DuffingTransmon, FluxDrive
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3)
>>> flux = FluxDrive(target=q)
>>> flux.rwa is None
True
Parameters:
class quchip.control.ParametricDrive(coupling, *, label=None, **kwargs)[source]

Bases: BaseDrive

Control line pumping a modulable coupling’s strength δ(t) in GHz.

Targets a coupling (object or label string; labels late-bind via Chip.connect()). The scheduled envelope is the real amplitude A(t): with an explicit freq the pump is δ(t) = A(t)·cos(2π·freq·t - phase); with freq omitted the pump is baseband, δ(t) = A(t) directly. The pump tone is never RWA-split — the coupling’s RWA policy selects the operator structure via its parametric hook; the tone keeps both sidebands (declared, the solver integrates the fast one).

Accepted couplings implement parametric_interaction(); a static coupling raises TypeError naming the hook.

Parameters:
  • coupling (BaseCoupling | str) – Modulable coupling to pump, given as the coupling object or its label. A string label late-binds to the coupling instance via Chip.connect().

  • label (str | None) – Optional explicit label; otherwise auto-generated from "parametric".

  • kwargs (Any)

Raises:
  • TypeErrorcoupling does not implement parametric_interaction() (a static coupling), or an unexpected keyword argument is passed.

  • ValueError – An explicit rwa keyword argument is passed — the RWA policy is fixed by the coupling’s parametric hook, not per-drive.

target_kind: ClassVar[str] = 'edge'

"device" for drives targeting a device (the default), "edge" for drives targeting a coupling (see ParametricDrive).

Type:

Structural dispatch key for equipment/chip/sequence code

property device_label: None

an edge pump has no device target.

Device-keyed paths (drive-noise collection, device-line bookkeeping) treat None as “skip this line”; edge code reads target_label instead.

Type:

Always None

property target_label: str

Label of the pumped coupling (resolves objects and label strings).

connect(coupling)[source]

Rebind to coupling (no device-side handshake — couplings hold no drive list).

Parameters:

coupling (Any)

Return type:

None

local_channels(device)[source]

Edge pumps have no device channel; stage 2 compiles them from the coupling’s hook.

Parameters:

device (Any)

Return type:

list[DriveChannel]

class quchip.control.PhaseDrive(target=None, *, label=None, rwa=None)[source]

Bases: BaseDrive

Microwave phase drive coupling to \(\hat a + \hat a^\dagger\).

Same carrier machinery as ChargeDrive but with an in-phase (rather than quadrature) coupling. Useful when modeling phase-noise channels or drives whose physical coupling is already referenced to the field quadrature. See Krantz et al. 2019, Sec. IV.A for the two conventions.

Parameters:
class quchip.control.TwoPhotonDrive(target=None, *, label=None, rwa=None)[source]

Bases: BaseDrive

Parametric two-photon drive for Kerr-cat qubit stabilisation.

Coupling operator: a^2 + a_dag^2

The drive should be scheduled at twice the cavity frequency (freq = 2 * cavity.freq) so that in the rotating frame the interaction is static: eps2(t) * (a_dag^2 + a^2). This combination of Kerr nonlinearity and two-photon drive creates and stabilises cat states.

Uses the standard DriveModulation.SINGLE_TONE carrier dispatch – no engine modifications required. The engine band-decomposes a^2 + a_dag^2 into bands of excitation weight Delta_n = +2 and Delta_n = -2, attaching the correct two-photon carrier automatically.

SINGLE_TONE’s real-field projection contributes only half the scheduled envelope amplitude to each band: the coefficient landing on a_dag^2 + a^2 in the rotating frame is A(t)/2, where A(t) is the amplitude scheduled on this drive’s envelope. Schedule amplitude=2*eps2(t) to realize the target two-photon drive strength eps2(t) used above and in alpha^2 = eps2/K.

Parameters:
  • target (BaseDevice | None) – Device to connect this drive to. None means unconnected.

  • label (str | None) – Optional explicit label; otherwise auto-generated.

  • rwa (bool | None) – Per-drive RWA override. None means follow the chip-level setting.

References

Examples

>>> from quchip.devices.kerr_cavity import KerrCavity
>>> from quchip.control.drives_two_photon import TwoPhotonDrive
>>> cav = KerrCavity(freq=5.0, kerr=1.0, levels=10, label="cav")
>>> d2 = TwoPhotonDrive(target=cav)
>>> channels = d2.local_channels(cav)
>>> len(channels)
1
local_channels(device)[source]

Return the two-photon coupling channel a^2 + a_dag^2.

Parameters:

device (BaseDevice) – The cavity device being driven.

Returns:

One channel with operator a^2 + a_dag^2 and DriveModulation.SINGLE_TONE modulation.

Return type:

list[DriveChannel]

physics_notes()[source]

Return the base drive notes plus the two-photon coupling declaration.

Return type:

list[str]

class quchip.control.ControlEquipment(lines, *, signal_chain=None)[source]

Bases: object

Ordered drive lines plus a sequence of signal-chain transforms.

Drives produce raw line signals; the equipment pipes them through signal_chain in order before the engine assembles Hamiltonian terms.

Parameters:
property lines: list[BaseDrive]

Ordered drive lines (defensive copy).

property signal_chain: list[SignalTransform]

Signal-chain transforms (defensive copy).

apply_signal_chain(signals)[source]

Apply every signal-chain transform to signals, in order.

Each transform receives the previous transform’s output, so transforms compose sequentially: reordering signal_chain changes the result (e.g. a Delay applied before a Gain sees the undelayed signal).

Parameters:

signals (SignalMap) – {(drive_label, drive_index): SignalProgram} map of raw line signals. drive_index distinguishes multiple ops on the same drive line and is assigned by the engine when it enumerates the chip’s scheduled drive ops.

Returns:

Transformed signal map. May contain keys absent from signals: a Crosstalk transform, for example, adds an entry under the victim drive’s label for every source entry it leaks from.

Return type:

SignalMap

property crosstalks: list[Crosstalk]

Directed crosstalk edges represented by the signal chain.

crosstalk_matrix()[source]

Return a dense matrix view of the Crosstalk transforms.

The matrix uses wiring order (self.lines) as the stable axis ordering. Column index = source drive, row index = victim drive. Diagonal entries are beta=1, theta=0, delay=0 by convention (self-coupling). Off-diagonal entries aggregate every Crosstalk transform present in the signal chain; lines with no corresponding transform contribute zeros.

Non-Crosstalk transforms (Gain, Delay) are ignored here; this is strictly a view of the crosstalk edges.

Returns:

labels (wiring order), beta, theta, delay as [n, n] arrays. Arrays use jax.numpy when any stored entry is a JAX tracer or array, otherwise numpy.

Return type:

CrosstalkMatrix

set_crosstalk_matrix(beta, theta=None, delay=None, *, labels=None)[source]

Rehydrate the crosstalk edges from dense matrices.

Removes every crosstalk transform currently in the signal chain and replaces them with one CrosstalkMatrix. Other signal-chain transforms (Gain, Delay, and user-defined subclasses) are preserved in order.

Parameters:
  • beta (Any) – [n, n] amplitude matrix. beta[i, j] is emitted as the leakage amplitude from source labels[j] onto victim labels[i]. Diagonal entries are ignored (self-coupling belongs to the drive itself, not to a crosstalk edge).

  • theta (Any, optional) – [n, n] phase matrix (radians). Defaults to zeros.

  • delay (Any, optional) – [n, n] delay matrix (ns). Defaults to zeros.

  • labels (tuple[str, ...] | list[str] | None, optional) – Axis ordering. Defaults to wiring order (self.lines). Must match beta.shape[0].

Return type:

None

Notes

Traced JAX entries flow unchanged into CrosstalkMatrix and therefore into the signal-program IR. No concretization occurs.

copy(device_map, coupling_map=None)[source]

Return a structural copy with drive lines rebound to device_map / coupling_map.

Edge lines (target_kind == "edge") rebind via coupling_map, keyed by coupling label; device lines rebind via device_map as before.

Parameters:
Return type:

ControlEquipment

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d, dev_map, coupling_map=None)[source]

Reconstruct from to_dict() output, rebinding drives via dev_map / coupling_map.

Each line’s target_label is resolved against dev_map first, then coupling_map — device and coupling labels are disjoint by Chip construction, so at most one map holds the label.

Parameters:
Return type:

ControlEquipment

class quchip.control.CrosstalkMatrix(labels, beta, theta, delay)[source]

Bases: SignalTransform

Dense crosstalk transform and matrix view in control-line order.

Parameters:
labels

Drive labels in wiring order (the order drives appear in ControlEquipment.lines). Row / column i corresponds to labels[i].

Type:

tuple[str, …]

beta

[n, n] amplitude matrix. beta[i, j] is the leakage amplitude from source labels[j] onto victim labels[i] (column = source, row = victim). Diagonals represent self-coupling and are conventionally 1.0.

Type:

Any

theta

[n, n] phase matrix (radians), same indexing as beta.

Type:

Any

delay

[n, n] delay matrix (ns), same indexing as beta.

Type:

Any

Notes

Every off-diagonal edge reads the same input signal map, so reciprocal entries form one linear mixing stage without recursively leaking one another’s output. Matrix entries flow directly into the signal-program IR (PolarScale/Shift), preserving end-to-end JAX traceability.

labels: tuple[str, ...]
beta: Any
theta: Any
delay: Any
apply(signals)[source]

Apply all directed leakage edges to one shared input snapshot.

Parameters:

signals (dict[tuple[str, int], SignalNode])

Return type:

dict[tuple[str, int], SignalNode]

referenced_lines()[source]

Return control-line labels referenced by this transform.

Return type:

tuple[str, …]

without_line(line)[source]

Return this transform without line, or None when it must be dropped.

Parameters:

line (str)

Return type:

CrosstalkMatrix | None

edges()[source]

Return the directed-edge view used by topology and visualization.

Return type:

list[Crosstalk]

to_dict()[source]

Serialize into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct from to_dict() output.

On the registry root, dispatch to the concrete subclass named by data["type"] (forwarding *args / **kwargs). On a concrete subclass, defer to _from_dict_payload(). Concrete subclasses that carry payload override this method directly.

Parameters:

d (dict[str, Any])

Return type:

CrosstalkMatrix

class quchip.control.Gaussian(duration, sigmas=3, amplitude=1.0)[source]

Bases: EnvelopeShape

Centered Gaussian pulse.

\[E(t) = A \exp\!\left[-\frac{(t - \tau/2)^2}{2 \sigma^2}\right], \qquad \sigma = \frac{\tau}{2 N_\sigma}.\]

The sigmas parameter \(N_\sigma\) is the number of standard deviations from the pulse center to its edge at t = 0 or t = duration. Gaussian pulses minimize spectral leakage onto higher transmon levels and are the starting point for DRAG corrections (Motzoi et al., PRL 103, 110501 (2009)).

The scheduled window [0, duration] starts and ends at amplitude * exp(-sigmas**2 / 2), not zero — about 0.011 * amplitude at the default sigmas=3. The pulse turns on and off with that jump; the Gaussian waveform itself is unchanged.

Parameters:
  • duration (Any)

  • sigmas (Any)

  • amplitude (Any)

duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
sigmas: Any = Parameter(default=3, positive=True, nonnegative=False, serialize=True, unit=None)
amplitude: Any = Parameter(default=1.0, positive=False, nonnegative=False, serialize=True, unit=None)
value(t)[source]

Evaluate the centered Gaussian envelope at time points t.

Parameters:

t (Any)

Return type:

Any

class quchip.control.GaussianEdge(duration, edge_duration, sigmas=3, amplitude=1.0)[source]

Bases: EnvelopeShape

Flat-top pulse with Gaussian ramp-up and ramp-down edges.

Each edge is a Gaussian of width \(\sigma = \tau_e / (2 N_\sigma)\) where \(\tau_e\) = edge_duration; the plateau between edges holds a constant amplitude \(A\). Total duration includes both edges. Commonly used for two-qubit gates (Krantz et al. 2019, Sec. IV.C) because the flat top sets the gate area while the Gaussian edges suppress spectral leakage.

Parameters:
  • duration (float) – Total pulse length, including both edges, in ns.

  • edge_duration (float) – Ramp time \(\tau_e\) per edge, in ns. Must satisfy 2 * edge_duration <= duration.

  • sigmas (float) – Number of standard deviations spanned by each edge.

  • amplitude (float) – Plateau amplitude \(A\).

See also

SquareWithGaussianEdges

Same shape parameterized by edge_frac (fraction) instead of absolute edge_duration.

References

  • Krantz et al., APR 6, 021318 (2019), Sec. IV.C.

duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
edge_duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
sigmas: Any = Parameter(default=3, positive=True, nonnegative=False, serialize=True, unit=None)
amplitude: Any = Parameter(default=1.0, positive=False, nonnegative=False, serialize=True, unit=None)
validate()[source]

Reject edges that overrun the pulse (2 * edge_duration > duration).

Return type:

None

value(t)[source]

Evaluate the flat-top Gaussian-edge envelope at time points t.

Parameters:

t (Any)

Return type:

Any

class quchip.control.LinearRamp(duration, ramp_duration, amplitude=1.0)[source]

Bases: EnvelopeShape

Linearly rising ramp that holds at peak amplitude.

The envelope rises linearly from 0 to amplitude over the first ramp_duration nanoseconds, then holds constant at amplitude for the remainder of the pulse.

\[E(t) = A \cdot \min\!\left(\frac{t}{\tau_r},\, 1\right), \qquad 0 \le t \le \tau,\]

where \(\tau_r\) is ramp_duration and \(\tau\) is duration.

Parameters:
  • duration (float) – Total pulse duration in ns. Must be > 0.

  • ramp_duration (float) – Duration of the linear rise in ns. Must satisfy 0 < ramp_duration <= duration.

  • amplitude (float) – Peak amplitude \(A\) (default 1.0).

Notes

For an adiabatic ramp into a Kerr-cat qubit, choose ramp_duration long compared to 1 / (2 * K) (the inverse gap at the bifurcation point). See Grimm et al., Nature 584, 205 (2020).

The waveform is JAX-traceable: ramp_duration and amplitude may be JAX tracers so the ramp parameters are differentiable.

Examples

>>> from quchip.control.envelopes import LinearRamp
>>> ramp = LinearRamp(duration=60.0, ramp_duration=50.0, amplitude=4.0)
>>> import numpy as np
>>> t = np.array([0.0, 25.0, 50.0, 55.0])
>>> np.real(ramp.waveform(t)).tolist()
[0.0, 2.0, 4.0, 4.0]
duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
ramp_duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
amplitude: Any = Parameter(default=1.0, positive=False, nonnegative=False, serialize=True, unit=None)
validate()[source]

Reject ramps longer than the pulse (ramp_duration > duration).

Return type:

None

value(t)[source]

Evaluate the linear-ramp envelope at time points t (ns).

Parameters:

t (array-like) – 1-D array of time points in nanoseconds.

Returns:

Complex-valued waveform: rises linearly over ramp_duration, holds constant at amplitude afterward.

Return type:

array

class quchip.control.Square(duration, amplitude=1.0, phase=0.0)[source]

Bases: EnvelopeShape

Constant-amplitude pulse with optional global phase.

\[E(t) = A\, e^{i\phi}, \qquad 0 \le t \le \tau.\]
Parameters:
  • duration (float) – Pulse length \(\tau\) in ns.

  • amplitude (float) – Real amplitude \(A\) applied on top of value().

  • phase (float) – Global phase \(\phi\) in radians.

duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
amplitude: Any = Parameter(default=1.0, positive=False, nonnegative=False, serialize=True, unit=None)
phase: Any = Parameter(default=0.0, positive=False, nonnegative=False, serialize=True, unit='rad')
value(t)[source]

Evaluate the constant complex envelope at time points t.

Parameters:

t (Any)

Return type:

Any

class quchip.control.SquareWithGaussianEdges(duration, amplitude=1.0, edge_frac=0.25, sigmas=3)[source]

Bases: EnvelopeShape

Flat-top pulse with Gaussian ramp-up and ramp-down edges.

Each ramp has duration \(\tau_e = f_e \cdot \tau\) with \(f_e\) = edge_frac; the plateau between ramps holds amplitude \(A\). Total duration includes both edges. The Gaussian width is \(\sigma = \tau_e / (2 N_\sigma)\) with \(N_\sigma\) = sigmas.

This is the canonical shape used in Krantz et al. 2019 (Sec. IV.C) for two-qubit gates — the flat top sets the gate area while the Gaussian edges suppress spectral leakage. Parametrizing the ramp as a fraction of the total duration makes the shape shape-invariant under changes of duration.

Parameters:
  • duration (float) – Total pulse length in ns (includes both ramps).

  • amplitude (float) – Plateau amplitude \(A\).

  • edge_frac (float) – Ramp length as a fraction of the total duration. Must satisfy 0 < edge_frac and 2 * edge_frac <= 1.

  • sigmas (float) – Number of standard deviations spanned by each ramp.

duration: Any = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='ns')
amplitude: Any = Parameter(default=1.0, positive=False, nonnegative=False, serialize=True, unit=None)
edge_frac: Any = Parameter(default=0.25, positive=True, nonnegative=False, serialize=True, unit=None)
sigmas: Any = Parameter(default=3, positive=True, nonnegative=False, serialize=True, unit=None)
validate()[source]

Reject ramps that overrun the pulse (2 * edge_frac > 1).

Return type:

None

property edge_duration: float

Ramp duration in ns (edge_frac * duration).

value(t)[source]

Evaluate the fraction-parameterized Gaussian-edge envelope.

Parameters:

t (Any)

Return type:

Any

Modules

batch

Batch / sweep-axis machinery for QuantumSequence.

drive

Drive classes and Hamiltonian channel definitions.

drives_two_photon

TwoPhotonDrive -- parametric two-photon drive for Kerr-cat qubits.

envelopes

Pulse envelope models for quantum control.

equipment

Control-equipment container: drive lines and signal chain.

sequence

Declarative pulse programming for a Chip.

signal

Signal-chain transforms for control equipment.

signal_spec

Frame-agnostic drive signal specifications.