Skip to content

Give each atom a different detuning

Apply one local waveform with different weights on two atoms. Read the bound values, inspect target-grid adjustments and identify which program actually runs. Complete waveform design first; this local two-atom example uses 120 time steps and 16 shots.

A local detuning contributes −Δ_local(t) Σ_i w_i n_i to the Hamiltonian. With global detuning included, site i sees Δ_global(t) + w_i Δ_local(t) for this single local term. The weights are dimensionless. They scale a detuning, not the probability of choosing a site.

Here Δ_local rises from zero to 0.8 rad/us, with weights 1 on q0 and 0.25 on q1. Predict the two final detunings. Also explain why this diagonal control alone would not excite an atom starting in a computational-basis state; the global Rabi drive supplies state transitions in this experiment.

Keep time and space separate

"""Apply a time-dependent local detuning with a static site pattern.

The waveform carries time dependence; ``SitePattern`` carries register-aligned
dimensionless weights. They remain separate typed objects and are validated
against a target that explicitly supports local AHS controls.
"""

from __future__ import annotations

import json

from cascaqit import (
    AHSProgram,
    AtomRegister,
    MockNeutralAtomTarget,
    SitePattern,
    Waveform,
)


def main() -> None:
    """Bind, validate, discretize, and run one addressed detuning term."""
    program = AHSProgram(
        AtomRegister.line(count=2, spacing=5.0),
        program_id="lesson.experimentalist.detuning",
    )
    delta = program.parameter("delta", default=0.8, lower_bound=-2.0, upper_bound=2.0)
    program.drive(
        rabi=Waveform.constant(0.6, duration=0.3),
        detuning=Waveform.constant(0.0, duration=0.3),
        phase=0.0,
    ).local_detuning(
        waveform=Waveform.linear(0.0, delta, duration=0.3),
        pattern=SitePattern.from_mapping({"q0": 1.0, "q1": 0.25}),
    ).measure()
    bound = program.bind({})
    target = MockNeutralAtomTarget.local_ahs_v0_1()
    validated = bound.validate(target, shots=16)
    discretized, report = validated.discretize(target)
    result = bound.run(shots=16, seed=303, time_steps=120)
    term = discretized.program_ir.hamiltonian.local_detuning_terms[0]

    payload = {
        "track": "quantum_experimentalist",
        "level": "applied",
        "lesson": "local_detuning",
        "facts": {
            "site_ids": list(term.addressing.site_ids),
            "weights": list(term.addressing.weights[0]),
            "addressing_frame_count": term.addressing.frame_count,
            "waveform_values": list(term.waveform.values or ()),
            "discretized_paths": [
                item.path
                for item in report.field_reports
                if "local_detuning" in item.path
            ],
            "validation_errors": [
                item.code for item in validated.diagnostics if item.severity == "error"
            ],
            "counts_total": sum(result.counts.values()),
        },
        "boundaries": {
            "hardware_execution": False,
            "cloud_execution": False,
            "network_accessed": False,
            "credentials_loaded": False,
        },
    }
    print(json.dumps(payload, sort_keys=True))


if __name__ == "__main__":
    main()

Download the full script

python3 examples/user/tracks/quantum_experimentalist/03_applied_local_detuning_en.py

bind({}) uses the declared default for delta; it is not an instruction to leave the parameter unresolved. SitePattern.from_mapping supplies every filled site. The SDK aligns the weights with register order, so dictionary insertion order does not determine the physical assignment.

{
  "boundaries": {
    "cloud_execution": false,
    "credentials_loaded": false,
    "hardware_execution": false,
    "network_accessed": false
  },
  "facts": {
    "addressing_frame_count": 1,
    "counts_total": 16,
    "discretized_paths": [],
    "site_ids": [
      "q0",
      "q1"
    ],
    "validation_errors": [],
    "waveform_values": [
      0.0,
      0.8
    ],
    "weights": [
      1.0,
      0.25
    ]
  },
  "lesson": "local_detuning",
  "level": "applied",
  "track": "quantum_experimentalist"
}

The final local detunings are 0.8 and 0.2 rad/us. addressing_frame_count = 1 means that the spatial pattern is static even though its waveform changes with time. The default numbers already fit the mock target grid, so discretized_paths is empty.

The script has two branches: it inspects discretized.program_ir, but bound.run(...) executes the original bound program. For these on-grid values the distinction is harmless. If you introduce off-grid values, do not describe its counts as execution of the adjusted program. To run that adjusted program, pass the discretized object to LocalAhsSimulator(target=target).run(discretized, shots=16), as in the Analog guide.

The helper bound.run() selects a local-control-capable mock target when none is supplied. An explicitly supplied conservative target is not silently replaced. Geometry and any selected blockade model still matter when interpreting a two-atom probability distribution.

Change one part of the control

  1. Swap the two weights. Predict the final detuning at each site and inspect the aligned arrays.
  2. Change the default to 0.8004. Compare the bound waveform with waveform_values and discretized_paths in the output. Which program does the unchanged run line execute?
  3. Remove q1 from the pattern. Then try a weight larger than one. Read the input errors instead of assigning physical meaning to an invalid configuration.
Check your reasoning

Swapping weights gives 0.2 on q0 and 0.8 rad/us on q1. With the 0.8004 default, nearest-grid projection changes the waveform endpoint to 0.8 and records its path, while the original bound waveform remains 0.8004. The unchanged bound.run() still uses that original. A dense SitePattern must cover every filled site and its weights must remain in [0, 1], with at least one nonzero weight. Use a sparse SiteMask when binary selection expresses the intended control better.

A small difference in sixteen sampled counts cannot establish a site-specific response. Inspect probabilities or a specified observable and repeat the comparison with a sampling budget chosen in advance. Continue with local Rabi control for a pulse that directly drives a selected atom. The local-detuning guide covers multiple additive terms and dynamic masks.

中文版

SDK 1.0.8a · `8b227bff`