Skip to content

Commit dd2db60

Browse files
authored
Paper plot (#24)
* initial * paper plot * update\
1 parent c696501 commit dd2db60

File tree

7 files changed

+125
-42
lines changed

7 files changed

+125
-42
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
/.vscode/
22
/Manifest.toml
33
.DS_Store
4-
_local/
4+
_local/
5+
*.aux
6+
*.fls
7+
*.log
8+
*.fdb_latexmk

flowchart.pdf

14.4 KB
Binary file not shown.

project/viz_flowchart.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using UnitDiskMapping.TikzGraph
2+
3+
function routine(centerx, centery, width, height, text; kwargs...)
4+
Node(centerx, centery, shape="rectangle", rounded_corners = "0.5ex", minimum_width="$(width)cm", minimum_height="$(height)cm", line_width="1pt", minimum_size="", text=text, kwargs...)
5+
end
6+
7+
# aspect = width/height
8+
function decision(centerx, centery, width, height, text; kwargs...)
9+
Node(centerx, centery, shape="diamond", minimum_size="$(height)cm", aspect=width/height, text=text, line_width="1pt", kwargs...)
10+
end
11+
12+
function arrow(nodes...; kwargs...)
13+
Line(nodes...; arrow="->", line_width="1pt", kwargs...)
14+
end
15+
16+
function draw_flowchart()
17+
canvas(libs=["shapes"]) do c
18+
n1 = routine(0.0, 0.0, 3, 1, "input graph") >> c
19+
n2 = decision(0.0, -3, 3, 1, "satisfies the crossing criteria") >> c
20+
n3 = decision(0.0, -6, 3, 1, "has a same tropical tensor") >> c
21+
arrow(n1, n2) >> c
22+
arrow(n2, n3; annotate="T") >> c
23+
arrow(n2, (3.0, -3.0), (3.0, 0.0), n1; annotate="F") >> c
24+
end
25+
end
26+
27+
write("_local/flowchart.tex", draw_flowchart())
28+
run(`latexmk -pdf _local/flowchart.tex`)

project/vizgadget.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ function viz_gadget(p::Pattern)
2525
dx2, dy2 = xmid+1, 0
2626
return canvas(; props=Dict("scale"=>"0.8")) do c
2727
BoundingBox(-1,Wx-1,-1,Wy-1) >> c
28-
Mesh(dx1, Gx+dx1-1, dy1, Gy+dy1-1; step="1cm", draw=rgbcolor!(c, 100,200,200), line_width=0.5) >> c
28+
Mesh(dx1, Gx+dx1-1, dy1, Gy+dy1-1; step="1cm", draw=rgbcolor!(c, 200,200,200), line_width=0.5) >> c
2929
command_graph!(c, locs1, g1, pin1, dx1, dy1, 0.3, "s")
30-
Mesh(dx2, Gx+dx2-1, dy2, Gy+dy2-1; step="1cm", draw=rgbcolor!(c, 200,100,100), line_width=0.03) >> c
30+
Mesh(dx2, Gx+dx2-1, dy2, Gy+dy2-1; step="1cm", draw=rgbcolor!(c, 200,200,200), line_width=0.03) >> c
3131
command_graph!(c, locs2, g2, pin2, dx2, dy2, 0.3, "d")
3232
PlainText(xmid, ymid, "\$\\mathbf{\\rightarrow}\$") >> c
3333
end

src/mapping.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,16 +318,16 @@ function crossat(ug::UGrid, v, w)
318318
end
319319

320320
"""
321-
embed_graph([mode,] g::SimpleGraph; vertex_order=Greedy())
321+
embed_graph([mode,] g::SimpleGraph; vertex_order=Branching())
322322
323323
Embed graph `g` into a unit disk grid, where the optional argument `mode` can be `Weighted()` or `UnWeighted`.
324324
The `vertex_order` can be a vector or one of the following inputs
325325
326326
* `Greedy()` fast but non-optimal.
327327
* `Branching()` slow but optimal.
328328
"""
329-
embed_graph(g::SimpleGraph; vertex_order=Greedy()) = embed_graph(UnWeighted(), g; vertex_order)
330-
function embed_graph(mode, g::SimpleGraph; vertex_order=Greedy())
329+
embed_graph(g::SimpleGraph; vertex_order=Branching()) = embed_graph(UnWeighted(), g; vertex_order)
330+
function embed_graph(mode, g::SimpleGraph; vertex_order=Branching())
331331
if vertex_order isa AbstractVector
332332
L = PathDecomposition.Layout(g, collect(vertex_order))
333333
else
@@ -356,7 +356,7 @@ struct MappingResult{CT,WT}
356356
end
357357

358358
"""
359-
map_graph([mode=Weighted(),] g::SimpleGraph; vertex_order=Greedy(), ruleset=[...])
359+
map_graph([mode=Weighted(),] g::SimpleGraph; vertex_order=Branching(), ruleset=[...])
360360
361361
Map a graph to a unit disk grid graph that being "equivalent" to the original graph.
362362
Here "equivalent" means a maximum independent set in the grid graph can be mapped back to
@@ -373,10 +373,10 @@ It can be a vector or one of the following inputs
373373
374374
Returns a `MappingResult` instance.
375375
"""
376-
function map_graph(g::SimpleGraph; vertex_order=Greedy(), ruleset=default_simplifier_ruleset(UnWeighted()))
376+
function map_graph(g::SimpleGraph; vertex_order=Branching(), ruleset=default_simplifier_ruleset(UnWeighted()))
377377
map_graph(UnWeighted(), g; ruleset=ruleset, vertex_order=vertex_order)
378378
end
379-
function map_graph(mode, g::SimpleGraph; vertex_order=Greedy(), ruleset=default_simplifier_ruleset(mode))
379+
function map_graph(mode, g::SimpleGraph; vertex_order=Branching(), ruleset=default_simplifier_ruleset(mode))
380380
ug = embed_graph(mode, g; vertex_order=vertex_order)
381381
mis_overhead0 = mis_overhead_copylines(ug)
382382
ug, tape = apply_crossing_gadgets!(mode, ug)
@@ -388,4 +388,4 @@ end
388388

389389
map_configs_back(r::MappingResult{<:Cell}, configs::AbstractVector) = unapply_gadgets!(copy(r.grid_graph), r.mapping_history, copy.(configs))[2]
390390
default_simplifier_ruleset(::UnWeighted) = vcat([rotated_and_reflected(rule) for rule in simplifier_ruleset]...)
391-
default_simplifier_ruleset(::Weighted) = weighted.(default_simplifier_ruleset(UnWeighted()))
391+
default_simplifier_ruleset(::Weighted) = weighted.(default_simplifier_ruleset(UnWeighted()))

src/tikz/tikz.jl

Lines changed: 80 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
module TikzGraph
2-
export rgbcolor!, Node, Line, BoundingBox, Mesh, Canvas, >>, command, canvas, generate_standalone, StringElement, PlainText
2+
export rgbcolor!, Node, Line, BoundingBox, Mesh, Canvas, >>, command, canvas, generate_standalone, StringElement, PlainText, uselib!
3+
export Cycle, Controls, annotate, Annotate, autoid!, vizgraph!
34

45
const instance_counter = Ref(0)
56
abstract type AbstractTikzElement end
67

78
struct Canvas
89
header::String
10+
libs::Vector{String}
911
colors::Dict{String, Tuple{Int,Int,Int}}
1012
contents::Vector{AbstractTikzElement}
1113
props::Dict{String,String}
1214
end
1315

14-
function canvas(f; header="", colors=Dict{String,Tuple{Int,Int,Int}}(), props=Dict{String,String}())
15-
canvas = Canvas(header, colors, AbstractTikzElement[], props)
16+
function canvas(f; header="", libs=String[], colors=Dict{String,Tuple{Int,Int,Int}}(), props=Dict{String,String}())
17+
canvas = Canvas(header, libs, colors, AbstractTikzElement[], props)
1618
f(canvas)
1719
return canvas
1820
end
1921

20-
Base.:(>>)(element::AbstractTikzElement, canvas::Canvas) = push!(canvas.contents, element)
21-
Base.:(>>)(element::String, canvas::Canvas) = push!(canvas.contents, StringElement(element))
22+
Base.:(>>)(element::AbstractTikzElement, canvas::Canvas) = (push!(canvas.contents, element); element)
23+
Base.:(>>)(element::String, canvas::Canvas) = (push!(canvas.contents, StringElement(element)); element)
2224

25+
function uselib!(canvas::Canvas, lib::String)
26+
push!(canvas.libs, lib)
27+
return lib
28+
end
2329
function rgbcolor!(canvas::Canvas, red::Int, green::Int, blue::Int)
24-
instance_counter[] += 1
25-
colorname = "color$(instance_counter[])"
30+
colorname = "color$(autoid!())"
2631
canvas.colors[colorname] = (red,green,blue)
2732
return colorname
2833
end
@@ -56,7 +61,7 @@ end
5661

5762
function Node(x, y;
5863
shape::String = "circle",
59-
id = string((instance_counter[] += 1; instance_counter[])),
64+
id = autoid!(),
6065
text::String = "",
6166
fill = "none",
6267
draw = "black",
@@ -73,12 +78,13 @@ function Node(x, y;
7378
kwargs...)
7479
return Node(x, y, shape, id, text, props)
7580
end
81+
autoid!() = string((instance_counter[] += 1; instance_counter[]))
7682
function build_props(; kwargs...)
7783
Dict([replace(string(k), "_"=>" ")=>string(v) for (k,v) in kwargs])
7884
end
7985

8086
function command(node::Node)
81-
return "\\node[$(node.shape), $(command(node.props))] at ($(node.x), $(node.y)) ($(node.id)) {$(node.text)};"
87+
return "\\node[$(parse_args([string(node.shape)], node.props))] at ($(node.x), $(node.y)) ($(node.id)) {$(node.text)};"
8288
end
8389

8490
struct Mesh <: AbstractTikzElement
@@ -93,28 +99,52 @@ function Mesh(xmin, xmax, ymin, ymax; step="1.0cm", draw="gray", line_width=0.03
9399
Mesh(xmin, xmax, ymin, ymax, build_props(; step=step, draw=draw, line_width=line_width, kwargs...))
94100
end
95101
function command(grid::Mesh)
96-
return "\\draw[$(command(grid.props))] ($(grid.xmin),$(grid.ymin)) grid ($(grid.xmax),$(grid.ymax));"
102+
return "\\draw[$(parse_args(String[], grid.props))] ($(grid.xmin),$(grid.ymin)) grid ($(grid.xmax),$(grid.ymax));"
97103
end
98104

99-
struct Line <: AbstractTikzElement
100-
src::String
101-
dst::String
102-
controls::Vector{Int}
103-
props::Dict{String,String}
105+
struct Cycle end
106+
struct Controls
107+
start::String
108+
controls::Vector{String}
109+
stop::String
110+
Controls(start, c1, stop) = new(parse_path(start), [parse_path(c1)], parse_path(stop))
111+
Controls(start, c1, c2, stop) = new(parse_path(start), [parse_path(c1), parse_path(c2)], parse_path(stop))
104112
end
105113

106-
function Line(src, dst; controls=Int[], line_width = "0.03", kwargs...)
107-
Line(string(src), string(dst), controls, build_props(; line_width=line_width, kwargs...))
114+
struct Annotate
115+
args::Vector{String} # e.g. "[midway, above]"
116+
id::String
117+
text::String
108118
end
109-
Line(src::Node, dst::Node; kwargs...) = Line(src.id, dst.id)
119+
Base.isempty(ann::Annotate) = isempty(ann.text)
110120

121+
# arrow styles: https://latexdraw.com/exploring-tikz-arrows/
122+
# line styles: https://tex.stackexchange.com/questions/45275/tikz-get-values-for-predefined-dash-patterns
123+
struct Line <: AbstractTikzElement
124+
path::Vector{String}
125+
arrow::String
126+
line_style::String
127+
annotate::Annotate
128+
props::Dict{String,String}
129+
end
130+
function Line(path...; annotate::Union{String,Annotate}="", arrow::String="", line_width = "0.03", line_style="", kwargs...)
131+
ann = annotate isa String ? Annotate(["midway", "above", "sloped"], "", annotate) : annotate
132+
Line(collect(parse_path.(path)), arrow, line_style, ann, build_props(; line_width=line_width, kwargs...))
133+
end
134+
parse_path(t::Tuple) = "$(t)"
135+
parse_path(n::Node) = "($(n.id))"
136+
parse_path(s::String) = "($s)"
137+
parse_path(s::Cycle) = "cycle"
138+
function parse_path(c::Controls)
139+
"$(c.start) .. controls $(join(["$c" for c in c.controls], " and ")) .. $(c.stop)"
140+
end
111141
function command(edge::Line)
112-
head = "\\draw[$(command(edge.props))]"
113-
if isempty(edge.controls)
114-
return "$head ($(edge.src)) -- ($(edge.dst));"
115-
else
116-
return "$head ($(edge.src)) .. controls $(join(["($c)" for c in edge.controls], " and ")) .. ($(edge.dst));"
117-
end
142+
head = "\\draw[$(parse_args([edge.arrow, edge.line_style], edge.props))]"
143+
path = join(edge.path, " -- ")
144+
ann = edge.annotate
145+
isempty(ann) && return "$head $path;"
146+
annotate = "node [$(parse_args(ann.args, Dict{String,String}()))] ($(ann.id)) {$(ann.text)}"
147+
return "$head $path $annotate;"
118148
end
119149

120150
struct PlainText <: AbstractTikzElement
@@ -127,28 +157,47 @@ function PlainText(x, y, text; kwargs...)
127157
PlainText(x, y, text, build_props(; kwargs...))
128158
end
129159
function command(text::PlainText)
130-
"\\node[$(command(text.props))] at ($(text.x), $(text.y)) {$(text.text)};"
160+
"\\node[$(parse_args(String[], text.props))] at ($(text.x), $(text.y)) {$(text.text)};"
131161
end
132162

133-
function command(node::Dict) # properties
134-
return join(["$k=$v" for (k,v) in node], ", ")
163+
annotate(node::Node, text; offsetx=0, offsety=0, kwargs...) = PlainText(node.x+offsetx, node.y+offsety, text; kwargs...)
164+
165+
function parse_args(args::Vector, kwargs::Dict) # properties
166+
return join(filter(!isempty, [args..., ["$k=$v" for (k,v) in kwargs if !isempty(v)]...]), ", ")
135167
end
136168

137-
function generate_standalone(header::String, props::Dict, content::String)
169+
function generate_standalone(libs::Vector, header::String, props::Dict, content::String)
138170
return """
139171
\\documentclass[crop,tikz]{standalone}
172+
$(join(["\\usepgflibrary{$lib}" for lib in libs], "\n"))
140173
$(header)
141174
\\begin{document}
142-
\\begin{tikzpicture}[$(command(props))]
175+
\\begin{tikzpicture}[$(parse_args(String[], props))]
143176
$content
144177
\\end{tikzpicture}
145178
\\end{document}
146179
"""
147180
end
148-
generate_standalone(canvas::Canvas) = generate_standalone(canvas.header, canvas.props, join([[generate_rgbcolor(k,v...) for (k,v) in canvas.colors]..., command.(canvas.contents)...], "\n"))
181+
generate_standalone(canvas::Canvas) = generate_standalone(canvas.libs, canvas.header, canvas.props, join([[generate_rgbcolor(k,v...) for (k,v) in canvas.colors]..., command.(canvas.contents)...], "\n"))
149182

150183
function Base.write(io::IO, canvas::Canvas)
151184
write(io, generate_standalone(canvas))
152185
end
153186

154-
end
187+
function vizgraph!(c::Canvas, locations::AbstractVector, edges; fills=fill("black", length(locations)),
188+
texts=fill("", length(locations)), ids=[autoid!() for i=1:length(locations)], minimum_size="0.4cm",
189+
draw="", line_width="1pt", edgecolors=fill("black", length(edges)))
190+
nodes = Node[]
191+
lines = Line[]
192+
for i=1:length(locations)
193+
n = Node(locations[i]...; fill=fills[i], minimum_size=minimum_size, draw=draw, id=ids[i], text=texts[i]) >> c
194+
push!(nodes, n)
195+
end
196+
for (k, (i, j)) in enumerate(edges)
197+
l = Line(nodes[i], nodes[j], line_width=line_width, draw=edgecolors[k]) >> c
198+
push!(lines, l)
199+
end
200+
return nodes, lines
201+
end
202+
203+
end

test/tikz/tikz.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ using UnitDiskMapping.TikzGraph, Test
55
@test command(n) isa String
66
m = Node(0.6, 0.5)
77
@test command(n) isa String
8-
l = Line(m, n)
8+
l = Line(m, Controls(m, (0.3, 0.4), n), Controls(m, (0.2, 0.3), (0.3, 0.4), n), n, Cycle(); arrow="->", annotate="A")
99
@test command(n) isa String
1010
b = BoundingBox(0, 10, 0, 10)
1111
@test command(b) isa String
@@ -15,6 +15,8 @@ using UnitDiskMapping.TikzGraph, Test
1515
@test command(s) == "jajaja"
1616
s = PlainText(20.0, 3.0, "jajaja")
1717
@test command(s) isa String
18+
a = annotate(n, "jajaja"; offsetx=0.1, offsety=0.2)
19+
@test command(a) isa String
1820
end
1921

2022
@testset "canvas" begin

0 commit comments

Comments
 (0)