Skip to content

Follow a Program into physical dynamics

A FatQat emulator follows the physical state during timed controls. It accepts a Program, builds a physical schedule, and integrates a time-dependent Hamiltonian (and, when requested, Lindblad evolution). Use it to study pulse duration, coupling, leakage, or noise acting continuously over elapsed time. Circuit simulators can include noise channels without resolving this time evolution.

Two authoring paths meet at that same schedule:

Program gate ----> calibration ----\
                                  +----> physical schedule
PulseOperation --> controls ------/               |
                                                   v
                                    Hamiltonian/Lindblad evolution

The model supplies the physical levels, units, drift, channels, and coupling. A gate implementation map turns an ordinary gate into calibrated controls. A direct pulse supplies those controls explicitly. The following pages apply this shared workflow to transmons and atoms.

Run a calibrated gate

Use a packaged physical model as a reproducible baseline, then construct its emulator. Here a one-qubit Program is realized on a model containing two three-level transmons:

>>> import numpy as np
>>> import fatqat as fq
>>> import fatqat.operations as ops
>>> model = fq.emulator.TransmonModel.from_document(
...     fq.emulator.load_model_document("transmon.reference")
... )
>>> backend = fq.emulator.TransmonEmulator(model)
>>> calibrated_program = fq.Program(1)
>>> calibrated_program.add(ops.RX(np.pi / 2), 0)
>>> calibrated_result = backend.run(calibrated_program).result()
>>> calibrated_result.get_statevector().shape
(9,)

RX remains an ordinary Program operation. At execution time, the emulator's gate map obtains a pulse recipe from its calibration and binds that recipe to the model's drive channel. The physical model has two qutrits, so the returned vector covers all \(3^2\) basis states, including the second transmon. The Program still declares one two-level qubit. Each transmon's third physical level lets the result show leakage out of its qubit states, |0> and |1>.

Packaged models and calibrations are reference snapshots. Supply a validated model document and implementation map when the physical system or calibration changes; do not interpret the packaged data as a live-device calibration.

Add a pulse directly

A direct pulse has three pieces: waveform samples, the physical channel they drive, and the duration of the control block. The code below builds them in that order as a SampledWaveform, a PulseControl, and finally a PulseOperation:

>>> duration = 20.0
>>> waveform = fq.emulator.SampledWaveform(
...     (0.0, 10.0, duration),
...     (0.0, 0.02, 0.0),
... )
>>> control = fq.emulator.PulseControl(
...     model.control.drive("q0"),
...     waveform,
... )
>>> pulse = ops.PulseOperation(duration=duration, controls=(control,))
>>> direct_program = fq.Program(1)
>>> direct_program.add(pulse)
>>> direct_result = backend.run(direct_program).result()
>>> direct_result.get_statevector().shape
(9,)

Notice that direct_program.add(pulse) has no logical target. The channel already names physical transmon q0, and a ResourceLayout does not remap that address. The model and channel define the time and value units; the API reference records the exact domains for each emulator.

Read a pulse as continuous evolution

The three waveform samples above specify a drive over the full 20-unit interval. The emulator interpolates between them, combines the drive with drift and coupling terms, and integrates the physical state. The state covers every level in the physical model throughout the pulse, including levels that the Program did not declare.

The next chapter turns this mechanism into a concrete transmon experiment: it compares a calibrated rotation with a direct drive and makes the resulting leakage visible.

Understand scheduling

All controls inside one PulseOperation share its interval; start_offset can move an individual waveform within that interval. Between operations, the schedule preserves source order for blocks that use the same physical resource and may overlap independent blocks. Choose "ASAP" or "ALAP" through simulation_config when that placement matters.

Drift and background continuous noise evolve throughout elapsed time. On an emulator that supports classical conditions, a false condition can skip a control block without deleting its duration, so the model still evolves during the interval. This lets you study the effect of elapsed time even when no control is active.

The constructor's method selects the mathematical representation and Result accessor: statevector (the default), density_matrix, or unitary. It does not select an internal differential-equation solver.

Continue with Transmon emulation or Neutral-atom emulation. For pulse object, schedule, execution-method, and model contracts, use the pulse-control API and emulator API.