Tutorials
The Category of Discrete Sub-Unit Intervals,
Definition: Let
Objects
and for ;Non-identity morphisms
and for .
We call
While the precise name of this category is the category of discrete subunit-intervals, letter TemporalSheaves.jl and across the literature here, this category is also affectionately referred to as the
Examples Using the Category,
Computing and on Time Points
Underlying TemporalSheaves.jl is the SchZigZag Presentation based on Catlab.jl's FreeSchema and the abstract acset type, AbstractZigZag. These foundational abstractions allow flexibility in defining methods based on a zigzag schema category with finite number of time points. Using this basis, TemporalSheaves.jl provides the following functionality to produce a zigzag schema and constructor for
TemporalSheaves.zigzag Function
zigzag(time_points::Int; opposite::Bool = true)Generates a discrete representation of the discrete subunit interval category (referred to as the ZigZag category) for n time points.
Arguments
time_points::Int- how many time points to represent
Keyword Arguments
opposite::Bool- iftruemake the underlying schema associated to the ZigZag category opposite; iffalse, the schema remains unchanged (default:true)
Returns
sch::Presentation- aPresentationrepresenting the schema fornnumber oftime_pointscons::DataType- an ACSetDataTypethat represents the constructor built by@acset_type
Examples
Create a ZigZag with 2 time points:
julia> s, c = zigzag(2);Using this function, we can define a zigzag schema on
schema, constructor = zigzag(2; opposite = false);This produces a schema and constructor object. We can look at the schema produced:
to_graphviz(schema, graph_attrs=Dict(:dpi => "70"), prog = "circo")Through this schema, we see two time points: t0 and t1. Additionally, the apex of this span, t0_to_t1, is an object in this category that relates information over these two time points via the homomorphisms, t0_inclS and t1_inclF.
However, for our purposes, we want to work with TemporalSheaves.jl provides op functionality to compute
schema, constructor = zigzag(2; opposite = true);Which yields, reversed homomorphisms for this category:
to_graphviz(schema, graph_attrs=Dict(:dpi => "70"), prog = "circo")Working with Subobjects of
To view the subobjects of this category, one can use Catlab.jl's subobject_classifier method on the constructor object. However, the resulting subobjects are not immediately convenient to visualize or read so TemporalSheaves.jl provides the following method:
TemporalSheaves.subobject_graph_embedding Function
subobject_graph_embedding(cons)Computes the subobjects associated to a ZigZag and interprets them as graph embeddings associated to the underlying graph of the constructor's schema.
Note: If you want raw subobjects, please see the
subobject_classifierfunction.
Arguments
cons::DataType- an ACSetDataTypethat represents the constructor built by@acset_type
Returns
- Vector of subobjects as graph embeddings (specifically,
NamedGraph's).
Examples
Compute the subobjects on the ZigZag schema
julia> s, c = zigzag(c);
julia> subobs = subobject_graph_embedding(c);Calling this function, we can obtain all subobjects as graph embeddings into the graph of the zigzag category:
subobs = subobject_graph_embedding(constructor)Furthermore, we can view these subobjects with the following method:
to_graphviz_htl(subobs, style = "", node_labels = true, edge_labels = true)Furthermore, using these subobject embeddings, one can readily perform propositional logic operations with them such as follows:
A = subobs[4]
B = subobs[1]
C = @withmodel ACSetCategory(constructor()) (⟹) begin
B ⟹ A
end
to_graphviz_htl([B, A, C], node_labels = true, edge_labels = true)You can read the output as
Adding Data To Finite Structures
Preparing across Time Points
To add data to the objects of a zigzag schema category we construct, we proceed in a very similar way with the non-attributed case. However, this time, we start with the following method:
TemporalSheaves.zigzag! Function
zigzag!(time_points::Int; opposite::Bool = true)Generates a discrete representation of the discrete subunit interval category (referred to as the ZigZag category) for n time points prepared for combinatorial data.
Arguments
time_points::Int- how many time points to represent
Keyword Arguments
opposite::Bool- iftruemake the underlying schema associated to the ZigZag category opposite; iffalse, the schema remains unchanged (default:true)
Returns
sch::Presentation- aPresentationrepresenting the schema fornnumber oftime_pointscons::DataType- an ACSetDataTypethat represents the constructor built by@acset_type
Examples
Create a ZigZag with 2 time points:
julia> s, c = zigzag!(2);Applying the same approach as before, we can generate a schema and constructor object:
schema, constructor = zigzag!(2);Attributed - on Time Points
Before continuing, let's examine the new graph of this schema:
to_graphviz(schema, graph_attrs=Dict(:dpi => "70"), prog = "circo")While this schema looks radically different than the previous schema, it is not as different as one may think. For complete clarity, let's look at the definition of this schema:
@present SchZop2! <: SchZigZag begin
(t0, t1, t0_to_t1)::Ob
state::Ob
t0_inclS::Hom(t0, t0_to_t1)
t1_inclF::Hom(t1, t0_to_t1)
t0_state::Hom(t0, state)
t1_state::Hom(t1, state)
temporal_set::AttrType
label::AttrType
t0_temporal_set::Attr(t0, temporal_set)
t1_temporal_set::Attr(t1, temporal_set)
t0_to_t1_temporal_set::Attr(t0_to_t1, temporal_set)
state_label::Attr(state, label)
endBetween the last two schemas, the time point objects and inclusion homomorphsisms are the same. What has been added to this Presentation is attribute information to attach temporal sets to each time point. These are the Attr's denoted as t0_temporal_set, t1_temporal_set, and t0_to_t1_temporal_set. Moreover, the state object has been added so as to record the potential states associated to each element of a temporal set. The state_label Attr associates a given state to labels provided at an instance of this Presentation. The addition of these features to this schema is motivated by applications (see section on applications) and allow full exploitation of the categorical machinery provided by Catlab.jl on such zigzag categories.
Computational Applications of -
To better understand how to use these features, we provide a few examples
Example: Temporal Paths of Flu Transmission
Here, we use the zigzag schema associated to
flu_transmission = @acset constructor{String, String} begin
state = 4
state_labels = ["S", "I", "R", "D"]
t0 = 2
t1 = 3
t0_to_t1 = 2
t0_inclS = [1, 2]
t1_inclF = [1, 2]
t0_state = [1, 2]
t1_state = [2, 3, 1]
t0_temporal_set = ["Jacob", "Sanna"]
t1_temporal_set = ["Jacob", "Sanna", "Tino"]
t0_to_t1_temporal_set = ["Jacob", "Sanna"]
end;| t0 | t0_state | t0_temporal_set |
|---|---|---|
| 1 | 1 | Jacob |
| 2 | 2 | Sanna |
| t0_to_t1 | t0_inclS | t1_inclF | t0_to_t1_temporal_set |
|---|---|---|---|
| 1 | 1 | 1 | Jacob |
| 2 | 2 | 2 | Sanna |
| t1 | t1_state | t1_temporal_set |
|---|---|---|
| 1 | 2 | Jacob |
| 2 | 3 | Sanna |
| 3 | 1 | Tino |
| state | state_labels |
|---|---|
| 1 | S |
| 2 | I |
| 3 | R |
| 4 | D |
We define temporal sets with
function temporal_path(acs, sch, name::String)
s = acset_schema(acs)
t_obs = get_timepoints(sch, type = :discrete)
span_obs = get_timepoints(sch, type = :cumulative)
function get_state(ob)
ob_sym = nameof(ob)
temporal_attr = only(
attr for (attr, dom, codom) in attrs(s; from=ob_sym)
if occursin("temporal_set", string(attr))
)
rows = incident(acs, name, temporal_attr)
isempty(rows) && return nothing
state_hom = findfirst(
((hom, dom, codom),) -> occursin("state", string(hom)),
collect(homs(s; from=ob_sym))
)
isnothing(state_hom) && return nothing
hom_name = homs(s; from=ob_sym)[state_hom][1]
subpart(acs, subpart(acs, only(rows), hom_name), :state_labels)
end
tps = []
states = []
for ob in t_obs
state = get_state(ob)
push!(tps, nameof(ob))
push!(states, state)
end
return hcat(tps, states)
endtemporal_path (generic function with 1 method)Using this function, we can find across the temporal path
temporal_path(flu_transmission, schema, "Jacob")2×2 Matrix{Any}:
:t0 "S"
:t1 "I"We can also do this across more time points; for example:
schema, constructor = zigzag!(4; opposite = true);
longer_flu_transmission = @acset constructor{String, String} begin
state = 4
state_labels = ["S", "I", "R", "D"]
# --- t0 ---
t0 = 3
t0_state = [1, 1, 1] # S, S, S
t0_temporal_set = ["Jacob", "Sanna", "Tino"]
# --- t1 ---
t1 = 3
t1_state = [2, 1, 1] # I, S, S
t1_temporal_set = ["Jacob", "Sanna", "Tino"]
# --- t2 ---
t2 = 3
t2_state = [3, 2, 1] # R, I, S
t2_temporal_set = ["Jacob", "Sanna", "Tino"]
# --- t3 ---
t3 = 3
t3_state = [3, 3, 2] # R, R, I
t3_temporal_set = ["Jacob", "Sanna", "Tino"]
# --- t0_to_t1 span ---
t0_to_t1 = 3
t0_to_t1_temporal_set = ["Jacob", "Sanna", "Tino"]
t0_inclS = [1, 2, 3] # all of t0 persists
t1_inclF = [1, 2, 3] # all of t1 persists
# --- t1_to_t2 span ---
t1_to_t2 = 3
t1_to_t2_temporal_set = ["Jacob", "Sanna", "Tino"]
t1_inclS = [1, 2, 3] # all of t1 persists
t2_inclF = [1, 2, 3] # all of t2 persists
# --- t2_to_t3 span ---
t2_to_t3 = 3
t2_to_t3_temporal_set = ["Jacob", "Sanna", "Tino"]
t2_inclS = [1, 2, 3] # all of t2 persists
t3_inclF = [1, 2, 3] # all of t3 persists
end
temporal_path(longer_flu_transmission, schema, "Sanna")4×2 Matrix{Any}:
:t0 "S"
:t1 "S"
:t2 "I"
:t3 "R"Tips and Tricks
For visualization convenience beyond Catlab.jl's to_graphviz method, TemporalSheaves.jl provides the following methods:
TemporalSheaves.to_graphviz_htl Function
to_graphviz_htl(graphs; style="display: flex; flex-wrap: wrap;",
graph_attrs=Dict(:splines=>"false", :rankdir=>"LR", :dpi=>"70"),
kwargs...)Render a collection of Graphviz graphs as a single HypertextLiteral HTML object, suitable for display in Documenter.jl @example blocks.
Each graph is converted to an SVG string and embedded as a raw HTML <div>, laid out according to style.
Arguments
graphs- a collection of Graphviz-renderable graph objectsstyle::String- CSS style string applied to the outer wrapper<div>graph_attrs- dictionary of Graphviz graph-level attributes passed toto_graphvizkwargs...- additional keyword arguments forwarded toto_graphviz
Returns
- A
HypertextLiteralHTML object containing all graphs as embedded SVGs
Examples
julia> subobs = subobject_graph_embedding(constructor);
julia> to_graphviz_htl(subobs)TemporalSheaves.display_in_repl Function
display_in_repl(g::Graph; image_gap=true)Render a Graphviz Graph as a PNG and display it inline in the terminal using Sixel encoding.
Arguments
g::Graph- a Graphviz graph to renderimage_gap::Bool- iftrue, prints a blank line above the image for visual spacing
Returns
nothing(displays the image tostdoutas a side effect)
Examples
julia> display_in_repl(my_graph)
julia> display_in_repl(my_graph; image_gap=false)