Skip to content

Commit 3f41432

Browse files
committed
2 parents 10552d5 + 1a1a402 commit 3f41432

File tree

16 files changed

+150
-28
lines changed

16 files changed

+150
-28
lines changed

.github/workflows/CI.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,25 @@ on:
55
- master
66
pull_request:
77
jobs:
8+
pre_job:
9+
# continue-on-error: true # Uncomment once integration is finished
10+
runs-on: ubuntu-latest
11+
# Map a step output to a job output
12+
outputs:
13+
should_skip: ${{ steps.skip_check.outputs.should_skip }}
14+
steps:
15+
- id: skip_check
16+
uses: fkirc/skip-duplicate-actions@master
17+
with:
18+
# All of these options are optional, so you can remove them if you are happy with the defaults
19+
concurrent_skipping: 'never'
20+
skip_after_successful_duplicate: 'true'
21+
paths_ignore: '["**/README.md", "**/docs/**", "**/examples/**"]'
22+
do_not_skip: '["pull_request", "workflow_dispatch", "schedule"]'
23+
824
test:
25+
needs: pre_job
26+
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
927
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
1028
runs-on: ${{ matrix.os }}
1129
strategy:
@@ -44,8 +62,9 @@ jobs:
4462
path-to-lcov: lcov.info
4563

4664
finish:
65+
needs: [pre_job, test]
66+
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
4767
name: Coveralls Finished
48-
needs: test
4968
runs-on: ubuntu-latest
5069
steps:
5170
- uses: coverallsapp/github-action@master

README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,34 @@
88
<p>
99
GraphTensorNetworks is a &nbsp;
1010
<a href="https://julialang.org">
11-
<img src="https://julialang.org/favicon.ico" width="16em">
11+
<img src="https://raw.githubusercontent.com/JuliaLang/julia-logo-graphics/master/images/julia.ico" width="16em">
1212
Julia Language
1313
</a>
1414
&nbsp; package. To install GraphTensorNetworks,
1515
please <a href="https://docs.julialang.org/en/v1/manual/getting-started/">open
1616
Julia's interactive session (known as REPL)</a> and press <kbd>]</kbd> key in the REPL to use the package mode, then
1717
</p>
1818

19-
1. if you have access to our registry
19+
1. if you are a user, just type
2020
```julia
2121
pkg> add GraphTensorNetworks
2222
```
2323

24-
2. otherwise (e.g. if you are an external collaborator), you can install in develop mode
24+
If you do not have access to our registry, e.g. you are an external collaborator, you can install the master branch by typing
25+
```julia
26+
pkg> add https://github.com/Happy-Diode/GraphTensorNetworks.jl.git#master
27+
```
28+
29+
To update, just type `up` in the package mode.
30+
31+
2. If you are a developer, you can install it in develop mode
2532
```julia
2633
pkg> dev https://github.com/Happy-Diode/GraphTensorNetworks.jl.git
2734
```
2835

