Skip to content

MPS Initialization

Construct a symmetry-aware initial MPS for tensor network algorithms.

init_mps

init_mps(
    L: int,
    Spc: Index,
    Op: Dict[str, Tensor],
    bond_dim: int = 1,
    *,
    config: Optional[list[int]] = None,
    target_qn=None,
    seed: int = 42,
) -> MPS

Construct an initial MPS for DMRG.

Works for all three particle types (bosonic, fermionic, conductor) without a particle-type argument. The (Spc, Op) pair from load_space carries all required symmetry information.

Parameters:

Name Type Description Default
L int

Chain length.

required
Spc Index

Physical Index returned by load_space.

required
Op Dict[str, Tensor]

Operator dictionary returned by load_space.

required
bond_dim int

Target bond dimension.

  • bond_dim=1: deterministic product state, bond dimension 1. Best used with CBE (scheme='1sp') or 2-site (scheme='2s') DMRG.
  • bond_dim>1: random MPS with group-derived bond sectors. Bond sectors are chosen by BFS from the center-bond charge to depth 2, fixing the sector count regardless of L.
1
config Optional[list[int]]

Optional list of physical-sector indices (0-based into Spc.sectors), one per site. When None (default) _auto_config selects a balanced configuration targeting target_qn (see below).

None
target_qn

Desired total quantum number of the chain, i.e. the right-boundary charge Q[L]. When None (default) the target is Q_vac (half-filling).

The parameter affects both modes, but in different ways:

  • bond_dim=1 (product state): target_qn is passed to _auto_config which tries to find a config whose charge path ends at target_qn. The right boundary is always Q[L] from the resulting path.
  • bond_dim>1 (random MPS): _auto_config targets target_qn for a physically relevant center-bond charge. The right boundary is explicitly pinned to target_qn.

In both modes, if the auto-config's Q[L] differs from target_qn (meaning target_qn is unreachable for this L and physical space), a ValueError is raised. When target_qn is None and Q[L] is not Q_vac (e.g. odd L), a WARNING is logged instead.

None
seed int

Base random seed used when bond_dim>1. Site i uses seed+i.

42

Returns:

Type Description
MPS

Right-canonical MPS with orthogonality center at site 0.

Raises:

Type Description
ValueError

