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
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 beanalog.counts_total: should equal the requested local simulation shots.validation_errors: should be empty for this valid example.diagnostic_codes: should includeSIMULATION_COMPLETED.mean_excitation: a small observable derived from local simulation output.hardware_execution: alwaysFalsefor this example.cloud_execution: alwaysFalsefor 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.