Skip to content

Changes based on new version of ProblemReductions #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 13, 2024
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LuxorGraphPlot = "1f49bdf2-22a7-4bc4-978b-948dc219fbbc"
OMEinsum = "ebe7aa44-baf0-506c-a96f-8464559b3922"
Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
ProblemReductions = "899c297d-f7d2-4ebf-8815-a35996def416"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SIMDTypes = "94e857df-77ce-4151-89e5-788b33177be4"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
Expand All @@ -41,7 +41,7 @@ LuxorGraphPlot = "0.5"
OMEinsum = "0.8"
Polynomials = "4"
Primes = "0.5"
Printf = "1"
ProblemReductions = "0.2"
Random = "1"
SIMDTypes = "0.1"
Serialization = "1"
Expand Down
5 changes: 2 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Pkg
using GenericTensorNetworks
using GenericTensorNetworks: TropicalNumbers, Polynomials, OMEinsum, OMEinsum.OMEinsumContractionOrders, LuxorGraphPlot
using GenericTensorNetworks: TropicalNumbers, Polynomials, OMEinsum, OMEinsum.OMEinsumContractionOrders, LuxorGraphPlot, ProblemReductions
using Documenter
using DocThemeIndigo
using Literate
Expand All @@ -17,7 +17,7 @@ indigo = DocThemeIndigo.install(GenericTensorNetworks)
DocMeta.setdocmeta!(GenericTensorNetworks, :DocTestSetup, :(using GenericTensorNetworks); recursive=true)

