diff --git a/.gitignore b/.gitignore index 6b1d5a0..13c6fe9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.vscode/ /Manifest.toml +.DS_Store diff --git a/project/createmap.jl b/project/createmap.jl index 27fbc86..8f76727 100644 --- a/project/createmap.jl +++ b/project/createmap.jl @@ -1,4 +1,4 @@ -using UnitDiskMapping, GraphTensorNetworks +using UnitDiskMapping, GraphTensorNetworks, Graphs function mapped_entry_to_compact(s::Pattern) locs, g, pins = mapped_graph(s) @@ -40,8 +40,8 @@ function compute_mis_overhead(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")) - @test nv(g1) == length(locs1) && nv(g2) == length(locs2) - sig, diff = UnitDiskMapping.is_diff_by_const(content.(m1), content.(m2)) + @assert nv(g1) == length(locs1) && nv(g2) == length(locs2) + sig, diff = UnitDiskMapping.is_diff_by_const(GraphTensorNetworks.content.(m1), GraphTensorNetworks.content.(m2)) @assert sig return diff end @@ -71,7 +71,9 @@ function dump_mapping_to_julia(filename, patterns) end end + dump_mapping_to_julia(joinpath(@__DIR__, "..", "src", "extracting_results.jl"), (Cross{false}(), Cross{true}(), Turn(), WTurn(), Branch(), BranchFix(), TrivialTurn(), TCon(), BranchFixB(), - UnitDiskMapping.simplifier_ruleset...)) \ No newline at end of file + EndTurn(), + UnitDiskMapping.simplifier_ruleset...)) diff --git a/src/UnitDiskMapping.jl b/src/UnitDiskMapping.jl index d3efda6..95a6b35 100644 --- a/src/UnitDiskMapping.jl +++ b/src/UnitDiskMapping.jl @@ -6,8 +6,10 @@ using Graphs export UGrid, apply_crossing_gadgets!, apply_simplifier_gadgets!, apply_gadget!, embed_graph export unapply_gadgets!, unmatch -export Pattern, Corner, Turn, Cross, source_graph, mapped_graph, TruncatedTurn +export Pattern, Corner, Turn, Cross, source_graph, mapped_graph, TruncatedTurn, EndTurn export mapped_entry_to_compact, source_entry_to_configs, map_config_back, mis_overhead +export UNode, contract_graph, compress_graph_ug, compress_graph_loc +export unitdisk_graph include("utils.jl") include("gadgets.jl") @@ -15,5 +17,6 @@ include("simplifiers.jl") include("mapping.jl") include("extracting_results.jl") include("pathdecomposition/pathdecomposition.jl") +include("shrinking/compressUDG.jl") end diff --git a/src/extracting_results.jl b/src/extracting_results.jl index 0ce8d8b..19bad27 100644 --- a/src/extracting_results.jl +++ b/src/extracting_results.jl @@ -5,7 +5,7 @@ function mapped_entry_to_compact(::Cross{false}) end function source_entry_to_configs(::Cross{false}) - return Dict(Pair{Int64, Vector{BitVector}}[5 => [[1, 0, 0, 1, 0, 0, 1, 0, 1], [1, 0, 1, 0, 0, 0, 1, 0, 1]], 12 => [[0, 1, 0, 0, 1, 0, 1, 0, 1], [0, 0, 1, 0, 1, 0, 1, 0, 1]], 8 => [[0, 1, 0, 0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0]], 1 => [[1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 1, 0, 0]], 0 => [[0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 1, 0, 0]], 6 => [[0, 1, 0, 1, 0, 1, 0, 0, 1]], 11 => [[1, 0, 1, 0, 1, 1, 0, 1, 0]], 9 => [[1, 0, 1, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 0]], 14 => [[0, 1, 0, 0, 1, 1, 0, 0, 1], [0, 0, 1, 0, 1, 1, 0, 0, 1]], 3 => [[1, 0, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 1, 0]], 7 => [[1, 0, 0, 1, 0, 1, 0, 0, 1], [1, 0, 1, 0, 0, 1, 0, 0, 1]], 4 => [[0, 1, 0, 1, 0, 0, 1, 0, 1]], 13 => [[1, 0, 1, 0, 1, 0, 1, 0, 1]], 15 => [[1, 0, 1, 0, 1, 1, 0, 0, 1]], 2 => [[0, 1, 0, 1, 0, 1, 0, 1, 0]], 10 => [[0, 1, 0, 0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 1, 1, 0, 1, 0]]]) + return Dict(Pair{Int64, Vector{BitVector}}[5 => [[1, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 1, 0, 0, 1, 0, 1]], 12 => [[0, 0, 1, 0, 1, 0, 1, 0, 1], [0, 1, 0, 0, 1, 0, 1, 0, 1]], 8 => [[0, 0, 1, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0, 0]], 1 => [[1, 0, 1, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 0, 1, 0, 0]], 0 => [[0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 1, 0, 0]], 6 => [[0, 1, 0, 1, 0, 1, 0, 0, 1]], 11 => [[1, 0, 1, 0, 1, 1, 0, 1, 0]], 9 => [[1, 0, 1, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 0]], 14 => [[0, 0, 1, 0, 1, 1, 0, 0, 1], [0, 1, 0, 0, 1, 1, 0, 0, 1]], 3 => [[1, 0, 1, 0, 0, 1, 0, 1, 0], [1, 0, 0, 1, 0, 1, 0, 1, 0]], 7 => [[1, 0, 1, 0, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 1, 0, 0, 1]], 4 => [[0, 1, 0, 1, 0, 0, 1, 0, 1]], 13 => [[1, 0, 1, 0, 1, 0, 1, 0, 1]], 15 => [[1, 0, 1, 0, 1, 1, 0, 0, 1]], 2 => [[0, 1, 0, 1, 0, 1, 0, 1, 0]], 10 => [[0, 0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 0, 0, 1, 1, 0, 1, 0]]]) end mis_overhead(::Cross{false}) = -1.0 @@ -27,7 +27,7 @@ function mapped_entry_to_compact(::Turn) end function source_entry_to_configs(::Turn) - return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0]], 2 => [[0, 0, 1, 0, 1], [0, 1, 0, 0, 1]], 3 => [[1, 0, 1, 0, 1]], 1 => [[1, 0, 0, 1, 0], [1, 0, 1, 0, 0]]]) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0]], 2 => [[0, 0, 1, 0, 1], [0, 1, 0, 0, 1]], 3 => [[1, 0, 1, 0, 1]], 1 => [[1, 0, 1, 0, 0], [1, 0, 0, 1, 0]]]) end mis_overhead(::Turn) = -1.0 @@ -49,7 +49,7 @@ function mapped_entry_to_compact(::Branch) end function source_entry_to_configs(::Branch) - return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0, 0, 1, 0]], 4 => [[0, 1, 0, 0, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 1], [0, 1, 0, 1, 0, 0, 0, 1]], 5 => [[1, 0, 1, 0, 0, 1, 0, 1]], 6 => [[0, 1, 0, 0, 1, 1, 0, 1], [0, 0, 1, 0, 1, 1, 0, 1]], 2 => [[0, 1, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 0, 1, 1, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0]], 7 => [[1, 0, 1, 0, 1, 1, 0, 1]], 3 => [[1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 0, 0]], 1 => [[1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 0, 1, 0]]]) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0, 0, 1, 0]], 4 => [[0, 1, 0, 0, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 1], [0, 1, 0, 1, 0, 0, 0, 1]], 5 => [[1, 0, 1, 0, 0, 1, 0, 1]], 6 => [[0, 1, 0, 0, 1, 1, 0, 1], [0, 0, 1, 0, 1, 1, 0, 1]], 2 => [[0, 1, 0, 0, 1, 1, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0]], 7 => [[1, 0, 1, 0, 1, 1, 0, 1]], 3 => [[1, 0, 1, 0, 1, 1, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0]], 1 => [[1, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 1, 0]]]) end mis_overhead(::Branch) = -1.0 @@ -60,7 +60,7 @@ function mapped_entry_to_compact(::BranchFix) end function source_entry_to_configs(::BranchFix) - return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 0]], 2 => [[0, 1, 0, 1, 0, 1]], 3 => [[1, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 1]], 1 => [[1, 0, 1, 0, 1, 0]]]) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0]], 2 => [[0, 1, 0, 1, 0, 1]], 3 => [[1, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 1]], 1 => [[1, 0, 1, 0, 1, 0]]]) end mis_overhead(::BranchFix) = -1.0 @@ -99,6 +99,17 @@ end mis_overhead(::BranchFixB) = -1.0 +function mapped_entry_to_compact(::EndTurn) + return Dict([0 => 0, 1 => 1]) +end + +function source_entry_to_configs(::EndTurn) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 0, 1], [0, 1, 0]], 1 => [[1, 0, 1]]]) +end + +mis_overhead(::EndTurn) = -1.0 + + function mapped_entry_to_compact(::UnitDiskMapping.DanglingLeg) return Dict([0 => 0, 1 => 1]) end @@ -108,3 +119,36 @@ function source_entry_to_configs(::UnitDiskMapping.DanglingLeg) end mis_overhead(::UnitDiskMapping.DanglingLeg) = -1.0 + + +function mapped_entry_to_compact(::UnitDiskMapping.Square) + return Dict([0 => 0, 2 => 2, 3 => 3, 1 => 1]) +end + +function source_entry_to_configs(::UnitDiskMapping.Square) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 0, 1, 0], [0, 0, 0, 1]], 2 => [[0, 1, 1, 0]], 3 => [], 1 => [[1, 0, 0, 1]]]) +end + +mis_overhead(::UnitDiskMapping.Square) = -1.0 + + +function mapped_entry_to_compact(::UnitDiskMapping.Cane) + return Dict([0 => 0, 2 => 0, 3 => 3, 1 => 0]) +end + +function source_entry_to_configs(::UnitDiskMapping.Cane) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 0, 1, 0]], 2 => [[0, 1, 0, 0, 1], [0, 0, 1, 0, 1]], 3 => [[1, 0, 1, 0, 1]], 1 => [[1, 0, 0, 1, 0], [1, 0, 1, 0, 0]]]) +end + +mis_overhead(::UnitDiskMapping.Cane) = -1.0 + + +function mapped_entry_to_compact(::UnitDiskMapping.CLoop) + return Dict([0 => 0, 2 => 0, 3 => 3, 1 => 0]) +end + +function source_entry_to_configs(::UnitDiskMapping.CLoop) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 1, 1, 0, 0]], 2 => [[0, 1, 0, 0, 1], [1, 0, 0, 0, 1]], 3 => [[1, 0, 0, 1, 1]], 1 => [[0, 0, 1, 1, 0], [1, 0, 0, 1, 0]]]) +end + +mis_overhead(::UnitDiskMapping.CLoop) = -1.0 diff --git a/src/gadgets.jl b/src/gadgets.jl index 5d9a480..d246f08 100644 --- a/src/gadgets.jl +++ b/src/gadgets.jl @@ -108,18 +108,18 @@ end struct Cross{CON} <: CrossPattern end iscon(::Cross{CON}) where {CON} = CON -# ⋅ ● ⋅ -# ◆ ◉ ● -# ⋅ ◆ ⋅ +# ⋅ ● ⋅ +# ◆ ◉ ● +# ⋅ ◆ ⋅ function source_graph(::Cross{true}) locs = [(2,1), (2,2), (2,3), (1,2), (2,2), (3,2)] g = simplegraph([(1,2), (2,3), (4,5), (5,6), (1,6)]) return locs, g, [1,4,6,3] end -# ⋅ ● ⋅ -# ● ● ● -# ⋅ ● ⋅ +# ⋅ ● ⋅ +# ● ● ● +# ⋅ ● ⋅ function mapped_graph(::Cross{true}) locs = [(2,1), (2,2), (2,3), (1,2), (3,2)] locs, unitdisk_graph(locs, 1.5), [1,4,5,3] @@ -128,20 +128,20 @@ Base.size(::Cross{true}) = (3, 3) cross_location(::Cross{true}) = (2,2) connect_locations(::Cross{true}) = [(2, 1), (3,2)] -# ⋅ ⋅ ● ⋅ ⋅ -# ● ● ◉ ● ● -# ⋅ ⋅ ● ⋅ ⋅ -# ⋅ ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ● ⋅ ⋅ +# ● ● ◉ ● ● +# ⋅ ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ● ⋅ ⋅ function source_graph(::Cross{false}) locs = [(2,1), (2,2), (2,3), (2,4), (2,5), (1,3), (2,3), (3,3), (4,3)] g = simplegraph([(1,2), (2,3), (3,4), (4,5), (6,7), (7,8), (8,9)]) return locs, g, [1,6,9,5] end -# ⋅ ⋅ ● ⋅ ⋅ -# ● ● ● ● ● -# ⋅ ● ● ● ⋅ -# ⋅ ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ● ⋅ ⋅ +# ● ● ● ● ● +# ⋅ ● ● ● ⋅ +# ⋅ ⋅ ● ⋅ ⋅ function mapped_graph(::Cross{false}) locs = [(2,1), (2,2), (2,3), (2,4), (2,5), (1,3), (3,3), (4,3), (3, 2), (3,4)] locs, unitdisk_graph(locs, 1.5), [1,6,8,5] @@ -151,9 +151,9 @@ cross_location(::Cross{false}) = (2,3) struct Turn <: CrossPattern end iscon(::Turn) = false -# ⋅ ● ⋅ ⋅ -# ⋅ ● ⋅ ⋅ -# ⋅ ● ● ● +# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ● ● # ⋅ ⋅ ⋅ ⋅ function source_graph(::Turn) locs = [(1,2), (2,2), (3,2), (3,3), (3,4)] @@ -161,9 +161,9 @@ function source_graph(::Turn) return locs, g, [1,5] end -# ⋅ ● ⋅ ⋅ -# ⋅ ⋅ ● ⋅ -# ⋅ ⋅ ⋅ ● +# ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ● ⋅ +# ⋅ ⋅ ⋅ ● # ⋅ ⋅ ⋅ ⋅ function mapped_graph(::Turn) locs = [(1,2), (2,3), (3,4)] @@ -175,20 +175,20 @@ cross_location(::Turn) = (3,2) export Branch, TrivialTurn, BranchFix, WTurn, TCon, BranchFixB struct Branch <: CrossPattern end -# ⋅ ● ⋅ ⋅ -# ⋅ ● ⋅ ⋅ -# ⋅ ● ● ● -# ⋅ ● ● ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ● ● +# ⋅ ● ● ⋅ # ⋅ ● ⋅ ⋅ function source_graph(::Branch) locs = [(1,2), (2,2), (3,2),(3,3),(3,4),(4,3),(4,2),(5,2)] g = simplegraph([(1,2), (2,3), (3, 4), (4,5), (4,6), (6,7), (7,8)]) return locs, g, [1, 5, 8] end -# ⋅ ● ⋅ ⋅ -# ⋅ ⋅ ● ⋅ -# ⋅ ● ⋅ ● -# ⋅ ⋅ ● ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ● ⋅ +# ⋅ ● ⋅ ● +# ⋅ ⋅ ● ⋅ # ⋅ ● ⋅ ⋅ function mapped_graph(::Branch) locs = [(1,2), (2,3), (3,2),(3,4),(4,3),(5,2)] @@ -199,19 +199,19 @@ cross_location(::Branch) = (3,2) iscon(::Branch) = false struct BranchFix <: CrossPattern end -# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ● ⋅ # ⋅ ● ● ⋅ -# ⋅ ● ● ⋅ # ⋅ ● ⋅ ⋅ function source_graph(::BranchFix) locs = [(1,2), (2,2), (2,3),(3,3),(3,2),(4,2)] g = simplegraph([(1,2), (2,3), (3,4),(4,5), (5,6)]) return locs, g, [1, 6] end -# ⋅ ● ⋅ ⋅ -# ⋅ ● ⋅ ⋅ # ⋅ ● ⋅ ⋅ -# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ +# ⋅ ● ⋅ ⋅ function mapped_graph(::BranchFix) locs = [(1,2),(2,2),(3,2),(4,2)] return locs, unitdisk_graph(locs, 1.5), [1, 4] @@ -221,18 +221,18 @@ cross_location(::BranchFix) = (2,2) iscon(::BranchFix) = false struct WTurn <: CrossPattern end -# ⋅ ⋅ ⋅ ⋅ -# ⋅ ⋅ ● ● -# ⋅ ● ● ⋅ +# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ● ● +# ⋅ ● ● ⋅ # ⋅ ● ⋅ ⋅ function source_graph(::WTurn) locs = [(2,3), (2,4), (3,2),(3,3),(4,2)] g = simplegraph([(1,2), (1,4), (3,4),(3,5)]) return locs, g, [2, 5] end -# ⋅ ⋅ ⋅ ⋅ -# ⋅ ⋅ ⋅ ● -# ⋅ ⋅ ● ⋅ +# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ● +# ⋅ ⋅ ● ⋅ # ⋅ ● ⋅ ⋅ function mapped_graph(::WTurn) locs = [(2,4),(3,3),(4,2)] @@ -243,19 +243,19 @@ cross_location(::WTurn) = (2,2) iscon(::WTurn) = false struct BranchFixB <: CrossPattern end -# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ # ⋅ ⋅ ● ⋅ -# ⋅ ● ● ⋅ +# ⋅ ● ● ⋅ # ⋅ ● ⋅ ⋅ function source_graph(::BranchFixB) locs = [(2,3),(3,3),(3,2),(4,2)] g = simplegraph([(1,3), (2,3), (2,4)]) return locs, g, [1, 4] end -# ⋅ ⋅ ⋅ ⋅ -# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ +# ⋅ ● ⋅ ⋅ # ⋅ ● ⋅ ⋅ -# ⋅ ● ⋅ ⋅ function mapped_graph(::BranchFixB) locs = [(3,2),(4,2)] return locs, unitdisk_graph(locs, 1.5), [1, 2] @@ -267,7 +267,7 @@ iscon(::BranchFixB) = false struct TCon <: CrossPattern end # ⋅ ◆ ⋅ ⋅ -# ◆ ● ⋅ ⋅ +# ◆ ● ⋅ ⋅ # ⋅ ● ⋅ ⋅ function source_graph(::TCon) locs = [(1,2), (2,1), (2,2),(3,2)] @@ -306,6 +306,26 @@ cross_location(::TrivialTurn) = (2,2) iscon(::TrivialTurn) = true connect_locations(::TrivialTurn) = [(1,2), (2,1)] +struct EndTurn <: CrossPattern end +# ⋅ ● ⋅ ⋅ +# ⋅ ● ● ⋅ +# ⋅ ⋅ ⋅ ⋅ +function source_graph(::EndTurn) + locs = [(1,2), (2,2), (2,3)] + g = simplegraph([(1,2), (2,3)]) + return locs, g, [1] +end +# ⋅ ● ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ +function mapped_graph(::EndTurn) + locs = [(1,2)] + return locs, unitdisk_graph(locs, 1.5), [1] +end +Base.size(::EndTurn) = (3,4) +cross_location(::EndTurn) = (2,2) +iscon(::EndTurn) = false + ############## Rotation and Flip ############### export RotatedGadget, ReflectedGadget struct RotatedGadget{GT} <: Pattern @@ -402,4 +422,4 @@ function _boundary_config(pins, config) res += Int(config[p]) << (i-1) end return res -end \ No newline at end of file +end diff --git a/src/mapping.jl b/src/mapping.jl index 13b3543..d70a2d7 100644 --- a/src/mapping.jl +++ b/src/mapping.jl @@ -72,7 +72,7 @@ end const crossing_ruleset = (Cross{false}(), Turn(), WTurn(), Branch(), BranchFix(), TCon(), TrivialTurn(), RotatedGadget(TCon(), 1), ReflectedGadget(Cross{true}(), "y"), - ReflectedGadget(TrivialTurn(), "y"), BranchFixB(), + ReflectedGadget(TrivialTurn(), "y"), BranchFixB(), EndTurn(), ReflectedGadget(RotatedGadget(TCon(), 1), "y")) function apply_crossing_gadgets!(ug::UGrid, ruleset=crossing_ruleset) tape = Tuple{Pattern,Int,Int}[] @@ -92,7 +92,29 @@ function apply_crossing_gadgets!(ug::UGrid, ruleset=crossing_ruleset) return ug, tape end -function apply_simplifier_gadgets!(ug::UGrid; ruleset, nrepeat::Int=10) +function apply_simplifier_gadgets!(ug::UGrid; ruleset=[RotatedGadget(DanglingLeg(), 0), + RotatedGadget(DanglingLeg(), 1), RotatedGadget(DanglingLeg(), 2), + RotatedGadget(DanglingLeg(), 3), RotatedGadget(Square(), 0), + RotatedGadget(Square(), 1), RotatedGadget(Square(), 2), + RotatedGadget(Square(), 3), RotatedGadget(Cane(), 0), + RotatedGadget(Cane(), 1), RotatedGadget(Cane(), 2), + RotatedGadget(Cane(), 3), RotatedGadget(ReflectedGadget(Cane(), "y"),0), + RotatedGadget(ReflectedGadget(Cane(), "y"),1), + RotatedGadget(ReflectedGadget(Cane(), "y"),2), + RotatedGadget(ReflectedGadget(Cane(), "y"),3), + RotatedGadget(ReflectedGadget(Cane(), "x"),0), + RotatedGadget(ReflectedGadget(Cane(), "x"),1), + RotatedGadget(ReflectedGadget(Cane(), "x"),2), + RotatedGadget(ReflectedGadget(Cane(), "x"),3), RotatedGadget(CLoop(), 0), + RotatedGadget(CLoop(), 1), RotatedGadget(CLoop(), 2), + RotatedGadget(CLoop(), 3), RotatedGadget(ReflectedGadget(CLoop(), "y"),0), + RotatedGadget(ReflectedGadget(CLoop(), "y"),1), + RotatedGadget(ReflectedGadget(CLoop(), "y"),2), + RotatedGadget(ReflectedGadget(CLoop(), "y"),3), + RotatedGadget(ReflectedGadget(CLoop(), "x"),0), + RotatedGadget(ReflectedGadget(CLoop(), "x"),1), + RotatedGadget(ReflectedGadget(CLoop(), "x"),2), + RotatedGadget(ReflectedGadget(CLoop(), "x"),3)], nrepeat::Int=10) tape = Tuple{Pattern,Int,Int}[] for _ in 1:nrepeat, pattern in ruleset for j=0:size(ug.content, 2) # start from 0 because there can be one empty padding column/row. @@ -327,7 +349,29 @@ a maximum independent set of the original graph in polynomial time. Returns a `MappingResult` instance. """ -function map_graph(g::SimpleGraph; ruleset=[RotatedGadget(DanglingLeg(), n) for n=0:3]) +function map_graph(g::SimpleGraph; ruleset=[RotatedGadget(DanglingLeg(), 0), + RotatedGadget(DanglingLeg(), 1), RotatedGadget(DanglingLeg(), 2), + RotatedGadget(DanglingLeg(), 3), RotatedGadget(Square(), 0), + RotatedGadget(Square(), 1), RotatedGadget(Square(), 2), + RotatedGadget(Square(), 3), RotatedGadget(Cane(), 0), + RotatedGadget(Cane(), 1), RotatedGadget(Cane(), 2), + RotatedGadget(Cane(), 3), RotatedGadget(ReflectedGadget(Cane(), "y"),0), + RotatedGadget(ReflectedGadget(Cane(), "y"),1), + RotatedGadget(ReflectedGadget(Cane(), "y"),2), + RotatedGadget(ReflectedGadget(Cane(), "y"),3), + RotatedGadget(ReflectedGadget(Cane(), "x"),0), + RotatedGadget(ReflectedGadget(Cane(), "x"),1), + RotatedGadget(ReflectedGadget(Cane(), "x"),2), + RotatedGadget(ReflectedGadget(Cane(), "x"),3), RotatedGadget(CLoop(), 0), + RotatedGadget(CLoop(), 1), RotatedGadget(CLoop(), 2), + RotatedGadget(CLoop(), 3), RotatedGadget(ReflectedGadget(CLoop(), "y"),0), + RotatedGadget(ReflectedGadget(CLoop(), "y"),1), + RotatedGadget(ReflectedGadget(CLoop(), "y"),2), + RotatedGadget(ReflectedGadget(CLoop(), "y"),3), + RotatedGadget(ReflectedGadget(CLoop(), "x"),0), + RotatedGadget(ReflectedGadget(CLoop(), "x"),1), + RotatedGadget(ReflectedGadget(CLoop(), "x"),2), + RotatedGadget(ReflectedGadget(CLoop(), "x"),3)]) ug = embed_graph(g) mis_overhead0 = mis_overhead_copylines(ug) ug, tape = apply_crossing_gadgets!(ug) @@ -337,4 +381,49 @@ function map_graph(g::SimpleGraph; ruleset=[RotatedGadget(DanglingLeg(), n) for return MappingResult(ug, vcat(tape, tape2) , mis_overhead0 + mis_overhead1 + mis_overhead2) end + map_configs_back(r::MappingResult, configs::AbstractVector) = unapply_gadgets!(copy(r.grid_graph), r.mapping_history, copy.(configs))[2] + +function compress_graph_ug(ug::UGrid) + # get locations + M = ug.content + + locs = Vector{Tuple{Int, Int}}() + + for i=1:size(ug.content)[1] + for j = 1:size(ug.content)[2] + if M[i, j] > 0 + push!(locs, (i, j)) + end + end + end + + new_locs = contract_graph(locs) + + count = 0 + + while (new_locs != locs) || (count < 10) + locs = new_locs + new_locs = contract_graph(locs) + print(count) + count += 1 + end + + return new_locs +end + + +function compress_graph_loc(locs::Vector{Tuple{Int, Int}}) + new_locs = contract_graph(locs) + + count = 0 + + while (new_locs != locs) || (count < 10) + locs = new_locs + new_locs = contract_graph(locs) + print(count) + count += 1 + end + + return new_locs +end diff --git a/src/shrinking/compressUDG.jl b/src/shrinking/compressUDG.jl new file mode 100644 index 0000000..0fbd6d0 --- /dev/null +++ b/src/shrinking/compressUDG.jl @@ -0,0 +1,309 @@ +module CompressUDG +using Graphs + +export UNode, contract_graph, CompressUDGMethod + +struct UNode + vertex::Int # vertex index in original graph + pos::Tuple{Int,Int} + neighbors::Vector{Int} # neighbors of node +end +Base.hash(unode::UNode) = hash(unode.vertex) +function Base.:(==)(x::UNode, y::UNode) + x.vertex == y.vertex && x.neighbors == y.neighbors +end + +# get surrounding neighbor points on UDG +function get_udg_neighbors(pos::Tuple{Int, Int}) + p_x, p_y = pos + + pos_udg_neighbors = Vector{Tuple{Int, Int}}() + for i=-1:1 + for j=-1:1 + if !(i == 0 && j == 0) + push!(pos_udg_neighbors, (p_x + i, p_y + j)) + end + end + end + return pos_udg_neighbors +end + +# find the UDNode given a position +# return nothing if no node at that position +function get_UNode_from_pos(pos::Tuple{Int, Int}, node_list::Vector{UNode}) + for u in node_list + if u.pos == pos + return u + end + end + return nothing +end + +# find the boundaries of a grid graph given list of UNodes +function find_boundaries(node_list::Vector{UNode}) + min_x = typemax(Int) + min_y = typemax(Int) + max_x = 0 + max_y = 0 + + for u in node_list + p_x, p_y = u.pos + + if p_x > max_x + max_x = p_x + end + if p_x < min_x + min_x = p_x + end + if p_y > max_y + max_y = p_y + end + if p_y < min_y + min_y = p_y + end + end + return min_x, min_y, max_x, max_y +end + +# find points on the boundary in which we would like to move +# divide region into 4 and move nodes greedily closer to center +function find_boundary_points(node_list::Vector{UNode}, x_min, x_max, y_min, + y_max) + half_x = (x_max - x_min)/2 + half_y = (y_max - y_min)/2 + + pts_xmin_upper = UNode[] + pts_xmax_upper = Vector{UNode}() + pts_xmin_lower = Vector{UNode}() + pts_xmax_lower = Vector{UNode}() + + pts_ymin_left = Vector{UNode}() + pts_ymax_left = Vector{UNode}() + pts_ymin_right = Vector{UNode}() + pts_ymax_right = Vector{UNode}() + + for u in node_list + p_x, p_y = u.pos + + if p_x == x_min && p_y >= half_y + push!(pts_xmin_upper, u) + end + if p_x == x_min && p_y < half_y + push!(pts_xmin_lower, u) + end + if p_x == x_max && p_y >= half_y + push!(pts_xmax_upper, u) + end + if p_x == x_max && p_y < half_y + push!(pts_xmax_lower, u) + end + if p_x >= half_x && p_y == y_min + push!(pts_ymin_right, u) + end + if p_x < half_x && p_y == y_min + push!(pts_ymin_left, u) + end + if p_x >= half_x && p_y == y_max + push!(pts_ymax_right, u) + end + if p_x < half_x && p_y == y_max + push!(pts_ymax_left, u) + end + end + + return pts_xmin_upper, pts_xmin_lower, pts_xmax_upper, pts_xmax_lower, + pts_ymin_right, pts_ymin_left, pts_ymax_right, pts_ymax_left +end + +# check that the new position of node n satisfies UDG requirements +function check_UDG_criteria(n::UNode, new_pos::Tuple{Int, Int}, node_list::Vector{UNode}) + # check if new_pos is already occupied + if get_UNode_from_pos(new_pos, node_list) != Nothing() + return false + end + + p_x, p_y = new_pos + p_neighbors = n.neighbors + + new_neighbors = Vector{Int}() + UDG_neighbor_pos = get_udg_neighbors(new_pos) + + for p in UDG_neighbor_pos + unode = get_UNode_from_pos(p, node_list) + + if unode !== nothing + if unode.vertex != n.vertex + push!(new_neighbors, unode.vertex) + end + end + end + + + if issetequal(new_neighbors, p_neighbors) == true + return true + end + return false +end + +# move node n to a new position new_pos +function move_node(n::UNode, node_list::Vector{UNode}, candidates::Vector{Tuple{Int, Int}}) + + for p in candidates + if check_UDG_criteria(n, p, node_list) == true + new_n = UNode(n.vertex, p, n.neighbors) + #n.pos = p + node_list[n.vertex] = new_n + return node_list + end + end + return node_list +end + +# determine candidates +function candidates_xmin_upper(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x + 1, p_y), (p_x + 1, p_y - 1), (p_x, p_y - 1)] +end + +function candidates_xmin_lower(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x + 1, p_y), (p_x + 1, p_y + 1), (p_x, p_y + 1)] +end + + +function candidates_xmax_upper(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x - 1, p_y), (p_x - 1, p_y - 1), (p_x, p_y - 1)] +end + + +function candidates_xmax_lower(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x - 1, p_y), (p_x - 1, p_y + 1), (p_x, p_y + 1)] +end + + +function candidates_ymin_left(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x, p_y + 1), (p_x + 1, p_y + 1), (p_x + 1, p_y)] +end + +function candidates_ymin_right(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x, p_y + 1), (p_x - 1, p_y + 1), (p_x - 1, p_y)] +end + +function candidates_ymax_left(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x, p_y - 1), (p_x + 1, p_y - 1), (p_x + 1, p_y)] +end + +function candidates_ymax_right(pos::Tuple{Int, Int}) + p_x, p_y = pos + return [(p_x, p_y - 1), (p_x - 1, p_y - 1), (p_x - 1, p_y)] +end + +function greedy_step(node_list::Vector{UNode}, min_x::Int, max_x::Int, + min_y::Int, max_y::Int) + + xmin_upper, xmin_lower, xmax_upper, xmax_lower, ymin_right, ymin_left, + ymax_right, ymax_left = find_boundary_points(node_list, min_x, max_x, + min_y, max_y) + + for p in xmin_upper + candidates = candidates_xmin_upper(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in xmin_lower + candidates = candidates_xmin_lower(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in xmax_upper + candidates = candidates_xmax_upper(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in xmax_lower + candidates = candidates_xmax_lower(p.pos) + node_list = move_node(p, node_list, candidates) + end + + for p in ymin_left + candidates = candidates_ymin_left(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in ymin_right + candidates = candidates_ymin_right(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in ymax_left + candidates = candidates_ymax_left(p.pos) + node_list = move_node(p, node_list, candidates) + end + for p in ymax_right + candidates = candidates_ymax_right(p.pos) + node_list = move_node(p, node_list, candidates) + end + + return node_list +end + +# interfaces +abstract type CompressUDGMethod end + +""" + contract_graph(locs::Vector{Tuple{Int, Int}}) + +Compute a contracted version of input graph node positions and returns a +corresponding layout of new condensed graph +""" +# execute +function udg(locs::Vector{Tuple{Int, Int}}, unit::Real) + n = length(locs) + g = SimpleGraph(n) + for i=1:n, j=i+1:n + if sum(abs2, locs[i] .- locs[j]) < unit ^ 2 + add_edge!(g, i, j) + end + end + return g +end +function contract_graph(node_positions::Vector{Tuple{Int, Int}}) + # initiate UNodes + + n_list = Vector{UNode}(undef, size(node_positions)[1]) + g = udg(node_positions, 1.5) + + for (ind, n_pos) in enumerate(node_positions) + uneighbors = neighbors(g, ind) + unode = UNode(ind, n_pos, uneighbors) + n_list[ind] = unode + end + + xmin, ymin, xmax, ymax = find_boundaries(n_list) + + while (xmax - xmin > 1) && (ymax - ymin > 1) + n_list = greedy_step(n_list, xmin, xmax, ymin, ymax) + + if xmin < xmax + xmin += 1 + xmax -= 1 + end + + if ymin < ymax + ymin += 1 + ymax -= 1 + end + end + + locs_new = Vector{Tuple{Int, Int}}(undef, size(node_positions)[1]) + for (ind, un) in enumerate(n_list) + locs_new[ind] = un.pos + end + + return locs_new +end +end + + +using .CompressUDG +export UNode, contract_graph_ug, compress_graph_loc, CompressUDGMethod diff --git a/src/simplifiers.jl b/src/simplifiers.jl index e271dfb..d58e7e7 100644 --- a/src/simplifiers.jl +++ b/src/simplifiers.jl @@ -70,18 +70,67 @@ end # # How to add a new simplification rule # 1. specify a gadget like the following. Use either `o` and `●` to specify a vertex, # either `.` or `⋅` to specify a placeholder. +# ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ +# ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ @gg DanglingLeg = - """ - ⋅ ⋅ ⋅ - ⋅ ● ⋅ - ⋅ ● ⋅ - ⋅ ● ⋅ + """ + ⋅ ⋅ ⋅ + ⋅ ● ⋅ + ⋅ ● ⋅ + ⋅ ● ⋅ """=>""" - ⋅ ⋅ ⋅ - ⋅ ⋅ ⋅ - ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ● ⋅ """ +@gg Square = + """ + ⋅ ● ⋅ ⋅ + ● ⋅ ● ⋅ + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + """=>""" + ⋅ ● ⋅ ⋅ + ● ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + """ + +@gg Cane = + """ + ⋅ ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ● ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + """=>""" + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ● ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ● ⋅ + """ + +@gg CLoop = +""" +⋅ ⋅ ⋅ ⋅ +⋅ ⋅ ● ⋅ +⋅ ● ⋅ ● +⋅ ● ⋅ ⋅ +⋅ ⋅ ● ⋅ +"""=>""" +⋅ ⋅ ⋅ ⋅ +⋅ ⋅ ⋅ ⋅ +⋅ ⋅ ⋅ ● +⋅ ⋅ ● ⋅ +⋅ ⋅ ● ⋅ +""" + + # 2. run the script `project/createmap` to generate `mis_overhead` and other informations required -# for mapping back. (Note: will overwrite the source file `src/extracting_results.jl`) \ No newline at end of file +# for mapping back. (Note: will overwrite the source file `src/extracting_results.jl`) diff --git a/test/gadgets.jl b/test/gadgets.jl index db965f0..1c06ebe 100644 --- a/test/gadgets.jl +++ b/test/gadgets.jl @@ -16,4 +16,4 @@ using Graphs @test diff == -mis_overhead(s) @test sig end -end \ No newline at end of file +end diff --git a/test/mapping.jl b/test/mapping.jl index f2a0f9c..9ac4569 100644 --- a/test/mapping.jl +++ b/test/mapping.jl @@ -60,6 +60,37 @@ end end end + +@testset "interface_K23" begin + g = SimpleGraph(5) + + add_edge!(g, 1, 5) + add_edge!(g, 4, 5) + add_edge!(g, 4, 3) + add_edge!(g, 3, 2) + add_edge!(g, 5, 2) + add_edge!(g, 1, 3) + + res = map_graph(g) + + # checking size + gp = Independence(SimpleGraph(res.grid_graph); optimizer=TreeSA(ntrials=1, niters=10), simplifier=MergeGreedy()) + missize_map = solve(gp, "size max")[].n + missize = solve(Independence(g), "size max")[].n + @test res.mis_overhead + missize == missize_map + + # checking mapping back + misconfig = solve(gp, "config max")[].c + c = zeros(Int, size(res.grid_graph.content)) + for (i, loc) in enumerate(findall(!iszero, res.grid_graph.content)) + c[loc] = misconfig.data[i] + end + original_configs = map_configs_back(res, [c]) + @test count(isone, original_configs[1]) == missize + @test is_independent_set(g, original_configs[1]) +end + + @testset "interface" begin g = smallgraph(:petersen) res = map_graph(g) @@ -79,4 +110,4 @@ end original_configs = map_configs_back(res, [c]) @test count(isone, original_configs[1]) == missize @test is_independent_set(g, original_configs[1]) -end \ No newline at end of file +end