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 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:

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:

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 nkdsl.ir.AmplitudeExpr. In user code they are usually built through normal Python operators.

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 nkdsl.dsl.context.ExpressionContext.

def amplitude(ctx):
    i = ctx.site("i")
    return ctx.sqrt(i.value + 1)

The context API mirrors symbol declarations:

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.