neuralqx.experimental.operators.symbolic.dsl.op module

Fluent operator builder, the primary entry point to the symbolic DSL.

The DOperator class is the single entry point for constructing symbolic quantum operators.

Usage

from neuralqx.experimental.operators.symbolic import DOperator
from neuralqx.experimental.operators.symbolic.dsl import site, shift, swap, identity

# diagonal operator
N_e0 = (
    DOperator(hi, "N_e0", hermitian=True)
    .globally()
    .emit(identity(), amplitude=my_sq_norm_expr)
    .build()
)

# single-site off-diagonal
h_plus = (
    DOperator(hi, "h+")
    .for_each_site("e")
    .where(site("e") < cutoff)
    .emit(shift("e", +1))
    .build()
)

# hopping: compound update + amplitude from both DOFs
hop = (
    DOperator(hi, "hopping")
    .for_each_pair("i", "j")
    .where(site("i") > 0)
    .emit(
        shift("i", -1).shift("j", +1),
        amplitude=site("i").value * site("j").value,
    )
    .build()
)

# K-body: static triplet iterator
vol = (
    DOperator(hi, "triplet_volume")
    .for_each(("e1", "e2", "e3"), over=triplet_index_sets)
    .emit(identity(), amplitude=triple_product_expr)
    .build()
)

# multi-emission: two branches per iterator evaluation
two_branch = (
    DOperator(hi, "two_branch")
    .for_each_site("i")
    .where(site("i").abs() < 2)
    .emit(shift("i", +1), amplitude=+0.5)
    .emit(shift("i", -1), amplitude=-0.5)
    .build()
)

# compile directly (skip explicit .build())
compiled = DOperator(hi, "my_op").for_each_site("i").emit(shift("i", +1)).compile()

Iterator methods

Calling any for_each_* / globally method seals the current in-progress term and begins a new one. Calling .where or .emit after is always associated with the most recent iterator call.

Multi-emission

Multiple .emit(...) calls on the same iterator scope produce multiple output branches (EmissionSpec entries) from a single iterator evaluation. This avoids the overhead of iterating over sites twice and keeps the semantic unit cohesive.

Branch-multiset note

If two terms (or two emissions within one term) produce the same x', both entries appear in the padded output with their own matrix elements. The output is a branch multiset, not a canonical deduplicated row.

class DOperator(hilbert, name='operator', *, dtype='float64', hermitian=False)

Bases: object

Fluent builder for declarative symbolic quantum operators.

The builder accumulates one or more terms. Each term consists of an iterator (which sites to visit), an optional predicate (which visits to activate), and one or more emissions (how to rewrite the configuration and what matrix element to assign per active visit).

Calling any iterator method (for_each_site, for_each_pair, …, globally) seals the previous term (if any) and begins a new one. .where and .emit always target the current open term.

Parameters:
  • hilbert (DiscreteHilbert) – NetKet DiscreteHilbert space.

  • name (str) – Readable operator name (accessible as .name on the resulting SymbolicOperator).

  • dtype (str) – Matrix-element dtype string (default "float64").

  • hermitian (bool) – Whether to declare the operator Hermitian.