Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion src/UnitDiskMapping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export UNode, contract_graph, compress_graph

include("utils.jl")
include("gadgets.jl")
include("simplifiers.jl")
include("mapping.jl")
include("weighted.jl")
include("simplifiers.jl")
include("extracting_results.jl")
include("pathdecomposition/pathdecomposition.jl")
#include("shrinking/compressUDG.jl")
Expand Down
27 changes: 21 additions & 6 deletions src/gadgets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -386,16 +386,17 @@ for T in [:RotatedGadget, :ReflectedGadget]
@eval mis_overhead(p::$T) = mis_overhead(p.gadget)
end

function _apply_transform(r::RotatedGadget, node::Node, center)
loc = getxy(node)
for T in [:RotatedGadget, :ReflectedGadget]
@eval _apply_transform(r::$T, node::Node, center) = chxy(node, _apply_transform(r, getxy(node), center))
end
function _apply_transform(r::RotatedGadget, loc::Tuple{Int,Int}, center)
for _=1:r.n
loc = rotate90(loc, center)
end
return chxy(node, loc)
return loc
end

function _apply_transform(r::ReflectedGadget, node::Node, center)
loc = getxy(node)
function _apply_transform(r::ReflectedGadget, loc::Tuple{Int,Int}, center)
loc = if r.mirror == "x"
reflectx(loc, center)
elseif r.mirror == "y"
Expand All @@ -407,7 +408,7 @@ function _apply_transform(r::ReflectedGadget, node::Node, center)
else
throw(ArgumentError("reflection direction $(r.direction) is not defined!"))
end
chxy(node, loc)
return loc
end

export vertex_overhead
Expand All @@ -429,3 +430,17 @@ function _boundary_config(pins, config)
end
return res
end

export rotated_and_reflected
function rotated_and_reflected(p::Pattern)
patterns = Pattern[p]
source_matrices = [source_matrix(p)]
for pi in [[RotatedGadget(p, i) for i=1:3]..., [ReflectedGadget(p, axis) for axis in ["x", "y", "diag", "offdiag"]]...]
m = source_matrix(pi)
if m ∉ source_matrices
push!(patterns, pi)
push!(source_matrices, m)
end
end
return patterns
end
8 changes: 6 additions & 2 deletions src/mapping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,10 @@ It can be a vector or one of the following inputs

