Domain: Physics — Statistical Mechanics

Problem:
Consider a spin chain with Hamiltonian \( H = -J\sum_{i=1}^{N-1}\sigma^x_i\sigma^x_{i+1} - h\sum_{i=1}^{N}\sigma^z_i \) with open boundaries, initial Néel state \( |\psi_0\rangle = |\uparrow\downarrow\uparrow\downarrow\cdots\rangle \), and observable \( A=\sum_{i=1}^{N}\sigma^z_i \) whose outcomes are \( m\in\{-N,-N+2,\ldots,N\} \) with degeneracy \( g_m \) (the number of computational-basis states having magnetization \( m \)). Derive, from first principles, the relation \( \varepsilon_m = R^{\mathrm{DE}}_m / p^{\mathrm{DE}}_m \) for the coarse-grained outcomes with projectors \( \Pi_m \).

Define \( \rho_{nn}=|\langle E_n|\psi_0\rangle|^2 \), \( U_{\mathrm{DE}}=\sum_n \rho_{nn} E_n \), \( p^{\mathrm{DE}}_m=\sum_n \rho_{nn}\langle E_n|\Pi_m|E_n\rangle \), and \( R^{\mathrm{DE}}_m=\sum_n \rho_{nn}E_n\langle E_n|\Pi_m|E_n\rangle \). Using maximum observable entropy \( S_{\mathrm{obs}}=-\sum_m p_m\ln(p_m/g_m) \) (natural logs) with constraints \( \sum_m p_m=1 \) and \( \sum_m \varepsilon_m p_m=U_{\mathrm{DE}} \), derive \( p^{\mathrm{MOEP}}_m=(g_m/Z)\exp(-\beta\varepsilon_m) \) with \( Z=\sum_m g_m\exp(-\beta\varepsilon_m) \), where \( \beta \) solves \( \sum_m \varepsilon_m p^{\mathrm{MOEP}}_m=U_{\mathrm{DE}} \). Then, for \( N=11 \), \( J=1 \), \( h=1.3 \), compute \( p^{\mathrm{DE}}_m \) and \( \varepsilon_m \) by exact diagonalization of \( H \)..

Deterministic support rule and zero-log convention: after computing raw \(p^{\mathrm{DE}}_m\), \(R^{\mathrm{DE}}_m\), first normalize by \(S_0=\sum_m p^{\mathrm{DE}}_m\); define \( \mathcal S=\{m:\, p^{\mathrm{DE}}_m \ge 10^{-15}\} \); set \(p^{\mathrm{DE}}_m=R^{\mathrm{DE}}_m=0\) for \(m\notin\mathcal S\) and renormalize \(p^{\mathrm{DE}}_m\) over \( \mathcal S \); compute \( \varepsilon_m \), MOEP, and \( \mathrm{JSD} \) strictly on \( \mathcal S \); use natural logs with \( 0\ln 0=0 \).

Through the determination of \( \beta \) by Brent’s method on \([-100,100]\) with tolerance \( 10^{-10} \); form \( p^{\mathrm{MOEP}}_m \); return the output,  the Jensen–Shannon divergence \( \mathrm{JSD}(p^{\mathrm{DE}},p^{\mathrm{MOEP}}) \) (natural logs) printed with three decimals, scientific notations.

Answer: \(6.203 \times10^{-2}\)

Solution code:
import numpy as np
from scipy.optimize import brent
from scipy.special import comb

N = 11
J = 1.0
h = 1.3

# Build Hamiltonian
dim = 2**N
H = np.zeros((dim, dim))

for state in range(dim):
    # Diagonal term: -h * sum_i sigma_z_i
    mag = 0
    for i in range(N):
        if (state >> i) & 1:
            mag += 1
        else:
            mag -= 1
    H[state, state] = -h * mag
    
    # Off-diagonal: -J * sum_i sigma_x_i sigma_x_{i+1}
    for i in range(N-1):
        flipped = state ^ (3 << i)  # Flip bits i and i+1
        H[state, flipped] -= J

# Diagonalize
E, V = np.linalg.eigh(H)

# Initial Néel state |↑↓↑↓↑↓↑↓↑↓↑⟩
neel_state = sum(1 << i for i in range(0, N, 2))  # Binary: 10101010101
psi0 = np.zeros(dim)
psi0[neel_state] = 1.0

# Compute rho_nn
rho_nn = np.abs(V.T @ psi0)**2

# Compute magnetization sectors
m_values = range(-N, N+1, 2)
g_m = {m: comb(N, (N-m)//2, exact=True) for m in m_values}

# Compute p_DE and R_DE
p_DE = {}
R_DE = {}

for m in m_values:
    p_m = 0
    R_m = 0
    for n in range(dim):
        # Check if eigenstate n contributes to magnetization m
        for state in range(dim):
            state_mag = sum(1 if (state >> i) & 1 else -1 for i in range(N))
            if state_mag == m:
                contrib = rho_nn[n] * abs(V[state, n])**2
                p_m += contrib
                R_m += contrib * E[n]
    p_DE[m] = p_m
    R_DE[m] = R_m

# Apply deterministic support rule
S0 = sum(p_DE.values())
p_DE = {m: p/S0 for m, p in p_DE.items()}
R_DE = {m: R/S0 for m, R in R_DE.items()}

support = {m for m in m_values if p_DE[m] >= 1e-15}
total_p = sum(p_DE[m] for m in support)

p_DE_final = {m: p_DE[m]/total_p if m in support else 0 for m in m_values}
epsilon_m = {m: R_DE[m]/p_DE[m] if m in support else 0 for m in support}

# Compute U_DE
U_DE = sum(epsilon_m[m] * p_DE_final[m] for m in support)

# Find beta using Brent's method
def energy_constraint(beta):
    Z = sum(g_m[m] * np.exp(-beta * epsilon_m[m]) for m in support)
    return sum(epsilon_m[m] * g_m[m]/Z * np.exp(-beta * epsilon_m[m]) 
               for m in support) - U_DE

beta_opt = brent(energy_constraint, brack=(-100, 100), tol=1e-10)

# Compute MOEP
Z = sum(g_m[m] * np.exp(-beta_opt * epsilon_m[m]) for m in support)
p_MOEP = {m: g_m[m]/Z * np.exp(-beta_opt * epsilon_m[m]) if m in support else 0 
          for m in m_values}

# Compute Jensen-Shannon Divergence
def jsd(p, q, support):
    m_dist = {m: 0.5*(p[m] + q[m]) for m in support}
    D_pm = sum(p[m] * np.log(p[m]/m_dist[m]) if p[m] > 0 else 0 for m in support)
    D_qm = sum(q[m] * np.log(q[m]/m_dist[m]) if q[m] > 0 else 0 for m in support)
    return 0.5 * (D_pm + D_qm)

jsd_value = jsd(p_DE_final, p_MOEP, support)
print(jsd_value)