Spin-glass problem

Note

It is highly recommended to read the Independent set problem chapter before reading this one.

using GenericTensorNetworks

Spin-glass problem on a simple graph

Let $G=(V, E)$ be a graph, the spin-glass problem in physics is characterized by the following energy function

\[H = \sum_{ij \in E} J_{ij} s_i s_j + \sum_{i \in V} h_i s_i,\]

where $h_i$ is an onsite energy term associated with spin $s_i \in \{-1, 1\}$, and $J_{ij}$ is the coupling strength between spins $s_i$ and $s_j$. In the program, we use boolean variable $n_i = \frac{1-s_i}{2}$ to represent a spin configuration.

using Graphs

In the following, we are going to defined an spin glass problem for the Petersen graph.

graph = Graphs.smallgraph(:petersen)
{10, 15} undirected simple Int64 graph

We can visualize this graph using the following function

rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a
locations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]
show_graph(graph, locations; format=:svg)

Generic tensor network representation

An anti-ferromagnetic spin glass problem can be defined with the SpinGlass type as

spinglass = SpinGlass(graph, fill(1, ne(graph)))
SpinGlass{Vector{Int64}}(10, [[1, 2], [1, 5], [1, 6], [2, 3], [2, 7], [3, 4], [3, 8], [4, 5], [4, 9], [5, 10]  …  [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

The tensor network representation of the set packing problem can be obtained by

problem = GenericTensorNetwork(spinglass)
GenericTensorNetwork{SpinGlass{Vector{Int64}}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}(SpinGlass{Vector{Int64}}(10, [[1, 2], [1, 5], [1, 6], [2, 3], [2, 7], [3, 4], [3, 8], [4, 5], [4, 9], [5, 10]  …  [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 6∘7∘4, 4∘7∘6 -> 
├─ 6∘5∘3∘7, 3∘5∘4 -> 6∘7∘4
│  ├─ 6∘5∘3∘7, 3∘6∘5∘7 -> 6∘5∘3∘7
│  │  ├─ 2∘6∘5, 3∘7∘2 -> 6∘5∘3∘7
│  │  │  ├─ 2∘6∘1, 1∘5 -> 2∘6∘5
│  │  │  │  ├─ 1∘2, 1∘6 -> 2∘6∘1
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ 5, 1∘5 -> 1∘5
│  │  │  │     ⋮
│  │  │  │     
│  │  │  └─ 2∘3, 2∘7 -> 3∘7∘2
│  │  │     ├─ 3, 2∘3 -> 2∘3
│  │  │     │  ⋮
│  │  │     │  
│  │  │     └─ 7, 2∘7 -> 2∘7
│  │  │        ⋮
│  │  │        
│  │  └─ 3∘6∘8, 5∘7∘8 -> 3∘6∘5∘7
│  │     ├─ 3∘8, 6∘8 -> 3∘6∘8
│  │     │  ├─ 8, 3∘8 -> 3∘8
│  │     │  │  ⋮
│  │     │  │  
│  │     │  └─ 6∘8
│  │     └─ 5∘7∘10, 8∘10 -> 5∘7∘8
│  │        ├─ 5∘10, 7∘10 -> 5∘7∘10
│  │        │  ⋮
│  │        │  
│  │        └─ 8∘10
│  └─ 3∘4, 4∘5 -> 3∘5∘4
│     ├─ 4, 3∘4 -> 3∘4
│     │  ├─ 4
│     │  └─ 4, 3∘4 -> 3∘4
│     │     ├─ 4
│     │     └─ 3∘4
│     └─ 4∘5
└─ 4∘7∘9, 6∘9 -> 4∘7∘6
   ├─ 4∘9, 7∘9 -> 4∘7∘9
   │  ├─ 9, 4∘9 -> 4∘9
   │  │  ├─ 9
   │  │  └─ 9, 4∘9 -> 4∘9
   │  │     ├─ 9
   │  │     └─ 4∘9
   │  └─ 7∘9
   └─ 6∘9
, Dict{Int64, Int64}())

The contraction order is already optimized.

The tensor network reduction

We defined the reduction of the spin-glass problem to a tensor network on a hypergraph. Let $H = (V, E)$ be a hypergraph, the tensor network for the spin glass problem on $H$ can be defined as the following triple of (alphabet of labels $\Lambda$, input tensors $\mathcal{T}$, output labels $\sigma_o$).

\[\begin{cases} \Lambda &= \{s_v \mid v \in V\}\\ \mathcal{T} &= \{B^{(c)}_{s_{N(c, 1),N(c, 2),\ldots,N(c, d(c))}} \mid c \in E\} \cup \{W^{(v)}_{s_v} \mid v \in V\}\\ \sigma_o &= \varepsilon \end{cases}\]

where $s_v \in \{0, 1\}$ is the boolean degreen associated to vertex $v$, $N(c, k)$ is the $k$th vertex of hyperedge $c$, and $d(c)$ is the degree of $c$. The edge tensor $B^{(c)}$ is defined as

\[B^{(c)} = \begin{cases} x^{w_c} & (\sum_{v\in c} s_v) \;is\; even, \\ x^{-w_c} & otherwise. \end{cases}\]

and the vertex tensor $W^{(v)}$ (used to carry labels) is defined as

\[W^{(v)} = \left(\begin{matrix}1_v\\ 1_v\end{matrix}\right)\]

Graph properties

Minimum and maximum energies

To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.

Emin = solve(problem, SizeMin())[]
-9.0ₜ

The state with the highest energy is the one with all spins having the same value.

Emax = solve(problem, SizeMax())[]
15.0ₜ

Counting properties

In the following, we are going to find the partition function and the graph polynomial of the spin glass problem. Consider a spin glass problem on a graph $G = (V, E)$ with integer coupling strength $J$ and onsite energy $h$. Its graph polynomial is a Laurent polynomial

\[Z(G, J, h, x) = \sum_{k=E_{\rm min}}^{E_{\rm max}} c_k x^k,\]

where $E_{\rm min}$ and $E_{\rm max}$ are minimum and maximum energies, $c_k$ is the number of spin configurations with energy $k$. The partition function at temperature $\beta^{-1}$ can be computed by the graph polynomial at $x = e^-\beta$.

partition_function = solve(problem, GraphPolynomial())[]
10.0∙x⁻⁹ + 60.0∙x⁻⁷ + 120.0∙x⁻⁵ + 120.0∙x⁻³ + 150.0∙x⁻¹ + 240.0∙x + 200.0∙x³ + 72.0∙x⁵ + 30.0∙x⁷ + 20.0∙x⁹ + 2.0∙x¹⁵

Configuration properties

The ground state of the spin glass problem can be found by the SingleConfigMin solver.

ground_state = solve(problem, SingleConfigMin())[].c.data
1011011001

The energy of the ground state can be verified by the spinglass_energy function.

Emin_verify = spinglass_energy(spinglass, ground_state)
-9

You should see a consistent result as above Emin.

show_graph(graph, locations; vertex_colors=[
        iszero(ground_state[i]) ? "white" : "red" for i=1:nv(graph)], format=:svg)

In the plot, the red vertices are the ones with spin value -1 (or 1 in the boolean representation).

Spin-glass problem on a hypergraph

A spin-glass problem on hypergraph $H = (V, E)$ can be characterized by the following energy function

\[E = \sum_{c \in E} w_{c} \prod_{v\in c} S_v\]

where $S_v \in \{-1, 1\}$, $w_c$ is coupling strength associated with hyperedge $c$. In the program, we use boolean variable $s_v = \frac{1-S_v}{2}$ to represent a spin configuration.

In the following, we are going to defined an spin glass problem for the following hypergraph.

num_vertices = 15

hyperedges = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],
    [1,2,14,15], [3,6,10,12,14], [8,14,15],
    [1,2,6,11], [1,2,4,6,8,12]]

weights = [-1, 1, -1, 1, -1, 1, -1, 1];

The energy function of the spin glass problem is

\[\begin{align*} E = &-S_1S_3S_4S_6S_7 + S_4S_7S_8S_{12} - S_2S_5S_9S_{11}S_{13} +\\ &S_1S_2S_{14}S_{15} - S_3S_6S_{10}S_{12}S_{14} + S_8S_{14}S_{15} +\\ &S_1S_2S_6S_{11} - S_1s_2S_4S_6S_8S_{12} \end{align*}\]

A spin glass problem can be defined with the SpinGlass type as

hyperspinglass = SpinGlass(num_vertices, hyperedges, weights)
SpinGlass{Vector{Int64}}(15, [[1, 3, 4, 6, 7], [4, 7, 8, 12], [2, 5, 9, 11, 13], [1, 2, 14, 15], [3, 6, 10, 12, 14], [8, 14, 15], [1, 2, 6, 11], [1, 2, 4, 6, 8, 12]], [-1, 1, -1, 1, -1, 1, -1, 1])

The tensor network representation of the set packing problem can be obtained by

hyperproblem = GenericTensorNetwork(hyperspinglass)
GenericTensorNetwork{SpinGlass{Vector{Int64}}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}(SpinGlass{Vector{Int64}}(15, [[1, 3, 4, 6, 7], [4, 7, 8, 12], [2, 5, 9, 11, 13], [1, 2, 14, 15], [3, 6, 10, 12, 14], [8, 14, 15], [1, 2, 6, 11], [1, 2, 4, 6, 8, 12]], [-1, 1, -1, 1, -1, 1, -1, 1]), 7∘8∘4∘12, 4∘7∘8∘12 -> 
├─ 1∘4∘7∘12∘14∘6, 14∘4∘12∘6∘8∘1 -> 7∘8∘4∘12
│  ├─ 1∘3∘4∘6∘7, 3∘6∘12∘14∘10 -> 1∘4∘7∘12∘14∘6
│  │  ├─ 7, 7∘1∘3∘4∘6 -> 1∘3∘4∘6∘7
│  │  │  ├─ 7
│  │  │  └─ 6, 6∘7∘1∘3∘4 -> 7∘1∘3∘4∘6
│  │  │     ├─ 6
│  │  │     └─ 4, 4∘6∘7∘1∘3 -> 6∘7∘1∘3∘4
│  │  │        ⋮
│  │  │        
│  │  └─ 10, 3∘6∘10∘12∘14 -> 3∘6∘12∘14∘10
│  │     ├─ 10
│  │     └─ 3∘6∘10∘12∘14
│  └─ 6∘8∘14∘1∘2, 1∘2∘4∘6∘8∘12 -> 14∘4∘12∘6∘8∘1
│     ├─ 1∘6∘2, 1∘2∘8∘14 -> 6∘8∘14∘1∘2
│     │  ├─ 2∘5∘9∘11∘13, 1∘2∘6∘11 -> 1∘6∘2
│     │  │  ├─ 13, 13∘2∘5∘9∘11 -> 2∘5∘9∘11∘13
│     │  │  │  ⋮
│     │  │  │  
│     │  │  └─ 1∘2∘6∘11
│     │  └─ 1∘2∘14∘15, 8∘14∘15 -> 1∘2∘8∘14
│     │     ├─ 15, 1∘2∘15∘14 -> 1∘2∘14∘15
│     │     │  ⋮
│     │     │  
│     │     └─ 8∘14∘15
│     └─ 1∘2∘4∘6∘8∘12
└─ 12, 4∘7∘12∘8 -> 4∘7∘8∘12
   ├─ 12
   └─ 8, 4∘7∘8∘12 -> 4∘7∘12∘8
      ├─ 8
      └─ 4∘7∘8∘12
, Dict{Int64, Int64}())

Graph properties

Minimum and maximum energies

To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.

Emin = solve(hyperproblem, SizeMin())[]
-8.0ₜ
Emax = solve(hyperproblem, SizeMax())[]
8.0ₜ

In this example, the spin configurations can be chosen to make all hyperedges having even or odd spin parity.

Counting properties

partition function and graph polynomial

The graph polynomial defined for the spin-glass problem is a Laurent polynomial

\[Z(G, w, x) = \sum_{k=E_{\rm min}}^{E_{\rm max}} c_k x^k,\]

where $E_{\rm min}$ and $E_{\rm max}$ are minimum and maximum energies, $c_k$ is the number of spin configurations with energy $k$. Let the inverse temperature $\beta = 2$, the partition function is

β = 2.0
Z = solve(hyperproblem, PartitionFunction(β))[]
1.3151672584981668e9

The infinite temperature partition function is the counting of all feasible configurations

solve(hyperproblem, PartitionFunction(0.0))[]
32768.0

The graph polynomial is

poly = solve(hyperproblem, GraphPolynomial())[]
128.0∙x⁻⁸ + 1024.0∙x⁻⁶ + 3584.0∙x⁻⁴ + 7168.0∙x⁻² + 8960.0 + 7168.0∙x² + 3584.0∙x⁴ + 1024.0∙x⁶ + 128.0∙x⁸

Configuration properties

The ground state of the spin glass problem can be found by the SingleConfigMin solver.

ground_state = solve(hyperproblem, SingleConfigMin())[].c.data
010101011101011

The energy of the ground state can be verified by the spinglass_energy function.

Emin_verify = spinglass_energy(hyperspinglass, ground_state)
-8

You should see a consistent result as above Emin.


This page was generated using Literate.jl.