Skip to content

Analog Walkthrough

This walkthrough explains the short analog example at examples/release/minimal_analog_quickstart.py. Start with examples/learning/analog_first_run.py when you are learning the SDK for the first time; use this page when you want the shorter script explained line by line.

The example builds a tiny AHS program, validates it against a mock neutral-atom target, discretizes it to the target grid, runs local simulation, and prints a short summary. It does not submit to Hanyuan hardware or CASCAQit Cloud.

Run The Example

From the repository root:

python3 examples/release/minimal_analog_quickstart.py

Expected output:

{'program_type': 'analog', 'counts_total': 16, 'validation_errors': [], 'diagnostic_codes': ['SIMULATION_COMPLETED'], 'mean_excitation': 0.210409, 'hardware_execution': False, 'cloud_execution': False}

The fields are intentionally small. They tell you that the program is analog, the local simulator produced 16 shots, validation found no errors, simulation completed, and no hardware or cloud path was used.

Imports

The example uses the top-level public imports:

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

Use these imports when writing a first program. Package-level imports such as from cascaqit.analog import AHSProgram are also available, but the top-level imports are easier for quick examples.

Target And Register

The example starts with a mock target and a two-site atom register:

target = MockNeutralAtomTarget.v0_1()
register = AtomRegister.line(count=2, spacing=5.0)

MockNeutralAtomTarget.v0_1() provides local constraints for validation and discretization. It is not a live device connection.

AtomRegister.line(count=2, spacing=5.0) creates two atoms on a one-dimensional line. The spacing is chosen to satisfy the mock target constraints, so validation should not produce spacing errors.

Program And Drive

The analog program is built from the register:

program = AHSProgram(
    register,
    program_id="program.example.minimal_analog_quickstart",
)

The drive defines the time-dependent control fields:

program.drive(
    rabi=Waveform.linear(0.0, 2.0, duration=1.0, waveform_id="rabi"),
    detuning=Waveform.piecewise_linear(
        times=[0.0, 0.5, 1.0],
        values=[-4.0, 0.0, 4.0],
        waveform_id="detuning",
    ),
    phase=0.0,
)
program.measure()

rabi controls the drive strength. detuning changes over time through three points. phase is constant in this example. program.measure() adds a terminal measurement so the simulator can return bitstring counts.

Validate And Discretize

Before simulation, the example validates and discretizes the program:

validated = program.validate(target, shots=128)
discretized, _report = validated.discretize(target, policy="nearest")

Validation checks the program against target constraints, such as atom spacing, waveform shape, duration, and shot settings. In this valid example, validation_errors should be an empty list.

Discretization maps continuous program values to the target grid. The "nearest" policy means the SDK chooses the nearest representable value where quantization is needed. The example keeps the report out of the printed output so the terminal output stays small, but the report is useful when debugging larger programs.

Local Simulation

The example runs the local analog simulator:

result = LocalAhsSimulator(target=target, seed=1234).run(discretized, shots=16)

The seed makes the example deterministic enough for documentation and local checks. The result is a structured ResultIR-style object with counts, observables, diagnostics, and metadata.

Van Der Waals Interaction

Use VanDerWaalsInteraction when the register should evolve with a finite two-body term:

from cascaqit import LocalBackend, VanDerWaalsInteraction

register = AtomRegister.custom(
    ((0.0, 0.0), (5.0, 0.0), (2.0, 5.0), (8.0, 4.0))
)
program = AHSProgram(
    register,
    interaction=VanDerWaalsInteraction(
        c6=15_625.0,
        cutoff_radius=5.0,
        enabled=True,
    ),
)
program.drive(
    rabi=Waveform.constant(1.0, duration=0.2),
    detuning=Waveform.constant(0.0, duration=0.2),
    phase=0.0,
).measure()

result = LocalBackend(seed=31).run(program, shots=32).result()
interaction = result.interaction_report()

For every active pair whose Euclidean distance is less than or equal to the cutoff, the simulator applies

\[ V_{ij} = \frac{C_6}{r_{ij}^{6}}. \]

C6 uses rad*um^6/us; coordinates and cutoff use um. One-dimensional line registers and arbitrary two-dimensional registers share the same geometry model. Setting enabled=False keeps the configuration in the Program but contributes no pair energy.

For this standalone program, interaction_report() returns the executed coherent + crosstalk + number_number evidence. A Hybrid result with multiple Analog blocks uses interaction_reports() instead. This interaction is not the coherent XX crosstalk noise channel, and a finite interaction does not activate a hard-blockade subspace. Run python3 examples/user/van_der_waals_interaction.py for the complete deterministic example. Position-noise realization is an internal extension point only and has no user-facing configuration API yet.

Read The Output

The printed dictionary is a compact view over the result:

  • program_type: should be analog.
  • counts_total: should equal the requested local simulation shots.
  • validation_errors: should be empty for this valid example.
  • diagnostic_codes: should include SIMULATION_COMPLETED.
  • mean_excitation: a small observable derived from local simulation output.
  • hardware_execution: always False for this example.
  • cloud_execution: always False for this example.

Use ResultIR and ProgramIR as the source records when building larger tools. Printed dictionaries, reports, and visualization objects are derived views for inspection.

Reusable Parameters And Waveforms

For a reusable declaration, create parameters from the program and pass the returned values into waveforms:

omega = program.parameter("omega", unit="rad/us", default=1.0)
delta = program.parameter("delta", unit="rad/us")
rabi = Waveform.constant(omega, duration=0.25).concat(
    Waveform.constant(omega / 2, duration=0.25)
)
program.drive(
    rabi=rabi,
    detuning=Waveform.constant(delta, duration=0.5),
    phase=0.0,
).measure()

bound = program.bind({"delta": 0.4})
result = bound.run(shots=16, seed=17)

Parameters carry rad/us or rad; addition and subtraction require matching units, while multiplication and division accept finite scalar values. concat() only combines compatible constant-family or linear-family segments and keeps the source waveforms unchanged. Typed programs must be fully bound before IR export, validation, discretization, Local AHS execution, or Local Hybrid payload construction.

Run python3 examples/user/analog_program_ergonomics.py for the complete offline workflow.

What This Example Does Not Do

This walkthrough does not use live Hanyuan2 execution, live hardware execution, CASCAQit Cloud execution, network endpoint access, credential loading, object-store access, artifact-byte reads, package publication upload, or release signing.

The mock target, validation, discretization, and local simulator are enough to learn the analog programming shape. They are not proof of live hardware readiness.

SDK 1.0.8a · `8b227bff`