netket.operator.EmbedOperator#

class netket.operator.EmbedOperator[source]#

Bases: ABC

Inheritance
Inheritance diagram of netket.operator.EmbedOperator
__init__(hilbert, operator, subspace, **kwargs)[source]#

Embeds an operator acting on a subspace into a larger tensor product Hilbert space.

Mathematically, this operator represents:

\[\hat{O}_{\text{embed}} = \mathbb{I}_0 \otimes \mathbb{I}_1 \otimes \cdots \otimes \hat{O}_i \otimes \cdots \otimes \mathbb{I}_N\]

where \(\hat{O}_i\) is the operator acting on subspace \(i\), and \(\mathbb{I}_j\) are identity operators on all other subspaces \(j \neq i\).

This is useful for constructing operators on composite quantum systems, such as coupled electron-phonon systems, where you want an operator to act only on one subsystem (e.g., only on electrons or only on phonons) while leaving the other subsystems unchanged.

Parameters:
  • hilbert (TensorHilbert) – A TensorHilbert space representing the composite system. Must be a tensor product of multiple Hilbert spaces.

  • operator (AbstractOperator) – The operator to embed. Its Hilbert space must match the specified subspace of the tensor Hilbert space.

  • subspace (int) – The index of the subspace (in the TensorHilbert) where the operator acts. Must satisfy hilbert.subspaces[subspace] == operator.hilbert.

Warning

Performance consideration for Hamiltonian construction:

When building complex Hamiltonians, the order of operations matters significantly for performance. Operators should be simplified before embedding to avoid creating many redundant embedded operators that cannot be combined, leading to very high connected elements count.

Try to always simplify first, then embed:

# Build the full operator on the subspace first
h_fermion = sum(nk.operator.boson.number(hi_boson, i) for i in range(N))
h_embed = nk.operator.EmbedOperator(hi_joint, h_fermion, subspace=0)
H = H + h_embed  # Single embedded operator

as opposed to this negative example below

# Don't do this! Creates many embedded operators that can't be simplified
for i in range(N):
    h_fermion = nk.operator.boson.number(hi_boson, i)
    # Embedding inside the loop prevents simplification!
    h_embed = nk.operator.EmbedOperator(hi_joint, h_fermion, subspace=0)
    H = H + h_embed  # Many redundant embedded operators!

The first approach creates a single embedded operator with optimized connected elements, while the second creates N separate embedded operators that cannot be combined, resulting in significantly more connected states and slower evaluation.

Examples

Embed a spin operator in a composite spin-boson system:

>>> import netket as nk
>>> # Create subsystems
>>> hi_spin = nk.hilbert.Spin(s=1/2, N=2)
>>> hi_boson = nk.hilbert.Fock(n_max=3, N=2)
>>> hi_joint = nk.hilbert.TensorHilbert(hi_spin, hi_boson)
>>> # Create operator on spin subsystem
>>> sx = nk.operator.spin.sigmax(hi_spin, 0)
>>> # Embed it in the joint space (acts on subspace 0)
>>> sx_embed = nk.operator.EmbedOperator(hi_joint, sx, subspace=0)

Combine embedded operators from different subspaces:

>>> # Bosonic operator on second subspace
>>> n_b = nk.operator.boson.number(hi_boson, 0)
>>> n_b_embed = nk.operator.EmbedOperator(hi_joint, n_b, subspace=1)
>>> # Combine them
>>> H = sx_embed + 0.5 * n_b_embed  # Spin + phonon Hamiltonian
>>> H_interaction = sx_embed @ n_b_embed  # Spin-phonon coupling
Attributes
dtype#
operator#

The tuple of all operators in the terms of this sum. Every operator is summed with a corresponding coefficient

subspace#

The index of the subspace in the hilbert space.

Methods