From c054d08051fb25d017a7305d8d1838ecd11ab91a Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sun, 15 Dec 2024 09:27:30 +0000 Subject: [PATCH] build based on 4759afb --- dev/.documenter-siteinfo.json | 2 +- dev/generated/Coloring/index.html | 12 +- .../{2562107b.svg => 806e81b1.svg} | 72 ++++---- dev/generated/DominatingSet/index.html | 4 +- .../{cd232c92.svg => f85763dc.svg} | 48 ++--- dev/generated/IndependentSet/index.html | 80 +++++---- dev/generated/Matching/index.html | 20 +-- dev/generated/MaxCut/index.html | 4 +- .../MaximalIS/{d3a90438.svg => 85803ac3.svg} | 76 ++++---- .../MaximalIS/{eb8be401.svg => d2afa411.svg} | 108 ++++++------ dev/generated/MaximalIS/index.html | 4 +- .../PaintShop/{16fd7be5.svg => 18b59807.svg} | 54 +++--- .../PaintShop/{bcf11b3a.svg => c1783cd1.svg} | 54 +++--- dev/generated/PaintShop/index.html | 6 +- dev/generated/Satisfiability/index.html | 2 +- dev/generated/SetCovering/index.html | 2 +- dev/generated/SetPacking/index.html | 8 +- dev/generated/SpinGlass/index.html | 14 +- dev/generated/open/index.html | 2 +- dev/generated/saveload/index.html | 106 ++++++----- .../weighted/{245a5454.svg => 68c9362b.svg} | 20 +-- dev/generated/weighted/index.html | 4 +- dev/gist/index.html | 2 +- dev/index.html | 4 +- dev/performancetips/index.html | 18 +- dev/ref/index.html | 58 +++---- dev/search_index.js | 2 +- dev/sumproduct/5f94069e.png | Bin 0 -> 24324 bytes dev/sumproduct/ee6f4e25.png | Bin 24191 -> 0 bytes dev/sumproduct/index.html | 164 +++++++++--------- 30 files changed, 484 insertions(+), 466 deletions(-) rename dev/generated/DominatingSet/{2562107b.svg => 806e81b1.svg} (86%) rename dev/generated/IndependentSet/{cd232c92.svg => f85763dc.svg} (81%) rename dev/generated/MaximalIS/{d3a90438.svg => 85803ac3.svg} (85%) rename dev/generated/MaximalIS/{eb8be401.svg => d2afa411.svg} (85%) rename dev/generated/PaintShop/{16fd7be5.svg => 18b59807.svg} (94%) rename dev/generated/PaintShop/{bcf11b3a.svg => c1783cd1.svg} (94%) rename dev/generated/weighted/{245a5454.svg => 68c9362b.svg} (92%) create mode 100644 dev/sumproduct/5f94069e.png delete mode 100644 dev/sumproduct/ee6f4e25.png diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 074ec24..379ebf8 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-14T03:02:37","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-15T09:27:25","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/generated/Coloring/index.html b/dev/generated/Coloring/index.html index 37e8500..4f31cb5 100644 --- a/dev/generated/Coloring/index.html +++ b/dev/generated/Coloring/index.html @@ -69,14 +69,14 @@ - - - + + + - + - + @@ -86,4 +86,4 @@ for e in edges(graph)]; format=:svg)Example block output

Let us construct the tensor network and see if there are solutions.

lineproblem = Coloring{3}(linegraph);
 
 num_of_coloring = solve(GenericTensorNetwork(lineproblem), CountingMin())[]
-read_size_count(num_of_coloring)
17.0 => 1800.0

You will see the maximum size 28 is smaller than the number of edges in the linegraph, meaning no solution for the 3-coloring on edges of a Petersen graph.


This page was generated using Literate.jl.

+read_size_count(num_of_coloring)
17.0 => 1800.0

You will see the maximum size 28 is smaller than the number of edges in the linegraph, meaning no solution for the 3-coloring on edges of a Petersen graph.


This page was generated using Literate.jl.

diff --git a/dev/generated/DominatingSet/2562107b.svg b/dev/generated/DominatingSet/806e81b1.svg similarity index 86% rename from dev/generated/DominatingSet/2562107b.svg rename to dev/generated/DominatingSet/806e81b1.svg index 1c5409e..81cefee 100644 --- a/dev/generated/DominatingSet/2562107b.svg +++ b/dev/generated/DominatingSet/806e81b1.svg @@ -42,15 +42,15 @@ - - + + - + - + @@ -67,14 +67,14 @@ - - + + - + - + @@ -95,12 +95,12 @@ - - + + - - + + @@ -116,12 +116,12 @@ - + - - + + - + @@ -141,16 +141,16 @@ - + - - + + - + @@ -166,15 +166,15 @@ - - + + - + - + @@ -192,12 +192,12 @@ - + - - + + - + @@ -218,14 +218,14 @@ - - + + - + - + @@ -241,14 +241,14 @@ - + - + - + - + diff --git a/dev/generated/DominatingSet/index.html b/dev/generated/DominatingSet/index.html index 9ede4eb..b92422b 100644 --- a/dev/generated/DominatingSet/index.html +++ b/dev/generated/DominatingSet/index.html @@ -41,6 +41,6 @@ x_v^{w_v} & \text{otherwise}, \end{cases}\]

where $w_v$ is the weight of vertex $v$. This tensor means if both $v$ and its neighboring vertices are not in $D$, i.e., $s_1=s_2=\ldots=s_{|N(v)|}=s_v=0$, this configuration is forbidden because $v$ is not adjacent to any member in the set. otherwise, if $v$ is in $D$, it has a contribution $x_v^{w_v}$ to the final result. One can check the contraction time space complexity of a DominatingSet instance by typing:

contraction_complexity(problem)
Time complexity: 2^11.118941072723507
 Space complexity: 2^8.0
-Read-write complexity: 2^11.33371442609397

Solving properties

Counting properties

Domination polynomial

The graph polynomial for the dominating set problem is known as the domination polynomial (see arXiv:0905.2251). It is defined as

\[D(G, x) = \sum_{k=0}^{\gamma(G)} d_k x^k,\]

where $d_k$ is the number of dominating sets of size $k$ in graph $G=(V, E)$.

domination_polynomial = solve(problem, GraphPolynomial())[]
10∙x3 + 75∙x4 + 192∙x5 + 200∙x6 + 120∙x7 + 45∙x8 + 10∙x9 + x10

The domination number $\gamma(G)$ can be computed with the SizeMin property:

domination_number = solve(problem, SizeMin())[]
3.0ₜ

Similarly, we have its counting CountingMin:

counting_min_dominating_set = solve(problem, CountingMin())[]
(3.0, 10.0)ₜ

Configuration properties

finding minimum dominating set

One can enumerate all minimum dominating sets with the ConfigsMin property in the program.

min_configs = read_config(solve(problem, ConfigsMin())[])
+Read-write complexity: 2^11.333714426093968

Solving properties

Counting properties

Domination polynomial

The graph polynomial for the dominating set problem is known as the domination polynomial (see arXiv:0905.2251). It is defined as

\[D(G, x) = \sum_{k=0}^{\gamma(G)} d_k x^k,\]

where $d_k$ is the number of dominating sets of size $k$ in graph $G=(V, E)$.

domination_polynomial = solve(problem, GraphPolynomial())[]
10∙x3 + 75∙x4 + 192∙x5 + 200∙x6 + 120∙x7 + 45∙x8 + 10∙x9 + x10

The domination number $\gamma(G)$ can be computed with the SizeMin property:

domination_number = solve(problem, SizeMin())[]
3.0ₜ

Similarly, we have its counting CountingMin:

counting_min_dominating_set = solve(problem, CountingMin())[]
(3.0, 10.0)ₜ

Configuration properties

finding minimum dominating set

One can enumerate all minimum dominating sets with the ConfigsMin property in the program.

min_configs = read_config(solve(problem, ConfigsMin())[])
 
-all(c->is_dominating_set(graph, c), min_configs)
true
show_configs(graph, locations, reshape(collect(min_configs), 2, 5); padding_left=20)
Example block output

Similarly, if one is only interested in computing one of the minimum dominating sets, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

+all(c->is_dominating_set(graph, c), min_configs)
true
show_configs(graph, locations, reshape(collect(min_configs), 2, 5); padding_left=20)
Example block output

Similarly, if one is only interested in computing one of the minimum dominating sets, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

diff --git a/dev/generated/IndependentSet/cd232c92.svg b/dev/generated/IndependentSet/f85763dc.svg similarity index 81% rename from dev/generated/IndependentSet/cd232c92.svg rename to dev/generated/IndependentSet/f85763dc.svg index 2353c87..a711063 100644 --- a/dev/generated/IndependentSet/cd232c92.svg +++ b/dev/generated/IndependentSet/f85763dc.svg @@ -18,14 +18,14 @@ - - + + - - - - + + + + @@ -41,16 +41,16 @@ - - + + - - - + + + - + @@ -67,15 +67,15 @@ - - - - + + + + - + - + @@ -116,14 +116,14 @@ - + - - - + + + - - + + diff --git a/dev/generated/IndependentSet/index.html b/dev/generated/IndependentSet/index.html index 987f366..7533346 100644 --- a/dev/generated/IndependentSet/index.html +++ b/dev/generated/IndependentSet/index.html @@ -44,14 +44,14 @@ 1 & 0 \end{matrix}\right).\]

Ideally, an optimal contraction order has a space complexity $2^{{\rm tw}(G)}$, where ${\rm tw(G)}$ is the tree-width of $G$ (or graph in the code). We can check the time, space and read-write complexities by typing

contraction_complexity(problem)
Time complexity: 2^7.977279923499915
 Space complexity: 2^4.0
-Read-write complexity: 2^8.675957032941747

For more information about how to improve the contraction order, please check the Performance Tips.

Solution space properties

Maximum independent set size $\alpha(G)$

We can compute solution space properties with the solve function, which takes two positional arguments, the problem instance and the wanted property.

maximum_independent_set_size = solve(problem, SizeMax())[]
4.0ₜ

Here SizeMax means finding the solution with maximum set size. The return value has Tropical type. We can get its content by typing

read_size(maximum_independent_set_size)
4.0

Counting properties

Count all solutions and best several solutions

We can count all independent sets with the CountingAll property.

count_all_independent_sets = solve(problem, CountingAll())[]
76.0

The return value has type Float64. The counting of all independent sets is equivalent to the infinite temperature partition function

solve(problem, PartitionFunction(0.0))[]
76.0

We can count the maximum independent sets with CountingMax.

count_maximum_independent_sets = solve(problem, CountingMax())[]
(4.0, 5.0)ₜ

The return value has type CountingTropical, which contains two fields. They are n being the maximum independent set size and c being the number of the maximum independent sets.

read_size_count(count_maximum_independent_sets)
4.0 => 5.0

Similarly, we can count independent sets of sizes $\alpha(G)$ and $\alpha(G)-1$ by feeding an integer positional argument to CountingMax.

count_max2_independent_sets = solve(problem, CountingMax(2))[]
30.0*x^3 + 5.0*x^4

The return value has type TruncatedPoly, which contains two fields. They are maxorder being the maximum independent set size and coeffs being the number of independent sets having sizes $\alpha(G)-1$ and $\alpha(G)$.

read_size_count(count_max2_independent_sets)
2-element Vector{Pair{Float64, Float64}}:
+Read-write complexity: 2^8.67595703294175

For more information about how to improve the contraction order, please check the Performance Tips.

Solution space properties

Maximum independent set size $\alpha(G)$

We can compute solution space properties with the solve function, which takes two positional arguments, the problem instance and the wanted property.

maximum_independent_set_size = solve(problem, SizeMax())[]
4.0ₜ

Here SizeMax means finding the solution with maximum set size. The return value has Tropical type. We can get its content by typing

read_size(maximum_independent_set_size)
4.0

Counting properties

Count all solutions and best several solutions

We can count all independent sets with the CountingAll property.

count_all_independent_sets = solve(problem, CountingAll())[]
76

The return value has type Float64. The counting of all independent sets is equivalent to the infinite temperature partition function

solve(problem, PartitionFunction(0.0))[]
76.0

We can count the maximum independent sets with CountingMax.

count_maximum_independent_sets = solve(problem, CountingMax())[]
(4.0, 5.0)ₜ

The return value has type CountingTropical, which contains two fields. They are n being the maximum independent set size and c being the number of the maximum independent sets.

read_size_count(count_maximum_independent_sets)
4.0 => 5.0

Similarly, we can count independent sets of sizes $\alpha(G)$ and $\alpha(G)-1$ by feeding an integer positional argument to CountingMax.

count_max2_independent_sets = solve(problem, CountingMax(2))[]
30.0*x^3 + 5.0*x^4

The return value has type TruncatedPoly, which contains two fields. They are maxorder being the maximum independent set size and coeffs being the number of independent sets having sizes $\alpha(G)-1$ and $\alpha(G)$.

read_size_count(count_max2_independent_sets)
2-element Vector{Pair{Float64, Float64}}:
  3.0 => 30.0
  4.0 => 5.0
Find the graph polynomial

We can count the number of independent sets at any size, which is equivalent to finding the coefficients of an independence polynomial that defined as

\[I(G, x) = \sum_{k=0}^{\alpha(G)} a_k x^k,\]

where $\alpha(G)$ is the maximum independent set size, $a_k$ is the number of independent sets of size $k$. The total number of independent sets is thus equal to $I(G, 1)$. There are 3 methods to compute a graph polynomial, :finitefield, :fft and :polynomial. These methods are introduced in the docstring of GraphPolynomial.

independence_polynomial = solve(problem, GraphPolynomial(; method=:finitefield))[]
1 + 10∙x + 30∙x2 + 30∙x3 + 5∙x4

The return type is Polynomial.

read_size_count(independence_polynomial)
5-element Vector{Pair{Int64, BigInt}}:
  0 => 1
  1 => 10
  2 => 30
  3 => 30
- 4 => 5

Configuration properties

Find one best solution

We can use the bounded or unbounded SingleConfigMax to find one of the solutions with largest size. The unbounded (default) version uses a joint type of CountingTropical and ConfigSampler in computation, where CountingTropical finds the maximum size and ConfigSampler samples one of the best solutions. The bounded version uses the binary gradient back-propagation (see our paper) to compute the gradients. It requires caching intermediate states, but is often faster (on CPU) because it can use TropicalGEMM (see Performance Tips).

max_config = solve(problem, SingleConfigMax(; bounded=false))[]
(4.0, ConfigSampler{10, 1, 1}(1010000011))ₜ

The return value has type CountingTropical with its counting field having ConfigSampler type. The data field of ConfigSampler is a bit string that corresponds to the solution

single_solution = read_config(max_config)
1010000011

This bit string should be read from left to right, with the i-th bit being 1 (0) to indicate the i-th vertex is present (absent) in the set. We can visualize this MIS with the following function.

show_graph(graph, locations; format=:svg, vertex_colors=
+ 4 => 5

Configuration properties

Find one best solution

We can use the bounded or unbounded SingleConfigMax to find one of the solutions with largest size. The unbounded (default) version uses a joint type of CountingTropical and ConfigSampler in computation, where CountingTropical finds the maximum size and ConfigSampler samples one of the best solutions. The bounded version uses the binary gradient back-propagation (see our paper) to compute the gradients. It requires caching intermediate states, but is often faster (on CPU) because it can use TropicalGEMM (see Performance Tips).

max_config = solve(problem, SingleConfigMax(; bounded=false))[]
(4.0, ConfigSampler{10, 1, 1}(0010111000))ₜ

The return value has type CountingTropical with its counting field having ConfigSampler type. The data field of ConfigSampler is a bit string that corresponds to the solution

single_solution = read_config(max_config)
0010111000

This bit string should be read from left to right, with the i-th bit being 1 (0) to indicate the i-th vertex is present (absent) in the set. We can visualize this MIS with the following function.

show_graph(graph, locations; format=:svg, vertex_colors=
     [iszero(single_solution[i]) ? "white" : "red" for i=1:nv(graph)])
Enumerate all solutions and best several solutions

We can use bounded or unbounded ConfigsMax to find all solutions with largest-K set sizes. In most cases, the bounded (default) version is preferred because it can reduce the memory usage significantly.

all_max_configs = solve(problem, ConfigsMax(; bounded=true))[]
(4.0, {1001001100, 0101010001, 0010111000, 0100100110, 1010000011})ₜ

The return value has type CountingTropical, while its counting field having type ConfigEnumerator. The data field of a ConfigEnumerator instance contains a vector of bit strings.

_, configs_vector = read_size_config(all_max_configs)
4.0 => StaticBitVector{10, 1}[1001001100, 0101010001, 0010111000, 0100100110, 1010000011]

These solutions can be visualized with the show_configs function.

show_configs(graph, locations, reshape(configs_vector, 1, :); padding_left=20)
Example block output

We can use ConfigsAll to enumerate all sets satisfying the independence constraint.

all_independent_sets = solve(problem, ConfigsAll())[]
{0101000001, 0101000100, 0101000000, 1001000001, 0001000001, 1001001100, 1001000100, 0001001100, 0001000100, 1001001000, 1001000000, 0001001000, 0001000000, 0100000001, 0100100100, 0100000100, 0100100000, 0100000000, 1010000001, 0010000001, 1000000001, 0000000001, 0010101000, 0010100000, 1010001000, 1010000000, 0010001000, 0010000000, 0000101100, 0000100100, 1000001100, 1000000100, 0000001100, 0000000100, 0000101000, 0000100000, 1000001000, 1000000000, 0000001000, 0000000000, 0101010001, 0101010000, 0001010001, 0001011000, 0001010000, 0100010001, 0100110000, 0100010000, 0010010001, 0000010001, 0010111000, 0010110000, 0010011000, 0010010000, 0000111000, 0000110000, 0000011000, 0000010000, 0100000011, 0100100110, 0100000110, 0100100010, 0100000010, 1010000011, 0010000011, 1000000011, 0000000011, 0010100010, 1010000010, 0010000010, 0000100110, 1000000110, 0000000110, 0000100010, 1000000010, 0000000010}

The return value has type ConfigEnumerator.

Sample solutions

It is often difficult to store all configurations in a vector. A more clever way to store the data is using the sum product tree format.

all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]
+ (count = 76.0)
+'/>
Enumerate all solutions and best several solutions

We can use bounded or unbounded ConfigsMax to find all solutions with largest-K set sizes. In most cases, the bounded (default) version is preferred because it can reduce the memory usage significantly.

all_max_configs = solve(problem, ConfigsMax(; bounded=true))[]
(4.0, {1010000011, 1001001100, 0101010001, 0100100110, 0010111000})ₜ

The return value has type CountingTropical, while its counting field having type ConfigEnumerator. The data field of a ConfigEnumerator instance contains a vector of bit strings.

_, configs_vector = read_size_config(all_max_configs)
4.0 => StaticBitVector{10, 1}[1010000011, 1001001100, 0101010001, 0100100110, 0010111000]

These solutions can be visualized with the show_configs function.

show_configs(graph, locations, reshape(configs_vector, 1, :); padding_left=20)
Example block output

We can use ConfigsAll to enumerate all sets satisfying the independence constraint.

all_independent_sets = solve(problem, ConfigsAll())[]
{0100000110, 1000000110, 0000000110, 0100000011, 0100000010, 1010000011, 0010000011, 1010000010, 0010000010, 1000000011, 0000000011, 1000000010, 0000000010, 0100000100, 1000001100, 0000001100, 1000000100, 0000000100, 0100010001, 0100000001, 0100010000, 0100000000, 1010001000, 0010011000, 0010001000, 1010000001, 0010010001, 0010000001, 1010000000, 0010010000, 0010000000, 1000001000, 0000011000, 0000001000, 1000000001, 0000010001, 0000000001, 1000000000, 0000010000, 0000000000, 0101000100, 1001001100, 0001001100, 1001000100, 0001000100, 0101010001, 0101000001, 0101010000, 0101000000, 1001001000, 0001011000, 0001001000, 1001000001, 0001010001, 0001000001, 1001000000, 0001010000, 0001000000, 0100100110, 0000100110, 0100100010, 0010100010, 0000100010, 0100100100, 0000101100, 0000100100, 0100110000, 0100100000, 0010111000, 0010101000, 0010110000, 0010100000, 0000111000, 0000101000, 0000110000, 0000100000}

The return value has type ConfigEnumerator.

Sample solutions

It is often difficult to store all configurations in a vector. A more clever way to store the data is using the sum product tree format.

all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]
+ (count = 76.0)
 ├─ + (count = 58.0)
 │  ├─ + (count = 40.0)
 │  │  ├─ * (count = 13.0)
-│  │  │  ├─ OnehotVec{10, 2}(4, 1)
+│  │  │  ├─ * (count = 1.0)
+│  │  │  │  ├─ OnehotVec{10, 2}(9, 1)
+│  │  │  │  └─ OnehotVec{10, 2}(9, 1)
 │  │  │  └─ + (count = 13.0)
 │  │  │     ├─ * (count = 1.0)
 │  │  │     │  ⋮
@@ -109,27 +111,31 @@
 │  │           ⋮
 │  │           
 │  └─ * (count = 18.0)
-│     ├─ OnehotVec{10, 2}(6, 1)
-│     └─ + (count = 18.0)
-│        ├─ * (count = 5.0)
-│        │  ├─ OnehotVec{10, 2}(4, 1)
-│        │  └─ + (count = 5.0)
-│        │     ⋮
-│        │     
-│        └─ + (count = 13.0)
+│     ├─ OnehotVec{10, 2}(4, 1)
+│     └─ * (count = 18.0)
+│        ├─ OnehotVec{10, 2}(4, 1)
+│        └─ + (count = 18.0)
 │           ├─ * (count = 1.0)
 │           │  ⋮
 │           │  
-│           └─ + (count = 12.0)
+│           └─ + (count = 17.0)
 │              ⋮
 │              
 └─ * (count = 18.0)
-   ├─ OnehotVec{10, 2}(9, 1)
-   └─ * (count = 18.0)
-      ├─ * (count = 1.0)
-      │  ├─ OnehotVec{10, 2}(9, 1)
-      │  └─ OnehotVec{10, 2}(9, 1)
-      └─ + (count = 18.0)
+   ├─ OnehotVec{10, 2}(5, 1)
+   └─ + (count = 18.0)
+      ├─ * (count = 5.0)
+      │  ├─ * (count = 1.0)
+      │  │  ├─ OnehotVec{10, 2}(9, 1)
+      │  │  └─ OnehotVec{10, 2}(9, 1)
+      │  └─ + (count = 5.0)
+      │     ├─ * (count = 1.0)
+      │     │  ⋮
+      │     │  
+      │     └─ + (count = 4.0)
+      │        ⋮
+      │        
+      └─ + (count = 13.0)
          ├─ * (count = 1.0)
          │  ├─ * (count = 1.0)
          │  │  ⋮
@@ -137,23 +143,23 @@
          │  └─ * (count = 1.0)
          │     ⋮
          │     
-         └─ + (count = 17.0)
-            ├─ * (count = 4.0)
+         └─ + (count = 12.0)
+            ├─ * (count = 2.0)
             │  ⋮
             │  
-            └─ + (count = 13.0)
+            └─ + (count = 10.0)
                ⋮
                
 

The return value has the SumProductTree type. Its length corresponds to the number of configurations.

length(all_independent_sets_tree)
76.0

We can use Base.collect function to create a ConfigEnumerator or use generate_samples to generate samples from it.

collect(all_independent_sets_tree)
 
 generate_samples(all_independent_sets_tree, 10)
10-element Vector{StaticBitVector{10, 1}}:
- 0001000001
+ 0000000100
+ 0100000000
+ 0010011000
+ 0000001000
+ 0101000100
+ 0001000100
  0001001100
- 1001001100
- 0100000001
- 0010001000
- 0000000000
- 0100000010
- 1000000010
- 1000000010
- 0000000110

This page was generated using Literate.jl.

+ 1001001000 + 0000100100 + 0010110000

This page was generated using Literate.jl.

diff --git a/dev/generated/Matching/index.html b/dev/generated/Matching/index.html index ff16114..3cfc277 100644 --- a/dev/generated/Matching/index.html +++ b/dev/generated/Matching/index.html @@ -48,23 +48,23 @@ 3 => 145 4 => 90 5 => 6

Configuration properties

one of the perfect matches
match_config = solve(problem, SingleConfigMax())[]
-read_size_config(match_config)
5.0 => 001100010000101

Let us show the result by coloring the matched edges to red

show_graph(graph, locations; format=:svg, edge_colors=
+read_size_config(match_config)
5.0 => 010011000001001

Let us show the result by coloring the matched edges to red

show_graph(graph, locations; format=:svg, edge_colors=
     [isone(read_config(match_config)[i]) ? "red" : "black" for i=1:ne(graph)])

where we use edges with red color to related pairs of matched vertices.


This page was generated using Literate.jl.

+'/>

where we use edges with red color to related pairs of matched vertices.


This page was generated using Literate.jl.

diff --git a/dev/generated/MaxCut/index.html b/dev/generated/MaxCut/index.html index 6642b9b..5d9a9fc 100644 --- a/dev/generated/MaxCut/index.html +++ b/dev/generated/MaxCut/index.html @@ -33,7 +33,7 @@ '/>

Generic tensor network representation

We can define the cutting problem with the MaxCut type as

maxcut = MaxCut(graph)
MaxCut{Int64, UnitWeight}(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])

The tensor network representation of the cutting problem can be obtained by

problem = GenericTensorNetwork(maxcut)
GenericTensorNetwork{MaxCut{Int64, UnitWeight}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
 - open vertices: Int64[]
 - fixed vertices: Dict{Int64, Int64}()
-- contraction time = 2^7.755, space = 2^4.0, read-write = 2^8.308

Theory (can skip)

We associated a vertex $v\in V$ with a boolean degree of freedom $s_v\in\{0, 1\}$. Then the maximum cutting problem can be encoded to tensor networks by mapping an edge $(i,j)\in E$ to an edge matrix labelled by $s_i$ and $s_j$

\[B(x_i, x_j, w_{ij}) = \left(\begin{matrix} +- contraction time = 2^7.807, space = 2^4.0, read-write = 2^8.379

Theory (can skip)

We associated a vertex $v\in V$ with a boolean degree of freedom $s_v\in\{0, 1\}$. Then the maximum cutting problem can be encoded to tensor networks by mapping an edge $(i,j)\in E$ to an edge matrix labelled by $s_i$ and $s_j$

\[B(x_i, x_j, w_{ij}) = \left(\begin{matrix} 1 & x_{i}^{w_{ij}}\\ x_{j}^{w_{ij}} & 1 \end{matrix}\right),\]

where $w_{ij}$ is a real number associated with edge $(i, j)$ as the edge weight. If and only if the bipartition cuts on edge $(i, j)$, this tensor contributes a factor $x_{i}^{w_{ij}}$ or $x_{j}^{w_{ij}}$. Similarly, one can assign weights to vertices, which corresponds to the onsite energy terms in the spin glass. The vertex tensor is

\[W(x_i, w_i) = \left(\begin{matrix} @@ -71,4 +71,4 @@ -'/>

where red vertices and white vertices are separated by the cut.


This page was generated using Literate.jl.

+'/>

where red vertices and white vertices are separated by the cut.


This page was generated using Literate.jl.

diff --git a/dev/generated/MaximalIS/d3a90438.svg b/dev/generated/MaximalIS/85803ac3.svg similarity index 85% rename from dev/generated/MaximalIS/d3a90438.svg rename to dev/generated/MaximalIS/85803ac3.svg index 30b28eb..3b48d42 100644 --- a/dev/generated/MaximalIS/d3a90438.svg +++ b/dev/generated/MaximalIS/85803ac3.svg @@ -43,13 +43,13 @@ - - - - - + + + + + - + @@ -67,15 +67,15 @@ - - + + - + - + @@ -91,14 +91,14 @@ - + - + - + - + @@ -119,11 +119,11 @@ - - - + + + - + @@ -166,13 +166,13 @@ - - - + + + - - - + + + @@ -191,15 +191,15 @@ - + - + - - - - + + + + @@ -216,16 +216,16 @@ - - + + - + - + @@ -242,12 +242,12 @@ - + - - + + - + diff --git a/dev/generated/MaximalIS/eb8be401.svg b/dev/generated/MaximalIS/d2afa411.svg similarity index 85% rename from dev/generated/MaximalIS/eb8be401.svg rename to dev/generated/MaximalIS/d2afa411.svg index 099eb02..3fa798c 100644 --- a/dev/generated/MaximalIS/eb8be401.svg +++ b/dev/generated/MaximalIS/d2afa411.svg @@ -41,15 +41,15 @@ - + - + - + - + @@ -67,15 +67,15 @@ - - + + - + - + @@ -93,12 +93,12 @@ - + - + - + @@ -121,10 +121,10 @@ - + - - + + @@ -166,15 +166,15 @@ - - - - + + + + - + - + @@ -191,14 +191,14 @@ - + - + - + @@ -216,16 +216,16 @@ - - + + - + - + - - - + + + @@ -241,13 +241,13 @@ - - + + - + @@ -266,16 +266,16 @@ - + - - + + - - + + - - + + @@ -292,12 +292,12 @@ - - + + - + @@ -318,13 +318,13 @@ - + - - - + + + @@ -344,13 +344,13 @@ - + - - - + + + @@ -367,13 +367,13 @@ - + - + - + diff --git a/dev/generated/MaximalIS/index.html b/dev/generated/MaximalIS/index.html index aaada44..d099edf 100644 --- a/dev/generated/MaximalIS/index.html +++ b/dev/generated/MaximalIS/index.html @@ -42,7 +42,7 @@ Space complexity: 2^9.0 Read-write complexity: 2^11.518161355756956

Solving properties

Counting properties

maximal independence polynomial

The graph polynomial defined for the maximal independent set problem is

\[I_{\rm max}(G, x) = \sum_{k=0}^{\alpha(G)} b_k x^k,\]

where $b_k$ is the number of maximal independent sets of size $k$ in graph $G=(V, E)$.

maximal_indenpendence_polynomial = solve(problem, GraphPolynomial())[]
10∙x3 + 5∙x4

One can see the first several coefficients are 0, because it only counts the maximal independent sets, The minimum maximal independent set size is also known as the independent domination number. It can be computed with the SizeMin property:

independent_domination_number = solve(problem, SizeMin())[]
3.0ₜ

Similarly, we have its counting CountingMin:

counting_min_maximal_independent_set = solve(problem, CountingMin())[]
(3.0, 10.0)ₜ

Configuration properties

finding all maximal independent set
maximal_configs = read_config(solve(problem, ConfigsAll())[])
 
-all(c->is_maximal_independent_set(graph, c), maximal_configs)
true
show_configs(graph, locations, reshape(collect(maximal_configs), 3, 5); padding_left=20)
Example block output

This result should be consistent with that given by the Bron Kerbosch algorithm on the complement of Petersen graph.

cliques = maximal_cliques(complement(graph))
15-element Vector{Vector{Int64}}:
+all(c->is_maximal_independent_set(graph, c), maximal_configs)
true
show_configs(graph, locations, reshape(collect(maximal_configs), 3, 5); padding_left=20)
Example block output

This result should be consistent with that given by the Bron Kerbosch algorithm on the complement of Petersen graph.

cliques = maximal_cliques(complement(graph))
15-element Vector{Vector{Int64}}:
  [5, 6, 7, 3]
  [5, 6, 2]
  [5, 9, 2, 8]
@@ -59,4 +59,4 @@
  [1, 9, 8]
  [1, 3, 7]

For sparse graphs, the generic tensor network approach is usually much faster and memory efficient than the Bron Kerbosch algorithm.

finding minimum maximal independent set

It is the ConfigsMin property in the program.

minimum_maximal_configs = read_config(solve(problem, ConfigsMin())[])
 
-show_configs(graph, locations, reshape(collect(minimum_maximal_configs), 2, 5); padding_left=20)
Example block output

Similarly, if one is only interested in computing one of the minimum sets, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

+show_configs(graph, locations, reshape(collect(minimum_maximal_configs), 2, 5); padding_left=20)Example block output

Similarly, if one is only interested in computing one of the minimum sets, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

diff --git a/dev/generated/PaintShop/16fd7be5.svg b/dev/generated/PaintShop/18b59807.svg similarity index 94% rename from dev/generated/PaintShop/16fd7be5.svg rename to dev/generated/PaintShop/18b59807.svg index 1cec571..0d5a89c 100644 --- a/dev/generated/PaintShop/16fd7be5.svg +++ b/dev/generated/PaintShop/18b59807.svg @@ -2,31 +2,31 @@ - + - + - + - + - + - + - + - + - + @@ -59,74 +59,74 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/dev/generated/PaintShop/bcf11b3a.svg b/dev/generated/PaintShop/c1783cd1.svg similarity index 94% rename from dev/generated/PaintShop/bcf11b3a.svg rename to dev/generated/PaintShop/c1783cd1.svg index a93af29..c7975ae 100644 --- a/dev/generated/PaintShop/bcf11b3a.svg +++ b/dev/generated/PaintShop/c1783cd1.svg @@ -2,31 +2,31 @@ - + - + - + - + - + - + - + - + - + @@ -59,74 +59,74 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/dev/generated/PaintShop/index.html b/dev/generated/PaintShop/index.html index eee3289..9d288ef 100644 --- a/dev/generated/PaintShop/index.html +++ b/dev/generated/PaintShop/index.html @@ -27,10 +27,10 @@ i != j && add_edge!(graph, i, j) end show_graph(graph, locations; texts=string.(sequence), format=:svg, edge_colors= - [sequence[e.src] == sequence[e.dst] ? "blue" : "black" for e in edges(graph)])Example block output

Vertices connected by blue edges must have different colors, and the goal becomes a min-cut problem defined on black edges.

Generic tensor network representation

We can define the binary paint shop problem with the PaintShop type as

pshop = PaintShop(sequence)
PaintShop{Char}(['i', 'a', 'd', 'g', 'b', 'e', 'a', 'd', 'f', 'c', 'c', 'h', 'g', 'h', 'e', 'b', 'i', 'f'], Bool[1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0])

The tensor network representation of the binary paint shop problem can be obtained by

problem = GenericTensorNetwork(pshop)
GenericTensorNetwork{PaintShop{Char}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
+    [sequence[e.src] == sequence[e.dst] ? "blue" : "black" for e in edges(graph)])
Example block output

Vertices connected by blue edges must have different colors, and the goal becomes a min-cut problem defined on black edges.

Generic tensor network representation

We can define the binary paint shop problem with the PaintShop type as

pshop = PaintShop(sequence)
PaintShop{Char}(['i', 'a', 'd', 'g', 'b', 'e', 'a', 'd', 'f', 'c', 'c', 'h', 'g', 'h', 'e', 'b', 'i', 'f'], Bool[1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0])

The tensor network representation of the binary paint shop problem can be obtained by

problem = GenericTensorNetwork(pshop)
GenericTensorNetwork{PaintShop{Char}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
 - open vertices: Int64[]
 - fixed vertices: Dict{Int64, Int64}()
-- contraction time = 2^7.426, space = 2^4.0, read-write = 2^8.195

Theory (can skip)

Type PaintShop can be used for constructing the tensor network with optimized contraction order for solving a binary paint shop problem. To obtain its tensor network representation, we associating car $c_i$ (the $i$-th character in our example) with a degree of freedom $s_{c_i} \in \{0, 1\}$, where we use $0$ to denote the first appearance of a car is colored red and $1$ to denote the first appearance of a car is colored blue. For each black edges $(i, i+1)$, we define an edge tensor labeled by $(s_{c_i}, s_{c_{i+1}})$ as follows: If both cars on this edge are their first or second appearance

\[B^{\rm parallel} = \left(\begin{matrix} +- contraction time = 2^7.459, space = 2^4.0, read-write = 2^8.234

Theory (can skip)

Type PaintShop can be used for constructing the tensor network with optimized contraction order for solving a binary paint shop problem. To obtain its tensor network representation, we associating car $c_i$ (the $i$-th character in our example) with a degree of freedom $s_{c_i} \in \{0, 1\}$, where we use $0$ to denote the first appearance of a car is colored red and $1$ to denote the first appearance of a car is colored blue. For each black edges $(i, i+1)$, we define an edge tensor labeled by $(s_{c_i}, s_{c_{i+1}})$ as follows: If both cars on this edge are their first or second appearance

\[B^{\rm parallel} = \left(\begin{matrix} x & 1 \\ 1 & x \\ \end{matrix}\right),\]

otherwise,

\[B^{\rm anti-parallel} = \left(\begin{matrix} @@ -40,4 +40,4 @@ show_graph(graph, locations; format=:svg, texts=string.(sequence), edge_colors=[sequence[e.src] == sequence[e.dst] ? "blue" : "black" for e in edges(graph)], - vertex_colors=[isone(c) ? "red" : "black" for c in painting1], config=GraphDisplayConfig(;vertex_text_color="white"))Example block output

Since we have different choices of initial color, the number of best solution is 2.

The following function will check the solution and return you the number of color switches

num_paint_shop_color_switch(sequence, painting1)
4

This page was generated using Literate.jl.

+ vertex_colors=[isone(c) ? "red" : "black" for c in painting1], config=GraphDisplayConfig(;vertex_text_color="white"))Example block output

Since we have different choices of initial color, the number of best solution is 2.

The following function will check the solution and return you the number of color switches

num_paint_shop_color_switch(sequence, painting1)
4

This page was generated using Literate.jl.

diff --git a/dev/generated/Satisfiability/index.html b/dev/generated/Satisfiability/index.html index ddaf9f3..8474b4e 100644 --- a/dev/generated/Satisfiability/index.html +++ b/dev/generated/Satisfiability/index.html @@ -20,4 +20,4 @@ \end{matrix}\right).\]

There is only one entry $(s_x, s_y, s_z) = (1, 0, 1)$ that makes this clause unsatisfied.

Solving properties

Satisfiability and its counting

The size of a satisfiability problem is defined by the number of unsatisfied clauses.

num_satisfiable = solve(problem, SizeMin())[]
0.0ₜ

The GraphPolynomial of a satisfiability problem counts the number of solutions that k clauses satisfied.

num_satisfiable_count = read_size_count(solve(problem, GraphPolynomial())[])
3-element Vector{Pair{Int64, BigInt}}:
  0 => 60
  1 => 56
- 2 => 12

Find one of the solutions

single_config = read_config(solve(problem, SingleConfigMin())[])
0111111

One will see a bit vector printed. One can create an assignment and check the validity with the following statement:

satisfiable(cnf, Dict(zip(ProblemReductions.symbols(problem.problem), single_config)))
true

This page was generated using Literate.jl.

+ 2 => 12

Find one of the solutions

single_config = read_config(solve(problem, SingleConfigMin())[])
1111101

One will see a bit vector printed. One can create an assignment and check the validity with the following statement:

satisfiable(cnf, Dict(zip(ProblemReductions.symbols(problem.problem), single_config)))
true

This page was generated using Literate.jl.

diff --git a/dev/generated/SetCovering/index.html b/dev/generated/SetCovering/index.html index 561d4e9..9a9cbdb 100644 --- a/dev/generated/SetCovering/index.html +++ b/dev/generated/SetCovering/index.html @@ -22,4 +22,4 @@ Space complexity: 2^4.0 Read-write complexity: 2^9.342074667999139

Solving properties

Counting properties

The "graph" polynomial

The graph polynomial for the set covering problem is defined as

\[P(S, x) = \sum_{k=0}^{|S|} c_k x^k,\]

where $c_k$ is the number of configurations having $k$ sets.

covering_polynomial = solve(problem, GraphPolynomial())[]
2∙x4 + 11∙x5 + 13∙x6 + 6∙x7 + x8

The minimum number of sets that covering the set of elements can be computed with the SizeMin property:

min_cover_size = solve(problem, SizeMin())[]
4.0ₜ

Similarly, we have its counting CountingMin:

counting_minimum_setcovering = solve(problem, CountingMin())[]
(4.0, 2.0)ₜ

Configuration properties

Finding minimum set covering

One can enumerate all minimum set covering with the ConfigsMin property in the program.

min_configs = read_config(solve(problem, ConfigsMin())[])
2-element Vector{StaticBitVector{8, 1}}:
  01111000
- 10101100

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 function.

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

Similarly, if one is only interested in computing one of the minimum set coverings, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

+ 10101100

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 function.

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

Similarly, if one is only interested in computing one of the minimum set coverings, one can use the graph property SingleConfigMin.


This page was generated using Literate.jl.

diff --git a/dev/generated/SetPacking/index.html b/dev/generated/SetPacking/index.html index b744eca..d7c9e8c 100644 --- a/dev/generated/SetPacking/index.html +++ b/dev/generated/SetPacking/index.html @@ -12,13 +12,13 @@ [1, 2, 4, 6, 8, 12]

Generic tensor network representation

We can define the set packing problem with the SetPacking type as

problem = SetPacking(sets)
SetPacking{Int64, Int64, UnitWeight}([1, 3, 4, 6, 7, 8, 12, 2, 5, 9, 11, 13, 14, 15, 10], [[1, 3, 4, 6, 7], [4, 7, 8, 12], [2, 5, 9, 11, 13], [1, 2, 14, 15], [3, 6, 10, 12, 14], [8, 14, 15], [1, 2, 6, 11], [1, 2, 4, 6, 8, 12]], [1, 1, 1, 1, 1, 1, 1, 1])

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

problem = GenericTensorNetwork(problem)
GenericTensorNetwork{SetPacking{Int64, Int64, UnitWeight}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
 - open vertices: Int64[]
 - fixed vertices: Dict{Int64, Int64}()
-- contraction time = 2^8.17, space = 2^4.0, read-write = 2^9.111

Theory (can skip)

Let $S$ be the target set packing problem that we want to solve. For each set $s \in S$, we associate it with a weight $w_s$ to it. The tensor network representation map a set $s\in S$ to a boolean degree of freedom $v_s\in\{0, 1\}$. For each set $s$, we defined a parameterized rank-one tensor indexed by $v_s$ as

\[W(x_s^{w_s}) = \left(\begin{matrix} +- contraction time = 2^8.209, space = 2^4.0, read-write = 2^9.152

Theory (can skip)

Let $S$ be the target set packing problem that we want to solve. For each set $s \in S$, we associate it with a weight $w_s$ to it. The tensor network representation map a set $s\in S$ to a boolean degree of freedom $v_s\in\{0, 1\}$. For each set $s$, we defined a parameterized rank-one tensor indexed by $v_s$ as

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

where $x_s$ is a variable associated with $s$. For each unique element $a$, we defined the constraint over all sets containing it $N(a) = \{s | s \in S \land a\in s\}$:

\[B_{s_1,s_2,\ldots,s_{|N(a)|}} = \begin{cases} 0 & s_1+s_2+\ldots+s_{|N(a)|} > 1,\\ 1 & \text{otherwise}. -\end{cases}\]

This tensor means if in a configuration, two sets contain the element $a$, then this configuration is forbidden, One can check the contraction time space complexity of a SetPacking instance by typing:

contraction_complexity(problem)
Time complexity: 2^8.169925001442312
+\end{cases}\]

This tensor means if in a configuration, two sets contain the element $a$, then this configuration is forbidden, One can check the contraction time space complexity of a SetPacking instance by typing:

contraction_complexity(problem)
Time complexity: 2^8.20945336562895
 Space complexity: 2^4.0
-Read-write complexity: 2^9.111135670234708

Solving properties

Counting properties

The "graph" polynomial

The graph polynomial for the set packing problem is defined as

\[P(S, x) = \sum_{k=0}^{\alpha(S)} c_k x^k,\]

where $c_k$ is the number of configurations having $k$ sets, and $\alpha(S)$ is the maximum size of the packing.

packing_polynomial = solve(problem, GraphPolynomial())[]
1 + 8∙x + 8∙x2 + x3

The maximum number of sets that packing the set of elements can be computed with the SizeMax property:

max_packing_size = solve(problem, SizeMax())[]
3.0ₜ

Similarly, we have its counting CountingMax:

counting_maximum_set_packing = solve(problem, CountingMax())[]
(3.0, 1.0)ₜ

Configuration properties

Finding maximum set packing

One can enumerate all maximum set packing with the ConfigsMax property in the program.

max_configs = read_config(solve(problem, ConfigsMax())[])
1-element Vector{StaticBitVector{8, 1}}:
- 10100100

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 function.

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

Similarly, if one is only interested in computing one of the maximum set packing, one can use the graph property SingleConfigMax.


This page was generated using Literate.jl.

+Read-write complexity: 2^9.152284842306582

Solving properties

Counting properties

The "graph" polynomial

The graph polynomial for the set packing problem is defined as

\[P(S, x) = \sum_{k=0}^{\alpha(S)} c_k x^k,\]

where $c_k$ is the number of configurations having $k$ sets, and $\alpha(S)$ is the maximum size of the packing.

packing_polynomial = solve(problem, GraphPolynomial())[]
1 + 8∙x + 8∙x2 + x3

The maximum number of sets that packing the set of elements can be computed with the SizeMax property:

max_packing_size = solve(problem, SizeMax())[]
3.0ₜ

Similarly, we have its counting CountingMax:

counting_maximum_set_packing = solve(problem, CountingMax())[]
(3.0, 1.0)ₜ

Configuration properties

Finding maximum set packing

One can enumerate all maximum set packing with the ConfigsMax property in the program.

max_configs = read_config(solve(problem, ConfigsMax())[])
1-element Vector{StaticBitVector{8, 1}}:
+ 10100100

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 function.

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

Similarly, if one is only interested in computing one of the maximum set packing, one can use the graph property SingleConfigMax.


This page was generated using Literate.jl.

diff --git a/dev/generated/SpinGlass/index.html b/dev/generated/SpinGlass/index.html index 1b46049..0a5b774 100644 --- a/dev/generated/SpinGlass/index.html +++ b/dev/generated/SpinGlass/index.html @@ -33,14 +33,14 @@ '/>

Generic tensor network representation

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

spinglass = SpinGlass(graph, fill(1, ne(graph)), zeros(Int, nv(graph)))
SpinGlass{SimpleGraph{Int64}, Int64, Vector{Int64}}(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], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

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

problem = GenericTensorNetwork(spinglass)
GenericTensorNetwork{SpinGlass{SimpleGraph{Int64}, Int64, Vector{Int64}}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
 - open vertices: Int64[]
 - fixed vertices: Dict{Int64, Int64}()
-- contraction time = 2^8.0, space = 2^4.0, read-write = 2^8.704

The contraction order is already optimized.

The tensor network reduction

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

\[\begin{cases} +- contraction time = 2^8.17, space = 2^5.0, read-write = 2^8.861

The contraction order is already optimized.

The tensor network reduction

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

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

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

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

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

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

Graph properties

Minimum and maximum energies

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

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

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

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

Counting properties

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

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

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

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

Configuration properties

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

ground_state = read_config(solve(problem, SingleConfigMin())[])
0110110011

The energy of the ground state can be verified by the energy 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))
-9

You should see a consistent result as above Emin.

show_graph(graph, locations; vertex_colors=[
+\end{cases}\]

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

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

Graph properties

Minimum and maximum energies

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

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

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

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

Counting properties

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

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

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

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

Configuration properties

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

ground_state = read_config(solve(problem, SingleConfigMin())[])
0100100110

The energy of the ground state can be verified by the energy 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))
-9

You should see a consistent result as above Emin.

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

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

Spin-glass problem on a hypergraph

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

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

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

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

num_vertices = 15
 
@@ -84,4 +84,4 @@
 - open vertices: Int64[]
 - fixed vertices: Dict{Int64, Int64}()
 - contraction time = 2^9.807, space = 2^6.0, read-write = 2^10.53

Graph properties

Minimum and maximum energies

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

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

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

Counting properties

partition function and graph polynomial

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

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

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

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

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

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

The graph polynomial is

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

Configuration properties

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

ground_state = read_config(solve(hyperproblem, SingleConfigMin())[])
101101011001111

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

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

You should see a consistent result as above Emin.


This page was generated using Literate.jl.

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

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

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

The graph polynomial is

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

Configuration properties

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

ground_state = read_config(solve(hyperproblem, SingleConfigMin())[])
010111011001100

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

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

You should see a consistent result as above Emin.


This page was generated using Literate.jl.

diff --git a/dev/generated/open/index.html b/dev/generated/open/index.html index dd06cf6..cb198f9 100644 --- a/dev/generated/open/index.html +++ b/dev/generated/open/index.html @@ -26,4 +26,4 @@ [:, :, 2] = 4.0ₜ -Infₜ - 4.0ₜ -Infₜ

One can easily check this one also gets the correct marginal on vertices 1, 2 and 3. As a reminder, their computational hardness can be different, because the contraction order optimization program can optimize over open degrees of freedom.


This page was generated using Literate.jl.

+ 4.0ₜ -Infₜ

One can easily check this one also gets the correct marginal on vertices 1, 2 and 3. As a reminder, their computational hardness can be different, because the contraction order optimization program can optimize over open degrees of freedom.


This page was generated using Literate.jl.

diff --git a/dev/generated/saveload/index.html b/dev/generated/saveload/index.html index 0804938..bc10830 100644 --- a/dev/generated/saveload/index.html +++ b/dev/generated/saveload/index.html @@ -3,87 +3,97 @@ problem = GenericTensorNetwork(IndependentSet(Graphs.smallgraph(:petersen))) -all_independent_sets = solve(problem, ConfigsAll())[]
{0010010001, 1010000011, 0010000011, 1010000001, 0010000001, 0010111000, 0010011000, 0010110000, 0010010000, 1010000010, 0010100010, 0010000010, 1010001000, 0010101000, 0010001000, 1010000000, 0010100000, 0010000000, 0000010001, 1000000011, 0000000011, 1000000001, 0000000001, 0000111000, 0000011000, 0000110000, 0000010000, 1000000010, 0000100010, 0000000010, 1000001000, 0000101000, 0000001000, 1000000000, 0000100000, 0000000000, 0100010001, 0100000011, 0100000001, 0100110000, 0100010000, 0100100010, 0100000010, 0100100000, 0100000000, 0001010001, 1001000001, 0001000001, 0001011000, 0001010000, 1001001000, 0001001000, 1001000000, 0001000000, 0101010001, 0101000001, 0101010000, 0101000000, 1000000110, 0000100110, 0000000110, 1000001100, 0000101100, 0000001100, 1000000100, 0000100100, 0000000100, 0100100110, 0100000110, 0100100100, 0100000100, 1001001100, 0001001100, 1001000100, 0001000100, 0101000100}

The return value has type ConfigEnumerator. We can use save_configs and load_configs to save and read a ConfigEnumerator instance to the disk.

filename = tempname()
+all_independent_sets = solve(problem, ConfigsAll())[]
{0000010001, 1000000011, 0000000011, 1000000001, 0000000001, 0000111000, 0000011000, 0000110000, 0000010000, 0000100110, 1000000110, 0000000110, 0000101100, 1000001100, 0000001100, 0000100100, 1000000100, 0000000100, 0000100010, 1000000010, 0000000010, 0000101000, 1000001000, 0000001000, 0000100000, 1000000000, 0000000000, 0100010001, 0100000011, 0100000001, 0100110000, 0100010000, 0100100110, 0100000110, 0100100100, 0100000100, 0100100010, 0100000010, 0100100000, 0100000000, 0001010001, 1001000001, 0001000001, 0001011000, 0001010000, 1001001100, 0001001100, 1001000100, 0001000100, 1001001000, 0001001000, 1001000000, 0001000000, 0101010001, 0101000001, 0101010000, 0101000100, 0101000000, 0010010001, 1010000011, 0010000011, 1010000001, 0010000001, 0010111000, 0010011000, 0010110000, 0010010000, 0010100010, 1010000010, 0010000010, 0010101000, 1010001000, 0010001000, 0010100000, 1010000000, 0010000000}

The return value has type ConfigEnumerator. We can use save_configs and load_configs to save and read a ConfigEnumerator instance to the disk.

filename = tempname()
 
 save_configs(filename, all_independent_sets; format=:binary)
 
-loaded_sets = load_configs(filename; format=:binary, bitlength=10)
{0010010001, 1010000011, 0010000011, 1010000001, 0010000001, 0010111000, 0010011000, 0010110000, 0010010000, 1010000010, 0010100010, 0010000010, 1010001000, 0010101000, 0010001000, 1010000000, 0010100000, 0010000000, 0000010001, 1000000011, 0000000011, 1000000001, 0000000001, 0000111000, 0000011000, 0000110000, 0000010000, 1000000010, 0000100010, 0000000010, 1000001000, 0000101000, 0000001000, 1000000000, 0000100000, 0000000000, 0100010001, 0100000011, 0100000001, 0100110000, 0100010000, 0100100010, 0100000010, 0100100000, 0100000000, 0001010001, 1001000001, 0001000001, 0001011000, 0001010000, 1001001000, 0001001000, 1001000000, 0001000000, 0101010001, 0101000001, 0101010000, 0101000000, 1000000110, 0000100110, 0000000110, 1000001100, 0000101100, 0000001100, 1000000100, 0000100100, 0000000100, 0100100110, 0100000110, 0100100100, 0100000100, 1001001100, 0001001100, 1001000100, 0001000100, 0101000100}
Note

When loading the data in the binary format, bit string length information bitlength is required.

For the SumProductTree type output, we can use save_sumproduct and load_sumproduct to save and load serialized data.

all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]
+loaded_sets = load_configs(filename; format=:binary, bitlength=10)
{0000010001, 1000000011, 0000000011, 1000000001, 0000000001, 0000111000, 0000011000, 0000110000, 0000010000, 0000100110, 1000000110, 0000000110, 0000101100, 1000001100, 0000001100, 0000100100, 1000000100, 0000000100, 0000100010, 1000000010, 0000000010, 0000101000, 1000001000, 0000001000, 0000100000, 1000000000, 0000000000, 0100010001, 0100000011, 0100000001, 0100110000, 0100010000, 0100100110, 0100000110, 0100100100, 0100000100, 0100100010, 0100000010, 0100100000, 0100000000, 0001010001, 1001000001, 0001000001, 0001011000, 0001010000, 1001001100, 0001001100, 1001000100, 0001000100, 1001001000, 0001001000, 1001000000, 0001000000, 0101010001, 0101000001, 0101010000, 0101000100, 0101000000, 0010010001, 1010000011, 0010000011, 1010000001, 0010000001, 0010111000, 0010011000, 0010110000, 0010010000, 0010100010, 1010000010, 0010000010, 0010101000, 1010001000, 0010001000, 0010100000, 1010000000, 0010000000}
Note

When loading the data in the binary format, bit string length information bitlength is required.

For the SumProductTree type output, we can use save_sumproduct and load_sumproduct to save and load serialized data.

all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]
 
 save_sumproduct(filename, all_independent_sets_tree)
 
 loaded_sets_tree = load_sumproduct(filename)
+ (count = 76.0)
-├─ + (count = 75.0)
-│  ├─ + (count = 71.0)
-│  │  ├─ + (count = 67.0)
-│  │  │  ├─ + (count = 58.0)
-│  │  │  │  ├─ + (count = 54.0)
+├─ + (count = 58.0)
+│  ├─ + (count = 53.0)
+│  │  ├─ + (count = 40.0)
+│  │  │  ├─ + (count = 27.0)
+│  │  │  │  ├─ * (count = 1.0)
 │  │  │  │  │  ⋮
 │  │  │  │  │  
-│  │  │  │  └─ * (count = 4.0)
+│  │  │  │  └─ + (count = 26.0)
 │  │  │  │     ⋮
 │  │  │  │     
-│  │  │  └─ * (count = 9.0)
-│  │  │     ├─ * (count = 9.0)
+│  │  │  └─ * (count = 13.0)
+│  │  │     ├─ + (count = 13.0)
 │  │  │     │  ⋮
 │  │  │     │  
-│  │  │     └─ * (count = 1.0)
-│  │  │        ⋮
-│  │  │        
-│  │  └─ * (count = 4.0)
-│  │     ├─ * (count = 4.0)
-│  │     │  ├─ * (count = 4.0)
+│  │  │     └─ OnehotVec{10, 2}(2, 1)
+│  │  └─ * (count = 13.0)
+│  │     ├─ + (count = 13.0)
+│  │     │  ├─ * (count = 1.0)
 │  │     │  │  ⋮
 │  │     │  │  
-│  │     │  └─ * (count = 1.0)
+│  │     │  └─ + (count = 12.0)
 │  │     │     ⋮
 │  │     │     
 │  │     └─ * (count = 1.0)
-│  │        ├─ OnehotVec{10, 2}(2, 1)
-│  │        └─ * (count = 1.0)
-│  │           ⋮
-│  │           
-│  └─ * (count = 4.0)
-│     ├─ * (count = 4.0)
-│     │  ├─ * (count = 4.0)
-│     │  │  ├─ + (count = 2.0)
+│  │        ├─ OnehotVec{10, 2}(4, 1)
+│  │        └─ OnehotVec{10, 2}(4, 1)
+│  └─ * (count = 5.0)
+│     ├─ + (count = 5.0)
+│     │  ├─ * (count = 1.0)
+│     │  │  ├─ * (count = 1.0)
 │     │  │  │  ⋮
 │     │  │  │  
-│     │  │  └─ * (count = 2.0)
+│     │  │  └─ * (count = 1.0)
 │     │  │     ⋮
 │     │  │     
-│     │  └─ * (count = 1.0)
-│     │     ├─ OnehotVec{10, 2}(8, 1)
-│     │     └─ OnehotVec{10, 2}(8, 1)
+│     │  └─ + (count = 4.0)
+│     │     ├─ * (count = 1.0)
+│     │     │  ⋮
+│     │     │  
+│     │     └─ + (count = 3.0)
+│     │        ⋮
+│     │        
 │     └─ * (count = 1.0)
-│        ├─ * (count = 1.0)
-│        │  ├─ OnehotVec{10, 2}(8, 1)
-│        │  └─ OnehotVec{10, 2}(8, 1)
+│        ├─ OnehotVec{10, 2}(2, 1)
 │        └─ * (count = 1.0)
 │           ├─ OnehotVec{10, 2}(4, 1)
 │           └─ OnehotVec{10, 2}(4, 1)
-└─ * (count = 1.0)
-   ├─ * (count = 1.0)
+└─ * (count = 18.0)
+   ├─ + (count = 18.0)
    │  ├─ * (count = 1.0)
    │  │  ├─ * (count = 1.0)
    │  │  │  ├─ * (count = 1.0)
    │  │  │  │  ⋮
    │  │  │  │  
-   │  │  │  └─ OnehotVec{10, 2}(4, 1)
+   │  │  │  └─ * (count = 1.0)
+   │  │  │     ⋮
+   │  │  │     
    │  │  └─ * (count = 1.0)
-   │  │     ├─ OnehotVec{10, 2}(2, 1)
-   │  │     └─ OnehotVec{10, 2}(4, 1)
-   │  └─ * (count = 1.0)
-   │     ├─ OnehotVec{10, 2}(8, 1)
-   │     └─ OnehotVec{10, 2}(8, 1)
+   │  │     ├─ * (count = 1.0)
+   │  │     │  ⋮
+   │  │     │  
+   │  │     └─ OnehotVec{10, 2}(10, 1)
+   │  └─ + (count = 17.0)
+   │     ├─ * (count = 4.0)
+   │     │  ├─ * (count = 4.0)
+   │     │  │  ⋮
+   │     │  │  
+   │     │  └─ * (count = 1.0)
+   │     │     ⋮
+   │     │     
+   │     └─ + (count = 13.0)
+   │        ├─ * (count = 4.0)
+   │        │  ⋮
+   │        │  
+   │        └─ * (count = 9.0)
+   │           ⋮
+   │           
    └─ * (count = 1.0)
       ├─ * (count = 1.0)
-      │  ├─ OnehotVec{10, 2}(2, 1)
-      │  └─ * (count = 1.0)
-      │     ├─ OnehotVec{10, 2}(8, 1)
-      │     └─ OnehotVec{10, 2}(8, 1)
-      └─ * (count = 1.0)
-         ├─ OnehotVec{10, 2}(4, 1)
-         └─ OnehotVec{10, 2}(4, 1)
+      │  ├─ OnehotVec{10, 2}(3, 1)
+      │  └─ OnehotVec{10, 2}(3, 1)
+      └─ OnehotVec{10, 2}(3, 1)
 

Loading solutions to python

The following python script loads and unpacks the solutions as a numpy array from a :binary format file.

import numpy as np
 
 def loadfile(filename:str, bitlength:int):
@@ -95,4 +105,4 @@
     print("number of solutions = %d"%(len(res)))
     return res  # in big endian format
 
-res = loadfile(filename, 10)
Note

Check section Maximal independent set problem for solution space properties related the maximal independent sets. That example also contains using cases of finding solution space properties related to minimum sizes:

  • SizeMin for finding minimum several set sizes,
  • CountingMin for counting minimum several set sizes,
  • SingleConfigMin for finding one solution with minimum several sizes,
  • ConfigsMin for enumerating solutions with minimum several sizes,

This page was generated using Literate.jl.

+res = loadfile(filename, 10)
Note

Check section Maximal independent set problem for solution space properties related the maximal independent sets. That example also contains using cases of finding solution space properties related to minimum sizes:

  • SizeMin for finding minimum several set sizes,
  • CountingMin for counting minimum several set sizes,
  • SingleConfigMin for finding one solution with minimum several sizes,
  • ConfigsMin for enumerating solutions with minimum several sizes,

This page was generated using Literate.jl.

diff --git a/dev/generated/weighted/245a5454.svg b/dev/generated/weighted/68c9362b.svg similarity index 92% rename from dev/generated/weighted/245a5454.svg rename to dev/generated/weighted/68c9362b.svg index ba63f6b..6b1d2c5 100644 --- a/dev/generated/weighted/245a5454.svg +++ b/dev/generated/weighted/68c9362b.svg @@ -17,14 +17,14 @@ - - - + + + - + - + @@ -42,14 +42,14 @@ - - - + + + - + - + diff --git a/dev/generated/weighted/index.html b/dev/generated/weighted/index.html index 24dba33..de9e9a8 100644 --- a/dev/generated/weighted/index.html +++ b/dev/generated/weighted/index.html @@ -65,8 +65,8 @@ 22.0ₜ 23.0ₜ 24.0ₜ

We can see the order is a vector of Tropical numbers. Similarly, we can get weighted independent sets with maximum 5 sizes as follows.

max5_configs = read_config(solve(problem, SingleConfigMax(5))[])
5-element Vector{StaticBitVector{10, 1}}:
- 0010000011
  0101010001
+ 0010000011
  0000100110
  1010000011
- 0100100110

The return value of solve has type ExtendedTropical, but this time the element type of orders has been changed to CountingTropical{Float64,ConfigSampler}. Let us visually check these configurations

show_configs(graph, locations, [max5_configs[j] for i=1:1, j=1:5]; padding_left=20)
Example block output

This page was generated using Literate.jl.

+ 0100100110

The return value of solve has type ExtendedTropical, but this time the element type of orders has been changed to CountingTropical{Float64,ConfigSampler}. Let us visually check these configurations

show_configs(graph, locations, [max5_configs[j] for i=1:1, j=1:5]; padding_left=20)
Example block output

This page was generated using Literate.jl.

diff --git a/dev/gist/index.html b/dev/gist/index.html index 3d701e7..3d88c1c 100644 --- a/dev/gist/index.html +++ b/dev/gist/index.html @@ -112,4 +112,4 @@ println("one of the optimal configurations is $(mis_config(optimized_code; all=false)[].c.data)") # direct enumeration of configurations can be very slow; please check the bounding version in our Github repo. -println("all optimal configurations are $(mis_config(optimized_code; all=true)[].c)") +println("all optimal configurations are $(mis_config(optimized_code; all=true)[].c)") diff --git a/dev/index.html b/dev/index.html index 77ccfc8..ce57951 100644 --- a/dev/index.html +++ b/dev/index.html @@ -10,6 +10,6 @@ GraphPolynomial(); usecuda=false # the default value )0-dimensional Array{Polynomial{BigInt, :x}, 0}: -Polynomial(1 + 20*x + 160*x^2 + 659*x^3 + 1501*x^4 + 1895*x^5 + 1270*x^6 + 414*x^7 + 53*x^8 + x^9)

Here the main function solve takes three input arguments, the problem instance of type IndependentSet, the property instance of type GraphPolynomial and an optional key word argument usecuda to decide use GPU or not. If one wants to use GPU to accelerate the computation, the , CUDA should be uncommented.

An IndependentSet instance takes two positional arguments to initialize, the graph instance that one wants to solve and the weights for each vertex. Here, we use a random regular graph with 20 vertices and degree 3, and the default uniform weight 1.

The GenericTensorNetwork function is a constructor for the problem instance, which takes the problem instance as the first argument and optional key word arguments. The key word argument optimizer is for specifying the tensor network optimization algorithm. The keyword argument openvertices is a tuple of labels for specifying the degrees of freedom not summed over, and fixedvertices is a label-value dictionary for specifying the fixed values of the degree of freedoms. Here, we use TreeSA method as the tensor network optimizer, and leave openvertices the default values. The TreeSA method finds the best contraction order in most of our applications, while the default GreedyMethod runs the fastest.

The first execution of this function will be a bit slow due to Julia's just in time compiling. The subsequent runs will be fast. The following diagram lists possible combinations of input arguments, where functions in the Graph are mainly defined in the package Graphs, and the rest can be found in this package.

+Polynomial(1 + 20*x + 160*x^2 + 658*x^3 + 1488*x^4 + 1835*x^5 + 1146*x^6 + 302*x^7 + 20*x^8)

Here the main function solve takes three input arguments, the problem instance of type IndependentSet, the property instance of type GraphPolynomial and an optional key word argument usecuda to decide use GPU or not. If one wants to use GPU to accelerate the computation, the , CUDA should be uncommented.

An IndependentSet instance takes two positional arguments to initialize, the graph instance that one wants to solve and the weights for each vertex. Here, we use a random regular graph with 20 vertices and degree 3, and the default uniform weight 1.

The GenericTensorNetwork function is a constructor for the problem instance, which takes the problem instance as the first argument and optional key word arguments. The key word argument optimizer is for specifying the tensor network optimization algorithm. The keyword argument openvertices is a tuple of labels for specifying the degrees of freedom not summed over, and fixedvertices is a label-value dictionary for specifying the fixed values of the degree of freedoms. Here, we use TreeSA method as the tensor network optimizer, and leave openvertices the default values. The TreeSA method finds the best contraction order in most of our applications, while the default GreedyMethod runs the fastest.

The first execution of this function will be a bit slow due to Julia's just in time compiling. The subsequent runs will be fast. The following diagram lists possible combinations of input arguments, where functions in the Graph are mainly defined in the package Graphs, and the rest can be found in this package.

-

⠀ You can find many examples in this documentation, a good one to start with is Independent set problem.

+

⠀ You can find many examples in this documentation, a good one to start with is Independent set problem.

diff --git a/dev/performancetips/index.html b/dev/performancetips/index.html index 3637318..455658b 100644 --- a/dev/performancetips/index.html +++ b/dev/performancetips/index.html @@ -1,12 +1,12 @@ -Performance Tips · GenericTensorNetworks.jl

Performance Tips

Optimize contraction orders

Let us use the independent set problem on 3-regular graphs as an example.

julia> using GenericTensorNetworks, Graphs, Random
julia> graph = random_regular_graph(120, 3){120, 180} undirected simple Int64 graph
julia> iset = IndependentSet(graph)IndependentSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(180, [[9, 38, 56], [5, 47, 74], [36, 78, 107], [6, 77, 105], [2, 65, 100], [4, 46, 63], [38, 57, 64], [14, 95, 106], [1, 37, 66], [47, 94, 106] … [16, 23, 45], [25, 43, 88], [18, 19, 23], [13, 14, 37], [21, 90, 103], [16, 75, 103], [37, 41, 58], [35, 44, 106], [56, 57, 81], [21, 25, 74]]), [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA( - sc_target=20, sc_weight=1.0, rw_weight=3.0, ntrials=10, βs=0.01:0.1:15.0, niters=20));

The GenericTensorNetwork constructor maps an independent set problem to a tensor network with optimized contraction order. The key word argument optimizer specifies the contraction order optimizer of the tensor network. Here, we choose the local search based TreeSA algorithm, which often finds the smallest time/space complexity and supports slicing. One can type ?TreeSA in a Julia REPL for more information about how to configure the hyper-parameters of the TreeSA method, while the detailed algorithm explanation is in arXiv: 2108.05665. Alternative tensor network contraction order optimizers include

For example, the MergeGreedy() here "contracts" tensors greedily whenever the contraction result has a smaller space complexity. It can remove all vertex tensors (vectors) before entering the contraction order optimization algorithm.

The returned object problem contains a field code that specifies the tensor network with optimized contraction order. For an independent set problem, the optimal contraction time/space complexity is $\sim 2^{{\rm tw}(G)}$, where ${\rm tw(G)}$ is the tree-width of $G$. One can check the time, space and read-write complexity with the contraction_complexity function.

julia> contraction_complexity(problem)Time complexity: 2^19.663342673395327
-Space complexity: 2^14.0
-Read-write complexity: 2^16.98700858624569

The return values are log2 values of the number of multiplications, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements. In this example, the number * operations is $\sim 2^{21.9}$, the number of read-write operations are $\sim 2^{20}$, and the largest tensor size is $2^{17}$. One can check the element size by typing

julia> sizeof(TropicalF64)8
julia> sizeof(TropicalF32)4
julia> sizeof(StaticBitVector{200,4})32
julia> sizeof(TruncatedPoly{5,Float64,Float64})48

One can use estimate_memory to get a good estimation of peak memory in bytes. For example, to compute the graph polynomial, the peak memory can be estimated as follows.

julia> estimate_memory(problem, GraphPolynomial(; method=:finitefield))165936
julia> estimate_memory(problem, GraphPolynomial(; method=:polynomial))39824640

The finite field approach only requires 298 KB memory, while using the Polynomial number type requires 71 MB memory.

Note
  • The actual run time memory can be several times larger than the size of the maximum tensor, so the estimate_memory is more accurate in estimating the peak memory.
  • For mutable element types like ConfigEnumerator, none of memory estimation functions measure the actual memory usage correctly.

Slicing technique

For large scale applications, it is also possible to slice over certain degrees of freedom to reduce the space complexity, i.e. loop and accumulate over certain degrees of freedom so that one can have a smaller tensor network inside the loop due to the removal of these degrees of freedom. In the TreeSA optimizer, one can set nslices to a value larger than zero to turn on this feature.

julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));
julia> contraction_complexity(problem)Time complexity: 2^19.543311303259614 -Space complexity: 2^14.0 -Read-write complexity: 2^17.181550232334953
julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));
julia> contraction_complexity(problem)Time complexity: 2^19.79796543240424 -Space complexity: 2^10.0 -Read-write complexity: 2^19.257535169222354

In the second IndependentSet constructor, we slice over 5 degrees of freedom, which can reduce the space complexity by at most 5. In this application, the slicing achieves the largest possible space complexity reduction 5, while the time and read-write complexity are only increased by less than 1, i.e. the peak memory usage is reduced by a factor $32$, while the (theoretical) computing time is increased by at a factor $< 2$.

GEMM for Tropical numbers

One can speed up the Tropical number matrix multiplication when computing the solution space property SizeMax() by using the Tropical GEMM routines implemented in package TropicalGEMM.

julia> using BenchmarkTools
+Performance Tips · GenericTensorNetworks.jl

Performance Tips

Optimize contraction orders

Let us use the independent set problem on 3-regular graphs as an example.

julia> using GenericTensorNetworks, Graphs, Random
julia> graph = random_regular_graph(120, 3){120, 180} undirected simple Int64 graph
julia> iset = IndependentSet(graph)IndependentSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(180, [[33, 34, 114], [98, 110, 118], [5, 39, 86], [98, 106, 115], [3, 83, 95], [22, 37, 75], [20, 28, 40], [55, 58, 109], [32, 39, 91], [63, 65, 97] … [11, 54, 85], [43, 79, 116], [60, 95, 97], [1, 37, 48], [4, 26, 91], [39, 76, 112], [31, 64, 69], [2, 54, 86], [14, 51, 80], [12, 90, 103]]), [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA( + sc_target=20, sc_weight=1.0, rw_weight=3.0, ntrials=10, βs=0.01:0.1:15.0, niters=20));

The GenericTensorNetwork constructor maps an independent set problem to a tensor network with optimized contraction order. The key word argument optimizer specifies the contraction order optimizer of the tensor network. Here, we choose the local search based TreeSA algorithm, which often finds the smallest time/space complexity and supports slicing. One can type ?TreeSA in a Julia REPL for more information about how to configure the hyper-parameters of the TreeSA method, while the detailed algorithm explanation is in arXiv: 2108.05665. Alternative tensor network contraction order optimizers include

For example, the MergeGreedy() here "contracts" tensors greedily whenever the contraction result has a smaller space complexity. It can remove all vertex tensors (vectors) before entering the contraction order optimization algorithm.

The returned object problem contains a field code that specifies the tensor network with optimized contraction order. For an independent set problem, the optimal contraction time/space complexity is $\sim 2^{{\rm tw}(G)}$, where ${\rm tw(G)}$ is the tree-width of $G$. One can check the time, space and read-write complexity with the contraction_complexity function.

julia> contraction_complexity(problem)Time complexity: 2^21.18276047073739
+Space complexity: 2^16.0
+Read-write complexity: 2^19.17065127332141

The return values are log2 values of the number of multiplications, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements. In this example, the number * operations is $\sim 2^{21.9}$, the number of read-write operations are $\sim 2^{20}$, and the largest tensor size is $2^{17}$. One can check the element size by typing

julia> sizeof(TropicalF64)8
julia> sizeof(TropicalF32)4
julia> sizeof(StaticBitVector{200,4})32
julia> sizeof(TruncatedPoly{5,Float64,Float64})48

One can use estimate_memory to get a good estimation of peak memory in bytes. For example, to compute the graph polynomial, the peak memory can be estimated as follows.

julia> estimate_memory(problem, GraphPolynomial(; method=:finitefield))532592
julia> estimate_memory(problem, GraphPolynomial(; method=:polynomial))127822080

The finite field approach only requires 298 KB memory, while using the Polynomial number type requires 71 MB memory.

Note
  • The actual run time memory can be several times larger than the size of the maximum tensor, so the estimate_memory is more accurate in estimating the peak memory.
  • For mutable element types like ConfigEnumerator, none of memory estimation functions measure the actual memory usage correctly.

Slicing technique

For large scale applications, it is also possible to slice over certain degrees of freedom to reduce the space complexity, i.e. loop and accumulate over certain degrees of freedom so that one can have a smaller tensor network inside the loop due to the removal of these degrees of freedom. In the TreeSA optimizer, one can set nslices to a value larger than zero to turn on this feature.

julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));
julia> contraction_complexity(problem)Time complexity: 2^20.861677606481805 +Space complexity: 2^16.0 +Read-write complexity: 2^19.83282976466858
julia> problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));
julia> contraction_complexity(problem)Time complexity: 2^21.041915775225846 +Space complexity: 2^11.0 +Read-write complexity: 2^20.204189023987166

In the second IndependentSet constructor, we slice over 5 degrees of freedom, which can reduce the space complexity by at most 5. In this application, the slicing achieves the largest possible space complexity reduction 5, while the time and read-write complexity are only increased by less than 1, i.e. the peak memory usage is reduced by a factor $32$, while the (theoretical) computing time is increased by at a factor $< 2$.

GEMM for Tropical numbers

One can speed up the Tropical number matrix multiplication when computing the solution space property SizeMax() by using the Tropical GEMM routines implemented in package TropicalGEMM.

julia> using BenchmarkTools
 
 julia> @btime solve(problem, SizeMax())
   91.630 ms (19203 allocations: 23.72 MiB)
@@ -47,4 +47,4 @@
 
 julia> solve(problem, SizeMax(), usecuda=true)
 0-dimensional CuArray{TropicalF64, 0, CUDA.Mem.DeviceBuffer}:
-53.0ₜ

Solution space properties computable on GPU includes

Benchmarks

We run a single thread benchmark on central processing units (CPU) Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz, and its CUDA version on a GPU Tesla V100-SXM2 16G. The results are summarized in the following plot. The benchmark code can be found in our paper repository.

benchmark-independent-set This benchmark results is for computing different solution space properties of independent sets of random three-regular graphs with different tensor element types. The time in these plots only includes tensor network contraction, without taking into account the contraction order finding and just-in-time compilation time. Legends are properties, algebra, and devices that we used in the computation; one can find the corresponding computed solution space property in Table 1 in the paper.

  • (a) time and space complexity versus the number of vertices for the benchmarked graphs.
  • (b) The computation time for calculating the MIS size and for counting the number of all independent sets (ISs), the number of MISs, the number of independent sets having size $\alpha(G)$ and $\alpha(G)-1$, and finding 100 largest set sizes.
  • (c) The computation time for calculating the independence polynomials with different approaches.
  • (d) The computation time for configuration enumeration, including single MIS configuration, the enumeration of all independent set configurations, all MIS configurations, all independent sets, and all independent set configurations having size $\alpha(G)$ and $\alpha(G)-1$.

The graphs in all benchmarks are random three-regular graphs, which have treewidth that is asymptotically smaller than $|V|/6$. In this benchmark, we do not include traditional algorithms for finding the MIS sizes such as branching or dynamic programming. To the best of our knowledge, these algorithms are not suitable for computing most of the solution space properties mentioned in this paper. The main goal of this section is to show the relative computation time for calculating different solution space properties.

Panel (a) shows the time and space complexity of tensor network contraction for different graph sizes. The contraction order is obtained using the TreeSA algorithm that implemented in OMEinsumContractionOrders. If we assume our contraction-order finding program has found the optimal treewidth, which is very likely to be true, the space complexity is the same as the treewidth of the problem graph. Slicing technique has been used for graphs with space complexity greater than $2^{27}$ (above the yellow dashed line) to fit the computation into a 16GB memory. One can see that all the computation times in panels (b), (c), and (d) have a strong correlation with the predicted time and space complexity. While in panel (d), the computation time of configuration enumeration also strongly correlates with other factors such as the configuration space size. Among these benchmarks, computational tasks with data types real numbers, complex numbers, or Tropical numbers (CPU only) can utilize fast basic linear algebra subprograms (BLAS) functions. These tasks usually compute much faster than ones with other element types in the same category. Immutable data types with no reference to other values can be compiled to GPU devices that run much faster than CPUs in all cases when the problem scale is big enough. These data types do not include those defined in Polynomial, ConfigEnumerator, ExtendedTropical and SumProductTree or a data type containing them as a part. In panel (c), one can see the Fourier transformation-based method is the fastest in computing the independence polynomial, but it may suffer from round-off errors. The finite field (GF(p)) approach is the only method that does not have round-off errors and can be run on a GPU. In panel (d), one can see the technique to bound the enumeration space (see paper) improves the performance for more than one order of magnitude in enumerating the MISs. The bounding technique can also reduce the memory usage significantly, without which the largest computable graph size is only $\sim150$ on a device with 32GB main memory.

We show the benchmark of computing the maximal independent set properties on 3-regular graphs in the following plot, including a comparison to the Bron-Kerbosch algorithm from Julia package Graphs

benchmark-maximal-independent-set

In this plot, benchmarks of computing different solution space properties of the maximal independent sets (ISs) problem on random three regular graphs at different sizes.

  • (a) time and space complexity of tensor network contraction.
  • (b) The wall clock time for counting and enumeration of maximal ISs.

Panel (a) shows the space and time complexities of tensor contraction, which are typically larger than those for the independent set problem. In panel (b), one can see counting maximal independent sets are much more efficient than enumerating them, while our generic tensor network approach runs slightly faster than the Bron-Kerbosch approach in enumerating all maximal independent sets.

+53.0ₜ

Solution space properties computable on GPU includes

Benchmarks

We run a single thread benchmark on central processing units (CPU) Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz, and its CUDA version on a GPU Tesla V100-SXM2 16G. The results are summarized in the following plot. The benchmark code can be found in our paper repository.

benchmark-independent-set This benchmark results is for computing different solution space properties of independent sets of random three-regular graphs with different tensor element types. The time in these plots only includes tensor network contraction, without taking into account the contraction order finding and just-in-time compilation time. Legends are properties, algebra, and devices that we used in the computation; one can find the corresponding computed solution space property in Table 1 in the paper.

  • (a) time and space complexity versus the number of vertices for the benchmarked graphs.
  • (b) The computation time for calculating the MIS size and for counting the number of all independent sets (ISs), the number of MISs, the number of independent sets having size $\alpha(G)$ and $\alpha(G)-1$, and finding 100 largest set sizes.
  • (c) The computation time for calculating the independence polynomials with different approaches.
  • (d) The computation time for configuration enumeration, including single MIS configuration, the enumeration of all independent set configurations, all MIS configurations, all independent sets, and all independent set configurations having size $\alpha(G)$ and $\alpha(G)-1$.

The graphs in all benchmarks are random three-regular graphs, which have treewidth that is asymptotically smaller than $|V|/6$. In this benchmark, we do not include traditional algorithms for finding the MIS sizes such as branching or dynamic programming. To the best of our knowledge, these algorithms are not suitable for computing most of the solution space properties mentioned in this paper. The main goal of this section is to show the relative computation time for calculating different solution space properties.

Panel (a) shows the time and space complexity of tensor network contraction for different graph sizes. The contraction order is obtained using the TreeSA algorithm that implemented in OMEinsumContractionOrders. If we assume our contraction-order finding program has found the optimal treewidth, which is very likely to be true, the space complexity is the same as the treewidth of the problem graph. Slicing technique has been used for graphs with space complexity greater than $2^{27}$ (above the yellow dashed line) to fit the computation into a 16GB memory. One can see that all the computation times in panels (b), (c), and (d) have a strong correlation with the predicted time and space complexity. While in panel (d), the computation time of configuration enumeration also strongly correlates with other factors such as the configuration space size. Among these benchmarks, computational tasks with data types real numbers, complex numbers, or Tropical numbers (CPU only) can utilize fast basic linear algebra subprograms (BLAS) functions. These tasks usually compute much faster than ones with other element types in the same category. Immutable data types with no reference to other values can be compiled to GPU devices that run much faster than CPUs in all cases when the problem scale is big enough. These data types do not include those defined in Polynomial, ConfigEnumerator, ExtendedTropical and SumProductTree or a data type containing them as a part. In panel (c), one can see the Fourier transformation-based method is the fastest in computing the independence polynomial, but it may suffer from round-off errors. The finite field (GF(p)) approach is the only method that does not have round-off errors and can be run on a GPU. In panel (d), one can see the technique to bound the enumeration space (see paper) improves the performance for more than one order of magnitude in enumerating the MISs. The bounding technique can also reduce the memory usage significantly, without which the largest computable graph size is only $\sim150$ on a device with 32GB main memory.

We show the benchmark of computing the maximal independent set properties on 3-regular graphs in the following plot, including a comparison to the Bron-Kerbosch algorithm from Julia package Graphs

benchmark-maximal-independent-set

In this plot, benchmarks of computing different solution space properties of the maximal independent sets (ISs) problem on random three regular graphs at different sizes.

  • (a) time and space complexity of tensor network contraction.
  • (b) The wall clock time for counting and enumeration of maximal ISs.

Panel (a) shows the space and time complexities of tensor contraction, which are typically larger than those for the independent set problem. In panel (b), one can see counting maximal independent sets are much more efficient than enumerating them, while our generic tensor network approach runs slightly faster than the Bron-Kerbosch approach in enumerating all maximal independent sets.

diff --git a/dev/ref/index.html b/dev/ref/index.html index e37ee94..0bfe5a5 100644 --- a/dev/ref/index.html +++ b/dev/ref/index.html @@ -1,5 +1,5 @@ -References · GenericTensorNetworks.jl

References

Constraint Satisfaction Problems

GenericTensorNetworks.solveFunction
solve(problem, property; usecuda=false, T=Float64)

Solving a certain property of a graph problem.

Positional Arguments

  • problem is the graph problem with tensor network information,

  • property is string specifying the task. Using the maximum independent set problem as an example, it can be one of

    • PartitionFunction() 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

  • usecuda is a switch to use CUDA (if possible), user need to call statement using CUDA before turning on this switch.
  • T is the "base" element type, sometimes can be used to reduce the memory cost.
source
GenericTensorNetworks.GenericTensorNetworkType
struct GenericTensorNetwork{CFG, CT, LT}
GenericTensorNetwork(problem::ConstraintSatisfactionProblem; openvertices=(), fixedvertices=Dict(), optimizer=GreedyMethod())

The generic tensor network that generated from a ConstraintSatisfactionProblem.

Positional arguments

  • problem is the graph problem.
  • code is the tensor network contraction code.
  • fixedvertices is a dictionary specifying the fixed dimensions.
source
ProblemReductions.ConstraintSatisfactionProblemType
ConstraintSatisfactionProblem{T} <: AbstractProblem

The abstract base type of constraint satisfaction problems. T is the type of the local size of the constraints.

Required interfaces

  • hard_constraints, the specification of the hard constraints. Once the hard constraints are violated, the size goes to infinity.

  • is_satisfied, check if the hard constraints are satisfied.

  • local_solution_spec, the specification of the size terms as soft constraints, which is associated with weights.

  • weights: The weights of the soft constraints.

  • set_weights: Change the weights for the problem and return a new problem instance.

  • solution_size, the size of the problem given a configuration.

  • energy_mode, the definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter.

source
ProblemReductions.IndependentSetType
struct IndependentSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}
IndependentSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(nv(graph))) -> IndependentSet

Independent 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.

Fields

  • graph::AbstractGraph: The problem graph.
  • weights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(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
+References · GenericTensorNetworks.jl

References

Constraint Satisfaction Problems

GenericTensorNetworks.solveFunction
solve(problem, property; usecuda=false, T=Float64)

Solving a certain property of a graph problem.

Positional Arguments

  • problem is the graph problem with tensor network information,

  • property is string specifying the task. Using the maximum independent set problem as an example, it can be one of

    • PartitionFunction() 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

  • usecuda is a switch to use CUDA (if possible), user need to call statement using CUDA before turning on this switch.
  • T is the "base" element type, sometimes can be used to reduce the memory cost.
source
GenericTensorNetworks.GenericTensorNetworkType
struct GenericTensorNetwork{CFG, CT, LT}
GenericTensorNetwork(problem::ConstraintSatisfactionProblem; openvertices=(), fixedvertices=Dict(), optimizer=GreedyMethod())

The generic tensor network that generated from a ConstraintSatisfactionProblem.

Positional arguments

  • problem is the graph problem.
  • code is the tensor network contraction code.
  • fixedvertices is a dictionary specifying the fixed dimensions.
source
ProblemReductions.ConstraintSatisfactionProblemType
ConstraintSatisfactionProblem{T} <: AbstractProblem

The abstract base type of constraint satisfaction problems. T is the type of the local size of the constraints.

Required interfaces

  • hard_constraints, the specification of the hard constraints. Once the hard constraints are violated, the size goes to infinity.

  • is_satisfied, check if the hard constraints are satisfied.

  • local_solution_spec, the specification of the size terms as soft constraints, which is associated with weights.

  • weights: The weights of the soft constraints.

  • set_weights: Change the weights for the problem and return a new problem instance.

  • solution_size, the size of the problem given a configuration.

  • energy_mode, the definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter.

source
ProblemReductions.IndependentSetType
struct IndependentSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}
IndependentSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(nv(graph))) -> IndependentSet

Independent 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.

Fields

  • graph::AbstractGraph: The problem graph.
  • weights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(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
@@ -258,22 +258,22 @@
 
 julia> gp.code(GenericTensorNetworks.generate_tensors(Tropical(1.0), gp)...)
 0-dimensional Array{Tropical{Float64}, 0}:
-4.0ₜ
source
ProblemReductions.flavorsFunction
flavors(::Type{<:AbstractProblem}) -> Vector

Returns a vector of integers as the flavors (domain) of a degree of freedom.

source
flavors(::Type{<:GenericTensorNetwork}) -> Vector

It 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.

source
ProblemReductions.set_weightsFunction
set_weights(problem::ConstraintSatisfactionProblem, weights) -> ConstraintSatisfactionProblem

Change the weights for the problem and return a new problem instance.

source
ProblemReductions.is_weightedFunction
is_weighted(problem::ConstraintSatisfactionProblem) -> Bool

Check if the problem is weighted. Returns true if the problem has non-unit weights.

source
ProblemReductions.num_flavorsFunction
num_flavors(::Type{<:AbstractProblem}) -> Int
-num_flavors(::GT) where GT<:AbstractProblem -> Int

Returns the number of flavors (domain) of a degree of freedom.

source
num_flavors(::GenericTensorNetwork{GT}) where GT<:ConstraintSatisfactionProblem -> Int

Bond size is equal to the number of flavors.

source
GenericTensorNetworks.fixedverticesFunction
fixedvertices(tnet::GenericTensorNetwork) -> Dict

Returns the fixed vertices in the graph problem, which is a dictionary specifying the fixed dimensions.

source

Constraint Satisfaction Problem Utilities

ProblemReductions.is_satisfiedFunction
is_satisfied(::Type{<:ConstraintSatisfactionProblem}, constraint::HardConstraint, config) -> Bool

Check if the constraint is satisfied by the configuration config.

source
ProblemReductions.local_solution_specFunction
local_solution_spec(problem::AbstractProblem) -> Vector{LocalSolutionSpec}

The constraints related to the size of the problem. Each term is associated with weights.

source
ProblemReductions.energyFunction
energy(problem::AbstractProblem, config) -> Number

The energy of the problem given the configuration config. Please check the energy_mode for the definition of the energy function.

source
ProblemReductions.is_vertex_coloringFunction
is_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.

source
ProblemReductions.is_matchingFunction
is_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).

source
ProblemReductions.cut_sizeFunction
cut_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.

source
ProblemReductions.flavorsFunction
flavors(::Type{<:AbstractProblem}) -> Vector

Returns a vector of integers as the flavors (domain) of a degree of freedom.

source
flavors(::Type{<:GenericTensorNetwork}) -> Vector

It 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.

source
ProblemReductions.set_weightsFunction
set_weights(problem::ConstraintSatisfactionProblem, weights) -> ConstraintSatisfactionProblem

Change the weights for the problem and return a new problem instance.

source
ProblemReductions.is_weightedFunction
is_weighted(problem::ConstraintSatisfactionProblem) -> Bool

Check if the problem is weighted. Returns true if the problem has non-unit weights.

source
ProblemReductions.num_flavorsFunction
num_flavors(::Type{<:AbstractProblem}) -> Int
+num_flavors(::GT) where GT<:AbstractProblem -> Int

Returns the number of flavors (domain) of a degree of freedom.

source
num_flavors(::GenericTensorNetwork{GT}) where GT<:ConstraintSatisfactionProblem -> Int

Bond size is equal to the number of flavors.

source
GenericTensorNetworks.fixedverticesFunction
fixedvertices(tnet::GenericTensorNetwork) -> Dict

Returns the fixed vertices in the graph problem, which is a dictionary specifying the fixed dimensions.

source

Constraint Satisfaction Problem Utilities

ProblemReductions.is_satisfiedFunction
is_satisfied(::Type{<:ConstraintSatisfactionProblem}, constraint::HardConstraint, config) -> Bool

Check if the constraint is satisfied by the configuration config.

source
ProblemReductions.local_solution_specFunction
local_solution_spec(problem::AbstractProblem) -> Vector{LocalSolutionSpec}

The constraints related to the size of the problem. Each term is associated with weights.

source
ProblemReductions.energyFunction
energy(problem::AbstractProblem, config) -> Number

The energy of the problem given the configuration config. Please check the energy_mode for the definition of the energy function.

source
ProblemReductions.is_vertex_coloringFunction
is_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.

source
ProblemReductions.is_matchingFunction
is_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).

source
ProblemReductions.cut_sizeFunction
cut_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.

source
ProblemReductions.satisfiableFunction
satisfiable(expr, config::AbstractDict{T}) where T

Check if the boolean expression expr is satisfied by the configuration config.

source
GenericTensorNetworks.mis_compactify!Function
mis_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
source

Properties

GenericTensorNetworks.SizeMaxType
SizeMax{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 Tropical if K is Single and ExtendedTropical if K is an integer.
  • It is compatible with weighted Constraint Satisfaction Problems.
  • BLAS (on CPU) and GPU are supported only if K is Single,
source
GenericTensorNetworks.SizeMinType
SizeMin{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 Tropical if K is Single and inverted ExtendedTropical K is 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 K is Single,
source
GenericTensorNetworks.CountingAllType
CountingAll <: AbstractProperty
-CountingAll()

Counting the total number of sets. e.g. for the IndependentSet problem, it counts the independent sets.

  • The corresponding tensor element type is Base.Real.
  • The weights on graph does not have effect.
  • BLAS (GPU and CPU) and GPU are supported,
source
GenericTensorNetworks.CountingMaxType
CountingMax{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 CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.
  • Weighted constraint satisfaction problems is only supported if K is Single.
  • GPU is supported,
source
GenericTensorNetworks.CountingMinType
CountingMin{K} <: AbstractProperty
-CountingMin(K=Single)

Counting the number of sets with smallest-K size.

  • The corresponding tensor element type is inverted CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.
  • Weighted constraint satisfaction problems is only supported if K is Single.
  • GPU is supported,
source
GenericTensorNetworks.GraphPolynomialType
GraphPolynomial{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 the IndependentSet problem).
  • :polynomial and :laurent, use (Laurent) polynomial numbers to solve the polynomial directly.
    • The corresponding tensor element types are Polynomial and LaurentPolynomial.
    • 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.
  • :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) and r, if r > 1, one has better precision for coefficients of large order, if r < 1, one has better precision for coefficients of small order.
  • :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.

Graph polynomials are not defined for weighted constraint satisfaction problems.

source
GenericTensorNetworks.SingleConfigMaxType
SingleConfigMax{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.

Keyword Arguments

  • bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
source
GenericTensorNetworks.SingleConfigMinType
SingleConfigMin{K, BOUNDED} <: AbstractProperty
-SingleConfigMin(k::Int; bounded=false)

Finding single solution with smallest-K size.

Keyword Arguments

  • bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
source
GenericTensorNetworks.ConfigsAllType
ConfigsAll{TREESTORAGE} <:AbstractProperty
-ConfigsAll(; tree_storage=false)

Find all valid configurations, e.g. for IndependentSet problem, it is finding all independent sets.

Keyword Arguments

  • tree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.
source
GenericTensorNetworks.ConfigsMaxType
ConfigsMax{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} if K is Single and TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.
  • Weighted constraint satisfaction problem is only supported if K is Single.

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.
source
GenericTensorNetworks.ConfigsMinType
ConfigsMin{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} if K is Single and inverted TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.
  • Weighted constraint satisfaction problem is only supported if K is Single.

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.
source

Element Algebras

Boolean variable for constructing CNF clauses.

source
ProblemReductions.satisfiableFunction
satisfiable(expr, config::AbstractDict{T}) where T

Check if the boolean expression expr is satisfied by the configuration config.

source
GenericTensorNetworks.mis_compactify!Function
mis_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
source

Properties

GenericTensorNetworks.SizeMaxType
SizeMax{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 Tropical if K is Single and ExtendedTropical if K is an integer.
  • It is compatible with weighted Constraint Satisfaction Problems.
  • BLAS (on CPU) and GPU are supported only if K is Single,
source
GenericTensorNetworks.SizeMinType
SizeMin{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 Tropical if K is Single and inverted ExtendedTropical K is 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 K is Single,
source
GenericTensorNetworks.CountingAllType
CountingAll <: 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,
source
GenericTensorNetworks.CountingMaxType
CountingMax{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 CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.
  • Weighted constraint satisfaction problems is only supported if K is Single.
  • GPU is supported,
source
GenericTensorNetworks.CountingMinType
CountingMin{K} <: AbstractProperty
+CountingMin(K=Single)

Counting the number of sets with smallest-K size.

  • The corresponding tensor element type is inverted CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.
  • Weighted constraint satisfaction problems is only supported if K is Single.
  • GPU is supported,
source
GenericTensorNetworks.GraphPolynomialType
GraphPolynomial{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 the IndependentSet problem).
  • :polynomial and :laurent, use (Laurent) polynomial numbers to solve the polynomial directly.
    • The corresponding tensor element types are Polynomial and LaurentPolynomial.
    • 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.
  • :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) and r, if r > 1, one has better precision for coefficients of large order, if r < 1, one has better precision for coefficients of small order.
  • :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.

Graph polynomials are not defined for weighted constraint satisfaction problems.

source
GenericTensorNetworks.SingleConfigMaxType
SingleConfigMax{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.

Keyword Arguments

  • bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
source
GenericTensorNetworks.SingleConfigMinType
SingleConfigMin{K, BOUNDED} <: AbstractProperty
+SingleConfigMin(k::Int; bounded=false)

Finding single solution with smallest-K size.

Keyword Arguments

  • bounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
source
GenericTensorNetworks.ConfigsAllType
ConfigsAll{TREESTORAGE} <:AbstractProperty
+ConfigsAll(; tree_storage=false)

Find all valid configurations, e.g. for IndependentSet problem, it is finding all independent sets.

Keyword Arguments

  • tree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.
source
GenericTensorNetworks.ConfigsMaxType
ConfigsMax{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} if K is Single and TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.
  • Weighted constraint satisfaction problem is only supported if K is Single.

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.
source
GenericTensorNetworks.ConfigsMinType
ConfigsMin{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} if K is Single and inverted TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.
  • Weighted constraint satisfaction problem is only supported if K is Single.

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.
source

Element Algebras

GenericTensorNetworks.is_commutative_semiringFunction
is_commutative_semiring(a::T, b::T, c::T) where T

Check 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 &\\ @@ -286,7 +286,7 @@ (a\oplus b) \odot c = a\odot c \oplus b\odot c &\\ &\\ a \odot \mathbb{0} = \mathbb{0} \odot a = \mathbb{0} -\end{align*}\]

source
TropicalNumbers.TropicalType
TropicalMaxPlus{T} = Tropical{T} <: AbstractSemiring

TropicalMaxPlus is a semiring algebra, can be described by

  • Tropical (TropicalMaxPlus), (ℝ, max, +, -Inf, 0).

It maps

  • + to max in regular algebra,
  • * to + in regular algebra,
  • 1 to 0 in regular algebra,
  • 0 to -Inf in regular algebra (for integer content types, this is chosen as a small integer).

Example

julia> TropicalMaxPlus(1.0) + TropicalMaxPlus(3.0)
+\end{align*}\]

source
TropicalNumbers.TropicalType
TropicalMaxPlus{T} = Tropical{T} <: AbstractSemiring

TropicalMaxPlus is a semiring algebra, can be described by

  • Tropical (TropicalMaxPlus), (ℝ, max, +, -Inf, 0).

It maps

  • + to max in regular algebra,
  • * to + in regular algebra,
  • 1 to 0 in regular algebra,
  • 0 to -Inf in 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)
@@ -323,7 +323,7 @@
 ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, 0.0ₜ])
 
 julia> zero(x)
-ExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, -Infₜ])
source
GenericTensorNetworks.TruncatedPolyType
TruncatedPoly{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

  • coeffs is the largest-K coefficients of a polynomial. In GenericTensorNetworks, it can be the counting or enumeration of solutions.
  • maxorder is the order of a polynomial.

Examples

julia> TruncatedPoly((1,2,3), 6)
 x^4 + 2*x^5 + 3*x^6
 
@@ -331,8 +331,8 @@
 20*x^7 + 8*x^8 + 3*x^9
 
 julia> TruncatedPoly((1,2,3), 6) + TruncatedPoly((5,2,1), 3)
-x^4 + 2*x^5 + 3*x^6
source
GenericTensorNetworks.ConfigEnumeratorType
ConfigEnumerator{N,S,C} <: AbstractSetNumber

Set 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

Examples

julia> a = ConfigEnumerator([StaticBitVector([1,1,1,0,0]), StaticBitVector([1,0,0,0,1])])
+x^4 + 2*x^5 + 3*x^6
source
GenericTensorNetworks.ConfigEnumeratorType
ConfigEnumerator{N,S,C} <: AbstractSetNumber

Set 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

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])])
@@ -345,7 +345,7 @@
 {00000}
 
 julia> zero(a)
-{}
source
GenericTensorNetworks.SumProductTreeType
SumProductTree{ET} <: AbstractSetNumber

Configuration 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

  • tag is one of ZERO, ONE, LEAF, SUM, PROD.
  • data is the element stored in a LEAF node.
  • left and right are two operands of a SUM or PROD node.

Examples

julia> s = SumProductTree(bv"00111")
+{}
source
GenericTensorNetworks.SumProductTreeType
SumProductTree{ET} <: AbstractSetNumber

Configuration 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

  • tag is one of ZERO, ONE, LEAF, SUM, PROD.
  • data is the element stored in a LEAF node.
  • left and right are two operands of a SUM or PROD node.

Examples

julia> s = SumProductTree(bv"00111")
 00111
 
 
@@ -384,7 +384,7 @@
 julia> one(s)
 00000
 
-
source
GenericTensorNetworks.ConfigSamplerType
ConfigSampler{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`.

Note

ConfigSampler is a probabilistic commutative semiring, adding two config samplers do not give you deterministic results.

Fields

Examples

julia> ConfigSampler(StaticBitVector([1,1,1,0,0]))
 ConfigSampler{5, 1, 1}(11100)
 
@@ -398,7 +398,7 @@
 ConfigSampler{5, 1, 1}(00000)
 
 julia> zero(ConfigSampler{5, 1, 1})
-ConfigSampler{5, 1, 1}(11111)
source

GenericTensorNetworks also exports 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_configFunction
read_config(x; keeptree=false)

Read the configuration information from the generic element, if keeptree=true, the tree structure will not be flattened.

source
GenericTensorNetworks.read_size_configFunction
read_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.

source

The following functions are for saving and loading configurations.

GenericTensorNetworks also exports 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_configFunction
read_config(x; keeptree=false)

Read the configuration information from the generic element, if keeptree=true, the tree structure will not be flattened.

source
GenericTensorNetworks.read_size_configFunction
read_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.

source

The following functions are for saving and loading configurations.

ProblemReductions.StaticBitVectorType
StaticBitVector{N,C} = StaticElementVector{N,1,C}
 StaticBitVector(x::AbstractVector)

Examples

julia> sb = StaticBitVector([1,0,0,1,1])
 10011
 
@@ -425,7 +425,7 @@
  0
  1
  2
source
GenericTensorNetworks.load_configsFunction
load_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.

source
ProblemReductions.onehotvFunction
onehotv(::Type{<:StaticElementVector}, i, v)
+OnehotVec{N,NF}(loc, val)

Onehot vector type, N is the number of vector length, NF is the number of flavors.

source
GenericTensorNetworks.load_configsFunction
load_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.

source
ProblemReductions.onehotvFunction
onehotv(::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).

source
GenericTensorNetworks.generate_samplesFunction
generate_samples(t::SumProductTree, nsamples::Int)

Direct sampling configurations from a SumProductTree instance.

Examples

julia> using Graphs
 
 julia> g= smallgraph(:petersen)
@@ -436,7 +436,7 @@
 julia> samples = generate_samples(t, 1000);
 
 julia> all(s->is_independent_set(g, s), samples)
-true
source
GenericTensorNetworks.hamming_distributionFunction
hamming_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.

source

Tensor Network

OMEinsumContractionOrders.optimize_codeFunction
optimize_code(eincode, size_dict, optimizer = GreedyMethod(), simplifier=nothing, permute=true) -> optimized_eincode

Optimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum instance. Input arguments are

  • eincode is an einsum contraction code instance, one of DynamicEinCode, StaticEinCode or NestedEinsum.
  • size is a dictionary of "edge label=>edge size" that contains the size information, one can use uniformsize(eincode, 2) to create a uniform size.
  • optimizer is a CodeOptimizer instance, should be one of GreedyMethod, ExactTreewidth, KaHyParBipartite, SABipartite or TreeSA. Check their docstrings for details.
  • simplifier is one of MergeVectors or MergeGreedy.
  • optimize the permutation if permute is true.

Examples

julia> using OMEinsum
+true
source
GenericTensorNetworks.hamming_distributionFunction
hamming_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.

source

Tensor Network

OMEinsumContractionOrders.optimize_codeFunction
optimize_code(eincode, size_dict, optimizer = GreedyMethod(), simplifier=nothing, permute=true) -> optimized_eincode

Optimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum instance. Input arguments are

  • eincode is an einsum contraction code instance, one of DynamicEinCode, StaticEinCode or NestedEinsum.
  • size is a dictionary of "edge label=>edge size" that contains the size information, one can use uniformsize(eincode, 2) to create a uniform size.
  • optimizer is a CodeOptimizer instance, should be one of GreedyMethod, ExactTreewidth, KaHyParBipartite, SABipartite or TreeSA. Check their docstrings for details.
  • simplifier is one of MergeVectors or MergeGreedy.
  • optimize the permutation if permute is true.

Examples

julia> using OMEinsum
 
 julia> code = ein"ij, jk, kl, il->"
 ij, jk, kl, il -> 
julia> optimize_code(code, uniformsize(code, 2), TreeSA())
@@ -458,7 +458,7 @@
     property::GenericTensorNetworks.AbstractProperty;
     T
 ) -> Any
-

Memory estimation in number of bytes to compute certain property of a problem. T is the base type.

source
OMEinsum.@ein_strMacro
ein"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);
+

Memory estimation in number of bytes to compute certain property of a problem. T is the base type.

source
OMEinsum.@ein_strMacro
ein"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
 true
source
OMEinsumContractionOrders.GreedyMethodType
GreedyMethod{MT}
@@ -477,7 +477,7 @@
     )

Show a graph in VSCode, Pluto or Jupyter notebook, or save it to a file.

Positional arguments

  • f is a function that returns extra Luxor plotting statements.
  • graph is a graph instance.
  • locs is a vector of tuples for specifying the vertex locations, or a AbstractLayout instance.

Keyword arguments

  • config is a GraphDisplayConfig instance.

  • vertex_colors is a vector of color strings for specifying vertex fill colors.

  • vertex_sizes is a vector of real numbers for specifying vertex sizes.

  • vertex_shapes is a vector of strings for specifying vertex shapes, the string should be "circle" or "box".

  • vertex_stroke_colors is a vector of color strings for specifying vertex stroke colors.

  • vertex_text_colors is a vector of color strings for specifying vertex text colors.

  • edge_colors is a vector of color strings for specifying edge colors.

  • texts is a vector of strings for labeling vertices.

  • padding_left::Int = 10, the padding on the left side of the drawing

  • padding_right::Int = 10, the padding on the right side of the drawing

  • padding_top::Int = 10, the padding on the top side of the drawing

  • padding_bottom::Int = 10, the padding on the bottom side of the drawing

  • format is the output format, which can be :svg, :png or :pdf.

  • filename is a string as the output filename.

Example

julia> using Graphs, LuxorGraphPlot
 
 julia> show_graph(smallgraph(:petersen); format=:png, vertex_colors=rand(["blue", "red"], 10));
source
GenericTensorNetworks.show_configsFunction
show_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.

source
GenericTensorNetworks.show_einsumFunction
show_einsum(ein::AbstractEinsum;
+show_configs(graph::SimpleGraph, locs, configs::AbstractMatrix; num_flavors=2, kwargs...)

Show a gallery of configurations on a graph.

source
GenericTensorNetworks.show_einsumFunction
show_einsum(ein::AbstractEinsum;
     tensor_locs=nothing,
     label_locs=nothing,  # dict
     spring::Bool=true,
@@ -493,13 +493,13 @@
     open_label_color="black",
     annotate_labels=true,
     kwargs...
-    )

Positional arguments

  • ein is an Einsum contraction code (provided by package OMEinsum).

Keyword arguments

  • locs is a tuple of tensor_locs (vector) and label_locs (dict).

  • spring is switch to use spring method to optimize the location.

  • optimal_distance is a optimal distance parameter for spring optimizer.

  • tensor_color is a string to specify the color of tensor nodes.

  • tensor_size is a real number to specify the size of tensor nodes.

  • tensor_text_color is a color strings to specify tensor text color.

  • annotate_tensors is a boolean switch for annotate different tensors by integers.

  • label_size is a real number to specify label text node size.

  • label_color is a color strings to specify label text color.

  • open_label_color is a color strings to specify open label text color.

  • annotate_labels is a boolean switch for annotate different labels.

  • format is the output format, which can be :svg, :png or :pdf.

  • filename is a string as the output filename.

  • fontsize::Float64 = 12.0, the font size

  • fontface::String = "", the font face, leave empty to follow system

  • vertex_text_color = "black", the default text color

  • vertex_stroke_color = "black", the default stroke color for vertices

  • vertex_color = "transparent", the default default fill color for vertices

  • vertex_size::Float64 = 10.0, the default vertex size

  • vertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot

  • vertex_line_width::Float64 = 1, the default vertex stroke line width

  • vertex_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 color

  • edge_line_width::Float64 = 1, the default line width

  • edge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]

source
GenericTensorNetworks.show_landscapeFunction
show_landscape(is_neighbor, configurations::TruncatedPoly;
+    )

Positional arguments

  • ein is an Einsum contraction code (provided by package OMEinsum).

Keyword arguments

  • locs is a tuple of tensor_locs (vector) and label_locs (dict).

  • spring is switch to use spring method to optimize the location.

  • optimal_distance is a optimal distance parameter for spring optimizer.

  • tensor_color is a string to specify the color of tensor nodes.

  • tensor_size is a real number to specify the size of tensor nodes.

  • tensor_text_color is a color strings to specify tensor text color.

  • annotate_tensors is a boolean switch for annotate different tensors by integers.

  • label_size is a real number to specify label text node size.

  • label_color is a color strings to specify label text color.

  • open_label_color is a color strings to specify open label text color.

  • annotate_labels is a boolean switch for annotate different labels.

  • format is the output format, which can be :svg, :png or :pdf.

  • filename is a string as the output filename.

  • fontsize::Float64 = 12.0, the font size

  • fontface::String = "", the font face, leave empty to follow system

  • vertex_text_color = "black", the default text color

  • vertex_stroke_color = "black", the default stroke color for vertices

  • vertex_color = "transparent", the default default fill color for vertices

  • vertex_size::Float64 = 10.0, the default vertex size

  • vertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot

  • vertex_line_width::Float64 = 1, the default vertex stroke line width

  • vertex_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 color

  • edge_line_width::Float64 = 1, the default line width

  • edge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]

source
GenericTensorNetworks.show_landscapeFunction
show_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 the solve function with ConfigsMax property as the argument.

Keyword arguments

  • layer_distance: the distance between layers.
  • config: a LuxorGraphPlot.GraphDisplayConfig object.
  • layout_method: the layout method, either :spring, :stress or :spectral
  • optimal_distance: the optimal distance for the layout.
  • colors: a vector of colors for each layer.
  • kwargs...: other keyword arguments passed to show_graph.
source
LuxorGraphPlot.GraphDisplayConfigType
GraphDisplayConfig

The configuration for graph display.

Keyword arguments

  • locs is a vector of tuples for specifying the vertex locations.

  • edges is a vector of tuples for specifying the edges.

  • fontsize::Float64 = 12.0, the font size

  • fontface::String = "", the font face, leave empty to follow system

  • vertex_text_color = "black", the default text color

  • vertex_stroke_color = "black", the default stroke color for vertices

  • vertex_color = "transparent", the default default fill color for vertices

  • vertex_size::Float64 = 10.0, the default vertex size

  • vertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot

  • vertex_line_width::Float64 = 1, the default vertex stroke line width

  • vertex_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 color

  • edge_line_width::Float64 = 1, the default line width

  • edge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]

source
LuxorGraphPlot.Layouts.SpringLayoutType
SpringLayout <: AbstractLayout

A layout algorithm based on a spring model.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • maxiter::Int: the maximum number of iterations
  • α0::Float64: the initial moving speed
  • meta::Dict{Symbol, Any}: graph dependent meta information, including
    • initial_locs: initial vertex locations
    • mask: boolean mask for which vertices to relocate
source
LuxorGraphPlot.Layouts.StressLayoutType
StressLayout <: AbstractLayout

A layout algorithm based on stress majorization.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • maxiter::Int: the maximum number of iterations
  • rtol::Float64: the absolute tolerance
  • initial_locs: initial vertex locations
  • mask: boolean mask for which vertices to relocate
  • meta::Dict{Symbol, Any}: graph dependent meta information, including
    • initial_locs: initial vertex locations
    • mask: boolean mask for which vertices to relocate
source
LuxorGraphPlot.Layouts.SpectralLayoutType
SpectralLayout <: AbstractLayout

A layout algorithm based on spectral graph theory.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • dimension::Int: the number of dimensions
source
LuxorGraphPlot.Layouts.LayeredType
Layered <: AbstractLayout

Layered version of a parent layout algorithm.

Fields

  • parent::LT: the parent layout algorithm
  • zlocs::Vector{T}: the z-axis locations
  • aspect_ratio::Float64: the aspect ratio of the z-axis
source
LuxorGraphPlot.Layouts.LayeredSpringLayoutFunction
LayeredSpringLayout(; zlocs, optimal_distance, aspect_ration=0.2)

Create a layered spring layout.

Keyword Arguments

  • zlocs: the z-axis locations
  • optimal_distance::Float64: the optimal distance between vertices
  • aspect_ration::Float64: the aspect ratio of the z-axis
  • α0::Float64: the initial moving speed
  • maxiter::Int: the maximum number of iterations
source
LuxorGraphPlot.Layouts.LayeredStressLayoutFunction
LayeredStressLayout(; zlocs, optimal_distance, aspect_ration=0.2)

Create a layered stress layout.

Keyword Arguments

  • zlocs: the z-axis locations
  • optimal_distance::Float64: the optimal distance between vertices
  • aspect_ration::Float64: the aspect ratio of the z-axis
  • maxiter::Int: the maximum number of iterations
  • rtol::Float64: the absolute tolerance
source
GenericTensorNetworks.line_graphFunction
line_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.

source

One can also use random_regular_graph and smallgraph in Graphs to build special graphs.

Multiprocessing

GenericTensorNetworks.SimpleMultiprocessing.multiprocess_runFunction
multiprocess_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
+    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 the solve function with ConfigsMax property as the argument.

Keyword arguments

  • layer_distance: the distance between layers.
  • config: a LuxorGraphPlot.GraphDisplayConfig object.
  • layout_method: the layout method, either :spring, :stress or :spectral
  • optimal_distance: the optimal distance for the layout.
  • colors: a vector of colors for each layer.
  • kwargs...: other keyword arguments passed to show_graph.
source
LuxorGraphPlot.GraphDisplayConfigType
GraphDisplayConfig

The configuration for graph display.

Keyword arguments

  • locs is a vector of tuples for specifying the vertex locations.

  • edges is a vector of tuples for specifying the edges.

  • fontsize::Float64 = 12.0, the font size

  • fontface::String = "", the font face, leave empty to follow system

  • vertex_text_color = "black", the default text color

  • vertex_stroke_color = "black", the default stroke color for vertices

  • vertex_color = "transparent", the default default fill color for vertices

  • vertex_size::Float64 = 10.0, the default vertex size

  • vertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot

  • vertex_line_width::Float64 = 1, the default vertex stroke line width

  • vertex_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 color

  • edge_line_width::Float64 = 1, the default line width

  • edge_style::String = "solid", the line style of edges, which can be one of ["solid", "dotted", "dot", "dotdashed", "longdashed", "shortdashed", "dash", "dashed", "dotdotdashed", "dotdotdotdashed"]

source
LuxorGraphPlot.Layouts.SpringLayoutType
SpringLayout <: AbstractLayout

A layout algorithm based on a spring model.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • maxiter::Int: the maximum number of iterations
  • α0::Float64: the initial moving speed
  • meta::Dict{Symbol, Any}: graph dependent meta information, including
    • initial_locs: initial vertex locations
    • mask: boolean mask for which vertices to relocate
source
LuxorGraphPlot.Layouts.StressLayoutType
StressLayout <: AbstractLayout

A layout algorithm based on stress majorization.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • maxiter::Int: the maximum number of iterations
  • rtol::Float64: the absolute tolerance
  • initial_locs: initial vertex locations
  • mask: boolean mask for which vertices to relocate
  • meta::Dict{Symbol, Any}: graph dependent meta information, including
    • initial_locs: initial vertex locations
    • mask: boolean mask for which vertices to relocate
source
LuxorGraphPlot.Layouts.SpectralLayoutType
SpectralLayout <: AbstractLayout

A layout algorithm based on spectral graph theory.

Fields

  • optimal_distance::Float64: the optimal distance between vertices
  • dimension::Int: the number of dimensions
source
LuxorGraphPlot.Layouts.LayeredType
Layered <: AbstractLayout

Layered version of a parent layout algorithm.

Fields

  • parent::LT: the parent layout algorithm
  • zlocs::Vector{T}: the z-axis locations
  • aspect_ratio::Float64: the aspect ratio of the z-axis
source
LuxorGraphPlot.Layouts.LayeredSpringLayoutFunction
LayeredSpringLayout(; zlocs, optimal_distance, aspect_ration=0.2)

Create a layered spring layout.

Keyword Arguments

  • zlocs: the z-axis locations
  • optimal_distance::Float64: the optimal distance between vertices
  • aspect_ration::Float64: the aspect ratio of the z-axis
  • α0::Float64: the initial moving speed
  • maxiter::Int: the maximum number of iterations
source
LuxorGraphPlot.Layouts.LayeredStressLayoutFunction
LayeredStressLayout(; zlocs, optimal_distance, aspect_ration=0.2)

Create a layered stress layout.

Keyword Arguments

  • zlocs: the z-axis locations
  • optimal_distance::Float64: the optimal distance between vertices
  • aspect_ration::Float64: the aspect ratio of the z-axis
  • maxiter::Int: the maximum number of iterations
  • rtol::Float64: the absolute tolerance
source
GenericTensorNetworks.line_graphFunction
line_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.

source

One can also use random_regular_graph and smallgraph in Graphs to build special graphs.

Multiprocessing

GenericTensorNetworks.SimpleMultiprocessing.multiprocess_runFunction
multiprocess_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
@@ -509,4 +509,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
source
+ From worker 5: [ Info: running argument 0.39460402723831134 on device 5source diff --git a/dev/search_index.js b/dev/search_index.js index 8504443..8e37017 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"EditURL = \"../../../examples/IndependentSet.jl\"","category":"page"},{"location":"generated/IndependentSet/#Independent-set-problem","page":"Independent set problem","title":"Independent set problem","text":"","category":"section"},{"location":"generated/IndependentSet/#Problem-definition","page":"Independent set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"In graph theory, an independent set is a set of vertices in a graph, no two of which are adjacent.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"In the following, we are going to solve the solution space properties of the independent set problem on the Petersen graph. To start, let us define a Petersen graph instance.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can visualize this graph using the show_graph function","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"# set the vertex locations manually instead of using the default spring layout\nrot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The graphical display is available in the following editors","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"a VSCode editor,\na Jupyter notebook,\nor a Pluto notebook,","category":"page"},{"location":"generated/IndependentSet/#Generic-tensor-network-representation","page":"Independent set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The independent set problem can be constructed with IndependentSet type as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"iset = IndependentSet(graph)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The tensor network representation of the independent set problem can be obtained by","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"problem = GenericTensorNetwork(iset; optimizer=TreeSA())","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Here, the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA. The resulting contraction order optimized tensor network is contained in the code field of problem.","category":"page"},{"location":"generated/IndependentSet/#Theory-(can-skip)","page":"Independent set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Let G=(V E) be a graph with each vertex vin V associated with a weight w_v. To reduce the independent set problem on it to a tensor network contraction, we first map a vertex vin V to a label s_v in 0 1 of dimension 2, where we use 0 (1) to denote a vertex absent (present) in the set. For each vertex v, we defined a parameterized rank-one tensor indexed by s_v as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"W(x_v^w_v) = left(beginmatrix\n 1 \n x_v^w_v\n endmatrixright)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where x_v is a variable associated with v. Similarly, for each edge (u v) in E, we define a matrix B indexed by s_u and s_v as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"B = left(beginmatrix\n1 1\n1 0\nendmatrixright)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Ideally, an optimal contraction order has a space complexity 2^rm tw(G), where rm tw(G) is the tree-width of G (or graph in the code). We can check the time, space and read-write complexities by typing","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"For more information about how to improve the contraction order, please check the Performance Tips.","category":"page"},{"location":"generated/IndependentSet/#Solution-space-properties","page":"Independent set problem","title":"Solution space properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Maximum-independent-set-size-\\alpha(G)","page":"Independent set problem","title":"Maximum independent set size alpha(G)","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can compute solution space properties with the solve function, which takes two positional arguments, the problem instance and the wanted property.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"maximum_independent_set_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Here SizeMax means finding the solution with maximum set size. The return value has Tropical type. We can get its content by typing","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size(maximum_independent_set_size)","category":"page"},{"location":"generated/IndependentSet/#Counting-properties","page":"Independent set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Count-all-solutions-and-best-several-solutions","page":"Independent set problem","title":"Count all solutions and best several solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count all independent sets with the CountingAll property.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_all_independent_sets = solve(problem, CountingAll())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type Float64. The counting of all independent sets is equivalent to the infinite temperature partition function","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"solve(problem, PartitionFunction(0.0))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count the maximum independent sets with CountingMax.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_maximum_independent_sets = solve(problem, CountingMax())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical, which contains two fields. They are n being the maximum independent set size and c being the number of the maximum independent sets.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(count_maximum_independent_sets)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Similarly, we can count independent sets of sizes alpha(G) and alpha(G)-1 by feeding an integer positional argument to CountingMax.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_max2_independent_sets = solve(problem, CountingMax(2))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type TruncatedPoly, which contains two fields. They are maxorder being the maximum independent set size and coeffs being the number of independent sets having sizes alpha(G)-1 and alpha(G).","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(count_max2_independent_sets)","category":"page"},{"location":"generated/IndependentSet/#Find-the-graph-polynomial","page":"Independent set problem","title":"Find the graph polynomial","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count the number of independent sets at any size, which is equivalent to finding the coefficients of an independence polynomial that defined as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"I(G x) = sum_k=0^alpha(G) a_k x^k","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where alpha(G) is the maximum independent set size, a_k is the number of independent sets of size k. The total number of independent sets is thus equal to I(G 1). There are 3 methods to compute a graph polynomial, :finitefield, :fft and :polynomial. These methods are introduced in the docstring of GraphPolynomial.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"independence_polynomial = solve(problem, GraphPolynomial(; method=:finitefield))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return type is Polynomial.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(independence_polynomial)","category":"page"},{"location":"generated/IndependentSet/#Configuration-properties","page":"Independent set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Find-one-best-solution","page":"Independent set problem","title":"Find one best solution","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use the bounded or unbounded SingleConfigMax to find one of the solutions with largest size. The unbounded (default) version uses a joint type of CountingTropical and ConfigSampler in computation, where CountingTropical finds the maximum size and ConfigSampler samples one of the best solutions. The bounded version uses the binary gradient back-propagation (see our paper) to compute the gradients. It requires caching intermediate states, but is often faster (on CPU) because it can use TropicalGEMM (see Performance Tips).","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"max_config = solve(problem, SingleConfigMax(; bounded=false))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical with its counting field having ConfigSampler type. The data field of ConfigSampler is a bit string that corresponds to the solution","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"single_solution = read_config(max_config)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"This bit string should be read from left to right, with the i-th bit being 1 (0) to indicate the i-th vertex is present (absent) in the set. We can visualize this MIS with the following function.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"show_graph(graph, locations; format=:svg, vertex_colors=\n [iszero(single_solution[i]) ? \"white\" : \"red\" for i=1:nv(graph)])","category":"page"},{"location":"generated/IndependentSet/#Enumerate-all-solutions-and-best-several-solutions","page":"Independent set problem","title":"Enumerate all solutions and best several solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use bounded or unbounded ConfigsMax to find all solutions with largest-K set sizes. In most cases, the bounded (default) version is preferred because it can reduce the memory usage significantly.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_max_configs = solve(problem, ConfigsMax(; bounded=true))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical, while its counting field having type ConfigEnumerator. The data field of a ConfigEnumerator instance contains a vector of bit strings.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"_, configs_vector = read_size_config(all_max_configs)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"These solutions can be visualized with the show_configs function.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"show_configs(graph, locations, reshape(configs_vector, 1, :); padding_left=20)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use ConfigsAll to enumerate all sets satisfying the independence constraint.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_independent_sets = solve(problem, ConfigsAll())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type ConfigEnumerator.","category":"page"},{"location":"generated/IndependentSet/#Sample-solutions","page":"Independent set problem","title":"Sample solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"It is often difficult to store all configurations in a vector. A more clever way to store the data is using the sum product tree format.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has the SumProductTree type. Its length corresponds to the number of configurations.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"length(all_independent_sets_tree)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use Base.collect function to create a ConfigEnumerator or use generate_samples to generate samples from it.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"collect(all_independent_sets_tree)\n\ngenerate_samples(all_independent_sets_tree, 10)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"EditURL = \"../../../examples/PaintShop.jl\"","category":"page"},{"location":"generated/PaintShop/#Binary-paint-shop-problem","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/PaintShop/#Problem-Definition","page":"Binary paint shop problem","title":"Problem Definition","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"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.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"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.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"using GenericTensorNetworks, Graphs, GenericTensorNetworks.ProblemReductions\n\nsequence = collect(\"iadgbeadfcchghebif\")","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"We can visualize this paint shop problem as a graph","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"rot(a, b, θ) = cos(θ)*a + sin(θ)*b, cos(θ)*b - sin(θ)*a\nlocations = [rot(0.0, 100.0, -0.25π - 1.5*π*(i-0.5)/length(sequence)) for i=1:length(sequence)]\ngraph = path_graph(length(sequence))\nfor i=1:length(sequence)\n j = findlast(==(sequence[i]), sequence)\n i != j && add_edge!(graph, i, j)\nend\nshow_graph(graph, locations; texts=string.(sequence), format=:svg, edge_colors=\n [sequence[e.src] == sequence[e.dst] ? \"blue\" : \"black\" for e in edges(graph)])","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Vertices connected by blue edges must have different colors, and the goal becomes a min-cut problem defined on black edges.","category":"page"},{"location":"generated/PaintShop/#Generic-tensor-network-representation","page":"Binary paint shop problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"We can define the binary paint shop problem with the PaintShop type as","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"pshop = PaintShop(sequence)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The tensor network representation of the binary paint shop problem can be obtained by","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"problem = GenericTensorNetwork(pshop)","category":"page"},{"location":"generated/PaintShop/#Theory-(can-skip)","page":"Binary paint shop problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Type PaintShop can be used for constructing the tensor network with optimized contraction order for solving a binary paint shop problem. To obtain its tensor network representation, we associating car c_i (the i-th character in our example) with a degree of freedom s_c_i in 0 1, where we use 0 to denote the first appearance of a car is colored red and 1 to denote the first appearance of a car is colored blue. For each black edges (i i+1), we define an edge tensor labeled by (s_c_i s_c_i+1) as follows: If both cars on this edge are their first or second appearance","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"B^rm parallel = left(beginmatrix\nx 1 \n1 x \nendmatrixright)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"otherwise,","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"B^rm anti-parallel = left(beginmatrix\n1 x \nx 1 \nendmatrixright)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"It can be understood as, when both cars are their first appearance, they tend to have the same configuration so that the color is not changed. Otherwise, they tend to have different configuration to keep the color unchanged.","category":"page"},{"location":"generated/PaintShop/#Counting-properties","page":"Binary paint shop problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/PaintShop/#graph-polynomial","page":"Binary paint shop problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The graph polynomial defined for the maximal independent set problem is","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"I_rm max(G x) = sum_k=0^alpha(G) b_k x^k","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"where b_k is the number of maximal independent sets of size k in graph G=(V E).","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"max_config = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Since it only counts the maximal independent sets, the first several coefficients are 0.","category":"page"},{"location":"generated/PaintShop/#Counting-properties-2","page":"Binary paint shop problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/PaintShop/#graph-polynomial-2","page":"Binary paint shop problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The graph polynomial of the binary paint shop problem in our convention is defined as","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"P(G x) = sum_k=0^delta(G) p_k x^k","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"where p_k is the number of possible coloring with number of color changes 2m-1-k.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"paint_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/PaintShop/#Configuration-properties","page":"Binary paint shop problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/PaintShop/#finding-best-solutions","page":"Binary paint shop problem","title":"finding best solutions","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"best_configs = solve(problem, ConfigsMin())[]","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"One can see to identical bitstrings corresponding two different vertex configurations, they are related to bit-flip symmetry.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"painting1 = ProblemReductions.paint_shop_coloring_from_config(pshop, read_config(best_configs)[1])\n\nshow_graph(graph, locations; format=:svg, texts=string.(sequence),\n edge_colors=[sequence[e.src] == sequence[e.dst] ? \"blue\" : \"black\" for e in edges(graph)],\n vertex_colors=[isone(c) ? \"red\" : \"black\" for c in painting1], config=GraphDisplayConfig(;vertex_text_color=\"white\"))","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Since we have different choices of initial color, the number of best solution is 2.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The following function will check the solution and return you the number of color switches","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"num_paint_shop_color_switch(sequence, painting1)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"sumproduct/#Sum-product-representation-for-configurations","page":"Sum product tree representation","title":"Sum product representation for configurations","text":"","category":"section"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"SumProductTree can use polynomial memory to store exponential number of configurations. It is a sum-product expression tree to store ConfigEnumerator in a lazy style, where configurations can be extracted by depth first searching the tree with the Base.collect method. Although it is space efficient, it is in general not easy to extract information from it due to the exponential large configuration space. Directed sampling is one of its most important operations, with which one can get some statistic properties from it with an intermediate effort. For example, if we want to check some property of an intermediate scale graph, one can type","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"using GenericTensorNetworks\ngraph = random_regular_graph(70, 3)\nproblem = GenericTensorNetwork(IndependentSet(graph); optimizer=TreeSA());\ntree = solve(problem, ConfigsAll(; tree_storage=true))[]","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"If one wants to store these configurations, he will need a hard disk of size 256 TB! However, this sum-product binary tree structure supports efficient and unbiased direct sampling.","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"samples = generate_samples(tree, 1000)","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"With these samples, one can already compute useful properties like Hamming distance (see hamming_distribution) distribution. The following code visualizes this distribution with CairoMakie.","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"using CairoMakie\ndist = hamming_distribution(samples, samples)\n# bar plot\nfig = Figure()\nax = Axis(fig[1, 1]; xlabel=\"Hamming distance\", ylabel=\"Frequency\")\nbarplot!(ax, 0:length(dist)-1, dist)\nfig","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"EditURL = \"../../../examples/Coloring.jl\"","category":"page"},{"location":"generated/Coloring/#Coloring-problem","page":"Coloring problem","title":"Coloring problem","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Coloring/#Problem-definition","page":"Coloring problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"A vertex coloring is an assignment of labels or colors to each vertex of a graph such that no edge connects two identically colored vertices. In the following, we are going to defined a 3-coloring problem for the Petersen graph.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/Coloring/#Generic-tensor-network-representation","page":"Coloring problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"We can define the 3-coloring problem with the Coloring type as","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"coloring = Coloring{3}(graph)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The tensor network representation of the 3-coloring problem can be obtained by","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"problem = GenericTensorNetwork(coloring)","category":"page"},{"location":"generated/Coloring/#Theory-(can-skip)","page":"Coloring problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Type Coloring can be used for constructing the tensor network with optimized contraction order for a coloring problem. Let us use 3-coloring problem defined on vertices as an example. For a vertex v, we define the degrees of freedom c_vin123 and a vertex tensor labelled by it as","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"W(v) = left(beginmatrix\n 1\n 1\n 1\nendmatrixright)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"For an edge (u v), we define an edge tensor as a matrix labelled by (c_u c_v) to specify the constraint","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"B = left(beginmatrix\n 1 x x\n x 1 x\n x x 1\nendmatrixright)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The number of possible coloring can be obtained by contracting this tensor network by setting vertex tensor elements r_v g_v and b_v to 1.","category":"page"},{"location":"generated/Coloring/#Solving-properties","page":"Coloring problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Coloring/#counting-all-possible-coloring","page":"Coloring problem","title":"counting all possible coloring","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The size of a coloring problem is the number of violations of the coloring constraint.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"num_of_coloring = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/Coloring/#finding-one-best-coloring","page":"Coloring problem","title":"finding one best coloring","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"single_solution = solve(problem, SingleConfigMin())[]\nread_config(single_solution)\n\nis_vertex_coloring(graph, read_config(single_solution))\n\nvertex_color_map = Dict(0=>\"red\", 1=>\"green\", 2=>\"blue\")\n\nshow_graph(graph, locations; format=:svg, vertex_colors=[vertex_color_map[Int(c)]\n for c in read_config(single_solution)])","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Let us try to solve the same issue on its line graph, a graph that generated by mapping an edge to a vertex and two edges sharing a common vertex will be connected.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"linegraph = line_graph(graph)\n\nshow_graph(linegraph, [(locations[e.src] .+ locations[e.dst])\n for e in edges(graph)]; format=:svg)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Let us construct the tensor network and see if there are solutions.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"lineproblem = Coloring{3}(linegraph);\n\nnum_of_coloring = solve(GenericTensorNetwork(lineproblem), CountingMin())[]\nread_size_count(num_of_coloring)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"You will see the maximum size 28 is smaller than the number of edges in the linegraph, meaning no solution for the 3-coloring on edges of a Petersen graph.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"EditURL = \"../../../examples/SetPacking.jl\"","category":"page"},{"location":"generated/SetPacking/#Set-packing-problem","page":"Set packing problem","title":"Set packing problem","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SetPacking/#Problem-definition","page":"Set packing problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The set packing problem is generalization of the IndependentSet problem from the simple graph to the multigraph. Suppose one has a finite set S and a list of subsets of S. Then, the set packing problem asks if some k subsets in the list are pairwise disjoint. In the following, we will find the solution space properties for the set in the Set covering problem.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The packing stadium areas of cameras are represented as the following sets.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"sets = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]","category":"page"},{"location":"generated/SetPacking/#Generic-tensor-network-representation","page":"Set packing problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"We can define the set packing problem with the SetPacking type as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"problem = SetPacking(sets)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"problem = GenericTensorNetwork(problem)","category":"page"},{"location":"generated/SetPacking/#Theory-(can-skip)","page":"Set packing problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Let S be the target set packing problem that we want to solve. For each set s in S, we associate it with a weight w_s to it. The tensor network representation map a set sin S to a boolean degree of freedom v_sin0 1. For each set s, we defined a parameterized rank-one tensor indexed by v_s as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"W(x_s^w_s) = left(beginmatrix\n 1 \n x_s^w_s\n endmatrixright)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"where x_s is a variable associated with s. For each unique element a, we defined the constraint over all sets containing it N(a) = s s in S land ain s:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"B_s_1s_2ldotss_N(a) = begincases\n 0 s_1+s_2+ldots+s_N(a) 1\n 1 textotherwise\nendcases","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"This tensor means if in a configuration, two sets contain the element a, then this configuration is forbidden, One can check the contraction time space complexity of a SetPacking instance by typing:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/SetPacking/#Solving-properties","page":"Set packing problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/SetPacking/#Counting-properties","page":"Set packing problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SetPacking/#The-\"graph\"-polynomial","page":"Set packing problem","title":"The \"graph\" polynomial","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The graph polynomial for the set packing problem is defined as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"P(S x) = sum_k=0^alpha(S) c_k x^k","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"where c_k is the number of configurations having k sets, and alpha(S) is the maximum size of the packing.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"packing_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The maximum number of sets that packing the set of elements can be computed with the SizeMax property:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"max_packing_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Similarly, we have its counting CountingMax:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"counting_maximum_set_packing = solve(problem, CountingMax())[]","category":"page"},{"location":"generated/SetPacking/#Configuration-properties","page":"Set packing problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SetPacking/#Finding-maximum-set-packing","page":"Set packing problem","title":"Finding maximum set packing","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"One can enumerate all maximum set packing with the ConfigsMax property in the program.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"max_configs = read_config(solve(problem, ConfigsMax())[])","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"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 function.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"all(c->is_set_packing(problem.problem, c), max_configs)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Similarly, if one is only interested in computing one of the maximum set packing, one can use the graph property SingleConfigMax.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"EditURL = \"../../../examples/open.jl\"","category":"page"},{"location":"generated/open/#Open-and-fixed-degrees-of-freedom","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"","category":"section"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"Open degrees of freedom is useful when one want to get the marginal about certain degrees of freedom. When one specifies the openvertices keyword argument in solve function as a tuple of vertices, the output will be a tensor that can be indexed by these degrees of freedom. Let us use the maximum independent set problem on Petersen graph as an example.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"The following code computes the MIS tropical tensor (reference to be added) with open vertices 1, 2 and 3.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"problem = GenericTensorNetwork(IndependentSet(graph); openvertices=[1,2,3]);\n\nmarginal = solve(problem, SizeMax())","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"The return value is a rank-3 tensor, with its elements being the MIS sizes under different configuration of open vertices. For the maximum independent set problem, this tensor is also called the MIS tropical tensor, which can be useful in the MIS tropical tensor analysis (reference to be added).","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"One can also specify the fixed degrees of freedom by providing the fixedvertices keyword argument as a Dict, which can be used to get conditioned probability. For example, we can use the following code to do the same calculation as using openvertices.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"problem = GenericTensorNetwork(IndependentSet(graph); fixedvertices=Dict(1=>0, 2=>0, 3=>0));\n\noutput = zeros(TropicalF64,2,2,2);\n\nmarginal_alternative = map(CartesianIndices((2,2,2))) do ci\n problem.fixedvertices[1] = ci.I[1]-1\n problem.fixedvertices[2] = ci.I[2]-1\n problem.fixedvertices[3] = ci.I[3]-1\n output[ci] = solve(problem, SizeMax())[]\nend","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"One can easily check this one also gets the correct marginal on vertices 1, 2 and 3. As a reminder, their computational hardness can be different, because the contraction order optimization program can optimize over open degrees of freedom.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"EditURL = \"../../../examples/Matching.jl\"","category":"page"},{"location":"generated/Matching/#Vertex-matching-problem","page":"Vertex matching problem","title":"Vertex matching problem","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Matching/#Problem-definition","page":"Vertex matching problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"A k-matching in a graph G is a set of k edges, no two of which have a vertex in common.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"In the following, we are going to defined a matching problem for the Petersen graph.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/Matching/#Generic-tensor-network-representation","page":"Vertex matching problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"We can define the matching problem with the Matching type as","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"matching = Matching(graph)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The tensor network representation of the matching problem can be obtained by","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"problem = GenericTensorNetwork(matching)","category":"page"},{"location":"generated/Matching/#Theory-(can-skip)","page":"Vertex matching problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"Type Matching can be used for constructing the tensor network with optimized contraction order for a matching problem. We map an edge (u v) in E to a label langle u vrangle in 0 1 in a tensor network, where 1 means two vertices of an edge are matched, 0 means otherwise. Then we define a tensor of rank d(v) = N(v) on vertex v such that,","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"W_langle v n_1rangle langle v n_2 rangle ldots langle v n_d(v)rangle = begincases\n 1 sum_i=1^d(v) langle v n_i rangle leq 1\n 0 textotherwise\nendcases","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"and a tensor of rank 1 on the bond","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"B_langle v wrangle = begincases\n1 langle v w rangle = 0 \nx langle v w rangle = 1\nendcases","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where label langle v w rangle is equivalent to langle wvrangle.","category":"page"},{"location":"generated/Matching/#Solving-properties","page":"Vertex matching problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The maximum matching size can be obtained by","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"max_matching = solve(problem, SizeMax())[]\nread_size(max_matching)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The largest number of matching is 5, which means we have a perfect matching (vertices are all paired).","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The graph polynomial defined for the matching problem is known as the matching polynomial. Here, we adopt the first definition in the wiki page.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"M(G x) = sumlimits_k=1^V2 c_k x^k","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where k is the number of matches, and coefficients c_k are the corresponding counting.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"matching_poly = solve(problem, GraphPolynomial())[]\nread_size_count(matching_poly)","category":"page"},{"location":"generated/Matching/#Configuration-properties","page":"Vertex matching problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/Matching/#one-of-the-perfect-matches","page":"Vertex matching problem","title":"one of the perfect matches","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"match_config = solve(problem, SingleConfigMax())[]\nread_size_config(match_config)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"Let us show the result by coloring the matched edges to red","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"show_graph(graph, locations; format=:svg, edge_colors=\n [isone(read_config(match_config)[i]) ? \"red\" : \"black\" for i=1:ne(graph)])","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where we use edges with red color to related pairs of matched vertices.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"EditURL = \"../../../examples/Satisfiability.jl\"","category":"page"},{"location":"generated/Satisfiability/#Satisfiability-problem","page":"Satisfiability problem","title":"Satisfiability problem","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Satisfiability/#Problem-definition","page":"Satisfiability problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"In logic and computer science, the boolean satisfiability problem is the problem of determining if there exists an interpretation that satisfies a given boolean formula. One can specify a satisfiable problem in the 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.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions\n\n@bools a b c d e f g\n\ncnf = ∧(∨(a, b, ¬d, ¬e), ∨(¬a, d, e, ¬f), ∨(f, g), ∨(¬b, c))","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"To goal is to find an assignment to satisfy the above CNF. For a satisfiability problem at this size, we can find the following assignment to satisfy this assignment manually.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"assignment = Dict([:a=>true, :b=>false, :c=>false, :d=>true, :e=>false, :f=>false, :g=>true])\n\nsatisfiable(cnf, assignment)","category":"page"},{"location":"generated/Satisfiability/#Generic-tensor-network-representation","page":"Satisfiability problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"We can use Satisfiability to construct the tensor network for solving the satisfiability problem as","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"sat = Satisfiability(cnf)","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The tensor network representation of the satisfiability problem can be obtained by","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"problem = GenericTensorNetwork(sat)","category":"page"},{"location":"generated/Satisfiability/#Theory-(can-skip)","page":"Satisfiability problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"We can construct a Satisfiability problem to solve the above problem. To generate a tensor network, we map a boolean variable x and its negation neg x to a degree of freedom (label) s_x in 0 1, where 0 stands for variable x having value false while 1 stands for having value true. Then we map a clause to a tensor. For example, a clause x y z can be mapped to a tensor labeled by (s_x s_y s_z).","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"C = left(beginmatrix\nleft(beginmatrix\nx x \nx x\nendmatrixright) \nleft(beginmatrix\nx x \n1 x\nendmatrixright)\nendmatrixright)","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"There is only one entry (s_x s_y s_z) = (1 0 1) that makes this clause unsatisfied.","category":"page"},{"location":"generated/Satisfiability/#Solving-properties","page":"Satisfiability problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Satisfiability/#Satisfiability-and-its-counting","page":"Satisfiability problem","title":"Satisfiability and its counting","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The size of a satisfiability problem is defined by the number of unsatisfied clauses.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"num_satisfiable = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The GraphPolynomial of a satisfiability problem counts the number of solutions that k clauses satisfied.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"num_satisfiable_count = read_size_count(solve(problem, GraphPolynomial())[])","category":"page"},{"location":"generated/Satisfiability/#Find-one-of-the-solutions","page":"Satisfiability problem","title":"Find one of the solutions","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"single_config = read_config(solve(problem, SingleConfigMin())[])","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"One will see a bit vector printed. One can create an assignment and check the validity with the following statement:","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"satisfiable(cnf, Dict(zip(ProblemReductions.symbols(problem.problem), single_config)))","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"EditURL = \"../../../examples/SpinGlass.jl\"","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem","page":"Spin glass problem","title":"Spin-glass problem","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"using GenericTensorNetworks","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem-on-a-simple-graph","page":"Spin glass problem","title":"Spin-glass problem on a simple graph","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Let G=(V E) be a graph, the spin-glass problem in physics is characterized by the following energy function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"H = sum_ij in E J_ij s_i s_j + sum_i in V h_i s_i","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where h_i is an onsite energy term associated with spin s_i in -1 1, and J_ij is the coupling strength between spins s_i and s_j. In the program, we use boolean variable n_i = frac1-s_i2 to represent a spin configuration.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"using Graphs","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to defined an spin glass problem for the Petersen graph.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/SpinGlass/#Generic-tensor-network-representation","page":"Spin glass problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"An anti-ferromagnetic spin glass problem can be defined with the SpinGlass type as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"spinglass = SpinGlass(graph, fill(1, ne(graph)), zeros(Int, nv(graph)))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"problem = GenericTensorNetwork(spinglass)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The contraction order is already optimized.","category":"page"},{"location":"generated/SpinGlass/#The-tensor-network-reduction","page":"Spin glass problem","title":"The tensor network reduction","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"We defined the reduction of the spin-glass problem to a tensor network on a hypergraph. Let H = (V E) be a hypergraph, the tensor network for the spin glass problem on H can be defined as the following triple of (alphabet of labels Lambda, input tensors mathcalT, output labels sigma_o).","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"begincases\nLambda = s_v mid v in V\nmathcalT = B^(c)_s_N(c 1)N(c 2)ldotsN(c d(c)) mid c in E cup W^(v)_s_v mid v in V\nsigma_o = varepsilon\nendcases","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where s_v in 0 1 is the boolean degreen associated to vertex v, N(c k) is the kth vertex of hyperedge c, and d(c) is the degree of c. The edge tensor B^(c) is defined as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"B^(c) = begincases\nx^w_c (sum_vin c s_v) is even \nx^-w_c otherwise\nendcases","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"and the vertex tensor W^(v) (used to carry labels) is defined as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"W^(v) = left(beginmatrix1_v 1_vendmatrixright)","category":"page"},{"location":"generated/SpinGlass/#Graph-properties","page":"Spin glass problem","title":"Graph properties","text":"","category":"section"},{"location":"generated/SpinGlass/#Minimum-and-maximum-energies","page":"Spin glass problem","title":"Minimum and maximum energies","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The state with the highest energy is the one with all spins having the same value.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emax = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/SpinGlass/#Counting-properties","page":"Spin glass problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to find the partition function and the graph polynomial of the spin glass problem. Consider a spin glass problem on a graph G = (V E) with integer coupling strength J and onsite energy h. Its graph polynomial is a Laurent polynomial","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Z(G J h x) = sum_k=E_rm min^E_rm max c_k x^k","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where E_rm min and E_rm max are minimum and maximum energies, c_k is the number of spin configurations with energy k. The partition function at temperature beta^-1 can be computed by the graph polynomial at x = e^-beta.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"partition_function = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SpinGlass/#Configuration-properties","page":"Spin glass problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The ground state of the spin glass problem can be found by the SingleConfigMin solver.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"ground_state = read_config(solve(problem, SingleConfigMin())[])","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy of the ground state can be verified by the energy 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.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin_verify = energy(problem.problem, 1 .- 2 .* Int.(ground_state))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"You should see a consistent result as above Emin.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"show_graph(graph, locations; vertex_colors=[\n iszero(ground_state[i]) ? \"white\" : \"red\" for i=1:nv(graph)], format=:svg)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the plot, the red vertices are the ones with spin value -1 (or 1 in the boolean representation).","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem-on-a-hypergraph","page":"Spin glass problem","title":"Spin-glass problem on a hypergraph","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"A spin-glass problem on hypergraph H = (V E) can be characterized by the following energy function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"E = sum_c in E w_c prod_vin c S_v","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where S_v in -1 1, w_c is coupling strength associated with hyperedge c. In the program, we use boolean variable s_v = frac1-S_v2 to represent a spin configuration.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to defined an spin glass problem for the following hypergraph.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"num_vertices = 15\n\nhyperedges = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]\n\nweights = [-1, 1, -1, 1, -1, 1, -1, 1];\nnothing #hide","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy function of the spin glass problem is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"beginalign*\nE = -S_1S_3S_4S_6S_7 + S_4S_7S_8S_12 - S_2S_5S_9S_11S_13 +\n S_1S_2S_14S_15 - S_3S_6S_10S_12S_14 + S_8S_14S_15 +\n S_1S_2S_6S_11 - S_1s_2S_4S_6S_8S_12\nendalign*","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"A spin glass problem can be defined with the SpinGlass type as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"hyperspinglass = SpinGlass(HyperGraph(num_vertices, hyperedges), weights, zeros(Int, num_vertices))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"hyperproblem = GenericTensorNetwork(hyperspinglass)","category":"page"},{"location":"generated/SpinGlass/#Graph-properties-2","page":"Spin glass problem","title":"Graph properties","text":"","category":"section"},{"location":"generated/SpinGlass/#Minimum-and-maximum-energies-2","page":"Spin glass problem","title":"Minimum and maximum energies","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin = solve(hyperproblem, SizeMin())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emax = solve(hyperproblem, SizeMax())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In this example, the spin configurations can be chosen to make all hyperedges having even or odd spin parity.","category":"page"},{"location":"generated/SpinGlass/#Counting-properties-2","page":"Spin glass problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SpinGlass/#partition-function-and-graph-polynomial","page":"Spin glass problem","title":"partition function and graph polynomial","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The graph polynomial defined for the spin-glass problem is a Laurent polynomial","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Z(G w x) = sum_k=E_rm min^E_rm max c_k x^k","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where E_rm min and E_rm max are minimum and maximum energies, c_k is the number of spin configurations with energy k. Let the inverse temperature beta = 2, the partition function is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"β = 2.0\nZ = solve(hyperproblem, PartitionFunction(β))[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The infinite temperature partition function is the counting of all feasible configurations","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"solve(hyperproblem, PartitionFunction(0.0))[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The graph polynomial is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"poly = solve(hyperproblem, GraphPolynomial())[]","category":"page"},{"location":"generated/SpinGlass/#Configuration-properties-2","page":"Spin glass problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The ground state of the spin glass problem can be found by the SingleConfigMin solver.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"ground_state = read_config(solve(hyperproblem, SingleConfigMin())[])","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy of the ground state can be verified by the energy function.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin_verify = energy(hyperproblem.problem, 1 .- 2 .* Int.(ground_state))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"You should see a consistent result as above Emin.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"performancetips/#Performance-Tips","page":"Performance Tips","title":"Performance Tips","text":"","category":"section"},{"location":"performancetips/#Optimize-contraction-orders","page":"Performance Tips","title":"Optimize contraction orders","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Let us use the independent set problem on 3-regular graphs as an example.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"using GenericTensorNetworks, Graphs, Random\ngraph = random_regular_graph(120, 3)\niset = IndependentSet(graph)\nproblem = GenericTensorNetwork(iset; optimizer=TreeSA(\n sc_target=20, sc_weight=1.0, rw_weight=3.0, ntrials=10, βs=0.01:0.1:15.0, niters=20));","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The GenericTensorNetwork constructor maps an independent set problem to a tensor network with optimized contraction order. The key word argument optimizer specifies the contraction order optimizer of the tensor network. Here, we choose the local search based TreeSA algorithm, which often finds the smallest time/space complexity and supports slicing. One can type ?TreeSA in a Julia REPL for more information about how to configure the hyper-parameters of the TreeSA method, while the detailed algorithm explanation is in arXiv: 2108.05665. Alternative tensor network contraction order optimizers include","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"GreedyMethod (default, fastest in searching speed but worst in contraction complexity)\nKaHyParBipartite\nSABipartite","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"For example, the MergeGreedy() here \"contracts\" tensors greedily whenever the contraction result has a smaller space complexity. It can remove all vertex tensors (vectors) before entering the contraction order optimization algorithm.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The returned object problem contains a field code that specifies the tensor network with optimized contraction order. For an independent set problem, the optimal contraction time/space complexity is sim 2^rm tw(G), where rm tw(G) is the tree-width of G. One can check the time, space and read-write complexity with the contraction_complexity function.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"contraction_complexity(problem)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The return values are log2 values of the number of multiplications, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements. In this example, the number * operations is sim 2^219, the number of read-write operations are sim 2^20, and the largest tensor size is 2^17. One can check the element size by typing","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"sizeof(TropicalF64)\nsizeof(TropicalF32)\nsizeof(StaticBitVector{200,4})\nsizeof(TruncatedPoly{5,Float64,Float64})","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can use estimate_memory to get a good estimation of peak memory in bytes. For example, to compute the graph polynomial, the peak memory can be estimated as follows.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"estimate_memory(problem, GraphPolynomial(; method=:finitefield))\nestimate_memory(problem, GraphPolynomial(; method=:polynomial))","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The finite field approach only requires 298 KB memory, while using the Polynomial number type requires 71 MB memory.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"note: Note\nThe actual run time memory can be several times larger than the size of the maximum tensor, so the estimate_memory is more accurate in estimating the peak memory.\nFor mutable element types like ConfigEnumerator, none of memory estimation functions measure the actual memory usage correctly.","category":"page"},{"location":"performancetips/#Slicing-technique","page":"Performance Tips","title":"Slicing technique","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"For large scale applications, it is also possible to slice over certain degrees of freedom to reduce the space complexity, i.e. loop and accumulate over certain degrees of freedom so that one can have a smaller tensor network inside the loop due to the removal of these degrees of freedom. In the TreeSA optimizer, one can set nslices to a value larger than zero to turn on this feature.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));\ncontraction_complexity(problem)\nproblem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));\ncontraction_complexity(problem)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"In the second IndependentSet constructor, we slice over 5 degrees of freedom, which can reduce the space complexity by at most 5. In this application, the slicing achieves the largest possible space complexity reduction 5, while the time and read-write complexity are only increased by less than 1, i.e. the peak memory usage is reduced by a factor 32, while the (theoretical) computing time is increased by at a factor 2.","category":"page"},{"location":"performancetips/#GEMM-for-Tropical-numbers","page":"Performance Tips","title":"GEMM for Tropical numbers","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can speed up the Tropical number matrix multiplication when computing the solution space property SizeMax() by using the Tropical GEMM routines implemented in package TropicalGEMM.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"julia> using BenchmarkTools\n\njulia> @btime solve(problem, SizeMax())\n 91.630 ms (19203 allocations: 23.72 MiB)\n0-dimensional Array{TropicalF64, 0}:\n53.0ₜ\n\njulia> using TropicalGEMM\n\njulia> @btime solve(problem, SizeMax())\n 8.960 ms (18532 allocations: 17.01 MiB)\n0-dimensional Array{TropicalF64, 0}:\n53.0ₜ","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The TropicalGEMM package pirates the LinearAlgebra.mul! interface, hence it takes effect upon using. The above example shows more than 10x speed up on a single thread CPU, which can be even faster if the Julia multi-threading if turned on. The benchmark in the TropicalGEMM repo shows this performance is close to the theoretical optimal value.","category":"page"},{"location":"performancetips/#Multiprocessing","page":"Performance Tips","title":"Multiprocessing","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Submodule GenericTensorNetworks.SimpleMutiprocessing provides one function GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run function for simple multi-processing jobs. It is not directly related to GenericTensorNetworks, but is very convenient to have one. Suppose we want to find the independence polynomial for multiple graphs with 4 processes. We can create a file, e.g. named run.jl with the following content","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"using Distributed, GenericTensorNetworks.SimpleMultiprocessing\nusing Random, GenericTensorNetworks # to avoid multi-precompilation\n@everywhere using Random, GenericTensorNetworks\n\nresults = multiprocess_run(collect(1:10)) do seed\n Random.seed!(seed)\n n = 10\n @info \"Graph size $n x $n, seed= $seed\"\n g = random_diagonal_coupled_graph(n, n, 0.8)\n gp = GenericTensorNetwork(IndependentSet(g); optimizer=TreeSA())\n res = solve(gp, GraphPolynomial())[]\n return res\nend\n\nprintln(results)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can run this script file with the following command","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"$ julia -p4 run.jl\n From worker 3:\t[ Info: running argument 4 on device 3\n From worker 4:\t[ Info: running argument 2 on device 4\n From worker 5:\t[ Info: running argument 3 on device 5\n From worker 2:\t[ Info: running argument 1 on device 2\n From worker 3:\t[ Info: Graph size 10 x 10, seed= 4\n From worker 4:\t[ Info: Graph size 10 x 10, seed= 2\n From worker 5:\t[ Info: Graph size 10 x 10, seed= 3\n From worker 2:\t[ Info: Graph size 10 x 10, seed= 1\n From worker 4:\t[ Info: running argument 5 on device\n ...","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"You will see a vector of polynomials printed out.","category":"page"},{"location":"performancetips/#Make-use-of-GPUs","page":"Performance Tips","title":"Make use of GPUs","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"To upload the computation to GPU, you just add using CUDA before calling the solve function, and set the keyword argument usecuda to true.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"julia> using CUDA\n[ Info: OMEinsum loaded the CUDA module successfully\n\njulia> solve(problem, SizeMax(), usecuda=true)\n0-dimensional CuArray{TropicalF64, 0, CUDA.Mem.DeviceBuffer}:\n53.0ₜ","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Solution space properties computable on GPU includes","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"SizeMax and SizeMin\nCountingAll\nCountingMax and CountingMin\nGraphPolynomial\nSingleConfigMax and SingleConfigMin","category":"page"},{"location":"performancetips/#Benchmarks","page":"Performance Tips","title":"Benchmarks","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"We run a single thread benchmark on central processing units (CPU) Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz, and its CUDA version on a GPU Tesla V100-SXM2 16G. The results are summarized in the following plot. The benchmark code can be found in our paper repository.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(Image: benchmark-independent-set) This benchmark results is for computing different solution space properties of independent sets of random three-regular graphs with different tensor element types. The time in these plots only includes tensor network contraction, without taking into account the contraction order finding and just-in-time compilation time. Legends are properties, algebra, and devices that we used in the computation; one can find the corresponding computed solution space property in Table 1 in the paper.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(a) time and space complexity versus the number of vertices for the benchmarked graphs.\n(b) The computation time for calculating the MIS size and for counting the number of all independent sets (ISs), the number of MISs, the number of independent sets having size alpha(G) and alpha(G)-1, and finding 100 largest set sizes.\n(c) The computation time for calculating the independence polynomials with different approaches.\n(d) The computation time for configuration enumeration, including single MIS configuration, the enumeration of all independent set configurations, all MIS configurations, all independent sets, and all independent set configurations having size alpha(G) and alpha(G)-1.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The graphs in all benchmarks are random three-regular graphs, which have treewidth that is asymptotically smaller than V6. In this benchmark, we do not include traditional algorithms for finding the MIS sizes such as branching or dynamic programming. To the best of our knowledge, these algorithms are not suitable for computing most of the solution space properties mentioned in this paper. The main goal of this section is to show the relative computation time for calculating different solution space properties.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Panel (a) shows the time and space complexity of tensor network contraction for different graph sizes. The contraction order is obtained using the TreeSA algorithm that implemented in OMEinsumContractionOrders. If we assume our contraction-order finding program has found the optimal treewidth, which is very likely to be true, the space complexity is the same as the treewidth of the problem graph. Slicing technique has been used for graphs with space complexity greater than 2^27 (above the yellow dashed line) to fit the computation into a 16GB memory. One can see that all the computation times in panels (b), (c), and (d) have a strong correlation with the predicted time and space complexity. While in panel (d), the computation time of configuration enumeration also strongly correlates with other factors such as the configuration space size. Among these benchmarks, computational tasks with data types real numbers, complex numbers, or Tropical numbers (CPU only) can utilize fast basic linear algebra subprograms (BLAS) functions. These tasks usually compute much faster than ones with other element types in the same category. Immutable data types with no reference to other values can be compiled to GPU devices that run much faster than CPUs in all cases when the problem scale is big enough. These data types do not include those defined in Polynomial, ConfigEnumerator, ExtendedTropical and SumProductTree or a data type containing them as a part. In panel (c), one can see the Fourier transformation-based method is the fastest in computing the independence polynomial, but it may suffer from round-off errors. The finite field (GF(p)) approach is the only method that does not have round-off errors and can be run on a GPU. In panel (d), one can see the technique to bound the enumeration space (see paper) improves the performance for more than one order of magnitude in enumerating the MISs. The bounding technique can also reduce the memory usage significantly, without which the largest computable graph size is only sim150 on a device with 32GB main memory.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"We show the benchmark of computing the maximal independent set properties on 3-regular graphs in the following plot, including a comparison to the Bron-Kerbosch algorithm from Julia package Graphs","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(Image: benchmark-maximal-independent-set)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"In this plot, benchmarks of computing different solution space properties of the maximal independent sets (ISs) problem on random three regular graphs at different sizes.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(a) time and space complexity of tensor network contraction.\n(b) The wall clock time for counting and enumeration of maximal ISs.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Panel (a) shows the space and time complexities of tensor contraction, which are typically larger than those for the independent set problem. In panel (b), one can see counting maximal independent sets are much more efficient than enumerating them, while our generic tensor network approach runs slightly faster than the Bron-Kerbosch approach in enumerating all maximal independent sets.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"EditURL = \"../../../examples/MaximalIS.jl\"","category":"page"},{"location":"generated/MaximalIS/#Maximal-independent-set-problem","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/MaximalIS/#Problem-definition","page":"Maximal independent set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"In graph theory, a maximal independent set is an independent set that is not a subset of any other independent set. It is different from maximum independent set because it does not require the set to have the max size. In the following, we are going to solve the maximal independent set problem on the Petersen graph.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/MaximalIS/#Generic-tensor-network-representation","page":"Maximal independent set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"We can use MaximalIS to construct the tensor network for solving the maximal independent set problem as","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximalis = MaximalIS(graph)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The tensor network representation of the maximal independent set problem can be obtained by","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"problem = GenericTensorNetwork(maximalis)","category":"page"},{"location":"generated/MaximalIS/#Theory-(can-skip)","page":"Maximal independent set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Let G=(VE) be the target graph that we want to solve. The tensor network representation map a vertex vin V to a boolean degree of freedom s_vin0 1. We defined the restriction on its neighborhood N(v):","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"T(x_v)_s_1s_2ldotss_N(v)s_v = begincases\n s_vx_v^w_v s_1=s_2=ldots=s_N(v)=0\n 1-s_v textotherwise\nendcases","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The first case corresponds to all the neighborhood vertices of v are not in I_m, then v must be in I_m and contribute a factor x_v^w_v, where w_v is the weight of vertex v. Otherwise, if any of the neighboring vertices of v is in I_m, v must not be in I_m by the independence requirement.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Its contraction time space complexity of a MaximalIS instance is no longer determined by the tree-width of the original graph G. It is often harder to contract this tensor network than to contract the one for regular independent set problem.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/MaximalIS/#Solving-properties","page":"Maximal independent set problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/MaximalIS/#Counting-properties","page":"Maximal independent set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/MaximalIS/#maximal-independence-polynomial","page":"Maximal independent set problem","title":"maximal independence polynomial","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The graph polynomial defined for the maximal independent set problem is","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"I_rm max(G x) = sum_k=0^alpha(G) b_k x^k","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"where b_k is the number of maximal independent sets of size k in graph G=(V E).","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximal_indenpendence_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"One can see the first several coefficients are 0, because it only counts the maximal independent sets, The minimum maximal independent set size is also known as the independent domination number. It can be computed with the SizeMin property:","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"independent_domination_number = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"counting_min_maximal_independent_set = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/MaximalIS/#Configuration-properties","page":"Maximal independent set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/MaximalIS/#finding-all-maximal-independent-set","page":"Maximal independent set problem","title":"finding all maximal independent set","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximal_configs = read_config(solve(problem, ConfigsAll())[])\n\nall(c->is_maximal_independent_set(graph, c), maximal_configs)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"show_configs(graph, locations, reshape(collect(maximal_configs), 3, 5); padding_left=20)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"This result should be consistent with that given by the Bron Kerbosch algorithm on the complement of Petersen graph.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"cliques = maximal_cliques(complement(graph))","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"For sparse graphs, the generic tensor network approach is usually much faster and memory efficient than the Bron Kerbosch algorithm.","category":"page"},{"location":"generated/MaximalIS/#finding-minimum-maximal-independent-set","page":"Maximal independent set problem","title":"finding minimum maximal independent set","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"It is the ConfigsMin property in the program.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"minimum_maximal_configs = read_config(solve(problem, ConfigsMin())[])\n\nshow_configs(graph, locations, reshape(collect(minimum_maximal_configs), 2, 5); padding_left=20)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Similarly, if one is only interested in computing one of the minimum sets, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"EditURL = \"../../../examples/MaxCut.jl\"","category":"page"},{"location":"generated/MaxCut/#Cutting-problem","page":"Cutting problem","title":"Cutting problem","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/MaxCut/#Problem-definition","page":"Cutting problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"In graph theory, a cut is a partition of the vertices of a graph into two disjoint subsets. It is closely related to the Spin-glass problem in physics. Finding the maximum cut is NP-Hard, where a maximum cut is a cut whose size is at least the size of any other cut, where the size of a cut is the number of edges (or the sum of weights on edges) crossing the cut.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"In the following, we are going to defined an cutting problem for the Petersen graph.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/MaxCut/#Generic-tensor-network-representation","page":"Cutting problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We can define the cutting problem with the MaxCut type as","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"maxcut = MaxCut(graph)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"The tensor network representation of the cutting problem can be obtained by","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"problem = GenericTensorNetwork(maxcut)","category":"page"},{"location":"generated/MaxCut/#Theory-(can-skip)","page":"Cutting problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We associated a vertex vin V with a boolean degree of freedom s_vin0 1. Then the maximum cutting problem can be encoded to tensor networks by mapping an edge (ij)in E to an edge matrix labelled by s_i and s_j","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"B(x_i x_j w_ij) = left(beginmatrix\n 1 x_i^w_ij\n x_j^w_ij 1\nendmatrixright)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where w_ij is a real number associated with edge (i j) as the edge weight. If and only if the bipartition cuts on edge (i j), this tensor contributes a factor x_i^w_ij or x_j^w_ij. Similarly, one can assign weights to vertices, which corresponds to the onsite energy terms in the spin glass. The vertex tensor is","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"W(x_i w_i) = left(beginmatrix\n 1\n x_i^w_i\nendmatrixright)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where w_i is a real number associated with vertex i as the vertex weight.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"Its contraction time space complexity is 2^rm tw(G), where rm tw(G) is the tree-width of G.","category":"page"},{"location":"generated/MaxCut/#Solving-properties","page":"Cutting problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/MaxCut/#Maximum-cut-size-\\gamma(G)","page":"Cutting problem","title":"Maximum cut size gamma(G)","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_cut_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/MaxCut/#Counting-properties","page":"Cutting problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/MaxCut/#graph-polynomial","page":"Cutting problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"The graph polynomial defined for the cutting problem is","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"C(G x) = sum_k=0^gamma(G) c_k x^k","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where gamma(G) is the maximum cut size, c_k2 is the number of cuts of size k in graph G=(VE). Since the variable x is defined on edges, the coefficients of the polynomial is the number of configurations having different number of anti-parallel edges.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_config = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/MaxCut/#Configuration-properties","page":"Cutting problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/MaxCut/#finding-one-max-cut-solution","page":"Cutting problem","title":"finding one max cut solution","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_vertex_config = read_config(solve(problem, SingleConfigMax())[])\n\nmax_cut_size_verify = cut_size(graph, max_vertex_config)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"You should see a consistent result as above max_cut_size.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"show_graph(graph, locations; vertex_colors=[\n iszero(max_vertex_config[i]) ? \"white\" : \"red\" for i=1:nv(graph)], format=:svg)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where red vertices and white vertices are separated by the cut.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"EditURL = \"../../../examples/saveload.jl\"","category":"page"},{"location":"generated/saveload/#Save-and-load-solutions","page":"Save and load solutions","title":"Save and load solutions","text":"","category":"section"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"Let us use the maximum independent set problem on Petersen graph as an example. The following code enumerates all independent sets.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"using GenericTensorNetworks, Graphs\n\nproblem = GenericTensorNetwork(IndependentSet(Graphs.smallgraph(:petersen)))\n\nall_independent_sets = solve(problem, ConfigsAll())[]","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"The return value has type ConfigEnumerator. We can use save_configs and load_configs to save and read a ConfigEnumerator instance to the disk.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"filename = tempname()\n\nsave_configs(filename, all_independent_sets; format=:binary)\n\nloaded_sets = load_configs(filename; format=:binary, bitlength=10)","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"note: Note\nWhen loading the data in the binary format, bit string length information bitlength is required.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"For the SumProductTree type output, we can use save_sumproduct and load_sumproduct to save and load serialized data.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]\n\nsave_sumproduct(filename, all_independent_sets_tree)\n\nloaded_sets_tree = load_sumproduct(filename)","category":"page"},{"location":"generated/saveload/#Loading-solutions-to-python","page":"Save and load solutions","title":"Loading solutions to python","text":"","category":"section"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"The following python script loads and unpacks the solutions as a numpy array from a :binary format file.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"import numpy as np\n\ndef loadfile(filename:str, bitlength:int):\n C = int(np.ceil(bitlength / 64))\n arr = np.fromfile(filename, dtype=\"uint8\")\n # Some axes should be transformed from big endian to little endian\n res = np.unpackbits(arr).reshape(-1, C, 8, 8)[:,::-1,::-1,:]\n res = res.reshape(-1, C*64)[:, :(64*C-bitlength)-1:-1]\n print(\"number of solutions = %d\"%(len(res)))\n return res # in big endian format\n\nres = loadfile(filename, 10)","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"note: Note\nCheck section Maximal independent set problem for solution space properties related the maximal independent sets. That example also contains using cases of finding solution space properties related to minimum sizes:SizeMin for finding minimum several set sizes,\nCountingMin for counting minimum several set sizes,\nSingleConfigMin for finding one solution with minimum several sizes,\nConfigsMin for enumerating solutions with minimum several sizes,","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"EditURL = \"../../../examples/SetCovering.jl\"","category":"page"},{"location":"generated/SetCovering/#Set-covering-problem","page":"Set covering problem","title":"Set covering problem","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SetCovering/#Problem-definition","page":"Set covering problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The set covering problem is a significant NP-hard problem in combinatorial optimization. Given a collection of elements, the set covering problem aims to find the minimum number of sets that incorporate (cover) all of these elements. In the following, we will find the solution space properties for the camera location and stadium area example in the Cornell University Computational Optimization Open Textbook.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The covering stadium areas of cameras are represented as the following sets.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"sets = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]","category":"page"},{"location":"generated/SetCovering/#Generic-tensor-network-representation","page":"Set covering problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"We can define the set covering problem with the SetCovering type as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"setcover = SetCovering(sets)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The tensor network representation of the set covering problem can be obtained by","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"problem = GenericTensorNetwork(setcover)","category":"page"},{"location":"generated/SetCovering/#Theory-(can-skip)","page":"Set covering problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Let S be the target set covering problem that we want to solve. For each set s in S, we associate it with a weight w_s to it. The tensor network representation map a set sin S to a boolean degree of freedom v_sin0 1. For each set s, we defined a parameterized rank-one tensor indexed by v_s as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"W(x_s^w_s) = left(beginmatrix\n 1 \n x_s^w_s\n endmatrixright)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"where x_s is a variable associated with s. For each unique element a, we defined the constraint over all sets containing it N(a) = s s in S land ain s:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"B_s_1s_2ldotss_N(a) = begincases\n 0 s_1=s_2=ldots=s_N(a)=0\n 1 textotherwise\nendcases","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"This tensor means if none of the sets containing element a are included, then this configuration is forbidden, One can check the contraction time space complexity of a SetCovering instance by typing:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/SetCovering/#Solving-properties","page":"Set covering problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/SetCovering/#Counting-properties","page":"Set covering problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SetCovering/#The-\"graph\"-polynomial","page":"Set covering problem","title":"The \"graph\" polynomial","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The graph polynomial for the set covering problem is defined as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"P(S x) = sum_k=0^S c_k x^k","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"where c_k is the number of configurations having k sets.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"covering_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The minimum number of sets that covering the set of elements can be computed with the SizeMin property:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"min_cover_size = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"counting_minimum_setcovering = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/SetCovering/#Configuration-properties","page":"Set covering problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SetCovering/#Finding-minimum-set-covering","page":"Set covering problem","title":"Finding minimum set covering","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"One can enumerate all minimum set covering with the ConfigsMin property in the program.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"min_configs = read_config(solve(problem, ConfigsMin())[])","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"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 function.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"all(c->is_set_covering(problem.problem, c), min_configs)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Similarly, if one is only interested in computing one of the minimum set coverings, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"gist/#Gist-of-implementation","page":"Gist","title":"Gist of implementation","text":"","category":"section"},{"location":"gist/","page":"Gist","title":"Gist","text":"The code we will show below is a gist of how this package is implemented for pedagogical purpose, which covers many functionalities of the main repo without caring much about performance. This project depends on multiple open source packages in the Julia ecosystem:","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"OMEinsum and OMEinsumContractionOrders are packages providing the support for Einstein's (or tensor network) notation and state-of-the-art algorithms for contraction order optimization, which includes multiple state of the art algorithms.\nTropicalNumbers and TropicalGEMM are packages providing tropical number and efficient tropical matrix multiplication.\nGraphs is a foundational package for graph manipulation in the Julia community.\nPolynomials is a package providing polynomial algebra and polynomial fitting.\nMods and the Primes package providing finite field algebra and prime number manipulation.","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"They can be installed in a similar way to GenericTensorNetworks. After installing the required packages, one can open a Julia REPL, and copy-paste the following code snippet into it.","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"using OMEinsum\nusing Graphs\nusing Random\n\n# generate a random regular graph of size 50, degree 3\ngraph = (Random.seed!(2); Graphs.random_regular_graph(50, 3))\n\n# generate einsum code, i.e. the labels of tensors\ncode = EinCode(([minmax(e.src,e.dst) for e in Graphs.edges(graph)]..., # labels for edge tensors\n [(i,) for i in Graphs.vertices(graph)]...), ()) # labels for vertex tensors\n\n# an einsum contraction without a contraction order specified is called `EinCode`,\n# an einsum contraction having a contraction order (specified as a tree structure) is called `NestedEinsum`.\n# assign each label a dimension-2, it will be used in the contraction order optimization\n# `uniquelabels` function extracts the tensor labels into a vector.\nsize_dict = Dict([s=>2 for s in uniquelabels(code)])\n# optimize the contraction order using the `TreeSA` method; the target space complexity is 2^17\noptimized_code = optimize_code(code, size_dict, TreeSA())\nprintln(\"time/space complexity is $(OMEinsum.timespace_complexity(optimized_code, size_dict))\")\n\n# a function for computing the independence polynomial\nfunction independence_polynomial(x::T, code) where {T}\n\txs = map(getixsv(code)) do ix\n # if the tensor rank is 1, create a vertex tensor.\n # otherwise the tensor rank must be 2, create a bond tensor.\n length(ix)==1 ? [one(T), x] : [one(T) one(T); one(T) zero(T)]\n end\n # both `EinCode` and `NestedEinsum` are callable, inputs are tensors.\n\tcode(xs...)\nend\n\n########## COMPUTING THE MAXIMUM INDEPENDENT SET SIZE AND ITS COUNTING/DEGENERACY ###########\n\n# using Tropical numbers to compute the MIS size and the MIS degeneracy.\nusing TropicalNumbers\nmis_size(code) = independence_polynomial(TropicalF64(1.0), code)[]\nprintln(\"the maximum independent set size is $(mis_size(optimized_code).n)\")\n\n# A `CountingTropical` object has two fields, tropical field `n` and counting field `c`.\nmis_count(code) = independence_polynomial(CountingTropical{Float64,Float64}(1.0, 1.0), code)[]\nprintln(\"the degeneracy of maximum independent sets is $(mis_count(optimized_code).c)\")\n\n########## COMPUTING THE INDEPENDENCE POLYNOMIAL ###########\n\n# using Polynomial numbers to compute the polynomial directly\nusing Polynomials\nprintln(\"the independence polynomial is $(independence_polynomial(Polynomial([0.0, 1.0]), optimized_code)[])\")\n\n########## FINDING MIS CONFIGURATIONS ###########\n\n# define the set algebra\nstruct ConfigEnumerator{N}\n # NOTE: BitVector is dynamic and it can be very slow; check our repo for the static version\n data::Vector{BitVector}\nend\nfunction Base.:+(x::ConfigEnumerator{N}, y::ConfigEnumerator{N}) where {N}\n res = ConfigEnumerator{N}(vcat(x.data, y.data))\n return res\nend\nfunction Base.:*(x::ConfigEnumerator{L}, y::ConfigEnumerator{L}) where {L}\n M, N = length(x.data), length(y.data)\n z = Vector{BitVector}(undef, M*N)\n for j=1:N, i=1:M\n z[(j-1)*M+i] = x.data[i] .| y.data[j]\n end\n return ConfigEnumerator{L}(z)\nend\nBase.zero(::Type{ConfigEnumerator{N}}) where {N} = ConfigEnumerator{N}(BitVector[])\nBase.one(::Type{ConfigEnumerator{N}}) where {N} = ConfigEnumerator{N}([falses(N)])\n\n# the algebra sampling one of the configurations\nstruct ConfigSampler{N}\n data::BitVector\nend\n\nfunction Base.:+(x::ConfigSampler{N}, y::ConfigSampler{N}) where {N} # biased sampling: return `x`\n return x # randomly pick one\nend\nfunction Base.:*(x::ConfigSampler{L}, y::ConfigSampler{L}) where {L}\n ConfigSampler{L}(x.data .| y.data)\nend\n\nBase.zero(::Type{ConfigSampler{N}}) where {N} = ConfigSampler{N}(trues(N))\nBase.one(::Type{ConfigSampler{N}}) where {N} = ConfigSampler{N}(falses(N))\n\n# enumerate all configurations if `all` is true; compute one otherwise.\n# a configuration is stored in the data type of `StaticBitVector`; it uses integers to represent bit strings.\n# `ConfigTropical` is defined in `TropicalNumbers`. It has two fields: tropical number `n` and optimal configuration `config`.\n# `CountingTropical{T,<:ConfigEnumerator}` stores configurations instead of simple counting.\nfunction mis_config(code; all=false)\n # map a vertex label to an integer\n vertex_index = Dict([s=>i for (i, s) in enumerate(uniquelabels(code))])\n N = length(vertex_index) # number of vertices\n xs = map(getixsv(code)) do ix\n T = all ? CountingTropical{Float64, ConfigEnumerator{N}} : CountingTropical{Float64, ConfigSampler{N}}\n if length(ix) == 2\n return [one(T) one(T); one(T) zero(T)]\n else\n s = falses(N)\n s[vertex_index[ix[1]]] = true # one hot vector\n if all\n [one(T), T(1.0, ConfigEnumerator{N}([s]))]\n else\n [one(T), T(1.0, ConfigSampler{N}(s))]\n end\n end\n end\n\treturn code(xs...)\nend\n\nprintln(\"one of the optimal configurations is $(mis_config(optimized_code; all=false)[].c.data)\")\n\n# direct enumeration of configurations can be very slow; please check the bounding version in our Github repo.\nprintln(\"all optimal configurations are $(mis_config(optimized_code; all=true)[].c)\")","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"EditURL = \"../../../examples/DominatingSet.jl\"","category":"page"},{"location":"generated/DominatingSet/#Dominating-set-problem","page":"Dominating set problem","title":"Dominating set problem","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/DominatingSet/#Problem-definition","page":"Dominating set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"In graph theory, a dominating set for a graph G = (V E) is a subset D of V such that every vertex not in D is adjacent to at least one member of D. The domination number gamma(G) is the number of vertices in a smallest dominating set for G. The decision version of finding the minimum dominating set is an NP-complete. In the following, we are going to solve the dominating set problem on the Petersen graph.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/DominatingSet/#Generic-tensor-network-representation","page":"Dominating set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"We can use DominatingSet to construct the tensor network for solving the dominating set problem as","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"dom = DominatingSet(graph)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The tensor network representation of the dominating set problem can be obtained by","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"problem = GenericTensorNetwork(dom; optimizer=TreeSA())","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA.","category":"page"},{"location":"generated/DominatingSet/#Theory-(can-skip)","page":"Dominating set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Let G=(VE) be the target graph that we want to solve. The tensor network representation map a vertex vin V to a boolean degree of freedom s_vin0 1. We defined the restriction on a vertex and its neighboring vertices N(v):","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"T(x_v)_s_1s_2ldotss_N(v)s_v = begincases\n 0 s_1=s_2=ldots=s_N(v)=s_v=0\n 1 s_v=0\n x_v^w_v textotherwise\nendcases","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where w_v is the weight of vertex v. This tensor means if both v and its neighboring vertices are not in D, i.e., s_1=s_2=ldots=s_N(v)=s_v=0, this configuration is forbidden because v is not adjacent to any member in the set. otherwise, if v is in D, it has a contribution x_v^w_v to the final result. One can check the contraction time space complexity of a DominatingSet instance by typing:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/DominatingSet/#Solving-properties","page":"Dominating set problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/DominatingSet/#Counting-properties","page":"Dominating set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/DominatingSet/#Domination-polynomial","page":"Dominating set problem","title":"Domination polynomial","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The graph polynomial for the dominating set problem is known as the domination polynomial (see arXiv:0905.2251). It is defined as","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"D(G x) = sum_k=0^gamma(G) d_k x^k","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where d_k is the number of dominating sets of size k in graph G=(V E).","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"domination_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The domination number gamma(G) can be computed with the SizeMin property:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"domination_number = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"counting_min_dominating_set = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/DominatingSet/#Configuration-properties","page":"Dominating set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/DominatingSet/#finding-minimum-dominating-set","page":"Dominating set problem","title":"finding minimum dominating set","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"One can enumerate all minimum dominating sets with the ConfigsMin property in the program.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"min_configs = read_config(solve(problem, ConfigsMin())[])\n\nall(c->is_dominating_set(graph, c), min_configs)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"show_configs(graph, locations, reshape(collect(min_configs), 2, 5); padding_left=20)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Similarly, if one is only interested in computing one of the minimum dominating sets, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"EditURL = \"../../../examples/weighted.jl\"","category":"page"},{"location":"generated/weighted/#Weighted-problems","page":"Weighted problems","title":"Weighted problems","text":"","category":"section"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"Let us use the maximum independent set problem on Petersen graph as an example.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The following code constructs a weighted MIS problem instance.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"problem = GenericTensorNetwork(IndependentSet(graph, collect(1:10)));\nGenericTensorNetworks.weights(problem)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The tensor labels that associated with the weights can be accessed by","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"ProblemReductions.local_solution_spec(problem.problem)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"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. For example, the maximum independent set can be found as follows.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"max_config_weighted = solve(problem, SingleConfigMax())[]","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"Let us visualize the solution.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg, vertex_colors=\n [iszero(max_config_weighted.c.data[i]) ? \"white\" : \"red\" for i=1:nv(graph)])","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The only solution space property that can not be defined for general real-weighted (not including integer-weighted) graphs is the GraphPolynomial.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"For the weighted MIS problem, a useful solution space property is the \"energy spectrum\", i.e. the largest several configurations and their weights. We can use the solution space property is SizeMax(10) to compute the largest 10 weights.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"spectrum = solve(problem, SizeMax(10))[]","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The return value has type ExtendedTropical, which contains one field orders.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"spectrum.orders","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"We can see the order is a vector of Tropical numbers. Similarly, we can get weighted independent sets with maximum 5 sizes as follows.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"max5_configs = read_config(solve(problem, SingleConfigMax(5))[])","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The return value of solve has type ExtendedTropical, but this time the element type of orders has been changed to CountingTropical{Float64,ConfigSampler}. Let us visually check these configurations","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"show_configs(graph, locations, [max5_configs[j] for i=1:1, j=1:5]; padding_left=20)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"This page was generated using Literate.jl.","category":"page"},{"location":"ref/#References","page":"References","title":"References","text":"","category":"section"},{"location":"ref/#Constraint-Satisfaction-Problems","page":"References","title":"Constraint Satisfaction Problems","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"solve\nGenericTensorNetwork\nConstraintSatisfactionProblem\nIndependentSet\nMaximalIS\nMatching\nColoring\nDominatingSet\nSpinGlass\nMaxCut\nPaintShop\nSatisfiability\nSetCovering\nSetPacking","category":"page"},{"location":"ref/#GenericTensorNetworks.solve","page":"References","title":"GenericTensorNetworks.solve","text":"solve(problem, property; usecuda=false, T=Float64)\n\nSolving a certain property of a graph problem.\n\nPositional Arguments\n\nproblem is the graph problem with tensor network information,\nproperty is string specifying the task. Using the maximum independent set problem as an example, it can be one of\nPartitionFunction() for computing the partition function,\nSizeMax(k=Single) for finding maximum-k set sizes,\nSizeMin(k=Single) for finding minimum-k set sizes,\nCountingMax(k=Single) for counting configurations with maximum-k sizes,\nCountingMin(k=Single) for counting configurations with minimum-k sizes,\nCountingAll() for counting all configurations,\nPartitionFunction() for counting all configurations,\nGraphPolynomial(; method=:finitefield, kwargs...) for evaluating the graph polynomial,\nSingleConfigMax(k=Single; bounded=false) for finding one maximum-k configuration for each size,\nSingleConfigMin(k=Single; bounded=false) for finding one minimum-k configuration for each size,\nConfigsMax(k=Single; bounded=true, tree_storage=false) for enumerating configurations with maximum-k sizes,\nConfigsMin(k=Single; bounded=true, tree_storage=false) for enumerating configurations with minimum-k sizes,\nConfigsAll(; tree_storage=false) for enumerating all configurations,\n\nKeyword arguments\n\nusecuda is a switch to use CUDA (if possible), user need to call statement using CUDA before turning on this switch.\nT is the \"base\" element type, sometimes can be used to reduce the memory cost.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.GenericTensorNetwork","page":"References","title":"GenericTensorNetworks.GenericTensorNetwork","text":"struct GenericTensorNetwork{CFG, CT, LT}\n\nGenericTensorNetwork(problem::ConstraintSatisfactionProblem; openvertices=(), fixedvertices=Dict(), optimizer=GreedyMethod())\n\nThe generic tensor network that generated from a ConstraintSatisfactionProblem.\n\nPositional arguments\n\nproblem is the graph problem.\ncode is the tensor network contraction code.\nfixedvertices is a dictionary specifying the fixed dimensions.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.ConstraintSatisfactionProblem","page":"References","title":"ProblemReductions.ConstraintSatisfactionProblem","text":"ConstraintSatisfactionProblem{T} <: AbstractProblem\n\nThe abstract base type of constraint satisfaction problems. T is the type of the local size of the constraints.\n\nRequired interfaces\n\nhard_constraints, the specification of the hard constraints. Once the hard constraints are violated, the size goes to infinity.\nis_satisfied, check if the hard constraints are satisfied.\nlocal_solution_spec, the specification of the size terms as soft constraints, which is associated with weights.\nweights: The weights of the soft constraints.\nset_weights: Change the weights for the problem and return a new problem instance.\nsolution_size, the size of the problem given a configuration.\nenergy_mode, the definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.IndependentSet","page":"References","title":"ProblemReductions.IndependentSet","text":"struct IndependentSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nIndependentSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(nv(graph))) -> IndependentSet\n\nIndependent 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.\n\nFields\n\ngraph::AbstractGraph: The problem graph.\nweights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(nv(graph)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))\n{4, 4} undirected simple Int64 graph\n\njulia> IS = IndependentSet(graph)\nIndependentSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, 1, 1, 1])\n\njulia> num_variables(IS) # degrees of freedom\n4\n\njulia> flavors(IS) # flavors of the vertices\n(0, 1)\n\njulia> solution_size(IS, [1, 0, 0, 1]) # Positive sample: -(size) of an independent set\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(IS, [0, 1, 1, 0]) # Negative sample: 0\nSolutionSize{Int64}(2, false)\n\njulia> findbest(IS, BruteForce()) # solve the problem with brute force\n2-element Vector{Vector{Int64}}:\n [1, 0, 0, 1]\n [0, 1, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.MaximalIS","page":"References","title":"ProblemReductions.MaximalIS","text":"struct MaximalIS{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nMaximal 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.\n\nFields\n\ngraph is the problem graph.\nweights are associated with the vertices of the graph.\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3), (1, 4)]))\n{4, 5} undirected simple Int64 graph\n\njulia> problem = MaximalIS(graph)\nMaximalIS{Int64, UnitWeight}(SimpleGraph{Int64}(5, [[2, 3, 4], [1, 3], [1, 2, 4], [1, 3]]), [1, 1, 1, 1])\n\njulia> num_variables(problem) # degrees of freedom\n4\n\njulia> flavors(problem)\n(0, 1)\n\njulia> solution_size(problem, [0, 1, 0, 0]) # unlike the independent set, this configuration is not a valid solution\nSolutionSize{Int64}(1, false)\n\njulia> findbest(problem, BruteForce())\n1-element Vector{Vector{Int64}}:\n [0, 1, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Matching","page":"References","title":"ProblemReductions.Matching","text":"struct Matching{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nThe Vertex matching problem.\n\nPositional arguments\n\ngraph is the problem graph.\nweights are associated with the edges of the graph.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Coloring","page":"References","title":"ProblemReductions.Coloring","text":"struct Coloring{K, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nColoring{K}(graph; weights=UnitWeight(nv(graph)))\n\nThe 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.\n\nFields\n\ngraph is the problem graph.\nweights are associated with the edges of the graph, default to UnitWeight(ne(graph)).\n\nExample\n\nTo initialize a Coloring problem, we need to first define a graph and decide the number of colors.\n\njulia> using ProblemReductions, Graphs\n\njulia> g = smallgraph(:petersen) # define a simple graph, petersen as example\n{10, 15} undirected simple Int64 graph\n\njulia> coloring = Coloring{3}(g) # 3 colors\nColoring{3, Int64, UnitWeight}(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])\n\njulia> variables(coloring)\n1:10\n\njulia> flavors(coloring)\n(0, 1, 2)\n\njulia> is_vertex_coloring(coloring.graph,[1,2,3,1,3,2,1,2,3,1]) #random assignment\nfalse\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.DominatingSet","page":"References","title":"ProblemReductions.DominatingSet","text":"struct DominatingSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nDominatingSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(ne(graph))) -> DominatingSet\n\nDominaing 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.\n\nFields\n\ngraph is the problem graph.\nweights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(nv(graph)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = path_graph(5)\n{5, 4} undirected simple Int64 graph\n\njulia> DS = DominatingSet(graph)\nDominatingSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2], [1, 3], [2, 4], [3, 5], [4]]), [1, 1, 1, 1, 1])\n\njulia> variables(DS) # degrees of freedom\n1:5\n\njulia> flavors(DS) # flavors of the vertices\n(0, 1)\n\njulia> solution_size(DS, [0, 1, 0, 1, 0]) # Positive sample: (size) of a dominating set\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(DS, [0, 1, 1, 0, 0]) # Negative sample: number of vertices\nSolutionSize{Int64}(2, false)\n\njulia> findbest(DS, BruteForce()) # solve the problem with brute force\n3-element Vector{Vector{Int64}}:\n [1, 0, 0, 1, 0]\n [0, 1, 0, 1, 0]\n [0, 1, 0, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SpinGlass","page":"References","title":"ProblemReductions.SpinGlass","text":"struct SpinGlass{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nSpinGlass(graph::AbstractGraph, weights::AbstractVector)\nSpinGlass(graph::SimpleGraph, J, h=zeros(nv(graph)))\n\nSpin Glass is a type of disordered magnetic system that exhibits a glassy behavior. The Hamiltonian of the system on a simple graph G is given by\n\nH(G sigma) = sum_(ij) in E(G) J_ij sigma_i sigma_j + sum_i in V(G) h_i sigma_i\n\nwhere J_ij in mathbbR is the coupling strength between spins i and j, h_i in mathbbR is the external field on spin i, and sigma_i is the spin variable that can take values in -1 1 for spin up and spin down, respectively.\n\nThis definition naturally extends to the case of a HyperGraph:\n\nH(G sigma) = sum_e in E(G) J_e prod_ksigma_k + sum_i in V(G) h_i sigma_i\n\nwhere J_e is the coupling strength associated with hyperedge e, and the product is over all spins in the hyperedge.\n\nFields\n\ngraph is a graph object.\nJ are the coupling strengths associated with the edges.\nh are the external fields associated with the vertices.\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, ProblemReductions.Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))\n{4, 4} undirected simple Int64 graph\n\njulia> J = [1, -1, 1, -1] # coupling strength\n4-element Vector{Int64}:\n 1\n -1\n 1\n -1\n\njulia> h = [1, -1, -1, 1] # external field\n4-element Vector{Int64}:\n 1\n -1\n -1\n 1\n\njulia> spinglass = SpinGlass(graph, J, h) # Define a spin glass problem\nSpinGlass{SimpleGraph{Int64}, Int64, Vector{Int64}}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, -1, 1, -1], [1, -1, -1, 1])\n\njulia> num_variables(spinglass) # degrees of freedom\n4\n\njulia> flavors(spinglass) # flavors of the spins\n(1, -1)\n\njulia> solution_size(spinglass, [-1, 1, 1, -1]) # size of a configuration\nSolutionSize{Int64}(-2, true)\n\njulia> findbest(spinglass, BruteForce()) # solve the problem with brute force\n1-element Vector{Vector{Int64}}:\n [-1, 1, -1, -1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.MaxCut","page":"References","title":"ProblemReductions.MaxCut","text":"struct MaxCut{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nMax 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.\n\nPositional arguments\n\ngraph is the problem graph.\nweights are associated with the edges of the graph. We have ensure that the weights are in the same order as the edges in edges(graph).\n\nExample\n\nIn the following example, we solve a Max Cut problem on a complete graph with 3 vertices and edge weights [1,2,3].\n\njulia> using ProblemReductions, Graphs\n\njulia> g = complete_graph(3)\n{3, 3} undirected simple Int64 graph\n\njulia> maxcut = MaxCut(g,[1,2,3]) # specify the weights of the edges\nMaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [1, 2, 3])\n\njulia> mc = set_weights(maxcut, [2,1,3]) # set the weights and get a new instance\nMaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [2, 1, 3])\n\n\njulia> num_variables(maxcut) # return the number of vertices\n3\n\njulia> flavors(maxcut) # return the flavors of the vertices\n(0, 1)\n\njulia> solution_size(maxcut, [0,1,0]) # return the size of the configuration\nSolutionSize{Int64}(4, true)\n\njulia> findbest(maxcut, BruteForce()) # find the best configuration\n2-element Vector{Vector{Int64}}:\n [1, 1, 0]\n [0, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.PaintShop","page":"References","title":"ProblemReductions.PaintShop","text":"struct PaintShop{LT} <: ConstraintSatisfactionProblem{Int64}\n\nThe 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.\n\nFields\n\nsequence is a vector of symbols, each symbol is associated with a color.\nisfirst is a vector of boolean numbers, indicating whether the symbol is the first appearance in the sequence.\n\nExample\n\nIn the following example, we define a paint shop problem with 6 cars.\n\njulia> using ProblemReductions\n\njulia> problem = PaintShop([\"a\",\"b\",\"a\",\"c\",\"c\",\"b\"])\nPaintShop{String}([\"a\", \"b\", \"a\", \"c\", \"c\", \"b\"], Bool[1, 1, 0, 1, 0, 0])\n\njulia> num_variables(problem)\n3\n\njulia> flavors(problem)\n(0, 1)\n\njulia> solution_size(problem, [0, 1, 0])\nSolutionSize{Int64}(4, true)\n\njulia> findbest(problem, BruteForce())\n2-element Vector{Vector{Int64}}:\n [1, 0, 0]\n [0, 1, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Satisfiability","page":"References","title":"ProblemReductions.Satisfiability","text":"struct Satisfiability{S, T, WT<:(AbstractArray{T})} <: ProblemReductions.AbstractSatisfiabilityProblem{S, T}\n\nSatisfiability (also called SAT) problem is to find the boolean assignment that satisfies a Conjunctive Normal Form (CNF). A tipical CNF would look like:\n\nleft(l_11 vee ldots vee l_1 n_1right) wedge ldots wedgeleft(l_m 1 vee ldots vee l_m n_mright)\n\nwhere literals are joint by vee to for m clauses and clauses are joint by wedge to form a CNF.\n\nWe 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.\n\nFields\n\ncnf is a conjunctive normal form (CNF) for specifying the satisfiability problems.\nweights are associated with clauses.\n\nExample\n\nIn the following example, we define a satisfiability problem with two clauses.\n\njulia> using ProblemReductions\n\njulia> bv1, bv2, bv3 = BoolVar.([\"x\", \"y\", \"z\"])\n3-element Vector{BoolVar{String}}:\n x\n y\n z\n\njulia> clause1 = CNFClause([bv1, bv2, bv3])\nx ∨ y ∨ z\n\njulia> clause2 = CNFClause([BoolVar(\"w\"), bv1, BoolVar(\"x\", true)])\nw ∨ x ∨ ¬x\n\njulia> cnf_test = CNF([clause1, clause2])\n(x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x)\n\njulia> sat_test = Satisfiability(cnf_test)\nSatisfiability{String, Int64, UnitWeight}([\"x\", \"y\", \"z\", \"w\"], [1, 1], (x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x))\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SetCovering","page":"References","title":"ProblemReductions.SetCovering","text":"struct SetCovering{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nThe 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.\n\nPositional arguments\n\nelements is a vector of elements in the universe.\nsets is a vector of vectors, a collection of subsets of universe , each set is associated with a weight specified in weights.\nweights are associated with sets.\n\nExample\n\nIn the following example, we solve a Set Covering problem with 3 subsets and weights [1,2,3].\n\njulia> using ProblemReductions\n\njulia> subsets = [[1, 2, 3], [2, 4], [1, 4]]\n3-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [2, 4]\n [1, 4]\n\njulia> weights = [1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> setcovering = SetCovering(subsets, weights)\nSetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])\n\njulia> num_variables(setcovering) # degrees of freedom\n3\n\njulia> solution_size(setcovering, [1, 0, 1]) # size of a configuration\nSolutionSize{Int64}(4, true)\n\njulia> solution_size(setcovering, [0, 1, 1])\nSolutionSize{Int64}(5, false)\n\njulia> sc = set_weights(setcovering, [1, 2, 3]) # set the weights of the subsets\nSetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SetPacking","page":"References","title":"ProblemReductions.SetPacking","text":"struct SetPacking{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nSetPacking(elements::AbstractVector, sets::AbstractVector, weights::AbstractVector=UnitWeight(length(sets))) -> SetPacking\n\nA 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.\n\nFields\n\nelements is a vector of elements in the universe.\nsets is a vector of vectors, each set is associated with a weight specified in weights.\nweights are associated with sets. Defaults to UnitWeight(length(sets)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions\n\njulia> sets = [[1, 2, 5], [1, 3], [2, 4], [3, 6], [2, 3, 6]]\n5-element Vector{Vector{Int64}}:\n [1, 2, 5]\n [1, 3]\n [2, 4]\n [3, 6]\n [2, 3, 6]\n\njulia> SP = SetPacking(sets)\nSetPacking{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])\n\njulia> num_variables(SP) # degrees of freedom\n5\n\njulia> flavors(SP) # flavors of the subsets\n(0, 1)\n\njulia> solution_size(SP, [1, 0, 0, 1, 0]) # Positive sample: -(size) of a packing\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(SP, [1, 0, 1, 1, 0]) # Negative sample: 0\nSolutionSize{Int64}(3, false)\n\njulia> findbest(SP, BruteForce()) # solve the problem with brute force\n3-element Vector{Vector{Int64}}:\n [0, 1, 1, 0, 0]\n [1, 0, 0, 1, 0]\n [0, 0, 1, 1, 0]\n\n\n\n\n\n","category":"type"},{"location":"ref/#Constraint-Satisfaction-Problem-Interfaces","page":"References","title":"Constraint Satisfaction Problem Interfaces","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"To subtype ConstraintSatisfactionProblem, a new type must contain a code field to represent the (optimized) tensor network. Interfaces GenericTensorNetworks.generate_tensors, flavors and weights are required. num_flavors is optional.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks.generate_tensors\nflavors\nweights\nset_weights\nis_weighted\nnum_flavors\nfixedvertices","category":"page"},{"location":"ref/#GenericTensorNetworks.generate_tensors","page":"References","title":"GenericTensorNetworks.generate_tensors","text":"generate_tensors(func, problem::GenericTensorNetwork)\n\nGenerate 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.\n\nExample\n\nThe following code gives your the maximum independent set size\n\njulia> using Graphs, GenericTensorNetworks\n\njulia> gp = GenericTensorNetwork(IndependentSet(smallgraph(:petersen)));\n\njulia> getixsv(gp.code)\n25-element Vector{Vector{Int64}}:\n [1, 2]\n [1, 5]\n [1, 6]\n [2, 3]\n [2, 7]\n [3, 4]\n [3, 8]\n [4, 5]\n [4, 9]\n [5, 10]\n ⋮\n [2]\n [3]\n [4]\n [5]\n [6]\n [7]\n [8]\n [9]\n [10]\n\njulia> gp.code(GenericTensorNetworks.generate_tensors(Tropical(1.0), gp)...)\n0-dimensional Array{Tropical{Float64}, 0}:\n4.0ₜ\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.flavors","page":"References","title":"ProblemReductions.flavors","text":"flavors(::Type{<:AbstractProblem}) -> Vector\n\nReturns a vector of integers as the flavors (domain) of a degree of freedom.\n\n\n\n\n\nflavors(::Type{<:GenericTensorNetwork}) -> Vector\n\nIt 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.weights","page":"References","title":"ProblemReductions.weights","text":"weights(problem::ConstraintSatisfactionProblem) -> Vector\n\nThe weights of the constraints in the problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.set_weights","page":"References","title":"ProblemReductions.set_weights","text":"set_weights(problem::ConstraintSatisfactionProblem, weights) -> ConstraintSatisfactionProblem\n\nChange the weights for the problem and return a new problem instance.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_weighted","page":"References","title":"ProblemReductions.is_weighted","text":"is_weighted(problem::ConstraintSatisfactionProblem) -> Bool\n\nCheck if the problem is weighted. Returns true if the problem has non-unit weights.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.num_flavors","page":"References","title":"ProblemReductions.num_flavors","text":"num_flavors(::Type{<:AbstractProblem}) -> Int\nnum_flavors(::GT) where GT<:AbstractProblem -> Int\n\nReturns the number of flavors (domain) of a degree of freedom.\n\n\n\n\n\nnum_flavors(::GenericTensorNetwork{GT}) where GT<:ConstraintSatisfactionProblem -> Int\n\nBond size is equal to the number of flavors.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.fixedvertices","page":"References","title":"GenericTensorNetworks.fixedvertices","text":"fixedvertices(tnet::GenericTensorNetwork) -> Dict\n\nReturns the fixed vertices in the graph problem, which is a dictionary specifying the fixed dimensions.\n\n\n\n\n\n","category":"function"},{"location":"ref/#Constraint-Satisfaction-Problem-Utilities","page":"References","title":"Constraint Satisfaction Problem Utilities","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"hard_constraints\nis_satisfied\nlocal_solution_spec\nsolution_size\nenergy_mode\nLargerSizeIsBetter\nSmallerSizeIsBetter\nenergy\n\nis_independent_set\nis_maximal_independent_set\nis_dominating_set\nis_vertex_coloring\nis_matching\nis_set_covering\nis_set_packing\n\ncut_size\nnum_paint_shop_color_switch\n\nCNF\nCNFClause\nBoolVar\nsatisfiable\n@bools\n∨\n¬\n∧\n\nmis_compactify!","category":"page"},{"location":"ref/#ProblemReductions.hard_constraints","page":"References","title":"ProblemReductions.hard_constraints","text":"hard_constraints(problem::AbstractProblem) -> Vector{HardConstraint}\n\nThe hard constraints of the problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_satisfied","page":"References","title":"ProblemReductions.is_satisfied","text":"is_satisfied(::Type{<:ConstraintSatisfactionProblem}, constraint::HardConstraint, config) -> Bool\n\nCheck if the constraint is satisfied by the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.local_solution_spec","page":"References","title":"ProblemReductions.local_solution_spec","text":"local_solution_spec(problem::AbstractProblem) -> Vector{LocalSolutionSpec}\n\nThe constraints related to the size of the problem. Each term is associated with weights.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.solution_size","page":"References","title":"ProblemReductions.solution_size","text":"solution_size(problem::AbstractProblem, config) -> SolutionSize\n\nSize of the problem given the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.energy_mode","page":"References","title":"ProblemReductions.energy_mode","text":"energy_mode(problem::AbstractProblem) -> EnergyMode\n\nThe definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter. If will be used in the energy based modeling of the target problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.LargerSizeIsBetter","page":"References","title":"ProblemReductions.LargerSizeIsBetter","text":"LargerSizeIsBetter <: EnergyMode\n\nThe energy is defined as the negative size of the solution, which is the larger size the lower energy.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SmallerSizeIsBetter","page":"References","title":"ProblemReductions.SmallerSizeIsBetter","text":"SmallerSizeIsBetter <: EnergyMode\n\nThe energy is defined as the size of the solution, which is the smaller size the lower energy.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.energy","page":"References","title":"ProblemReductions.energy","text":"energy(problem::AbstractProblem, config) -> Number\n\nThe energy of the problem given the configuration config. Please check the energy_mode for the definition of the energy function.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_independent_set","page":"References","title":"ProblemReductions.is_independent_set","text":"is_independent_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is an independent set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_maximal_independent_set","page":"References","title":"ProblemReductions.is_maximal_independent_set","text":"is_maximal_independent_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is a maximal independent set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_dominating_set","page":"References","title":"ProblemReductions.is_dominating_set","text":"is_dominating_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is a dominating set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_vertex_coloring","page":"References","title":"ProblemReductions.is_vertex_coloring","text":"is_vertex_coloring(graph::SimpleGraph, config)\n\nReturns 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_matching","page":"References","title":"ProblemReductions.is_matching","text":"is_matching(graph::SimpleGraph, config)\n\nReturns 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).\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_set_covering","page":"References","title":"ProblemReductions.is_set_covering","text":"is_set_covering(c::SetCovering, config)\n\nReturn true if config (a vector of boolean numbers as the mask of sets) is a set covering of sets.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_set_packing","page":"References","title":"ProblemReductions.is_set_packing","text":"is_set_packing(sp::SetPacking, config)\n\nReturn true if config (a vector of boolean numbers as the mask of sets) is a set packing of sp.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.cut_size","page":"References","title":"ProblemReductions.cut_size","text":"cut_size(g::AbstractGraph, config; weights=UnitWeight(ne(g)))\n\nReturn 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.num_paint_shop_color_switch","page":"References","title":"ProblemReductions.num_paint_shop_color_switch","text":"num_paint_shop_color_switch(sequence::AbstractVector, coloring)\n\nReturns the number of color switches.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.CNF","page":"References","title":"ProblemReductions.CNF","text":"CNF{T}\nCNF(clauses)\n\nBoolean expression in conjunctive normal form. clauses is a vector of CNFClause, if and only if all clauses are satisfied, this CNF is satisfied.\n\nExample\n\nUnder development\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.CNFClause","page":"References","title":"ProblemReductions.CNFClause","text":"CNFClause{T}\nCNFClause(vars)\n\nA clause in CNF, its value is the logical or of vars, where vars is a vector of BoolVar.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.BoolVar","page":"References","title":"ProblemReductions.BoolVar","text":"BoolVar{T}\nBoolVar(name, neg)\n\nBoolean variable for constructing CNF clauses.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.satisfiable","page":"References","title":"ProblemReductions.satisfiable","text":"satisfiable(expr, config::AbstractDict{T}) where T\n\nCheck if the boolean expression expr is satisfied by the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.@bools","page":"References","title":"ProblemReductions.@bools","text":"@bools(syms::Symbol...)\n\nCreate some boolean variables of type BoolVar in current scope that can be used in create a CNF.\n\nExample\n\nUnder Development\n\n\n\n\n\n","category":"macro"},{"location":"ref/#ProblemReductions.:∨","page":"References","title":"ProblemReductions.:∨","text":"∨(vars...)\n\nLogical or applied on BoolVar and CNFClause. Returns a CNFClause.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.:¬","page":"References","title":"ProblemReductions.:¬","text":"¬(var::BoolVar)\n\nNegation of a boolean variables of type BoolVar.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.:∧","page":"References","title":"ProblemReductions.:∧","text":"∧(vars...)\n\nLogical and applied on CNFClause and CNF. Returns a new CNF.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.mis_compactify!","page":"References","title":"GenericTensorNetworks.mis_compactify!","text":"mis_compactify!(tropicaltensor; potential=nothing)\n\nCompactify 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).\n\nArguments\n\ntropicaltensor::AbstractArray{T}: the tropical tensor\n\nKeyword arguments\n\npotential=nothing: the maximum possible MIS contribution from each open vertex\n\n\n\n\n\n","category":"function"},{"location":"ref/#Properties","page":"References","title":"Properties","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"PartitionFunction\nSizeMax\nSizeMin\nCountingAll\nCountingMax\nCountingMin\nGraphPolynomial\nSingleConfigMax\nSingleConfigMin\nConfigsAll\nConfigsMax\nConfigsMin","category":"page"},{"location":"ref/#GenericTensorNetworks.PartitionFunction","page":"References","title":"GenericTensorNetworks.PartitionFunction","text":"struct PartitionFunction{T} <: GenericTensorNetworks.AbstractProperty\n\nbeta\n\nCompute the partition function for the target problem.\n\nThe corresponding tensor element type is T.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SizeMax","page":"References","title":"GenericTensorNetworks.SizeMax","text":"SizeMax{K} <: AbstractProperty\nSizeMax(k::Int)\n\nThe maximum-K set sizes. e.g. the largest size of the IndependentSet problem is also know as the independence number.\n\nThe corresponding tensor element type are max-plus tropical number Tropical if K is Single and ExtendedTropical if K is an integer.\nIt is compatible with weighted Constraint Satisfaction Problems.\nBLAS (on CPU) and GPU are supported only if K is Single,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SizeMin","page":"References","title":"GenericTensorNetworks.SizeMin","text":"SizeMin{K} <: AbstractProperty\nSizeMin(k::Int)\n\nThe minimum-K set sizes. e.g. the smallest size ofthe MaximalIS problem is also known as the independent domination number.\n\nThe corresponding tensor element type are inverted max-plus tropical number Tropical if K is Single and inverted ExtendedTropical K is an integer.\n\nThe inverted Tropical number emulates the min-plus tropical number.\n\nIt is compatible with weighted constraint satisfaction problems.\nBLAS (on CPU) and GPU are supported only if K is Single,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingAll","page":"References","title":"GenericTensorNetworks.CountingAll","text":"CountingAll <: AbstractProperty\nCountingAll()\n\nCounting the total number of sets. e.g. for the IndependentSet problem, it counts the independent sets.\n\nThe corresponding tensor element type is Base.Real.\nThe weights on graph does not have effect.\nBLAS (GPU and CPU) and GPU are supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingMax","page":"References","title":"GenericTensorNetworks.CountingMax","text":"CountingMax{K} <: AbstractProperty\nCountingMax(K=Single)\n\nCounting 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.\n\nThe corresponding tensor element type is CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.\nWeighted constraint satisfaction problems is only supported if K is Single.\nGPU is supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingMin","page":"References","title":"GenericTensorNetworks.CountingMin","text":"CountingMin{K} <: AbstractProperty\nCountingMin(K=Single)\n\nCounting the number of sets with smallest-K size.\n\nThe corresponding tensor element type is inverted CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.\nWeighted constraint satisfaction problems is only supported if K is Single.\nGPU is supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.GraphPolynomial","page":"References","title":"GenericTensorNetworks.GraphPolynomial","text":"GraphPolynomial{METHOD} <: AbstractProperty\nGraphPolynomial(; method=:finitefield, kwargs...)\n\nCompute the graph polynomial, e.g. for IndependentSet problem, it is the independence polynomial. The METHOD type parameter can be one of the following symbols\n\nMethod Argument\n\n:finitefield, uses finite field algebra to fit the polynomial.\nThe corresponding tensor element type is Mods.Mod,\nIt does not have round-off error,\nGPU is supported,\nIt accepts keyword arguments maxorder (optional, e.g. the MIS size in the IndependentSet problem).\n:polynomial and :laurent, use (Laurent) polynomial numbers to solve the polynomial directly.\nThe corresponding tensor element types are Polynomial and LaurentPolynomial.\nIt might have small round-off error depending on the data type for storing the counting.\nIt has memory overhead that linear to the graph size.\n:fft, use fast fourier transformation to fit the polynomial.\nThe corresponding tensor element type is Base.Complex.\nIt has (controllable) round-off error.\nBLAS and GPU are supported.\nIt accepts keyword arguments maxorder (optional) and r, if r > 1, one has better precision for coefficients of large order, if r < 1, one has better precision for coefficients of small order.\n:fitting, fit the polynomial directly.\nThe corresponding tensor element type is floating point numbers like Base.Float64.\nIt has round-off error.\nBLAS and GPU are supported, it is the fastest among all methods.\n\nGraph polynomials are not defined for weighted constraint satisfaction problems.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SingleConfigMax","page":"References","title":"GenericTensorNetworks.SingleConfigMax","text":"SingleConfigMax{K, BOUNDED} <: AbstractProperty\nSingleConfigMax(k::Int; bounded=false)\n\nFinding single solution for largest-K sizes, e.g. for IndependentSet problem, it is one of the maximum independent sets.\n\nThe corresponding data type is CountingTropical{Float64,<:ConfigSampler} if BOUNDED is false, Tropical otherwise.\nWeighted constraint satisfaction problems is supported.\nGPU is supported,\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SingleConfigMin","page":"References","title":"GenericTensorNetworks.SingleConfigMin","text":"SingleConfigMin{K, BOUNDED} <: AbstractProperty\nSingleConfigMin(k::Int; bounded=false)\n\nFinding single solution with smallest-K size.\n\nThe corresponding data type is inverted CountingTropical{Float64,<:ConfigSampler} if BOUNDED is false, inverted Tropical otherwise.\nWeighted constraint satisfaction problems is supported.\nGPU is supported,\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsAll","page":"References","title":"GenericTensorNetworks.ConfigsAll","text":"ConfigsAll{TREESTORAGE} <:AbstractProperty\nConfigsAll(; tree_storage=false)\n\nFind all valid configurations, e.g. for IndependentSet problem, it is finding all independent sets.\n\nThe corresponding data type is ConfigEnumerator.\nWeights do not take effect.\n\nKeyword Arguments\n\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsMax","page":"References","title":"GenericTensorNetworks.ConfigsMax","text":"ConfigsMax{K, BOUNDED, TREESTORAGE} <:AbstractProperty\nConfigsMax(K=Single; bounded=true, tree_storage=true)\n\nFind 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.\n\nThe corresponding data type is CountingTropical{Float64,<:ConfigEnumerator} if K is Single and TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.\nWeighted constraint satisfaction problem is only supported if K is Single.\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsMin","page":"References","title":"GenericTensorNetworks.ConfigsMin","text":"ConfigsMin{K, BOUNDED, TREESTORAGE} <:AbstractProperty\nConfigsMin(K=Single; bounded=true, tree_storage=false)\n\nFind configurations with smallest-K sizes.\n\nThe corresponding data type is inverted CountingTropical{Float64,<:ConfigEnumerator} if K is Single and inverted TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.\nWeighted constraint satisfaction problem is only supported if K is Single.\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#Element-Algebras","page":"References","title":"Element Algebras","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"is_commutative_semiring","category":"page"},{"location":"ref/#GenericTensorNetworks.is_commutative_semiring","page":"References","title":"GenericTensorNetworks.is_commutative_semiring","text":"is_commutative_semiring(a::T, b::T, c::T) where T\n\nCheck if elements a, b and c satisfied the commutative semiring requirements.\n\nbeginalign*\n(a oplus b) oplus c = a oplus (b oplus c) hspace5emtrianglerighttextcommutative monoid oplus with identity mathbb0\na oplus mathbb0 = mathbb0 oplus a = a \na oplus b = b oplus a \n\n(a odot b) odot c = a odot (b odot c) hspace5emtriangleright textcommutative monoid odot with identity mathbb1\na odot mathbb1 = mathbb1 odot a = a \na odot b = b odot a \n\na odot (boplus c) = aodot b oplus aodot c hspace5emtriangleright textleft and right distributive\n(aoplus b) odot c = aodot c oplus bodot c \n\na odot mathbb0 = mathbb0 odot a = mathbb0\nendalign*\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"TropicalNumbers.Tropical\nTropicalNumbers.CountingTropical\nExtendedTropical\nGenericTensorNetworks.Mods.Mod\nTruncatedPoly\nMax2Poly\nConfigEnumerator\nSumProductTree\nConfigSampler","category":"page"},{"location":"ref/#TropicalNumbers.Tropical","page":"References","title":"TropicalNumbers.Tropical","text":"TropicalMaxPlus{T} = Tropical{T} <: AbstractSemiring\n\nTropicalMaxPlus is a semiring algebra, can be described by\n\nTropical (TropicalMaxPlus), (ℝ, max, +, -Inf, 0).\n\nIt maps\n\n+ to max in regular algebra,\n* to + in regular algebra,\n1 to 0 in regular algebra,\n0 to -Inf in regular algebra (for integer content types, this is chosen as a small integer).\n\nExample\n\njulia> TropicalMaxPlus(1.0) + TropicalMaxPlus(3.0)\n3.0ₜ\n\njulia> TropicalMaxPlus(1.0) * TropicalMaxPlus(3.0)\n4.0ₜ\n\njulia> one(TropicalMaxPlusF64)\n0.0ₜ\n\njulia> zero(TropicalMaxPlusF64)\n-Infₜ\n\n\n\n\n\n","category":"type"},{"location":"ref/#TropicalNumbers.CountingTropical","page":"References","title":"TropicalNumbers.CountingTropical","text":"CountingTropical{T,CT} <: Number\n\nCounting 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.\n\nExample\n\njulia> CountingTropical(1.0, 5.0) + CountingTropical(3.0, 2.0)\n(3.0, 2.0)ₜ\n\njulia> CountingTropical(1.0, 5.0) * CountingTropical(3.0, 2.0)\n(4.0, 10.0)ₜ\n\njulia> one(CountingTropicalF64)\n(0.0, 1.0)ₜ\n\njulia> zero(CountingTropicalF64)\n(-Inf, 0.0)ₜ\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ExtendedTropical","page":"References","title":"GenericTensorNetworks.ExtendedTropical","text":"ExtendedTropical{K,TO} <: Number\nExtendedTropical{K}(orders)\n\nExtended 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\n\n+ to finding largest K values of union of two sets.\n* to finding largest K values of sum combination of two sets.\n0 to set [-Inf, -Inf, ..., -Inf, -Inf]\n1 to set [-Inf, -Inf, ..., -Inf, 0]\n\nFields\n\norders is a vector of Tropical (CountingTropical) numbers as the largest-K solution sizes (solutions).\n\nExamples\n\njulia> x = ExtendedTropical{3}(Tropical.([1.0, 2, 3]))\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[1.0ₜ, 2.0ₜ, 3.0ₜ])\n\njulia> y = ExtendedTropical{3}(Tropical.([-Inf, 2, 5]))\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, 2.0ₜ, 5.0ₜ])\n\njulia> x * y\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[6.0ₜ, 7.0ₜ, 8.0ₜ])\n\njulia> x + y\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[2.0ₜ, 3.0ₜ, 5.0ₜ])\n\njulia> one(x)\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, 0.0ₜ])\n\njulia> zero(x)\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, -Infₜ])\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.Mods.Mod","page":"References","title":"GenericTensorNetworks.Mods.Mod","text":"Mod{m}(v) creates a modular number in mod m with value mod(v,m).\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.TruncatedPoly","page":"References","title":"GenericTensorNetworks.TruncatedPoly","text":"TruncatedPoly{K,T,TO} <: Number\nTruncatedPoly(coeffs::Tuple, maxorder)\n\nPolynomial truncated to largest K orders. T is the coefficients type and TO is the orders type.\n\nFields\n\ncoeffs is the largest-K coefficients of a polynomial. In GenericTensorNetworks, it can be the counting or enumeration of solutions.\nmaxorder is the order of a polynomial.\n\nExamples\n\njulia> TruncatedPoly((1,2,3), 6)\nx^4 + 2*x^5 + 3*x^6\n\njulia> TruncatedPoly((1,2,3), 6) * TruncatedPoly((5,2,1), 3)\n20*x^7 + 8*x^8 + 3*x^9\n\njulia> TruncatedPoly((1,2,3), 6) + TruncatedPoly((5,2,1), 3)\nx^4 + 2*x^5 + 3*x^6\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.Max2Poly","page":"References","title":"GenericTensorNetworks.Max2Poly","text":"Max2Poly{T,TO} = TruncatedPoly{2,T,TO}\nMax2Poly(a, b, maxorder)\n\nA shorthand of TruncatedPoly{2}.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigEnumerator","page":"References","title":"GenericTensorNetworks.ConfigEnumerator","text":"ConfigEnumerator{N,S,C} <: AbstractSetNumber\n\nSet 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`.\n\nFields\n\ndata is a vector of StaticElementVector as the solution set.\n\nExamples\n\njulia> a = ConfigEnumerator([StaticBitVector([1,1,1,0,0]), StaticBitVector([1,0,0,0,1])])\n{11100, 10001}\n\njulia> b = ConfigEnumerator([StaticBitVector([0,0,0,0,0]), StaticBitVector([1,0,1,0,1])])\n{00000, 10101}\n\njulia> a + b\n{11100, 10001, 00000, 10101}\n\njulia> one(a)\n{00000}\n\njulia> zero(a)\n{}\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SumProductTree","page":"References","title":"GenericTensorNetworks.SumProductTree","text":"SumProductTree{ET} <: AbstractSetNumber\n\nConfiguration 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.\n\nFields\n\ntag is one of ZERO, ONE, LEAF, SUM, PROD.\ndata is the element stored in a LEAF node.\nleft and right are two operands of a SUM or PROD node.\n\nExamples\n\njulia> s = SumProductTree(bv\"00111\")\n00111\n\n\njulia> q = SumProductTree(bv\"10000\")\n10000\n\n\njulia> x = s + q\n+ (count = 2.0)\n├─ 00111\n└─ 10000\n\n\njulia> y = x * x\n* (count = 4.0)\n├─ + (count = 2.0)\n│ ├─ 00111\n│ └─ 10000\n└─ + (count = 2.0)\n ├─ 00111\n └─ 10000\n\n\njulia> collect(y)\n4-element Vector{StaticBitVector{5, 1}}:\n 00111\n 10111\n 10111\n 10000\n\njulia> zero(s)\n∅\n\n\n\njulia> one(s)\n00000\n\n\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigSampler","page":"References","title":"GenericTensorNetworks.ConfigSampler","text":"ConfigSampler{N,S,C} <: AbstractSetNumber\nConfigSampler(elements::StaticElementVector)\n\nThe 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`.\n\nnote: Note\nConfigSampler is a probabilistic commutative semiring, adding two config samplers do not give you deterministic results.\n\nFields\n\ndata is a StaticElementVector as the sampled solution.\n\nExamples\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0]))\nConfigSampler{5, 1, 1}(11100)\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0])) + ConfigSampler(StaticBitVector([1,0,1,0,0]))\nConfigSampler{5, 1, 1}(10100)\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0])) * ConfigSampler(StaticBitVector([0,0,0,0,1]))\nConfigSampler{5, 1, 1}(11101)\n\njulia> one(ConfigSampler{5, 1, 1})\nConfigSampler{5, 1, 1}(00000)\n\njulia> zero(ConfigSampler{5, 1, 1})\nConfigSampler{5, 1, 1}(11111)\n\n\n\n\n\n","category":"type"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks also exports the Polynomial and LaurentPolynomial types defined in package Polynomials.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"For reading the properties from the above element types, one can use the following functions.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"read_size\nread_count\nread_config\nread_size_count\nread_size_config","category":"page"},{"location":"ref/#GenericTensorNetworks.read_size","page":"References","title":"GenericTensorNetworks.read_size","text":"read_size(x)\n\nRead the size information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_count","page":"References","title":"GenericTensorNetworks.read_count","text":"read_count(x)\n\nRead the counting information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_config","page":"References","title":"GenericTensorNetworks.read_config","text":"read_config(x; keeptree=false)\n\nRead the configuration information from the generic element, if keeptree=true, the tree structure will not be flattened.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_size_count","page":"References","title":"GenericTensorNetworks.read_size_count","text":"read_size_count(x)\n\nRead the size and counting information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_size_config","page":"References","title":"GenericTensorNetworks.read_size_config","text":"read_size_config(x; keeptree=false)\n\nRead the size and configuration information from the generic element. If keeptree=true, the tree structure will not be flattened.\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"The following functions are for saving and loading configurations.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"StaticBitVector\nStaticElementVector\nOnehotVec\nsave_configs\nload_configs\nsave_sumproduct\nload_sumproduct\n@bv_str\nonehotv\n\ngenerate_samples\nhamming_distribution","category":"page"},{"location":"ref/#ProblemReductions.StaticBitVector","page":"References","title":"ProblemReductions.StaticBitVector","text":"StaticBitVector{N,C} = StaticElementVector{N,1,C}\nStaticBitVector(x::AbstractVector)\n\nExamples\n\njulia> sb = StaticBitVector([1,0,0,1,1])\n10011\n\njulia> sb[3]\n0x0000000000000000\n\njulia> collect(Int, sb)\n5-element Vector{Int64}:\n 1\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.StaticElementVector","page":"References","title":"ProblemReductions.StaticElementVector","text":"StaticElementVector{N,S,C}\nStaticElementVector(nflavor::Int, x::AbstractVector)\n\nN 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.\n\nFields\n\ndata is a tuple of UInt64 for storing the configuration of static elements.\n\nExamples\n\njulia> ev = StaticElementVector(3, [1,2,0,1,2])\n12012\n\njulia> ev[2]\n0x0000000000000002\n\njulia> collect(Int, ev)\n5-element Vector{Int64}:\n 1\n 2\n 0\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.OnehotVec","page":"References","title":"GenericTensorNetworks.OnehotVec","text":"OnehotVec{N,NF}\nOnehotVec{N,NF}(loc, val)\n\nOnehot vector type, N is the number of vector length, NF is the number of flavors.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.save_configs","page":"References","title":"GenericTensorNetworks.save_configs","text":"save_configs(filename, data::ConfigEnumerator; format=:binary)\n\nSave configurations data to file filename. The format is :binary or :text.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.load_configs","page":"References","title":"GenericTensorNetworks.load_configs","text":"load_configs(filename; format=:binary, bitlength=nothing, num_flavors=2)\n\nLoad 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.save_sumproduct","page":"References","title":"GenericTensorNetworks.save_sumproduct","text":"save_sumproduct(filename, t::SumProductTree)\n\nSerialize a sum-product tree into a file.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.load_sumproduct","page":"References","title":"GenericTensorNetworks.load_sumproduct","text":"load_sumproduct(filename)\n\nDeserialize a sum-product tree from a file.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.@bv_str","page":"References","title":"ProblemReductions.@bv_str","text":"Constructing a static bit vector.\n\n\n\n\n\n","category":"macro"},{"location":"ref/#ProblemReductions.onehotv","page":"References","title":"ProblemReductions.onehotv","text":"onehotv(::Type{<:StaticElementVector}, i, v)\nonehotv(::Type{<:StaticBitVector}, i)\n\nReturns a static element vector, with the value at location i being v (1 if not specified).\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.generate_samples","page":"References","title":"GenericTensorNetworks.generate_samples","text":"generate_samples(t::SumProductTree, nsamples::Int)\n\nDirect sampling configurations from a SumProductTree instance.\n\nExamples\n\njulia> using Graphs\n\njulia> g= smallgraph(:petersen)\n{10, 15} undirected simple Int64 graph\n\njulia> t = solve(GenericTensorNetwork(IndependentSet(g)), ConfigsAll(; tree_storage=true))[];\n\njulia> samples = generate_samples(t, 1000);\n\njulia> all(s->is_independent_set(g, s), samples)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.hamming_distribution","page":"References","title":"GenericTensorNetworks.hamming_distribution","text":"hamming_distribution(S, T)\n\nCompute the distribution of pair-wise Hamming distances, which is defined as:\n\nc(k) = sum_sigmain S tauin T delta(rm dist(sigma tau) k)\n\nwhere delta is a function that returns 1 if two arguments are equivalent, 0 otherwise, rm dist is the Hamming distance function.\n\nReturns the counting as a vector.\n\n\n\n\n\n","category":"function"},{"location":"ref/#Tensor-Network","page":"References","title":"Tensor Network","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"optimize_code\ngetixsv\ngetiyv\ncontraction_complexity\nestimate_memory\n@ein_str\nGreedyMethod\nTreeSA\nSABipartite\nKaHyParBipartite\nMergeVectors\nMergeGreedy","category":"page"},{"location":"ref/#OMEinsumContractionOrders.optimize_code","page":"References","title":"OMEinsumContractionOrders.optimize_code","text":"optimize_code(eincode, size_dict, optimizer = GreedyMethod(), simplifier=nothing, permute=true) -> optimized_eincode\n\nOptimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum instance. Input arguments are\n\neincode is an einsum contraction code instance, one of DynamicEinCode, StaticEinCode or NestedEinsum.\nsize is a dictionary of \"edge label=>edge size\" that contains the size information, one can use uniformsize(eincode, 2) to create a uniform size.\noptimizer is a CodeOptimizer instance, should be one of GreedyMethod, ExactTreewidth, KaHyParBipartite, SABipartite or TreeSA. Check their docstrings for details.\nsimplifier is one of MergeVectors or MergeGreedy.\noptimize the permutation if permute is true.\n\nExamples\n\njulia> using OMEinsum\n\njulia> code = ein\"ij, jk, kl, il->\"\nij, jk, kl, il -> \n\njulia> optimize_code(code, uniformsize(code, 2), TreeSA())\nSlicedEinsum{Char, NestedEinsum{DynamicEinCode{Char}}}(Char[], ki, ki -> \n├─ jk, ij -> ki\n│ ├─ jk\n│ └─ ij\n└─ kl, il -> ki\n ├─ kl\n └─ il\n)\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.getixsv","page":"References","title":"OMEinsum.getixsv","text":"getixsv(code)\n\nGet labels of input tensors for EinCode, NestedEinsum and some other einsum like objects. Returns a vector of vectors.\n\njulia> getixsv(ein\"(ij,jk),k->i\")\n3-element Vector{Vector{Char}}:\n ['i', 'j']\n ['j', 'k']\n ['k']\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.getiyv","page":"References","title":"OMEinsum.getiyv","text":"getiy(code)\n\nGet labels of the output tensor for EinCode, NestedEinsum and some other einsum like objects. Returns a vector.\n\njulia> getiyv(ein\"(ij,jk),k->i\")\n1-element Vector{Char}:\n 'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsumContractionOrders.contraction_complexity","page":"References","title":"OMEinsumContractionOrders.contraction_complexity","text":"contraction_complexity(eincode, size_dict) -> ContractionComplexity\n\nReturns the time, space and read-write complexity of the einsum contraction. The returned object contains 3 fields:\n\ntime complexity tc defined as log2(number of element-wise multiplications).\nspace complexity sc defined as log2(size of the maximum intermediate tensor).\nread-write complexity rwc defined as log2(the number of read-write operations).\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.estimate_memory","page":"References","title":"GenericTensorNetworks.estimate_memory","text":"estimate_memory(\n problem::GenericTensorNetwork,\n property::GenericTensorNetworks.AbstractProperty;\n T\n) -> Any\n\n\nMemory estimation in number of bytes to compute certain property of a problem. T is the base type.\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.@ein_str","page":"References","title":"OMEinsum.@ein_str","text":"ein\"ij,jk -> ik\"(A,B)\n\nString 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 α-ω.\n\nexample\n\njulia> a, b, c = rand(10,10), rand(10,10), rand(10,1);\n\njulia> ein\"ij,jk,kl -> il\"(a,b,c) ≈ ein\"(ij,jk),kl -> il\"(a,b,c) ≈ a * b * c\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"ref/#OMEinsumContractionOrders.GreedyMethod","page":"References","title":"OMEinsumContractionOrders.GreedyMethod","text":"GreedyMethod{MT}\nGreedyMethod(; α = 0.0, temperature = 0.0, nrepeat=10)\n\nThe fast but poor greedy optimizer. Input arguments are\n\n* `α` is the parameter for the loss function, for pairwise interaction, L = size(out) - α * (size(in1) + size(in2))\n* `temperature` is 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).\n* `nrepeat` is the number of repeatition, returns the best contraction order.\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.TreeSA","page":"References","title":"OMEinsumContractionOrders.TreeSA","text":"TreeSA{RT,IT,GM}\nTreeSA(; sc_target=20, βs=collect(0.01:0.05:15), ntrials=10, niters=50,\n sc_weight=1.0, rw_weight=0.2, initializer=:greedy, greedy_config=GreedyMethod(; nrepeat=1))\n\nOptimize the einsum contraction pattern using the simulated annealing on tensor expression tree.\n\nsc_target is the target space complexity,\nntrials, βs and niters are annealing parameters, doing ntrials indepedent annealings, each has inverse tempteratures specified by βs, in each temperature, do niters updates of the tree.\nsc_weight is the relative importance factor of space complexity in the loss compared with the time complexity.\nrw_weight is the relative importance factor of memory read and write in the loss compared with the time complexity.\ninitializer specifies how to determine the initial configuration, it can be :greedy or :random. If it is using :greedy method to generate the initial configuration, it also uses two extra arguments greedy_method and greedy_nrepeat.\nnslices is the number of sliced legs, default is 0.\nfixed_slices is a vector of sliced legs, default is [].\n\nReferences\n\nRecursive Multi-Tensor Contraction for XEB Verification of Quantum Circuits\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.SABipartite","page":"References","title":"OMEinsumContractionOrders.SABipartite","text":"SABipartite{RT,BT}\nSABipartite(; sc_target=25, ntrials=50, βs=0.1:0.2:15.0, niters=1000\n max_group_size=40, greedy_config=GreedyMethod(), initializer=:random)\n\nOptimize 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\n\nsize_dict, a dictionary that specifies leg dimensions,\nsc_target is the target space complexity, defined as log2(number of elements in the largest tensor),\nmax_group_size is the maximum size that allowed to used greedy search,\nβs is a list of inverse temperature 1/T,\nniters is the number of iteration in each temperature,\nntrials is the number of repetition (with different random seeds),\nsub_optimizer, the optimizer for the bipartited sub graphs, one can choose GreedyMethod() or TreeSA(),\ninitializer, the partition configuration initializer, one can choose :random or :greedy (slow but better).\n\nReferences\n\nHyper-optimized tensor network contraction\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.KaHyParBipartite","page":"References","title":"OMEinsumContractionOrders.KaHyParBipartite","text":"KaHyParBipartite{RT,IT,GM}\nKaHyParBipartite(; sc_target, imbalances=collect(0.0:0.005:0.8),\n max_group_size=40, greedy_config=GreedyMethod())\n\nOptimize 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\n\nsc_target is the target space complexity, defined as log2(number of elements in the largest tensor),\nimbalances is a KaHyPar parameter that controls the group sizes in hierarchical bipartition,\nmax_group_size is the maximum size that allowed to used greedy search,\ngreedy_config is a greedy optimizer.\n\nReferences\n\nHyper-optimized tensor network contraction\nSimulating the Sycamore quantum supremacy circuits\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.MergeVectors","page":"References","title":"OMEinsumContractionOrders.MergeVectors","text":"MergeVectors <: CodeSimplifier\nMergeVectors()\n\nContraction code simplifier (in order to reduce the time of calling optimizers) that merges vectors to closest tensors.\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.MergeGreedy","page":"References","title":"OMEinsumContractionOrders.MergeGreedy","text":"MergeGreedy <: CodeSimplifier\nMergeGreedy(; threshhold=-1e-12)\n\nContraction 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).\n\n\n\n\n\n","category":"type"},{"location":"ref/#Others","page":"References","title":"Others","text":"","category":"section"},{"location":"ref/#Graph","page":"References","title":"Graph","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"Except the SimpleGraph defined in Graphs, GenericTensorNetworks also defines the following types and functions.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"HyperGraph\nUnitDiskGraph\n\nshow_graph\nshow_configs\nshow_einsum\nshow_landscape\nGraphDisplayConfig\nAbstractLayout\nSpringLayout\nStressLayout\nSpectralLayout\nLayered\nLayeredSpringLayout\nLayeredStressLayout\nrender_locs\n\ndiagonal_coupled_graph\nsquare_lattice_graph\nline_graph\n\nrandom_diagonal_coupled_graph\nrandom_square_lattice_graph","category":"page"},{"location":"ref/#ProblemReductions.HyperGraph","page":"References","title":"ProblemReductions.HyperGraph","text":"struct HyperGraph <: Graphs.AbstractGraph{Int64}\n\nA hypergraph is a generalization of a graph in which an edge can connect any number of vertices.\n\nFields\n\nn::Int: the number of vertices\nedges::Vector{Vector{Int}}: a vector of vectors of integers, where each vector represents a hyperedge connecting the vertices with the corresponding indices.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.UnitDiskGraph","page":"References","title":"ProblemReductions.UnitDiskGraph","text":"struct UnitDiskGraph{D, T} <: Graphs.AbstractGraph{Int64}\n\nA 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.\n\nFields\n\nlocations::Vector{NTuple{D, T}}: the locations of the vertices\nradius::Float64: the radius of the unit disk\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.show_graph","page":"References","title":"LuxorGraphPlot.show_graph","text":"show_graph([f, ]graph::AbstractGraph;\n kwargs...\n )\n\nShow a graph in VSCode, Pluto or Jupyter notebook, or save it to a file.\n\nPositional arguments\n\nf is a function that returns extra Luxor plotting statements.\ngraph is a graph instance.\nlocs is a vector of tuples for specifying the vertex locations, or a AbstractLayout instance.\n\nKeyword arguments\n\nconfig is a GraphDisplayConfig instance.\nvertex_colors is a vector of color strings for specifying vertex fill colors.\nvertex_sizes is a vector of real numbers for specifying vertex sizes.\nvertex_shapes is a vector of strings for specifying vertex shapes, the string should be \"circle\" or \"box\".\nvertex_stroke_colors is a vector of color strings for specifying vertex stroke colors.\nvertex_text_colors is a vector of color strings for specifying vertex text colors.\nedge_colors is a vector of color strings for specifying edge colors.\ntexts is a vector of strings for labeling vertices.\n\npadding_left::Int = 10, the padding on the left side of the drawing\npadding_right::Int = 10, the padding on the right side of the drawing\npadding_top::Int = 10, the padding on the top side of the drawing\npadding_bottom::Int = 10, the padding on the bottom side of the drawing\nformat is the output format, which can be :svg, :png or :pdf.\nfilename is a string as the output filename.\n\nExample\n\njulia> using Graphs, LuxorGraphPlot\n\njulia> show_graph(smallgraph(:petersen); format=:png, vertex_colors=rand([\"blue\", \"red\"], 10));\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_configs","page":"References","title":"GenericTensorNetworks.show_configs","text":"show_configs(gp::ConstraintSatisfactionProblem, locs, configs::AbstractMatrix; kwargs...)\nshow_configs(graph::SimpleGraph, locs, configs::AbstractMatrix; num_flavors=2, kwargs...)\n\nShow a gallery of configurations on a graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_einsum","page":"References","title":"GenericTensorNetworks.show_einsum","text":"show_einsum(ein::AbstractEinsum;\n tensor_locs=nothing,\n label_locs=nothing, # dict\n spring::Bool=true,\n optimal_distance=25.0,\n\n tensor_size=15,\n tensor_color=\"black\",\n tensor_text_color=\"white\",\n annotate_tensors=false,\n\n label_size=7,\n label_color=\"black\",\n open_label_color=\"black\",\n annotate_labels=true,\n kwargs...\n )\n\nPositional arguments\n\nein is an Einsum contraction code (provided by package OMEinsum).\n\nKeyword arguments\n\nlocs is a tuple of tensor_locs (vector) and label_locs (dict).\nspring is switch to use spring method to optimize the location.\noptimal_distance is a optimal distance parameter for spring optimizer.\ntensor_color is a string to specify the color of tensor nodes.\ntensor_size is a real number to specify the size of tensor nodes.\ntensor_text_color is a color strings to specify tensor text color.\nannotate_tensors is a boolean switch for annotate different tensors by integers.\nlabel_size is a real number to specify label text node size.\nlabel_color is a color strings to specify label text color.\nopen_label_color is a color strings to specify open label text color.\nannotate_labels is a boolean switch for annotate different labels.\nformat is the output format, which can be :svg, :png or :pdf.\nfilename is a string as the output filename.\n\nfontsize::Float64 = 12.0, the font size\nfontface::String = \"\", the font face, leave empty to follow system\nvertex_text_color = \"black\", the default text color\nvertex_stroke_color = \"black\", the default stroke color for vertices\nvertex_color = \"transparent\", the default default fill color for vertices\nvertex_size::Float64 = 10.0, the default vertex size\nvertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot\nvertex_line_width::Float64 = 1, the default vertex stroke line width\nvertex_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\"]\nedge_color = \"black\", the default edge color\nedge_line_width::Float64 = 1, the default line width\nedge_style::String = \"solid\", the line style of edges, which can be one of [\"solid\", \"dotted\", \"dot\", \"dotdashed\", \"longdashed\", \"shortdashed\", \"dash\", \"dashed\", \"dotdotdashed\", \"dotdotdotdashed\"]\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_landscape","page":"References","title":"GenericTensorNetworks.show_landscape","text":"show_landscape(is_neighbor, configurations::TruncatedPoly;\n layer_distance=200,\n config=GraphDisplayConfig(; edge_color=\"gray\", vertex_stroke_color=\"transparent\", vertex_size=5),\n layout_method=:spring,\n optimal_distance=30.0,\n colors=fill(\"green\", K),\n kwargs...)\n\nShow the energy landscape of configurations.\n\nArguments\n\nis_neighbor: a function to determine if two configurations are neighbors.\nconfigurations: a TruncatedPoly object, which is the default output of the solve function with ConfigsMax property as the argument.\n\nKeyword arguments\n\nlayer_distance: the distance between layers.\nconfig: a LuxorGraphPlot.GraphDisplayConfig object.\nlayout_method: the layout method, either :spring, :stress or :spectral\noptimal_distance: the optimal distance for the layout.\ncolors: a vector of colors for each layer.\nkwargs...: other keyword arguments passed to show_graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.GraphDisplayConfig","page":"References","title":"LuxorGraphPlot.GraphDisplayConfig","text":"GraphDisplayConfig\n\nThe configuration for graph display.\n\nKeyword arguments\n\nlocs is a vector of tuples for specifying the vertex locations.\nedges is a vector of tuples for specifying the edges.\nfontsize::Float64 = 12.0, the font size\nfontface::String = \"\", the font face, leave empty to follow system\nvertex_text_color = \"black\", the default text color\nvertex_stroke_color = \"black\", the default stroke color for vertices\nvertex_color = \"transparent\", the default default fill color for vertices\nvertex_size::Float64 = 10.0, the default vertex size\nvertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot\nvertex_line_width::Float64 = 1, the default vertex stroke line width\nvertex_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\"]\nedge_color = \"black\", the default edge color\nedge_line_width::Float64 = 1, the default line width\nedge_style::String = \"solid\", the line style of edges, which can be one of [\"solid\", \"dotted\", \"dot\", \"dotdashed\", \"longdashed\", \"shortdashed\", \"dash\", \"dashed\", \"dotdotdashed\", \"dotdotdotdashed\"]\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.AbstractLayout","page":"References","title":"LuxorGraphPlot.Layouts.AbstractLayout","text":"AbstractLayout\n\nAbstract type for layout algorithms.\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.SpringLayout","page":"References","title":"LuxorGraphPlot.Layouts.SpringLayout","text":"SpringLayout <: AbstractLayout\n\nA layout algorithm based on a spring model.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\nmaxiter::Int: the maximum number of iterations\nα0::Float64: the initial moving speed\nmeta::Dict{Symbol, Any}: graph dependent meta information, including\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.StressLayout","page":"References","title":"LuxorGraphPlot.Layouts.StressLayout","text":"StressLayout <: AbstractLayout\n\nA layout algorithm based on stress majorization.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\nmaxiter::Int: the maximum number of iterations\nrtol::Float64: the absolute tolerance\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\nmeta::Dict{Symbol, Any}: graph dependent meta information, including\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.SpectralLayout","page":"References","title":"LuxorGraphPlot.Layouts.SpectralLayout","text":"SpectralLayout <: AbstractLayout\n\nA layout algorithm based on spectral graph theory.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\ndimension::Int: the number of dimensions\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.Layered","page":"References","title":"LuxorGraphPlot.Layouts.Layered","text":"Layered <: AbstractLayout\n\nLayered version of a parent layout algorithm.\n\nFields\n\nparent::LT: the parent layout algorithm\nzlocs::Vector{T}: the z-axis locations\naspect_ratio::Float64: the aspect ratio of the z-axis\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.LayeredSpringLayout","page":"References","title":"LuxorGraphPlot.Layouts.LayeredSpringLayout","text":"LayeredSpringLayout(; zlocs, optimal_distance, aspect_ration=0.2)\n\nCreate a layered spring layout.\n\nKeyword Arguments\n\nzlocs: the z-axis locations\noptimal_distance::Float64: the optimal distance between vertices\naspect_ration::Float64: the aspect ratio of the z-axis\nα0::Float64: the initial moving speed\nmaxiter::Int: the maximum number of iterations\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.Layouts.LayeredStressLayout","page":"References","title":"LuxorGraphPlot.Layouts.LayeredStressLayout","text":"LayeredStressLayout(; zlocs, optimal_distance, aspect_ration=0.2)\n\nCreate a layered stress layout.\n\nKeyword Arguments\n\nzlocs: the z-axis locations\noptimal_distance::Float64: the optimal distance between vertices\naspect_ration::Float64: the aspect ratio of the z-axis\nmaxiter::Int: the maximum number of iterations\nrtol::Float64: the absolute tolerance\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.Layouts.render_locs","page":"References","title":"LuxorGraphPlot.Layouts.render_locs","text":"render_locs(graph, layout::Layout)\n\nRender the vertex locations for a graph from an AbstractLayout instance.\n\nArguments\n\ngraph::AbstractGraph: the graph to render\nlayout::AbstractLayout: the layout algorithm\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.diagonal_coupled_graph","page":"References","title":"GenericTensorNetworks.diagonal_coupled_graph","text":"diagonal_coupled_graph(mask::AbstractMatrix{Bool})\n\nCreate a masked diagonal coupled square lattice graph from a specified mask.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.square_lattice_graph","page":"References","title":"GenericTensorNetworks.square_lattice_graph","text":"square_lattice_graph(mask::AbstractMatrix{Bool})\n\nCreate a masked square lattice graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.line_graph","page":"References","title":"GenericTensorNetworks.line_graph","text":"line_graph(g::SimpleGraph)\n\nReturns 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.random_diagonal_coupled_graph","page":"References","title":"GenericTensorNetworks.random_diagonal_coupled_graph","text":"random_diagonal_coupled_graph(m::Int, n::Int, ρ::Real)\n\nCreate a mtimes n random masked diagonal coupled square lattice graph, with number of vertices equal to lfloor m times ntimes rho rceil.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.random_square_lattice_graph","page":"References","title":"GenericTensorNetworks.random_square_lattice_graph","text":"random_square_lattice_graph(m::Int, n::Int, ρ::Real)\n\nCreate a random masked square lattice graph, with number of vertices fixed to lfloor mnrho rceil.\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"One can also use random_regular_graph and smallgraph in Graphs to build special graphs.","category":"page"},{"location":"ref/#Multiprocessing","page":"References","title":"Multiprocessing","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","category":"page"},{"location":"ref/#GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","page":"References","title":"GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","text":"multiprocess_run(func, inputs::AbstractVector)\n\nExecute function func on inputs with multiple processing.\n\nExample\n\nSuppose we have a file run.jl with the following contents\n\nusing GenericTensorNetworks.SimpleMultiprocessing\n\nresults = multiprocess_run(x->x^2, randn(8))\n\nIn an terminal, you may run the script with 4 processes by typing\n\n$ julia -p4 run.jl\n From worker 2:\t[ Info: running argument -0.17544008350172655 on device 2\n From worker 5:\t[ Info: running argument 0.34578117779452555 on device 5\n From worker 3:\t[ Info: running argument 2.0312551239727705 on device 3\n From worker 4:\t[ Info: running argument -0.7319353419291961 on device 4\n From worker 2:\t[ Info: running argument 0.013132180639054629 on device 2\n From worker 3:\t[ Info: running argument 0.9960101782201602 on device 3\n From worker 4:\t[ Info: running argument -0.5613942832743966 on device 4\n From worker 5:\t[ Info: running argument 0.39460402723831134 on device 5\n\n\n\n\n\n","category":"function"},{"location":"","page":"Home","title":"Home","text":"CurrentModule = GenericTensorNetworks","category":"page"},{"location":"#GenericTensorNetworks","page":"Home","title":"GenericTensorNetworks","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package implements generic tensor networks to compute solution space properties of a class of hard combinatorial problems. The solution space properties include","category":"page"},{"location":"","page":"Home","title":"Home","text":"The maximum/minimum solution sizes,\nThe number of solutions at certain sizes,\nThe enumeration of solutions at certain sizes.\nThe direct sampling of solutions at certain sizes.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The solvable problems include Independent set problem, Maximal independent set problem, Spin-glass problem, Cutting problem, Vertex matching problem, Binary paint shop problem, Coloring problem, Dominating set problem, Satisfiability problem, Set packing problem and Set covering problem.","category":"page"},{"location":"#Background-knowledge","page":"Home","title":"Background knowledge","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Please check our paper \"Computing properties of independent sets by generic programming tensor networks\". If you find our paper or software useful in your work, we would be grateful if you could cite our work. The CITATION.bib file in the root of this repository lists the relevant papers.","category":"page"},{"location":"#Quick-start","page":"Home","title":"Quick start","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"You can find a set up guide in our README. To get started, open a Julia REPL and type the following code.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using GenericTensorNetworks, Graphs#, CUDA\nsolve(\n GenericTensorNetwork(IndependentSet(\n Graphs.random_regular_graph(20, 3),\n UnitWeight(20)); # default: uniform weight 1\n optimizer = TreeSA(),\n openvertices = (), # default: no open vertices\n fixedvertices = Dict() # default: no fixed vertices\n ),\n GraphPolynomial();\n usecuda=false # the default value\n )","category":"page"},{"location":"","page":"Home","title":"Home","text":"Here the main function solve takes three input arguments, the problem instance of type IndependentSet, the property instance of type GraphPolynomial and an optional key word argument usecuda to decide use GPU or not. If one wants to use GPU to accelerate the computation, the , CUDA should be uncommented.","category":"page"},{"location":"","page":"Home","title":"Home","text":"An IndependentSet instance takes two positional arguments to initialize, the graph instance that one wants to solve and the weights for each vertex. Here, we use a random regular graph with 20 vertices and degree 3, and the default uniform weight 1.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The GenericTensorNetwork function is a constructor for the problem instance, which takes the problem instance as the first argument and optional key word arguments. The key word argument optimizer is for specifying the tensor network optimization algorithm. The keyword argument openvertices is a tuple of labels for specifying the degrees of freedom not summed over, and fixedvertices is a label-value dictionary for specifying the fixed values of the degree of freedoms. Here, we use TreeSA method as the tensor network optimizer, and leave openvertices the default values. The TreeSA method finds the best contraction order in most of our applications, while the default GreedyMethod runs the fastest.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The first execution of this function will be a bit slow due to Julia's just in time compiling. The subsequent runs will be fast. The following diagram lists possible combinations of input arguments, where functions in the Graph are mainly defined in the package Graphs, and the rest can be found in this package.","category":"page"},{"location":"","page":"Home","title":"Home","text":"
\n\n
","category":"page"},{"location":"","page":"Home","title":"Home","text":"⠀ You can find many examples in this documentation, a good one to start with is Independent set problem.","category":"page"}] +[{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"EditURL = \"../../../examples/IndependentSet.jl\"","category":"page"},{"location":"generated/IndependentSet/#Independent-set-problem","page":"Independent set problem","title":"Independent set problem","text":"","category":"section"},{"location":"generated/IndependentSet/#Problem-definition","page":"Independent set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"In graph theory, an independent set is a set of vertices in a graph, no two of which are adjacent.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"In the following, we are going to solve the solution space properties of the independent set problem on the Petersen graph. To start, let us define a Petersen graph instance.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can visualize this graph using the show_graph function","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"# set the vertex locations manually instead of using the default spring layout\nrot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The graphical display is available in the following editors","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"a VSCode editor,\na Jupyter notebook,\nor a Pluto notebook,","category":"page"},{"location":"generated/IndependentSet/#Generic-tensor-network-representation","page":"Independent set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The independent set problem can be constructed with IndependentSet type as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"iset = IndependentSet(graph)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The tensor network representation of the independent set problem can be obtained by","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"problem = GenericTensorNetwork(iset; optimizer=TreeSA())","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Here, the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA. The resulting contraction order optimized tensor network is contained in the code field of problem.","category":"page"},{"location":"generated/IndependentSet/#Theory-(can-skip)","page":"Independent set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Let G=(V E) be a graph with each vertex vin V associated with a weight w_v. To reduce the independent set problem on it to a tensor network contraction, we first map a vertex vin V to a label s_v in 0 1 of dimension 2, where we use 0 (1) to denote a vertex absent (present) in the set. For each vertex v, we defined a parameterized rank-one tensor indexed by s_v as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"W(x_v^w_v) = left(beginmatrix\n 1 \n x_v^w_v\n endmatrixright)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where x_v is a variable associated with v. Similarly, for each edge (u v) in E, we define a matrix B indexed by s_u and s_v as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"B = left(beginmatrix\n1 1\n1 0\nendmatrixright)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Ideally, an optimal contraction order has a space complexity 2^rm tw(G), where rm tw(G) is the tree-width of G (or graph in the code). We can check the time, space and read-write complexities by typing","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"For more information about how to improve the contraction order, please check the Performance Tips.","category":"page"},{"location":"generated/IndependentSet/#Solution-space-properties","page":"Independent set problem","title":"Solution space properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Maximum-independent-set-size-\\alpha(G)","page":"Independent set problem","title":"Maximum independent set size alpha(G)","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can compute solution space properties with the solve function, which takes two positional arguments, the problem instance and the wanted property.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"maximum_independent_set_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Here SizeMax means finding the solution with maximum set size. The return value has Tropical type. We can get its content by typing","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size(maximum_independent_set_size)","category":"page"},{"location":"generated/IndependentSet/#Counting-properties","page":"Independent set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Count-all-solutions-and-best-several-solutions","page":"Independent set problem","title":"Count all solutions and best several solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count all independent sets with the CountingAll property.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_all_independent_sets = solve(problem, CountingAll())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type Float64. The counting of all independent sets is equivalent to the infinite temperature partition function","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"solve(problem, PartitionFunction(0.0))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count the maximum independent sets with CountingMax.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_maximum_independent_sets = solve(problem, CountingMax())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical, which contains two fields. They are n being the maximum independent set size and c being the number of the maximum independent sets.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(count_maximum_independent_sets)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"Similarly, we can count independent sets of sizes alpha(G) and alpha(G)-1 by feeding an integer positional argument to CountingMax.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"count_max2_independent_sets = solve(problem, CountingMax(2))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type TruncatedPoly, which contains two fields. They are maxorder being the maximum independent set size and coeffs being the number of independent sets having sizes alpha(G)-1 and alpha(G).","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(count_max2_independent_sets)","category":"page"},{"location":"generated/IndependentSet/#Find-the-graph-polynomial","page":"Independent set problem","title":"Find the graph polynomial","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can count the number of independent sets at any size, which is equivalent to finding the coefficients of an independence polynomial that defined as","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"I(G x) = sum_k=0^alpha(G) a_k x^k","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"where alpha(G) is the maximum independent set size, a_k is the number of independent sets of size k. The total number of independent sets is thus equal to I(G 1). There are 3 methods to compute a graph polynomial, :finitefield, :fft and :polynomial. These methods are introduced in the docstring of GraphPolynomial.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"independence_polynomial = solve(problem, GraphPolynomial(; method=:finitefield))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return type is Polynomial.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"read_size_count(independence_polynomial)","category":"page"},{"location":"generated/IndependentSet/#Configuration-properties","page":"Independent set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/IndependentSet/#Find-one-best-solution","page":"Independent set problem","title":"Find one best solution","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use the bounded or unbounded SingleConfigMax to find one of the solutions with largest size. The unbounded (default) version uses a joint type of CountingTropical and ConfigSampler in computation, where CountingTropical finds the maximum size and ConfigSampler samples one of the best solutions. The bounded version uses the binary gradient back-propagation (see our paper) to compute the gradients. It requires caching intermediate states, but is often faster (on CPU) because it can use TropicalGEMM (see Performance Tips).","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"max_config = solve(problem, SingleConfigMax(; bounded=false))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical with its counting field having ConfigSampler type. The data field of ConfigSampler is a bit string that corresponds to the solution","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"single_solution = read_config(max_config)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"This bit string should be read from left to right, with the i-th bit being 1 (0) to indicate the i-th vertex is present (absent) in the set. We can visualize this MIS with the following function.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"show_graph(graph, locations; format=:svg, vertex_colors=\n [iszero(single_solution[i]) ? \"white\" : \"red\" for i=1:nv(graph)])","category":"page"},{"location":"generated/IndependentSet/#Enumerate-all-solutions-and-best-several-solutions","page":"Independent set problem","title":"Enumerate all solutions and best several solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use bounded or unbounded ConfigsMax to find all solutions with largest-K set sizes. In most cases, the bounded (default) version is preferred because it can reduce the memory usage significantly.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_max_configs = solve(problem, ConfigsMax(; bounded=true))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type CountingTropical, while its counting field having type ConfigEnumerator. The data field of a ConfigEnumerator instance contains a vector of bit strings.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"_, configs_vector = read_size_config(all_max_configs)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"These solutions can be visualized with the show_configs function.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"show_configs(graph, locations, reshape(configs_vector, 1, :); padding_left=20)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use ConfigsAll to enumerate all sets satisfying the independence constraint.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_independent_sets = solve(problem, ConfigsAll())[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has type ConfigEnumerator.","category":"page"},{"location":"generated/IndependentSet/#Sample-solutions","page":"Independent set problem","title":"Sample solutions","text":"","category":"section"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"It is often difficult to store all configurations in a vector. A more clever way to store the data is using the sum product tree format.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"The return value has the SumProductTree type. Its length corresponds to the number of configurations.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"length(all_independent_sets_tree)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"We can use Base.collect function to create a ConfigEnumerator or use generate_samples to generate samples from it.","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"collect(all_independent_sets_tree)\n\ngenerate_samples(all_independent_sets_tree, 10)","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"","category":"page"},{"location":"generated/IndependentSet/","page":"Independent set problem","title":"Independent set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"EditURL = \"../../../examples/PaintShop.jl\"","category":"page"},{"location":"generated/PaintShop/#Binary-paint-shop-problem","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/PaintShop/#Problem-Definition","page":"Binary paint shop problem","title":"Problem Definition","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"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.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"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.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"using GenericTensorNetworks, Graphs, GenericTensorNetworks.ProblemReductions\n\nsequence = collect(\"iadgbeadfcchghebif\")","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"We can visualize this paint shop problem as a graph","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"rot(a, b, θ) = cos(θ)*a + sin(θ)*b, cos(θ)*b - sin(θ)*a\nlocations = [rot(0.0, 100.0, -0.25π - 1.5*π*(i-0.5)/length(sequence)) for i=1:length(sequence)]\ngraph = path_graph(length(sequence))\nfor i=1:length(sequence)\n j = findlast(==(sequence[i]), sequence)\n i != j && add_edge!(graph, i, j)\nend\nshow_graph(graph, locations; texts=string.(sequence), format=:svg, edge_colors=\n [sequence[e.src] == sequence[e.dst] ? \"blue\" : \"black\" for e in edges(graph)])","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Vertices connected by blue edges must have different colors, and the goal becomes a min-cut problem defined on black edges.","category":"page"},{"location":"generated/PaintShop/#Generic-tensor-network-representation","page":"Binary paint shop problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"We can define the binary paint shop problem with the PaintShop type as","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"pshop = PaintShop(sequence)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The tensor network representation of the binary paint shop problem can be obtained by","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"problem = GenericTensorNetwork(pshop)","category":"page"},{"location":"generated/PaintShop/#Theory-(can-skip)","page":"Binary paint shop problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Type PaintShop can be used for constructing the tensor network with optimized contraction order for solving a binary paint shop problem. To obtain its tensor network representation, we associating car c_i (the i-th character in our example) with a degree of freedom s_c_i in 0 1, where we use 0 to denote the first appearance of a car is colored red and 1 to denote the first appearance of a car is colored blue. For each black edges (i i+1), we define an edge tensor labeled by (s_c_i s_c_i+1) as follows: If both cars on this edge are their first or second appearance","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"B^rm parallel = left(beginmatrix\nx 1 \n1 x \nendmatrixright)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"otherwise,","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"B^rm anti-parallel = left(beginmatrix\n1 x \nx 1 \nendmatrixright)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"It can be understood as, when both cars are their first appearance, they tend to have the same configuration so that the color is not changed. Otherwise, they tend to have different configuration to keep the color unchanged.","category":"page"},{"location":"generated/PaintShop/#Counting-properties","page":"Binary paint shop problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/PaintShop/#graph-polynomial","page":"Binary paint shop problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The graph polynomial defined for the maximal independent set problem is","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"I_rm max(G x) = sum_k=0^alpha(G) b_k x^k","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"where b_k is the number of maximal independent sets of size k in graph G=(V E).","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"max_config = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Since it only counts the maximal independent sets, the first several coefficients are 0.","category":"page"},{"location":"generated/PaintShop/#Counting-properties-2","page":"Binary paint shop problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/PaintShop/#graph-polynomial-2","page":"Binary paint shop problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The graph polynomial of the binary paint shop problem in our convention is defined as","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"P(G x) = sum_k=0^delta(G) p_k x^k","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"where p_k is the number of possible coloring with number of color changes 2m-1-k.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"paint_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/PaintShop/#Configuration-properties","page":"Binary paint shop problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/PaintShop/#finding-best-solutions","page":"Binary paint shop problem","title":"finding best solutions","text":"","category":"section"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"best_configs = solve(problem, ConfigsMin())[]","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"One can see to identical bitstrings corresponding two different vertex configurations, they are related to bit-flip symmetry.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"painting1 = ProblemReductions.paint_shop_coloring_from_config(pshop, read_config(best_configs)[1])\n\nshow_graph(graph, locations; format=:svg, texts=string.(sequence),\n edge_colors=[sequence[e.src] == sequence[e.dst] ? \"blue\" : \"black\" for e in edges(graph)],\n vertex_colors=[isone(c) ? \"red\" : \"black\" for c in painting1], config=GraphDisplayConfig(;vertex_text_color=\"white\"))","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"Since we have different choices of initial color, the number of best solution is 2.","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"The following function will check the solution and return you the number of color switches","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"num_paint_shop_color_switch(sequence, painting1)","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"","category":"page"},{"location":"generated/PaintShop/","page":"Binary paint shop problem","title":"Binary paint shop problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"sumproduct/#Sum-product-representation-for-configurations","page":"Sum product tree representation","title":"Sum product representation for configurations","text":"","category":"section"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"SumProductTree can use polynomial memory to store exponential number of configurations. It is a sum-product expression tree to store ConfigEnumerator in a lazy style, where configurations can be extracted by depth first searching the tree with the Base.collect method. Although it is space efficient, it is in general not easy to extract information from it due to the exponential large configuration space. Directed sampling is one of its most important operations, with which one can get some statistic properties from it with an intermediate effort. For example, if we want to check some property of an intermediate scale graph, one can type","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"using GenericTensorNetworks\ngraph = random_regular_graph(70, 3)\nproblem = GenericTensorNetwork(IndependentSet(graph); optimizer=TreeSA());\ntree = solve(problem, ConfigsAll(; tree_storage=true))[]","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"If one wants to store these configurations, he will need a hard disk of size 256 TB! However, this sum-product binary tree structure supports efficient and unbiased direct sampling.","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"samples = generate_samples(tree, 1000)","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"With these samples, one can already compute useful properties like Hamming distance (see hamming_distribution) distribution. The following code visualizes this distribution with CairoMakie.","category":"page"},{"location":"sumproduct/","page":"Sum product tree representation","title":"Sum product tree representation","text":"using CairoMakie\ndist = hamming_distribution(samples, samples)\n# bar plot\nfig = Figure()\nax = Axis(fig[1, 1]; xlabel=\"Hamming distance\", ylabel=\"Frequency\")\nbarplot!(ax, 0:length(dist)-1, dist)\nfig","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"EditURL = \"../../../examples/Coloring.jl\"","category":"page"},{"location":"generated/Coloring/#Coloring-problem","page":"Coloring problem","title":"Coloring problem","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Coloring/#Problem-definition","page":"Coloring problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"A vertex coloring is an assignment of labels or colors to each vertex of a graph such that no edge connects two identically colored vertices. In the following, we are going to defined a 3-coloring problem for the Petersen graph.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/Coloring/#Generic-tensor-network-representation","page":"Coloring problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"We can define the 3-coloring problem with the Coloring type as","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"coloring = Coloring{3}(graph)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The tensor network representation of the 3-coloring problem can be obtained by","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"problem = GenericTensorNetwork(coloring)","category":"page"},{"location":"generated/Coloring/#Theory-(can-skip)","page":"Coloring problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Type Coloring can be used for constructing the tensor network with optimized contraction order for a coloring problem. Let us use 3-coloring problem defined on vertices as an example. For a vertex v, we define the degrees of freedom c_vin123 and a vertex tensor labelled by it as","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"W(v) = left(beginmatrix\n 1\n 1\n 1\nendmatrixright)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"For an edge (u v), we define an edge tensor as a matrix labelled by (c_u c_v) to specify the constraint","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"B = left(beginmatrix\n 1 x x\n x 1 x\n x x 1\nendmatrixright)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The number of possible coloring can be obtained by contracting this tensor network by setting vertex tensor elements r_v g_v and b_v to 1.","category":"page"},{"location":"generated/Coloring/#Solving-properties","page":"Coloring problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Coloring/#counting-all-possible-coloring","page":"Coloring problem","title":"counting all possible coloring","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"The size of a coloring problem is the number of violations of the coloring constraint.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"num_of_coloring = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/Coloring/#finding-one-best-coloring","page":"Coloring problem","title":"finding one best coloring","text":"","category":"section"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"single_solution = solve(problem, SingleConfigMin())[]\nread_config(single_solution)\n\nis_vertex_coloring(graph, read_config(single_solution))\n\nvertex_color_map = Dict(0=>\"red\", 1=>\"green\", 2=>\"blue\")\n\nshow_graph(graph, locations; format=:svg, vertex_colors=[vertex_color_map[Int(c)]\n for c in read_config(single_solution)])","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Let us try to solve the same issue on its line graph, a graph that generated by mapping an edge to a vertex and two edges sharing a common vertex will be connected.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"linegraph = line_graph(graph)\n\nshow_graph(linegraph, [(locations[e.src] .+ locations[e.dst])\n for e in edges(graph)]; format=:svg)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"Let us construct the tensor network and see if there are solutions.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"lineproblem = Coloring{3}(linegraph);\n\nnum_of_coloring = solve(GenericTensorNetwork(lineproblem), CountingMin())[]\nread_size_count(num_of_coloring)","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"You will see the maximum size 28 is smaller than the number of edges in the linegraph, meaning no solution for the 3-coloring on edges of a Petersen graph.","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"","category":"page"},{"location":"generated/Coloring/","page":"Coloring problem","title":"Coloring problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"EditURL = \"../../../examples/SetPacking.jl\"","category":"page"},{"location":"generated/SetPacking/#Set-packing-problem","page":"Set packing problem","title":"Set packing problem","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SetPacking/#Problem-definition","page":"Set packing problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The set packing problem is generalization of the IndependentSet problem from the simple graph to the multigraph. Suppose one has a finite set S and a list of subsets of S. Then, the set packing problem asks if some k subsets in the list are pairwise disjoint. In the following, we will find the solution space properties for the set in the Set covering problem.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The packing stadium areas of cameras are represented as the following sets.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"sets = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]","category":"page"},{"location":"generated/SetPacking/#Generic-tensor-network-representation","page":"Set packing problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"We can define the set packing problem with the SetPacking type as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"problem = SetPacking(sets)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"problem = GenericTensorNetwork(problem)","category":"page"},{"location":"generated/SetPacking/#Theory-(can-skip)","page":"Set packing problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Let S be the target set packing problem that we want to solve. For each set s in S, we associate it with a weight w_s to it. The tensor network representation map a set sin S to a boolean degree of freedom v_sin0 1. For each set s, we defined a parameterized rank-one tensor indexed by v_s as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"W(x_s^w_s) = left(beginmatrix\n 1 \n x_s^w_s\n endmatrixright)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"where x_s is a variable associated with s. For each unique element a, we defined the constraint over all sets containing it N(a) = s s in S land ain s:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"B_s_1s_2ldotss_N(a) = begincases\n 0 s_1+s_2+ldots+s_N(a) 1\n 1 textotherwise\nendcases","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"This tensor means if in a configuration, two sets contain the element a, then this configuration is forbidden, One can check the contraction time space complexity of a SetPacking instance by typing:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/SetPacking/#Solving-properties","page":"Set packing problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/SetPacking/#Counting-properties","page":"Set packing problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SetPacking/#The-\"graph\"-polynomial","page":"Set packing problem","title":"The \"graph\" polynomial","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The graph polynomial for the set packing problem is defined as","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"P(S x) = sum_k=0^alpha(S) c_k x^k","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"where c_k is the number of configurations having k sets, and alpha(S) is the maximum size of the packing.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"packing_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"The maximum number of sets that packing the set of elements can be computed with the SizeMax property:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"max_packing_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Similarly, we have its counting CountingMax:","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"counting_maximum_set_packing = solve(problem, CountingMax())[]","category":"page"},{"location":"generated/SetPacking/#Configuration-properties","page":"Set packing problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SetPacking/#Finding-maximum-set-packing","page":"Set packing problem","title":"Finding maximum set packing","text":"","category":"section"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"One can enumerate all maximum set packing with the ConfigsMax property in the program.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"max_configs = read_config(solve(problem, ConfigsMax())[])","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"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 function.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"all(c->is_set_packing(problem.problem, c), max_configs)","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"Similarly, if one is only interested in computing one of the maximum set packing, one can use the graph property SingleConfigMax.","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"","category":"page"},{"location":"generated/SetPacking/","page":"Set packing problem","title":"Set packing problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"EditURL = \"../../../examples/open.jl\"","category":"page"},{"location":"generated/open/#Open-and-fixed-degrees-of-freedom","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"","category":"section"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"Open degrees of freedom is useful when one want to get the marginal about certain degrees of freedom. When one specifies the openvertices keyword argument in solve function as a tuple of vertices, the output will be a tensor that can be indexed by these degrees of freedom. Let us use the maximum independent set problem on Petersen graph as an example.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"The following code computes the MIS tropical tensor (reference to be added) with open vertices 1, 2 and 3.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"problem = GenericTensorNetwork(IndependentSet(graph); openvertices=[1,2,3]);\n\nmarginal = solve(problem, SizeMax())","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"The return value is a rank-3 tensor, with its elements being the MIS sizes under different configuration of open vertices. For the maximum independent set problem, this tensor is also called the MIS tropical tensor, which can be useful in the MIS tropical tensor analysis (reference to be added).","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"One can also specify the fixed degrees of freedom by providing the fixedvertices keyword argument as a Dict, which can be used to get conditioned probability. For example, we can use the following code to do the same calculation as using openvertices.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"problem = GenericTensorNetwork(IndependentSet(graph); fixedvertices=Dict(1=>0, 2=>0, 3=>0));\n\noutput = zeros(TropicalF64,2,2,2);\n\nmarginal_alternative = map(CartesianIndices((2,2,2))) do ci\n problem.fixedvertices[1] = ci.I[1]-1\n problem.fixedvertices[2] = ci.I[2]-1\n problem.fixedvertices[3] = ci.I[3]-1\n output[ci] = solve(problem, SizeMax())[]\nend","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"One can easily check this one also gets the correct marginal on vertices 1, 2 and 3. As a reminder, their computational hardness can be different, because the contraction order optimization program can optimize over open degrees of freedom.","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"","category":"page"},{"location":"generated/open/","page":"Open and fixed degrees of freedom","title":"Open and fixed degrees of freedom","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"EditURL = \"../../../examples/Matching.jl\"","category":"page"},{"location":"generated/Matching/#Vertex-matching-problem","page":"Vertex matching problem","title":"Vertex matching problem","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Matching/#Problem-definition","page":"Vertex matching problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"A k-matching in a graph G is a set of k edges, no two of which have a vertex in common.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"In the following, we are going to defined a matching problem for the Petersen graph.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/Matching/#Generic-tensor-network-representation","page":"Vertex matching problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"We can define the matching problem with the Matching type as","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"matching = Matching(graph)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The tensor network representation of the matching problem can be obtained by","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"problem = GenericTensorNetwork(matching)","category":"page"},{"location":"generated/Matching/#Theory-(can-skip)","page":"Vertex matching problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"Type Matching can be used for constructing the tensor network with optimized contraction order for a matching problem. We map an edge (u v) in E to a label langle u vrangle in 0 1 in a tensor network, where 1 means two vertices of an edge are matched, 0 means otherwise. Then we define a tensor of rank d(v) = N(v) on vertex v such that,","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"W_langle v n_1rangle langle v n_2 rangle ldots langle v n_d(v)rangle = begincases\n 1 sum_i=1^d(v) langle v n_i rangle leq 1\n 0 textotherwise\nendcases","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"and a tensor of rank 1 on the bond","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"B_langle v wrangle = begincases\n1 langle v w rangle = 0 \nx langle v w rangle = 1\nendcases","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where label langle v w rangle is equivalent to langle wvrangle.","category":"page"},{"location":"generated/Matching/#Solving-properties","page":"Vertex matching problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The maximum matching size can be obtained by","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"max_matching = solve(problem, SizeMax())[]\nread_size(max_matching)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The largest number of matching is 5, which means we have a perfect matching (vertices are all paired).","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"The graph polynomial defined for the matching problem is known as the matching polynomial. Here, we adopt the first definition in the wiki page.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"M(G x) = sumlimits_k=1^V2 c_k x^k","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where k is the number of matches, and coefficients c_k are the corresponding counting.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"matching_poly = solve(problem, GraphPolynomial())[]\nread_size_count(matching_poly)","category":"page"},{"location":"generated/Matching/#Configuration-properties","page":"Vertex matching problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/Matching/#one-of-the-perfect-matches","page":"Vertex matching problem","title":"one of the perfect matches","text":"","category":"section"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"match_config = solve(problem, SingleConfigMax())[]\nread_size_config(match_config)","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"Let us show the result by coloring the matched edges to red","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"show_graph(graph, locations; format=:svg, edge_colors=\n [isone(read_config(match_config)[i]) ? \"red\" : \"black\" for i=1:ne(graph)])","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"where we use edges with red color to related pairs of matched vertices.","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"","category":"page"},{"location":"generated/Matching/","page":"Vertex matching problem","title":"Vertex matching problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"EditURL = \"../../../examples/Satisfiability.jl\"","category":"page"},{"location":"generated/Satisfiability/#Satisfiability-problem","page":"Satisfiability problem","title":"Satisfiability problem","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/Satisfiability/#Problem-definition","page":"Satisfiability problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"In logic and computer science, the boolean satisfiability problem is the problem of determining if there exists an interpretation that satisfies a given boolean formula. One can specify a satisfiable problem in the 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.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions\n\n@bools a b c d e f g\n\ncnf = ∧(∨(a, b, ¬d, ¬e), ∨(¬a, d, e, ¬f), ∨(f, g), ∨(¬b, c))","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"To goal is to find an assignment to satisfy the above CNF. For a satisfiability problem at this size, we can find the following assignment to satisfy this assignment manually.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"assignment = Dict([:a=>true, :b=>false, :c=>false, :d=>true, :e=>false, :f=>false, :g=>true])\n\nsatisfiable(cnf, assignment)","category":"page"},{"location":"generated/Satisfiability/#Generic-tensor-network-representation","page":"Satisfiability problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"We can use Satisfiability to construct the tensor network for solving the satisfiability problem as","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"sat = Satisfiability(cnf)","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The tensor network representation of the satisfiability problem can be obtained by","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"problem = GenericTensorNetwork(sat)","category":"page"},{"location":"generated/Satisfiability/#Theory-(can-skip)","page":"Satisfiability problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"We can construct a Satisfiability problem to solve the above problem. To generate a tensor network, we map a boolean variable x and its negation neg x to a degree of freedom (label) s_x in 0 1, where 0 stands for variable x having value false while 1 stands for having value true. Then we map a clause to a tensor. For example, a clause x y z can be mapped to a tensor labeled by (s_x s_y s_z).","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"C = left(beginmatrix\nleft(beginmatrix\nx x \nx x\nendmatrixright) \nleft(beginmatrix\nx x \n1 x\nendmatrixright)\nendmatrixright)","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"There is only one entry (s_x s_y s_z) = (1 0 1) that makes this clause unsatisfied.","category":"page"},{"location":"generated/Satisfiability/#Solving-properties","page":"Satisfiability problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/Satisfiability/#Satisfiability-and-its-counting","page":"Satisfiability problem","title":"Satisfiability and its counting","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The size of a satisfiability problem is defined by the number of unsatisfied clauses.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"num_satisfiable = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"The GraphPolynomial of a satisfiability problem counts the number of solutions that k clauses satisfied.","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"num_satisfiable_count = read_size_count(solve(problem, GraphPolynomial())[])","category":"page"},{"location":"generated/Satisfiability/#Find-one-of-the-solutions","page":"Satisfiability problem","title":"Find one of the solutions","text":"","category":"section"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"single_config = read_config(solve(problem, SingleConfigMin())[])","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"One will see a bit vector printed. One can create an assignment and check the validity with the following statement:","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"satisfiable(cnf, Dict(zip(ProblemReductions.symbols(problem.problem), single_config)))","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"","category":"page"},{"location":"generated/Satisfiability/","page":"Satisfiability problem","title":"Satisfiability problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"EditURL = \"../../../examples/SpinGlass.jl\"","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem","page":"Spin glass problem","title":"Spin-glass problem","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"using GenericTensorNetworks","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem-on-a-simple-graph","page":"Spin glass problem","title":"Spin-glass problem on a simple graph","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Let G=(V E) be a graph, the spin-glass problem in physics is characterized by the following energy function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"H = sum_ij in E J_ij s_i s_j + sum_i in V h_i s_i","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where h_i is an onsite energy term associated with spin s_i in -1 1, and J_ij is the coupling strength between spins s_i and s_j. In the program, we use boolean variable n_i = frac1-s_i2 to represent a spin configuration.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"using Graphs","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to defined an spin glass problem for the Petersen graph.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/SpinGlass/#Generic-tensor-network-representation","page":"Spin glass problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"An anti-ferromagnetic spin glass problem can be defined with the SpinGlass type as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"spinglass = SpinGlass(graph, fill(1, ne(graph)), zeros(Int, nv(graph)))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"problem = GenericTensorNetwork(spinglass)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The contraction order is already optimized.","category":"page"},{"location":"generated/SpinGlass/#The-tensor-network-reduction","page":"Spin glass problem","title":"The tensor network reduction","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"We defined the reduction of the spin-glass problem to a tensor network on a hypergraph. Let H = (V E) be a hypergraph, the tensor network for the spin glass problem on H can be defined as the following triple of (alphabet of labels Lambda, input tensors mathcalT, output labels sigma_o).","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"begincases\nLambda = s_v mid v in V\nmathcalT = B^(c)_s_N(c 1)N(c 2)ldotsN(c d(c)) mid c in E cup W^(v)_s_v mid v in V\nsigma_o = varepsilon\nendcases","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where s_v in 0 1 is the boolean degreen associated to vertex v, N(c k) is the kth vertex of hyperedge c, and d(c) is the degree of c. The edge tensor B^(c) is defined as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"B^(c) = begincases\nx^w_c (sum_vin c s_v) is even \nx^-w_c otherwise\nendcases","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"and the vertex tensor W^(v) (used to carry labels) is defined as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"W^(v) = left(beginmatrix1_v 1_vendmatrixright)","category":"page"},{"location":"generated/SpinGlass/#Graph-properties","page":"Spin glass problem","title":"Graph properties","text":"","category":"section"},{"location":"generated/SpinGlass/#Minimum-and-maximum-energies","page":"Spin glass problem","title":"Minimum and maximum energies","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The state with the highest energy is the one with all spins having the same value.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emax = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/SpinGlass/#Counting-properties","page":"Spin glass problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to find the partition function and the graph polynomial of the spin glass problem. Consider a spin glass problem on a graph G = (V E) with integer coupling strength J and onsite energy h. Its graph polynomial is a Laurent polynomial","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Z(G J h x) = sum_k=E_rm min^E_rm max c_k x^k","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where E_rm min and E_rm max are minimum and maximum energies, c_k is the number of spin configurations with energy k. The partition function at temperature beta^-1 can be computed by the graph polynomial at x = e^-beta.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"partition_function = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SpinGlass/#Configuration-properties","page":"Spin glass problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The ground state of the spin glass problem can be found by the SingleConfigMin solver.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"ground_state = read_config(solve(problem, SingleConfigMin())[])","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy of the ground state can be verified by the energy 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.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin_verify = energy(problem.problem, 1 .- 2 .* Int.(ground_state))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"You should see a consistent result as above Emin.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"show_graph(graph, locations; vertex_colors=[\n iszero(ground_state[i]) ? \"white\" : \"red\" for i=1:nv(graph)], format=:svg)","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the plot, the red vertices are the ones with spin value -1 (or 1 in the boolean representation).","category":"page"},{"location":"generated/SpinGlass/#Spin-glass-problem-on-a-hypergraph","page":"Spin glass problem","title":"Spin-glass problem on a hypergraph","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"A spin-glass problem on hypergraph H = (V E) can be characterized by the following energy function","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"E = sum_c in E w_c prod_vin c S_v","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where S_v in -1 1, w_c is coupling strength associated with hyperedge c. In the program, we use boolean variable s_v = frac1-S_v2 to represent a spin configuration.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In the following, we are going to defined an spin glass problem for the following hypergraph.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"num_vertices = 15\n\nhyperedges = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]\n\nweights = [-1, 1, -1, 1, -1, 1, -1, 1];\nnothing #hide","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy function of the spin glass problem is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"beginalign*\nE = -S_1S_3S_4S_6S_7 + S_4S_7S_8S_12 - S_2S_5S_9S_11S_13 +\n S_1S_2S_14S_15 - S_3S_6S_10S_12S_14 + S_8S_14S_15 +\n S_1S_2S_6S_11 - S_1s_2S_4S_6S_8S_12\nendalign*","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"A spin glass problem can be defined with the SpinGlass type as","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"hyperspinglass = SpinGlass(HyperGraph(num_vertices, hyperedges), weights, zeros(Int, num_vertices))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The tensor network representation of the set packing problem can be obtained by","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"hyperproblem = GenericTensorNetwork(hyperspinglass)","category":"page"},{"location":"generated/SpinGlass/#Graph-properties-2","page":"Spin glass problem","title":"Graph properties","text":"","category":"section"},{"location":"generated/SpinGlass/#Minimum-and-maximum-energies-2","page":"Spin glass problem","title":"Minimum and maximum energies","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"To find the minimum and maximum energies of the spin glass problem, we can use the SizeMin and SizeMax solvers.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin = solve(hyperproblem, SizeMin())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emax = solve(hyperproblem, SizeMax())[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"In this example, the spin configurations can be chosen to make all hyperedges having even or odd spin parity.","category":"page"},{"location":"generated/SpinGlass/#Counting-properties-2","page":"Spin glass problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SpinGlass/#partition-function-and-graph-polynomial","page":"Spin glass problem","title":"partition function and graph polynomial","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The graph polynomial defined for the spin-glass problem is a Laurent polynomial","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Z(G w x) = sum_k=E_rm min^E_rm max c_k x^k","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"where E_rm min and E_rm max are minimum and maximum energies, c_k is the number of spin configurations with energy k. Let the inverse temperature beta = 2, the partition function is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"β = 2.0\nZ = solve(hyperproblem, PartitionFunction(β))[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The infinite temperature partition function is the counting of all feasible configurations","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"solve(hyperproblem, PartitionFunction(0.0))[]","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The graph polynomial is","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"poly = solve(hyperproblem, GraphPolynomial())[]","category":"page"},{"location":"generated/SpinGlass/#Configuration-properties-2","page":"Spin glass problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The ground state of the spin glass problem can be found by the SingleConfigMin solver.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"ground_state = read_config(solve(hyperproblem, SingleConfigMin())[])","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"The energy of the ground state can be verified by the energy function.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"Emin_verify = energy(hyperproblem.problem, 1 .- 2 .* Int.(ground_state))","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"You should see a consistent result as above Emin.","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"","category":"page"},{"location":"generated/SpinGlass/","page":"Spin glass problem","title":"Spin glass problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"performancetips/#Performance-Tips","page":"Performance Tips","title":"Performance Tips","text":"","category":"section"},{"location":"performancetips/#Optimize-contraction-orders","page":"Performance Tips","title":"Optimize contraction orders","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Let us use the independent set problem on 3-regular graphs as an example.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"using GenericTensorNetworks, Graphs, Random\ngraph = random_regular_graph(120, 3)\niset = IndependentSet(graph)\nproblem = GenericTensorNetwork(iset; optimizer=TreeSA(\n sc_target=20, sc_weight=1.0, rw_weight=3.0, ntrials=10, βs=0.01:0.1:15.0, niters=20));","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The GenericTensorNetwork constructor maps an independent set problem to a tensor network with optimized contraction order. The key word argument optimizer specifies the contraction order optimizer of the tensor network. Here, we choose the local search based TreeSA algorithm, which often finds the smallest time/space complexity and supports slicing. One can type ?TreeSA in a Julia REPL for more information about how to configure the hyper-parameters of the TreeSA method, while the detailed algorithm explanation is in arXiv: 2108.05665. Alternative tensor network contraction order optimizers include","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"GreedyMethod (default, fastest in searching speed but worst in contraction complexity)\nKaHyParBipartite\nSABipartite","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"For example, the MergeGreedy() here \"contracts\" tensors greedily whenever the contraction result has a smaller space complexity. It can remove all vertex tensors (vectors) before entering the contraction order optimization algorithm.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The returned object problem contains a field code that specifies the tensor network with optimized contraction order. For an independent set problem, the optimal contraction time/space complexity is sim 2^rm tw(G), where rm tw(G) is the tree-width of G. One can check the time, space and read-write complexity with the contraction_complexity function.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"contraction_complexity(problem)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The return values are log2 values of the number of multiplications, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements. In this example, the number * operations is sim 2^219, the number of read-write operations are sim 2^20, and the largest tensor size is 2^17. One can check the element size by typing","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"sizeof(TropicalF64)\nsizeof(TropicalF32)\nsizeof(StaticBitVector{200,4})\nsizeof(TruncatedPoly{5,Float64,Float64})","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can use estimate_memory to get a good estimation of peak memory in bytes. For example, to compute the graph polynomial, the peak memory can be estimated as follows.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"estimate_memory(problem, GraphPolynomial(; method=:finitefield))\nestimate_memory(problem, GraphPolynomial(; method=:polynomial))","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The finite field approach only requires 298 KB memory, while using the Polynomial number type requires 71 MB memory.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"note: Note\nThe actual run time memory can be several times larger than the size of the maximum tensor, so the estimate_memory is more accurate in estimating the peak memory.\nFor mutable element types like ConfigEnumerator, none of memory estimation functions measure the actual memory usage correctly.","category":"page"},{"location":"performancetips/#Slicing-technique","page":"Performance Tips","title":"Slicing technique","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"For large scale applications, it is also possible to slice over certain degrees of freedom to reduce the space complexity, i.e. loop and accumulate over certain degrees of freedom so that one can have a smaller tensor network inside the loop due to the removal of these degrees of freedom. In the TreeSA optimizer, one can set nslices to a value larger than zero to turn on this feature.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));\ncontraction_complexity(problem)\nproblem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));\ncontraction_complexity(problem)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"In the second IndependentSet constructor, we slice over 5 degrees of freedom, which can reduce the space complexity by at most 5. In this application, the slicing achieves the largest possible space complexity reduction 5, while the time and read-write complexity are only increased by less than 1, i.e. the peak memory usage is reduced by a factor 32, while the (theoretical) computing time is increased by at a factor 2.","category":"page"},{"location":"performancetips/#GEMM-for-Tropical-numbers","page":"Performance Tips","title":"GEMM for Tropical numbers","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can speed up the Tropical number matrix multiplication when computing the solution space property SizeMax() by using the Tropical GEMM routines implemented in package TropicalGEMM.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"julia> using BenchmarkTools\n\njulia> @btime solve(problem, SizeMax())\n 91.630 ms (19203 allocations: 23.72 MiB)\n0-dimensional Array{TropicalF64, 0}:\n53.0ₜ\n\njulia> using TropicalGEMM\n\njulia> @btime solve(problem, SizeMax())\n 8.960 ms (18532 allocations: 17.01 MiB)\n0-dimensional Array{TropicalF64, 0}:\n53.0ₜ","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The TropicalGEMM package pirates the LinearAlgebra.mul! interface, hence it takes effect upon using. The above example shows more than 10x speed up on a single thread CPU, which can be even faster if the Julia multi-threading if turned on. The benchmark in the TropicalGEMM repo shows this performance is close to the theoretical optimal value.","category":"page"},{"location":"performancetips/#Multiprocessing","page":"Performance Tips","title":"Multiprocessing","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Submodule GenericTensorNetworks.SimpleMutiprocessing provides one function GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run function for simple multi-processing jobs. It is not directly related to GenericTensorNetworks, but is very convenient to have one. Suppose we want to find the independence polynomial for multiple graphs with 4 processes. We can create a file, e.g. named run.jl with the following content","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"using Distributed, GenericTensorNetworks.SimpleMultiprocessing\nusing Random, GenericTensorNetworks # to avoid multi-precompilation\n@everywhere using Random, GenericTensorNetworks\n\nresults = multiprocess_run(collect(1:10)) do seed\n Random.seed!(seed)\n n = 10\n @info \"Graph size $n x $n, seed= $seed\"\n g = random_diagonal_coupled_graph(n, n, 0.8)\n gp = GenericTensorNetwork(IndependentSet(g); optimizer=TreeSA())\n res = solve(gp, GraphPolynomial())[]\n return res\nend\n\nprintln(results)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"One can run this script file with the following command","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"$ julia -p4 run.jl\n From worker 3:\t[ Info: running argument 4 on device 3\n From worker 4:\t[ Info: running argument 2 on device 4\n From worker 5:\t[ Info: running argument 3 on device 5\n From worker 2:\t[ Info: running argument 1 on device 2\n From worker 3:\t[ Info: Graph size 10 x 10, seed= 4\n From worker 4:\t[ Info: Graph size 10 x 10, seed= 2\n From worker 5:\t[ Info: Graph size 10 x 10, seed= 3\n From worker 2:\t[ Info: Graph size 10 x 10, seed= 1\n From worker 4:\t[ Info: running argument 5 on device\n ...","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"You will see a vector of polynomials printed out.","category":"page"},{"location":"performancetips/#Make-use-of-GPUs","page":"Performance Tips","title":"Make use of GPUs","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"To upload the computation to GPU, you just add using CUDA before calling the solve function, and set the keyword argument usecuda to true.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"julia> using CUDA\n[ Info: OMEinsum loaded the CUDA module successfully\n\njulia> solve(problem, SizeMax(), usecuda=true)\n0-dimensional CuArray{TropicalF64, 0, CUDA.Mem.DeviceBuffer}:\n53.0ₜ","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Solution space properties computable on GPU includes","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"SizeMax and SizeMin\nCountingAll\nCountingMax and CountingMin\nGraphPolynomial\nSingleConfigMax and SingleConfigMin","category":"page"},{"location":"performancetips/#Benchmarks","page":"Performance Tips","title":"Benchmarks","text":"","category":"section"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"We run a single thread benchmark on central processing units (CPU) Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz, and its CUDA version on a GPU Tesla V100-SXM2 16G. The results are summarized in the following plot. The benchmark code can be found in our paper repository.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(Image: benchmark-independent-set) This benchmark results is for computing different solution space properties of independent sets of random three-regular graphs with different tensor element types. The time in these plots only includes tensor network contraction, without taking into account the contraction order finding and just-in-time compilation time. Legends are properties, algebra, and devices that we used in the computation; one can find the corresponding computed solution space property in Table 1 in the paper.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(a) time and space complexity versus the number of vertices for the benchmarked graphs.\n(b) The computation time for calculating the MIS size and for counting the number of all independent sets (ISs), the number of MISs, the number of independent sets having size alpha(G) and alpha(G)-1, and finding 100 largest set sizes.\n(c) The computation time for calculating the independence polynomials with different approaches.\n(d) The computation time for configuration enumeration, including single MIS configuration, the enumeration of all independent set configurations, all MIS configurations, all independent sets, and all independent set configurations having size alpha(G) and alpha(G)-1.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"The graphs in all benchmarks are random three-regular graphs, which have treewidth that is asymptotically smaller than V6. In this benchmark, we do not include traditional algorithms for finding the MIS sizes such as branching or dynamic programming. To the best of our knowledge, these algorithms are not suitable for computing most of the solution space properties mentioned in this paper. The main goal of this section is to show the relative computation time for calculating different solution space properties.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Panel (a) shows the time and space complexity of tensor network contraction for different graph sizes. The contraction order is obtained using the TreeSA algorithm that implemented in OMEinsumContractionOrders. If we assume our contraction-order finding program has found the optimal treewidth, which is very likely to be true, the space complexity is the same as the treewidth of the problem graph. Slicing technique has been used for graphs with space complexity greater than 2^27 (above the yellow dashed line) to fit the computation into a 16GB memory. One can see that all the computation times in panels (b), (c), and (d) have a strong correlation with the predicted time and space complexity. While in panel (d), the computation time of configuration enumeration also strongly correlates with other factors such as the configuration space size. Among these benchmarks, computational tasks with data types real numbers, complex numbers, or Tropical numbers (CPU only) can utilize fast basic linear algebra subprograms (BLAS) functions. These tasks usually compute much faster than ones with other element types in the same category. Immutable data types with no reference to other values can be compiled to GPU devices that run much faster than CPUs in all cases when the problem scale is big enough. These data types do not include those defined in Polynomial, ConfigEnumerator, ExtendedTropical and SumProductTree or a data type containing them as a part. In panel (c), one can see the Fourier transformation-based method is the fastest in computing the independence polynomial, but it may suffer from round-off errors. The finite field (GF(p)) approach is the only method that does not have round-off errors and can be run on a GPU. In panel (d), one can see the technique to bound the enumeration space (see paper) improves the performance for more than one order of magnitude in enumerating the MISs. The bounding technique can also reduce the memory usage significantly, without which the largest computable graph size is only sim150 on a device with 32GB main memory.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"We show the benchmark of computing the maximal independent set properties on 3-regular graphs in the following plot, including a comparison to the Bron-Kerbosch algorithm from Julia package Graphs","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(Image: benchmark-maximal-independent-set)","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"In this plot, benchmarks of computing different solution space properties of the maximal independent sets (ISs) problem on random three regular graphs at different sizes.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"(a) time and space complexity of tensor network contraction.\n(b) The wall clock time for counting and enumeration of maximal ISs.","category":"page"},{"location":"performancetips/","page":"Performance Tips","title":"Performance Tips","text":"Panel (a) shows the space and time complexities of tensor contraction, which are typically larger than those for the independent set problem. In panel (b), one can see counting maximal independent sets are much more efficient than enumerating them, while our generic tensor network approach runs slightly faster than the Bron-Kerbosch approach in enumerating all maximal independent sets.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"EditURL = \"../../../examples/MaximalIS.jl\"","category":"page"},{"location":"generated/MaximalIS/#Maximal-independent-set-problem","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/MaximalIS/#Problem-definition","page":"Maximal independent set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"In graph theory, a maximal independent set is an independent set that is not a subset of any other independent set. It is different from maximum independent set because it does not require the set to have the max size. In the following, we are going to solve the maximal independent set problem on the Petersen graph.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/MaximalIS/#Generic-tensor-network-representation","page":"Maximal independent set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"We can use MaximalIS to construct the tensor network for solving the maximal independent set problem as","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximalis = MaximalIS(graph)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The tensor network representation of the maximal independent set problem can be obtained by","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"problem = GenericTensorNetwork(maximalis)","category":"page"},{"location":"generated/MaximalIS/#Theory-(can-skip)","page":"Maximal independent set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Let G=(VE) be the target graph that we want to solve. The tensor network representation map a vertex vin V to a boolean degree of freedom s_vin0 1. We defined the restriction on its neighborhood N(v):","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"T(x_v)_s_1s_2ldotss_N(v)s_v = begincases\n s_vx_v^w_v s_1=s_2=ldots=s_N(v)=0\n 1-s_v textotherwise\nendcases","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The first case corresponds to all the neighborhood vertices of v are not in I_m, then v must be in I_m and contribute a factor x_v^w_v, where w_v is the weight of vertex v. Otherwise, if any of the neighboring vertices of v is in I_m, v must not be in I_m by the independence requirement.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Its contraction time space complexity of a MaximalIS instance is no longer determined by the tree-width of the original graph G. It is often harder to contract this tensor network than to contract the one for regular independent set problem.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/MaximalIS/#Solving-properties","page":"Maximal independent set problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/MaximalIS/#Counting-properties","page":"Maximal independent set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/MaximalIS/#maximal-independence-polynomial","page":"Maximal independent set problem","title":"maximal independence polynomial","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"The graph polynomial defined for the maximal independent set problem is","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"I_rm max(G x) = sum_k=0^alpha(G) b_k x^k","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"where b_k is the number of maximal independent sets of size k in graph G=(V E).","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximal_indenpendence_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"One can see the first several coefficients are 0, because it only counts the maximal independent sets, The minimum maximal independent set size is also known as the independent domination number. It can be computed with the SizeMin property:","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"independent_domination_number = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"counting_min_maximal_independent_set = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/MaximalIS/#Configuration-properties","page":"Maximal independent set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/MaximalIS/#finding-all-maximal-independent-set","page":"Maximal independent set problem","title":"finding all maximal independent set","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"maximal_configs = read_config(solve(problem, ConfigsAll())[])\n\nall(c->is_maximal_independent_set(graph, c), maximal_configs)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"show_configs(graph, locations, reshape(collect(maximal_configs), 3, 5); padding_left=20)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"This result should be consistent with that given by the Bron Kerbosch algorithm on the complement of Petersen graph.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"cliques = maximal_cliques(complement(graph))","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"For sparse graphs, the generic tensor network approach is usually much faster and memory efficient than the Bron Kerbosch algorithm.","category":"page"},{"location":"generated/MaximalIS/#finding-minimum-maximal-independent-set","page":"Maximal independent set problem","title":"finding minimum maximal independent set","text":"","category":"section"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"It is the ConfigsMin property in the program.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"minimum_maximal_configs = read_config(solve(problem, ConfigsMin())[])\n\nshow_configs(graph, locations, reshape(collect(minimum_maximal_configs), 2, 5); padding_left=20)","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"Similarly, if one is only interested in computing one of the minimum sets, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"","category":"page"},{"location":"generated/MaximalIS/","page":"Maximal independent set problem","title":"Maximal independent set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"EditURL = \"../../../examples/MaxCut.jl\"","category":"page"},{"location":"generated/MaxCut/#Cutting-problem","page":"Cutting problem","title":"Cutting problem","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/MaxCut/#Problem-definition","page":"Cutting problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"In graph theory, a cut is a partition of the vertices of a graph into two disjoint subsets. It is closely related to the Spin-glass problem in physics. Finding the maximum cut is NP-Hard, where a maximum cut is a cut whose size is at least the size of any other cut, where the size of a cut is the number of edges (or the sum of weights on edges) crossing the cut.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"In the following, we are going to defined an cutting problem for the Petersen graph.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"graph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/MaxCut/#Generic-tensor-network-representation","page":"Cutting problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We can define the cutting problem with the MaxCut type as","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"maxcut = MaxCut(graph)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"The tensor network representation of the cutting problem can be obtained by","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"problem = GenericTensorNetwork(maxcut)","category":"page"},{"location":"generated/MaxCut/#Theory-(can-skip)","page":"Cutting problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"We associated a vertex vin V with a boolean degree of freedom s_vin0 1. Then the maximum cutting problem can be encoded to tensor networks by mapping an edge (ij)in E to an edge matrix labelled by s_i and s_j","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"B(x_i x_j w_ij) = left(beginmatrix\n 1 x_i^w_ij\n x_j^w_ij 1\nendmatrixright)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where w_ij is a real number associated with edge (i j) as the edge weight. If and only if the bipartition cuts on edge (i j), this tensor contributes a factor x_i^w_ij or x_j^w_ij. Similarly, one can assign weights to vertices, which corresponds to the onsite energy terms in the spin glass. The vertex tensor is","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"W(x_i w_i) = left(beginmatrix\n 1\n x_i^w_i\nendmatrixright)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where w_i is a real number associated with vertex i as the vertex weight.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"Its contraction time space complexity is 2^rm tw(G), where rm tw(G) is the tree-width of G.","category":"page"},{"location":"generated/MaxCut/#Solving-properties","page":"Cutting problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/MaxCut/#Maximum-cut-size-\\gamma(G)","page":"Cutting problem","title":"Maximum cut size gamma(G)","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_cut_size = solve(problem, SizeMax())[]","category":"page"},{"location":"generated/MaxCut/#Counting-properties","page":"Cutting problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/MaxCut/#graph-polynomial","page":"Cutting problem","title":"graph polynomial","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"The graph polynomial defined for the cutting problem is","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"C(G x) = sum_k=0^gamma(G) c_k x^k","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where gamma(G) is the maximum cut size, c_k2 is the number of cuts of size k in graph G=(VE). Since the variable x is defined on edges, the coefficients of the polynomial is the number of configurations having different number of anti-parallel edges.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_config = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/MaxCut/#Configuration-properties","page":"Cutting problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/MaxCut/#finding-one-max-cut-solution","page":"Cutting problem","title":"finding one max cut solution","text":"","category":"section"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"max_vertex_config = read_config(solve(problem, SingleConfigMax())[])\n\nmax_cut_size_verify = cut_size(graph, max_vertex_config)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"You should see a consistent result as above max_cut_size.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"show_graph(graph, locations; vertex_colors=[\n iszero(max_vertex_config[i]) ? \"white\" : \"red\" for i=1:nv(graph)], format=:svg)","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"where red vertices and white vertices are separated by the cut.","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"","category":"page"},{"location":"generated/MaxCut/","page":"Cutting problem","title":"Cutting problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"EditURL = \"../../../examples/saveload.jl\"","category":"page"},{"location":"generated/saveload/#Save-and-load-solutions","page":"Save and load solutions","title":"Save and load solutions","text":"","category":"section"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"Let us use the maximum independent set problem on Petersen graph as an example. The following code enumerates all independent sets.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"using GenericTensorNetworks, Graphs\n\nproblem = GenericTensorNetwork(IndependentSet(Graphs.smallgraph(:petersen)))\n\nall_independent_sets = solve(problem, ConfigsAll())[]","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"The return value has type ConfigEnumerator. We can use save_configs and load_configs to save and read a ConfigEnumerator instance to the disk.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"filename = tempname()\n\nsave_configs(filename, all_independent_sets; format=:binary)\n\nloaded_sets = load_configs(filename; format=:binary, bitlength=10)","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"note: Note\nWhen loading the data in the binary format, bit string length information bitlength is required.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"For the SumProductTree type output, we can use save_sumproduct and load_sumproduct to save and load serialized data.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"all_independent_sets_tree = solve(problem, ConfigsAll(; tree_storage=true))[]\n\nsave_sumproduct(filename, all_independent_sets_tree)\n\nloaded_sets_tree = load_sumproduct(filename)","category":"page"},{"location":"generated/saveload/#Loading-solutions-to-python","page":"Save and load solutions","title":"Loading solutions to python","text":"","category":"section"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"The following python script loads and unpacks the solutions as a numpy array from a :binary format file.","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"import numpy as np\n\ndef loadfile(filename:str, bitlength:int):\n C = int(np.ceil(bitlength / 64))\n arr = np.fromfile(filename, dtype=\"uint8\")\n # Some axes should be transformed from big endian to little endian\n res = np.unpackbits(arr).reshape(-1, C, 8, 8)[:,::-1,::-1,:]\n res = res.reshape(-1, C*64)[:, :(64*C-bitlength)-1:-1]\n print(\"number of solutions = %d\"%(len(res)))\n return res # in big endian format\n\nres = loadfile(filename, 10)","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"note: Note\nCheck section Maximal independent set problem for solution space properties related the maximal independent sets. That example also contains using cases of finding solution space properties related to minimum sizes:SizeMin for finding minimum several set sizes,\nCountingMin for counting minimum several set sizes,\nSingleConfigMin for finding one solution with minimum several sizes,\nConfigsMin for enumerating solutions with minimum several sizes,","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"","category":"page"},{"location":"generated/saveload/","page":"Save and load solutions","title":"Save and load solutions","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"EditURL = \"../../../examples/SetCovering.jl\"","category":"page"},{"location":"generated/SetCovering/#Set-covering-problem","page":"Set covering problem","title":"Set covering problem","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/SetCovering/#Problem-definition","page":"Set covering problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The set covering problem is a significant NP-hard problem in combinatorial optimization. Given a collection of elements, the set covering problem aims to find the minimum number of sets that incorporate (cover) all of these elements. In the following, we will find the solution space properties for the camera location and stadium area example in the Cornell University Computational Optimization Open Textbook.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"using GenericTensorNetworks, Graphs","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The covering stadium areas of cameras are represented as the following sets.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"sets = [[1,3,4,6,7], [4,7,8,12], [2,5,9,11,13],\n [1,2,14,15], [3,6,10,12,14], [8,14,15],\n [1,2,6,11], [1,2,4,6,8,12]]","category":"page"},{"location":"generated/SetCovering/#Generic-tensor-network-representation","page":"Set covering problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"We can define the set covering problem with the SetCovering type as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"setcover = SetCovering(sets)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The tensor network representation of the set covering problem can be obtained by","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"problem = GenericTensorNetwork(setcover)","category":"page"},{"location":"generated/SetCovering/#Theory-(can-skip)","page":"Set covering problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Let S be the target set covering problem that we want to solve. For each set s in S, we associate it with a weight w_s to it. The tensor network representation map a set sin S to a boolean degree of freedom v_sin0 1. For each set s, we defined a parameterized rank-one tensor indexed by v_s as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"W(x_s^w_s) = left(beginmatrix\n 1 \n x_s^w_s\n endmatrixright)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"where x_s is a variable associated with s. For each unique element a, we defined the constraint over all sets containing it N(a) = s s in S land ain s:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"B_s_1s_2ldotss_N(a) = begincases\n 0 s_1=s_2=ldots=s_N(a)=0\n 1 textotherwise\nendcases","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"This tensor means if none of the sets containing element a are included, then this configuration is forbidden, One can check the contraction time space complexity of a SetCovering instance by typing:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/SetCovering/#Solving-properties","page":"Set covering problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/SetCovering/#Counting-properties","page":"Set covering problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/SetCovering/#The-\"graph\"-polynomial","page":"Set covering problem","title":"The \"graph\" polynomial","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The graph polynomial for the set covering problem is defined as","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"P(S x) = sum_k=0^S c_k x^k","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"where c_k is the number of configurations having k sets.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"covering_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"The minimum number of sets that covering the set of elements can be computed with the SizeMin property:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"min_cover_size = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"counting_minimum_setcovering = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/SetCovering/#Configuration-properties","page":"Set covering problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/SetCovering/#Finding-minimum-set-covering","page":"Set covering problem","title":"Finding minimum set covering","text":"","category":"section"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"One can enumerate all minimum set covering with the ConfigsMin property in the program.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"min_configs = read_config(solve(problem, ConfigsMin())[])","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"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 function.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"all(c->is_set_covering(problem.problem, c), min_configs)","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"Similarly, if one is only interested in computing one of the minimum set coverings, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"","category":"page"},{"location":"generated/SetCovering/","page":"Set covering problem","title":"Set covering problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"gist/#Gist-of-implementation","page":"Gist","title":"Gist of implementation","text":"","category":"section"},{"location":"gist/","page":"Gist","title":"Gist","text":"The code we will show below is a gist of how this package is implemented for pedagogical purpose, which covers many functionalities of the main repo without caring much about performance. This project depends on multiple open source packages in the Julia ecosystem:","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"OMEinsum and OMEinsumContractionOrders are packages providing the support for Einstein's (or tensor network) notation and state-of-the-art algorithms for contraction order optimization, which includes multiple state of the art algorithms.\nTropicalNumbers and TropicalGEMM are packages providing tropical number and efficient tropical matrix multiplication.\nGraphs is a foundational package for graph manipulation in the Julia community.\nPolynomials is a package providing polynomial algebra and polynomial fitting.\nMods and the Primes package providing finite field algebra and prime number manipulation.","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"They can be installed in a similar way to GenericTensorNetworks. After installing the required packages, one can open a Julia REPL, and copy-paste the following code snippet into it.","category":"page"},{"location":"gist/","page":"Gist","title":"Gist","text":"using OMEinsum\nusing Graphs\nusing Random\n\n# generate a random regular graph of size 50, degree 3\ngraph = (Random.seed!(2); Graphs.random_regular_graph(50, 3))\n\n# generate einsum code, i.e. the labels of tensors\ncode = EinCode(([minmax(e.src,e.dst) for e in Graphs.edges(graph)]..., # labels for edge tensors\n [(i,) for i in Graphs.vertices(graph)]...), ()) # labels for vertex tensors\n\n# an einsum contraction without a contraction order specified is called `EinCode`,\n# an einsum contraction having a contraction order (specified as a tree structure) is called `NestedEinsum`.\n# assign each label a dimension-2, it will be used in the contraction order optimization\n# `uniquelabels` function extracts the tensor labels into a vector.\nsize_dict = Dict([s=>2 for s in uniquelabels(code)])\n# optimize the contraction order using the `TreeSA` method; the target space complexity is 2^17\noptimized_code = optimize_code(code, size_dict, TreeSA())\nprintln(\"time/space complexity is $(OMEinsum.timespace_complexity(optimized_code, size_dict))\")\n\n# a function for computing the independence polynomial\nfunction independence_polynomial(x::T, code) where {T}\n\txs = map(getixsv(code)) do ix\n # if the tensor rank is 1, create a vertex tensor.\n # otherwise the tensor rank must be 2, create a bond tensor.\n length(ix)==1 ? [one(T), x] : [one(T) one(T); one(T) zero(T)]\n end\n # both `EinCode` and `NestedEinsum` are callable, inputs are tensors.\n\tcode(xs...)\nend\n\n########## COMPUTING THE MAXIMUM INDEPENDENT SET SIZE AND ITS COUNTING/DEGENERACY ###########\n\n# using Tropical numbers to compute the MIS size and the MIS degeneracy.\nusing TropicalNumbers\nmis_size(code) = independence_polynomial(TropicalF64(1.0), code)[]\nprintln(\"the maximum independent set size is $(mis_size(optimized_code).n)\")\n\n# A `CountingTropical` object has two fields, tropical field `n` and counting field `c`.\nmis_count(code) = independence_polynomial(CountingTropical{Float64,Float64}(1.0, 1.0), code)[]\nprintln(\"the degeneracy of maximum independent sets is $(mis_count(optimized_code).c)\")\n\n########## COMPUTING THE INDEPENDENCE POLYNOMIAL ###########\n\n# using Polynomial numbers to compute the polynomial directly\nusing Polynomials\nprintln(\"the independence polynomial is $(independence_polynomial(Polynomial([0.0, 1.0]), optimized_code)[])\")\n\n########## FINDING MIS CONFIGURATIONS ###########\n\n# define the set algebra\nstruct ConfigEnumerator{N}\n # NOTE: BitVector is dynamic and it can be very slow; check our repo for the static version\n data::Vector{BitVector}\nend\nfunction Base.:+(x::ConfigEnumerator{N}, y::ConfigEnumerator{N}) where {N}\n res = ConfigEnumerator{N}(vcat(x.data, y.data))\n return res\nend\nfunction Base.:*(x::ConfigEnumerator{L}, y::ConfigEnumerator{L}) where {L}\n M, N = length(x.data), length(y.data)\n z = Vector{BitVector}(undef, M*N)\n for j=1:N, i=1:M\n z[(j-1)*M+i] = x.data[i] .| y.data[j]\n end\n return ConfigEnumerator{L}(z)\nend\nBase.zero(::Type{ConfigEnumerator{N}}) where {N} = ConfigEnumerator{N}(BitVector[])\nBase.one(::Type{ConfigEnumerator{N}}) where {N} = ConfigEnumerator{N}([falses(N)])\n\n# the algebra sampling one of the configurations\nstruct ConfigSampler{N}\n data::BitVector\nend\n\nfunction Base.:+(x::ConfigSampler{N}, y::ConfigSampler{N}) where {N} # biased sampling: return `x`\n return x # randomly pick one\nend\nfunction Base.:*(x::ConfigSampler{L}, y::ConfigSampler{L}) where {L}\n ConfigSampler{L}(x.data .| y.data)\nend\n\nBase.zero(::Type{ConfigSampler{N}}) where {N} = ConfigSampler{N}(trues(N))\nBase.one(::Type{ConfigSampler{N}}) where {N} = ConfigSampler{N}(falses(N))\n\n# enumerate all configurations if `all` is true; compute one otherwise.\n# a configuration is stored in the data type of `StaticBitVector`; it uses integers to represent bit strings.\n# `ConfigTropical` is defined in `TropicalNumbers`. It has two fields: tropical number `n` and optimal configuration `config`.\n# `CountingTropical{T,<:ConfigEnumerator}` stores configurations instead of simple counting.\nfunction mis_config(code; all=false)\n # map a vertex label to an integer\n vertex_index = Dict([s=>i for (i, s) in enumerate(uniquelabels(code))])\n N = length(vertex_index) # number of vertices\n xs = map(getixsv(code)) do ix\n T = all ? CountingTropical{Float64, ConfigEnumerator{N}} : CountingTropical{Float64, ConfigSampler{N}}\n if length(ix) == 2\n return [one(T) one(T); one(T) zero(T)]\n else\n s = falses(N)\n s[vertex_index[ix[1]]] = true # one hot vector\n if all\n [one(T), T(1.0, ConfigEnumerator{N}([s]))]\n else\n [one(T), T(1.0, ConfigSampler{N}(s))]\n end\n end\n end\n\treturn code(xs...)\nend\n\nprintln(\"one of the optimal configurations is $(mis_config(optimized_code; all=false)[].c.data)\")\n\n# direct enumeration of configurations can be very slow; please check the bounding version in our Github repo.\nprintln(\"all optimal configurations are $(mis_config(optimized_code; all=true)[].c)\")","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"EditURL = \"../../../examples/DominatingSet.jl\"","category":"page"},{"location":"generated/DominatingSet/#Dominating-set-problem","page":"Dominating set problem","title":"Dominating set problem","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"note: Note\nIt is highly recommended to read the Independent set problem chapter before reading this one.","category":"page"},{"location":"generated/DominatingSet/#Problem-definition","page":"Dominating set problem","title":"Problem definition","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"In graph theory, a dominating set for a graph G = (V E) is a subset D of V such that every vertex not in D is adjacent to at least one member of D. The domination number gamma(G) is the number of vertices in a smallest dominating set for G. The decision version of finding the minimum dominating set is an NP-complete. In the following, we are going to solve the dominating set problem on the Petersen graph.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"using GenericTensorNetworks, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"We can visualize this graph using the following function","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg)","category":"page"},{"location":"generated/DominatingSet/#Generic-tensor-network-representation","page":"Dominating set problem","title":"Generic tensor network representation","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"We can use DominatingSet to construct the tensor network for solving the dominating set problem as","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"dom = DominatingSet(graph)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The tensor network representation of the dominating set problem can be obtained by","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"problem = GenericTensorNetwork(dom; optimizer=TreeSA())","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where the key word argument optimizer specifies the tensor network contraction order optimizer as a local search based optimizer TreeSA.","category":"page"},{"location":"generated/DominatingSet/#Theory-(can-skip)","page":"Dominating set problem","title":"Theory (can skip)","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Let G=(VE) be the target graph that we want to solve. The tensor network representation map a vertex vin V to a boolean degree of freedom s_vin0 1. We defined the restriction on a vertex and its neighboring vertices N(v):","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"T(x_v)_s_1s_2ldotss_N(v)s_v = begincases\n 0 s_1=s_2=ldots=s_N(v)=s_v=0\n 1 s_v=0\n x_v^w_v textotherwise\nendcases","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where w_v is the weight of vertex v. This tensor means if both v and its neighboring vertices are not in D, i.e., s_1=s_2=ldots=s_N(v)=s_v=0, this configuration is forbidden because v is not adjacent to any member in the set. otherwise, if v is in D, it has a contribution x_v^w_v to the final result. One can check the contraction time space complexity of a DominatingSet instance by typing:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"contraction_complexity(problem)","category":"page"},{"location":"generated/DominatingSet/#Solving-properties","page":"Dominating set problem","title":"Solving properties","text":"","category":"section"},{"location":"generated/DominatingSet/#Counting-properties","page":"Dominating set problem","title":"Counting properties","text":"","category":"section"},{"location":"generated/DominatingSet/#Domination-polynomial","page":"Dominating set problem","title":"Domination polynomial","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The graph polynomial for the dominating set problem is known as the domination polynomial (see arXiv:0905.2251). It is defined as","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"D(G x) = sum_k=0^gamma(G) d_k x^k","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"where d_k is the number of dominating sets of size k in graph G=(V E).","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"domination_polynomial = solve(problem, GraphPolynomial())[]","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"The domination number gamma(G) can be computed with the SizeMin property:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"domination_number = solve(problem, SizeMin())[]","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Similarly, we have its counting CountingMin:","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"counting_min_dominating_set = solve(problem, CountingMin())[]","category":"page"},{"location":"generated/DominatingSet/#Configuration-properties","page":"Dominating set problem","title":"Configuration properties","text":"","category":"section"},{"location":"generated/DominatingSet/#finding-minimum-dominating-set","page":"Dominating set problem","title":"finding minimum dominating set","text":"","category":"section"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"One can enumerate all minimum dominating sets with the ConfigsMin property in the program.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"min_configs = read_config(solve(problem, ConfigsMin())[])\n\nall(c->is_dominating_set(graph, c), min_configs)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"show_configs(graph, locations, reshape(collect(min_configs), 2, 5); padding_left=20)","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"Similarly, if one is only interested in computing one of the minimum dominating sets, one can use the graph property SingleConfigMin.","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"","category":"page"},{"location":"generated/DominatingSet/","page":"Dominating set problem","title":"Dominating set problem","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"EditURL = \"../../../examples/weighted.jl\"","category":"page"},{"location":"generated/weighted/#Weighted-problems","page":"Weighted problems","title":"Weighted problems","text":"","category":"section"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"Let us use the maximum independent set problem on Petersen graph as an example.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions, Graphs\n\ngraph = Graphs.smallgraph(:petersen)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The following code constructs a weighted MIS problem instance.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"problem = GenericTensorNetwork(IndependentSet(graph, collect(1:10)));\nGenericTensorNetworks.weights(problem)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The tensor labels that associated with the weights can be accessed by","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"ProblemReductions.local_solution_spec(problem.problem)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"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. For example, the maximum independent set can be found as follows.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"max_config_weighted = solve(problem, SingleConfigMax())[]","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"Let us visualize the solution.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a\nlocations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]\nshow_graph(graph, locations; format=:svg, vertex_colors=\n [iszero(max_config_weighted.c.data[i]) ? \"white\" : \"red\" for i=1:nv(graph)])","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The only solution space property that can not be defined for general real-weighted (not including integer-weighted) graphs is the GraphPolynomial.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"For the weighted MIS problem, a useful solution space property is the \"energy spectrum\", i.e. the largest several configurations and their weights. We can use the solution space property is SizeMax(10) to compute the largest 10 weights.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"spectrum = solve(problem, SizeMax(10))[]","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The return value has type ExtendedTropical, which contains one field orders.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"spectrum.orders","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"We can see the order is a vector of Tropical numbers. Similarly, we can get weighted independent sets with maximum 5 sizes as follows.","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"max5_configs = read_config(solve(problem, SingleConfigMax(5))[])","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"The return value of solve has type ExtendedTropical, but this time the element type of orders has been changed to CountingTropical{Float64,ConfigSampler}. Let us visually check these configurations","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"show_configs(graph, locations, [max5_configs[j] for i=1:1, j=1:5]; padding_left=20)","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"","category":"page"},{"location":"generated/weighted/","page":"Weighted problems","title":"Weighted problems","text":"This page was generated using Literate.jl.","category":"page"},{"location":"ref/#References","page":"References","title":"References","text":"","category":"section"},{"location":"ref/#Constraint-Satisfaction-Problems","page":"References","title":"Constraint Satisfaction Problems","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"solve\nGenericTensorNetwork\nConstraintSatisfactionProblem\nIndependentSet\nMaximalIS\nMatching\nColoring\nDominatingSet\nSpinGlass\nMaxCut\nPaintShop\nSatisfiability\nSetCovering\nSetPacking","category":"page"},{"location":"ref/#GenericTensorNetworks.solve","page":"References","title":"GenericTensorNetworks.solve","text":"solve(problem, property; usecuda=false, T=Float64)\n\nSolving a certain property of a graph problem.\n\nPositional Arguments\n\nproblem is the graph problem with tensor network information,\nproperty is string specifying the task. Using the maximum independent set problem as an example, it can be one of\nPartitionFunction() for computing the partition function,\nSizeMax(k=Single) for finding maximum-k set sizes,\nSizeMin(k=Single) for finding minimum-k set sizes,\nCountingMax(k=Single) for counting configurations with maximum-k sizes,\nCountingMin(k=Single) for counting configurations with minimum-k sizes,\nCountingAll() for counting all configurations,\nPartitionFunction() for counting all configurations,\nGraphPolynomial(; method=:finitefield, kwargs...) for evaluating the graph polynomial,\nSingleConfigMax(k=Single; bounded=false) for finding one maximum-k configuration for each size,\nSingleConfigMin(k=Single; bounded=false) for finding one minimum-k configuration for each size,\nConfigsMax(k=Single; bounded=true, tree_storage=false) for enumerating configurations with maximum-k sizes,\nConfigsMin(k=Single; bounded=true, tree_storage=false) for enumerating configurations with minimum-k sizes,\nConfigsAll(; tree_storage=false) for enumerating all configurations,\n\nKeyword arguments\n\nusecuda is a switch to use CUDA (if possible), user need to call statement using CUDA before turning on this switch.\nT is the \"base\" element type, sometimes can be used to reduce the memory cost.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.GenericTensorNetwork","page":"References","title":"GenericTensorNetworks.GenericTensorNetwork","text":"struct GenericTensorNetwork{CFG, CT, LT}\n\nGenericTensorNetwork(problem::ConstraintSatisfactionProblem; openvertices=(), fixedvertices=Dict(), optimizer=GreedyMethod())\n\nThe generic tensor network that generated from a ConstraintSatisfactionProblem.\n\nPositional arguments\n\nproblem is the graph problem.\ncode is the tensor network contraction code.\nfixedvertices is a dictionary specifying the fixed dimensions.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.ConstraintSatisfactionProblem","page":"References","title":"ProblemReductions.ConstraintSatisfactionProblem","text":"ConstraintSatisfactionProblem{T} <: AbstractProblem\n\nThe abstract base type of constraint satisfaction problems. T is the type of the local size of the constraints.\n\nRequired interfaces\n\nhard_constraints, the specification of the hard constraints. Once the hard constraints are violated, the size goes to infinity.\nis_satisfied, check if the hard constraints are satisfied.\nlocal_solution_spec, the specification of the size terms as soft constraints, which is associated with weights.\nweights: The weights of the soft constraints.\nset_weights: Change the weights for the problem and return a new problem instance.\nsolution_size, the size of the problem given a configuration.\nenergy_mode, the definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.IndependentSet","page":"References","title":"ProblemReductions.IndependentSet","text":"struct IndependentSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nIndependentSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(nv(graph))) -> IndependentSet\n\nIndependent 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.\n\nFields\n\ngraph::AbstractGraph: The problem graph.\nweights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(nv(graph)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))\n{4, 4} undirected simple Int64 graph\n\njulia> IS = IndependentSet(graph)\nIndependentSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, 1, 1, 1])\n\njulia> num_variables(IS) # degrees of freedom\n4\n\njulia> flavors(IS) # flavors of the vertices\n(0, 1)\n\njulia> solution_size(IS, [1, 0, 0, 1]) # Positive sample: -(size) of an independent set\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(IS, [0, 1, 1, 0]) # Negative sample: 0\nSolutionSize{Int64}(2, false)\n\njulia> findbest(IS, BruteForce()) # solve the problem with brute force\n2-element Vector{Vector{Int64}}:\n [1, 0, 0, 1]\n [0, 1, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.MaximalIS","page":"References","title":"ProblemReductions.MaximalIS","text":"struct MaximalIS{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nMaximal 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.\n\nFields\n\ngraph is the problem graph.\nweights are associated with the vertices of the graph.\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3), (1, 4)]))\n{4, 5} undirected simple Int64 graph\n\njulia> problem = MaximalIS(graph)\nMaximalIS{Int64, UnitWeight}(SimpleGraph{Int64}(5, [[2, 3, 4], [1, 3], [1, 2, 4], [1, 3]]), [1, 1, 1, 1])\n\njulia> num_variables(problem) # degrees of freedom\n4\n\njulia> flavors(problem)\n(0, 1)\n\njulia> solution_size(problem, [0, 1, 0, 0]) # unlike the independent set, this configuration is not a valid solution\nSolutionSize{Int64}(1, false)\n\njulia> findbest(problem, BruteForce())\n1-element Vector{Vector{Int64}}:\n [0, 1, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Matching","page":"References","title":"ProblemReductions.Matching","text":"struct Matching{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nThe Vertex matching problem.\n\nPositional arguments\n\ngraph is the problem graph.\nweights are associated with the edges of the graph.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Coloring","page":"References","title":"ProblemReductions.Coloring","text":"struct Coloring{K, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nColoring{K}(graph; weights=UnitWeight(nv(graph)))\n\nThe 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.\n\nFields\n\ngraph is the problem graph.\nweights are associated with the edges of the graph, default to UnitWeight(ne(graph)).\n\nExample\n\nTo initialize a Coloring problem, we need to first define a graph and decide the number of colors.\n\njulia> using ProblemReductions, Graphs\n\njulia> g = smallgraph(:petersen) # define a simple graph, petersen as example\n{10, 15} undirected simple Int64 graph\n\njulia> coloring = Coloring{3}(g) # 3 colors\nColoring{3, Int64, UnitWeight}(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])\n\njulia> variables(coloring)\n1:10\n\njulia> flavors(coloring)\n(0, 1, 2)\n\njulia> is_vertex_coloring(coloring.graph,[1,2,3,1,3,2,1,2,3,1]) #random assignment\nfalse\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.DominatingSet","page":"References","title":"ProblemReductions.DominatingSet","text":"struct DominatingSet{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nDominatingSet(graph::AbstractGraph, weights::AbstractVector=UnitWeight(ne(graph))) -> DominatingSet\n\nDominaing 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.\n\nFields\n\ngraph is the problem graph.\nweights::AbstractVector: Weights associated with the vertices of the graph. Defaults to UnitWeight(nv(graph)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, Graphs\n\njulia> graph = path_graph(5)\n{5, 4} undirected simple Int64 graph\n\njulia> DS = DominatingSet(graph)\nDominatingSet{SimpleGraph{Int64}, Int64, UnitWeight}(SimpleGraph{Int64}(4, [[2], [1, 3], [2, 4], [3, 5], [4]]), [1, 1, 1, 1, 1])\n\njulia> variables(DS) # degrees of freedom\n1:5\n\njulia> flavors(DS) # flavors of the vertices\n(0, 1)\n\njulia> solution_size(DS, [0, 1, 0, 1, 0]) # Positive sample: (size) of a dominating set\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(DS, [0, 1, 1, 0, 0]) # Negative sample: number of vertices\nSolutionSize{Int64}(2, false)\n\njulia> findbest(DS, BruteForce()) # solve the problem with brute force\n3-element Vector{Vector{Int64}}:\n [1, 0, 0, 1, 0]\n [0, 1, 0, 1, 0]\n [0, 1, 0, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SpinGlass","page":"References","title":"ProblemReductions.SpinGlass","text":"struct SpinGlass{GT<:Graphs.AbstractGraph, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nSpinGlass(graph::AbstractGraph, weights::AbstractVector)\nSpinGlass(graph::SimpleGraph, J, h=zeros(nv(graph)))\n\nSpin Glass is a type of disordered magnetic system that exhibits a glassy behavior. The Hamiltonian of the system on a simple graph G is given by\n\nH(G sigma) = sum_(ij) in E(G) J_ij sigma_i sigma_j + sum_i in V(G) h_i sigma_i\n\nwhere J_ij in mathbbR is the coupling strength between spins i and j, h_i in mathbbR is the external field on spin i, and sigma_i is the spin variable that can take values in -1 1 for spin up and spin down, respectively.\n\nThis definition naturally extends to the case of a HyperGraph:\n\nH(G sigma) = sum_e in E(G) J_e prod_ksigma_k + sum_i in V(G) h_i sigma_i\n\nwhere J_e is the coupling strength associated with hyperedge e, and the product is over all spins in the hyperedge.\n\nFields\n\ngraph is a graph object.\nJ are the coupling strengths associated with the edges.\nh are the external fields associated with the vertices.\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions, ProblemReductions.Graphs\n\njulia> graph = SimpleGraph(Graphs.SimpleEdge.([(1, 2), (1, 3), (3, 4), (2, 3)]))\n{4, 4} undirected simple Int64 graph\n\njulia> J = [1, -1, 1, -1] # coupling strength\n4-element Vector{Int64}:\n 1\n -1\n 1\n -1\n\njulia> h = [1, -1, -1, 1] # external field\n4-element Vector{Int64}:\n 1\n -1\n -1\n 1\n\njulia> spinglass = SpinGlass(graph, J, h) # Define a spin glass problem\nSpinGlass{SimpleGraph{Int64}, Int64, Vector{Int64}}(SimpleGraph{Int64}(4, [[2, 3], [1, 3], [1, 2, 4], [3]]), [1, -1, 1, -1], [1, -1, -1, 1])\n\njulia> num_variables(spinglass) # degrees of freedom\n4\n\njulia> flavors(spinglass) # flavors of the spins\n(1, -1)\n\njulia> solution_size(spinglass, [-1, 1, 1, -1]) # size of a configuration\nSolutionSize{Int64}(-2, true)\n\njulia> findbest(spinglass, BruteForce()) # solve the problem with brute force\n1-element Vector{Vector{Int64}}:\n [-1, 1, -1, -1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.MaxCut","page":"References","title":"ProblemReductions.MaxCut","text":"struct MaxCut{T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nMax 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.\n\nPositional arguments\n\ngraph is the problem graph.\nweights are associated with the edges of the graph. We have ensure that the weights are in the same order as the edges in edges(graph).\n\nExample\n\nIn the following example, we solve a Max Cut problem on a complete graph with 3 vertices and edge weights [1,2,3].\n\njulia> using ProblemReductions, Graphs\n\njulia> g = complete_graph(3)\n{3, 3} undirected simple Int64 graph\n\njulia> maxcut = MaxCut(g,[1,2,3]) # specify the weights of the edges\nMaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [1, 2, 3])\n\njulia> mc = set_weights(maxcut, [2,1,3]) # set the weights and get a new instance\nMaxCut{Int64, Vector{Int64}}(SimpleGraph{Int64}(3, [[2, 3], [1, 3], [1, 2]]), [2, 1, 3])\n\n\njulia> num_variables(maxcut) # return the number of vertices\n3\n\njulia> flavors(maxcut) # return the flavors of the vertices\n(0, 1)\n\njulia> solution_size(maxcut, [0,1,0]) # return the size of the configuration\nSolutionSize{Int64}(4, true)\n\njulia> findbest(maxcut, BruteForce()) # find the best configuration\n2-element Vector{Vector{Int64}}:\n [1, 1, 0]\n [0, 0, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.PaintShop","page":"References","title":"ProblemReductions.PaintShop","text":"struct PaintShop{LT} <: ConstraintSatisfactionProblem{Int64}\n\nThe 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.\n\nFields\n\nsequence is a vector of symbols, each symbol is associated with a color.\nisfirst is a vector of boolean numbers, indicating whether the symbol is the first appearance in the sequence.\n\nExample\n\nIn the following example, we define a paint shop problem with 6 cars.\n\njulia> using ProblemReductions\n\njulia> problem = PaintShop([\"a\",\"b\",\"a\",\"c\",\"c\",\"b\"])\nPaintShop{String}([\"a\", \"b\", \"a\", \"c\", \"c\", \"b\"], Bool[1, 1, 0, 1, 0, 0])\n\njulia> num_variables(problem)\n3\n\njulia> flavors(problem)\n(0, 1)\n\njulia> solution_size(problem, [0, 1, 0])\nSolutionSize{Int64}(4, true)\n\njulia> findbest(problem, BruteForce())\n2-element Vector{Vector{Int64}}:\n [1, 0, 0]\n [0, 1, 1]\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.Satisfiability","page":"References","title":"ProblemReductions.Satisfiability","text":"struct Satisfiability{S, T, WT<:(AbstractArray{T})} <: ProblemReductions.AbstractSatisfiabilityProblem{S, T}\n\nSatisfiability (also called SAT) problem is to find the boolean assignment that satisfies a Conjunctive Normal Form (CNF). A tipical CNF would look like:\n\nleft(l_11 vee ldots vee l_1 n_1right) wedge ldots wedgeleft(l_m 1 vee ldots vee l_m n_mright)\n\nwhere literals are joint by vee to for m clauses and clauses are joint by wedge to form a CNF.\n\nWe 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.\n\nFields\n\ncnf is a conjunctive normal form (CNF) for specifying the satisfiability problems.\nweights are associated with clauses.\n\nExample\n\nIn the following example, we define a satisfiability problem with two clauses.\n\njulia> using ProblemReductions\n\njulia> bv1, bv2, bv3 = BoolVar.([\"x\", \"y\", \"z\"])\n3-element Vector{BoolVar{String}}:\n x\n y\n z\n\njulia> clause1 = CNFClause([bv1, bv2, bv3])\nx ∨ y ∨ z\n\njulia> clause2 = CNFClause([BoolVar(\"w\"), bv1, BoolVar(\"x\", true)])\nw ∨ x ∨ ¬x\n\njulia> cnf_test = CNF([clause1, clause2])\n(x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x)\n\njulia> sat_test = Satisfiability(cnf_test)\nSatisfiability{String, Int64, UnitWeight}([\"x\", \"y\", \"z\", \"w\"], [1, 1], (x ∨ y ∨ z) ∧ (w ∨ x ∨ ¬x))\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SetCovering","page":"References","title":"ProblemReductions.SetCovering","text":"struct SetCovering{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nThe 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.\n\nPositional arguments\n\nelements is a vector of elements in the universe.\nsets is a vector of vectors, a collection of subsets of universe , each set is associated with a weight specified in weights.\nweights are associated with sets.\n\nExample\n\nIn the following example, we solve a Set Covering problem with 3 subsets and weights [1,2,3].\n\njulia> using ProblemReductions\n\njulia> subsets = [[1, 2, 3], [2, 4], [1, 4]]\n3-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [2, 4]\n [1, 4]\n\njulia> weights = [1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> setcovering = SetCovering(subsets, weights)\nSetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])\n\njulia> num_variables(setcovering) # degrees of freedom\n3\n\njulia> solution_size(setcovering, [1, 0, 1]) # size of a configuration\nSolutionSize{Int64}(4, true)\n\njulia> solution_size(setcovering, [0, 1, 1])\nSolutionSize{Int64}(5, false)\n\njulia> sc = set_weights(setcovering, [1, 2, 3]) # set the weights of the subsets\nSetCovering{Int64, Int64, Vector{Int64}}([1, 2, 3, 4], [[1, 2, 3], [2, 4], [1, 4]], [1, 2, 3])\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SetPacking","page":"References","title":"ProblemReductions.SetPacking","text":"struct SetPacking{ET, T, WT<:AbstractArray{T, 1}} <: ConstraintSatisfactionProblem{T}\n\nSetPacking(elements::AbstractVector, sets::AbstractVector, weights::AbstractVector=UnitWeight(length(sets))) -> SetPacking\n\nA 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.\n\nFields\n\nelements is a vector of elements in the universe.\nsets is a vector of vectors, each set is associated with a weight specified in weights.\nweights are associated with sets. Defaults to UnitWeight(length(sets)).\n\nExample\n\nIn 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.\n\njulia> using ProblemReductions\n\njulia> sets = [[1, 2, 5], [1, 3], [2, 4], [3, 6], [2, 3, 6]]\n5-element Vector{Vector{Int64}}:\n [1, 2, 5]\n [1, 3]\n [2, 4]\n [3, 6]\n [2, 3, 6]\n\njulia> SP = SetPacking(sets)\nSetPacking{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])\n\njulia> num_variables(SP) # degrees of freedom\n5\n\njulia> flavors(SP) # flavors of the subsets\n(0, 1)\n\njulia> solution_size(SP, [1, 0, 0, 1, 0]) # Positive sample: -(size) of a packing\nSolutionSize{Int64}(2, true)\n\njulia> solution_size(SP, [1, 0, 1, 1, 0]) # Negative sample: 0\nSolutionSize{Int64}(3, false)\n\njulia> findbest(SP, BruteForce()) # solve the problem with brute force\n3-element Vector{Vector{Int64}}:\n [0, 1, 1, 0, 0]\n [1, 0, 0, 1, 0]\n [0, 0, 1, 1, 0]\n\n\n\n\n\n","category":"type"},{"location":"ref/#Constraint-Satisfaction-Problem-Interfaces","page":"References","title":"Constraint Satisfaction Problem Interfaces","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"To subtype ConstraintSatisfactionProblem, a new type must contain a code field to represent the (optimized) tensor network. Interfaces GenericTensorNetworks.generate_tensors, flavors and weights are required. num_flavors is optional.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks.generate_tensors\nflavors\nweights\nset_weights\nis_weighted\nnum_flavors\nfixedvertices","category":"page"},{"location":"ref/#GenericTensorNetworks.generate_tensors","page":"References","title":"GenericTensorNetworks.generate_tensors","text":"generate_tensors(func, problem::GenericTensorNetwork)\n\nGenerate 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.\n\nExample\n\nThe following code gives your the maximum independent set size\n\njulia> using Graphs, GenericTensorNetworks\n\njulia> gp = GenericTensorNetwork(IndependentSet(smallgraph(:petersen)));\n\njulia> getixsv(gp.code)\n25-element Vector{Vector{Int64}}:\n [1, 2]\n [1, 5]\n [1, 6]\n [2, 3]\n [2, 7]\n [3, 4]\n [3, 8]\n [4, 5]\n [4, 9]\n [5, 10]\n ⋮\n [2]\n [3]\n [4]\n [5]\n [6]\n [7]\n [8]\n [9]\n [10]\n\njulia> gp.code(GenericTensorNetworks.generate_tensors(Tropical(1.0), gp)...)\n0-dimensional Array{Tropical{Float64}, 0}:\n4.0ₜ\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.flavors","page":"References","title":"ProblemReductions.flavors","text":"flavors(::Type{<:AbstractProblem}) -> Vector\n\nReturns a vector of integers as the flavors (domain) of a degree of freedom.\n\n\n\n\n\nflavors(::Type{<:GenericTensorNetwork}) -> Vector\n\nIt 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.weights","page":"References","title":"ProblemReductions.weights","text":"weights(problem::ConstraintSatisfactionProblem) -> Vector\n\nThe weights of the constraints in the problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.set_weights","page":"References","title":"ProblemReductions.set_weights","text":"set_weights(problem::ConstraintSatisfactionProblem, weights) -> ConstraintSatisfactionProblem\n\nChange the weights for the problem and return a new problem instance.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_weighted","page":"References","title":"ProblemReductions.is_weighted","text":"is_weighted(problem::ConstraintSatisfactionProblem) -> Bool\n\nCheck if the problem is weighted. Returns true if the problem has non-unit weights.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.num_flavors","page":"References","title":"ProblemReductions.num_flavors","text":"num_flavors(::Type{<:AbstractProblem}) -> Int\nnum_flavors(::GT) where GT<:AbstractProblem -> Int\n\nReturns the number of flavors (domain) of a degree of freedom.\n\n\n\n\n\nnum_flavors(::GenericTensorNetwork{GT}) where GT<:ConstraintSatisfactionProblem -> Int\n\nBond size is equal to the number of flavors.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.fixedvertices","page":"References","title":"GenericTensorNetworks.fixedvertices","text":"fixedvertices(tnet::GenericTensorNetwork) -> Dict\n\nReturns the fixed vertices in the graph problem, which is a dictionary specifying the fixed dimensions.\n\n\n\n\n\n","category":"function"},{"location":"ref/#Constraint-Satisfaction-Problem-Utilities","page":"References","title":"Constraint Satisfaction Problem Utilities","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"hard_constraints\nis_satisfied\nlocal_solution_spec\nsolution_size\nenergy_mode\nLargerSizeIsBetter\nSmallerSizeIsBetter\nenergy\n\nis_independent_set\nis_maximal_independent_set\nis_dominating_set\nis_vertex_coloring\nis_matching\nis_set_covering\nis_set_packing\n\ncut_size\nnum_paint_shop_color_switch\n\nCNF\nCNFClause\nBoolVar\nsatisfiable\n@bools\n∨\n¬\n∧\n\nmis_compactify!","category":"page"},{"location":"ref/#ProblemReductions.hard_constraints","page":"References","title":"ProblemReductions.hard_constraints","text":"hard_constraints(problem::AbstractProblem) -> Vector{HardConstraint}\n\nThe hard constraints of the problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_satisfied","page":"References","title":"ProblemReductions.is_satisfied","text":"is_satisfied(::Type{<:ConstraintSatisfactionProblem}, constraint::HardConstraint, config) -> Bool\n\nCheck if the constraint is satisfied by the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.local_solution_spec","page":"References","title":"ProblemReductions.local_solution_spec","text":"local_solution_spec(problem::AbstractProblem) -> Vector{LocalSolutionSpec}\n\nThe constraints related to the size of the problem. Each term is associated with weights.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.solution_size","page":"References","title":"ProblemReductions.solution_size","text":"solution_size(problem::AbstractProblem, config) -> SolutionSize\n\nSize of the problem given the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.energy_mode","page":"References","title":"ProblemReductions.energy_mode","text":"energy_mode(problem::AbstractProblem) -> EnergyMode\n\nThe definition of the energy function, which can be LargerSizeIsBetter or SmallerSizeIsBetter. If will be used in the energy based modeling of the target problem.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.LargerSizeIsBetter","page":"References","title":"ProblemReductions.LargerSizeIsBetter","text":"LargerSizeIsBetter <: EnergyMode\n\nThe energy is defined as the negative size of the solution, which is the larger size the lower energy.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.SmallerSizeIsBetter","page":"References","title":"ProblemReductions.SmallerSizeIsBetter","text":"SmallerSizeIsBetter <: EnergyMode\n\nThe energy is defined as the size of the solution, which is the smaller size the lower energy.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.energy","page":"References","title":"ProblemReductions.energy","text":"energy(problem::AbstractProblem, config) -> Number\n\nThe energy of the problem given the configuration config. Please check the energy_mode for the definition of the energy function.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_independent_set","page":"References","title":"ProblemReductions.is_independent_set","text":"is_independent_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is an independent set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_maximal_independent_set","page":"References","title":"ProblemReductions.is_maximal_independent_set","text":"is_maximal_independent_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is a maximal independent set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_dominating_set","page":"References","title":"ProblemReductions.is_dominating_set","text":"is_dominating_set(g::SimpleGraph, config)\n\nReturn true if config (a vector of boolean numbers as the mask of vertices) is a dominating set of graph g.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_vertex_coloring","page":"References","title":"ProblemReductions.is_vertex_coloring","text":"is_vertex_coloring(graph::SimpleGraph, config)\n\nReturns 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_matching","page":"References","title":"ProblemReductions.is_matching","text":"is_matching(graph::SimpleGraph, config)\n\nReturns 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).\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_set_covering","page":"References","title":"ProblemReductions.is_set_covering","text":"is_set_covering(c::SetCovering, config)\n\nReturn true if config (a vector of boolean numbers as the mask of sets) is a set covering of sets.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.is_set_packing","page":"References","title":"ProblemReductions.is_set_packing","text":"is_set_packing(sp::SetPacking, config)\n\nReturn true if config (a vector of boolean numbers as the mask of sets) is a set packing of sp.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.cut_size","page":"References","title":"ProblemReductions.cut_size","text":"cut_size(g::AbstractGraph, config; weights=UnitWeight(ne(g)))\n\nReturn 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.num_paint_shop_color_switch","page":"References","title":"ProblemReductions.num_paint_shop_color_switch","text":"num_paint_shop_color_switch(sequence::AbstractVector, coloring)\n\nReturns the number of color switches.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.CNF","page":"References","title":"ProblemReductions.CNF","text":"CNF{T}\nCNF(clauses)\n\nBoolean expression in conjunctive normal form. clauses is a vector of CNFClause, if and only if all clauses are satisfied, this CNF is satisfied.\n\nExample\n\nUnder development\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.CNFClause","page":"References","title":"ProblemReductions.CNFClause","text":"CNFClause{T}\nCNFClause(vars)\n\nA clause in CNF, its value is the logical or of vars, where vars is a vector of BoolVar.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.BoolVar","page":"References","title":"ProblemReductions.BoolVar","text":"BoolVar{T}\nBoolVar(name, neg)\n\nBoolean variable for constructing CNF clauses.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.satisfiable","page":"References","title":"ProblemReductions.satisfiable","text":"satisfiable(expr, config::AbstractDict{T}) where T\n\nCheck if the boolean expression expr is satisfied by the configuration config.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.@bools","page":"References","title":"ProblemReductions.@bools","text":"@bools(syms::Symbol...)\n\nCreate some boolean variables of type BoolVar in current scope that can be used in create a CNF.\n\nExample\n\nUnder Development\n\n\n\n\n\n","category":"macro"},{"location":"ref/#ProblemReductions.:∨","page":"References","title":"ProblemReductions.:∨","text":"∨(vars...)\n\nLogical or applied on BoolVar and CNFClause. Returns a CNFClause.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.:¬","page":"References","title":"ProblemReductions.:¬","text":"¬(var::BoolVar)\n\nNegation of a boolean variables of type BoolVar.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.:∧","page":"References","title":"ProblemReductions.:∧","text":"∧(vars...)\n\nLogical and applied on CNFClause and CNF. Returns a new CNF.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.mis_compactify!","page":"References","title":"GenericTensorNetworks.mis_compactify!","text":"mis_compactify!(tropicaltensor; potential=nothing)\n\nCompactify 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).\n\nArguments\n\ntropicaltensor::AbstractArray{T}: the tropical tensor\n\nKeyword arguments\n\npotential=nothing: the maximum possible MIS contribution from each open vertex\n\n\n\n\n\n","category":"function"},{"location":"ref/#Properties","page":"References","title":"Properties","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"PartitionFunction\nSizeMax\nSizeMin\nCountingAll\nCountingMax\nCountingMin\nGraphPolynomial\nSingleConfigMax\nSingleConfigMin\nConfigsAll\nConfigsMax\nConfigsMin","category":"page"},{"location":"ref/#GenericTensorNetworks.PartitionFunction","page":"References","title":"GenericTensorNetworks.PartitionFunction","text":"struct PartitionFunction{T} <: GenericTensorNetworks.AbstractProperty\n\nbeta\n\nCompute the partition function for the target problem.\n\nThe corresponding tensor element type is T.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SizeMax","page":"References","title":"GenericTensorNetworks.SizeMax","text":"SizeMax{K} <: AbstractProperty\nSizeMax(k::Int)\n\nThe maximum-K set sizes. e.g. the largest size of the IndependentSet problem is also know as the independence number.\n\nThe corresponding tensor element type are max-plus tropical number Tropical if K is Single and ExtendedTropical if K is an integer.\nIt is compatible with weighted Constraint Satisfaction Problems.\nBLAS (on CPU) and GPU are supported only if K is Single,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SizeMin","page":"References","title":"GenericTensorNetworks.SizeMin","text":"SizeMin{K} <: AbstractProperty\nSizeMin(k::Int)\n\nThe minimum-K set sizes. e.g. the smallest size ofthe MaximalIS problem is also known as the independent domination number.\n\nThe corresponding tensor element type are inverted max-plus tropical number Tropical if K is Single and inverted ExtendedTropical K is an integer.\n\nThe inverted Tropical number emulates the min-plus tropical number.\n\nIt is compatible with weighted constraint satisfaction problems.\nBLAS (on CPU) and GPU are supported only if K is Single,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingAll","page":"References","title":"GenericTensorNetworks.CountingAll","text":"CountingAll <: AbstractProperty\nCountingAll()\n\nCounting 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.\n\nThe corresponding tensor element type is BigInt.\nThe weights on graph does not have effect.\nBLAS (GPU and CPU) and GPU are supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingMax","page":"References","title":"GenericTensorNetworks.CountingMax","text":"CountingMax{K} <: AbstractProperty\nCountingMax(K=Single)\n\nCounting 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.\n\nThe corresponding tensor element type is CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.\nWeighted constraint satisfaction problems is only supported if K is Single.\nGPU is supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.CountingMin","page":"References","title":"GenericTensorNetworks.CountingMin","text":"CountingMin{K} <: AbstractProperty\nCountingMin(K=Single)\n\nCounting the number of sets with smallest-K size.\n\nThe corresponding tensor element type is inverted CountingTropical if K is Single, and TruncatedPoly{K} if K is an integer.\nWeighted constraint satisfaction problems is only supported if K is Single.\nGPU is supported,\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.GraphPolynomial","page":"References","title":"GenericTensorNetworks.GraphPolynomial","text":"GraphPolynomial{METHOD} <: AbstractProperty\nGraphPolynomial(; method=:finitefield, kwargs...)\n\nCompute the graph polynomial, e.g. for IndependentSet problem, it is the independence polynomial. The METHOD type parameter can be one of the following symbols\n\nMethod Argument\n\n:finitefield, uses finite field algebra to fit the polynomial.\nThe corresponding tensor element type is Mods.Mod,\nIt does not have round-off error,\nGPU is supported,\nIt accepts keyword arguments maxorder (optional, e.g. the MIS size in the IndependentSet problem).\n:polynomial and :laurent, use (Laurent) polynomial numbers to solve the polynomial directly.\nThe corresponding tensor element types are Polynomial and LaurentPolynomial.\nIt might have small round-off error depending on the data type for storing the counting.\nIt has memory overhead that linear to the graph size.\n:fft, use fast fourier transformation to fit the polynomial.\nThe corresponding tensor element type is Base.Complex.\nIt has (controllable) round-off error.\nBLAS and GPU are supported.\nIt accepts keyword arguments maxorder (optional) and r, if r > 1, one has better precision for coefficients of large order, if r < 1, one has better precision for coefficients of small order.\n:fitting, fit the polynomial directly.\nThe corresponding tensor element type is floating point numbers like Base.Float64.\nIt has round-off error.\nBLAS and GPU are supported, it is the fastest among all methods.\n\nGraph polynomials are not defined for weighted constraint satisfaction problems.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SingleConfigMax","page":"References","title":"GenericTensorNetworks.SingleConfigMax","text":"SingleConfigMax{K, BOUNDED} <: AbstractProperty\nSingleConfigMax(k::Int; bounded=false)\n\nFinding single solution for largest-K sizes, e.g. for IndependentSet problem, it is one of the maximum independent sets.\n\nThe corresponding data type is CountingTropical{Float64,<:ConfigSampler} if BOUNDED is false, Tropical otherwise.\nWeighted constraint satisfaction problems is supported.\nGPU is supported,\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SingleConfigMin","page":"References","title":"GenericTensorNetworks.SingleConfigMin","text":"SingleConfigMin{K, BOUNDED} <: AbstractProperty\nSingleConfigMin(k::Int; bounded=false)\n\nFinding single solution with smallest-K size.\n\nThe corresponding data type is inverted CountingTropical{Float64,<:ConfigSampler} if BOUNDED is false, inverted Tropical otherwise.\nWeighted constraint satisfaction problems is supported.\nGPU is supported,\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsAll","page":"References","title":"GenericTensorNetworks.ConfigsAll","text":"ConfigsAll{TREESTORAGE} <:AbstractProperty\nConfigsAll(; tree_storage=false)\n\nFind all valid configurations, e.g. for IndependentSet problem, it is finding all independent sets.\n\nThe corresponding data type is ConfigEnumerator.\nWeights do not take effect.\n\nKeyword Arguments\n\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsMax","page":"References","title":"GenericTensorNetworks.ConfigsMax","text":"ConfigsMax{K, BOUNDED, TREESTORAGE} <:AbstractProperty\nConfigsMax(K=Single; bounded=true, tree_storage=true)\n\nFind 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.\n\nThe corresponding data type is CountingTropical{Float64,<:ConfigEnumerator} if K is Single and TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.\nWeighted constraint satisfaction problem is only supported if K is Single.\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigsMin","page":"References","title":"GenericTensorNetworks.ConfigsMin","text":"ConfigsMin{K, BOUNDED, TREESTORAGE} <:AbstractProperty\nConfigsMin(K=Single; bounded=true, tree_storage=false)\n\nFind configurations with smallest-K sizes.\n\nThe corresponding data type is inverted CountingTropical{Float64,<:ConfigEnumerator} if K is Single and inverted TruncatedPoly{K,<:ConfigEnumerator} if K is an integer.\nWeighted constraint satisfaction problem is only supported if K is Single.\n\nKeyword Arguments\n\nbounded, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.\ntree_storage, if it is true, it uses more memory efficient tree-structure to store the configurations.\n\n\n\n\n\n","category":"type"},{"location":"ref/#Element-Algebras","page":"References","title":"Element Algebras","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"is_commutative_semiring","category":"page"},{"location":"ref/#GenericTensorNetworks.is_commutative_semiring","page":"References","title":"GenericTensorNetworks.is_commutative_semiring","text":"is_commutative_semiring(a::T, b::T, c::T) where T\n\nCheck if elements a, b and c satisfied the commutative semiring requirements.\n\nbeginalign*\n(a oplus b) oplus c = a oplus (b oplus c) hspace5emtrianglerighttextcommutative monoid oplus with identity mathbb0\na oplus mathbb0 = mathbb0 oplus a = a \na oplus b = b oplus a \n\n(a odot b) odot c = a odot (b odot c) hspace5emtriangleright textcommutative monoid odot with identity mathbb1\na odot mathbb1 = mathbb1 odot a = a \na odot b = b odot a \n\na odot (boplus c) = aodot b oplus aodot c hspace5emtriangleright textleft and right distributive\n(aoplus b) odot c = aodot c oplus bodot c \n\na odot mathbb0 = mathbb0 odot a = mathbb0\nendalign*\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"TropicalNumbers.Tropical\nTropicalNumbers.CountingTropical\nExtendedTropical\nGenericTensorNetworks.Mods.Mod\nTruncatedPoly\nMax2Poly\nConfigEnumerator\nSumProductTree\nConfigSampler","category":"page"},{"location":"ref/#TropicalNumbers.Tropical","page":"References","title":"TropicalNumbers.Tropical","text":"TropicalMaxPlus{T} = Tropical{T} <: AbstractSemiring\n\nTropicalMaxPlus is a semiring algebra, can be described by\n\nTropical (TropicalMaxPlus), (ℝ, max, +, -Inf, 0).\n\nIt maps\n\n+ to max in regular algebra,\n* to + in regular algebra,\n1 to 0 in regular algebra,\n0 to -Inf in regular algebra (for integer content types, this is chosen as a small integer).\n\nExample\n\njulia> TropicalMaxPlus(1.0) + TropicalMaxPlus(3.0)\n3.0ₜ\n\njulia> TropicalMaxPlus(1.0) * TropicalMaxPlus(3.0)\n4.0ₜ\n\njulia> one(TropicalMaxPlusF64)\n0.0ₜ\n\njulia> zero(TropicalMaxPlusF64)\n-Infₜ\n\n\n\n\n\n","category":"type"},{"location":"ref/#TropicalNumbers.CountingTropical","page":"References","title":"TropicalNumbers.CountingTropical","text":"CountingTropical{T,CT} <: Number\n\nCounting 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.\n\nExample\n\njulia> CountingTropical(1.0, 5.0) + CountingTropical(3.0, 2.0)\n(3.0, 2.0)ₜ\n\njulia> CountingTropical(1.0, 5.0) * CountingTropical(3.0, 2.0)\n(4.0, 10.0)ₜ\n\njulia> one(CountingTropicalF64)\n(0.0, 1.0)ₜ\n\njulia> zero(CountingTropicalF64)\n(-Inf, 0.0)ₜ\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ExtendedTropical","page":"References","title":"GenericTensorNetworks.ExtendedTropical","text":"ExtendedTropical{K,TO} <: Number\nExtendedTropical{K}(orders)\n\nExtended 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\n\n+ to finding largest K values of union of two sets.\n* to finding largest K values of sum combination of two sets.\n0 to set [-Inf, -Inf, ..., -Inf, -Inf]\n1 to set [-Inf, -Inf, ..., -Inf, 0]\n\nFields\n\norders is a vector of Tropical (CountingTropical) numbers as the largest-K solution sizes (solutions).\n\nExamples\n\njulia> x = ExtendedTropical{3}(Tropical.([1.0, 2, 3]))\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[1.0ₜ, 2.0ₜ, 3.0ₜ])\n\njulia> y = ExtendedTropical{3}(Tropical.([-Inf, 2, 5]))\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, 2.0ₜ, 5.0ₜ])\n\njulia> x * y\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[6.0ₜ, 7.0ₜ, 8.0ₜ])\n\njulia> x + y\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[2.0ₜ, 3.0ₜ, 5.0ₜ])\n\njulia> one(x)\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, 0.0ₜ])\n\njulia> zero(x)\nExtendedTropical{3, Tropical{Float64}}(Tropical{Float64}[-Infₜ, -Infₜ, -Infₜ])\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.Mods.Mod","page":"References","title":"GenericTensorNetworks.Mods.Mod","text":"Mod{m}(v) creates a modular number in mod m with value mod(v,m).\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.TruncatedPoly","page":"References","title":"GenericTensorNetworks.TruncatedPoly","text":"TruncatedPoly{K,T,TO} <: Number\nTruncatedPoly(coeffs::Tuple, maxorder)\n\nPolynomial truncated to largest K orders. T is the coefficients type and TO is the orders type.\n\nFields\n\ncoeffs is the largest-K coefficients of a polynomial. In GenericTensorNetworks, it can be the counting or enumeration of solutions.\nmaxorder is the order of a polynomial.\n\nExamples\n\njulia> TruncatedPoly((1,2,3), 6)\nx^4 + 2*x^5 + 3*x^6\n\njulia> TruncatedPoly((1,2,3), 6) * TruncatedPoly((5,2,1), 3)\n20*x^7 + 8*x^8 + 3*x^9\n\njulia> TruncatedPoly((1,2,3), 6) + TruncatedPoly((5,2,1), 3)\nx^4 + 2*x^5 + 3*x^6\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.Max2Poly","page":"References","title":"GenericTensorNetworks.Max2Poly","text":"Max2Poly{T,TO} = TruncatedPoly{2,T,TO}\nMax2Poly(a, b, maxorder)\n\nA shorthand of TruncatedPoly{2}.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigEnumerator","page":"References","title":"GenericTensorNetworks.ConfigEnumerator","text":"ConfigEnumerator{N,S,C} <: AbstractSetNumber\n\nSet 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`.\n\nFields\n\ndata is a vector of StaticElementVector as the solution set.\n\nExamples\n\njulia> a = ConfigEnumerator([StaticBitVector([1,1,1,0,0]), StaticBitVector([1,0,0,0,1])])\n{11100, 10001}\n\njulia> b = ConfigEnumerator([StaticBitVector([0,0,0,0,0]), StaticBitVector([1,0,1,0,1])])\n{00000, 10101}\n\njulia> a + b\n{11100, 10001, 00000, 10101}\n\njulia> one(a)\n{00000}\n\njulia> zero(a)\n{}\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.SumProductTree","page":"References","title":"GenericTensorNetworks.SumProductTree","text":"SumProductTree{ET} <: AbstractSetNumber\n\nConfiguration 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.\n\nFields\n\ntag is one of ZERO, ONE, LEAF, SUM, PROD.\ndata is the element stored in a LEAF node.\nleft and right are two operands of a SUM or PROD node.\n\nExamples\n\njulia> s = SumProductTree(bv\"00111\")\n00111\n\n\njulia> q = SumProductTree(bv\"10000\")\n10000\n\n\njulia> x = s + q\n+ (count = 2.0)\n├─ 00111\n└─ 10000\n\n\njulia> y = x * x\n* (count = 4.0)\n├─ + (count = 2.0)\n│ ├─ 00111\n│ └─ 10000\n└─ + (count = 2.0)\n ├─ 00111\n └─ 10000\n\n\njulia> collect(y)\n4-element Vector{StaticBitVector{5, 1}}:\n 00111\n 10111\n 10111\n 10000\n\njulia> zero(s)\n∅\n\n\n\njulia> one(s)\n00000\n\n\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.ConfigSampler","page":"References","title":"GenericTensorNetworks.ConfigSampler","text":"ConfigSampler{N,S,C} <: AbstractSetNumber\nConfigSampler(elements::StaticElementVector)\n\nThe 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`.\n\nnote: Note\nConfigSampler is a probabilistic commutative semiring, adding two config samplers do not give you deterministic results.\n\nFields\n\ndata is a StaticElementVector as the sampled solution.\n\nExamples\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0]))\nConfigSampler{5, 1, 1}(11100)\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0])) + ConfigSampler(StaticBitVector([1,0,1,0,0]))\nConfigSampler{5, 1, 1}(10100)\n\njulia> ConfigSampler(StaticBitVector([1,1,1,0,0])) * ConfigSampler(StaticBitVector([0,0,0,0,1]))\nConfigSampler{5, 1, 1}(11101)\n\njulia> one(ConfigSampler{5, 1, 1})\nConfigSampler{5, 1, 1}(00000)\n\njulia> zero(ConfigSampler{5, 1, 1})\nConfigSampler{5, 1, 1}(11111)\n\n\n\n\n\n","category":"type"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks also exports the Polynomial and LaurentPolynomial types defined in package Polynomials.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"For reading the properties from the above element types, one can use the following functions.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"read_size\nread_count\nread_config\nread_size_count\nread_size_config","category":"page"},{"location":"ref/#GenericTensorNetworks.read_size","page":"References","title":"GenericTensorNetworks.read_size","text":"read_size(x)\n\nRead the size information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_count","page":"References","title":"GenericTensorNetworks.read_count","text":"read_count(x)\n\nRead the counting information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_config","page":"References","title":"GenericTensorNetworks.read_config","text":"read_config(x; keeptree=false)\n\nRead the configuration information from the generic element, if keeptree=true, the tree structure will not be flattened.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_size_count","page":"References","title":"GenericTensorNetworks.read_size_count","text":"read_size_count(x)\n\nRead the size and counting information from the generic element.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.read_size_config","page":"References","title":"GenericTensorNetworks.read_size_config","text":"read_size_config(x; keeptree=false)\n\nRead the size and configuration information from the generic element. If keeptree=true, the tree structure will not be flattened.\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"The following functions are for saving and loading configurations.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"StaticBitVector\nStaticElementVector\nOnehotVec\nsave_configs\nload_configs\nsave_sumproduct\nload_sumproduct\n@bv_str\nonehotv\n\ngenerate_samples\nhamming_distribution","category":"page"},{"location":"ref/#ProblemReductions.StaticBitVector","page":"References","title":"ProblemReductions.StaticBitVector","text":"StaticBitVector{N,C} = StaticElementVector{N,1,C}\nStaticBitVector(x::AbstractVector)\n\nExamples\n\njulia> sb = StaticBitVector([1,0,0,1,1])\n10011\n\njulia> sb[3]\n0x0000000000000000\n\njulia> collect(Int, sb)\n5-element Vector{Int64}:\n 1\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.StaticElementVector","page":"References","title":"ProblemReductions.StaticElementVector","text":"StaticElementVector{N,S,C}\nStaticElementVector(nflavor::Int, x::AbstractVector)\n\nN 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.\n\nFields\n\ndata is a tuple of UInt64 for storing the configuration of static elements.\n\nExamples\n\njulia> ev = StaticElementVector(3, [1,2,0,1,2])\n12012\n\njulia> ev[2]\n0x0000000000000002\n\njulia> collect(Int, ev)\n5-element Vector{Int64}:\n 1\n 2\n 0\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.OnehotVec","page":"References","title":"GenericTensorNetworks.OnehotVec","text":"OnehotVec{N,NF}\nOnehotVec{N,NF}(loc, val)\n\nOnehot vector type, N is the number of vector length, NF is the number of flavors.\n\n\n\n\n\n","category":"type"},{"location":"ref/#GenericTensorNetworks.save_configs","page":"References","title":"GenericTensorNetworks.save_configs","text":"save_configs(filename, data::ConfigEnumerator; format=:binary)\n\nSave configurations data to file filename. The format is :binary or :text.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.load_configs","page":"References","title":"GenericTensorNetworks.load_configs","text":"load_configs(filename; format=:binary, bitlength=nothing, num_flavors=2)\n\nLoad 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.save_sumproduct","page":"References","title":"GenericTensorNetworks.save_sumproduct","text":"save_sumproduct(filename, t::SumProductTree)\n\nSerialize a sum-product tree into a file.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.load_sumproduct","page":"References","title":"GenericTensorNetworks.load_sumproduct","text":"load_sumproduct(filename)\n\nDeserialize a sum-product tree from a file.\n\n\n\n\n\n","category":"function"},{"location":"ref/#ProblemReductions.@bv_str","page":"References","title":"ProblemReductions.@bv_str","text":"Constructing a static bit vector.\n\n\n\n\n\n","category":"macro"},{"location":"ref/#ProblemReductions.onehotv","page":"References","title":"ProblemReductions.onehotv","text":"onehotv(::Type{<:StaticElementVector}, i, v)\nonehotv(::Type{<:StaticBitVector}, i)\n\nReturns a static element vector, with the value at location i being v (1 if not specified).\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.generate_samples","page":"References","title":"GenericTensorNetworks.generate_samples","text":"generate_samples(t::SumProductTree, nsamples::Int)\n\nDirect sampling configurations from a SumProductTree instance.\n\nExamples\n\njulia> using Graphs\n\njulia> g= smallgraph(:petersen)\n{10, 15} undirected simple Int64 graph\n\njulia> t = solve(GenericTensorNetwork(IndependentSet(g)), ConfigsAll(; tree_storage=true))[];\n\njulia> samples = generate_samples(t, 1000);\n\njulia> all(s->is_independent_set(g, s), samples)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.hamming_distribution","page":"References","title":"GenericTensorNetworks.hamming_distribution","text":"hamming_distribution(S, T)\n\nCompute the distribution of pair-wise Hamming distances, which is defined as:\n\nc(k) = sum_sigmain S tauin T delta(rm dist(sigma tau) k)\n\nwhere delta is a function that returns 1 if two arguments are equivalent, 0 otherwise, rm dist is the Hamming distance function.\n\nReturns the counting as a vector.\n\n\n\n\n\n","category":"function"},{"location":"ref/#Tensor-Network","page":"References","title":"Tensor Network","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"optimize_code\ngetixsv\ngetiyv\ncontraction_complexity\nestimate_memory\n@ein_str\nGreedyMethod\nTreeSA\nSABipartite\nKaHyParBipartite\nMergeVectors\nMergeGreedy","category":"page"},{"location":"ref/#OMEinsumContractionOrders.optimize_code","page":"References","title":"OMEinsumContractionOrders.optimize_code","text":"optimize_code(eincode, size_dict, optimizer = GreedyMethod(), simplifier=nothing, permute=true) -> optimized_eincode\n\nOptimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum instance. Input arguments are\n\neincode is an einsum contraction code instance, one of DynamicEinCode, StaticEinCode or NestedEinsum.\nsize is a dictionary of \"edge label=>edge size\" that contains the size information, one can use uniformsize(eincode, 2) to create a uniform size.\noptimizer is a CodeOptimizer instance, should be one of GreedyMethod, ExactTreewidth, KaHyParBipartite, SABipartite or TreeSA. Check their docstrings for details.\nsimplifier is one of MergeVectors or MergeGreedy.\noptimize the permutation if permute is true.\n\nExamples\n\njulia> using OMEinsum\n\njulia> code = ein\"ij, jk, kl, il->\"\nij, jk, kl, il -> \n\njulia> optimize_code(code, uniformsize(code, 2), TreeSA())\nSlicedEinsum{Char, NestedEinsum{DynamicEinCode{Char}}}(Char[], ki, ki -> \n├─ jk, ij -> ki\n│ ├─ jk\n│ └─ ij\n└─ kl, il -> ki\n ├─ kl\n └─ il\n)\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.getixsv","page":"References","title":"OMEinsum.getixsv","text":"getixsv(code)\n\nGet labels of input tensors for EinCode, NestedEinsum and some other einsum like objects. Returns a vector of vectors.\n\njulia> getixsv(ein\"(ij,jk),k->i\")\n3-element Vector{Vector{Char}}:\n ['i', 'j']\n ['j', 'k']\n ['k']\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.getiyv","page":"References","title":"OMEinsum.getiyv","text":"getiy(code)\n\nGet labels of the output tensor for EinCode, NestedEinsum and some other einsum like objects. Returns a vector.\n\njulia> getiyv(ein\"(ij,jk),k->i\")\n1-element Vector{Char}:\n 'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsumContractionOrders.contraction_complexity","page":"References","title":"OMEinsumContractionOrders.contraction_complexity","text":"contraction_complexity(eincode, size_dict) -> ContractionComplexity\n\nReturns the time, space and read-write complexity of the einsum contraction. The returned object contains 3 fields:\n\ntime complexity tc defined as log2(number of element-wise multiplications).\nspace complexity sc defined as log2(size of the maximum intermediate tensor).\nread-write complexity rwc defined as log2(the number of read-write operations).\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.estimate_memory","page":"References","title":"GenericTensorNetworks.estimate_memory","text":"estimate_memory(\n problem::GenericTensorNetwork,\n property::GenericTensorNetworks.AbstractProperty;\n T\n) -> Any\n\n\nMemory estimation in number of bytes to compute certain property of a problem. T is the base type.\n\n\n\n\n\n","category":"function"},{"location":"ref/#OMEinsum.@ein_str","page":"References","title":"OMEinsum.@ein_str","text":"ein\"ij,jk -> ik\"(A,B)\n\nString 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 α-ω.\n\nexample\n\njulia> a, b, c = rand(10,10), rand(10,10), rand(10,1);\n\njulia> ein\"ij,jk,kl -> il\"(a,b,c) ≈ ein\"(ij,jk),kl -> il\"(a,b,c) ≈ a * b * c\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"ref/#OMEinsumContractionOrders.GreedyMethod","page":"References","title":"OMEinsumContractionOrders.GreedyMethod","text":"GreedyMethod{MT}\nGreedyMethod(; α = 0.0, temperature = 0.0, nrepeat=10)\n\nThe fast but poor greedy optimizer. Input arguments are\n\n* `α` is the parameter for the loss function, for pairwise interaction, L = size(out) - α * (size(in1) + size(in2))\n* `temperature` is 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).\n* `nrepeat` is the number of repeatition, returns the best contraction order.\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.TreeSA","page":"References","title":"OMEinsumContractionOrders.TreeSA","text":"TreeSA{RT,IT,GM}\nTreeSA(; sc_target=20, βs=collect(0.01:0.05:15), ntrials=10, niters=50,\n sc_weight=1.0, rw_weight=0.2, initializer=:greedy, greedy_config=GreedyMethod(; nrepeat=1))\n\nOptimize the einsum contraction pattern using the simulated annealing on tensor expression tree.\n\nsc_target is the target space complexity,\nntrials, βs and niters are annealing parameters, doing ntrials indepedent annealings, each has inverse tempteratures specified by βs, in each temperature, do niters updates of the tree.\nsc_weight is the relative importance factor of space complexity in the loss compared with the time complexity.\nrw_weight is the relative importance factor of memory read and write in the loss compared with the time complexity.\ninitializer specifies how to determine the initial configuration, it can be :greedy or :random. If it is using :greedy method to generate the initial configuration, it also uses two extra arguments greedy_method and greedy_nrepeat.\nnslices is the number of sliced legs, default is 0.\nfixed_slices is a vector of sliced legs, default is [].\n\nReferences\n\nRecursive Multi-Tensor Contraction for XEB Verification of Quantum Circuits\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.SABipartite","page":"References","title":"OMEinsumContractionOrders.SABipartite","text":"SABipartite{RT,BT}\nSABipartite(; sc_target=25, ntrials=50, βs=0.1:0.2:15.0, niters=1000\n max_group_size=40, greedy_config=GreedyMethod(), initializer=:random)\n\nOptimize 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\n\nsize_dict, a dictionary that specifies leg dimensions,\nsc_target is the target space complexity, defined as log2(number of elements in the largest tensor),\nmax_group_size is the maximum size that allowed to used greedy search,\nβs is a list of inverse temperature 1/T,\nniters is the number of iteration in each temperature,\nntrials is the number of repetition (with different random seeds),\nsub_optimizer, the optimizer for the bipartited sub graphs, one can choose GreedyMethod() or TreeSA(),\ninitializer, the partition configuration initializer, one can choose :random or :greedy (slow but better).\n\nReferences\n\nHyper-optimized tensor network contraction\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.KaHyParBipartite","page":"References","title":"OMEinsumContractionOrders.KaHyParBipartite","text":"KaHyParBipartite{RT,IT,GM}\nKaHyParBipartite(; sc_target, imbalances=collect(0.0:0.005:0.8),\n max_group_size=40, greedy_config=GreedyMethod())\n\nOptimize 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\n\nsc_target is the target space complexity, defined as log2(number of elements in the largest tensor),\nimbalances is a KaHyPar parameter that controls the group sizes in hierarchical bipartition,\nmax_group_size is the maximum size that allowed to used greedy search,\ngreedy_config is a greedy optimizer.\n\nReferences\n\nHyper-optimized tensor network contraction\nSimulating the Sycamore quantum supremacy circuits\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.MergeVectors","page":"References","title":"OMEinsumContractionOrders.MergeVectors","text":"MergeVectors <: CodeSimplifier\nMergeVectors()\n\nContraction code simplifier (in order to reduce the time of calling optimizers) that merges vectors to closest tensors.\n\n\n\n\n\n","category":"type"},{"location":"ref/#OMEinsumContractionOrders.MergeGreedy","page":"References","title":"OMEinsumContractionOrders.MergeGreedy","text":"MergeGreedy <: CodeSimplifier\nMergeGreedy(; threshhold=-1e-12)\n\nContraction 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).\n\n\n\n\n\n","category":"type"},{"location":"ref/#Others","page":"References","title":"Others","text":"","category":"section"},{"location":"ref/#Graph","page":"References","title":"Graph","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"Except the SimpleGraph defined in Graphs, GenericTensorNetworks also defines the following types and functions.","category":"page"},{"location":"ref/","page":"References","title":"References","text":"HyperGraph\nUnitDiskGraph\n\nshow_graph\nshow_configs\nshow_einsum\nshow_landscape\nGraphDisplayConfig\nAbstractLayout\nSpringLayout\nStressLayout\nSpectralLayout\nLayered\nLayeredSpringLayout\nLayeredStressLayout\nrender_locs\n\ndiagonal_coupled_graph\nsquare_lattice_graph\nline_graph\n\nrandom_diagonal_coupled_graph\nrandom_square_lattice_graph","category":"page"},{"location":"ref/#ProblemReductions.HyperGraph","page":"References","title":"ProblemReductions.HyperGraph","text":"struct HyperGraph <: Graphs.AbstractGraph{Int64}\n\nA hypergraph is a generalization of a graph in which an edge can connect any number of vertices.\n\nFields\n\nn::Int: the number of vertices\nedges::Vector{Vector{Int}}: a vector of vectors of integers, where each vector represents a hyperedge connecting the vertices with the corresponding indices.\n\n\n\n\n\n","category":"type"},{"location":"ref/#ProblemReductions.UnitDiskGraph","page":"References","title":"ProblemReductions.UnitDiskGraph","text":"struct UnitDiskGraph{D, T} <: Graphs.AbstractGraph{Int64}\n\nA 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.\n\nFields\n\nlocations::Vector{NTuple{D, T}}: the locations of the vertices\nradius::Float64: the radius of the unit disk\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.show_graph","page":"References","title":"LuxorGraphPlot.show_graph","text":"show_graph([f, ]graph::AbstractGraph;\n kwargs...\n )\n\nShow a graph in VSCode, Pluto or Jupyter notebook, or save it to a file.\n\nPositional arguments\n\nf is a function that returns extra Luxor plotting statements.\ngraph is a graph instance.\nlocs is a vector of tuples for specifying the vertex locations, or a AbstractLayout instance.\n\nKeyword arguments\n\nconfig is a GraphDisplayConfig instance.\nvertex_colors is a vector of color strings for specifying vertex fill colors.\nvertex_sizes is a vector of real numbers for specifying vertex sizes.\nvertex_shapes is a vector of strings for specifying vertex shapes, the string should be \"circle\" or \"box\".\nvertex_stroke_colors is a vector of color strings for specifying vertex stroke colors.\nvertex_text_colors is a vector of color strings for specifying vertex text colors.\nedge_colors is a vector of color strings for specifying edge colors.\ntexts is a vector of strings for labeling vertices.\n\npadding_left::Int = 10, the padding on the left side of the drawing\npadding_right::Int = 10, the padding on the right side of the drawing\npadding_top::Int = 10, the padding on the top side of the drawing\npadding_bottom::Int = 10, the padding on the bottom side of the drawing\nformat is the output format, which can be :svg, :png or :pdf.\nfilename is a string as the output filename.\n\nExample\n\njulia> using Graphs, LuxorGraphPlot\n\njulia> show_graph(smallgraph(:petersen); format=:png, vertex_colors=rand([\"blue\", \"red\"], 10));\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_configs","page":"References","title":"GenericTensorNetworks.show_configs","text":"show_configs(gp::ConstraintSatisfactionProblem, locs, configs::AbstractMatrix; kwargs...)\nshow_configs(graph::SimpleGraph, locs, configs::AbstractMatrix; num_flavors=2, kwargs...)\n\nShow a gallery of configurations on a graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_einsum","page":"References","title":"GenericTensorNetworks.show_einsum","text":"show_einsum(ein::AbstractEinsum;\n tensor_locs=nothing,\n label_locs=nothing, # dict\n spring::Bool=true,\n optimal_distance=25.0,\n\n tensor_size=15,\n tensor_color=\"black\",\n tensor_text_color=\"white\",\n annotate_tensors=false,\n\n label_size=7,\n label_color=\"black\",\n open_label_color=\"black\",\n annotate_labels=true,\n kwargs...\n )\n\nPositional arguments\n\nein is an Einsum contraction code (provided by package OMEinsum).\n\nKeyword arguments\n\nlocs is a tuple of tensor_locs (vector) and label_locs (dict).\nspring is switch to use spring method to optimize the location.\noptimal_distance is a optimal distance parameter for spring optimizer.\ntensor_color is a string to specify the color of tensor nodes.\ntensor_size is a real number to specify the size of tensor nodes.\ntensor_text_color is a color strings to specify tensor text color.\nannotate_tensors is a boolean switch for annotate different tensors by integers.\nlabel_size is a real number to specify label text node size.\nlabel_color is a color strings to specify label text color.\nopen_label_color is a color strings to specify open label text color.\nannotate_labels is a boolean switch for annotate different labels.\nformat is the output format, which can be :svg, :png or :pdf.\nfilename is a string as the output filename.\n\nfontsize::Float64 = 12.0, the font size\nfontface::String = \"\", the font face, leave empty to follow system\nvertex_text_color = \"black\", the default text color\nvertex_stroke_color = \"black\", the default stroke color for vertices\nvertex_color = \"transparent\", the default default fill color for vertices\nvertex_size::Float64 = 10.0, the default vertex size\nvertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot\nvertex_line_width::Float64 = 1, the default vertex stroke line width\nvertex_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\"]\nedge_color = \"black\", the default edge color\nedge_line_width::Float64 = 1, the default line width\nedge_style::String = \"solid\", the line style of edges, which can be one of [\"solid\", \"dotted\", \"dot\", \"dotdashed\", \"longdashed\", \"shortdashed\", \"dash\", \"dashed\", \"dotdotdashed\", \"dotdotdotdashed\"]\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.show_landscape","page":"References","title":"GenericTensorNetworks.show_landscape","text":"show_landscape(is_neighbor, configurations::TruncatedPoly;\n layer_distance=200,\n config=GraphDisplayConfig(; edge_color=\"gray\", vertex_stroke_color=\"transparent\", vertex_size=5),\n layout_method=:spring,\n optimal_distance=30.0,\n colors=fill(\"green\", K),\n kwargs...)\n\nShow the energy landscape of configurations.\n\nArguments\n\nis_neighbor: a function to determine if two configurations are neighbors.\nconfigurations: a TruncatedPoly object, which is the default output of the solve function with ConfigsMax property as the argument.\n\nKeyword arguments\n\nlayer_distance: the distance between layers.\nconfig: a LuxorGraphPlot.GraphDisplayConfig object.\nlayout_method: the layout method, either :spring, :stress or :spectral\noptimal_distance: the optimal distance for the layout.\ncolors: a vector of colors for each layer.\nkwargs...: other keyword arguments passed to show_graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.GraphDisplayConfig","page":"References","title":"LuxorGraphPlot.GraphDisplayConfig","text":"GraphDisplayConfig\n\nThe configuration for graph display.\n\nKeyword arguments\n\nlocs is a vector of tuples for specifying the vertex locations.\nedges is a vector of tuples for specifying the edges.\nfontsize::Float64 = 12.0, the font size\nfontface::String = \"\", the font face, leave empty to follow system\nvertex_text_color = \"black\", the default text color\nvertex_stroke_color = \"black\", the default stroke color for vertices\nvertex_color = \"transparent\", the default default fill color for vertices\nvertex_size::Float64 = 10.0, the default vertex size\nvertex_shape::Symbol = :circle, the default vertex shape, which can be :circle, :box or :dot\nvertex_line_width::Float64 = 1, the default vertex stroke line width\nvertex_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\"]\nedge_color = \"black\", the default edge color\nedge_line_width::Float64 = 1, the default line width\nedge_style::String = \"solid\", the line style of edges, which can be one of [\"solid\", \"dotted\", \"dot\", \"dotdashed\", \"longdashed\", \"shortdashed\", \"dash\", \"dashed\", \"dotdotdashed\", \"dotdotdotdashed\"]\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.AbstractLayout","page":"References","title":"LuxorGraphPlot.Layouts.AbstractLayout","text":"AbstractLayout\n\nAbstract type for layout algorithms.\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.SpringLayout","page":"References","title":"LuxorGraphPlot.Layouts.SpringLayout","text":"SpringLayout <: AbstractLayout\n\nA layout algorithm based on a spring model.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\nmaxiter::Int: the maximum number of iterations\nα0::Float64: the initial moving speed\nmeta::Dict{Symbol, Any}: graph dependent meta information, including\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.StressLayout","page":"References","title":"LuxorGraphPlot.Layouts.StressLayout","text":"StressLayout <: AbstractLayout\n\nA layout algorithm based on stress majorization.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\nmaxiter::Int: the maximum number of iterations\nrtol::Float64: the absolute tolerance\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\nmeta::Dict{Symbol, Any}: graph dependent meta information, including\ninitial_locs: initial vertex locations\nmask: boolean mask for which vertices to relocate\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.SpectralLayout","page":"References","title":"LuxorGraphPlot.Layouts.SpectralLayout","text":"SpectralLayout <: AbstractLayout\n\nA layout algorithm based on spectral graph theory.\n\nFields\n\noptimal_distance::Float64: the optimal distance between vertices\ndimension::Int: the number of dimensions\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.Layered","page":"References","title":"LuxorGraphPlot.Layouts.Layered","text":"Layered <: AbstractLayout\n\nLayered version of a parent layout algorithm.\n\nFields\n\nparent::LT: the parent layout algorithm\nzlocs::Vector{T}: the z-axis locations\naspect_ratio::Float64: the aspect ratio of the z-axis\n\n\n\n\n\n","category":"type"},{"location":"ref/#LuxorGraphPlot.Layouts.LayeredSpringLayout","page":"References","title":"LuxorGraphPlot.Layouts.LayeredSpringLayout","text":"LayeredSpringLayout(; zlocs, optimal_distance, aspect_ration=0.2)\n\nCreate a layered spring layout.\n\nKeyword Arguments\n\nzlocs: the z-axis locations\noptimal_distance::Float64: the optimal distance between vertices\naspect_ration::Float64: the aspect ratio of the z-axis\nα0::Float64: the initial moving speed\nmaxiter::Int: the maximum number of iterations\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.Layouts.LayeredStressLayout","page":"References","title":"LuxorGraphPlot.Layouts.LayeredStressLayout","text":"LayeredStressLayout(; zlocs, optimal_distance, aspect_ration=0.2)\n\nCreate a layered stress layout.\n\nKeyword Arguments\n\nzlocs: the z-axis locations\noptimal_distance::Float64: the optimal distance between vertices\naspect_ration::Float64: the aspect ratio of the z-axis\nmaxiter::Int: the maximum number of iterations\nrtol::Float64: the absolute tolerance\n\n\n\n\n\n","category":"function"},{"location":"ref/#LuxorGraphPlot.Layouts.render_locs","page":"References","title":"LuxorGraphPlot.Layouts.render_locs","text":"render_locs(graph, layout::Layout)\n\nRender the vertex locations for a graph from an AbstractLayout instance.\n\nArguments\n\ngraph::AbstractGraph: the graph to render\nlayout::AbstractLayout: the layout algorithm\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.diagonal_coupled_graph","page":"References","title":"GenericTensorNetworks.diagonal_coupled_graph","text":"diagonal_coupled_graph(mask::AbstractMatrix{Bool})\n\nCreate a masked diagonal coupled square lattice graph from a specified mask.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.square_lattice_graph","page":"References","title":"GenericTensorNetworks.square_lattice_graph","text":"square_lattice_graph(mask::AbstractMatrix{Bool})\n\nCreate a masked square lattice graph.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.line_graph","page":"References","title":"GenericTensorNetworks.line_graph","text":"line_graph(g::SimpleGraph)\n\nReturns 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.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.random_diagonal_coupled_graph","page":"References","title":"GenericTensorNetworks.random_diagonal_coupled_graph","text":"random_diagonal_coupled_graph(m::Int, n::Int, ρ::Real)\n\nCreate a mtimes n random masked diagonal coupled square lattice graph, with number of vertices equal to lfloor m times ntimes rho rceil.\n\n\n\n\n\n","category":"function"},{"location":"ref/#GenericTensorNetworks.random_square_lattice_graph","page":"References","title":"GenericTensorNetworks.random_square_lattice_graph","text":"random_square_lattice_graph(m::Int, n::Int, ρ::Real)\n\nCreate a random masked square lattice graph, with number of vertices fixed to lfloor mnrho rceil.\n\n\n\n\n\n","category":"function"},{"location":"ref/","page":"References","title":"References","text":"One can also use random_regular_graph and smallgraph in Graphs to build special graphs.","category":"page"},{"location":"ref/#Multiprocessing","page":"References","title":"Multiprocessing","text":"","category":"section"},{"location":"ref/","page":"References","title":"References","text":"GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","category":"page"},{"location":"ref/#GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","page":"References","title":"GenericTensorNetworks.SimpleMultiprocessing.multiprocess_run","text":"multiprocess_run(func, inputs::AbstractVector)\n\nExecute function func on inputs with multiple processing.\n\nExample\n\nSuppose we have a file run.jl with the following contents\n\nusing GenericTensorNetworks.SimpleMultiprocessing\n\nresults = multiprocess_run(x->x^2, randn(8))\n\nIn an terminal, you may run the script with 4 processes by typing\n\n$ julia -p4 run.jl\n From worker 2:\t[ Info: running argument -0.17544008350172655 on device 2\n From worker 5:\t[ Info: running argument 0.34578117779452555 on device 5\n From worker 3:\t[ Info: running argument 2.0312551239727705 on device 3\n From worker 4:\t[ Info: running argument -0.7319353419291961 on device 4\n From worker 2:\t[ Info: running argument 0.013132180639054629 on device 2\n From worker 3:\t[ Info: running argument 0.9960101782201602 on device 3\n From worker 4:\t[ Info: running argument -0.5613942832743966 on device 4\n From worker 5:\t[ Info: running argument 0.39460402723831134 on device 5\n\n\n\n\n\n","category":"function"},{"location":"","page":"Home","title":"Home","text":"CurrentModule = GenericTensorNetworks","category":"page"},{"location":"#GenericTensorNetworks","page":"Home","title":"GenericTensorNetworks","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package implements generic tensor networks to compute solution space properties of a class of hard combinatorial problems. The solution space properties include","category":"page"},{"location":"","page":"Home","title":"Home","text":"The maximum/minimum solution sizes,\nThe number of solutions at certain sizes,\nThe enumeration of solutions at certain sizes.\nThe direct sampling of solutions at certain sizes.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The solvable problems include Independent set problem, Maximal independent set problem, Spin-glass problem, Cutting problem, Vertex matching problem, Binary paint shop problem, Coloring problem, Dominating set problem, Satisfiability problem, Set packing problem and Set covering problem.","category":"page"},{"location":"#Background-knowledge","page":"Home","title":"Background knowledge","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Please check our paper \"Computing properties of independent sets by generic programming tensor networks\". If you find our paper or software useful in your work, we would be grateful if you could cite our work. The CITATION.bib file in the root of this repository lists the relevant papers.","category":"page"},{"location":"#Quick-start","page":"Home","title":"Quick start","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"You can find a set up guide in our README. To get started, open a Julia REPL and type the following code.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using GenericTensorNetworks, Graphs#, CUDA\nsolve(\n GenericTensorNetwork(IndependentSet(\n Graphs.random_regular_graph(20, 3),\n UnitWeight(20)); # default: uniform weight 1\n optimizer = TreeSA(),\n openvertices = (), # default: no open vertices\n fixedvertices = Dict() # default: no fixed vertices\n ),\n GraphPolynomial();\n usecuda=false # the default value\n )","category":"page"},{"location":"","page":"Home","title":"Home","text":"Here the main function solve takes three input arguments, the problem instance of type IndependentSet, the property instance of type GraphPolynomial and an optional key word argument usecuda to decide use GPU or not. If one wants to use GPU to accelerate the computation, the , CUDA should be uncommented.","category":"page"},{"location":"","page":"Home","title":"Home","text":"An IndependentSet instance takes two positional arguments to initialize, the graph instance that one wants to solve and the weights for each vertex. Here, we use a random regular graph with 20 vertices and degree 3, and the default uniform weight 1.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The GenericTensorNetwork function is a constructor for the problem instance, which takes the problem instance as the first argument and optional key word arguments. The key word argument optimizer is for specifying the tensor network optimization algorithm. The keyword argument openvertices is a tuple of labels for specifying the degrees of freedom not summed over, and fixedvertices is a label-value dictionary for specifying the fixed values of the degree of freedoms. Here, we use TreeSA method as the tensor network optimizer, and leave openvertices the default values. The TreeSA method finds the best contraction order in most of our applications, while the default GreedyMethod runs the fastest.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The first execution of this function will be a bit slow due to Julia's just in time compiling. The subsequent runs will be fast. The following diagram lists possible combinations of input arguments, where functions in the Graph are mainly defined in the package Graphs, and the rest can be found in this package.","category":"page"},{"location":"","page":"Home","title":"Home","text":"
\n\n
","category":"page"},{"location":"","page":"Home","title":"Home","text":"⠀ You can find many examples in this documentation, a good one to start with is Independent set problem.","category":"page"}] } diff --git a/dev/sumproduct/5f94069e.png b/dev/sumproduct/5f94069e.png new file mode 100644 index 0000000000000000000000000000000000000000..c1b2d184646ed6d111ed0d19a8c706e8ee0591f1 GIT binary patch literal 24324 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 D|1FK< literal 0 HcmV?d00001 diff --git a/dev/sumproduct/ee6f4e25.png b/dev/sumproduct/ee6f4e25.png deleted file mode 100644 index b83d8e0660c020ad2912cfe294ad8285782fe206..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24191 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 diff --git a/dev/sumproduct/index.html b/dev/sumproduct/index.html index 292cd80..e7bab51 100644 --- a/dev/sumproduct/index.html +++ b/dev/sumproduct/index.html @@ -1,94 +1,96 @@ -Sum product tree representation · GenericTensorNetworks.jl

Sum product representation for configurations

SumProductTree can use polynomial memory to store exponential number of configurations. It is a sum-product expression tree to store ConfigEnumerator in a lazy style, where configurations can be extracted by depth first searching the tree with the Base.collect method. Although it is space efficient, it is in general not easy to extract information from it due to the exponential large configuration space. Directed sampling is one of its most important operations, with which one can get some statistic properties from it with an intermediate effort. For example, if we want to check some property of an intermediate scale graph, one can type

julia> using GenericTensorNetworks
julia> graph = random_regular_graph(70, 3){70, 105} undirected simple Int64 graph
julia> problem = GenericTensorNetwork(IndependentSet(graph); optimizer=TreeSA());
julia> tree = solve(problem, ConfigsAll(; tree_storage=true))[]+ (count = 1.55951641647e13) -├─ + (count = 1.1851712477918e13) -│ ├─ + (count = 8.087315420816e12) -│ │ ├─ * (count = 8.25781484447e11) -│ │ │ ├─ * (count = 8.25781484447e11) -│ │ │ │ ├─ + (count = 8.25781484447e11) -│ │ │ │ │ ⋮ -│ │ │ │ │ -│ │ │ │ └─ * (count = 1.0) -│ │ │ │ ⋮ -│ │ │ │ -│ │ │ └─ * (count = 1.0) -│ │ │ ├─ OnehotVec{70, 2}(65, 1) -│ │ │ └─ * (count = 1.0) +Sum product tree representation · GenericTensorNetworks.jl

Sum product representation for configurations

SumProductTree can use polynomial memory to store exponential number of configurations. It is a sum-product expression tree to store ConfigEnumerator in a lazy style, where configurations can be extracted by depth first searching the tree with the Base.collect method. Although it is space efficient, it is in general not easy to extract information from it due to the exponential large configuration space. Directed sampling is one of its most important operations, with which one can get some statistic properties from it with an intermediate effort. For example, if we want to check some property of an intermediate scale graph, one can type

julia> using GenericTensorNetworks
julia> graph = random_regular_graph(70, 3){70, 105} undirected simple Int64 graph
julia> problem = GenericTensorNetwork(IndependentSet(graph); optimizer=TreeSA());
julia> tree = solve(problem, ConfigsAll(; tree_storage=true))[]+ (count = 1.7042933526212e13) +├─ + (count = 1.2943469325281e13) +│ ├─ + (count = 8.849769392095e12) +│ │ ├─ * (count = 9.47476020478e11) +│ │ │ ├─ * (count = 1.0) +│ │ │ │ ├─ OnehotVec{70, 2}(56, 1) +│ │ │ │ └─ OnehotVec{70, 2}(2, 1) +│ │ │ └─ + (count = 9.47476020478e11) +│ │ │ ├─ * (count = 1.30951955306e11) +│ │ │ │ ⋮ +│ │ │ │ +│ │ │ └─ + (count = 8.16524065172e11) │ │ │ ⋮ │ │ │ -│ │ └─ + (count = 7.261533936369e12) -│ │ ├─ * (count = 1.770261320811e12) -│ │ │ ├─ * (count = 1.770261320811e12) -│ │ │ │ ⋮ -│ │ │ │ -│ │ │ └─ OnehotVec{70, 2}(65, 1) -│ │ └─ + (count = 5.491272615558e12) -│ │ ├─ * (count = 1.747820928776e12) +│ │ └─ + (count = 7.902293371617e12) +│ │ ├─ * (count = 1.879319842489e12) +│ │ │ ├─ OnehotVec{70, 2}(2, 1) +│ │ │ └─ + (count = 1.879319842489e12) +│ │ │ ⋮ +│ │ │ +│ │ └─ + (count = 6.022973529128e12) +│ │ ├─ * (count = 1.929273595942e12) │ │ │ ⋮ │ │ │ -│ │ └─ + (count = 3.743451686782e12) +│ │ └─ + (count = 4.093699933186e12) │ │ ⋮ │ │ -│ └─ * (count = 3.764397057102e12) -│ ├─ OnehotVec{70, 2}(39, 1) -│ └─ + (count = 3.764397057102e12) -│ ├─ * (count = 3.74734118834e11) -│ │ ├─ * (count = 3.74734118834e11) -│ │ │ ⋮ -│ │ │ -│ │ └─ * (count = 1.0) -│ │ ⋮ -│ │ -│ └─ + (count = 3.389662938268e12) -│ ├─ * (count = 8.0397937569e11) -│ │ ⋮ -│ │ -│ └─ + (count = 2.585683562578e12) -│ ⋮ -│ -└─ * (count = 3.743451686782e12) - ├─ OnehotVec{70, 2}(51, 1) - └─ * (count = 3.743451686782e12) - ├─ + (count = 3.743451686782e12) - │ ├─ * (count = 1.169455305325e12) - │ │ ├─ + (count = 1.169455305325e12) - │ │ │ ⋮ - │ │ │ - │ │ └─ OnehotVec{70, 2}(44, 1) - │ └─ + (count = 2.573996381457e12) - │ ├─ * (count = 1.87731284801e11) - │ │ ⋮ - │ │ - │ └─ + (count = 2.386265096656e12) - │ ⋮ - │ - └─ * (count = 1.0) - ├─ OnehotVec{70, 2}(51, 1) - └─ * (count = 1.0) - ├─ OnehotVec{70, 2}(51, 1) - └─ OnehotVec{70, 2}(51, 1)

If one wants to store these configurations, he will need a hard disk of size 256 TB! However, this sum-product binary tree structure supports efficient and unbiased direct sampling.

julia> samples = generate_samples(tree, 1000)1000-element Vector{StaticBitVector{70, 2}}:
- 0000000100010010001000100001110011110001000000000000000110100010110000
- 1000000100001010010011100101100100100000000000000000100000011110101000
- 0000000000001010101000001010110100100001000000001000000100011010110000
- 0100000000011010010000110001110111100000010000000100000111100001110000
- 1100000000001011110010000000100010100000000010011000000010000000101010
- 0100001110001011100100001000100100100001000000110100000001001000101000
- 0000000000100011001001101000101100100000000001000101000010100000100000
- 0000001000000011101000001011100000100001000010100000000001001000101000
- 0000000100000110000000001100101101000000100000010100100001100110110000
- 0000000100000010010011000000100001001100100010000100100011001110101000
+│  └─ * (count = 4.093699933186e12)
+│     ├─ * (count = 4.093699933186e12)
+│     │  ├─ * (count = 1.0)
+│     │  │  ├─ OnehotVec{70, 2}(47, 1)
+│     │  │  └─ * (count = 1.0)
+│     │  │     ⋮
+│     │  │
+│     │  └─ + (count = 4.093699933186e12)
+│     │     ├─ * (count = 8.0585461904e10)
+│     │     │  ⋮
+│     │     │
+│     │     └─ + (count = 4.013114471282e12)
+│     │        ⋮
+│     │
+│     └─ OnehotVec{70, 2}(47, 1)
+└─ * (count = 4.099464200931e12)
+   ├─ + (count = 4.099464200931e12)
+   │  ├─ * (count = 4.32196039729e11)
+   │  │  ├─ * (count = 1.0)
+   │  │  │  ├─ OnehotVec{70, 2}(56, 1)
+   │  │  │  └─ OnehotVec{70, 2}(2, 1)
+   │  │  └─ + (count = 4.32196039729e11)
+   │  │     ├─ * (count = 5.84493145e10)
+   │  │     │  ⋮
+   │  │     │
+   │  │     └─ + (count = 3.73746725229e11)
+   │  │        ⋮
+   │  │
+   │  └─ + (count = 3.667268161202e12)
+   │     ├─ * (count = 8.59078393352e11)
+   │     │  ├─ OnehotVec{70, 2}(2, 1)
+   │     │  └─ + (count = 8.59078393352e11)
+   │     │     ⋮
+   │     │
+   │     └─ + (count = 2.80818976785e12)
+   │        ├─ * (count = 8.98174172841e11)
+   │        │  ⋮
+   │        │
+   │        └─ + (count = 1.910015595009e12)
+   │           ⋮
+   │
+   └─ OnehotVec{70, 2}(66, 1)

If one wants to store these configurations, he will need a hard disk of size 256 TB! However, this sum-product binary tree structure supports efficient and unbiased direct sampling.

julia> samples = generate_samples(tree, 1000)1000-element Vector{StaticBitVector{70, 2}}:
+ 1100001010100010000001101000011100000000010000000000100100001010100110
+ 1100000010010010001001111000010011011001010100000010110100000100100100
+ 0100100100101010000001111001000010100001011000001100001100000000100100
+ 0100001010110010000001001001000000000100010010000010010100001100101100
+ 0100000010001000011000101000010010010000010100000000001100110000100010
+ 0100000010110100000000011000010000000101010100000000110100011001100010
+ 0110001000010000000000101100010100001100010110000000000100100000101100
+ 0100000001010100010001001110001000010000010000000100001100000000100000
+ 0100100000001110100000000000000101000010010000000001000101001000000010
+ 1100001100101010010000100000010010010010010100001000100100010100100000
  ⋮
- 0001000101000000000100010010010000010101000000001010000000011000000001
- 1010110000010000000000010001010000000100010000000010000011000000001011
- 0100010000000100100000000010010000010001000000000010010011101000000100
- 0000000010000000010000110000000000001000100001000010000001001100001110
- 0010000000000000010001000010000000011100100000000011000001000100000001
- 0000001011010000000100000001000010000000110011000011011001000000000011
- 1010100000000000000000000001000000001000001000000111101011100000000111
- 0001100000001000001001100011000000000000000011001010000110001000000100
- 1000000000000000100000010001001000000001100001001110000010000000001110

With these samples, one can already compute useful properties like Hamming distance (see hamming_distribution) distribution. The following code visualizes this distribution with CairoMakie.

using CairoMakie
+ 0001001110000100100011000000100000100000001000000001001001100010110000
+ 0001000110101000000011000000100000000001000011000000000000001100010101
+ 0000000100101000000010000010100000010001001001001001001001010000010000
+ 0000000000110000100010010001100010100001000001000000000001001001010100
+ 0000001010110001110010000101100000001000001000000000010001000110011100
+ 0011000010000000000000000011001010010010000011000101000001000000110000
+ 0000000000010001100010010001000001011000001000010110001000000000011000
+ 0001000100001000010001010000001010000010000000000001000000100010010001
+ 0001010000010100100001000000000001010001001001000011001001000000010001

With these samples, one can already compute useful properties like Hamming distance (see hamming_distribution) distribution. The following code visualizes this distribution with CairoMakie.

using CairoMakie
 dist = hamming_distribution(samples, samples)
 # bar plot
 fig = Figure()
 ax = Axis(fig[1, 1]; xlabel="Hamming distance", ylabel="Frequency")
 barplot!(ax, 0:length(dist)-1, dist)
-fig
Example block output
+fig
Example block output