Parameter Validation and Aliases

Parameter Validation and Aliases#

This example demonstrates how parameter names are resolved via aliasing rules (braces, underscores, and spaces) and how the library validates that all required numeric parameters are present before backend compilation.

What you’ll learn#

  • The aliasing behavior for parameter names and how to supply values in params.

  • How missing parameters produce informative DSLValidationError messages.

Source#

  1# flake8: noqa
  2"""
  3Parameter validation, alias rules, and backend dispatch.
  4
  5This example walks through:
  6- Collecting required parameters from IR (Hamiltonian + collapse ops).
  7- Resolving aliases like omega_{c} vs omega_c.
  8- Seeing early validation errors before touching a backend.
  9- Dispatching to different backends after validation.
 10
 11Call functions individually; nothing runs on import.
 12"""
 13
 14from __future__ import annotations
 15
 16import sys
 17from pathlib import Path
 18from typing import Dict, Iterable, Tuple
 19
 20ROOT = Path(__file__).resolve().parents[1]
 21if str(ROOT) not in sys.path:
 22    sys.path.insert(0, str(ROOT))
 23
 24from latex_parser.backend_utils import (
 25    collect_parameter_names,
 26    param_aliases,
 27    resolve_param,
 28    validate_required_params,
 29)
 30from latex_parser.compile_core import compile_model_core
 31from latex_parser.dsl import HilbertConfig, QubitSpec
 32from latex_parser.ir import latex_to_ir
 33
 34
 35def list_aliases(symbol: str) -> None:
 36    """
 37    Show the alias spellings we try for a given parameter name.
 38    """
 39    print("Aliases for", symbol, ":", param_aliases(symbol))
 40
 41
 42def collect_required_params(
 43    H_latex: str, c_ops_latex: Iterable[str] | None, cfg: HilbertConfig
 44) -> Tuple[set[str], set[str]]:
 45    """
 46    Return (required_symbols, time_names) for a Hamiltonian/c_ops pair.
 47    """
 48    ir = latex_to_ir(H_latex, cfg, t_name="t")
 49    time_names = {"t"}
 50    required = collect_parameter_names(ir, cfg, time_names)
 51    for c in c_ops_latex or []:
 52        ir_c = latex_to_ir(c, cfg, t_name="t")
 53        required |= collect_parameter_names(ir_c, cfg, time_names)
 54    return required, time_names
 55
 56
 57def demonstrate_validation() -> None:
 58    """
 59    Run validation for a simple driven qubit with collapse.
 60    """
 61    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
 62    H = r"\frac{\omega_0}{2} \sigma_{z,1} + A \cos(\omega t) \sigma_{x,1}"
 63    c_ops = [r"\sqrt{\gamma} \sigma_{-,1}"]
 64    required, time_names = collect_required_params(H, c_ops, cfg)
 65    print("Required symbols:", sorted(required))
 66    params_good = {"omega_0": 2.0, "A": 0.5, "omega": 1.0, "gamma": 0.1}
 67    validate_required_params(required, params_good, time_names)
 68    params_missing = {"omega_0": 2.0}
 69    try:
 70        validate_required_params(required, params_missing, time_names)
 71    except Exception as exc:  # noqa: BLE001 - user-facing demo
 72        print("Expected failure:", exc)
 73
 74
 75def resolve_examples() -> None:
 76    """
 77    Demonstrate resolve_param on multiple spellings.
 78    """
 79    params = {"omega_c": 1.0, "kappa": 0.1, "A": 0.5}
 80    for name in ["omega_{c}", "omega c", "kappa", "A"]:
 81        key, val = resolve_param(name, params)
 82        print(f"{name!r} resolved to key={key!r}, val={val}")
 83
 84
 85def dispatch_after_validation() -> None:
 86    """
 87    Show full validation + dispatch using compile_model_core.
 88    """
 89    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
 90    H = r"\delta \sigma_{x,1}"
 91    params = {"delta": 0.4}
 92    model = compile_model_core(
 93        backend="qutip",
 94        H_latex=H,
 95        params=params,
 96        config=cfg,
 97        c_ops_latex=None,
 98        t_name="t",
 99        time_symbols=None,
100    )
101    print("Dispatched model type:", type(model))
102
103
104def advanced_alias_patterns() -> None:
105    """
106    Show aliases with braces, spaces, and asterisks.
107    """
108    cases = ["omega_{c}", "omega_{ c }", "omega*c", "omega c", "{omega_c}"]
109    for case in cases:
110        print(case, "->", param_aliases(case))
111
112
113def guard_against_operator_symbols() -> None:
114    """
115    Confirm operator symbols are not treated as params during collection.
116    """
117    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
118    H = r"\omega \sigma_{z,1} + \sigma_{x,1}"
119    ir = latex_to_ir(H, cfg, t_name="t")
120    req = collect_parameter_names(ir, cfg, {"t"})
121    print("Parameters collected (should exclude operators):", req)
122
123
124def validate_with_multiple_time_symbols() -> None:
125    """
126    Collect params when multiple time-like symbols are in use.
127    """
128    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
129    H = r"A \cos(\omega t) \sigma_{x,1} + B \sin(\nu s) \sigma_{x,1}"
130    ir = latex_to_ir(H, cfg, t_name="t", time_symbols=("s",))
131    req = collect_parameter_names(ir, cfg, {"t", "s"})
132    print("Required with extra time symbols:", sorted(req))
133
134
135def validate_collapse_time_dependence() -> None:
136    """
137    Show param collection for time-dependent collapse operators.
138    """
139    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
140    c_ops = [r"\sqrt{\gamma(t)} \sigma_{-,1}", r"\sqrt{\kappa} \sigma_{x,1}"]
141    req = set()
142    for c in c_ops:
143        ir = latex_to_ir(c, cfg, t_name="t")
144        req |= collect_parameter_names(ir, cfg, {"t"})
145    print("Collapse-required params:", sorted(req))
146
147
148def compare_backends_after_validation() -> None:
149    """
150    Dispatch the same LaTeX to multiple backends after validation.
151    """
152    cfg = HilbertConfig(qubits=[QubitSpec(label="q", index=1)], bosons=[], customs=[])
153    H = r"\delta \sigma_{x,1}"
154    params = {"delta": 0.4}
155    for backend in ("qutip", "numpy"):
156        model = compile_model_core(
157            backend=backend,
158            H_latex=H,
159            params=params,
160            config=cfg,
161            c_ops_latex=None,
162            t_name="t",
163            time_symbols=None,
164        )
165        print(f"Backend {backend} produced type:", type(model))
166
167
168def resolve_bulk(names: Iterable[str], params: Dict[str, complex]) -> None:
169    """
170    Resolve a list of names against a parameter dict.
171    """
172    for name in names:
173        try:
174            key, val = resolve_param(name, params)
175            print(f"{name!r} -> {key!r}={val}")
176        except Exception as exc:  # noqa: BLE001 - user-facing demo
177            print(f"{name!r} -> error {exc}")
178
179
180def resolve_demonstration_suite() -> None:
181    """
182    Suite of resolve_param calls covering edge cases.
183    """
184    params = {"omega_c": 1.0, "g": 0.5, "alpha": 0.3}
185    names = ["omega_{c}", "omega*c", "omega c", "omega{c}", "g", "beta"]
186    resolve_bulk(names, params)
187
188
189def main() -> None:
190    list_aliases("omega_{c}")
191    demonstrate_validation()
192    resolve_examples()
193    dispatch_after_validation()
194    advanced_alias_patterns()
195    guard_against_operator_symbols()
196    validate_with_multiple_time_symbols()
197    validate_collapse_time_dependence()
198    compare_backends_after_validation()
199    resolve_demonstration_suite()
200    print("End of parameter validation tour.")
201
202
203# Notes for developers:
204# - The registry-based dispatch in compile_core already performs the
205#   required-parameter collection shown above; this file exposes the same
206#   helpers for learning and debugging.
207# - To plug in your own backend, register it via `register_backend` and the
208#   same validation will run automatically.
209
210
211if __name__ == "__main__":
212    main()

Run#

python examples/example_param_validation_and_aliases.py

Notes#

  • Use this example when you encounter parameter lookup failures; it shows the candidate names the library will try.