Returns a `MappingResult` instance.
"""
map_graph(g::SimpleGraph; vertex_order=Greedy(), ruleset=[RotatedGadget(DanglingLeg(), n) for n=0:3]) = map_graph(UnWeighted(), g; ruleset=ruleset, vertex_order=vertex_order)
function map_graph(mode, g::SimpleGraph; vertex_order=Greedy(), ruleset=[RotatedGadget(DanglingLeg(), n) for n=0:3])
function map_graph(g::SimpleGraph; vertex_order=Greedy(), ruleset=default_simplifier_ruleset(UnWeighted()))
map_graph(UnWeighted(), g; ruleset=ruleset, vertex_order=vertex_order)
end
function map_graph(mode, g::SimpleGraph; vertex_order=Greedy(), ruleset=default_simplifier_ruleset(mode))
ug = embed_graph(mode, g; vertex_order=vertex_order)
mis_overhead0 = mis_overhead_copylines(ug)
ug, tape = apply_crossing_gadgets!(mode, ug)
Expand All @@ -385,3 +387,5 @@ function map_graph(mode, g::SimpleGraph; vertex_order=Greedy(), ruleset=[Rotated
end

map_configs_back(r::MappingResult{<:Cell}, configs::AbstractVector) = 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()))
38 changes: 27 additions & 11 deletions src/simplifiers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,51 @@ struct GridGraph{NT<:Node}
end
vertices_on_boundary(gg::GridGraph) = vertices_on_boundary(gg.nodes, gg.size...)

function gridgraphfromstring(str::String)
item_array = Vector{Bool}[]
function gridgraphfromstring(mode::Union{Weighted, UnWeighted}, str::String)
item_array = Vector{Int}[]
for line in split(str, "\n")
list = [item ∈ ("o", "●") ? true : (@assert item ∈ (".", "⋅"); false) for item in split(line, " ") if !isempty(item)]
items = [item for item in split(line, " ") if !isempty(item)]
list = if mode isa Weighted # TODO: the weighted version need to be tested! Consider removing it!
@assert all(item->item ∈ (".", "⋅", "@", "●", "o", "◯"), items)
[item ∈ ("@", "●") ? 2 : (item ∈ ("o", "◯") ? 1 : 0) for item in items]
else
@assert all(item->item ∈ (".", "⋅", "@", "●"), items)
[item ∈ ("@", "●") ? 1 : 0 for item in items]
end
if !isempty(list)
push!(item_array, list)
end
end
@assert all(==(length(item_array[1])), length.(item_array))
mat = hcat(item_array...)'
locs = [SimpleNode(ci.I) for ci in findall(mat)]
locs = [_to_node(mode, ci.I, mat[ci]) for ci in findall(!iszero, mat)]
return GridGraph(size(mat), locs)
end
_to_node(::UnWeighted, loc::Tuple{Int,Int}, w::Int) = SimpleNode(loc...)
_to_node(::Weighted, loc::Tuple{Int,Int}, w::Int) = WeightedNode(loc..., w)

const simplifier_ruleset = SimplifyPattern[]

macro gg(expr)
function gg_func(mode, expr)
@assert expr.head == :(=)
name = expr.args[1]
pair = expr.args[2]
@assert pair.head == :(call) && pair.args[1] == :(=>)
g1 = gridgraphfromstring(pair.args[2])
g2 = gridgraphfromstring(pair.args[3])
g1 = gridgraphfromstring(mode, pair.args[2])
g2 = gridgraphfromstring(mode, pair.args[3])
@assert g1.size == g2.size
@assert g1.nodes[vertices_on_boundary(g1)] == g2.nodes[vertices_on_boundary(g2)]
return quote
struct $(esc(name)) <: SimplifyPattern end
Base.size(::$(esc(name))) = $(g1.size)
$UnitDiskMapping.source_locations(::$(esc(name))) = $(g1.nodes)
$UnitDiskMapping.mapped_locations(::$(esc(name))) = $(g2.nodes)
push!($(simplifier_ruleset), $(esc(name))())
$(esc(name))
end
end

macro gg(expr)
gg_func(UnWeighted(), expr)
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.
Expand All @@ -83,5 +93,11 @@ end
⋅ ● ⋅
"""

# 2. run the script `project/createmap` to generate `mis_overhead` and other informations required
# 2. add your gadget to simplifier ruleset.
const simplifier_ruleset = SimplifyPattern[DanglingLeg()]
# set centers (vertices with weight 1) for the weighted version
source_centers(::WeightedGadget{DanglingLeg}) = [(2,2)]
mapped_centers(::WeightedGadget{DanglingLeg}) = [(4,2)]

# 3. 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`)
159 changes: 45 additions & 114 deletions src/weighted.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export WeightedCell, WeightedGadget, WeightedNode
# TODO:
# * add path decomposition
struct WeightedCell{RT} <: AbstractCell
Expand All @@ -7,13 +8,10 @@ struct WeightedCell{RT} <: AbstractCell
weight::RT
end

abstract type WeightedCrossPattern <: Pattern end
abstract type WeightedSimplifyPattern <:Pattern end
struct WeightedGadget{GT} <: Pattern
gadget::GT
factor::Int
end
const WeightedPattern = Union{WeightedCrossPattern, WeightedSimplifyPattern, WeightedGadget}
const WeightedGadgetTypes = Union{WeightedGadget, RotatedGadget{<:WeightedGadget}, ReflectedGadget{<:WeightedGadget}}

Base.isempty(cell::WeightedCell) = !cell.occupied
Base.empty(::Type{WeightedCell{RT}}) where RT = WeightedCell(false, false, false,0)
Expand Down Expand Up @@ -62,143 +60,76 @@ _weight2(::CopyLine{Weighted}, i, j) = WeightedNode(i, j, 2)
_weight1(::CopyLine{Weighted}, i, j) = WeightedNode(i, j, 1)
_cell_type(::Type{<:WeightedNode}) = WeightedCell{Int}

function source_graph(r::WeightedGadget)
locs, g, pins = source_graph(r.gadget)
_mul_weight.(locs, r.factor), g, pins
end
function mapped_graph(r::WeightedGadget)
locs, g, pins = mapped_graph(r.gadget)
_mul_weight.(locs, r.factor), g, pins
end
_mul_weight(node::SimpleNode, factor) = WeightedNode(node..., factor)
mis_overhead(p::WeightedGadget) = 2*mis_overhead(p.gadget)

