Skip to content

Commit

Permalink
Merge pull request #68 from epatters/compact-closed-wiring-diagrams
Browse files Browse the repository at this point in the history
Wiring diagrams for self-dual compact closed categories
  • Loading branch information
epatters committed Dec 26, 2019
2 parents 2dbcbef + 9bd6e9d commit ffd1e42
Show file tree
Hide file tree
Showing 15 changed files with 607 additions and 490 deletions.
31 changes: 29 additions & 2 deletions docs/literate/graphics/composejl_wiring_diagrams.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,41 @@ to_composejl((braid(A,B) ⊗ id(C)) ⋅ (id(B) ⊗ braid(A,C) ⋅ (braid(B,C)
# ### Biproduct category

A, B = Ob(FreeBiproductCategory, :A, :B)
f, g = Hom(:f, A, B), Hom(:g, B, A)
f = Hom(:f, A, B)

to_composejl(mcopy(A))
#-
to_composejl(delete(A))
#-
to_composejl(mcopy(A)(ff)mmerge(B))

# ### Compact closed category

# The unit and co-unit of a compact closed category appear as caps and cups.

A, B = Ob(FreeBicategoryRelations, :A, :B)
f = Hom(:f, A, B)

to_composejl(dunit(A))
#-
to_composejl(dcounit(A))

# In a self-dual compact closed category, such as a bicategory of relations,
# every morphism $f: A \to B$ has a transpose $f^\dagger: B \to A$ given by
# bending wires:

to_composejl((dunit(A) id(B)) (id(A) f id(B)) (id(A) dcounit(B)))

# ## Custom styles

# The visual appearance of wiring diagrams can be customized by passing Compose
# [properties](http://giovineitalia.github.io/Compose.jl/latest/gallery/properties/).

using Compose: fill, stroke

A, B, = Ob(FreeSymmetricMonoidalCategory, :A, :B)
f, g = Hom(:f, A, B), Hom(:g, B, A)

to_composejl(fg, box_props=[fill("lavender"), stroke("black")])

# ## Output formats
Expand All @@ -84,4 +104,11 @@ to_composejl(f⋅g, box_props=[fill("lavender"), stroke("black")])
using Compose: draw, PGF

pic = to_composejl(fg, rounded_boxes=false)
draw(PGF(stdout, pic.width, pic.height), pic.context)
pgf = sprint() do io
pgf_backend = PGF(io, pic.width, pic.height,
false, # emit_on_finish
true, # only_tikz
texfonts=true)
draw(pgf_backend, pic.context)
end
println(pgf)
1 change: 1 addition & 0 deletions docs/src/apis/wiring_diagrams.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ CurrentModule = Catlab.WiringDiagrams
Modules = [
WiringDiagramCore,
WiringLayers,
AlgebraicWiringDiagrams,
WiringDiagramAlgorithms,
WiringDiagramSerialization,
GraphMLWiringDiagrams,
Expand Down
7 changes: 4 additions & 3 deletions src/graphics/ComposeWiringDiagrams.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const C = Compose

using ...WiringDiagrams
using ..WiringDiagramLayouts
using ..WiringDiagramLayouts: AbstractVector2D, Vector2D, BoxShape,
RectangleShape, JunctionShape, position, size, lower_corner, upper_corner,
normal, tangent, wire_points
using ..WiringDiagramLayouts: AbstractVector2D, Vector2D,
BoxShape, RectangleShape, JunctionShape, NoShape,
position, size, lower_corner, upper_corner, normal, tangent, wire_points

# Data types
############
Expand Down Expand Up @@ -141,6 +141,7 @@ end
function render_box(::Val{JunctionShape}, ::Any, opts::ComposeOptions)
C.compose(C.context(), C.circle(), opts.junction_props...)
end
render_box(::Val{NoShape}, ::Any, ::ComposeOptions) = C.context()

# Compose.jl forms
##################
Expand Down
2 changes: 0 additions & 2 deletions src/graphics/TikZWiringDiagrams.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module TikZWiringDiagrams
export to_tikz

using Match

using ...Doctrines: ObExpr, HomExpr, dom, codom, head, args, compose, id
using ...Syntax: GATExpr, show_latex
using ...WiringDiagrams
Expand Down
34 changes: 19 additions & 15 deletions src/graphics/WiringDiagramLayouts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Specific features of the shape are determined by the graphics backend. For
example, a rectangle could be rendered with or without rounded corners or even
as another, similar shape, such as a rotated isosceles trapezoid.
"""
@enum BoxShape RectangleShape CircleShape JunctionShape
@enum BoxShape RectangleShape CircleShape JunctionShape NoShape

""" Layout for box in a wiring diagram.
"""
Expand Down Expand Up @@ -151,13 +151,17 @@ layout_hom_expr(f::HomExpr{:mcopy}, opts) = layout_junction_expr(f, opts)
layout_hom_expr(f::HomExpr{:delete}, opts) = layout_junction_expr(f, opts)
layout_hom_expr(f::HomExpr{:mmerge}, opts) = layout_junction_expr(f, opts)
layout_hom_expr(f::HomExpr{:create}, opts) = layout_junction_expr(f, opts)

layout_box_expr(f::HomExpr, opts) =
layout_box(f, collect(dom(f)), collect(codom(f)), opts)
layout_junction_expr(f::HomExpr, opts) =
layout_junction(f, collect(dom(f)), collect(codom(f)), opts)
layout_wires_expr(f::HomExpr, opts) =
layout_pure_wiring(to_wiring_diagram(f), opts)
layout_hom_expr(f::HomExpr{:dunit}, opts) =
layout_junction_expr(f, opts; visible=false, pad=false)
layout_hom_expr(f::HomExpr{:dcounit}, opts) =
layout_junction_expr(f, opts; visible=false, pad=false)

layout_box_expr(f::HomExpr, opts; kw...) =
layout_box(f, collect(dom(f)), collect(codom(f)), opts; kw...)
layout_junction_expr(f::HomExpr, opts; kw...) =
layout_junction(f, collect(dom(f)), collect(codom(f)), opts; kw...)
layout_wires_expr(f::HomExpr, opts; kw...) =
layout_pure_wiring(to_wiring_diagram(f), opts; kw...)

# Diagram layout
################
Expand Down Expand Up @@ -275,12 +279,12 @@ end
""" Lay out a circular junction and its ports.
"""
function layout_junction(value::Any, inputs::Vector, outputs::Vector,
opts::LayoutOptions)
radius = opts.junction_size
opts::LayoutOptions; visible::Bool=true, pad::Bool=true)
shape, radius = visible ? (JunctionShape, opts.junction_size) : (NoShape, 0)
size = 2*SVector(radius, radius)
box = Box(BoxLayout(value=value, shape=JunctionShape, size=size),
layout_circular_ports(InputPort, inputs, radius, opts),
layout_circular_ports(OutputPort, outputs, radius, opts))
box = Box(BoxLayout(value=value, shape=shape, size=size),
layout_circular_ports(InputPort, inputs, radius, opts; pad=pad),
layout_circular_ports(OutputPort, outputs, radius, opts; pad=pad))
size_to_fit!(singleton_diagram(box), opts)
end

Expand Down Expand Up @@ -318,10 +322,10 @@ end
""" Lay out ports along a circular arc.
"""
function layout_circular_ports(port_kind::PortKind, port_values::Vector,
radius::Real, opts::LayoutOptions)
radius::Real, opts::LayoutOptions; pad::Bool=true)
n = length(port_values)
θ1, θ2 = is_horizontal(opts.orientation) ?/2, -π/2) : (-π, 0)
θs = collect(range(θ1, θ2, length=n+2)[2:n+1])
θs = collect(pad ? range(θ1,θ2,length=n+2)[2:n+1] : range(θ1,θ2,length=n))
θs = port_sign(port_kind, opts.orientation) == -1 ? reverse(θs) : θs
dirs = [ SVector(cos(θ),-sin(θ)) for θ in θs ] # positive y-axis downwards
PortLayout[ PortLayout(value, radius * dir, dir)
Expand Down
Loading

0 comments on commit ffd1e42

Please sign in to comment.