Skip to content

[WIP] shrinking #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.vscode/
/Manifest.toml
.DS_Store
10 changes: 6 additions & 4 deletions project/createmap.jl
Original file line number Diff line number Diff line change
@@ -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...))
EndTurn(),
UnitDiskMapping.simplifier_ruleset...))
5 changes: 4 additions & 1 deletion src/UnitDiskMapping.jl
Original file line number Diff line number Diff line change
@@ -6,14 +6,17 @@ 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")
include("simplifiers.jl")
include("mapping.jl")
include("extracting_results.jl")
include("pathdecomposition/pathdecomposition.jl")
include("shrinking/compressUDG.jl")

end
52 changes: 48 additions & 4 deletions src/extracting_results.jl
Original file line number Diff line number Diff line change
@@ -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
112 changes: 66 additions & 46 deletions src/gadgets.jl
Original file line number Diff line number Diff line change
@@ -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,19 +151,19 @@ 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)]
g = simplegraph([(1,2), (2,3), (3,4), (4,5)])
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
end
Loading