Selectors and expressions ========================= Selectors --------- Selectors are how you refer to site-local data symbolically. ``site(label)`` reads from the source configuration ``x`` ``emitted(label)`` reads from the emitted configuration ``x'`` after the update program has been applied for the current branch ``symbol(name)`` creates a free named symbol that is not tied to an iterator label. You can also declare ``default``, ``doc``, and ``dtype`` metadata. The selector object is :class:`nkdsl.dsl.selectors.SiteSelector`. Useful selector properties -------------------------- ``.value`` the quantum number at the current site label ``.index`` the integer site index bound by the iterator Example: .. code-block:: python from nkdsl import emitted, site, symbol amplitude = symbol("g") * site("i").value * emitted("j").value predicate = (site("i").index != site("j").index) & (site("i") > 0) Symbol declarations ------------------- Free symbols can be declared with optional metadata: .. code-block:: python from nkdsl import symbol J = symbol( "J", default=1.0, doc="Nearest-neighbor exchange coupling", dtype="float32", ) amplitude = J * site("i").value * emitted("j").value Declaration fields: ``default`` fallback value used when no runtime binding for the symbol is provided ``doc`` human-readable description for tooling/readability ``dtype`` optional NumPy-compatible dtype declaration. If omitted and ``default`` is provided, dtype is inferred from the default value. Practical behavior: * ``symbol("J")`` is unresolved and can trigger ``NKDSL-E001`` at compile time. * ``symbol("J", default=1.0)`` is considered resolved and does not trigger unresolved-symbol linting. * if ``dtype`` is declared, runtime values are coerced to that dtype in the lowered evaluator. Amplitude expressions --------------------- Numeric expressions are represented by :class:`nkdsl.ir.AmplitudeExpr`. In user code they are usually built through normal Python operators. .. code-block:: python expr = 0.5 * site("i").value + 2 * site("j").value Common helpers exposed through the IR and expression context include: * ``sqrt`` * ``conj`` * ``abs_`` * ``pow`` * ``wrap_mod`` * ``source_index`` and ``target_index`` for flat-index source/target access * ``static_index`` and ``static_emitted_index`` remain available on ``AmplitudeExpr`` ExpressionContext ----------------- For callback-based construction, ``nkDSL`` exposes :class:`nkdsl.dsl.context.ExpressionContext`. .. code-block:: python def amplitude(ctx): i = ctx.site("i") return ctx.sqrt(i.value + 1) The context API mirrors symbol declarations: .. code-block:: python def amplitude(ctx): J = ctx.symbol("J", default=1.0, dtype="float32") i = ctx.site("i") return J * i.value This is mainly useful when a symbolic expression is easier to write as a small function than as one inline statement.