# new gadgets
struct WeightedWTurn <: WeightedCrossPattern end
# ⋅ ⋅ ⋅ ⋅
# ⋅ ⋅ ◯ ●
# ⋅ ● ● ⋅
# ⋅ ● ⋅ ⋅

# ⋅ ⋅ ⋅ ⋅
# ⋅ ⋅ ⋅ ●
# ⋅ ⋅ ◯ ⋅
# ⋅ ● ⋅ ⋅

struct WeightedBranchFix <: WeightedCrossPattern end
# ⋅ ● ⋅ ⋅
# ⋅ ● ◯ ⋅
# ⋅ ● ● ⋅
# ⋅ ● ⋅ ⋅

# ⋅ ● ⋅ ⋅
# ⋅ ● ⋅ ⋅
# ⋅ ◯ ⋅ ⋅
# ⋅ ● ⋅ ⋅

struct WeightedTurn <: WeightedCrossPattern end
# ⋅ ● ⋅ ⋅
# ⋅ ● ⋅ ⋅
# ⋅ ● ◯ ●
# ⋅ ⋅ ⋅ ⋅

# ⋅ ● ⋅ ⋅
# ⋅ ⋅ ◯ ⋅
# ⋅ ⋅ ⋅ ●
# ⋅ ⋅ ⋅ ⋅

struct WeightedBranch <: WeightedCrossPattern end
# ⋅ ● ⋅ ⋅
# ⋅ ● ⋅ ⋅
# ⋅ ● ◯ ●
# ⋅ ● ● ⋅
# ⋅ ● ⋅ ⋅


# ⋅ ● ⋅ ⋅ ?
# ⋅ ⋅ ◯ ⋅
# ⋅ ● ⋅ ●
# ⋅ ⋅ ● ⋅
# ⋅ ● ⋅ ⋅

struct WeightedBranchFixB <: WeightedCrossPattern end
# ⋅ ⋅ ⋅ ⋅
# ⋅ ⋅ ◯ ⋅
# ⋅ ● ● ⋅
# ⋅ ● ⋅ ⋅

# ⋅ ⋅ ⋅ ⋅
# ⋅ ⋅ ⋅ ⋅
# ⋅ ◯ ⋅ ⋅
# ⋅ ● ⋅ ⋅

struct WeightedEndTurn <: WeightedCrossPattern end
# ⋅ ● ⋅ ⋅
# ⋅ ● ◯ ⋅
# ⋅ ⋅ ⋅ ⋅

# ⋅ ◯ ⋅ ⋅
# ⋅ ⋅ ⋅ ⋅
# ⋅ ⋅ ⋅ ⋅

for T in [:Cross, :TrivialTurn, :TCon]
@eval weighted(c::$T) = WeightedGadget(c, 2)
end
weighted(c::Pattern) = WeightedGadget(c)
unweighted(w::WeightedGadget) = w.gadget
weighted(r::RotatedGadget) = RotatedGadget(weighted(r.gadget), r.n)
weighted(r::ReflectedGadget) = ReflectedGadget(weighted(r.gadget), r.mirror)
unweighted(r::RotatedGadget) = RotatedGadget(unweighted(r.gadget), r.n)
unweighted(r::ReflectedGadget) = ReflectedGadget(unweighted(r.gadget), r.mirror)
mis_overhead(w::WeightedGadget) = mis_overhead(w.gadget) * 2

for T in [:Turn, :Branch, :BranchFix, :BranchFixB, :WTurn, :EndTurn]
WT = Symbol(:Weighted, T)
@eval weighted(::$T) = $WT()
@eval unweighted(::$WT) = $T()
@eval mis_overhead(::$WT) = mis_overhead($T()) * 2
function source_graph(r::WeightedGadget)
raw = unweighted(r)
locs, g, pins = source_graph(raw)
return map(loc->_mul_weight(loc, getxy(loc) ∈ source_centers(r) ? 1 : 2), locs), g, pins
end
function mapped_graph(r::WeightedGadget)
raw = unweighted(r)
locs, g, pins = mapped_graph(raw)
return map(loc->_mul_weight(loc, getxy(loc) ∈ mapped_centers(r) ? 1 : 2), locs), g, pins
end
_mul_weight(node::SimpleNode, factor) = WeightedNode(node..., factor)

