Bind values before running a program¶
Declare parameters when you want to reuse a circuit or pulse structure while changing angles or amplitudes. Declare them through the Circuit or AHSProgram that uses them so types, units, bounds and usage locations stay together.
| Task | Entry point |
|---|---|
| Make a parameterized digital circuit executable | bound = circuit.bind(values) |
| Bind an analog waveform or phase | bound = program.bind(values) |
| Execute one declared program | LocalBackend.run(program, params=values).result() |
| Share a parameter between Hybrid blocks | Declare identical definitions in the blocks and let HybridProgram collect them |
| Execute several parameter points | Use a parameter scan instead of mutating the original program in a loop |
values maps parameter names to numbers. Check spelling, units and bounds. Unit labels do not convert MHz to rad/us. Shared declarations must agree on type, unit, bounds, default, expression and compilation impact; matching names alone are insufficient.
A complete binding example¶
This example binds an RY angle to 0.5 rad. bind() returns a new circuit while the original declaration remains symbolic.
"""Declare and bind a typed Digital rotation parameter.
Parameters remain symbolic while a circuit is reusable. ``bind`` creates a
new executable circuit, checks missing or unknown values, and preserves the
original declaration for another experiment.
"""
from __future__ import annotations
import json
from cascaqit import Circuit
def main() -> None:
"""Bind one angle and compare declaration with executable circuit."""
declaration = Circuit(1, program_id="lesson.digital.parameter")
theta = declaration.parameter("theta", lower_bound=-3.2, upper_bound=3.2)
declaration.ry(theta, 0).measure_all()
# Binding returns a separate circuit; the declaration stays symbolic.
bound = declaration.bind({"theta": 0.5})
result = bound.run(shots=0, seed=202, return_probabilities=True)
payload = {
"track": "digital_developer",
"level": "foundation",
"lesson": "parameter_binding",
"facts": {
"declaration_is_bound": declaration.is_bound,
"bound_is_bound": bound.is_bound,
"parameter_names": [item.name for item in bound.parameters],
"bound_angle": bound.operations[0].arguments["theta"],
"probability_sum": round(sum((result.probabilities or {}).values()), 12),
},
"boundaries": {
"hardware_execution": False,
"cloud_execution": False,
"network_accessed": False,
"credentials_loaded": False,
},
}
print(json.dumps(payload, sort_keys=True))
if __name__ == "__main__":
main()
python examples/user/tracks/digital_developer/02_foundation_parameter_binding_en.py
{
"boundaries": {
"cloud_execution": false,
"credentials_loaded": false,
"hardware_execution": false,
"network_accessed": false
},
"facts": {
"bound_angle": 0.5,
"bound_is_bound": true,
"declaration_is_bound": false,
"parameter_names": [
"theta"
],
"probability_sum": 1.0
},
"lesson": "parameter_binding",
"level": "foundation",
"track": "digital_developer"
}
Expect declaration_is_bound to be false, bound_is_bound true, and bound_angle 0.5. This run requests zero measurement shots and returns state probabilities, so empty counts do not indicate failure. probability_sum should equal one within numerical precision.
When binding fails¶
Check for missing required parameters, unknown names and values outside inclusive bounds. Derived parameters are computed from expressions; they are not independent inputs. Boolean parameters and numeric parameters are not interchangeable.
For a Hybrid conflict, correct the declarations in the source blocks. Repeating an unchanged request does not fix validation. See the shared-parameter lesson, Parameter and ParameterManager.