Skip to content

Commit

Permalink
Redo weighted map (#30)
Browse files Browse the repository at this point in the history
* update

* save

* save

* save

* redo trace center

* update docs
  • Loading branch information
GiggleLiu authored Feb 26, 2022
1 parent e7cba47 commit 9d6098f
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 139 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name = "UnitDiskMapping"
uuid = "1b61a8d9-79ed-4491-8266-ef37f39e1727"
authors = ["QuEra Computing Inc."]
version = "0.1.0"
version = "0.1.1"

[deps]
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"

[compat]
Graphs = "1.4"
Graphs = "1.6"
julia = "1"

[extras]
Expand Down
100 changes: 72 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@ The generic tensor network approach for solving MIS works best for graphs with s
```julia
julia> using GraphTensorNetworks

julia> gp = Independence(SimpleGraph(res.grid_graph); optimizer=TreeSA(ntrials=1, niters=10), simplifier=MergeGreedy());
julia> gp = IndependentSet(SimpleGraph(res.grid_graph); optimizer=TreeSA(ntrials=1, niters=10), simplifier=MergeGreedy());

julia> misconfig = solve(gp, "config max")[].c;
julia> misconfig = solve(gp, SingleConfigMax())[].c.data
10110001000110000111000001010101011000001111000001101010101010000101110100000010010101010101010001000000100111010000001001101000101010001110010001000101110100111010100010110100100110101010110100011100101010101010100011

# create a grid mask as the solution, where occupied locations are marked as value 1.
julia> c = zeros(Int, size(res.grid_graph.content));

julia> for (i, loc) in enumerate(findall(!isempty, res.grid_graph.content))
c[loc] = misconfig.data[i]
c[loc] = misconfig[i]
end

julia> print_config(res, c)
Expand Down Expand Up @@ -131,7 +132,7 @@ julia> print_config(res, c)

#### Step 3: solve the MIS solution back an MIS of the source graph
```julia
julia> original_configs = map_configs_back(res, [c])
julia> original_configs = map_configs_back(res, [misconfig])
1-element Vector{Vector{Int64}}:
[1, 0, 0, 1, 0, 0, 1, 1, 0, 0]

Expand All @@ -150,31 +151,74 @@ julia> w_res = map_graph(Weighted(), g, vertex_order=Branching());
julia> println(w_res.grid_graph)
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ● ● ● ● ○
```

Here, `` is a vertex having weight 3, `` is a vertex having weight 2 and `` is a vertex having weight 1.
One can add some weights in range 0~1 by typing

```julia
julia> source_weights = 0.05:0.1:0.95
0.05:0.1:0.95

julia> mapped_weights = map_weights(w_res, source_weights)
218-element Vector{Float64}:
1.85
2.0
1.95
2.0
2.0
2.0
1.0
2.0
2.0
2.0
2.0
1.0
2.0
```

One can easily check the correctness
```julia
julia> wr1 = solve(IndependentSet(g; weights=collect(source_weights)), SingleConfigMax())[]
(2.2, ConfigSampler{10, 1, 1}(0100100110))ₜ

julia> wr2 = solve(IndependentSet(SimpleGraph(w_res.grid_graph); weights=mapped_weights), SingleConfigMax())[].c.data
(178.2, ConfigSampler{218, 1, 4}(10001110100000111000110101000100010110010010110010010001010101100010011001010000101000100010101010010100001001101100000110010001010101010001100000110110010010111011000001111000010110101011010010101010101010101010100101))ₜ

julia> wr2.n - w_res.mis_overhead
2.1999999999999886

julia> map_configs_back(w_res, [wr2])
1-element Vector{Vector{Int64}}:
[0, 1, 0, 0, 1, 0, 0, 1, 1, 0]
```

Yep! We get exactly the same ground state.
4 changes: 2 additions & 2 deletions examples/petersen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ G, tape = apply_gadgets!(copy(ug))
locs = coordinates(G)

using GraphTensorNetworks
s1 = solve(Independence(g), "size max")
s2 = solve(Independence(SimpleGraph(G)), "size max")
s1 = solve(IndependentSet(g), SizeMax())
s2 = solve(IndependentSet(SimpleGraph(G)), SizeMax())
mis_overhead0 = 2 * nv(g) * (nv(g)-1) + nv(g)
mis_overhead1 = sum(x->mis_overhead(x[1]), tape)
s1[].n == s2[].n - mis_overhead0 - mis_overhead1
8 changes: 4 additions & 4 deletions project/createmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using UnitDiskMapping, GraphTensorNetworks, Graphs

function mapped_entry_to_compact(s::Pattern)
locs, g, pins = mapped_graph(s)
a = solve(Independence(g; openvertices=pins), "size max")
a = solve(IndependentSet(g; openvertices=pins), SizeMax())
b = mis_compactify!(copy(a))
n = length(a)
d = Dict{Int,Int}() # the mapping from bad to good
Expand All @@ -27,7 +27,7 @@ end
# from mapped graph bounary configuration to compact bounary configuration
function source_entry_to_configs(s::Pattern)
locs, g, pins = source_graph(s)
a = solve(Independence(g, openvertices=pins), "configs max")
a = solve(IndependentSet(g, openvertices=pins), ConfigsMax())
d = Dict{Int,Vector{BitVector}}() # the mapping from bad to good
for i=1:length(a)
d[i-1] = [BitVector(s) for s in a[i].c.data]
Expand All @@ -38,8 +38,8 @@ end
function compute_mis_overhead(s)
locs1, g1, pins1 = source_graph(s)
locs2, g2, pins2 = mapped_graph(s)
m1 = mis_compactify!(solve(Independence(g1, openvertices=pins1), "size max"))
m2 = mis_compactify!(solve(Independence(g2, openvertices=pins2), "size max"))
m1 = mis_compactify!(solve(IndependentSet(g1, openvertices=pins1), SizeMax()))
m2 = mis_compactify!(solve(IndependentSet(g2, openvertices=pins2), SizeMax()))
@assert nv(g1) == length(locs1) && nv(g2) == length(locs2)
sig, diff = UnitDiskMapping.is_diff_by_const(GraphTensorNetworks.content.(m1), GraphTensorNetworks.content.(m2))
@assert sig
Expand Down
4 changes: 2 additions & 2 deletions project/map_config_back.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ using GraphTensorNetworks, Graphs

function all_configurations(p::Pattern)
mlocs, mg, mpins = mapped_graph(p)
gp = Independence(mg, openvertices=mpins)
res = solve(gp, "configs max")
gp = IndependentSet(mg, openvertices=mpins)
res = solve(gp, ConfigsMax())
configs = []
for element in res
for bs in element.c.data
Expand Down
76 changes: 59 additions & 17 deletions src/mapping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,30 +254,42 @@ function center_location(tc::CopyLine; padding::Int)
end
function copyline_locations(tc::CopyLine; padding::Int)
s = 4
nline = 0
I, J = center_location(tc; padding=padding)
locations = _weight_type(tc)[]
# grow up
for i=I+s*(tc.vstart-tc.hslot)+1:I # even number of nodes up
push!(locations, _weight2(tc, i, J))
start = I+s*(tc.vstart-tc.hslot)+1
if tc.vstart < tc.hslot
nline += 1
end
for i=I:-1:start # even number of nodes up
push!(locations, _weighted(tc, i, J, 1+(i!=start))) # half weight on last node
end
# grow down
for i=I:I+s*(tc.vstop-tc.hslot)-1 # even number of nodes down
stop = I+s*(tc.vstop-tc.hslot)-1
if tc.vstop > tc.hslot
nline += 1
end
for i=I:stop # even number of nodes down
if i == I
push!(locations, _weight2(tc, i+1, J+1))
push!(locations, _weighted(tc, i+1, J+1, 2))
else
push!(locations, _weight2(tc, i, J))
push!(locations, _weighted(tc, i, J, 1+(i!=stop)))
end
end
# grow right
for j=J+2:J+s*(tc.hstop-tc.vslot)-1 # even number of nodes right
push!(locations, _weight2(tc, I, j))
stop = J+s*(tc.hstop-tc.vslot)-1
if tc.hstop > tc.vslot
nline += 1
end
push!(locations, _weight1(tc, I, J+1)) # center node
for j=J+2:stop # even number of nodes right
push!(locations, _weighted(tc, I, j, 1 + (j!=stop))) # half weight on last node
end
push!(locations, _weighted(tc, I, J+1, nline)) # center node
return locations
end
_weight_type(::CopyLine{UnWeighted}) = SimpleNode{Int}
_weight2(::CopyLine{UnWeighted}, i, j) = SimpleNode(i, j)
_weight1(::CopyLine{UnWeighted}, i, j) = SimpleNode(i, j)
_weighted(::CopyLine{UnWeighted}, i, j, w) = SimpleNode(i, j)

export ugrid
function ugrid(mode, g::SimpleGraph, vertex_order::AbstractVector{Int}; padding=2, nrow=nv(g))
Expand Down Expand Up @@ -342,9 +354,20 @@ end
export mis_overhead_copylines
function mis_overhead_copylines(ug::UGrid{WC,W}) where {WC,W}
sum(ug.lines) do line
locs = copyline_locations(line; padding=ug.padding)
mis_overhead_copyline(line)
end
end

function mis_overhead_copyline(line::CopyLine{W}) where {W}
if W === Weighted
s = 4
return (line.hslot - line.vstart) * s +
(line.vstop - line.hslot) * s +
max((line.hstop - line.vslot) * s - 2, 0)
else
locs = copyline_locations(line; padding=2)
@assert length(locs) % 2 == 1
W === Weighted ? length(locs)-1 : length(locs) ÷ 2
return length(locs) ÷ 2
end
end

Expand All @@ -360,20 +383,23 @@ end
"""
map_graph([mode=Weighted(),] g::SimpleGraph; vertex_order=Branching(), ruleset=[...])
Map a graph to a unit disk grid graph that being "equivalent" to the original graph.
Map a graph to a unit disk grid graph that being "equivalent" to the original graph, and return a `MappingResult` instance.
Here "equivalent" means a maximum independent set in the grid graph can be mapped back to
a maximum independent set of the original graph in polynomial time.
Positional Arguments
-------------------------------------
* `mode` is optional, it can be `Weighted()` (default) or `UnWeighted()`.
* `g` is a graph instance, check the documentation of [`Graphs`](https://juliagraphs.org/Graphs.jl/dev/) for details.
* `mode` is optional, it can be `Weighted()` (default) or `UnWeighted`.
Keyword Arguments
-------------------------------------
* `vertex_order` specifies the order finding algorithm for vertices.
Different vertex orders have different path width, i.e. different depth of mapped grid graph.
It can be a vector or one of the following inputs
* `Greedy()` fast but not optimal.
* `Branching()` slow but optimal.
* `ruleset` specifies and extra set of optimization patterns (not the crossing patterns).
Returns a `MappingResult` instance.
"""
function map_graph(g::SimpleGraph; vertex_order=Branching(), ruleset=default_simplifier_ruleset(UnWeighted()))
map_graph(UnWeighted(), g; ruleset=ruleset, vertex_order=vertex_order)
Expand All @@ -388,7 +414,23 @@ function map_graph(mode, g::SimpleGraph; vertex_order=Branching(), ruleset=defau
return MappingResult(ug, vcat(tape, tape2) , mis_overhead0 + mis_overhead1 + mis_overhead2)
end

map_configs_back(r::MappingResult{<:Cell}, configs::AbstractVector) = unapply_gadgets!(copy(r.grid_graph), r.mapping_history, copy.(configs))[2]
"""
map_configs_back(res::MappingResult, configs::AbstractVector)
Map MIS solutions for the mapped graph to a solution for the source graph.
"""
function map_configs_back(res::MappingResult, configs::AbstractVector)
cs = map(configs) do cfg
c = zeros(Int, size(res.grid_graph.content))
for (i, loc) in enumerate(findall(!isempty, res.grid_graph.content))
c[loc] = cfg[i]
end
c
end
return _map_configs_back(res, cs)
end
_map_configs_back(r::MappingResult{<:Cell}, configs::AbstractVector{<:AbstractMatrix}) = unapply_gadgets!(copy(r.grid_graph), r.mapping_history, copy.(configs))[2]

default_simplifier_ruleset(::UnWeighted) = vcat([rotated_and_reflected(rule) for rule in simplifier_ruleset]...)
default_simplifier_ruleset(::Weighted) = weighted.(default_simplifier_ruleset(UnWeighted()))

Expand Down
Loading

0 comments on commit 9d6098f

Please sign in to comment.