diff --git a/src/UnitDiskMapping.jl b/src/UnitDiskMapping.jl index e757af8..9f87b38 100644 --- a/src/UnitDiskMapping.jl +++ b/src/UnitDiskMapping.jl @@ -9,6 +9,7 @@ export unapply_gadgets!, unmatch 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 +export unitdisk_graph include("utils.jl") include("gadgets.jl") @@ -18,5 +19,6 @@ include("simplifiers.jl") include("extracting_results.jl") include("pathdecomposition/pathdecomposition.jl") include("tikz/tikz.jl") +include("shrinking/shrinking.jl") end diff --git a/src/extracting_results.jl b/src/extracting_results.jl index 90822aa..421b86c 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, 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]]]) + 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, 1, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 0, 0, 1, 0]], 1 => [[1, 0, 1, 0, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 0, 1, 0]], 0 => [[0, 1, 0, 1, 0, 0, 1, 0, 0], [0, 1, 0, 1, 0, 0, 0, 1, 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, 1, 0, 0], [1, 0, 1, 0, 1, 0, 0, 1, 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 @@ -38,7 +38,7 @@ function mapped_entry_to_compact(::WTurn) end function source_entry_to_configs(::WTurn) - return Dict(Pair{Int64, Vector{BitVector}}[0 => [[1, 0, 1, 0, 0]], 2 => [[0, 0, 0, 1, 1], [1, 0, 0, 0, 1]], 3 => [[0, 1, 0, 1, 1]], 1 => [[0, 1, 1, 0, 0], [0, 1, 0, 1, 0]]]) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[1, 0, 1, 0, 0]], 2 => [[1, 0, 0, 0, 1], [0, 0, 0, 1, 1]], 3 => [[0, 1, 0, 1, 1]], 1 => [[0, 1, 0, 1, 0], [0, 1, 1, 0, 0]]]) end mis_overhead(::WTurn) = -1 @@ -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, 0, 1, 0, 0, 1, 0, 1], [0, 1, 0, 0, 0, 1, 0, 1], [0, 1, 0, 1, 0, 0, 0, 1]], 5 => [[1, 0, 1, 0, 0, 1, 0, 1]], 6 => [[0, 0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 0, 1, 1, 0, 1]], 2 => [[0, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 1, 0, 0], [0, 1, 0, 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, 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]]]) end mis_overhead(::Branch) = -1 @@ -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, 0, 1, 0, 1, 0], [0, 1, 0, 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 @@ -119,3 +119,69 @@ function source_entry_to_configs(::UnitDiskMapping.DanglingLeg) end mis_overhead(::UnitDiskMapping.DanglingLeg) = -1 + + +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, 0, 1], [0, 0, 1, 0]], 2 => [[0, 1, 1, 0]], 3 => [], 1 => [[1, 0, 0, 1]]]) +end + +mis_overhead(::UnitDiskMapping.Square) = -1 + + +function mapped_entry_to_compact(::UnitDiskMapping.EndCrossing_with_Edge) + return Dict([0 => 0, 4 => 4, 5 => 1, 6 => 6, 2 => 2, 7 => 7, 3 => 3, 1 => 1]) +end + +function source_entry_to_configs(::UnitDiskMapping.EndCrossing_with_Edge) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0]], 4 => [[0, 0, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1]], 5 => [[1, 0, 0, 0, 0, 1]], 6 => [[0, 1, 0, 1, 0, 1]], 2 => [[0, 1, 0, 1, 0, 0]], 7 => [], 3 => [], 1 => [[1, 0, 0, 0, 1, 0]]]) +end + +mis_overhead(::UnitDiskMapping.EndCrossing_with_Edge) = 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 + + +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 => [[1, 0, 0, 0, 1], [0, 1, 0, 0, 1]], 3 => [[1, 0, 0, 1, 1]], 1 => [[1, 0, 0, 1, 0], [0, 0, 1, 1, 0]]]) +end + +mis_overhead(::UnitDiskMapping.CLoop) = -1 + + +function mapped_entry_to_compact(::UnitDiskMapping.CurveEnd) + return Dict([0 => 0, 1 => 1]) +end + +function source_entry_to_configs(::UnitDiskMapping.CurveEnd) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[1, 0, 0], [0, 1, 0]], 1 => [[1, 0, 1]]]) +end + +mis_overhead(::UnitDiskMapping.CurveEnd) = -1 + + +function mapped_entry_to_compact(::UnitDiskMapping.DiagonalEnd) + return Dict([0 => 0, 1 => 1]) +end + +function source_entry_to_configs(::UnitDiskMapping.DiagonalEnd) + return Dict(Pair{Int64, Vector{BitVector}}[0 => [[1, 0, 0], [0, 1, 0]], 1 => [[1, 0, 1]]]) +end + +mis_overhead(::UnitDiskMapping.DiagonalEnd) = -1 diff --git a/src/mapping.jl b/src/mapping.jl index b6e1383..f07130b 100644 --- a/src/mapping.jl +++ b/src/mapping.jl @@ -347,7 +347,7 @@ function mis_overhead_copylines(ug::UGrid{WC,W}) where {WC,W} end ##### Interfaces ###### -export MappingResult, map_graph, map_configs_back +export MappingResult, map_graph, map_configs_back, apply_simplifiers_unweighted struct MappingResult{CT,WT} grid_graph::UGrid{CT,WT} @@ -386,6 +386,10 @@ function map_graph(mode, g::SimpleGraph; vertex_order=Greedy(), ruleset=default_ return MappingResult(ug, vcat(tape, tape2) , mis_overhead0 + mis_overhead1 + mis_overhead2) end +function apply_simplifiers_unweighted(ug::UGrid) + return apply_simplifier_gadgets!(ug; ruleset=default_simplifier_ruleset(UnWeighted())) +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())) \ No newline at end of file +default_simplifier_ruleset(::Weighted) = weighted.(default_simplifier_ruleset(UnWeighted())) diff --git a/src/shrinking/shrinking.jl b/src/shrinking/shrinking.jl new file mode 100644 index 0000000..cbb8c54 --- /dev/null +++ b/src/shrinking/shrinking.jl @@ -0,0 +1,298 @@ +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} +end +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, j = -1:1 + !(i == 0 && j == 0) && push!(pos_udg_neighbors, (p_x + i, p_y + j)) + end + return pos_udg_neighbors +end + + +# find 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 + (u.pos == pos) && return u + end + return nothing +end + +# find boundaries of 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 + (p_x > max_x) && (max_x = p_x) + (p_x < min_x) && (min_x = p_x) + (p_y > max_y) && (max_y = p_y) + (p_y < min_y) && (min_y = p_y) + end + return min_x, min_y, max_x, max_y +end + +# find points on the boundary that can be moved +function find_boundary_points(node_list::Vector{UNode}, x_min, x_max, y_min, y_max) + pts_boundary = Vector{UNode}() + + for u in node_list + p_x, p_y = u.pos + (p_x == x_min || p_x == x_max || p_y == y_min || p_y == y_max) && push!(pts_boundary, u) + end + + return pts_boundary +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 + (get_UNode_from_pos(new_pos, node_list) != nothing) && return false + + p_x, p_y = new_pos + new_neighbors = Vector{Int}() + + for p in get_udg_neighbors(new_pos) + unode = get_UNode_from_pos(p, node_list) + + if (unode !== nothing) && (unode.vertex != n.vertex) + push!(new_neighbors, unode.vertex) + end + end + + (issetequal(new_neighbors, n.neighbors) == true) && return true + 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) + node_list[n.vertex] = UNode(n.vertex, p, n.neighbors) + return node_list + end + end + return node_list +end + +# determine candidates to move +function determine_candidates(pos::Tuple{Int, Int}, x_min, x_max, y_min, y_max) + p_x, p_y = pos + + halfx = (x_max - x_min)/2 + x_min + halfy = (y_max - y_min)/2 + y_min + + # move boundary vertices such that we can shrink graph from four quadrants + (p_x == x_min && p_y >= halfy) && return [(p_x + 1, p_y), (p_x + 1, p_y - 1), (p_x, p_y - 1)] + (p_x == x_min && p_y < halfy) && return [(p_x + 1, p_y), (p_x + 1, p_y + 1), (p_x, p_y + 1)] + (p_x == x_max && p_y >= halfy) && return [(p_x - 1, p_y), (p_x - 1, p_y - 1), (p_x, p_y - 1)] + (p_x == x_max && p_y < halfy) && return [(p_x - 1, p_y), (p_x - 1, p_y + 1), (p_x, p_y + 1)] + + (p_x < halfx && p_y == y_min) && return [(p_x, p_y + 1), (p_x + 1, p_y + 1), (p_x + 1, p_y)] + (p_x >= halfx && p_y == y_min) && return [(p_x, p_y + 1), (p_x - 1, p_y + 1), (p_x - 1, p_y)] + (p_x < halfx && p_y == y_max) && return [(p_x, p_y - 1), (p_x + 1, p_y - 1), (p_x + 1, p_y)] + (p_x >= halfx && p_y == y_max) && return [(p_x, p_y - 1), (p_x - 1, p_y - 1), (p_x - 1, p_y)] + +end + + +# one shrinking step +function greedy_step(node_list::Vector{UNode}, min_x::Int, max_x::Int, + min_y::Int, max_y::Int) + + boundary_pts = find_boundary_points(node_list, min_x, max_x, + min_y, max_y) + + for p in boundary_pts + node_list = move_node(p, node_list, determine_candidates(p.pos, min_x, max_x, + min_y, max_y)) + end + + return node_list +end + +function unitdisk_graph(locs::AbstractVector, 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 + +module CompressUDG +using Graphs +using ..UnitDiskMapping: unitdisk_graph + +export UNode, contract_graph, CompressUDGMethod + +struct UNode + vertex::Int + pos::Tuple{Int, Int} + neighbors::Vector{Int} +end +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}) + # udg radius = 1.5 + p_x, p_y = pos + pos_udg_neighbors = Vector{Tuple{Int, Int}} + + for i = -1:1, j = -1:1 + !(i == 0 && j == 0) && push!(pos_udg_neighbors, (p_x + i, p_y + j)) + end + return pos_udg_neighbors +end + +# find UNode from given position and return nothing if no node in that position +function get_UNode_from_pos(pos::Tuple{Int, Int}, node_list::Vector{UNode}) + for u in node_list + (u.pos == pos) && return u + end + return nothing +end + +# find the center of the graph given list of UNodes +function find_center(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 + (p_x > max_x) && (max_x = p_x) + (p_x < min_x) && (min_x = p_x) + (p_y > max_y) && (max_y = p_y) + (p_y < min_y) && (min_y = p_y) + end + + return (max_x - min_x)/2 + min_x, (max_y - min_y)/2 + min_y +end + +# filter function that checks that 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 + (get_UNode_from_pos(new_pos, node_list) !== nothing) && return false + + p_x, p_y = new_pos + new_neighbors = Vector{Int}() + + for p in get_udg_neighbors(new_pos) + unode = get_UNode_from_pos(p, node_list) + ((unode !== nothing) && (unode.vertex != n.vertex)) && push!(new_neighbors, unode.vertex) + end + + (issetequal(new_neighbors, n.neighbors)) && return true +end + +# determine cost for a position +# defined as distance from center of graph +function node_cost(pos::Tuple{Int, Int}, node_list::Vector{UNode}) + center_x, center_y = find_center(node_list) + p_x, p_y = pos + return (center_x - p_x)^2 + (center_y - p_y)^2 +end + +# move a node n to minimize cost +function move_node(n::UNode, node_list::Vector{UNode}) + min_cost = node_cost(n.pos, node_list) + + candidates = get_UDG_neighbors(n.pos) + + for p in candidates + if check_UDG_criteria(n, p, node_list) + if node_cost(p, node_list) < min_cost + node_list[n.vertex] = UNode(n.vertex, p, n.neighbors) + return node_list + end + end + end + return node_list, min_cost +end + +function total_cost(node_list::Vector{UNode}) + total_cost = 0 + for n in node_list + total_cost += node_cost(n.pos, node_list) + end + return total_cost +end + +# move all nodes to minimize cost one by one +function greedy_step(node_list::Vector{UNode}) + for n in node_list + node_list, min_cost1 = move_node(n, node_list) + node_list, min_cost2 = move_node(n, node_list) + while min_cost2 != min_cost1 + min_cost1 = min_cost2 + node_list, min_cost2 = move_node(n, node_list) + end + end + + return node_list, total_cost(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 +""" +function contract_graph(node_positions::Vector{Tuple{Int, Int}}) + # initiate UNodes + + n_list = Vector{UNode}(undef, size(node_positions)[1]) + g = unitdisk_graph(node_positions, 1.5) + + for (ind, n_pos) in enumerate(node_positions) + n_list[ind] = UNode(ind, n_pos, neighbors(g, ind)) + end + + n_list, cost = greedy_step(n_list) + n_list, cost2 = greedy_step(n_list) + + while cost != cost2 + cost = cost2 + n_list, cost2 = greedy_step(n_list) + 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, CompressUDGMethod diff --git a/src/simplifiers.jl b/src/simplifiers.jl index d68c21e..eec1584 100644 --- a/src/simplifiers.jl +++ b/src/simplifiers.jl @@ -81,23 +81,105 @@ end # 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 EndCrossing_with_Edge = + """ + ⋅ ● ⋅ ⋅ + ● ● ● ● + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + """=>""" + ⋅ ● ⋅ ⋅ + ● ⋅ ⋅ ● + ⋅ ● ● ⋅ + ⋅ ⋅ ⋅ ⋅ + """ + +@gg Cane = + """ + ⋅ ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ● ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + """=>""" + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ● ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ● ⋅ + """ + +@gg CLoop = + """ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ● ⋅ + ⋅ ● ⋅ ● + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ● ⋅ + """=>""" + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ● + ⋅ ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + """ + +@gg CurveEnd = + """ + ⋅ ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ● ⋅ + ⋅ ⋅ ● ⋅ + """=>""" + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ● ⋅ + """ + +@gg DiagonalEnd = + """ + ⋅ ⋅ ⋅ ⋅ + ⋅ ● ⋅ ⋅ + ⋅ ⋅ ● ⋅ + ⋅ ⋅ ⋅ ● + """=>""" + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ● + """ + # 2. add your gadget to simplifier ruleset. -const simplifier_ruleset = SimplifyPattern[DanglingLeg()] +const simplifier_ruleset = SimplifyPattern[DanglingLeg(), Square(), EndCrossing_with_Edge(), Cane(), CLoop(), CurveEnd(), DiagonalEnd()] # 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`) \ No newline at end of file +# for mapping back. (Note: will overwrite the source file `src/extracting_results.jl`) diff --git a/test/shrinking/shrinking.jl b/test/shrinking/shrinking.jl new file mode 100644 index 0000000..2dbc429 --- /dev/null +++ b/test/shrinking/shrinking.jl @@ -0,0 +1,27 @@ +using UnitDiskMapping, Test +using Graphs + +# test method "get_udg_neighbors" +# test "get_UNode_from_pos" +@testset "test neighbors" begin + # test on gadgets + g = smallgraph(:house) + # map to udg + pos = coordinates(map_graph(g).grid_graph) + ud_g = unitdisk_graph(pos, 1.5) + + # list of UNodes + n_list = Vector{UNode}(undef, size(pos)[1]) + # check that all neighbors of udg map in "get_udg_neighbors" + for (i, v) in enumerate(vertices(ud_g)) + for j in neighbors(ud_g, v) + @test(pos[j] in get_udg_neighbors(pos[i])) + end + # initiate unodes + unode = UNode(v, pos[i], neighbors(ud_g, v)) + n_list[i] = unode + end + + # test node_cost + @test(node_cost((find_center(n_list)), n_list) == 0) +end