29-
Please use **Julia-1.7**, otherwise you will suffer from huge overheads when contracting large tensor networks. If you have to use a lower version,
36+
Packages installed in developer mode will not be updated by the `up` command, you should go to the develop folder and use `git` to manage your versions. For more [details](https://docs.julialang.org/en/v1/stdlib/Pkg/).
37+
38+
Please use **Julia version >= 1.7**, otherwise you will suffer from huge overheads when contracting large tensor networks. If you have to use an old version Julia,
3039
you can avoid the overhead by overriding the `permutedims!` is `LinearAlgebra`, i.e. add the following code to your own project.
3140

3241
```julia
@@ -43,7 +52,7 @@ end
4352

4453
## Examples
4554

46-
Let us use the Petersen graph as an example, we first generate its tensor network contraction tree.
55+
In this example, we will show how to compute the independent set properties of the Petersen graph, we first generate its tensor network contraction tree.
4756
```julia
4857
julia> using GraphTensorNetworks, Random, Graphs
4958

@@ -83,9 +92,8 @@ julia> solve(problem, CountingMax(2))[]
8392
30.0*x^3 + 5.0*x^4
8493
```
8594

86-
#### 2. compute the independence polynomial
87-
8895
The following code computes independence polynomial using the finite field algebra (default) approach.
96+
It is equivalent to counting independent sets of an arbituary size.
8997

9098
```julia
9199
julia> solve(problem, GraphPolynomial())[]

docs/src/performancetips.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,31 @@ One can check the time, space and read-write complexity with the following funct
2828

2929
```julia
3030
julia> timespacereadwrite_complexity(problem)
31+
(21.90683335864693, 17.0, 20.03588509836998)
3132
```
3233

33-
The return values are `log2` of the the number of iterations, the number elements in the max tensor and the number of read-write operations to tensor elements.
34+
The return values are `log2` of the the number of iterations, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements.
35+
In this example, the number of `+` and `*` operations are both `\sim 2^{21.9}`
36+
and the number of read-write operations are `\sim 2^{20}`.
37+
The largest tensor size is ``2^17``, one can check the element size by typing
38+
```julia
39+
julia> sizeof(TropicalF64)
40+
8
41+
42+
julia> sizeof(TropicalF32)
43+
4
44+
45+
julia> sizeof(StaticBitVector{200,4})
46+
32
47+
48+
julia> sizeof(TruncatedPoly{5,Float64,Float64})
49+
48
50+
```
51+
52+
!!! note
53+
* The actual run time memory can be several times larger than the size of the maximum tensor.
54+
There is no constant bound for the factor, an empirical value for it is 3x.
55+
* For mutable types like [`Polynomial`](@ref) and [`ConfigEnumerater`](@ref), the `sizeof` function does not measure the actual element size.
3456

3557
## GEMM for Tropical numbers
3658
You can speed up the Tropical number matrix multiplication when computing `SizeMax()` by using the Tropical GEMM routines implemented in package [`TropicalGEMM.jl`](https://github.com/TensorBFS/TropicalGEMM.jl/).

examples/IndependentSet.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ locations = [[rot15(0.0, 1.0, i) for i=0:4]..., [rot15(0.0, 0.6, i) for i=0:4]..
1515

1616
show_graph(graph; locs=locations)
1717

18+
# In order to display your plot with [`show_graph`](@ref), you need to call this function in
19+
# * a [VSCode](https://github.com/julia-vscode/julia-vscode) editor,
20+
# * a [Jupyter](https://github.com/JunoLab/Juno.jl) notebook,
21+
# * or a [Pluto](https://github.com/fonsp/Pluto.jl) notebook,
22+
#
23+
# rather than a Julia REPL that does not have a graphical display.
24+
1825
# ## Tensor network representation
1926
# Let ``G=(V,E)`` be the target graph that we want to solve.
2027
# The tensor network representation map a vertex ``i\in V`` to a label ``s_i \in \{0, 1\}`` of dimension ``2`` in a tensor network, where we use ``0`` (``1``) to denote a vertex is absent (present) in the set.
@@ -47,7 +54,7 @@ problem = IndependentSet(graph; optimizer=TreeSA());
4754

4855
timespacereadwrite_complexity(problem)
4956

50-
# The return values are `log2` of the the number of iterations, the number elements in the tensor with maximum size during contraction and the number of tensor element read-write operations.
57+
# The return values are `log2` of the the number of iterations, the number elements in the largest tensor during contraction and the number of tensor element read-write operations.
5158
# For more information about how to improve the contraction order, please check the [Performance Tips](@ref).
5259

5360
# ## Solving properties

examples/PaintShop.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,18 @@ show_graph(graph; locs=locations, texts=string.(sequence), edge_colors=
4545
# For each black edges ``(i, i+1)``, we define an edge tensor labeld by ``(s_{c_i}, s_{c_{i+1}})`` as follows:
4646
# If both cars on this edge are their first or second appearance
4747
# ```math
48-
# B^{\rm parallel} = \begin{matrix}
48+
# B^{\rm parallel} = \left(\begin{matrix}
4949
# x & 1 \\
5050
# 1 & x \\
51-
# \end{matrix},
51+
# \end{matrix}\right),
52+
# ```
5253
#
5354
# otherwise,
54-
# B^{\rm anti-parallel} = B^{\rm 10} = \begin{matrix}
55+
# ```math
56+
# B^{\rm anti-parallel} = \left(\begin{matrix}
5557
# 1 & x \\
5658
# x & 1 \\
57-
# \end{matrix}.
59+
# \end{matrix}\right).
5860
# ```
5961
# It can be understood as, when both cars are their first appearance,
6062
# they tend to have the same configuration so that the color is not changed.

src/arithematics.jl

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,21 @@ end
7878

7979
"""
8080
TruncatedPoly{K,T,TO} <: Number
81+
TruncatedPoly(coeffs::Tuple, maxorder)
8182
8283
Polynomial truncated to largest `K` orders. `T` is the coefficients type and `TO` is the orders type.
8384
85+
Example
86+
------------------------
8487
```jldoctest; setup=(using GraphTensorNetworks)
8588
julia> TruncatedPoly((1,2,3), 6)
8689
x^4 + 2*x^5 + 3*x^6
90+
91+
julia> TruncatedPoly((1,2,3), 6) * TruncatedPoly((5,2,1), 3)
92+
20*x^7 + 8*x^8 + 3*x^9
93+
94+
julia> TruncatedPoly((1,2,3), 6) + TruncatedPoly((5,2,1), 3)
95+
x^4 + 2*x^5 + 3*x^6
8796
```
8897
"""
8998
struct TruncatedPoly{K,T,TO} <: Number
@@ -93,6 +102,9 @@ end
93102

94103
"""
95104
Max2Poly{T,TO} = TruncatedPoly{2,T,TO}
105+
Max2Poly(a, b, maxorder)
106+
107+
A shorthand of [`TruncatedPoly`](@ref){2}.
96108
"""
97109
const Max2Poly{T,TO} = TruncatedPoly{2,T,TO}
98110
Max2Poly(a, b, maxorder) = TruncatedPoly((a, b), maxorder)
@@ -157,6 +169,8 @@ Set algebra for enumerating configurations, where `N` is the length of configura
157169
`C` is the size of storage in unit of `UInt64`,
158170
`S` is the bit width to store a single element in a configuration, i.e. `log2(# of flavors)`, for bitstrings, it is `1``.
159171
172+
Example
173+
----------------------
160174
```jldoctest; setup=:(using GraphTensorNetworks)
161175
julia> a = ConfigEnumerator([StaticBitVector([1,1,1,0,0]), StaticBitVector([1,0,0,0,1])])
162176
{11100, 10001}
@@ -166,6 +180,12 @@ julia> b = ConfigEnumerator([StaticBitVector([0,0,0,0,0]), StaticBitVector([1,0,
166180
167181
julia> a + b
168182
{11100, 10001, 00000, 10101}
183+
184+
julia> one(a)
185+
{00000}
186+
187+
julia> zero(a)
188+
{}
169189
```
170190
"""
171191
struct ConfigEnumerator{N,S,C}
@@ -203,14 +223,32 @@ Base.show(io::IO, ::MIME"text/plain", x::ConfigEnumerator) = Base.show(io, x)
203223
# the algebra sampling one of the configurations
204224
"""
205225
ConfigSampler{N,S,C}
226+
ConfigSampler(elements::StaticElementVector)
206227
207228
The algebra for sampling one configuration, where `N` is the length of configurations,
208229
`C` is the size of storage in unit of `UInt64`,
209230
`S` is the bit width to store a single element in a configuration, i.e. `log2(# of flavors)`, for bitstrings, it is `1``.
210231
211-
```jldoctest; setup=:(using GraphTensorNetworks)
232+
!!! note
233+
`ConfigSampler` is a **probabilistic** commutative semiring, adding two config samplers do not give you deterministic results.
234+
235+
Example
236+
----------------------
237+
```jldoctest; setup=:(using GraphTensorNetworks, Random; Random.seed!(2))
212238
julia> ConfigSampler(StaticBitVector([1,1,1,0,0]))
213239
ConfigSampler{5, 1, 1}(11100)
240+
241+
julia> ConfigSampler(StaticBitVector([1,1,1,0,0])) + ConfigSampler(StaticBitVector([1,0,1,0,0]))
242+
ConfigSampler{5, 1, 1}(10100)
243+
244+
julia> ConfigSampler(StaticBitVector([1,1,1,0,0])) * ConfigSampler(StaticBitVector([0,0,0,0,1]))
245+
ConfigSampler{5, 1, 1}(11101)
246+
247+
julia> one(ConfigSampler{5, 1, 1})
248+
ConfigSampler{5, 1, 1}(00000)
249+
250+
julia> zero(ConfigSampler{5, 1, 1})
251+
ConfigSampler{5, 1, 1}(11111)
214252
```
215253
"""
216254
struct ConfigSampler{N,S,C}

src/bitvector.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
"""
22
StaticElementVector{N,S,C}
3+
StaticElementVector(nflavor::Int, x::AbstractVector)
34
45
`N` is the length of vector, `C` is the size of storage in unit of `UInt64`,
56
`S` is the stride defined as the `log2(# of flavors)`.
67
When the number of flavors is 2, it is a `StaticBitVector`.
8+
9+
Example
10+
-------------------------------
11+
```jldoctest; setup=:(using GraphTensorNetworks)
12+
julia> ev = StaticElementVector(3, [1,2,0,1,2])
13+
12012
14+
15+
julia> ev[2]
16+
0x0000000000000002
17+
```
718
"""
819
struct StaticElementVector{N,S,C}
920
data::NTuple{C,UInt64}
@@ -26,6 +37,9 @@ Base.:(==)(x::StaticElementVector{N,S,C}, y::StaticElementVector{N,S,C}) where {
2637
end
2738
end
2839
function StaticElementVector(nflavor::Int, x::AbstractVector)
40+
if any(x->x<0 || x>=nflavor, x)
41+
throw(ArgumentError("Vector elements must be in range `[0, $(nflavor-1)]`, got $x."))
42+
end
2943
N = length(x)
3044
S = ceil(Int,log2(nflavor)) # sometimes can not devide 64.
3145
convert(StaticElementVector{N,S,_nints(N,S)}, x)
@@ -69,6 +83,17 @@ end
6983
##### BitVectors
7084
"""
7185
StaticBitVector{N,C} = StaticElementVector{N,1,C}
86+
StaticBitVector(x::AbstractVector)
87+
88+
Example
89+
-------------------------------
90+
```jldoctest; setup=:(using GraphTensorNetworks)
91+
julia> sb = StaticBitVector([1,0,0,1,1])
92+
10011
93+
94+
julia> sb[3]
95+
0x0000000000000000
96+
```
7297
"""
7398
const StaticBitVector{N,C} = StaticElementVector{N,1,C}
7499
@inline function Base.getindex(x::StaticBitVector{N,C}, i::Integer) where {N,C}

src/networks/Coloring.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
Coloring{K,CT<:AbstractEinsum} <: GraphProblem
33
Coloring{K}(graph; openvertices=(), optimizer=GreedyMethod(), simplifier=nothing)
44
5-
[Vertex Coloring](https://psychic-meme-f4d866f8.pages.github.io/dev/tutorials/Coloring.html) problem.
6-
`optimizer` and `simplifier` are for tensor network optimization, check `optimize_code` for details.
5+
The [Vertex Coloring](https://psychic-meme-f4d866f8.pages.github.io/dev/tutorials/Coloring.html) problem.
6+
`optimizer` and `simplifier` are for tensor network optimization, check [`optimize_code`](@ref) for details.
77
"""
88
struct Coloring{K,CT<:AbstractEinsum} <: GraphProblem
99
code::CT

src/networks/IndependentSet.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
The [independent set problem](https://psychic-meme-f4d866f8.pages.github.io/dev/tutorials/IndependentSet.html) in graph theory.
77
In the constructor, `weights` are the weights of vertices.
88
`openvertices` specifies labels for the output tensor.
9-
`optimizer` and `simplifier` are for tensor network optimization, check `optimize_code` for details.
9+
`optimizer` and `simplifier` are for tensor network optimization, check [`optimize_code`](@ref) for details.
1010
"""
1111
struct IndependentSet{CT<:AbstractEinsum,WT<:Union{UnWeighted, Vector}} <: GraphProblem
1212
code::CT

src/networks/Matching.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
Matching{CT<:AbstractEinsum} <: GraphProblem
33
Matching(graph; openvertices=(), optimizer=GreedyMethod(), simplifier=nothing)
44
5-
[Vertex matching](https://psychic-meme-f4d866f8.pages.github.io/dev/tutorials/Matching.html) problem.
6-
`optimizer` and `simplifier` are for tensor network optimization, check `optimize_code` for details.
5+
The [Vertex matching](https://psychic-meme-f4d866f8.pages.github.io/dev/tutorials/Matching.html) problem.
6+
`optimizer` and `simplifier` are for tensor network optimization, check [`optimize_code`](@ref) for details.
77
"""
88
struct Matching{CT<:AbstractEinsum} <: GraphProblem
99
symbols::Vector{Tuple{Int,Int}}

0 commit comments

Comments
 (0)