diff --git a/Project.toml b/Project.toml index caaa297..7e5effd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpinGlassNetworks" uuid = "b7f6bd3e-55dc-4da6-96a9-ef9dbec6ac19" authors = ["Anna Maria Dziubyna ", "Tomasz Śmierzchalski ", "Bartłomiej Gardas ", "Konrad Jałowiecki ", "Łukasz Pawela ", "Marek M. Rams "] -version = "1.1.2" +version = "1.2.0" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" diff --git a/docs/src/api.md b/docs/src/api.md index cf987b7..8a78487 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -14,14 +14,14 @@ couplings ## Clustered Hamiltonian ```@docs split_into_clusters -decode_clustered_hamiltonian_state +decode_potts_hamiltonian_state rank_reveal energy energy_2site cluster_size bond_energy exact_cond_prob -truncate_clustered_hamiltonian +truncate_potts_hamiltonian ``` ## Belief propagation @@ -31,7 +31,7 @@ interaction_energy get_neighbors MergedEnergy update_message -merge_vertices_cl_h +merge_vertices_potts_h projector SparseCSC ``` @@ -54,8 +54,8 @@ brute_force ## Truncate ```@docs -truncate_clustered_hamiltonian_1site_BP -truncate_clustered_hamiltonian_2site_energy +truncate_potts_hamiltonian_1site_BP +truncate_potts_hamiltonian_2site_energy select_numstate_best ``` diff --git a/docs/src/bp.md b/docs/src/bp.md index 918f826..ebbc553 100644 --- a/docs/src/bp.md +++ b/docs/src/bp.md @@ -1,9 +1,9 @@ ## Belief propagation -Local dimensional reduction can be achieved by selectively choosing states in the clustered Hamiltonian that have the lowest local energy in the cluster. This approach aims to reduce the dimensionality of the problem by focusing on the most relevant and energetically favorable states. It can be done by truncation based on energy or truncation based on Loopy Belief Propagation. +Local dimensional reduction can be achieved by selectively choosing states in the Potts Hamiltonian that have the lowest local energy in the cluster. This approach aims to reduce the dimensionality of the problem by focusing on the most relevant and energetically favorable states. It can be done by truncation based on energy or truncation based on Loopy Belief Propagation. ```@docs -clustered_hamiltonian_2site +potts_hamiltonian_2site belief_propagation -truncate_clustered_hamiltonian_2site_BP +truncate_potts_hamiltonian_2site_BP ``` \ No newline at end of file diff --git a/docs/src/clh.md b/docs/src/clh.md index c3ba34a..c588b01 100644 --- a/docs/src/clh.md +++ b/docs/src/clh.md @@ -1,10 +1,10 @@ # Introduction -A clustered Hamiltonian is a graphical representation that allows for a convenient and intuitive way to describe the structure of a network. +A Potts Hamiltonian is a graphical representation that allows for a convenient and intuitive way to describe the structure of a network. -The concept of a clustered Hamiltonian within `SpinGlassNetworks.jl` introduces a mechanism for organizing spins into desired geometries, facilitating a structured approach to modeling complex spin systems. Analogous to a standard factor graph, the clustered Hamiltonian involves nodes that represent tensors within the underlying network. The edges connecting these nodes in the clustered Hamiltonian correspond to the indices shared between the respective tensors in the tensor network. +The concept of a Potts Hamiltonian within `SpinGlassNetworks.jl` introduces a mechanism for organizing spins into desired geometries, facilitating a structured approach to modeling complex spin systems. Analogous to a standard factor graph, the Potts Hamiltonian involves nodes that represent tensors within the underlying network. The edges connecting these nodes in the Potts Hamiltonian correspond to the indices shared between the respective tensors in the tensor network. ```@docs -clustered_hamiltonian +potts_hamiltonian ``` ## Simple example @@ -16,8 +16,8 @@ using SpinGlassNetworks instance = "$(@__DIR__)/../../src/instances/square_diagonal/5x5/diagonal.txt" ig = ising_graph(instance) -# Create clustered Hamiltonian -cl_h = clustered_hamiltonian( +# Create Potts Hamiltonian +potts_h = potts_hamiltonian( ig, cluster_assignment_rule = super_square_lattice((5,5,4)) ) diff --git a/docs/src/lattice.md b/docs/src/lattice.md index 05f4821..5f2ddc6 100644 --- a/docs/src/lattice.md +++ b/docs/src/lattice.md @@ -1,5 +1,5 @@ # Lattice geometries -The Ising graph allowed for loading instances directly from a file and translating them into a graph. The next step towards constructing the tensor network is to build a lattice, based on which we will transform the Ising graph into a clustered Hamiltonian. +The Ising graph allowed for loading instances directly from a file and translating them into a graph. The next step towards constructing the tensor network is to build a lattice, based on which we will transform the Ising graph into a Potts Hamiltonian. Within the `SpinGlassNetworks.jl` package, users have the flexibility to construct three types of lattice geometries, each tailored to specific needs. ## Super square lattice @@ -27,12 +27,12 @@ m = 5 n = 5 t = 4 -cl_h = clustered_hamiltonian( +potts_h = potts_hamiltonian( ig, cluster_assignment_rule = super_square_lattice((m, n, t)) ) -println("Number of nodes in oryginal instance: ", length(LabelledGraphs.vertices(ig)), "\n", " Number of nodes in clustered Hamiltonian: ", length(LabelledGraphs.vertices(cl_h))) +println("Number of nodes in oryginal instance: ", length(LabelledGraphs.vertices(ig)), "\n", " Number of nodes in Potts Hamiltonian: ", length(LabelledGraphs.vertices(potts_h))) ``` ## Pegasus graphs @@ -61,12 +61,12 @@ m = 3 n = 3 t = 3 -cl_h = clustered_hamiltonian( +potts_h = potts_hamiltonian( ig, cluster_assignment_rule = pegasus_lattice((m, n, t)) ) -println("Number of nodes in original instance: ", length(LabelledGraphs.vertices(ig)), "\n", " Number of nodes in clustered Hamiltonian: ", length(LabelledGraphs.vertices(cl_h))/2) +println("Number of nodes in original instance: ", length(LabelledGraphs.vertices(ig)), "\n", " Number of nodes in Potts Hamiltonian: ", length(LabelledGraphs.vertices(potts_h))/2) ``` @@ -96,7 +96,7 @@ m = 6 n = 6 t = 4 -cl_h = clustered_hamiltonian( +potts_h = potts_hamiltonian( ig, cluster_assignment_rule = zephyr_lattice((m, n, t)) ) diff --git a/docs/src/userguide.md b/docs/src/userguide.md index cb92310..e9d8313 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -2,4 +2,4 @@ A [Julia](http://julialang.org) package for building and interacting with Ising spin glass models in context of tensor networks. Part of [SpinGlassPEPS](https://github.com/euro-hpc-pl/SpinGlassPEPS.jl) package. -The contents of our package are illustrated through comprehensive examples, showcasing the practical utilization of key functions. Specifically, the `ising_graph` function is highlighted, demonstrating its capacity to generate Ising model graphs — a fundamental step in modeling spin systems. Additionally, the `clustered_hamiltonian` function is presented as a tool for converting Ising graphs into clustered Hamiltonians. The package delves into various lattice geometries, providing insights into constructing diverse structures such as the `super_square_lattice`, `pegasus_lattice`, and `zephyr_lattice`. Moreover, the documentation outlines methods for local dimensional reduction, shedding light on techniques to streamline computations and enhance the efficiency of spin system simulations. +The contents of our package are illustrated through comprehensive examples, showcasing the practical utilization of key functions. Specifically, the `ising_graph` function is highlighted, demonstrating its capacity to generate Ising model graphs — a fundamental step in modeling spin systems. Additionally, the `potts_hamiltonian` function is presented as a tool for converting Ising graphs into Potts Hamiltonians. The package delves into various lattice geometries, providing insights into constructing diverse structures such as the `super_square_lattice`, `pegasus_lattice`, and `zephyr_lattice`. Moreover, the documentation outlines methods for local dimensional reduction, shedding light on techniques to streamline computations and enhance the efficiency of spin system simulations. diff --git a/examples/bp.jl b/examples/bp.jl index b580145..b327460 100644 --- a/examples/bp.jl +++ b/examples/bp.jl @@ -13,7 +13,7 @@ Instance below looks like this: | 7 -- 8 -- 9 """ -function create_larger_example_clustered_hamiltonian_tree() +function create_larger_example_potts_hamiltonian_tree() instance = Dict( (1, 1) => 0.5, (2, 2) => 0.25, @@ -48,22 +48,22 @@ function create_larger_example_clustered_hamiltonian_tree() 9 => (3, 3, 1), ) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, Dict{NTuple{3,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule, ) - ig, cl_h + ig, potts_h end -ig, cl_h = create_larger_example_clustered_hamiltonian_tree() +ig, potts_h = create_larger_example_potts_hamiltonian_tree() beta = 0.1 iter = 0 -beliefs = belief_propagation(cl_h, beta; iter = iter) +beliefs = belief_propagation(potts_h, beta; iter = iter) -for v in vertices(cl_h) - en = get_prop(cl_h, v, :spectrum).energies +for v in vertices(potts_h) + en = get_prop(potts_h, v, :spectrum).energies println("vertex ", v, " energy = ", en .- minimum(en), " bp = ", beliefs[v]) end diff --git a/examples/temp.jl b/examples/temp.jl index 78d325b..6f99cf0 100644 --- a/examples/temp.jl +++ b/examples/temp.jl @@ -81,34 +81,34 @@ function load_openGM(fname::String, Nx::Integer, Ny::Integer) result end -function clustered_hamiltonian(fname::String, Nx::Integer = 240, Ny::Integer = 320) +function potts_hamiltonian(fname::String, Nx::Integer = 240, Ny::Integer = 320) loaded_rmf = load_openGM(fname, Nx, Ny) functions = loaded_rmf["fun"] factors = loaded_rmf["fac"] N = loaded_rmf["N"] clusters = super_square_lattice((Nx, Ny, 1)) - cl_h = LabelledGraph{MetaDiGraph}(sort(collect(values(clusters)))) - for v ∈ cl_h.labels + potts_h = LabelledGraph{MetaDiGraph}(sort(collect(values(clusters)))) + for v ∈ potts_h.labels x, y = v sp = Spectrum( Vector{Real}(undef, 1), Array{Vector{Int}}(undef, 1, 1), Vector{Int}(undef, 1), ) - set_props!(cl_h, v, Dict(:cluster => v, :spectrum => sp)) + set_props!(potts_h, v, Dict(:cluster => v, :spectrum => sp)) end for (index, value) in factors if length(index) == 2 y, x = index Eng = sum(functions[value]) - set_props!(cl_h, (x + 1, y + 1), Dict(:eng => Eng)) + set_props!(potts_h, (x + 1, y + 1), Dict(:eng => Eng)) elseif length(index) == 4 y1, x1, y2, x2 = index - add_edge!(cl_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1)) + add_edge!(potts_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1)) Eng = sum(functions[value], dims = 2) set_props!( - cl_h, + potts_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1), Dict( @@ -127,7 +127,7 @@ function clustered_hamiltonian(fname::String, Nx::Integer = 240, Ny::Integer = 3 end end - cl_h + potts_h end @@ -135,4 +135,4 @@ x, y = 240, 320 filename = "/home/tsmierzchalski/.julia/dev/SpinGlassNetworks/examples/penguin-small.h5" -cf = clustered_hamiltonian(filename, x, y) +cf = potts_hamiltonian(filename, x, y) diff --git a/src/SpinGlassNetworks.jl b/src/SpinGlassNetworks.jl index 05c2ea7..4ecc7ec 100644 --- a/src/SpinGlassNetworks.jl +++ b/src/SpinGlassNetworks.jl @@ -15,7 +15,7 @@ import Base.Prehashed include("ising.jl") include("spectrum.jl") include("lattice.jl") -include("clustered_hamiltonian.jl") +include("potts_hamiltonian.jl") include("bp.jl") include("truncate.jl") include("utils.jl") diff --git a/src/bp.jl b/src/bp.jl index 1ef02ef..0b62afb 100644 --- a/src/bp.jl +++ b/src/bp.jl @@ -1,36 +1,36 @@ export belief_propagation, - clustered_hamiltonian_2site, + potts_hamiltonian_2site, projector, get_neighbors, MergedEnergy, update_message, - merge_vertices_cl_h, + merge_vertices_potts_h, local_energy, interaction_energy, SparseCSC """ $(TYPEDSIGNATURES) -Perform loopy belief propagation on a given clustered Hamiltonian. +Perform loopy belief propagation on a given Potts Hamiltonian. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labelled graph. - `beta::Real`: The inverse temperature parameter for the belief propagation algorithm. - `tol::Real (optional, default=1e-6)`: The convergence tolerance. The algorithm stops when the message updates between iterations are smaller than this value. - `iter::Int (optional, default=1)`: The maximum number of iterations to perform. # Returns: -- `beliefs::Dict`: A dictionary where keys are vertices of clustered hamiltonian, and values are the +- `beliefs::Dict`: A dictionary where keys are vertices of Potts Hamiltonian, and values are the resulting beliefs after belief propagation. -The function implements loopy belief propagation on the given clustered hamiltonian `cl_h` to calculate beliefs for each vertex. -Belief propagation is an iterative algorithm that computes beliefs by passing messages between vertices and edges of the clustered hamiltonian. +The function implements loopy belief propagation on the given Potts Hamiltonian `potts_h` to calculate beliefs for each vertex. +Belief propagation is an iterative algorithm that computes beliefs by passing messages between vertices and edges of the Potts Hamiltonian. The algorithm continues until convergence or until the specified maximum number of iterations is reached. The beliefs are computed based on the inverse temperature parameter `beta`, which controls the influence of energy values on the beliefs. """ function belief_propagation( - cl_h::LabelledGraph{S,T}, + potts_h::LabelledGraph{S,T}, beta::Real; tol = 1e-6, iter = 1, @@ -39,8 +39,8 @@ function belief_propagation( messages_ev = Dict() # Initialize messages with uniform probabilities - for v in vertices(cl_h) - for (n, pv, _) in get_neighbors(cl_h, v) + for v in vertices(potts_h) + for (n, pv, _) in get_neighbors(potts_h, v) push!(messages_ev, (n, v) => ones(maximum(pv))) end end @@ -51,16 +51,16 @@ function belief_propagation( while !converged && iteration < iter # Set an appropriate number of iterations and convergence threshold iteration += 1 old_messages_ev = deepcopy(messages_ev) - for v in vertices(cl_h) + for v in vertices(potts_h) #update messages from vertex to edge node_messages = Dict() - for (n1, pv1, _) ∈ get_neighbors(cl_h, v) + for (n1, pv1, _) ∈ get_neighbors(potts_h, v) node_messages[n1, v] = messages_ev[n1, v][pv1] end - for (n1, pv1, _) ∈ get_neighbors(cl_h, v) - E_local = get_prop(cl_h, v, :spectrum).energies + for (n1, pv1, _) ∈ get_neighbors(potts_h, v) + E_local = get_prop(potts_h, v, :spectrum).energies temp = exp.(-(E_local .- minimum(E_local)) * beta) - for (n2, pv2, _) in get_neighbors(cl_h, v) + for (n2, pv2, _) in get_neighbors(potts_h, v) if n1 == n2 continue end @@ -72,8 +72,8 @@ function belief_propagation( end #update messages from edge to vertex - for v in vertices(cl_h) - for (n, _, en) ∈ get_neighbors(cl_h, v) + for v in vertices(potts_h) + for (n, _, en) ∈ get_neighbors(potts_h, v) messages_ev[n, v] = update_message(en, messages_ve[n, v], beta) end end @@ -86,10 +86,10 @@ function belief_propagation( end beliefs = Dict() - for v in vertices(cl_h) - E_local = get_prop(cl_h, v, :spectrum).energies + for v in vertices(potts_h) + E_local = get_prop(potts_h, v, :spectrum).energies beliefs[v] = exp.(-E_local * beta) - for (n, pv, _) ∈ get_neighbors(cl_h, v) + for (n, pv, _) ∈ get_neighbors(potts_h, v) beliefs[v] .*= messages_ev[n, v][pv] end beliefs[v] = -log.(beliefs[v]) ./ beta @@ -101,10 +101,10 @@ end """ $(TYPEDSIGNATURES) -Returns the neighbors of a given vertex in a clustered Hamiltonian. +Returns the neighbors of a given vertex in a Potts Hamiltonian. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `vertex::NTuple`: The vertex for which neighbors are to be retrieved. # Returns: @@ -114,23 +114,23 @@ Each tuple contains the following information: - `pv::Matrix`: The projector associated with the edge connecting the vertex and its neighbor. - `en::Real`: The energy associated with the edge connecting the vertex and its neighbor. -This function retrieves the neighbors of a given vertex in a clustered Hamiltonian graph. +This function retrieves the neighbors of a given vertex in a Potts Hamiltonian graph. It iterates through the edges of the graph and identifies edges connected to the specified vertex. For each neighboring edge, it extracts and returns the neighboring vertex, the associated projector, and the energy. """ -function get_neighbors(cl_h::LabelledGraph{S,T}, vertex::NTuple) where {S,T} +function get_neighbors(potts_h::LabelledGraph{S,T}, vertex::NTuple) where {S,T} neighbors = [] - for edge in edges(cl_h) + for edge in edges(potts_h) src_node, dst_node = src(edge), dst(edge) if src_node == vertex - en = get_prop(cl_h, src_node, dst_node, :en) - idx_pv = get_prop(cl_h, src_node, dst_node, :ipl) - pv = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pv, :CPU) + en = get_prop(potts_h, src_node, dst_node, :en) + idx_pv = get_prop(potts_h, src_node, dst_node, :ipl) + pv = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pv, :CPU) push!(neighbors, (dst_node, pv, en)) elseif dst_node == vertex - en = get_prop(cl_h, src_node, dst_node, :en)' - idx_pv = get_prop(cl_h, src_node, dst_node, :ipr) - pv = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pv, :CPU) + en = get_prop(potts_h, src_node, dst_node, :en)' + idx_pv = get_prop(potts_h, src_node, dst_node, :ipr) + pv = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pv, :CPU) push!(neighbors, (src_node, pv, en)) end end @@ -255,44 +255,44 @@ end """ $(TYPEDSIGNATURES) -Constructs a clustered Hamiltonian for a given clustered Hamiltonian with a 2-site cluster approximation used in Pegasus graph. +Constructs a Potts Hamiltonian for a given Potts Hamiltonian with a 2-site cluster approximation used in Pegasus graph. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labelled graph. - `beta::Real`: The inverse temperature parameter for the 2-site cluster Hamiltonian construction. # Returns: -- `new_cl_h::LabelledGraph{MetaDiGraph}`: A new labelled graph representing the 2-site cluster Hamiltonian. +- `new_potts_h::LabelledGraph{MetaDiGraph}`: A new labelled graph representing the 2-site cluster Hamiltonian. -This function constructs a clustered Hamiltonian `cl_h` by applying a 2-site cluster approximation. +This function constructs a Potts Hamiltonian `potts_h` by applying a 2-site cluster approximation. It combines and merges vertices and edges of the original graph to create a simplified representation of the Hamiltonian. -The resulting `new_cl_h` graph represents the 2-site cluster Hamiltonian with simplified interactions between clusters. +The resulting `new_potts_h` graph represents the 2-site cluster Hamiltonian with simplified interactions between clusters. The energy values, projectors, and spectra associated with the new vertices and edges are computed based on the provided temperature parameter `beta`. """ -function clustered_hamiltonian_2site(cl_h::LabelledGraph{S,T}, beta::Real) where {S,T} +function potts_hamiltonian_2site(potts_h::LabelledGraph{S,T}, beta::Real) where {S,T} - unified_vertices = unique([vertex[1:2] for vertex in vertices(cl_h)]) - new_cl_h = LabelledGraph{MetaDiGraph}(unified_vertices) + unified_vertices = unique([vertex[1:2] for vertex in vertices(potts_h)]) + new_potts_h = LabelledGraph{MetaDiGraph}(unified_vertices) new_lp = PoolOfProjectors{Int}() vertx = Set() - for v in vertices(cl_h) + for v in vertices(potts_h) i, j, _ = v if (i, j) ∈ vertx continue end - E1 = local_energy(cl_h, (i, j, 1)) - E2 = local_energy(cl_h, (i, j, 2)) - E = energy_2site(cl_h, i, j) .+ reshape(E1, :, 1) .+ reshape(E2, 1, :) + E1 = local_energy(potts_h, (i, j, 1)) + E2 = local_energy(potts_h, (i, j, 2)) + E = energy_2site(potts_h, i, j) .+ reshape(E1, :, 1) .+ reshape(E2, 1, :) sp = Spectrum(reshape(E, :), [], []) - set_props!(new_cl_h, (i, j), Dict(:spectrum => sp)) + set_props!(new_potts_h, (i, j), Dict(:spectrum => sp)) push!(vertx, (i, j)) end edge_states = Set() - for e ∈ edges(cl_h) + for e ∈ edges(potts_h) if e in edge_states continue end @@ -304,25 +304,25 @@ function clustered_hamiltonian_2site(cl_h::LabelledGraph{S,T}, beta::Real) where continue end - add_edge!(new_cl_h, (v1, v2), (w1, w2)) + add_edge!(new_potts_h, (v1, v2), (w1, w2)) - E, pl, pr = merge_vertices_cl_h(cl_h, beta, v, w) + E, pl, pr = merge_vertices_potts_h(potts_h, beta, v, w) ipl = add_projector!(new_lp, pl) ipr = add_projector!(new_lp, pr) - set_props!(new_cl_h, (v1, v2), (w1, w2), Dict(:ipl => ipl, :en => E, :ipr => ipr)) + set_props!(new_potts_h, (v1, v2), (w1, w2), Dict(:ipl => ipl, :en => E, :ipr => ipr)) push!(edge_states, sort([(v1, v2), (w1, w2)])) end - set_props!(new_cl_h, Dict(:pool_of_projectors => new_lp)) - new_cl_h + set_props!(new_potts_h, Dict(:pool_of_projectors => new_lp)) + new_potts_h end """ $(TYPEDSIGNATURES) -Merge two vertices in a clustered Hamiltonian to create a single merged vertex. +Merge two vertices in a Potts Hamiltonian to create a single merged vertex. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `β::Real`: The temperature parameter controlling the influence of energy values. - `node1::NTuple{3, Int64}`: The coordinates of the first vertex to merge. - `node2::NTuple{3, Int64}`: The coordinates of the second vertex to merge. @@ -332,15 +332,15 @@ Merge two vertices in a clustered Hamiltonian to create a single merged vertex. - `pl::AbstractVector`: The merged left projector. - `pr::AbstractVector`: The merged right projector. -This function merges two vertices in a clustered Hamiltonian graph `cl_h` to create a single merged vertex. +This function merges two vertices in a Potts Hamiltonian graph `potts_h` to create a single merged vertex. The merging process combines projectors and energy values associated with the original vertices based on the provided temperature parameter `β`. The merged energy values, left projector `pl`, and right projector `pr` are computed based on the interactions between the original vertices and their respective projectors. """ -function merge_vertices_cl_h( - cl_h::LabelledGraph{S,T}, +function merge_vertices_potts_h( + potts_h::LabelledGraph{S,T}, β::Real, node1::NTuple{3,Int64}, node2::NTuple{3,Int64}, @@ -348,18 +348,18 @@ function merge_vertices_cl_h( i1, j1, _ = node1 i2, j2, _ = node2 - p21l = projector(cl_h, (i1, j1, 2), (i2, j2, 1)) - p22l = projector(cl_h, (i1, j1, 2), (i2, j2, 2)) - p12l = projector(cl_h, (i1, j1, 1), (i2, j2, 2)) - p11l = projector(cl_h, (i1, j1, 1), (i2, j2, 1)) + p21l = projector(potts_h, (i1, j1, 2), (i2, j2, 1)) + p22l = projector(potts_h, (i1, j1, 2), (i2, j2, 2)) + p12l = projector(potts_h, (i1, j1, 1), (i2, j2, 2)) + p11l = projector(potts_h, (i1, j1, 1), (i2, j2, 1)) p1l, (p11l, p12l) = fuse_projectors((p11l, p12l)) p2l, (p21l, p22l) = fuse_projectors((p21l, p22l)) - p11r = projector(cl_h, (i2, j2, 1), (i1, j1, 1)) - p21r = projector(cl_h, (i2, j2, 1), (i1, j1, 2)) - p12r = projector(cl_h, (i2, j2, 2), (i1, j1, 1)) - p22r = projector(cl_h, (i2, j2, 2), (i1, j1, 2)) + p11r = projector(potts_h, (i2, j2, 1), (i1, j1, 1)) + p21r = projector(potts_h, (i2, j2, 1), (i1, j1, 2)) + p12r = projector(potts_h, (i2, j2, 2), (i1, j1, 1)) + p22r = projector(potts_h, (i2, j2, 2), (i1, j1, 2)) p1r, (p11r, p21r) = fuse_projectors((p11r, p21r)) p2r, (p12r, p22r) = fuse_projectors((p12r, p22r)) @@ -367,10 +367,10 @@ function merge_vertices_cl_h( pl = outer_projector(p1l, p2l) pr = outer_projector(p1r, p2r) - e11 = interaction_energy(cl_h, (i1, j1, 1), (i2, j2, 1)) - e12 = interaction_energy(cl_h, (i1, j1, 1), (i2, j2, 2)) - e21 = interaction_energy(cl_h, (i1, j1, 2), (i2, j2, 1)) - e22 = interaction_energy(cl_h, (i1, j1, 2), (i2, j2, 2)) + e11 = interaction_energy(potts_h, (i1, j1, 1), (i2, j2, 1)) + e12 = interaction_energy(potts_h, (i1, j1, 1), (i2, j2, 2)) + e21 = interaction_energy(potts_h, (i1, j1, 2), (i2, j2, 1)) + e22 = interaction_energy(potts_h, (i1, j1, 2), (i2, j2, 2)) e11 = e11[p11l, p11r] e21 = e21[p21l, p21r] @@ -383,52 +383,52 @@ end """ $(TYPEDSIGNATURES) -Get the local energy associated with a vertex in a clustered Hamiltonian. +Get the local energy associated with a vertex in a Potts Hamiltonian. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `v::NTuple{3, Int64}`: The coordinates of the vertex for which the local energy is requested. # Returns: - `local_energy::AbstractVector`: An abstract vector containing the local energy values associated with the specified vertex. -This function retrieves the local energy values associated with a given vertex `v` in a clustered Hamiltonian graph `cl_h`. +This function retrieves the local energy values associated with a given vertex `v` in a Potts Hamiltonian graph `potts_h`. If the vertex exists in the graph and has associated energy values, it returns those values; otherwise, it returns a vector of zeros. The local energy values are typically obtained from the spectrum associated with the vertex. """ -function local_energy(cl_h::LabelledGraph{S,T}, v::NTuple{3,Int64}) where {S,T} - has_vertex(cl_h, v) ? get_prop(cl_h, v, :spectrum).energies : zeros(1) +function local_energy(potts_h::LabelledGraph{S,T}, v::NTuple{3,Int64}) where {S,T} + has_vertex(potts_h, v) ? get_prop(potts_h, v, :spectrum).energies : zeros(1) end """ $(TYPEDSIGNATURES) -Get the interaction energy between two vertices in a clustered Hamiltonian. +Get the interaction energy between two vertices in a Potts Hamiltonian. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `v::NTuple{3, Int64}`: The coordinates of the first vertex. - `w::NTuple{3, Int64}`: The coordinates of the second vertex. # Returns: - `interaction_energy::AbstractMatrix`: An abstract matrix containing the interaction energy values between the specified vertices. -This function retrieves the interaction energy values between two vertices, `v` and `w`, in a clustered Hamiltonian graph `cl_h`. +This function retrieves the interaction energy values between two vertices, `v` and `w`, in a Potts Hamiltonian graph `potts_h`. If there is a directed edge from `w` to `v`, it returns the corresponding energy values; if there is a directed edge from `v` to `w`, it returns the transpose of the energy values; otherwise, it returns a matrix of zeros. The interaction energy values represent the energy associated with the interaction or connection between the two vertices. """ function interaction_energy( - cl_h::LabelledGraph{S,T}, + potts_h::LabelledGraph{S,T}, v::NTuple{3,Int64}, w::NTuple{3,Int64}, ) where {S,T} - if has_edge(cl_h, w, v) - get_prop(cl_h, w, v, :en)' - elseif has_edge(cl_h, v, w) - get_prop(cl_h, v, w, :en) + if has_edge(potts_h, w, v) + get_prop(potts_h, w, v, :en)' + elseif has_edge(potts_h, v, w) + get_prop(potts_h, v, w, :en) else zeros(1, 1) end @@ -437,10 +437,10 @@ end """ $(TYPEDSIGNATURES) -Get the projector associated with an edge between two vertices in a clustered Hamiltonian. +Get the projector associated with an edge between two vertices in a Potts Hamiltonian. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `v::NTuple{N, Int64}`: The coordinates of one of the two vertices connected by the edge. - `w::NTuple{N, Int64}`: The coordinates of the other vertex connected by the edge. @@ -448,26 +448,26 @@ Get the projector associated with an edge between two vertices in a clustered Ha - `p::AbstractVector`: An abstract vector representing the projector associated with the specified edge. This function retrieves the projector associated with an edge between two vertices, `v` and `w`, -in a clustered Hamiltonian graph `cl_h`. +in a Potts Hamiltonian graph `potts_h`. If there is a directed edge from `w` to `v`, it returns the index of right projector (`:ipr`); if there is a directed edge from `v` to `w`, it returns the index of left projector (`:ipl`). If no edge exists between the vertices, it returns a vector of ones. """ function projector( - cl_h::LabelledGraph{S,T}, + potts_h::LabelledGraph{S,T}, v::NTuple{N,Int64}, w::NTuple{N,Int64}, ) where {S,T,N} - if has_edge(cl_h, w, v) - idx_p = get_prop(cl_h, w, v, :ipr) - p = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_p, :CPU) - elseif has_edge(cl_h, v, w) - idx_p = get_prop(cl_h, v, w, :ipl) - p = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_p, :CPU) + if has_edge(potts_h, w, v) + idx_p = get_prop(potts_h, w, v, :ipr) + p = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_p, :CPU) + elseif has_edge(potts_h, v, w) + idx_p = get_prop(potts_h, v, w, :ipl) + p = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_p, :CPU) else p = ones( Int, - v ∈ vertices(cl_h) ? length(get_prop(cl_h, v, :spectrum).energies) : 1, + v ∈ vertices(potts_h) ? length(get_prop(potts_h, v, :spectrum).energies) : 1, ) end end diff --git a/src/clustered_hamiltonian.jl b/src/potts_hamiltonian.jl similarity index 57% rename from src/clustered_hamiltonian.jl rename to src/potts_hamiltonian.jl index f5c3f78..a70a9d9 100644 --- a/src/clustered_hamiltonian.jl +++ b/src/potts_hamiltonian.jl @@ -1,11 +1,11 @@ -export clustered_hamiltonian, +export potts_hamiltonian, rank_reveal, split_into_clusters, - decode_clustered_hamiltonian_state, + decode_potts_hamiltonian_state, energy, energy_2site, cluster_size, - truncate_clustered_hamiltonian, + truncate_potts_hamiltonian, exact_cond_prob, bond_energy, cluster_size @@ -13,21 +13,21 @@ export clustered_hamiltonian, """ $(TYPEDSIGNATURES) -Group spins into clusters based on an assignment rule, mapping clustered Hamiltonian coordinates to groups of spins in the Ising graph. -Dict(clustered Hamiltonian coordinates -> group of spins in Ising graph) +Group spins into clusters based on an assignment rule, mapping Potts Hamiltonian coordinates to groups of spins in the Ising graph. +Dict(Potts Hamiltonian coordinates -> group of spins in Ising graph) # Arguments: - `ig::LabelledGraph{G, L}`: The Ising graph represented as a labeled graph. -- `assignment_rule`: A mapping that assigns Ising graph vertices to clusters based on clustered Hamiltonian coordinates. +- `assignment_rule`: A mapping that assigns Ising graph vertices to clusters based on Potts Hamiltonian coordinates. # Returns: - `clusters::Dict{L, Vertex}`: A dictionary mapping cluster identifiers to representative vertices in the Ising graph. This function groups spins in the Ising graph into clusters based on an assignment rule. -The assignment rule defines how clustered Hamiltonian coordinates correspond to clusters of spins in the Ising graph. +The assignment rule defines how Potts Hamiltonian coordinates correspond to clusters of spins in the Ising graph. Each cluster is represented by a vertex from the Ising graph. -The `split_into_clusters` function is useful for organizing and analyzing spins in complex spin systems, particularly in the context of clustered Hamiltonian. +The `split_into_clusters` function is useful for organizing and analyzing spins in complex spin systems, particularly in the context of Potts Hamiltonian. """ function split_into_clusters(ig::LabelledGraph{G,L}, assignment_rule) where {G,L} @@ -41,32 +41,32 @@ end """ $(TYPEDSIGNATURES) -Create a clustered Hamiltonian. +Create a Potts Hamiltonian. -This function constructs a clustered Hamiltonian from an Ising graph by introducing a natural order in clustered Hamiltonian coordinates. +This function constructs a Potts Hamiltonian from an Ising graph by introducing a natural order in Potts Hamiltonian coordinates. # Arguments: - `ig::IsingGraph`: The Ising graph representing the spin system. - `num_states_cl::Int`: The number of states per cluster taken into account when calculating the spectrum. In every cluster the number of states is constant. -- `spectrum::Function`: A function for calculating the spectrum of the clustered Hamiltonian. It can be `full_spectrum` or `brute_force`. +- `spectrum::Function`: A function for calculating the spectrum of the Potts Hamiltonian. It can be `full_spectrum` or `brute_force`. - `cluster_assignment_rule::Dict{Int, L}`: A dictionary specifying the assignment rule that maps Ising graph vertices to clusters. It can be `super_square_lattice`, `pegasus_lattice` or `zephyr_lattice`. # Returns: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labelled graph. -The `clustered_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a clustered Hamiltonian by -introducing a natural order in clustered Hamiltonian coordinates. +The `potts_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a Potts Hamiltonian by +introducing a natural order in Potts Hamiltonian coordinates. It allows you to specify the number of states per cluster, a spectrum calculation function, and a cluster assignment rule, which maps Ising graph vertices to clusters. """ -function clustered_hamiltonian( +function potts_hamiltonian( ig::IsingGraph, num_states_cl::Int; spectrum::Function = full_spectrum, cluster_assignment_rule::Dict{Int,L}, # e.g. square lattice ) where {L} ns = Dict(i => num_states_cl for i ∈ Set(values(cluster_assignment_rule))) - clustered_hamiltonian( + potts_hamiltonian( ig, ns, spectrum = spectrum, @@ -77,42 +77,42 @@ end """ $(TYPEDSIGNATURES) -Create a clustered Hamiltonian. +Create a Potts Hamiltonian. -This function constructs a clustered Hamiltonian from an Ising graph by introducing a natural order in clustered Hamiltonian coordinates. +This function constructs a Potts Hamiltonian from an Ising graph by introducing a natural order in Potts Hamiltonian coordinates. # Arguments: - `ig::IsingGraph`: The Ising graph representing the spin system. - `num_states_cl::Dict{T, Int}`: A dictionary specifying the number of states per cluster for different clusters. Number of states are considered when calculating the spectrum. -- `spectrum::Function`: A function for calculating the spectrum of the clustered Hamiltonian. It can be `full_spectrum` or `brute_force`. +- `spectrum::Function`: A function for calculating the spectrum of the Potts Hamiltonian. It can be `full_spectrum` or `brute_force`. - `cluster_assignment_rule::Dict{Int, T}`: A dictionary specifying the assignment rule that maps Ising graph vertices to clusters. It can be `super_square_lattice`, `pegasus_lattice` or `zephyr_lattice`. # Returns: -- `cl_h::LabelledGraph{MetaDiGraph}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{MetaDiGraph}`: The Potts Hamiltonian represented as a labelled graph. -The `clustered_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a clustered Hamiltonian -by introducing a natural order in clustered Hamiltonian coordinates. It allows you to specify the number of +The `potts_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a Potts Hamiltonian +by introducing a natural order in Potts Hamiltonian coordinates. It allows you to specify the number of states per cluster which can vary for different clusters, a spectrum calculation function, and a cluster assignment rule, which maps Ising graph vertices to clusters. """ -function clustered_hamiltonian( +function potts_hamiltonian( ig::IsingGraph, num_states_cl::Dict{T,Int}; spectrum::Function = full_spectrum, cluster_assignment_rule::Dict{Int,T}, ) where {T} - cl_h = LabelledGraph{MetaDiGraph}(sort(unique(values(cluster_assignment_rule)))) + potts_h = LabelledGraph{MetaDiGraph}(sort(unique(values(cluster_assignment_rule)))) lp = PoolOfProjectors{Int}() for (v, cl) ∈ split_into_clusters(ig, cluster_assignment_rule) sp = spectrum(cl, num_states = get(num_states_cl, v, basis_size(cl))) - set_props!(cl_h, v, Dict(:cluster => cl, :spectrum => sp)) + set_props!(potts_h, v, Dict(:cluster => cl, :spectrum => sp)) end - for (i, v) ∈ enumerate(vertices(cl_h)), w ∈ vertices(cl_h)[i+1:end] - cl1, cl2 = get_prop(cl_h, v, :cluster), get_prop(cl_h, w, :cluster) + for (i, v) ∈ enumerate(vertices(potts_h)), w ∈ vertices(potts_h)[i+1:end] + cl1, cl2 = get_prop(potts_h, v, :cluster), get_prop(potts_h, w, :cluster) outer_edges, J = inter_cluster_edges(ig, cl1, cl2) if !isempty(outer_edges) @@ -122,8 +122,8 @@ function clustered_hamiltonian( ind2 = reshape(ind2, length(ind2)) JJ = J[ind1, ind2] - states_v = get_prop(cl_h, v, :spectrum).states - states_w = get_prop(cl_h, w, :spectrum).states + states_v = get_prop(potts_h, v, :spectrum).states + states_w = get_prop(potts_h, w, :spectrum).states pl, unique_states_v = rank_reveal([s[ind1] for s ∈ states_v], :PE) pr, unique_states_w = rank_reveal([s[ind2] for s ∈ states_w], :PE) @@ -131,47 +131,47 @@ function clustered_hamiltonian( ipl = add_projector!(lp, pl) ipr = add_projector!(lp, pr) - add_edge!(cl_h, v, w) + add_edge!(potts_h, v, w) set_props!( - cl_h, + potts_h, v, w, Dict(:outer_edges => outer_edges, :ipl => ipl, :en => en, :ipr => ipr), ) end end - set_props!(cl_h, Dict(:pool_of_projectors => lp)) - cl_h + set_props!(potts_h, Dict(:pool_of_projectors => lp)) + potts_h end """ $(TYPEDSIGNATURES) -Create a clustered Hamiltonian with optional cluster sizes. +Create a Potts Hamiltonian with optional cluster sizes. -This function constructs a clustered Hamiltonian from an Ising graph by introducing a natural order in clustered Hamiltonian coordinates. +This function constructs a Potts Hamiltonian from an Ising graph by introducing a natural order in Potts Hamiltonian coordinates. # Arguments: - `ig::IsingGraph`: The Ising graph representing the spin system. -- `spectrum::Function`: A function for calculating the spectrum of the clustered Hamiltonian. It can be `full_spectrum` or `brute_force`. Default is `full_spectrum`. +- `spectrum::Function`: A function for calculating the spectrum of the Potts Hamiltonian. It can be `full_spectrum` or `brute_force`. Default is `full_spectrum`. - `cluster_assignment_rule::Dict{Int, T}`: A dictionary specifying the assignment rule that maps Ising graph vertices to clusters. It can be `super_square_lattice`, `pegasus_lattice` or `zephyr_lattice`. # Returns: -- `cl_h::LabelledGraph{MetaDiGraph}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{MetaDiGraph}`: The Potts Hamiltonian represented as a labelled graph. -The `clustered_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a clustered Hamiltonian -by introducing a natural order in clustered Hamiltonian coordinates. +The `potts_hamiltonian` function takes an Ising graph (`ig`) as input and constructs a Potts Hamiltonian +by introducing a natural order in Potts Hamiltonian coordinates. You can optionally specify a spectrum calculation function and a cluster assignment rule, which maps Ising graph vertices to clusters. -This version of `clustered_hamiltonian` function does not truncate states in the cluster while calculating the spectrum. +This version of `potts_hamiltonian` function does not truncate states in the cluster while calculating the spectrum. If you want to specify custom cluster sizes, use the alternative version of this function by passing a `Dict{T, Int}` containing the number of states per cluster as `num_states_cl`. """ -function clustered_hamiltonian( +function potts_hamiltonian( ig::IsingGraph; spectrum::Function = full_spectrum, cluster_assignment_rule::Dict{Int,T}, ) where {T} - clustered_hamiltonian( + potts_hamiltonian( ig, Dict{T,Int}(), spectrum = spectrum, @@ -213,29 +213,29 @@ $(TYPEDSIGNATURES) TODO: check the order consistency over external packages. -Decode a clustered Hamiltonian state into Ising graph spin values. +Decode a Potts Hamiltonian state into Ising graph spin values. -This function decodes a state from a clustered Hamiltonian into Ising graph spin values and +This function decodes a state from a Potts Hamiltonian into Ising graph spin values and returns a dictionary mapping each Ising graph vertex to its corresponding spin value. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. -- `state::Vector{Int}`: The state to be decoded, represented as an array of state indices for each vertex in the clustered Hamiltonian. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. +- `state::Vector{Int}`: The state to be decoded, represented as an array of state indices for each vertex in the Potts Hamiltonian. # Returns: - `spin_values::Dict{Int, Int}`: A dictionary mapping each Ising graph vertex to its corresponding spin value. -This function assumes that the state has the same order as the vertices in the clustered Hamiltonian. -It decodes the state consistently based on the cluster assignments and spectra of the clustered Hamiltonian. +This function assumes that the state has the same order as the vertices in the Potts Hamiltonian. +It decodes the state consistently based on the cluster assignments and spectra of the Potts Hamiltonian. """ -function decode_clustered_hamiltonian_state( - cl_h::LabelledGraph{S,T}, +function decode_potts_hamiltonian_state( + potts_h::LabelledGraph{S,T}, state::Vector{Int}, ) where {S,T} ret = Dict{Int,Int}() - for (i, vert) ∈ zip(state, vertices(cl_h)) - spins = get_prop(cl_h, vert, :cluster).labels - states = get_prop(cl_h, vert, :spectrum).states + for (i, vert) ∈ zip(state, vertices(potts_h)) + spins = get_prop(potts_h, vert, :cluster).labels + states = get_prop(potts_h, vert, :spectrum).states if length(states) > 0 curr_state = states[i] merge!(ret, Dict(k => v for (k, v) ∈ zip(spins, curr_state))) @@ -247,47 +247,47 @@ end """ $(TYPEDSIGNATURES) -Calculate the energy of a clustered Hamiltonian state. +Calculate the energy of a Potts Hamiltonian state. -This function calculates the energy of a given state in a clustered Hamiltonian. +This function calculates the energy of a given state in a Potts Hamiltonian. The state is represented as a dictionary mapping each Ising graph vertex to its corresponding spin value. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `σ::Dict{T, Int}`: A dictionary mapping Ising graph vertices to their spin values. # Returns: -- `en_cl_h::Float64`: The energy of the state in the clustered Hamiltonian. +- `en_potts_h::Float64`: The energy of the state in the Potts Hamiltonian. This function computes the energy by summing the energies associated with individual clusters and the interaction energies between clusters. -It takes into account the cluster spectra and projectors stored in the clustered Hamiltonian. +It takes into account the cluster spectra and projectors stored in the Potts Hamiltonian. """ -function energy(cl_h::LabelledGraph{S,T}, σ::Dict{T,Int}) where {S,T} - en_cl_h = 0.0 - for v ∈ vertices(cl_h) - en_cl_h += get_prop(cl_h, v, :spectrum).energies[σ[v]] +function energy(potts_h::LabelledGraph{S,T}, σ::Dict{T,Int}) where {S,T} + en_potts_h = 0.0 + for v ∈ vertices(potts_h) + en_potts_h += get_prop(potts_h, v, :spectrum).energies[σ[v]] end - for edge ∈ edges(cl_h) - idx_pl = get_prop(cl_h, edge, :ipl) - pl = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pl, :CPU) - idx_pr = get_prop(cl_h, edge, :ipr) - pr = get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pr, :CPU) - en = get_prop(cl_h, edge, :en) - en_cl_h += en[pl[σ[src(edge)]], pr[σ[dst(edge)]]] + for edge ∈ edges(potts_h) + idx_pl = get_prop(potts_h, edge, :ipl) + pl = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pl, :CPU) + idx_pr = get_prop(potts_h, edge, :ipr) + pr = get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pr, :CPU) + en = get_prop(potts_h, edge, :en) + en_potts_h += en[pl[σ[src(edge)]], pr[σ[dst(edge)]]] end - en_cl_h + en_potts_h end """ $(TYPEDSIGNATURES) -Calculate the interaction energy between two nodes in a clustered Hamiltonian. +Calculate the interaction energy between two nodes in a Potts Hamiltonian. -This function computes the interaction energy between two specified nodes in a clustered Hamiltonian, represented as a labeled graph. +This function computes the interaction energy between two specified nodes in a Potts Hamiltonian, represented as a labeled graph. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `i::Int`: The index of the first site. - `j::Int`: The index of the second site. @@ -298,21 +298,21 @@ The function checks if there is an interaction edge between the two sites (i, j) If such edges exist, it retrieves the interaction energy matrix, projectors, and calculates the interaction energy. If no interaction edge is found, it returns a zero matrix. """ -function energy_2site(cl_h::LabelledGraph{S,T}, i::Int, j::Int) where {S,T} +function energy_2site(potts_h::LabelledGraph{S,T}, i::Int, j::Int) where {S,T} # matrix of interaction energies between two nodes - if has_edge(cl_h, (i, j, 1), (i, j, 2)) - en12 = copy(get_prop(cl_h, (i, j, 1), (i, j, 2), :en)) - idx_pl = get_prop(cl_h, (i, j, 1), (i, j, 2), :ipl) - pl = copy(get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pl, :CPU)) - idx_pr = get_prop(cl_h, (i, j, 1), (i, j, 2), :ipr) - pr = copy(get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pr, :CPU)) + if has_edge(potts_h, (i, j, 1), (i, j, 2)) + en12 = copy(get_prop(potts_h, (i, j, 1), (i, j, 2), :en)) + idx_pl = get_prop(potts_h, (i, j, 1), (i, j, 2), :ipl) + pl = copy(get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pl, :CPU)) + idx_pr = get_prop(potts_h, (i, j, 1), (i, j, 2), :ipr) + pr = copy(get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pr, :CPU)) int_eng = en12[pl, pr] - elseif has_edge(cl_h, (i, j, 2), (i, j, 1)) - en21 = copy(get_prop(cl_h, (i, j, 2), (i, j, 1), :en)) - idx_pl = get_prop(cl_h, (i, j, 2), (i, j, 1), :ipl) - pl = copy(get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pl, :CPU)) - idx_pr = get_prop(cl_h, (i, j, 2), (i, j, 1), :ipr) - pr = copy(get_projector!(get_prop(cl_h, :pool_of_projectors), idx_pr, :CPU)) + elseif has_edge(potts_h, (i, j, 2), (i, j, 1)) + en21 = copy(get_prop(potts_h, (i, j, 2), (i, j, 1), :en)) + idx_pl = get_prop(potts_h, (i, j, 2), (i, j, 1), :ipl) + pl = copy(get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pl, :CPU)) + idx_pr = get_prop(potts_h, (i, j, 2), (i, j, 1), :ipr) + pr = copy(get_projector!(get_prop(potts_h, :pool_of_projectors), idx_pr, :CPU)) int_eng = en21[pl, pr]' else int_eng = zeros(1, 1) @@ -323,14 +323,14 @@ end """ $(TYPEDSIGNATURES) -Calculate the bond energy between two clusters in a clustered Hamiltonian. +Calculate the bond energy between two clusters in a Potts Hamiltonian. -This function computes the bond energy between two specified clusters (cluster nodes) in a clustered Hamiltonian, represented as a labeled graph. +This function computes the bond energy between two specified clusters (cluster nodes) in a Potts Hamiltonian, represented as a labeled graph. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. -- `cl_h_u::NTuple{N, Int64}`: The coordinates of the first cluster. -- `cl_h_v::NTuple{N, Int64}`: The coordinates of the second cluster. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. +- `potts_h_u::NTuple{N, Int64}`: The coordinates of the first cluster. +- `potts_h_v::NTuple{N, Int64}`: The coordinates of the second cluster. - `σ::Int`: Index for which the bond energy is calculated. # Returns: @@ -341,35 +341,35 @@ If such edges exist, it retrieves the bond energy matrix and projectors and calc If no bond edge is found, it returns a zero vector. """ function bond_energy( - cl_h::LabelledGraph{S,T}, - cl_h_u::NTuple{N,Int64}, - cl_h_v::NTuple{N,Int64}, + potts_h::LabelledGraph{S,T}, + potts_h_u::NTuple{N,Int64}, + potts_h_v::NTuple{N,Int64}, σ::Int, ) where {S,T,N} - if has_edge(cl_h, cl_h_u, cl_h_v) - ipu, en, ipv = get_prop.(Ref(cl_h), Ref(cl_h_u), Ref(cl_h_v), (:ipl, :en, :ipr)) - pu = get_projector!(get_prop(cl_h, :pool_of_projectors), ipu, :CPU) - pv = get_projector!(get_prop(cl_h, :pool_of_projectors), ipv, :CPU) + if has_edge(potts_h, potts_h_u, potts_h_v) + ipu, en, ipv = get_prop.(Ref(potts_h), Ref(potts_h_u), Ref(potts_h_v), (:ipl, :en, :ipr)) + pu = get_projector!(get_prop(potts_h, :pool_of_projectors), ipu, :CPU) + pv = get_projector!(get_prop(potts_h, :pool_of_projectors), ipv, :CPU) @inbounds energies = en[pu, pv[σ]] - elseif has_edge(cl_h, cl_h_v, cl_h_u) - ipv, en, ipu = get_prop.(Ref(cl_h), Ref(cl_h_v), Ref(cl_h_u), (:ipl, :en, :ipr)) - pu = get_projector!(get_prop(cl_h, :pool_of_projectors), ipu, :CPU) - pv = get_projector!(get_prop(cl_h, :pool_of_projectors), ipv, :CPU) + elseif has_edge(potts_h, potts_h_v, potts_h_u) + ipv, en, ipu = get_prop.(Ref(potts_h), Ref(potts_h_v), Ref(potts_h_u), (:ipl, :en, :ipr)) + pu = get_projector!(get_prop(potts_h, :pool_of_projectors), ipu, :CPU) + pv = get_projector!(get_prop(potts_h, :pool_of_projectors), ipv, :CPU) @inbounds energies = en[pv[σ], pu] else - energies = zeros(cluster_size(cl_h, cl_h_u)) + energies = zeros(cluster_size(potts_h, potts_h_u)) end end """ $(TYPEDSIGNATURES) -Get the size of a cluster in a clustered Hamiltonian. +Get the size of a cluster in a Potts Hamiltonian. -This function returns the size (number of states) of a cluster in a clustered Hamiltonian, represented as a labeled graph. +This function returns the size (number of states) of a cluster in a Potts Hamiltonian, represented as a labeled graph. # Arguments: -- `clustered_hamiltonian::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_hamiltonian::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `vertex::T`: The vertex (cluster) for which the size is to be determined. # Returns: @@ -377,39 +377,39 @@ This function returns the size (number of states) of a cluster in a clustered Ha The function retrieves the spectrum associated with the specified cluster and returns the length of the energy vector in that spectrum. """ -function cluster_size(clustered_hamiltonian::LabelledGraph{S,T}, vertex::T) where {S,T} - length(get_prop(clustered_hamiltonian, vertex, :spectrum).energies) +function cluster_size(potts_hamiltonian::LabelledGraph{S,T}, vertex::T) where {S,T} + length(get_prop(potts_hamiltonian, vertex, :spectrum).energies) end """ $(TYPEDSIGNATURES) -Calculate the exact conditional probability of a target state in a clustered Hamiltonian. +Calculate the exact conditional probability of a target state in a Potts Hamiltonian. -This function computes the exact conditional probability of a specified target state in a clustered Hamiltonian, represented as a labelled graph. +This function computes the exact conditional probability of a specified target state in a Potts Hamiltonian, represented as a labelled graph. # Arguments: -- `clustered_hamiltonian::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_hamiltonian::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `beta`: The inverse temperature parameter. - `target_state::Dict`: A dictionary specifying the target state as a mapping of cluster vertices to Ising spin values. # Returns: - `prob::Float64`: The exact conditional probability of the target state. -The function generates all possible states for the clusters in the clustered Hamiltonian, +The function generates all possible states for the clusters in the Potts Hamiltonian, calculates their energies, and computes the probability distribution based on the given inverse temperature parameter. It then calculates the conditional probability of the specified target state by summing the probabilities of states that match the target state. """ function exact_cond_prob( - clustered_hamiltonian::LabelledGraph{S,T}, + potts_hamiltonian::LabelledGraph{S,T}, beta, target_state::Dict, ) where {S,T} # TODO: Not going to work without PoolOfProjectors - ver = vertices(clustered_hamiltonian) - rank = cluster_size.(Ref(clustered_hamiltonian), ver) + ver = vertices(potts_hamiltonian) + rank = cluster_size.(Ref(potts_hamiltonian), ver) states = [Dict(ver .=> σ) for σ ∈ Iterators.product([1:r for r ∈ rank]...)] - energies = SpinGlassNetworks.energy.(Ref(clustered_hamiltonian), states) + energies = SpinGlassNetworks.energy.(Ref(potts_hamiltonian), states) prob = exp.(-beta .* energies) prob ./= sum(prob) sum(prob[findall([all(s[k] == v for (k, v) ∈ target_state) for s ∈ states])]) @@ -418,48 +418,48 @@ end """ $(TYPEDSIGNATURES) -Truncate a clustered Hamiltonian based on specified states. +Truncate a Potts Hamiltonian based on specified states. -This function truncates a given clustered Hamiltonian by selecting a subset of states for each cluster based on the provided `states` dictionary. +This function truncates a given Potts Hamiltonian by selecting a subset of states for each cluster based on the provided `states` dictionary. The resulting truncated Hamiltonian contains only the selected states for each cluster. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `states::Dict`: A dictionary specifying the states to be retained for each cluster. # Returns: -- `new_cl_h::LabelledGraph{MetaDiGraph}`: The truncated clustered Hamiltonian with reduced states. +- `new_potts_h::LabelledGraph{MetaDiGraph}`: The truncated Potts Hamiltonian with reduced states. -The function creates a new clustered Hamiltonian `new_cl_h` with the same structure as the input `cl_h`. -It then updates the spectrum of each cluster in `new_cl_h` by selecting the specified states from the original spectrum. +The function creates a new Potts Hamiltonian `new_potts_h` with the same structure as the input `potts_h`. +It then updates the spectrum of each cluster in `new_potts_h` by selecting the specified states from the original spectrum. Additionally, it updates the interactions and projectors between clusters based on the retained states. -The resulting `new_cl_h` represents a truncated version of the original Hamiltonian. +The resulting `new_potts_h` represents a truncated version of the original Hamiltonian. """ -function truncate_clustered_hamiltonian(cl_h::LabelledGraph{S,T}, states::Dict) where {S,T} +function truncate_potts_hamiltonian(potts_h::LabelledGraph{S,T}, states::Dict) where {S,T} - new_cl_h = LabelledGraph{MetaDiGraph}(vertices(cl_h)) + new_potts_h = LabelledGraph{MetaDiGraph}(vertices(potts_h)) new_lp = PoolOfProjectors{Int}() - for v ∈ vertices(new_cl_h) - cl = get_prop(cl_h, v, :cluster) - sp = get_prop(cl_h, v, :spectrum) + for v ∈ vertices(new_potts_h) + cl = get_prop(potts_h, v, :cluster) + sp = get_prop(potts_h, v, :spectrum) if sp.states == Vector{Int64}[] sp = Spectrum(sp.energies[states[v]], sp.states, [1]) else sp = Spectrum(sp.energies[states[v]], sp.states[states[v]]) end - set_props!(new_cl_h, v, Dict(:cluster => cl, :spectrum => sp)) + set_props!(new_potts_h, v, Dict(:cluster => cl, :spectrum => sp)) end - for e ∈ edges(cl_h) + for e ∈ edges(potts_h) v, w = src(e), dst(e) - add_edge!(new_cl_h, v, w) - outer_edges = get_prop(cl_h, v, w, :outer_edges) - ipl = get_prop(cl_h, v, w, :ipl) - pl = get_projector!(get_prop(cl_h, :pool_of_projectors), ipl, :CPU) - ipr = get_prop(cl_h, v, w, :ipr) - pr = get_projector!(get_prop(cl_h, :pool_of_projectors), ipr, :CPU) - en = get_prop(cl_h, v, w, :en) + add_edge!(new_potts_h, v, w) + outer_edges = get_prop(potts_h, v, w, :outer_edges) + ipl = get_prop(potts_h, v, w, :ipl) + pl = get_projector!(get_prop(potts_h, :pool_of_projectors), ipl, :CPU) + ipr = get_prop(potts_h, v, w, :ipr) + pr = get_projector!(get_prop(potts_h, :pool_of_projectors), ipr, :CPU) + en = get_prop(potts_h, v, w, :en) pl = pl[states[v]] pr = pr[states[w]] pl_transition, pl_unique = rank_reveal(pl, :PE) @@ -468,18 +468,18 @@ function truncate_clustered_hamiltonian(cl_h::LabelledGraph{S,T}, states::Dict) ipl = add_projector!(new_lp, pl_transition) ipr = add_projector!(new_lp, pr_transition) set_props!( - new_cl_h, + new_potts_h, v, w, Dict(:outer_edges => outer_edges, :ipl => ipl, :en => en, :ipr => ipr), ) end - set_props!(new_cl_h, Dict(:pool_of_projectors => new_lp)) + set_props!(new_potts_h, Dict(:pool_of_projectors => new_lp)) - new_cl_h + new_potts_h end -function clustered_hamiltonian( +function potts_hamiltonian( fname::String, Nx::Union{Integer,Nothing} = nothing, Ny::Union{Integer,Nothing} = nothing, @@ -493,25 +493,25 @@ function clustered_hamiltonian( X, Y = loaded_rmf["Nx"], loaded_rmf["Ny"] clusters = super_square_lattice((X, Y, 1)) - cl_h = LabelledGraph{MetaDiGraph}(sort(collect(values(clusters)))) + potts_h = LabelledGraph{MetaDiGraph}(sort(collect(values(clusters)))) lp = PoolOfProjectors{Int}() - for v ∈ cl_h.labels - set_props!(cl_h, v, Dict(:cluster => v)) + for v ∈ potts_h.labels + set_props!(potts_h, v, Dict(:cluster => v)) end for (index, value) in factors if length(index) == 2 y, x = index Eng = functions[value]' sp = Spectrum(collect(Eng), Vector{Vector{Int}}[], zeros(Int, N[y+1, x+1])) - set_props!(cl_h, (x + 1, y + 1), Dict(:spectrum => sp)) + set_props!(potts_h, (x + 1, y + 1), Dict(:spectrum => sp)) elseif length(index) == 4 y1, x1, y2, x2 = index - add_edge!(cl_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1)) + add_edge!(potts_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1)) Eng = functions[value] ipl = add_projector!(lp, collect(1:N[y1+1, x1+1])) ipr = add_projector!(lp, collect(1:N[y2+1, x2+1])) set_props!( - cl_h, + potts_h, (x1 + 1, y1 + 1), (x2 + 1, y2 + 1), Dict( @@ -530,6 +530,6 @@ function clustered_hamiltonian( end end - set_props!(cl_h, Dict(:pool_of_projectors => lp, :Nx => X, :Ny => Y)) - cl_h + set_props!(potts_h, Dict(:pool_of_projectors => lp, :Nx => X, :Ny => Y)) + potts_h end diff --git a/src/truncate.jl b/src/truncate.jl index 5870c97..df29241 100644 --- a/src/truncate.jl +++ b/src/truncate.jl @@ -1,78 +1,78 @@ -export truncate_clustered_hamiltonian_2site_energy, - truncate_clustered_hamiltonian_1site_BP, - truncate_clustered_hamiltonian_2site_BP, +export truncate_potts_hamiltonian_2site_energy, + truncate_potts_hamiltonian_1site_BP, + truncate_potts_hamiltonian_2site_BP, select_numstate_best """ $(TYPEDSIGNATURES) -Truncates a clustered Hamiltonian using belief propagation (BP) for a single site cluster. +Truncates a Potts Hamiltonian using belief propagation (BP) for a single site cluster. -This function employs belief propagation (BP) to approximate the most probable states and energies for a clustered Hamiltonian -associated with a single-site cluster. It then truncates the clustered Hamiltonian based on the most probable states. +This function employs belief propagation (BP) to approximate the most probable states and energies for a Potts Hamiltonian +associated with a single-site cluster. It then truncates the Potts Hamiltonian based on the most probable states. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `num_states::Int`: The maximum number of most probable states to keep. - `beta::Real (optional)`: The inverse temperature parameter for the BP algorithm. Default is 1.0. - `tol::Real (optional)`: The tolerance value for convergence in BP. Default is 1e-10. - `iter::Int (optional)`: The maximum number of BP iterations. Default is 1. # Returns: -- `LabelledGraph{S, T}`: A truncated clustered Hamiltonian. +- `LabelledGraph{S, T}`: A truncated Potts Hamiltonian. """ -function truncate_clustered_hamiltonian_1site_BP( - cl_h::LabelledGraph{S,T}, +function truncate_potts_hamiltonian_1site_BP( + potts_h::LabelledGraph{S,T}, num_states::Int; beta = 1.0, tol = 1e-10, iter = 1, ) where {S,T} states = Dict() - beliefs = belief_propagation(cl_h, beta; tol = tol, iter = iter) - for node in vertices(cl_h) + beliefs = belief_propagation(potts_h, beta; tol = tol, iter = iter) + for node in vertices(potts_h) indices = partialsortperm(beliefs[node], 1:min(num_states, length(beliefs[node]))) push!(states, node => indices) end - truncate_clustered_hamiltonian(cl_h, states) + truncate_potts_hamiltonian(potts_h, states) end """ $(TYPEDSIGNATURES) -Truncate a clustered Hamiltonian based on 2-site energy states. +Truncate a Potts Hamiltonian based on 2-site energy states. -This function truncates a clustered Hamiltonian by considering 2-site energy states and selecting the most probable states +This function truncates a Potts Hamiltonian by considering 2-site energy states and selecting the most probable states to keep. It computes the energies for all 2-site combinations and selects the states that maximize the probability. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labeled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labeled graph. - `num_states::Int`: The maximum number of most probable states to keep. # Returns: -- `LabelledGraph{S, T}`: A truncated clustered Hamiltonian. +- `LabelledGraph{S, T}`: A truncated Potts Hamiltonian. """ -function truncate_clustered_hamiltonian_2site_energy( - cl_h::LabelledGraph{S,T}, +function truncate_potts_hamiltonian_2site_energy( + potts_h::LabelledGraph{S,T}, num_states::Int, ) where {S,T} # TODO: name to be clean to make it consistent with square2 and squarestar2 states = Dict() - for node in vertices(cl_h) + for node in vertices(potts_h) if node in keys(states) continue end i, j, _ = node - E1 = copy(get_prop(cl_h, (i, j, 1), :spectrum).energies) - E2 = copy(get_prop(cl_h, (i, j, 2), :spectrum).energies) - E = energy_2site(cl_h, i, j) .+ reshape(E1, :, 1) .+ reshape(E2, 1, :) + E1 = copy(get_prop(potts_h, (i, j, 1), :spectrum).energies) + E2 = copy(get_prop(potts_h, (i, j, 2), :spectrum).energies) + E = energy_2site(potts_h, i, j) .+ reshape(E1, :, 1) .+ reshape(E2, 1, :) sx, sy = size(E) E = reshape(E, sx * sy) ind1, ind2 = select_numstate_best(E, sx, num_states) push!(states, (i, j, 1) => ind1) push!(states, (i, j, 2) => ind2) end - truncate_clustered_hamiltonian(cl_h, states) + truncate_potts_hamiltonian(potts_h, states) end function load_file(filename) @@ -90,22 +90,22 @@ end """ $(TYPEDSIGNATURES) -Truncate a clustered Hamiltonian based on 2-site belief propagation states. +Truncate a Potts Hamiltonian based on 2-site belief propagation states. -This function truncates a clustered Hamiltonian by considering 2-site belief propagation states and selecting the most probable states +This function truncates a Potts Hamiltonian by considering 2-site belief propagation states and selecting the most probable states to keep. It computes the beliefs for all 2-site combinations and selects the states that maximize the probability. # Arguments: -- `cl_h::LabelledGraph{S, T}`: The clustered Hamiltonian represented as a labelled graph. +- `potts_h::LabelledGraph{S, T}`: The Potts Hamiltonian represented as a labelled graph. - `beliefs::Dict`: A dictionary containing belief values for 2-site interactions. - `num_states::Int`: The maximum number of most probable states to keep. - `beta::Real (optional)`: The inverse temperature parameter (default is 1.0). # Returns: -- `LabelledGraph{S, T}`: A truncated clustered Hamiltonian. +- `LabelledGraph{S, T}`: A truncated Potts Hamiltonian. """ -function truncate_clustered_hamiltonian_2site_BP( - cl_h::LabelledGraph{S,T}, +function truncate_potts_hamiltonian_2site_BP( + potts_h::LabelledGraph{S,T}, beliefs::Dict, num_states::Int, result_folder::String = "results_folder", @@ -115,14 +115,14 @@ function truncate_clustered_hamiltonian_2site_BP( states = Dict() saved_states = load_file(joinpath(result_folder, "$(inst).jld2")) - for node in vertices(cl_h) + for node in vertices(potts_h) if node in keys(states) continue end i, j, _ = node sx = - has_vertex(cl_h, (i, j, 1)) ? - length(get_prop(cl_h, (i, j, 1), :spectrum).energies) : 1 + has_vertex(potts_h, (i, j, 1)) ? + length(get_prop(potts_h, (i, j, 1), :spectrum).energies) : 1 E = beliefs[(i, j)] ind1, ind2 = select_numstate_best(E, sx, num_states) push!(states, (i, j, 1) => ind1) @@ -130,7 +130,7 @@ function truncate_clustered_hamiltonian_2site_BP( end path = joinpath(result_folder, "$(inst).jld2") save_object(string(path), states) - truncate_clustered_hamiltonian(cl_h, states) + truncate_potts_hamiltonian(potts_h, states) end """ @@ -138,17 +138,17 @@ $(TYPEDSIGNATURES) Select a specified number of best states based on energy. -This function selects a specified number of best states from a list of energies based on energy values in two nodes of clustered hamiltonian. +This function selects a specified number of best states from a list of energies based on energy values in two nodes of Potts Hamiltonian. It fine-tunes the selection to ensure that the resulting states have the expected number. # Arguments: - `E::Vector{Real}`: A vector of energy values. -- `sx::Int`: The size of the clustered Hamiltonian for one of the nodes. +- `sx::Int`: The size of the Potts Hamiltonian for one of the nodes. - `num_states::Int`: The desired number of states to select. # Returns: - `Tuple{Vector{Int}, Vector{Int}}`: A tuple containing two vectors of indices, `ind1` and `ind2`, -which represent the selected states for two nodes of a clustered Hamiltonian. +which represent the selected states for two nodes of a Potts Hamiltonian. """ function select_numstate_best(E, sx, num_states) low, high = 1, min(num_states, length(E)) @@ -171,8 +171,8 @@ function select_numstate_best(E, sx, num_states) end end -function truncate_clustered_hamiltonian( - cl_h, +function truncate_potts_hamiltonian( + potts_h, β, cs, result_folder, @@ -183,10 +183,10 @@ function truncate_clustered_hamiltonian( states = Dict() saved_states = load_file(joinpath(result_folder, "$(inst).jld2")) if isnothing(saved_states) - new_cl_h = clustered_hamiltonian_2site(cl_h, β) - beliefs = belief_propagation(new_cl_h, β; tol = 1e-6, iter = iter) - cl_h = truncate_clustered_hamiltonian_2site_BP( - cl_h, + new_potts_h = potts_hamiltonian_2site(potts_h, β) + beliefs = belief_propagation(new_potts_h, β; tol = 1e-6, iter = iter) + potts_h = truncate_potts_hamiltonian_2site_BP( + potts_h, beliefs, cs, result_folder, @@ -195,7 +195,7 @@ function truncate_clustered_hamiltonian( ) else states = saved_states - cl_h = truncate_clustered_hamiltonian(cl_h, states) + potts_h = truncate_potts_hamiltonian(potts_h, states) end - cl_h + potts_h end diff --git a/test/bp_1site.jl b/test/bp_1site.jl index c7f18d0..1fa3be7 100644 --- a/test/bp_1site.jl +++ b/test/bp_1site.jl @@ -6,7 +6,7 @@ Instance below looks like this: 3 -- 4 """ -function create_larger_example_clustered_hamiltonian_tree_basic() +function create_larger_example_potts_hamiltonian_tree_basic() instance = Dict( (1, 1) => -0.50, (2, 2) => 0.25, @@ -21,14 +21,14 @@ function create_larger_example_clustered_hamiltonian_tree_basic() assignment_rule = Dict(1 => (1, 1, 1), 2 => (1, 2, 1), 3 => (2, 1, 1), 4 => (2, 2, 2)) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, Dict{NTuple{3,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule, ) - ig, cl_h + ig, potts_h end """ @@ -40,7 +40,7 @@ Instance below looks like this: | 7 -- 8 -- 9 """ -function create_larger_example_clustered_hamiltonian_tree() +function create_larger_example_potts_hamiltonian_tree() instance = Dict( (1, 1) => 0.53, (2, 2) => -0.25, @@ -74,14 +74,14 @@ function create_larger_example_clustered_hamiltonian_tree() 9 => (3, 3, 1), ) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, Dict{NTuple{3,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule, ) - ig, cl_h + ig, potts_h end """ @@ -92,7 +92,7 @@ Instance below looks like this: 7 8 """ -function create_larger_example_clustered_hamiltonian_tree_pathological() +function create_larger_example_potts_hamiltonian_tree_pathological() instance = Dict( (1, 1) => 0.52, (2, 2) => 0.25, @@ -125,31 +125,31 @@ function create_larger_example_clustered_hamiltonian_tree_pathological() 8 => (2, 2), ) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, Dict{NTuple{2,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule, ) - ig, cl_h + ig, potts_h end @testset "Belief propagation" begin - for (ig, cl_h) ∈ [ - create_larger_example_clustered_hamiltonian_tree_basic(), - create_larger_example_clustered_hamiltonian_tree(), - create_larger_example_clustered_hamiltonian_tree_pathological(), + for (ig, potts_h) ∈ [ + create_larger_example_potts_hamiltonian_tree_basic(), + create_larger_example_potts_hamiltonian_tree(), + create_larger_example_potts_hamiltonian_tree_pathological(), ] for beta ∈ [0.5, 1] iter = 16 - beliefs = belief_propagation(cl_h, beta; iter = iter) + beliefs = belief_propagation(potts_h, beta; iter = iter) exact_marginal = Dict() for k in keys(beliefs) push!( exact_marginal, k => [ - exact_cond_prob(cl_h, beta, Dict(k => a)) for + exact_cond_prob(potts_h, beta, Dict(k => a)) for a = 1:length(beliefs[k]) ], ) diff --git a/test/bp_2site.jl b/test/bp_2site.jl index 5878444..d0111b1 100644 --- a/test/bp_2site.jl +++ b/test/bp_2site.jl @@ -6,7 +6,7 @@ Instance below looks like this: 56 -- 78 """ -function create_larger_example_clustered_hamiltonian_tree_2site() +function create_larger_example_potts_hamiltonian_tree_2site() instance = Dict( (1, 1) => 0.50, (2, 2) => -0.25, @@ -49,21 +49,21 @@ function create_larger_example_clustered_hamiltonian_tree_2site() 8 => (2, 2, 2), ) - cl_h1 = clustered_hamiltonian( + potts_h1 = potts_hamiltonian( ig, Dict{NTuple{2,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule1, ) - cl_h2 = clustered_hamiltonian( + potts_h2 = potts_hamiltonian( ig, Dict{NTuple{3,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule2, ) - ig, cl_h1, cl_h2 + ig, potts_h1, potts_h2 end """ @@ -76,7 +76,7 @@ Instance below looks like this: 10 """ -function create_larger_example_clustered_hamiltonian_tree_2site_pathological() +function create_larger_example_potts_hamiltonian_tree_2site_pathological() instance = Dict( (1, 1) => -0.50, (2, 2) => 0.25, @@ -129,45 +129,45 @@ function create_larger_example_clustered_hamiltonian_tree_2site_pathological() 10 => (3, 2, 2), ) - cl_h1 = clustered_hamiltonian( + potts_h1 = potts_hamiltonian( ig, Dict{NTuple{2,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule1, ) - cl_h2 = clustered_hamiltonian( + potts_h2 = potts_hamiltonian( ig, Dict{NTuple{3,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule2, ) - ig, cl_h1, cl_h2 + ig, potts_h1, potts_h2 end @testset "Belief propagation 2site" begin - for (ig, cl_h1, cl_h2) ∈ [ - create_larger_example_clustered_hamiltonian_tree_2site(), - create_larger_example_clustered_hamiltonian_tree_2site_pathological(), + for (ig, potts_h1, potts_h2) ∈ [ + create_larger_example_potts_hamiltonian_tree_2site(), + create_larger_example_potts_hamiltonian_tree_2site_pathological(), ] for beta ∈ [0.6, 1.1] tol = 1e-12 iter = 16 num_states = 10 - new_cl_h1 = clustered_hamiltonian_2site(cl_h2, beta) + new_potts_h1 = potts_hamiltonian_2site(potts_h2, beta) - @test vertices(new_cl_h1) == vertices(cl_h1) - @test edges(new_cl_h1) == edges(cl_h1) - for e ∈ vertices(new_cl_h1) - @test get_prop(new_cl_h1, e, :spectrum).energies ≈ - get_prop(cl_h1, e, :spectrum).energies + @test vertices(new_potts_h1) == vertices(potts_h1) + @test edges(new_potts_h1) == edges(potts_h1) + for e ∈ vertices(new_potts_h1) + @test get_prop(new_potts_h1, e, :spectrum).energies ≈ + get_prop(potts_h1, e, :spectrum).energies end - for e ∈ edges(new_cl_h1) - E = get_prop(new_cl_h1, src(e), dst(e), :en) + for e ∈ edges(new_potts_h1) + E = get_prop(new_potts_h1, src(e), dst(e), :en) # @cast E[(l1, l2), (r1, r2)] := # E.e11[l1, r1] + E.e21[l2, r1] + E.e12[l1, r2] + E.e22[l2, r2] a11 = reshape(CuArray(E.e11), size(E.e11, 1), :, size(E.e11, 2)) @@ -176,30 +176,30 @@ end a22 = reshape(CuArray(E.e22), 1, size(E.e22, 1), 1, size(E.e22, 2)) E = @__dot__(a11 + a21 + a12 + a22) E = reshape(E, size(E, 1) * size(E, 2), size(E, 3) * size(E, 4)) - @test Array(E) == get_prop(cl_h1, src(e), dst(e), :en) + @test Array(E) == get_prop(potts_h1, src(e), dst(e), :en) end - for e ∈ edges(new_cl_h1) - il1 = get_prop(new_cl_h1, src(e), dst(e), :ipl) - il2 = get_prop(cl_h1, src(e), dst(e), :ipl) - ir1 = get_prop(new_cl_h1, src(e), dst(e), :ipr) - ir2 = get_prop(cl_h1, src(e), dst(e), :ipr) - - pl1 = get_projector!(get_prop(new_cl_h1, :pool_of_projectors), il1, :CPU) - pl2 = get_projector!(get_prop(cl_h1, :pool_of_projectors), il2, :CPU) - pr1 = get_projector!(get_prop(new_cl_h1, :pool_of_projectors), ir1, :CPU) - pr2 = get_projector!(get_prop(cl_h1, :pool_of_projectors), ir2, :CPU) + for e ∈ edges(new_potts_h1) + il1 = get_prop(new_potts_h1, src(e), dst(e), :ipl) + il2 = get_prop(potts_h1, src(e), dst(e), :ipl) + ir1 = get_prop(new_potts_h1, src(e), dst(e), :ipr) + ir2 = get_prop(potts_h1, src(e), dst(e), :ipr) + + pl1 = get_projector!(get_prop(new_potts_h1, :pool_of_projectors), il1, :CPU) + pl2 = get_projector!(get_prop(potts_h1, :pool_of_projectors), il2, :CPU) + pr1 = get_projector!(get_prop(new_potts_h1, :pool_of_projectors), ir1, :CPU) + pr2 = get_projector!(get_prop(potts_h1, :pool_of_projectors), ir2, :CPU) @test pl1 == pl2 @test pr1 == pr2 end - beliefs = belief_propagation(new_cl_h1, beta; iter = iter, tol = tol) + beliefs = belief_propagation(new_potts_h1, beta; iter = iter, tol = tol) exact_marginal = Dict() for k in keys(beliefs) temp = -1 / beta .* log.([ - exact_cond_prob(cl_h1, beta, Dict(k => a)) for + exact_cond_prob(potts_h1, beta, Dict(k => a)) for a = 1:length(beliefs[k]) ]) push!(exact_marginal, k => temp .- minimum(temp)) diff --git a/test/clustered_hamiltonian.jl b/test/potts_hamiltonian.jl similarity index 73% rename from test/clustered_hamiltonian.jl rename to test/potts_hamiltonian.jl index 5bf9d25..db5531c 100644 --- a/test/clustered_hamiltonian.jl +++ b/test/potts_hamiltonian.jl @@ -15,20 +15,20 @@ enum(vec) = Dict(v => i for (i, v) ∈ enumerate(vec)) for T ∈ [Float16, Float32, Float64] ig = ising_graph(T, instance) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, 2, cluster_assignment_rule = super_square_lattice((m, n, 2 * t)), ) - @test collect(vertices(cl_h)) == [(i, j) for i ∈ 1:m for j ∈ 1:n] + @test collect(vertices(potts_h)) == [(i, j) for i ∈ 1:m for j ∈ 1:n] clv = [] cle = [] rank = rank_vec(ig) - for v ∈ vertices(cl_h) - cl = get_prop(cl_h, v, :cluster) + for v ∈ vertices(potts_h) + cl = get_prop(potts_h, v, :cluster) push!(clv, vertices(cl)) push!(cle, collect(edges(cl))) @@ -96,17 +96,17 @@ end ig = ising_graph(T, instance) @test eltype(ig) == T - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, spectrum = full_spectrum, cluster_assignment_rule = super_square_lattice((m, n, t)), ) - for (bd, e) in zip(bond_dimensions, edges(cl_h)) + for (bd, e) in zip(bond_dimensions, edges(potts_h)) ipl, en, ipr = - get_prop(cl_h, e, :ipl), get_prop(cl_h, e, :en), get_prop(cl_h, e, :ipr) - pl = get_projector!(get_prop(cl_h, :pool_of_projectors), ipl, :CPU) - pr = get_projector!(get_prop(cl_h, :pool_of_projectors), ipr, :CPU) + get_prop(potts_h, e, :ipl), get_prop(potts_h, e, :en), get_prop(potts_h, e, :ipr) + pl = get_projector!(get_prop(potts_h, :pool_of_projectors), ipl, :CPU) + pr = get_projector!(get_prop(potts_h, :pool_of_projectors), ipr, :CPU) @test minimum(size(en)) == bd @test maximum(pl) == size(en, 1) @@ -114,11 +114,11 @@ end end for ((i, j), cedge) ∈ cedges - ipl, en, ipr = get_prop(cl_h, i, j, :ipl), - get_prop(cl_h, i, j, :en), - get_prop(cl_h, i, j, :ipr) - pl = get_projector!(get_prop(cl_h, :pool_of_projectors), ipl, :CPU) - pr = get_projector!(get_prop(cl_h, :pool_of_projectors), ipr, :CPU) + ipl, en, ipr = get_prop(potts_h, i, j, :ipl), + get_prop(potts_h, i, j, :en), + get_prop(potts_h, i, j, :ipr) + pl = get_projector!(get_prop(potts_h, :pool_of_projectors), ipl, :CPU) + pr = get_projector!(get_prop(potts_h, :pool_of_projectors), ipr, :CPU) base_i = all_states(rank[i]) base_j = all_states(rank[j]) @@ -144,14 +144,14 @@ end @test energy ≈ en[pl, pr] end @testset "each cluster comprises expected cells" begin - for v ∈ vertices(cl_h) - cl = get_prop(cl_h, v, :cluster) + for v ∈ vertices(potts_h) + cl = get_prop(potts_h, v, :cluster) @test issetequal(vertices(cl), cells[v]) end end @testset "each edge comprises expected bunch of edges from source Ising graph" begin - for e ∈ edges(cl_h) - outer_edges = get_prop(cl_h, e, :outer_edges) + for e ∈ edges(potts_h) + outer_edges = get_prop(potts_h, e, :outer_edges) @test issetequal( cedges[(src(e), dst(e))], [(src(oe), dst(oe)) for oe ∈ outer_edges], @@ -161,7 +161,7 @@ end end end -function create_example_clustered_hamiltonian(::Type{T}) where {T} +function create_example_potts_hamiltonian(::Type{T}) where {T} J12 = -1 h1 = 1 / 2 h2 = 0.75 @@ -169,7 +169,7 @@ function create_example_clustered_hamiltonian(::Type{T}) where {T} D = Dict((1, 2) => J12, (1, 1) => h1, (2, 2) => h2) ig = ising_graph(T, D) - clustered_hamiltonian( + potts_hamiltonian( ig, Dict((1, 1) => 2, (1, 2) => 2), spectrum = full_spectrum, @@ -177,16 +177,16 @@ function create_example_clustered_hamiltonian(::Type{T}) where {T} ) end -cl_h_state_to_spin = +potts_h_state_to_spin = [([1, 1], [-1, -1]), ([1, 2], [-1, 1]), ([2, 1], [1, -1]), ([2, 2], [1, 1])] @testset "Decoding solution gives correct spin assignment" begin for T ∈ [Float16, Float32, Float64] - cl_h = create_example_clustered_hamiltonian(T) - @test all(eltype(get_prop(cl_h, e, :en)) == T for e ∈ edges(cl_h)) - for (state, spin_values) ∈ cl_h_state_to_spin - d = decode_clustered_hamiltonian_state(cl_h, state) + potts_h = create_example_potts_hamiltonian(T) + @test all(eltype(get_prop(potts_h, e, :en)) == T for e ∈ edges(potts_h)) + for (state, spin_values) ∈ potts_h_state_to_spin + d = decode_potts_hamiltonian_state(potts_h, state) states = collect(values(d))[collect(keys(d))] @test states == spin_values end @@ -204,7 +204,7 @@ Instance below looks like this: And we group the following spins together: [1, 2, 4, 5], [3, 6], [7, 8], [9]. """ -function create_larger_example_clustered_hamiltonian() +function create_larger_example_potts_hamiltonian() instance = Dict( (1, 1) => 0.5, (2, 2) => 0.25, @@ -242,34 +242,34 @@ function create_larger_example_clustered_hamiltonian() 9 => (2, 2), ) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, Dict{NTuple{2,Int},Int}(), spectrum = full_spectrum, cluster_assignment_rule = assignment_rule, ) - ig, cl_h + ig, potts_h end -function clustered_hamiltonian_energy(cl_h, state) +function potts_hamiltonian_energy(potts_h, state) # This is highly inefficient, but simple, which makes it suitable for testing. # If such a function is needed elsewhere, we need to implement it properly. total_en = 0 # Collect local terms from each cluster - for (s, v) ∈ zip(state, vertices(cl_h)) - total_en += get_prop(cl_h, v, :spectrum).energies[s] + for (s, v) ∈ zip(state, vertices(potts_h)) + total_en += get_prop(potts_h, v, :spectrum).energies[s] end # Collect inter-cluster terms - for edge ∈ edges(cl_h) - i, j = cl_h.reverse_label_map[src(edge)], cl_h.reverse_label_map[dst(edge)] - ipl, en, ipr = get_prop(cl_h, edge, :ipl), - get_prop(cl_h, edge, :en), - get_prop(cl_h, edge, :ipr) - pl = get_projector!(get_prop(cl_h, :pool_of_projectors), ipl, :CPU) - pr = get_projector!(get_prop(cl_h, :pool_of_projectors), ipr, :CPU) + for edge ∈ edges(potts_h) + i, j = potts_h.reverse_label_map[src(edge)], potts_h.reverse_label_map[dst(edge)] + ipl, en, ipr = get_prop(potts_h, edge, :ipl), + get_prop(potts_h, edge, :en), + get_prop(potts_h, edge, :ipr) + pl = get_projector!(get_prop(potts_h, :pool_of_projectors), ipl, :CPU) + pr = get_projector!(get_prop(potts_h, :pool_of_projectors), ipr, :CPU) edge_energy = en[pl, pr] total_en += edge_energy[state[i], state[j]] end @@ -277,18 +277,18 @@ function clustered_hamiltonian_energy(cl_h, state) end @testset "Decoding solution gives spins configuration with corresponding energies" begin - ig, cl_h = create_larger_example_clustered_hamiltonian() + ig, potts_h = create_larger_example_potts_hamiltonian() # Corresponding bases sizes for each cluster are 16, 4, 4, 2. all_states = [[i, j, k, l] for i ∈ 1:16 for j ∈ 1:4 for k ∈ 1:4 for l ∈ 1:2] for state ∈ all_states - d = decode_clustered_hamiltonian_state(cl_h, state) + d = decode_potts_hamiltonian_state(potts_h, state) spins = zeros(length(d)) for (k, v) ∈ d spins[k] = v end σ = [Int.(spins)] - @test clustered_hamiltonian_energy(cl_h, state) ≈ energy(σ, ig)[] + @test potts_hamiltonian_energy(potts_h, state) ≈ energy(σ, ig)[] end end diff --git a/test/runtests.jl b/test/runtests.jl index c968233..02d785a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -29,7 +29,7 @@ end my_tests = [ "ising.jl", - "clustered_hamiltonian.jl", + "potts_hamiltonian.jl", "bp_1site.jl", "bp_2site.jl", "utils.jl", diff --git a/test/utils.jl b/test/utils.jl index c822e8a..e4167b1 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -1,7 +1,7 @@ instance_dir = "$(@__DIR__)/instances/pegasus/" instances = ["P2"] #, "P4", "P8", "P16"] -@testset verbose = true "Renumerated instances generate correct clustered Hamiltonian" begin +@testset verbose = true "Renumerated instances generate correct Potts Hamiltonian" begin size = [2, 4, 8, 16] @testset "$instance" for (i, instance) ∈ enumerate(instances) @@ -11,16 +11,16 @@ instances = ["P2"] #, "P4", "P8", "P16"] max_cl_states = 2 ig = ising_graph(joinpath(instance_dir, instance)) - cl_h = clustered_hamiltonian( + potts_h = potts_hamiltonian( ig, max_cl_states, spectrum = brute_force, cluster_assignment_rule = super_square_lattice((m, n, t)), ) - @test nv(cl_h) == s^2 + @test nv(potts_h) == s^2 if s > 1 - @test all(has_edge(cl_h, (l, k), (l + 1, k - 1)) for l ∈ 1:s-1, k ∈ 2:s) + @test all(has_edge(potts_h, (l, k), (l + 1, k - 1)) for l ∈ 1:s-1, k ∈ 2:s) end end end