Skip to content
Draft
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
90 changes: 88 additions & 2 deletions src/categorical_algebra/CatElements.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module CatElements
export ThElements, AbstractElements, Elements, elements
export ThElements, AbstractElements, Elements, elements, attr_elements

using DataStructures: OrderedDict

using ..CSets, ..FinSets
using ...Present, ...Theories
using ...Theories: Category, ob, hom, dom_nums, codom_nums
using ...Theories: Category, ob, hom, dom_nums, codom_nums,
attr, attrtype, adom_nums, acodom_nums

@present ThElements(FreeSchema) begin
(El, Arr, Ob, Hom)::Ob
Expand Down Expand Up @@ -84,4 +85,89 @@ function presentation(X::AbstractElements)
add_generators!(P, values(homs))
return P, obs, homs
end

@present ThAttrElements <: ThElements begin
(Item, ItArr, AttrType, Attr)::Ob
Type::AttrType
Data::AttrType

itsrc::Hom(ItArr, El)
ittgt::Hom(ItArr, Item)
atsrc::Hom(Attr, Ob)
attgt::Hom(Attr, AttrType)

πᵢ::Hom(Item, AttrType)
πᵢₐ::Hom(ItArr, Attr)

namea::Attr(Attr, Name)
nameat::Attr(AttrType, Name)
type::Attr(AttrType, Type)
data::Attr(Item, Data)
end

@abstract_acset_type AbstractAttributedElements
@acset_type AttrElements(ThAttrElements, index=[:src, :tgt, :πₑ, :πₐ,
:itsrc, :ittgt, :πᵢ, :πᵢₐ]) <: AbstractAttributedElements


function el_inds(X::StructACSet{S}) where S
i = 1
inds = Vector{UnitRange{Int}}()
for o in ob(S)
push!(inds, i:(i+nparts(X,o) - 1))
i += nparts(X,o)
end
inds
end

function attr_elements(X::StructACSet{S, Ts}) where {S, Ts}
Y = AttrElements{Symbol, Type, Any}()
Y′ = elements(X)
copy_parts!(Y, Y′)
attrtypes = attrtype(S)
types = Ts.parameters

add_parts!(Y, :AttrType, length(attrtypes), nameat = attrtypes, type=types)

attrs = attr(S)
add_parts!(Y, :Attr, length(attrs), atsrc=adom_nums(S), attgt=acodom_nums(S), namea=attrs)

els = el_inds(X)
map(enumerate(zip(attrs, adom_nums(S), acodom_nums(S)))) do (i, (f, oi, ai))
o = ob(S)[oi]
items = add_parts!(Y, :Item, nparts(X,o), πᵢ = ai, data = X[f])
add_parts!(Y, :ItArr, nparts(X,o), itsrc=els[oi], ittgt=items, πᵢₐ=i)
end
Y
end

""" presentation(X::AbstractAttributedElements)

convert a category of elements with attributes into a new schema. Currently
this is performed by simply extending the current attributes to the new
objects.

TODO:
If attributes are going to be treated as homomorphisms, this should check
for unique attributes and generate a new AttrType for each one.
"""
function presentation(X::AbstractAttributedElements)
X′ = Elements{Symbol}()
copy_parts!(X′, X)
P, obs, homs = presentation(X′)
add_generators!(P, [AttrType(FreeSchema.AttrType, X[at, :nameat]) for at in parts(X, :AttrType)])

attrs = OrderedDict{Tuple{Symbol, Int}, Any}()
for a in 1:nparts(X, :Attr)
o = X[a, :atsrc]
class = X[o, :nameo]
for (i,j) in enumerate(incident(X, o, :πₑ))
oname = Symbol("$(class)_$i")
cur_attr = Attr(Symbol(X[a, :namea], "_", oname), P[oname], P[X[X[a, :attgt], :nameat]])
attrs[(class, j)] = cur_attr
end
end
add_generators!(P, values(attrs))
return P, obs, homs
end
end
49 changes: 48 additions & 1 deletion test/categorical_algebra/CatElements.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,58 @@ end

@testset "DiBipartite Elements" begin
@test length(generators(ThPetri)) == 8
@test nparts(sir_eltsch, :V_1) == 3
@test nparts(sir_eltsch, :V_1) == 3
@test nparts(sir_eltsch, :V_2) == 2
@test nparts(sir_eltsch, :E_1) == 3
@test nparts(sir_eltsch, :E_2) == 3
@test sir_eltsch[:, :src_E_2] == [1,1,2]
end

using Catlab.Graphs.BasicGraphs: TheoryGraph
@present TheoryLabelledGraph <: TheoryGraph begin
Label::AttrType
label::Attr(V,Label)
end
@acset_type LabelledGraph(TheoryLabelledGraph)

p₁ = @acset LabelledGraph{Symbol} begin
V = 2
E = 2
src=[1,2]
tgt=[2,1]
label=[:label, :label]
end

ThLabelledPetri, obmap, hommap = CatElements.presentation(attr_elements(p₁))
@test Symbol.(generators(ThLabelledPetri)) ==
[:V_1, :V_2, :E_1, :E_2, :src_E_1, :src_E_2, :tgt_E_1, :tgt_E_2, :Label, :label_V_1, :label_V_2]

@acset_type LabelledPetri(ThLabelledPetri)

sir_lab_eltsch = @acset LabelledPetri{Symbol} begin
V_1 = 3
V_2 = 2
E_1 = 3
E_2 = 3

src_E_1 = [1,2,2]
tgt_E_1 = [1,1,2]

src_E_2 = [1,1,2]
tgt_E_2 = [2,2,3]

label_V_1 = [:S, :I, :R]
label_V_2 = [:inf, :rec]
end

@testset "Labelled DiBipartite Elements" begin
@test length(generators(ThLabelledPetri)) == 11
@test nparts(sir_lab_eltsch, :V_1) == 3
@test nparts(sir_lab_eltsch, :V_2) == 2
@test nparts(sir_lab_eltsch, :E_1) == 3
@test nparts(sir_lab_eltsch, :E_2) == 3
@test sir_lab_eltsch[:, :src_E_2] == [1,1,2]
@test sir_lab_eltsch[:, :label_V_1] == [:S, :I, :R]
@test sir_lab_eltsch[:, :label_V_2] == [:inf, :rec]
end
end