References
Constraint Satisfaction Problems
GenericTensorNetworks.solve — Functionsolve(problem, property; usecuda=false, T=Float64)Solving a certain property of a graph problem.
Positional Arguments
problemis the graph problem with tensor network information,propertyis string specifying the task. Using the maximum independent set problem as an example, it can be one ofPartitionFunction()for computing the partition function,SizeMax(k=Single)for finding maximum-$k$ set sizes,SizeMin(k=Single)for finding minimum-$k$ set sizes,CountingMax(k=Single)for counting configurations with maximum-$k$ sizes,CountingMin(k=Single)for counting configurations with minimum-$k$ sizes,CountingAll()for counting all configurations,PartitionFunction()for counting all configurations,GraphPolynomial(; method=:finitefield, kwargs...)for evaluating the graph polynomial,SingleConfigMax(k=Single; bounded=false)for finding one maximum-$k$ configuration for each size,SingleConfigMin(k=Single; bounded=false)for finding one minimum-$k$ configuration for each size,ConfigsMax(k=Single; bounded=true, tree_storage=false)for enumerating configurations with maximum-$k$ sizes,ConfigsMin(k=Single; bounded=true, tree_storage=false)for enumerating configurations with minimum-$k$ sizes,ConfigsAll(; tree_storage=false)for enumerating all configurations,
Keyword arguments
usecudais a switch to use CUDA (if possible), user need to call statementusing CUDAbefore turning on this switch.Tis the "base" element type, sometimes can be used to reduce the memory cost.
GenericTensorNetworks.GenericTensorNetwork — Typestruct GenericTensorNetwork{CFG, CT, LT}GenericTensorNetwork(problem::ConstraintSatisfactionProblem; openvertices=(), fixedvertices=Dict(), optimizer=GreedyMethod(), slicer=nothing)The generic tensor network that generated from a ConstraintSatisfactionProblem.
Positional arguments
problemis the constraint satisfaction problem.
Keyword arguments
openverticesis a vector of open indices, which are the degrees of freedoms that appears in the output tensor.fixedverticesis a dictionary specifying the fixed degrees of freedom. For example, If I want to fix the variable5to be 0, I can setfixedvertices = Dict(5 => 0).optimizeris the contraction order optimizer for the generated tensor network.sliceris the slicer for the tensor network, it can reduce the memory usage at the cost of computing time by slicing the tensor network.
For more information about contraction order optimization and slicing, please refer to the OMEinsumContractionOrders documentation.
ProblemReductions.ConstraintSatisfactionProblem — TypeConstraintSatisfactionProblem{T} <: AbstractProblemThe abstract base type of constraint satisfaction problems. T is the type of the local size of the constraints.
Required interfaces
constraints, the specification of the constraints. Once the constraints are violated, the size goes to infinity.objectives, the specification of the size terms as soft constraints, which is associated with weights.
Optional interfaces
weights: The weights of the soft constraints.set_weights: Change the weights for theproblemand return a new problem instance.
Derived interfaces
is_satisfied, check if the constraints are satisfied.
ProblemReductions.IndependentSet — Typestruct IndependentSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}IndependentSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(nv(graph))) -> IndependentSetIndependent Set is a subset of vertices in a undirected graph such that all the vertices in the set are not connected by edges (or called not adjacent). The maximum IndependentSet problem is to find the independent set with maximum number of vertices, which is a NP-complete problem. Let $G=(V, E)$ be a graph, and $w_v$ be the weight of vertex $v$. The energy based model of the independent set problem is:
\[H(G, \mathbf{n}) = - \sum_{v \in V} w_v n_v + \sum_{(u, v) \in E} n_u n_v\]
where $n_v$ is the number of vertices in the independent set, i.e. $n_v = 1$ if $v$ is in the independent set, and $n_v = 0$ otherwise. The larger the size of the independent set, the lower the energy.
Fields
graph::AbstractGraph: The problem graph.weights::AbstractVector: Weights associated with the vertices of thegraph. Defaults toUnitWeight(nv(graph)).
Example
In the following example, we define an independent set problem on a graph with four vertices. To define an IndependentSet problem, we need to specify the graph and possibily the weights associated with vertices. The weights are set as unit by default in the current version and might be generalized to arbitrary positive weights.
julia> using ProblemReductions, Graphs
julia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))
{4, 4} undirected simple Int64 graph
julia> IS = IndependentSet(graph)
IndependentSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, 1, 1, 1])
julia> num_variables(IS) # degrees of freedom
4
julia> flavors(IS) # flavors of the vertices
(0, 1)
julia> solution_size(IS, [1, 0, 0, 1]) # Positive sample: -(size) of an independent set
SolutionSize{Int64}(2, true)
julia> solution_size(IS, [0, 1, 1, 0]) # Negative sample: 0
SolutionSize{Int64}(2, false)
julia> findbest(IS, BruteForce()) # solve the problem with brute force
2-element Vector{Vector{Int64}}:
[1, 0, 0, 1]
[0, 1, 0, 1]ProblemReductions.MaximalIS — Typestruct MaximalIS{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}Maximal independent set is a problem that very similar to the IndependentSet problem. The difference is that the solution space of a maximal indepdent set problem does not include the independent sets that can be extended by adding one more vertex.
Fields
graphis the problem graph.weightsare associated with the vertices of thegraph.
Example
In the following example, we define a maximal independent set problem on a graph with four vertices. To define a MaximalIS problem, we need to specify the graph and possibily the weights associated with vertices. The weights are set as unit by default in the current version and might be generalized to arbitrary positive weights in the following development.
julia> using ProblemReductions, Graphs
julia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3), (1, 4)]))
{4, 5} undirected simple Int64 graph
julia> problem = MaximalIS(graph)
MaximalIS{Int64, UnitWeight}(SimpleGraph{Int64}(5, [[2, 3, 4], [1, 3], [1, 2, 4], [1, 3]]), [1, 1, 1, 1])
julia> num_variables(problem) # degrees of freedom
4
julia> flavors(problem)
(0, 1)
julia> solution_size(problem, [0, 1, 0, 0]) # unlike the independent set, this configuration is not a valid solution
SolutionSize{Int64}(1, false)
julia> findbest(problem, BruteForce())
1-element Vector{Vector{Int64}}:
[0, 1, 0, 1]ProblemReductions.Matching — Typestruct Matching{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}The Vertex matching problem.
Positional arguments
graphis the problem graph.weightsare associated with the edges of thegraph.
ProblemReductions.Coloring — Typestruct Coloring{K, T, WT<:AbstractArray{T, 1}, OBJ} <: ConstraintSatisfactionProblem{T}Coloring{K}(graph; weights=UnitWeight(nv(graph)), use_constraints::Bool=false)The Vertex Coloring (Coloring) problem is defined on a simple graph. Given k kinds of colors, we need to determine whether we can color all vertices on the graph such that no two adjacent vertices share the same color.
Fields
graphis the problem graph.weightsare associated with the edges of thegraph, default toUnitWeight(ne(graph)).
Example
To initialize a Coloring problem, we need to first define a graph and decide the number of colors.
julia> using ProblemReductions, Graphs
julia> g = smallgraph(:petersen) # define a simple graph, petersen as example
{10, 15} undirected simple Int64 graph
julia> coloring = Coloring{3}(g) # 3 colors
Coloring{3, Int64, UnitWeight, ProblemReductions.EXTREMA}(SimpleGraph{Int64}(15, [[2, 5, 6], [1, 3, 7], [2, 4, 8], [3, 5, 9], [1, 4, 10], [1, 8, 9], [2, 9, 10], [3, 6, 10], [4, 6, 7], [5, 7, 8]]), [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
julia> variables(coloring)
1:10
julia> flavors(coloring)
(0, 1, 2)
julia> is_vertex_coloring(coloring.graph,[1,2,3,1,3,2,1,2,3,1]) #random assignment
falseProblemReductions.DominatingSet — Typestruct DominatingSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}DominatingSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(ne(graph))) -> DominatingSetDominaing Set is a subset of vertices in a undirected graph such that all the vertices in the set are either in the dominating set or in its first-order neighborhood. The DominatingSet problem is to find the dominating set with minimum number of vertices.
Fields
graphis the problem graph.weights::AbstractVector: Weights associated with the vertices of thegraph. Defaults toUnitWeight(nv(graph)).
Example
In the following example, we define a dominating set problem on a path graph with five vertices. To define a DominatingSet problem, we need to specify the graph and possibily the weights associated with vertices. The weights are set as unit by default in the current version and might be generalized to arbitrary positive weights in the following development.
julia> using ProblemReductions, Graphs
julia> graph = path_graph(5)
{5, 4} undirected simple Int64 graph
julia> DS = DominatingSet(graph)
DominatingSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2], [1, 3], [2, 4], [3, 5], [4]]), [1, 1, 1, 1, 1])
julia> variables(DS) # degrees of freedom
1:5
julia> flavors(DS) # flavors of the vertices
(0, 1)
julia> solution_size(DS, [0, 1, 0, 1, 0]) # Positive sample: (size) of a dominating set
SolutionSize{Int64}(2, true)
julia> solution_size(DS, [0, 1, 1, 0, 0]) # Negative sample: number of vertices
SolutionSize{Int64}(2, false)
julia> findbest(DS, BruteForce()) # solve the problem with brute force
3-element Vector{Vector{Int64}}:
[1, 0, 0, 1, 0]
[0, 1, 0, 1, 0]
[0, 1, 0, 0, 1]ProblemReductions.SpinGlass — Typestruct SpinGlass{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}SpinGlass(graph::AbstractGraph, weights::AbstractVector)
SpinGlass(graph::SimpleGraph, J, h=zeros(nv(graph)))Spin Glass is a type of disordered magnetic system that exhibits a glassy behavior. The Hamiltonian of the system on a simple graph $G=(V, E)$ is given by
\[H(G, \sigma) = \sum_{(i,j) \in E} J_{ij} \sigma_i \sigma_j + \sum_{i \in V} h_i \sigma_i\]
where $J_{ij} \in \mathbb{R}$ is the coupling strength between spins $i$ and $j$, $h_i \in \mathbb{R}$ is the external field on spin $i$, and $\sigma_i \in \{-1, 1\}$ is the spin variable. The configuration of a solution is specified by a binary variable in (0, 1), where 0 and 1 are mapped to spins -1 and 1, respectively.
This definition naturally extends to the case of a HyperGraph:
\[H(G, \sigma) = \sum_{e \in E} J_{e} \prod_k\sigma_k + \sum_{i \in V} h_i \sigma_i,\]
where $J_e$ is the coupling strength associated with hyperedge $e$, and the product is over all spins in the hyperedge.
Fields
graphis a graph object.Jare the coupling strengths associated with the edges.hare the external fields associated with the vertices.
Example
In the following example, we define a spin glass problem on a 4-vertex graph with given coupling strengths on edges and external fields on vertices.
julia> using ProblemReductions, ProblemReductions.Graphs
julia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))
{4, 4} undirected simple Int64 graph
julia> J = [1, -1, 1, -1] # coupling strength
4-element Vector{Int64}:
1
-1
1
-1
julia> h = [1, -1, -1, 1] # external field
4-element Vector{Int64}:
1
-1
-1
1
julia> spinglass = SpinGlass(graph, J, h) # Define a spin glass problem
SpinGlass{SimpleGraph{Int64}, Int64, Vector{Int64}}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, -1, 1, -1], [1, -1, -1, 1])
julia> num_variables(spinglass) # degrees of freedom
4
julia> flavors(spinglass) # flavors of the spins, 0 for up (+1), 1 for down (-1)
(0, 1)
julia> solution_size(spinglass, [1, 0, 0, 1]) # size of a configuration
SolutionSize{Int64}(-2, true)
julia> findbest(spinglass, BruteForce()) # solve the problem with brute force
1-element Vector{Vector{Int64}}:
[1, 0, 1, 1]ProblemReductions.MaxCut — Typestruct MaxCut{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}Max Cut problem is defined on weighted graphs. The goal is to find a partition of the vertices into two sets such that the sum of the weights of the edges between the two sets is maximized.
Positional arguments
graphis the problem graph.weightsare associated with the edges of thegraph. We have ensure that theweightsare in the same order as the edges inedges(graph).
Example
In the following example, we solve a Max Cut problem on a complete graph with 3 vertices and edge weights [1,2,3].
julia> using ProblemReductions, Graphs
julia> g = complete_graph(3)
{3, 3} undirected simple Int64 graph
julia> maxcut = MaxCut(g,[1,2,3]) # specify the weights of the edges
MaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [1, 2, 3])
julia> mc = set_weights(maxcut, [2,1,3]) # set the weights and get a new instance
MaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [2, 1, 3])
julia> num_variables(maxcut) # return the number of vertices
3
julia> flavors(maxcut) # return the flavors of the vertices
(0, 1)
julia> solution_size(maxcut, [0,1,0]) # return the size of the configuration
SolutionSize{Int64}(4, true)
julia> findbest(maxcut, BruteForce()) # find the best configuration
2-element Vector{Vector{Int64}}:
[1, 1, 0]
[0, 0, 1]ProblemReductions.PaintShop — Typestruct PaintShop{LT} <: ConstraintSatisfactionProblem{Int64}The binary paint shop problem is defined as follows: we are given a $2m$ length sequence containing $m$ cars, where each car appears twice. Each car need to be colored red in one occurrence, and blue in the other. We need to choose which occurrence for each car to color with which color — the goal is to minimize the number of times we need to change the current color.
Fields
sequenceis a vector of symbols, each symbol is associated with a color.isfirstis a vector of boolean numbers, indicating whether the symbol is the first appearance in the sequence.
Example
In the following example, we define a paint shop problem with 6 cars.
julia> using ProblemReductions
julia> problem = PaintShop(["a","b","a","c","c","b"])
PaintShop{String}(["a", "b", "a", "c", "c", "b"], Bool[1, 1, 0, 1, 0, 0])
julia> num_variables(problem)
3
julia> flavors(problem)
(0, 1)
julia> solution_size(problem, [0, 1, 0])
SolutionSize{Int64}(4, true)
julia> findbest(problem, BruteForce())
2-element Vector{Vector{Int64}}:
[1, 0, 0]
[0, 1, 1]ProblemReductions.Satisfiability — Typestruct Satisfiability{S, T, WT<:(AbstractArray{T}), OBJ} <: ProblemReductions.AbstractSatisfiabilityProblem{S, T, OBJ}Satisfiability(cnf::CNF{S}, weights::AbstractVector=UnitWeight(length(cnf.clauses)); use_constraints::Bool=false) where {S}Satisfiability (also called SAT) problem is to find the boolean assignment that satisfies a Conjunctive Normal Form (CNF). A tipical CNF would look like:
\[\left(l_{11} \vee \ldots \vee l_{1 n_1}\right) \wedge \ldots \wedge\left(l_{m 1} \vee \ldots \vee l_{m n_m}\right)\]
where literals are joint by $\vee$ to for $m$ clauses and clauses are joint by $\wedge$ to form a CNF. The satisfiability problem is to find the assignment that maximizes the number of satisfied clauses if use_constraints is false, otherwise, the goal is to find one assignment that can satisfy the CNF.
We should note that all the SAT problem problem can be reduced to the 3-SAT problem and it can be proved that 3-SAT is NP-complete.
Fields
cnfis a conjunctive normal form (CNF) for specifying the satisfiability problems.weightsare associated with clauses. The solution size is the weighted sum of the number of satisfied assignments.
Example
In the following example, we define a satisfiability problem with two clauses.
julia> using ProblemReductions
julia> bv1, bv2, bv3 = BoolVar.(["x", "y", "z"])
3-element Vector{BoolVar{String}}:
x
y
z
julia> clause1 = CNFClause([bv1, bv2, bv3])
x ∨ y ∨ z
julia> clause2 = CNFClause([BoolVar("w"), bv1, BoolVar("x", true)])
w ∨ x ∨ ¬x
julia> cnf_test = CNF([clause1, clause2])
(x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x)
julia> sat_test = Satisfiability(cnf_test)
Satisfiability{String, Int64, UnitWeight, ProblemReductions.EXTREMA}(["x", "y", "z", "w"], [1, 1], (x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x))ProblemReductions.SetCovering — Typestruct SetCovering{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}The Set Covering problem is defined as follow: given a universe of elements and a collection of subsets of the universe, each set is associated with a weight. The goal is to find a subset of sets that covers all the elements with the minimum total weight.
Positional arguments
elementsis a vector of elements in the universe.setsis a vector of vectors, a collection of subsets of universe , each set is associated with a weight specified inweights.weightsare associated with sets.
Example
In the following example, we solve a Set Covering problem with 3 subsets and weights [1,2,3].
julia> using ProblemReductions
julia> subsets = [[1, 2, 3], [2, 4], [1, 4]]
3-element Vector{Vector{Int64}}:
[1, 2, 3]
[2, 4]
[1, 4]
julia> weights = [1, 2, 3]
3-element Vector{Int64}:
1
2
3
julia> setcovering = SetCovering(subsets, weights)
SetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])
julia> num_variables(setcovering) # degrees of freedom
3
julia> solution_size(setcovering, [1, 0, 1]) # size of a configuration
SolutionSize{Int64}(4, true)
julia> solution_size(setcovering, [0, 1, 1])
SolutionSize{Int64}(5, false)
julia> sc = set_weights(setcovering, [1, 2, 3]) # set the weights of the subsets
SetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])ProblemReductions.SetPacking — Typestruct SetPacking{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}SetPacking(elements::AbstractVector, sets::AbstractVector, weights::AbstractVector=UnitWeight(length(sets))) -> SetPacking
A packing is a set of sets where each set is pairwise disjoint from each other. The maximum (weighted) packing problem is to find the maximum packing for a given union and a set of subsets.
Fields
elementsis a vector of elements in the universe.setsis a vector of vectors, each set is associated with a weight specified inweights.weightsare associated with sets. Defaults toUnitWeight(length(sets)).
Example
In the following example, we define a set packing problem with five subsets. To define a SetPacking problem, we need to specify the set of subsets and possibily the weights associated with these subsets. The weights are set as unit by default in the current version and might be generalized to arbitrary positive weights in the following development. Besides, the elements would be automatically counted by the construction function.
julia> using ProblemReductions
julia> sets = [[1, 2, 5], [1, 3], [2, 4], [3, 6], [2, 3, 6]]
5-element Vector{Vector{Int64}}:
[1, 2, 5]
[1, 3]
[2, 4]
[3, 6]
[2, 3, 6]
julia> SP = SetPacking(sets)
SetPacking{Int64, Int64, UnitWeight}([1, 2, 5, 3, 4, 6], [[1, 2, 5], [1, 3], [2, 4], [3, 6], [2, 3, 6]], [1, 1, 1, 1, 1])
julia> num_variables(SP) # degrees of freedom
5
julia> flavors(SP) # flavors of the subsets
(0, 1)
julia> solution_size(SP, [1, 0, 0, 1, 0]) # Positive sample: -(size) of a packing
SolutionSize{Int64}(2, true)
julia> solution_size(SP, [1, 0, 1, 1, 0]) # Negative sample: 0
SolutionSize{Int64}(3, false)
julia> findbest(SP, BruteForce()) # solve the problem with brute force
3-element Vector{Vector{Int64}}:
[0, 1, 1, 0, 0]
[1, 0, 0, 1, 0]
[0, 0, 1, 1, 0]Constraint Satisfaction Problem Interfaces
Constraint satisfaction problems are defined by a set of constraints and objectives defined on a set of local variables.
GenericTensorNetworks.generate_tensors — Functiongenerate_tensors(func, problem::GenericTensorNetwork)Generate a vector of tensors as the inputs of the tensor network contraction code problem.code. func is a function to customize the tensors. func(symbol) returns a vector of elements, the length of which is same as the number of flavors.
Example
The following code gives your the maximum independent set size
julia> using Graphs, GenericTensorNetworks
julia> gp = GenericTensorNetwork(IndependentSet(smallgraph(:petersen)));
julia> getixsv(gp.code)
25-element Vector{Vector{Int64}}:
[1, 2]
[1, 5]
[1, 6]
[2, 3]
[2, 7]
[3, 4]
[3, 8]
[4, 5]
[4, 9]
[5, 10]
⋮
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
julia> gp.code(GenericTensorNetworks.generate_tensors(Tropical(1.0), gp)...)
0-dimensional Array{Tropical{Float64}, 0}:
4.0ₜProblemReductions.flavors — Functionflavors(::Type{<:AbstractProblem}) -> UnitRange
flavors(::GT) where GT<:AbstractProblem -> UnitRangeReturns a vector of integers as the flavors (domain) of a degree of freedom.
Flavors is defined a 0:num_flavors-1. To access the previous version of the flavors, use flavor_names.
flavors(::Type{<:GenericTensorNetwork}) -> VectorIt returns a vector of integers as the flavors of a degree of freedom. Its size is the same as the degree of freedom on a single vertex/edge.
ProblemReductions.weights — Functionweights(problem::ConstraintSatisfactionProblem) -> VectorThe weights of the constraints in the problem.
ProblemReductions.set_weights — Functionset_weights(problem::ConstraintSatisfactionProblem, weights) -> ConstraintSatisfactionProblemChange the weights for the problem and return a new problem instance.
ProblemReductions.is_weighted — Functionis_weighted(problem::ConstraintSatisfactionProblem) -> BoolCheck if the problem is weighted. Returns true if the problem has non-unit weights.
ProblemReductions.num_flavors — Functionnum_flavors(::Type{<:AbstractProblem}) -> Int
num_flavors(::GT) where GT<:AbstractProblem -> IntReturns the number of flavors (domain) of a degree of freedom.
num_flavors(::GenericTensorNetwork{GT}) where GT<:ConstraintSatisfactionProblem -> IntBond size is equal to the number of flavors.
ProblemReductions.num_variables — Functionnum_variables(problem::AbstractProblem) -> IntThe number of variables in the computational problem.
GenericTensorNetworks.fixedvertices — Functionfixedvertices(tnet::GenericTensorNetwork) -> DictReturns the fixed vertices in the graph problem, which is a dictionary specifying the fixed dimensions.
Constraint Satisfaction Problem Utilities
ProblemReductions.constraints — Functionconstraints(problem::AbstractProblem) -> Vector{LocalConstraint}The constraints of the problem.
ProblemReductions.objectives — Functionobjectives(problem::AbstractProblem) -> Vector{<:LocalSolutionSize}The constraints related to the size of the problem. Each term is associated with weights.
ProblemReductions.flavor_names — Functionflavor_names(::Type{<:AbstractProblem}) -> VectorReturns a vector as the names of the flavors (domain) of a degree of freedom. It falls back to flavors if no method is defined. Use ProblemReductions.name2config and ProblemReductions.config2name to convert between the names and the configuration.
ProblemReductions.is_satisfied — Functionis_satisfied(constraint::LocalConstraint, config) -> Bool
is_satisfied(problem::ConstraintSatisfactionProblem, config) -> BoolCheck if the constraint is satisfied by the configuration config.
ProblemReductions.solution_size — Functionsolution_size(spec::LocalSolutionSize{WT}, config) where {WT}The local solution size of a local solution configuration.
solution_size(problem::AbstractProblem, config) -> SolutionSizeSize of the problem given the configuration config. If you have multiple configurations, use ProblemReductions.solution_size_multiple instead for better performance.
ProblemReductions.energy_mode — Functionenergy_mode(problem::AbstractProblem) -> EnergyModeThe definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter. If will be used in the energy based modeling of the target problem.
ProblemReductions.LargerSizeIsBetter — TypeLargerSizeIsBetter <: EnergyModeThe energy is defined as the negative size of the solution, which is the larger size the lower energy.
ProblemReductions.SmallerSizeIsBetter — TypeSmallerSizeIsBetter <: EnergyModeThe energy is defined as the size of the solution, which is the smaller size the lower energy.
ProblemReductions.energy — Functionenergy(problem::AbstractProblem, config) -> NumberThe energy of the problem given the configuration config. Please check the energy_mode for the definition of the energy function.
ProblemReductions.is_independent_set — Functionis_independent_set(g::SimpleGraph, config)Return true if config (a vector of boolean numbers as the mask of vertices) is an independent set of graph g.
ProblemReductions.is_maximal_independent_set — Functionis_maximal_independent_set(g::SimpleGraph, config)Return true if config (a vector of boolean numbers as the mask of vertices) is a maximal independent set of graph g.
ProblemReductions.is_dominating_set — Functionis_dominating_set(g::SimpleGraph, config)Return true if config (a vector of boolean numbers as the mask of vertices) is a dominating set of graph g.
ProblemReductions.is_vertex_coloring — Functionis_vertex_coloring(graph::SimpleGraph, config)Returns true if the coloring specified by config is a valid one, i.e. does not violate the contraints of vertices of an edges having different colors.
ProblemReductions.is_matching — Functionis_matching(graph::SimpleGraph, config)Returns true if config is a valid matching on graph, and false if a vertex is double matched. config is a vector of boolean variables, which has one to one correspondence with edges(graph).
ProblemReductions.is_set_covering — Functionis_set_covering(c::SetCovering, config)Return true if config (a vector of boolean numbers as the mask of sets) is a set covering of sets.
ProblemReductions.is_set_packing — Functionis_set_packing(sp::SetPacking, config)Return true if config (a vector of boolean numbers as the mask of sets) is a set packing of sp.
ProblemReductions.cut_size — Functioncut_size(g::AbstractGraph, config; weights=UnitWeight(ne(g)))Return the size of the cut of the graph g with configuration config. The configuration is a vector of boolean numbers as the group indices of vertices. Edges between vertices in different groups are counted as a cut.
ProblemReductions.num_paint_shop_color_switch — Functionnum_paint_shop_color_switch(sequence::AbstractVector, coloring)Returns the number of color switches.
ProblemReductions.CNF — TypeCNF{T}
CNF(clauses)Boolean expression in conjunctive normal form. clauses is a vector of CNFClause, if and only if all clauses are satisfied, this CNF is satisfied.
Example
Under development
ProblemReductions.CNFClause — TypeCNFClause{T}
CNFClause(vars)A clause in CNF, its value is the logical or of vars, where vars is a vector of BoolVar.
ProblemReductions.BoolVar — TypeBoolVar{T}
BoolVar(name, neg)Boolean variable for constructing CNF clauses.
ProblemReductions.satisfiable — Functionsatisfiable(expr, config::AbstractDict{T}) where TCheck if the boolean expression expr is satisfied by the configuration config.
ProblemReductions.@bools — Macro@bools(syms::Symbol...)Create some boolean variables of type BoolVar in current scope that can be used in create a CNF.
Example
Under Development
ProblemReductions.:∨ — FunctionProblemReductions.:¬ — Function¬(var::BoolVar)Negation of a boolean variables of type BoolVar.
ProblemReductions.:∧ — FunctionGenericTensorNetworks.mis_compactify! — Functionmis_compactify!(tropicaltensor; potential=nothing)Compactify tropical tensor for maximum independent set problem. It will eliminate some entries by setting them to zero, by the criteria that removing these entry does not change the MIS size of its parent graph (reference to be added).
Arguments
tropicaltensor::AbstractArray{T}: the tropical tensor
Keyword arguments
potential=nothing: the maximum possible MIS contribution from each open vertex
Properties
GenericTensorNetworks.PartitionFunction — Typestruct PartitionFunction{T} <: GenericTensorNetworks.AbstractPropertybeta
Compute the partition function for the target problem.
- The corresponding tensor element type is
T.
GenericTensorNetworks.SizeMax — TypeSizeMax{K} <: AbstractProperty
SizeMax(k::Int)The maximum-K set sizes. e.g. the largest size of the IndependentSet problem is also know as the independence number.
- The corresponding tensor element type are max-plus tropical number
TropicalifKisSingleandExtendedTropicalifKis an integer. - It is compatible with weighted Constraint Satisfaction Problems.
- BLAS (on CPU) and GPU are supported only if
KisSingle,
GenericTensorNetworks.SizeMin — TypeSizeMin{K} <: AbstractProperty
SizeMin(k::Int)The minimum-K set sizes. e.g. the smallest size ofthe MaximalIS problem is also known as the independent domination number.
- The corresponding tensor element type are inverted max-plus tropical number
TropicalifKisSingleand invertedExtendedTropicalKis an integer.
The inverted Tropical number emulates the min-plus tropical number.
- It is compatible with weighted constraint satisfaction problems.
- BLAS (on CPU) and GPU are supported only if
KisSingle,
GenericTensorNetworks.CountingAll — TypeCountingAll <: AbstractProperty
CountingAll()Counting the total number of sets exactly without overflow. e.g. for the IndependentSet problem, it counts the independent sets. Note that PartitionFunction(0.0) also does the counting. It is more efficient, but uses floating point numbers, which does not have arbitrary precision.
- The corresponding tensor element type is
BigInt. - The weights on graph does not have effect.
- BLAS (GPU and CPU) and GPU are supported,
GenericTensorNetworks.CountingMax — TypeCountingMax{K} <: AbstractProperty
CountingMax(K=Single)Counting the number of sets with largest-K size. e.g. for IndependentSet problem, it counts independent sets of size $\alpha(G), \alpha(G)-1, \ldots, \alpha(G)-K+1$.
- The corresponding tensor element type is
CountingTropicalifKisSingle, andTruncatedPoly{K}ifKis an integer. - Weighted constraint satisfaction problems is only supported if
KisSingle. - GPU is supported,
GenericTensorNetworks.CountingMin — TypeCountingMin{K} <: AbstractProperty
CountingMin(K=Single)Counting the number of sets with smallest-K size.
- The corresponding tensor element type is inverted
CountingTropicalifKisSingle, andTruncatedPoly{K}ifKis an integer. - Weighted constraint satisfaction problems is only supported if
KisSingle. - GPU is supported,
GenericTensorNetworks.GraphPolynomial — TypeGraphPolynomial{METHOD} <: AbstractProperty
GraphPolynomial(; method=:finitefield, kwargs...)Compute the graph polynomial, e.g. for IndependentSet problem, it is the independence polynomial. The METHOD type parameter can be one of the following symbols
Method Argument
:finitefield, uses finite field algebra to fit the polynomial.- The corresponding tensor element type is
Mods.Mod, - It does not have round-off error,
- GPU is supported,
- It accepts keyword arguments
maxorder(optional, e.g. the MIS size in theIndependentSetproblem).
- The corresponding tensor element type is
:polynomialand:laurent, use (Laurent) polynomial numbers to solve the polynomial directly.- The corresponding tensor element types are
PolynomialandLaurentPolynomial. - It might have small round-off error depending on the data type for storing the counting.
- It has memory overhead that linear to the graph size.
- The corresponding tensor element types are
:fft, use fast fourier transformation to fit the polynomial.- The corresponding tensor element type is
Base.Complex. - It has (controllable) round-off error.
- BLAS and GPU are supported.
- It accepts keyword arguments
maxorder(optional) andr, ifr > 1, one has better precision for coefficients of large order, ifr < 1, one has better precision for coefficients of small order.
- The corresponding tensor element type is
:fitting, fit the polynomial directly.- The corresponding tensor element type is floating point numbers like
Base.Float64. - It has round-off error.
- BLAS and GPU are supported, it is the fastest among all methods.
- The corresponding tensor element type is floating point numbers like
Graph polynomials are not defined for weighted constraint satisfaction problems.
GenericTensorNetworks.SingleConfigMax — TypeSingleConfigMax{K, BOUNDED} <: AbstractProperty
SingleConfigMax(k::Int; bounded=false)Finding single solution for largest-K sizes, e.g. for IndependentSet problem, it is one of the maximum independent sets.
- The corresponding data type is
CountingTropical{Float64,<:ConfigSampler}ifBOUNDEDisfalse,Tropicalotherwise. - Weighted constraint satisfaction problems is supported.
- GPU is supported,
Keyword Arguments
bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
GenericTensorNetworks.SingleConfigMin — TypeSingleConfigMin{K, BOUNDED} <: AbstractProperty
SingleConfigMin(k::Int; bounded=false)Finding single solution with smallest-K size.
- The corresponding data type is inverted
CountingTropical{Float64,<:ConfigSampler}ifBOUNDEDisfalse, invertedTropicalotherwise. - Weighted constraint satisfaction problems is supported.
- GPU is supported,
Keyword Arguments
bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
GenericTensorNetworks.ConfigsAll — TypeConfigsAll{TREESTORAGE} <:AbstractProperty
ConfigsAll(; tree_storage=false)Find all valid configurations, e.g. for IndependentSet problem, it is finding all independent sets.
- The corresponding data type is
ConfigEnumerator. - Weights do not take effect.
Keyword Arguments
tree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.
GenericTensorNetworks.ConfigsMax — TypeConfigsMax{K, BOUNDED, TREESTORAGE} <:AbstractProperty
ConfigsMax(K=Single; bounded=true, tree_storage=true)Find configurations with largest-K sizes, e.g. for IndependentSet problem, it is finding all independent sets of sizes $\alpha(G), \alpha(G)-1, \ldots, \alpha(G)-K+1$.
- The corresponding data type is
CountingTropical{Float64,<:ConfigEnumerator}ifKisSingleandTruncatedPoly{K,<:ConfigEnumerator}ifKis an integer. - Weighted constraint satisfaction problem is only supported if
KisSingle.
Keyword Arguments
bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.tree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.
GenericTensorNetworks.ConfigsMin — TypeConfigsMin{K, BOUNDED, TREESTORAGE} <:AbstractProperty
ConfigsMin(K=Single; bounded=true, tree_storage=false)Find configurations with smallest-K sizes.
- The corresponding data type is inverted
CountingTropical{Float64,<:ConfigEnumerator}ifKisSingleand invertedTruncatedPoly{K,<:ConfigEnumerator}ifKis an integer. - Weighted constraint satisfaction problem is only supported if
KisSingle.
Keyword Arguments
bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.tree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.
Element Algebras
GenericTensorNetworks.is_commutative_semiring — Functionis_commutative_semiring(a::T, b::T, c::T) where TCheck if elements a, b and c satisfied the commutative semiring requirements.
\[\begin{align*} (a \oplus b) \oplus c = a \oplus (b \oplus c) & \hspace{5em}\triangleright\text{commutative monoid $\oplus$ with identity $\mathbb{0}$}\\ a \oplus \mathbb{0} = \mathbb{0} \oplus a = a &\\ a \oplus b = b \oplus a &\\ &\\ (a \odot b) \odot c = a \odot (b \odot c) & \hspace{5em}\triangleright \text{commutative monoid $\odot$ with identity $\mathbb{1}$}\\ a \odot \mathbb{1} = \mathbb{1} \odot a = a &\\ a \odot b = b \odot a &\\ &\\ a \odot (b\oplus c) = a\odot b \oplus a\odot c & \hspace{5em}\triangleright \text{left and right distributive}\\ (a\oplus b) \odot c = a\odot c \oplus b\odot c &\\ &\\ a \odot \mathbb{0} = \mathbb{0} \odot a = \mathbb{0} \end{align*}\]
TropicalNumbers.Tropical — TypeTropicalMaxPlus{T} = Tropical{T} <: AbstractSemiringTropicalMaxPlus is a semiring algebra, can be described by
- Tropical (TropicalMaxPlus), (ℝ, max, +, -Inf, 0).
It maps
+tomaxin regular algebra,*to+in regular algebra,1to0in regular algebra,0to-Infin regular algebra (for integer content types, this is chosen as a small integer).
Example
julia> TropicalMaxPlus(1.0) + TropicalMaxPlus(3.0)
3.0ₜ
julia> TropicalMaxPlus(1.0) * TropicalMaxPlus(3.0)
4.0ₜ
julia> one(TropicalMaxPlusF64)
0.0ₜ
julia> zero(TropicalMaxPlusF64)
-InfₜTropicalNumbers.CountingTropical — TypeCountingTropical{T,CT} <: NumberCounting tropical number type is also a semiring algebra. It is tropical algebra with one extra field for counting, it is introduced in arXiv:2008.06888.
Example
julia> CountingTropical(1.0, 5.0) + CountingTropical(3.0, 2.0)
(3.0, 2.0)ₜ
julia> CountingTropical(1.0, 5.0) * CountingTropical(3.0, 2.0)
(4.0, 10.0)ₜ
julia> one(CountingTropicalF64)
(0.0, 1.0)ₜ
julia> zero(CountingTropicalF64)
(-Inf, 0.0)ₜGenericTensorNetworks.ExtendedTropical — TypeExtendedTropical{K,TO} <: Number
ExtendedTropical{K}(orders)Extended Tropical numbers with largest K orders keeped, or the TruncatedPoly without coefficients, TO is the element type of orders, usually Tropical numbers. This algebra maps
+to finding largestKvalues of union of two sets.*to finding largestKvalues of sum combination of two sets.0to set [-Inf, -Inf, ..., -Inf, -Inf]1to set [-Inf, -Inf, ..., -Inf, 0]
Fields
ordersis a vector ofTropical(CountingTropical) numbers as the largest-K solution sizes (solutions).
Examples
julia> x = ExtendedTropical{3}(Tropical.([1.0, 2, 3]))
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[1.0ₜ, 2.0ₜ, 3.0ₜ])
julia> y = ExtendedTropical{3}(Tropical.([-Inf, 2, 5]))
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, 2.0ₜ, 5.0ₜ])
julia> x * y
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[6.0ₜ, 7.0ₜ, 8.0ₜ])
julia> x + y
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[2.0ₜ, 3.0ₜ, 5.0ₜ])
julia> one(x)
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, 0.0ₜ])
julia> zero(x)
ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, -Infₜ])GenericTensorNetworks.Mods.Mod — TypeMod{m}(v) creates a modular number in mod m with value mod(v,m).
GenericTensorNetworks.TruncatedPoly — TypeTruncatedPoly{K,T,TO} <: Number
TruncatedPoly(coeffs::Tuple, maxorder)Polynomial truncated to largest K orders. T is the coefficients type and TO is the orders type.
Fields
coeffsis the largest-K coefficients of a polynomial. InGenericTensorNetworks, it can be the counting or enumeration of solutions.maxorderis the order of a polynomial.
Examples
julia> TruncatedPoly((1,2,3), 6)
x⁴ + 2*x⁵ + 3*x⁶
julia> TruncatedPoly((1,2,3), 6) * TruncatedPoly((5,2,1), 3)
20*x⁷ + 8*x⁸ + 3*x⁹
julia> TruncatedPoly((1,2,3), 6) + TruncatedPoly((5,2,1), 3)
x⁴ + 2*x⁵ + 3*x⁶GenericTensorNetworks.Max2Poly — TypeMax2Poly{T,TO} = TruncatedPoly{2,T,TO}
Max2Poly(a, b, maxorder)A shorthand of TruncatedPoly{2}.
GenericTensorNetworks.ConfigEnumerator — TypeConfigEnumerator{N,S,C} <: AbstractSetNumberSet algebra for enumerating configurations, where N is the length of configurations, C is the size of storage in unit of UInt64, S is the bit width to store a single element in a configuration, i.e. log2(# of flavors), for bitstrings, it is 1`.
Fields
datais a vector ofStaticElementVectoras the solution set.
Examples
julia> a = ConfigEnumerator([StaticBitVector([1,1,1,0,0]), StaticBitVector([1,0,0,0,1])])
{11100, 10001}
julia> b = ConfigEnumerator([StaticBitVector([0,0,0,0,0]), StaticBitVector([1,0,1,0,1])])
{00000, 10101}
julia> a + b
{11100, 10001, 00000, 10101}
julia> one(a)
{00000}
julia> zero(a)
{}GenericTensorNetworks.SumProductTree — TypeSumProductTree{ET} <: AbstractSetNumberConfiguration enumerator encoded in a tree, it is the most natural representation given by a sum-product network and is often more memory efficient than putting the configurations in a vector. One can use generate_samples to sample configurations from this tree structure efficiently.
Fields
tagis one ofZERO,ONE,LEAF,SUM,PROD.datais the element stored in aLEAFnode.leftandrightare two operands of aSUMorPRODnode.
Examples
julia> s = SumProductTree(bv"00111")
00111
julia> q = SumProductTree(bv"10000")
10000
julia> x = s + q
+ (count = 2.0)
├─ 00111
└─ 10000
julia> y = x * x
* (count = 4.0)
├─ + (count = 2.0)
│ ├─ 00111
│ └─ 10000
└─ + (count = 2.0)
├─ 00111
└─ 10000
julia> collect(y)
4-element Vector{StaticBitVector{5, 1}}:
00111
10111
10111
10000
julia> zero(s)
∅
julia> one(s)
00000
GenericTensorNetworks.ConfigSampler — TypeConfigSampler{N,S,C} <: AbstractSetNumber
ConfigSampler(elements::StaticElementVector)The algebra for sampling one configuration, where N is the length of configurations, C is the size of storage in unit of UInt64, S is the bit width to store a single element in a configuration, i.e. log2(# of flavors), for bitstrings, it is 1`.
ConfigSampler is a probabilistic commutative semiring, adding two config samplers do not give you deterministic results.
Fields
datais aStaticElementVectoras the sampled solution.
Examples
julia> ConfigSampler(StaticBitVector([1,1,1,0,0]))
ConfigSampler{5, 1, 1}(11100)
julia> ConfigSampler(StaticBitVector([1,1,1,0,0])) + ConfigSampler(StaticBitVector([1,0,1,0,0]))
ConfigSampler{5, 1, 1}(10100)
julia> ConfigSampler(StaticBitVector([1,1,1,0,0])) * ConfigSampler(StaticBitVector([0,0,0,0,1]))
ConfigSampler{5, 1, 1}(11101)
julia> one(ConfigSampler{5, 1, 1})
ConfigSampler{5, 1, 1}(00000)
julia> zero(ConfigSampler{5, 1, 1})
ConfigSampler{5, 1, 1}(11111)Extra types include the Polynomial and LaurentPolynomial types defined in package Polynomials.
For reading the properties from the above element types, one can use the following functions.
GenericTensorNetworks.read_size — Functionread_size(x)Read the size information from the generic element.
GenericTensorNetworks.read_count — Functionread_count(x)Read the counting information from the generic element.
GenericTensorNetworks.read_config — Functionread_config(x; keeptree=false)Read the configuration information from the generic element, if keeptree=true, the tree structure will not be flattened.
GenericTensorNetworks.read_size_count — Functionread_size_count(x)Read the size and counting information from the generic element.
GenericTensorNetworks.read_size_config — Functionread_size_config(x; keeptree=false)Read the size and configuration information from the generic element. If keeptree=true, the tree structure will not be flattened.
The following functions are for saving and loading configurations.
ProblemReductions.StaticBitVector — TypeStaticBitVector{N,C} = StaticElementVector{N,1,C}
StaticBitVector(x::AbstractVector)Examples
julia> sb = StaticBitVector([1,0,0,1,1])
10011
julia> sb[3]
0x0000000000000000
julia> collect(Int, sb)
5-element Vector{Int64}:
1
0
0
1
1ProblemReductions.StaticElementVector — TypeStaticElementVector{N,S,C}
StaticElementVector(nflavor::Int, x::AbstractVector)N is the length of vector, C is the size of storage in unit of UInt64, S is the stride defined as the log2(# of flavors). When the number of flavors is 2, it is a StaticBitVector.
Fields
datais a tuple ofUInt64for storing the configuration of static elements.
Examples
julia> ev = StaticElementVector(3, [1,2,0,1,2])
12012
julia> ev[2]
0x0000000000000002
julia> collect(Int, ev)
5-element Vector{Int64}:
1
2
0
1
2GenericTensorNetworks.OnehotVec — TypeOnehotVec{N,NF}
OnehotVec{N,NF}(loc, val)Onehot vector type, N is the number of vector length, NF is the number of flavors.
GenericTensorNetworks.save_configs — Functionsave_configs(filename, data::ConfigEnumerator; format=:binary)Save configurations data to file filename. The format is :binary or :text.
GenericTensorNetworks.load_configs — Functionload_configs(filename; format=:binary, bitlength=nothing, num_flavors=2)Load configurations from file filename. The format is :binary or :text. If the format is :binary, the bitstring length bitlength must be specified, num_flavors specifies the degree of freedom.
GenericTensorNetworks.save_sumproduct — Functionsave_sumproduct(filename, t::SumProductTree)Serialize a sum-product tree into a file.
GenericTensorNetworks.load_sumproduct — Functionload_sumproduct(filename)Deserialize a sum-product tree from a file.
ProblemReductions.@bv_str — MacroConstructing a static bit vector.
ProblemReductions.onehotv — Functiononehotv(::Type{<:StaticElementVector}, i, v)
onehotv(::Type{<:StaticBitVector}, i)Returns a static element vector, with the value at location i being v (1 if not specified).
GenericTensorNetworks.generate_samples — Functiongenerate_samples(t::SumProductTree, nsamples::Int)Direct sampling configurations from a SumProductTree instance.
Examples
julia> using Graphs
julia> g= smallgraph(:petersen)
{10, 15} undirected simple Int64 graph
julia> t = solve(GenericTensorNetwork(IndependentSet(g)), ConfigsAll(; tree_storage=true))[];
julia> samples = generate_samples(t, 1000);
julia> all(s->is_independent_set(g, s), samples)
trueGenericTensorNetworks.hamming_distribution — Functionhamming_distribution(S, T)Compute the distribution of pair-wise Hamming distances, which is defined as:
\[c(k) := \sum_{\sigma\in S, \tau\in T} \delta({\rm dist}(\sigma, \tau), k)\]
where $\delta$ is a function that returns 1 if two arguments are equivalent, 0 otherwise, ${\rm dist}$ is the Hamming distance function.
Returns the counting as a vector.
Tensor Network
OMEinsumContractionOrders.optimize_code — Functionoptimize_code(eincode, size_dict, optimizer = GreedyMethod(); slicer=nothing, simplifier=nothing, permute=true) -> optimized_eincodeOptimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum instance. Input arguments are
Arguments
eincodeis an einsum contraction code instance, one ofDynamicEinCode,StaticEinCodeorNestedEinsum.sizeis a dictionary of "edge label=>edge size" that contains the size information, one can useuniformsize(eincode, 2)to create a uniform size.optimizeris aCodeOptimizerinstance, should be one ofGreedyMethod,Treewidth,KaHyParBipartite,SABipartiteorTreeSA. Check their docstrings for details.
Keyword Arguments
sliceris for slicing the contraction code to reduce the space complexity, default is nothing. Currently onlyTreeSASliceris supported.simplifieris one ofMergeVectorsorMergeGreedy. Default is nothing.permuteis a boolean flag to indicate whether to optimize the permutation of the contraction order.
Examples
julia> using OMEinsum
julia> code = ein"ij, jk, kl, il->"
ij, jk, kl, il ->
julia> optimize_code(code, uniformsize(code, 2), TreeSA());OMEinsum.getixsv — Functiongetixsv(code)Get labels of input tensors for EinCode, NestedEinsum and some other einsum like objects. Returns a vector of vectors.
julia> getixsv(ein"(ij,jk),k->i")
3-element Vector{Vector{Char}}:
['i', 'j']
['j', 'k']
['k']OMEinsum.getiyv — Functiongetiy(code)Get labels of the output tensor for EinCode, NestedEinsum and some other einsum like objects. Returns a vector.
julia> getiyv(ein"(ij,jk),k->i")
1-element Vector{Char}:
'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)OMEinsumContractionOrders.contraction_complexity — Functioncontraction_complexity(eincode, size_dict) -> ContractionComplexityReturns the time, space and read-write complexity of the einsum contraction. The returned ContractionComplexity object contains 3 fields:
tc: time complexity defined aslog2(number of element-wise multiplications).sc: space complexity defined aslog2(size of the maximum intermediate tensor).rwc: read-write complexity defined aslog2(the number of read-write operations).
GenericTensorNetworks.estimate_memory — Functionestimate_memory(
problem::GenericTensorNetwork,
property::GenericTensorNetworks.AbstractProperty;
T
) -> Any
Memory estimation in number of bytes to compute certain property of a problem. T is the base type.
OMEinsum.@ein_str — Macroein"ij,jk -> ik"(A,B)String macro interface which understands numpy.einsum's notation. Translates strings into StaticEinCode-structs that can be called to evaluate an einsum. To control evaluation order, use parentheses - instead of an EinCode, a NestedEinsum is returned which evaluates the expression according to parens. The valid character ranges for index-labels are a-z and α-ω.
example
julia> a, b, c = rand(10,10), rand(10,10), rand(10,1);
julia> ein"ij,jk,kl -> il"(a,b,c) ≈ ein"(ij,jk),kl -> il"(a,b,c) ≈ a * b * c
trueOMEinsumContractionOrders.GreedyMethod — TypeGreedyMethod{MT}
GreedyMethod(; α = 0.0, temperature = 0.0)It may not be optimal, but it is fast.
Fields
αis the parameter for the loss function, for pairwise interaction, L = size(out) - α * (size(in1) + size(in2))temperatureis the parameter for sampling, if it is zero, the minimum loss is selected; for non-zero, the loss is selected by the Boltzmann distribution, given by p ~ exp(-loss/temperature).
OMEinsumContractionOrders.TreeSA — TypeTreeSA{IT} <: CodeOptimizer
TreeSA(; βs=collect(0.01:0.05:15), ntrials=10, niters=50, initializer=:greedy, score=ScoreFunction())Optimize the einsum contraction pattern using the simulated annealing on tensor expression tree.
Fields
ntrials,βsandnitersare annealing parameters, doingntrialsindepedent annealings, each has inverse tempteratures specified byβs, in each temperature, donitersupdates of the tree.initializerspecifies how to determine the initial configuration, it can be:greedy,:randomor:specified. If the initializer is:specified, the inputcodeshould be aNestedEinsumobject.scorespecifies the score function to evaluate the quality of the contraction tree, it is a function of time complexity, space complexity and read-write complexity.
References
Breaking changes:
nslicesis removed, since the slicing part is now separated from the optimization part, seeslice_codefunction andTreeSASlicer.greedy_methodis removed. If you want to have detailed control of the initializer, please pre-optimize the code with another method and then use:specifiedto initialize the tree.
OMEinsumContractionOrders.SABipartite — TypeSABipartite{RT,BT}
SABipartite(; sc_target=25, ntrials=50, βs=0.1:0.2:15.0, niters=1000
max_group_size=40, greedy_config=GreedyMethod(), initializer=:random)Optimize the einsum code contraction order using the Simulated Annealing bipartition + Greedy approach. This program first recursively cuts the tensors into several groups using simulated annealing, with maximum group size specifed by max_group_size and maximum space complexity specified by sc_target, Then finds the contraction order inside each group with the greedy search algorithm. Other arguments are
Fields
sc_targetis the target space complexity, defined aslog2(number of elements in the largest tensor),ntrialsis the number of repetition (with different random seeds),βsis a list of inverse temperature1/T,nitersis the number of iteration in each temperature,max_group_sizeis the maximum size that allowed to used greedy search,sub_optimizeris the optimizer for the bipartited sub graphs, one can chooseGreedyMethod()orTreeSA(),initializeris the partition configuration initializer, one can choose:randomor:greedy(slow but better).
References
OMEinsumContractionOrders.KaHyParBipartite — TypeKaHyParBipartite{RT,IT,GM}
KaHyParBipartite(; sc_target, imbalances=collect(0.0:0.005:0.8),
max_group_size=40, greedy_config=GreedyMethod())Optimize the einsum code contraction order using the KaHyPar + Greedy approach. This program first recursively cuts the tensors into several groups using KaHyPar, with maximum group size specifed by max_group_size and maximum space complexity specified by sc_target, Then finds the contraction order inside each group with the greedy search algorithm. Other arguments are
Fields
sc_targetis the target space complexity, defined aslog2(number of elements in the largest tensor),imbalancesis a KaHyPar parameter that controls the group sizes in hierarchical bipartition,max_group_sizeis the maximum size that allowed to used greedy search,sub_optimizeris the sub-optimizer used to find the contraction order when the group size is small enough.
References
OMEinsumContractionOrders.MergeVectors — TypeMergeVectors <: CodeSimplifier
MergeVectors()Contraction code simplifier (in order to reduce the time of calling optimizers) that merges vectors to closest tensors.
OMEinsumContractionOrders.MergeGreedy — TypeMergeGreedy <: CodeSimplifier
MergeGreedy(; threshhold=-1e-12)Contraction code simplifier (in order to reduce the time of calling optimizers) that merges tensors greedily if the space complexity of merged tensors is reduced (difference smaller than the threshhold).
OMEinsumContractionOrders.TreeSASlicer — TypeTreeSASlicer{IT, LT} <: CodeSlicerA structure for configuring the Tree Simulated Annealing (TreeSA) slicing algorithm. The goal of slicing is to reach the target space complexity specified by score.sc_target.
Fields
ntrials,βsandnitersare annealing parameters, doingntrialsindepedent annealings, each has inverse tempteratures specified byβs, in each temperature, donitersupdates of the tree.fixed_slices::Vector{LT}: A vector of fixed slices that should not be altered. Default is an empty vector.optimization_ratio::Float64: A constant used for determining the number of iterations for slicing. Default is 2.0. i.e. if the current space complexity is 30, and the target space complexity is 20, then the number of iterations for slicing is (30 - 20) xoptimization_ratio.score::ScoreFunction: A function to evaluate the quality of the contraction tree. Default isScoreFunction(sc_target=30.0).
References
OMEinsumContractionOrders.ScoreFunction — TypeScoreFunctionA function to compute the score of a contraction code:
score = tc_weight * 2^tc + rw_weight * 2^rw + sc_weight * max(0, 2^sc - 2^sc_target)Fields
tc_weight: the weight of the time complexity, default is 1.0.sc_weight: the weight of the space complexity (the size of the largest tensor), default is 1.0.rw_weight: the weight of the read-write complexity, default is 0.0.sc_target: the target space complexity, below which thesc_weightwill be set to 0 automatically, default is 0.0.
FileIO
GenericTensorNetworks.save_tensor_network — Functionsave_tensor_network(tn::GenericTensorNetwork; folder::String)Serialize a tensor network to disk for storage/reloading. Creates three structured files:
code.json: OMEinsum contraction code (tree structure and contraction order)fixedvertices.json: JSON-serialized Dict of pinned vertex configurationsproblem.json: Problem specification using ProblemReductions serialization
The target folder will be created recursively if it doesn't exist. Files are overwritten if they already exist. Uses JSON for human-readable serialization with type preservation.
The saved files can be loaded using load_tensor_network.
Arguments
tn::GenericTensorNetwork: aGenericTensorNetworkinstance to serialize. Must contain valid code, problem, and fixedvertices fields.folder::String: Destination directory path. Parent directories will be created as needed.
GenericTensorNetworks.load_tensor_network — Functionload_tensor_network(folder::String) -> GenericTensorNetworkLoad a tensor network from disk that was previously saved using save_tensor_network. Reconstructs the network from three required files: contraction code, fixed vertices mapping, and problem specification.
Arguments
folder::String: Path to directory containing saved network files. Must contain:code.json: Contraction order/structure from OMEinsumfixedvertices.json: Dictionary of pinned vertex statesproblem.json: Problem specification and parameters
Returns
GenericTensorNetwork: Reconstructed tensor network.
Others
Graph
Except the SimpleGraph defined in Graphs, GenericTensorNetworks also defines the following graph types and functions.
ProblemReductions.HyperGraph — Typestruct HyperGraph <: Graphs.AbstractGraph{Int64}A hypergraph is a generalization of a graph in which an edge can connect any number of vertices.
Fields
n::Int: the number of verticesedges::Vector{Vector{Int}}: a vector of vectors of integers, where each vector represents a hyperedge connecting the vertices with the corresponding indices.
ProblemReductions.UnitDiskGraph — Typestruct UnitDiskGraph{D, T} <: Graphs.AbstractGraph{Int64}A unit disk graph is a graph in which the vertices are points in a plane and two vertices are connected by an edge if and only if the Euclidean distance between them is at most a given radius.
Fields
locations::Vector{NTuple{D, T}}: the locations of the verticesradius::Float64: the radius of the unit disk
LuxorGraphPlot.show_graph — Functionshow_graph([f, ]graph::AbstractGraph;
kwargs...
)Show a graph in VSCode, Pluto or Jupyter notebook, or save it to a file.
Positional arguments
fis a function that returns extraLuxorplotting statements.graphis a graph instance.locsis a vector of tuples for specifying the vertex locations, or aAbstractLayoutinstance.
Keyword arguments
configis aGraphDisplayConfiginstance.vertex_colorsis a vector of color strings for specifying vertex fill colors.vertex_sizesis a vector of real numbers for specifying vertex sizes.vertex_shapesis a vector of strings for specifying vertex shapes, the string should be "circle" or "box".vertex_stroke_colorsis a vector of color strings for specifying vertex stroke colors.vertex_text_colorsis a vector of color strings for specifying vertex text colors.edge_colorsis a vector of color strings for specifying edge colors.textsis a vector of strings for labeling vertices.
padding_left::Int = 10, the padding on the left side of the drawingpadding_right::Int = 10, the padding on the right side of the drawingpadding_top::Int = 10, the padding on the top side of the drawingpadding_bottom::Int = 10, the padding on the bottom side of the drawingformatis the output format, which can be:svg,:pngor:pdf.filenameis a string as the output filename.
Example
julia> using Graphs, LuxorGraphPlot
julia> show_graph(smallgraph(:petersen); format=:png, vertex_colors=rand(["blue", "red"], 10));GenericTensorNetworks.show_configs — Functionshow_configs(gp::ConstraintSatisfactionProblem, locs, configs::AbstractMatrix; kwargs...)
show_configs(graph::SimpleGraph, locs, configs::AbstractMatrix; num_flavors=2, kwargs...)Show a gallery of configurations on a graph.
GenericTensorNetworks.show_einsum — Functionshow_einsum(ein::AbstractEinsum;
tensor_locs=nothing,
label_locs=nothing, # dict
spring::Bool=true,
optimal_distance=25.0,
tensor_size=15,
tensor_color="black",
tensor_text_color="white",
annotate_tensors=false,
label_size=7,
label_color="black",
open_label_color="black",
annotate_labels=true,
kwargs...
)Positional arguments
einis an Einsum contraction code (provided by packageOMEinsum).
Keyword arguments
locsis a tuple oftensor_locs(vector) andlabel_locs(dict).springis switch to use spring method to optimize the location.optimal_distanceis a optimal distance parameter forspringoptimizer.tensor_coloris a string to specify the color of tensor nodes.tensor_sizeis a real number to specify the size of tensor nodes.tensor_text_coloris a color strings to specify tensor text color.annotate_tensorsis a boolean switch for annotate different tensors by integers.label_sizeis a real number to specify label text node size.label_coloris a color strings to specify label text color.open_label_coloris a color strings to specify open label text color.annotate_labelsis a boolean switch for annotate different labels.formatis the output format, which can be:svg,:pngor:pdf.filenameis a string as the output filename.
fontsize::Float64 = 12.0, the font sizefontface::String = "", the font face, leave empty to follow systemvertex_text_color = "black", the default text colorvertex_stroke_color = "black", the default stroke color for verticesvertex_color = "transparent", the default default fill color for verticesvertex_size::Float64 = 10.0, the default vertex sizevertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dotvertex_line_width::Float64 = 1, the default vertex stroke line widthvertex_line_style::String = "solid", the line style of vertex stroke, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]edge_color = "black", the default edge coloredge_line_width::Float64 = 1, the default line widthedge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]
GenericTensorNetworks.show_landscape — Functionshow_landscape(is_neighbor, configurations::TruncatedPoly;
layer_distance=200,
config=GraphDisplayConfig(; edge_color="gray", vertex_stroke_color="transparent", vertex_size=5),
layout_method=:spring,
optimal_distance=30.0,
colors=fill("green", K),
kwargs...)Show the energy landscape of configurations.
Arguments
is_neighbor: a function to determine if two configurations are neighbors.configurations: a TruncatedPoly object, which is the default output of thesolvefunction withConfigsMaxproperty as the argument.
Keyword arguments
layer_distance: the distance between layers.config: aLuxorGraphPlot.GraphDisplayConfigobject.layout_method: the layout method, either:spring,:stressor:spectraloptimal_distance: the optimal distance for the layout.colors: a vector of colors for each layer.kwargs...: other keyword arguments passed toshow_graph.
LuxorGraphPlot.GraphDisplayConfig — TypeGraphDisplayConfigThe configuration for graph display.
Keyword arguments
locsis a vector of tuples for specifying the vertex locations.edgesis a vector of tuples for specifying the edges.fontsize::Float64 = 12.0, the font sizefontface::String = "", the font face, leave empty to follow systemvertex_text_color = "black", the default text colorvertex_stroke_color = "black", the default stroke color for verticesvertex_color = "transparent", the default default fill color for verticesvertex_size::Float64 = 10.0, the default vertex sizevertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dotvertex_line_width::Float64 = 1, the default vertex stroke line widthvertex_line_style::String = "solid", the line style of vertex stroke, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]edge_color = "black", the default edge coloredge_line_width::Float64 = 1, the default line widthedge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]
LuxorGraphPlot.Layouts.AbstractLayout — TypeAbstractLayoutAbstract type for layout algorithms.
LuxorGraphPlot.Layouts.SpringLayout — TypeSpringLayout <: AbstractLayoutA layout algorithm based on a spring model.
Fields
optimal_distance::Float64: the optimal distance between verticesmaxiter::Int: the maximum number of iterationsα0::Float64: the initial moving speedmeta::Dict{Symbol, Any}: graph dependent meta information, includinginitial_locs: initial vertex locationsmask: boolean mask for which vertices to relocate
LuxorGraphPlot.Layouts.StressLayout — TypeStressLayout <: AbstractLayoutA layout algorithm based on stress majorization.
Fields
optimal_distance::Float64: the optimal distance between verticesmaxiter::Int: the maximum number of iterationsrtol::Float64: the absolute toleranceinitial_locs: initial vertex locationsmask: boolean mask for which vertices to relocatemeta::Dict{Symbol, Any}: graph dependent meta information, includinginitial_locs: initial vertex locationsmask: boolean mask for which vertices to relocate
LuxorGraphPlot.Layouts.SpectralLayout — TypeSpectralLayout <: AbstractLayoutA layout algorithm based on spectral graph theory.
Fields
optimal_distance::Float64: the optimal distance between verticesdimension::Int: the number of dimensions
LuxorGraphPlot.Layouts.Layered — TypeLayered <: AbstractLayoutLayered version of a parent layout algorithm.
Fields
parent::LT: the parent layout algorithmzlocs::Vector{T}: the z-axis locationsaspect_ratio::Float64: the aspect ratio of the z-axis
LuxorGraphPlot.Layouts.LayeredSpringLayout — FunctionLayeredSpringLayout(; zlocs, optimal_distance, aspect_ration=0.2)Create a layered spring layout.
Keyword Arguments
zlocs: the z-axis locationsoptimal_distance::Float64: the optimal distance between verticesaspect_ration::Float64: the aspect ratio of the z-axisα0::Float64: the initial moving speedmaxiter::Int: the maximum number of iterations
LuxorGraphPlot.Layouts.LayeredStressLayout — FunctionLayeredStressLayout(; zlocs, optimal_distance, aspect_ration=0.2)Create a layered stress layout.
Keyword Arguments
zlocs: the z-axis locationsoptimal_distance::Float64: the optimal distance between verticesaspect_ration::Float64: the aspect ratio of the z-axismaxiter::Int: the maximum number of iterationsrtol::Float64: the absolute tolerance
LuxorGraphPlot.Layouts.render_locs — Functionrender_locs(graph, layout::Layout)Render the vertex locations for a graph from an AbstractLayout instance.
Arguments
graph::AbstractGraph: the graph to renderlayout::AbstractLayout: the layout algorithm
GenericTensorNetworks.diagonal_coupled_graph — Functiondiagonal_coupled_graph(mask::AbstractMatrix{Bool})Create a masked diagonal coupled square lattice graph from a specified mask.
GenericTensorNetworks.square_lattice_graph — Functionsquare_lattice_graph(mask::AbstractMatrix{Bool})Create a masked square lattice graph.
GenericTensorNetworks.line_graph — Functionline_graph(g::SimpleGraph)Returns the line graph of g. The line graph is generated by mapping an edge to a vertex and two edges sharing a common vertex will be connected.
GenericTensorNetworks.random_diagonal_coupled_graph — Functionrandom_diagonal_coupled_graph(m::Int, n::Int, ρ::Real)Create a $m\times n$ random masked diagonal coupled square lattice graph, with number of vertices equal to $\lfloor m \times n\times \rho \rceil$.
GenericTensorNetworks.random_square_lattice_graph — Functionrandom_square_lattice_graph(m::Int, n::Int, ρ::Real)Create a random masked square lattice graph, with number of vertices fixed to $\lfloor mn\rho \rceil$.
Multiprocessing
GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run — Functionmultiprocess_run(func, inputs::AbstractVector)Execute function func on inputs with multiple processing.
Example
Suppose we have a file run.jl with the following contents
using GenericTensorNetworks.SimpleMultiprocessing
results = multiprocess_run(x->x^2, randn(8))In an terminal, you may run the script with 4 processes by typing
$ julia -p4 run.jl
From worker 2: [ Info: running argument -0.17544008350172655 on device 2
From worker 5: [ Info: running argument 0.34578117779452555 on device 5
From worker 3: [ Info: running argument 2.0312551239727705 on device 3
From worker 4: [ Info: running argument -0.7319353419291961 on device 4
From worker 2: [ Info: running argument 0.013132180639054629 on device 2
From worker 3: [ Info: running argument 0.9960101782201602 on device 3
From worker 4: [ Info: running argument -0.5613942832743966 on device 4
From worker 5: [ Info: running argument 0.39460402723831134 on device 5