makedocs(;
modules=[GenericTensorNetworks, TropicalNumbers, OMEinsum, OMEinsumContractionOrders, LuxorGraphPlot],
modules=[GenericTensorNetworks, ProblemReductions, TropicalNumbers, OMEinsum, OMEinsumContractionOrders, LuxorGraphPlot],
authors="Jinguo Liu",
repo="https://github.com/QuEraComputing/GenericTensorNetworks.jl/blob/{commit}{path}#{line}",
sitename="GenericTensorNetworks.jl",
Expand All @@ -40,7 +40,6 @@ makedocs(;
"Satisfiability problem" => "generated/Satisfiability.md",
"Set covering problem" => "generated/SetCovering.md",
"Set packing problem" => "generated/SetPacking.md",
#"Other problems" => "generated/Others.md",
],
"Topics" => [
"Gist" => "gist.md",
Expand Down
45 changes: 26 additions & 19 deletions docs/src/ref.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# References
## Graph problems
## Constraint Satisfaction Problems
```@docs
solve
GenericTensorNetwork
GraphProblem
ConstraintSatisfactionProblem
IndependentSet
MaximalIS
Matching
Expand All @@ -15,28 +15,35 @@ PaintShop
Satisfiability
SetCovering
SetPacking
OpenPitMining
```

#### Graph Problem Interfaces
#### Constraint Satisfaction Problem Interfaces

To subtype [`GraphProblem`](@ref), a new type must contain a `code` field to represent the (optimized) tensor network.
Interfaces [`GenericTensorNetworks.generate_tensors`](@ref), [`labels`](@ref), [`flavors`](@ref) and [`get_weights`](@ref) are required.
[`nflavor`](@ref) is optional.
To subtype [`ConstraintSatisfactionProblem`](@ref), a new type must contain a `code` field to represent the (optimized) tensor network.
Interfaces [`GenericTensorNetworks.generate_tensors`](@ref), [`flavors`](@ref) and [`weights`](@ref) are required.
[`num_flavors`](@ref) is optional.

```@docs
GenericTensorNetworks.generate_tensors
labels
energy_terms
flavors
get_weights
chweights
nflavor
weights
set_weights
is_weighted
num_flavors
fixedvertices
```

#### Graph Problem Utilities
#### Constraint Satisfaction Problem Utilities
```@docs
hard_constraints
is_satisfied
local_solution_spec
solution_size
energy_mode
LargerSizeIsBetter
SmallerSizeIsBetter
energy

is_independent_set
is_maximal_independent_set
is_dominating_set
Expand All @@ -46,10 +53,7 @@ is_set_covering
is_set_packing

cut_size
spinglass_energy
num_paint_shop_color_switch
paint_shop_coloring_from_config
mis_compactify!

CNF
CNFClause
Expand All @@ -60,8 +64,7 @@ satisfiable
¬

is_valid_mining
print_mining
mis_compactify!
```

## Properties
Expand Down Expand Up @@ -145,7 +148,12 @@ MergeGreedy

## Others
#### Graph
Except the `SimpleGraph` defined in [Graphs](https://github.com/JuliaGraphs/Graphs.jl), `GenericTensorNetworks` also defines the following types and functions.

```@docs
HyperGraph
UnitDiskGraph

show_graph
show_configs
show_einsum
Expand All @@ -162,7 +170,6 @@ render_locs

diagonal_coupled_graph
square_lattice_graph
unit_disk_graph
line_graph

random_diagonal_coupled_graph
Expand Down
7 changes: 4 additions & 3 deletions examples/Coloring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ problem = GenericTensorNetwork(coloring)

# ## Solving properties
# ##### counting all possible coloring
num_of_coloring = solve(problem, CountingMax())[]
# The size of a coloring problem is the number of violations of the coloring constraint.
num_of_coloring = solve(problem, CountingMin())[]

# ##### finding one best coloring
single_solution = solve(problem, SingleConfigMax())[]
single_solution = solve(problem, SingleConfigMin())[]
read_config(single_solution)

is_vertex_coloring(graph, read_config(single_solution))
Expand All @@ -68,7 +69,7 @@ show_graph(linegraph, [(locations[e.src] .+ locations[e.dst])
# Let us construct the tensor network and see if there are solutions.
lineproblem = Coloring{3}(linegraph);

num_of_coloring = solve(GenericTensorNetwork(lineproblem), CountingMax())[]
num_of_coloring = solve(GenericTensorNetwork(lineproblem), CountingMin())[]
read_size_count(num_of_coloring)

# You will see the maximum size 28 is smaller than the number of edges in the `linegraph`,
Expand Down
4 changes: 2 additions & 2 deletions examples/PaintShop.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# In the following, we use a character to represent a car,
# and defined a binary paint shop problem as a string that each character appear exactly twice.

using GenericTensorNetworks, Graphs
using GenericTensorNetworks, Graphs, GenericTensorNetworks.ProblemReductions

sequence = collect("iadgbeadfcchghebif")

Expand Down Expand Up @@ -88,7 +88,7 @@ best_configs = solve(problem, ConfigsMin())[]

# One can see to identical bitstrings corresponding two different vertex configurations, they are related to bit-flip symmetry.

painting1 = paint_shop_coloring_from_config(pshop, read_config(best_configs)[1])
painting1 = ProblemReductions.paint_shop_coloring_from_config(pshop, read_config(best_configs)[1])

show_graph(graph, locations; format=:svg, texts=string.(sequence),
edge_colors=[sequence[e.src] == sequence[e.dst] ? "blue" : "black" for e in edges(graph)],
Expand Down
10 changes: 5 additions & 5 deletions examples/Satisfiability.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# One can specify a satisfiable problem in the [conjunctive normal form](https://en.wikipedia.org/wiki/Conjunctive_normal_form).
# In boolean logic, a formula is in conjunctive normal form (CNF) if it is a conjunction (∧) of one or more clauses,
# where a clause is a disjunction (∨) of literals.
using GenericTensorNetworks
using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions

@bools a b c d e f g

Expand Down Expand Up @@ -48,15 +48,15 @@ problem = GenericTensorNetwork(sat)

# ## Solving properties
# #### Satisfiability and its counting
# The size of a satisfiability problem is defined by the number of satisfiable clauses.
num_satisfiable = solve(problem, SizeMax())[]
# The size of a satisfiability problem is defined by the number of unsatisfied clauses.
num_satisfiable = solve(problem, SizeMin())[]

# The [`GraphPolynomial`](@ref) of a satisfiability problem counts the number of solutions that `k` clauses satisfied.
num_satisfiable_count = read_size_count(solve(problem, GraphPolynomial())[])

# #### Find one of the solutions
single_config = read_config(solve(problem, SingleConfigMax())[])
single_config = read_config(solve(problem, SingleConfigMin())[])

# One will see a bit vector printed.
# One can create an assignment and check the validity with the following statement:
satisfiable(cnf, Dict(zip(labels(problem), single_config)))
satisfiable(cnf, Dict(zip(ProblemReductions.symbols(problem.problem), single_config)))
2 changes: 1 addition & 1 deletion examples/SetCovering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ min_configs = read_config(solve(problem, ConfigsMin())[])
# Hence the two optimal solutions are ``\{z_1, z_3, z_5, z_6\}`` and ``\{z_2, z_3, z_4, z_5\}``.
# The correctness of this result can be checked with the [`is_set_covering`](@ref) function.

all(c->is_set_covering(sets, c), min_configs)
all(c->is_set_covering(problem.problem, c), min_configs)

# Similarly, if one is only interested in computing one of the minimum set coverings,
# one can use the graph property [`SingleConfigMin`](@ref).
2 changes: 1 addition & 1 deletion examples/SetPacking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ max_configs = read_config(solve(problem, ConfigsMax())[])
# Hence the only optimal solution is ``\{z_1, z_3, z_6\}`` that has size 3.
# The correctness of this result can be checked with the [`is_set_packing`](@ref) function.

all(c->is_set_packing(sets, c), max_configs)
all(c->is_set_packing(problem.problem, c), max_configs)

# Similarly, if one is only interested in computing one of the maximum set packing,
# one can use the graph property [`SingleConfigMax`](@ref).
14 changes: 8 additions & 6 deletions examples/SpinGlass.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ show_graph(graph, locations; format=:svg)

# ## Generic tensor network representation
# An anti-ferromagnetic spin glass problem can be defined with the [`SpinGlass`](@ref) type as
spinglass = SpinGlass(graph, fill(1, ne(graph)))
spinglass = SpinGlass(graph, fill(1, ne(graph)), zeros(Int, nv(graph)))

# The tensor network representation of the set packing problem can be obtained by
problem = GenericTensorNetwork(spinglass)
Expand Down Expand Up @@ -81,8 +81,10 @@ partition_function = solve(problem, GraphPolynomial())[]
# The ground state of the spin glass problem can be found by the [`SingleConfigMin`](@ref) solver.
ground_state = read_config(solve(problem, SingleConfigMin())[])

# The energy of the ground state can be verified by the [`spinglass_energy`](@ref) function.
Emin_verify = spinglass_energy(spinglass, ground_state)
# The energy of the ground state can be verified by the [`energy`](@ref) function.
# Note the output of the ground state can not be directly used as the input of the `energy` function.
# It needs to be converted to the spin configurations.
Emin_verify = energy(problem.problem, 1 .- 2 .* Int.(ground_state))

# You should see a consistent result as above `Emin`.

Expand Down Expand Up @@ -117,7 +119,7 @@ weights = [-1, 1, -1, 1, -1, 1, -1, 1];
# \end{align*}
# ```
# A spin glass problem can be defined with the [`SpinGlass`](@ref) type as
hyperspinglass = SpinGlass(num_vertices, hyperedges, weights)
hyperspinglass = SpinGlass(HyperGraph(num_vertices, hyperedges), weights, zeros(Int, num_vertices))

# The tensor network representation of the set packing problem can be obtained by
hyperproblem = GenericTensorNetwork(hyperspinglass)
Expand Down Expand Up @@ -155,8 +157,8 @@ poly = solve(hyperproblem, GraphPolynomial())[]
# The ground state of the spin glass problem can be found by the [`SingleConfigMin`](@ref) solver.
ground_state = read_config(solve(hyperproblem, SingleConfigMin())[])

# The energy of the ground state can be verified by the [`spinglass_energy`](@ref) function.
# The energy of the ground state can be verified by the [`energy`](@ref) function.

Emin_verify = spinglass_energy(hyperspinglass, ground_state)
Emin_verify = energy(hyperproblem.problem, 1 .- 2 .* Int.(ground_state))

# You should see a consistent result as above `Emin`.
6 changes: 3 additions & 3 deletions examples/weighted.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# # Weighted problems
# Let us use the maximum independent set problem on Petersen graph as an example.

using GenericTensorNetworks, Graphs
using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions, Graphs

graph = Graphs.smallgraph(:petersen)

# The following code constructs a weighted MIS problem instance.
problem = GenericTensorNetwork(IndependentSet(graph, collect(1:10)));
GenericTensorNetworks.get_weights(problem)
GenericTensorNetworks.weights(problem)

# The tensor labels that associated with the weights can be accessed by
GenericTensorNetworks.energy_terms(problem)
ProblemReductions.local_solution_spec(problem.problem)

# Here, the `weights` keyword argument can be a vector for weighted graphs or `UnitWeight()` for unweighted graphs.
# Most solution space properties work for unweighted graphs also work for the weighted graphs.
Expand Down
30 changes: 19 additions & 11 deletions src/GenericTensorNetworks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using TropicalNumbers
using OMEinsum
using OMEinsum: contraction_complexity, timespace_complexity, timespacereadwrite_complexity, getixsv, NestedEinsum, getixs, getiy, DynamicEinCode
using Graphs, Random
using DelimitedFiles, Serialization, Printf
using DelimitedFiles, Serialization
using LuxorGraphPlot
using LuxorGraphPlot.Luxor.Colors: @colorant_str
using LuxorGraphPlot: Layered
Expand All @@ -15,6 +15,12 @@ using FFTW
using Primes
using DocStringExtensions
using Base.Cartesian
using ProblemReductions
import ProblemReductions: ConstraintSatisfactionProblem, AbstractSatisfiabilityProblem, UnitWeight, hard_constraints, is_satisfied, local_solution_spec, solution_size, energy_mode, LargerSizeIsBetter, SmallerSizeIsBetter
import ProblemReductions: @bv_str, StaticElementVector, StaticBitVector, onehotv, _nints, hamming_distance
import ProblemReductions: is_set_covering, is_vertex_coloring, is_set_packing, is_dominating_set, is_matching, is_maximal_independent_set, cut_size, is_independent_set
import ProblemReductions: num_paint_shop_color_switch, spin_glass_from_matrix, CNF, CNFClause, BoolVar, satisfiable, @bools, ∨, ¬, ∧
import ProblemReductions: flavors, set_weights, weights, is_weighted, num_flavors, variables, energy
import AbstractTrees: children, printnode, print_tree
import StatsBase

Expand All @@ -34,28 +40,32 @@ export CountingTropicalF64, CountingTropicalF32, TropicalF64, TropicalF32, Exten
export generate_samples, OnehotVec

# Graphs
export HyperGraph, SimpleGraph, UnitDiskGraph
export random_regular_graph, diagonal_coupled_graph
export square_lattice_graph, unit_disk_graph, random_diagonal_coupled_graph, random_square_lattice_graph
export square_lattice_graph, random_diagonal_coupled_graph, random_square_lattice_graph
export line_graph


# Problems
export AbstractProblem, ConstraintSatisfactionProblem
export hard_constraints, is_satisfied, local_solution_spec, solution_size, energy_mode, LargerSizeIsBetter, SmallerSizeIsBetter
# Tensor Networks (Graph problems)
export GraphProblem, GenericTensorNetwork, optimize_code, UnitWeight, ZeroWeight
export flavors, labels, nflavor, get_weights, fixedvertices, chweights, energy_terms
export GenericTensorNetwork, optimize_code, UnitWeight
export flavors, variables, num_flavors, weights, fixedvertices, set_weights, is_weighted
export IndependentSet, mis_compactify!, is_independent_set
export MaximalIS, is_maximal_independent_set
export cut_size, MaxCut
export spinglass_energy, spin_glass_from_matrix, SpinGlass
export PaintShop, paintshop_from_pairs, num_paint_shop_color_switch, paint_shop_coloring_from_config, paint_shop_from_pairs
export energy, spin_glass_from_matrix, SpinGlass
export PaintShop, paintshop_from_pairs, num_paint_shop_color_switch
export Coloring, is_vertex_coloring
export Satisfiability, CNF, CNFClause, BoolVar, satisfiable, @bools, ∨, ¬, ∧
export DominatingSet, is_dominating_set
export Matching, is_matching
export SetPacking, is_set_packing
export SetCovering, is_set_covering
export OpenPitMining, is_valid_mining, print_mining

# Interfaces
export solve, SizeMax, SizeMin, PartitionFunction, CountingAll, CountingMax, CountingMin, GraphPolynomial, SingleConfigMax, SingleConfigMin, ConfigsAll, ConfigsMax, ConfigsMin, Single
export solve, SizeMax, SizeMin, PartitionFunction, CountingAll, CountingMax, CountingMin, GraphPolynomial, SingleConfigMax, SingleConfigMin, ConfigsAll, ConfigsMax, ConfigsMin, Single, AllConfigs

# Utilities
export save_configs, load_configs, hamming_distribution, save_sumproduct, load_sumproduct
Expand All @@ -73,10 +83,8 @@ project_relative_path(xs...) = normpath(joinpath(dirname(dirname(pathof(@__MODUL
include("Mods.jl/src/Mods.jl")
using .Mods

include("utils.jl")
include("bitvector.jl")
include("arithematics.jl")
include("networks/networks.jl")
include("networks.jl")
include("graph_polynomials.jl")
include("configurations.jl")
include("graphs.jl")
Expand Down
Loading
Loading