for (T, centerloc) in [(:Turn, (2, 3)), (:Branch, (2, 3)), (:BranchFix, (3, 2)), (:BranchFixB, (3, 2)), (:WTurn, (3, 3)), (:EndTurn, (1, 2))]
WT = Symbol(:Weighted, T)
@eval function source_graph(r::$WT)
raw = unweighted(r)
locs, g, pins = source_graph(raw)
return map(loc->_mul_weight(loc, loc == SimpleNode(cross_location(raw) .+ (0, 1)) ? 1 : 2), locs), g, pins
end
@eval function mapped_graph(r::$WT)
raw = unweighted(r)
locs, g, pins = mapped_graph(raw)
return map(loc->_mul_weight(loc, loc == SimpleNode($centerloc) ? 1 : 2), locs), g, pins
@eval source_centers(::WeightedGadget{<:$T}) = [cross_location($T()) .+ (0, 1)]
@eval mapped_centers(::WeightedGadget{<:$T}) = [$centerloc]
end
# default to having no source center!
source_centers(::WeightedGadget) = Tuple{Int,Int}[]
mapped_centers(::WeightedGadget) = Tuple{Int,Int}[]
for T in [:(RotatedGadget{<:WeightedGadget}), :(ReflectedGadget{<:WeightedGadget})]
@eval function source_centers(r::$T)
cross = cross_location(r.gadget)
return map(loc->loc .+ _get_offset(r), _apply_transform.(Ref(r), source_centers(r.gadget), Ref(cross)))
end
@eval function move_center(::$WT, nodexy)
nodexy .+ $centerloc .- (cross_location($WT()) .+ (0, 1))
@eval function mapped_centers(r::$T)
cross = cross_location(r.gadget)
return map(loc->loc .+ _get_offset(r), _apply_transform.(Ref(r), mapped_centers(r.gadget), Ref(cross)))
end
end
move_center(::Pattern, nodexy) = nodexy

for T in [:WeightedCrossPattern, :WeightedGadget]
@eval Base.size(r::$T) = size(unweighted(r))
@eval cross_location(r::$T) = cross_location(unweighted(r))
@eval iscon(r::$T) = iscon(unweighted(r))
@eval connected_nodes(r::$T) = connected_nodes(unweighted(r))
@eval vertex_overhead(r::$T) = vertex_overhead(unweighted(r))
end
Base.size(r::WeightedGadget) = size(unweighted(r))
cross_location(r::WeightedGadget) = cross_location(unweighted(r))
iscon(r::WeightedGadget) = iscon(unweighted(r))
connected_nodes(r::WeightedGadget) = connected_nodes(unweighted(r))
vertex_overhead(r::WeightedGadget) = vertex_overhead(unweighted(r))

const crossing_ruleset_weighted = weighted.(crossing_ruleset)
get_ruleset(::Weighted) = crossing_ruleset_weighted

export get_weights
get_weights(ug::UGrid) = [ug.content[ci...].weight for ci in coordinates(ug)]

# mapping configurations back
export trace_centers
function move_center(w::WeightedGadgetTypes, nodexy, offset)
for (sc, mc) in zip(source_centers(w), mapped_centers(w))
if offset == sc
return nodexy .+ mc .- sc # found
end
end
error("center not found, source center = $(source_centers(w)), while offset = $(offset)")
end

trace_centers(r::MappingResult) = trace_centers(r.grid_graph, r.mapping_history)
function trace_centers(ug::UGrid, tape)
center_locations = map(x->center_location(x; padding=ug.padding) .+ (0, 1), ug.lines)
for (gadget, i, j) in tape
m, n = size(gadget)
for (k, centerloc) in enumerate(center_locations)
offset = centerloc .- (i,j)
if 0<=offset[1] <= m-1 && 0<=offset[2] <= n-1
center_locations[k] = move_center(gadget, centerloc)
offset = centerloc .- (i-1,j-1)
if 1<=offset[1] <= m && 1<=offset[2] <= n
center_locations[k] = move_center(gadget, centerloc, offset)
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions test/gadgets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ using Graphs
@test diff == -mis_overhead(s)
@test sig
end
end

@testset "rotated_and_reflected" begin
@test length(rotated_and_reflected(UnitDiskMapping.DanglingLeg())) == 4
@test length(rotated_and_reflected(Cross{false}())) == 4
@test length(rotated_and_reflected(Cross{true}())) == 4
@test length(rotated_and_reflected(BranchFixB())) == 8
end
Loading