If bond_dim < 1, if an explicit config has the wrong length, or if an explicit target_qn is not reachable for the given L and physical space (i.e. auto-config's charge path ends at a different sector).

Examples:

Product state for Heisenberg spin-½ (U1), ready for 1sp DMRG:

>>> from nicole import load_space
>>> from alice import init_mps
>>> Spc, Op = load_space('Spin', 'U1', {'J': 0.5})
>>> mps = init_mps(20, Spc, Op, bond_dim=1)

Random MPS for spinless fermions (U1), bond dimension 32:

>>> Spc, Op = load_space('Ferm', 'U1')
>>> mps = init_mps(20, Spc, Op, bond_dim=32)

Odd-length chain — product state and random MPS with explicit Sz = +½:

>>> Spc, Op = load_space('Spin', 'U1', {'J': 0.5})
>>> mps1 = init_mps(7, Spc, Op, bond_dim=1,  target_qn=1)
>>> mps2 = init_mps(7, Spc, Op, bond_dim=32, target_qn=1)

Notes

init_mps operates in two modes selected by bond_dim:

Product state (bond_dim=1) — every virtual bond carries a single sector whose charge is determined by propagating the physical charges of the chosen site configuration through the group fusion rules. For Abelian groups this is additive; for SU(2) and product groups containing SU(2) the minimum-branch (dimer/VBS) rule selects the lowest-spin channel at each step. The result is a bond-dimension-1 MPS in a definite target sector. This mode pairs naturally with CBE (scheme='1sp') or 2-site (scheme='2s') DMRG, which grow the bond dimension during the first few sweeps.

Random MPS (bond_dim>1) — bond sectors are discovered by a breadth-first search (BFS) of depth 2 from the center-bond charge, so the sector set is independent of chain length and contains only charges reachable by physical fusion steps. Tensors are filled with random entries and the MPS is canonicalized with a two-pass sweep (right to site L-1, then left back to site 0) to compress spurious bond dimension from both ends.

Both modes are particle-type agnostic: no spin=, symmetry=, or particle_type= argument is required. The (Spc, Op) pair returned by Nicole's load_space encodes all symmetry information.

Logic Overview

The diagram below summarises how target_qn, config, Q[L], and bond_dim interact inside init_mps.

 target_qn given?
 ├─ No  ──► target = Q_vac  (half-filling default)
 └─ Yes ──► target = target_qn

 config given?
 ├─ No  ──► cfg = _auto_config(L, Spc, group, Q_vac, target)
 │             tries: single-sector fill → period-2 alternation → greedy
 └─ Yes ──► cfg = config  (used verbatim)

 Q = _bond_charges(cfg, Q_vac)   →  Q[0..L]

 Q[L] == target?
 ├─ Yes ──► (no action)
 └─ No  ──┬─ target was defaulted (Q_vac) ──► WARNING  (e.g. odd L, no target_qn given)
          └─ target was explicit          ──► ValueError  (physically unreachable)

 effective_right = target  if target was given explicitly
                 = Q[L]    if target was defaulted  (crucial for odd-L random MPS)

 bond_dim == 1?
 ├─ Yes ──► product_state_mps(cfg, Q)   right boundary = Q[L]  (rigid)
 └─ No  ──► random_mps(Q, bond_dim, effective_right)
               BFS seed  = Q[L//2]   (center-bond charge from cfg)
               right pin = effective_right

The key asymmetry is that in product-state mode the right boundary is always Q[L] — it cannot be overridden because every intermediate bond charge is fixed by the charge path. In random mode the right boundary is pinned explicitly to effective_right, which decouples it from the config path.

Charge Conventions

All standard Nicole physical spaces define charges relative to the half-filled reference, so the center-bond charge for a balanced even-L auto-config is zero:

Space Sectors Q_vac
Spin U(1) Sz = ±½ → charges ±1 0
Spin SU(2) multiplet label 2J 0
Ferm U(1) empty/occupied → charges ±1 0
Ferm Z₂ even/odd parity 0
Band U(1)⊗U(1) (±1, ±1) (0, 0)
Band Z₂⊗U(1) (parity, spin) (0, 0)
Band U(1)⊗SU(2) (charge, spin) (0, 0)
Band Z₂⊗SU(2) (parity, spin) (0, 0)

Bond Sectors in Random Mode

Bond sectors for the random MPS (bond_dim>1) are found by BFS of depth 2 from Q_c = Q[L//2]. The table below lists the resulting sector sets for a Q_vac-targeted auto-config (spin-½ where applicable):

Space Bond sectors Count
Spin U(1) −2, −1, 0, +1, +2 5
Spin SU(2) 2J = 0, 1, 2 3
Ferm U(1) −2, −1, 0, +1, +2 5
Ferm Z₂ 0, 1 2
Band U(1)⊗U(1) (c, s) with |c| + |s| ≤ 2 13
Band Z₂⊗U(1) (0, 0), (0, ±2), (1, ±1) 5
Band U(1)⊗SU(2) (c, 2J) with |c| ≤ 2, 2J ≤ 2 9
Band Z₂⊗SU(2) (0, 0), (0, 2), (1, 1) 3

When target_qn is given, Q_c = Q[L//2] is computed from the target_qn-targeted auto-config, which shifts the center-bond charge toward the requested sector.

Odd-chain lengths

For odd L, no site configuration can return the bond charge to Q_vac in an odd number of fusion steps with the standard physical sectors. The three exact strategies in _auto_config (single-sector fill and period-2 alternation) all fail, and the greedy fallback produces Q[L] ≠ Q_vac.

Default behavior (target_qn not given): init_mps targets Q_vac and, finding Q[L] ≠ Q_vac, logs a WARNING that multiple target sectors may exist and recommends passing target_qn explicitly. Both modes then use the greedy's Q[L] as the effective right boundary.

Explicit target_qn: pass the desired sector directly. For Abelian 2-sector spaces the greedy reaches the target exactly when it is achievable (correct parity and magnitude). If the requested sector is unreachable — e.g. target_qn=0 for odd-L spin-½ — init_mps raises a ValueError in both modes rather than silently constructing an MPS in the wrong sector.

# Spin-½ U(1), L=7 — both modes work with the same target_qn
Spc, Op = load_space('Spin', 'U1', {'J': 0.5})

# Product state in the Sz = +½ sector
mps_ps = init_mps(7, Spc, Op, bond_dim=1,  target_qn=1)

# Random MPS in the Sz = +½ sector, bond dimension 32
mps_rd = init_mps(7, Spc, Op, bond_dim=32, target_qn=1)

For Abelian spaces the two valid targets for odd-L spin-½ are target_qn=+1 (Sz = +½) and target_qn=-1 (Sz = −½). Any other value is physically unreachable and raises ValueError.

See Also