Skip to content

Commit

Permalink
Redesign ACSetFunctors when there are AttrVars (#915)
Browse files Browse the repository at this point in the history
* modifications to make attrvars play nicer with data migrations

* removed a question

---------

Co-authored-by: Kevin Arlin <[email protected]>
  • Loading branch information
KevinDCarlson and Kevin Arlin authored Jun 21, 2024
1 parent ee6a034 commit c1dc167
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
22 changes: 15 additions & 7 deletions src/categorical_algebra/CSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ FinDomFunction(c::Column{Int,Union{AttrVar,T}}, dom, codom) where {T} =
""" Create `VarSet` for attribute type of attributed C-set."""
function VarSet(X::ACSet, type::Symbol)
S = acset_schema(X)
if type ob(S)
if type ob(S) #honestly should probably be an error
return VarSet{Union{}}(nparts(X,type))
else
return VarSet{attrtype_type(X,type)}(nparts(X,type))
Expand All @@ -115,7 +115,7 @@ function VarFunction(X::ACSet, f::Symbol)
if f attrs(S; just_names=true)
VarFunction(X.subparts[f], parts(X,dom(S,f)), FinSet(nparts(X,codom(S,f))))
else
VarFunction(FinFunction(X,f))
VarFunction(FinFunction(X,f)) #also probably an error
end
end

Expand Down Expand Up @@ -198,20 +198,28 @@ end
FinDomFunctor(X::ACSet) = ACSetFunctor(X)
ACSet(X::ACSetFunctor) = X.acset

hasvar(X::ACSet) = any(o->nparts(X,o) > 0, attrtypes(acset_schema(X))) # upstream?
hasvar(X::ACSetFunctor) = hasvar(ACSet(X))
function hasvar(X::ACSet,x)
s = acset_schema(X)
(x attrs(acset_schema(X),just_names=true) && hasvar(X,codom(s,x))) ||
xattrtypes(acset_schema(X)) && nparts(X,x)>0
end
hasvar(X::ACSet) = any(o->hasvar(X,o), attrtypes(acset_schema(X)))
hasvar(X::ACSetFunctor,x) = hasvar(X.acset,x)
hasvar(X::ACSetFunctor) = hasvar(X.acset)


dom(F::ACSetFunctor) = FinCat(Presentation(ACSet(F)))

#not clear this couldn't just always give the Vars
function codom(F::ACSetFunctor)
hasvar(F) ? TypeCat{VarSet,VarFunction}() :
hasvar(F) ? TypeCat{Union{SetOb,VarSet},Union{FinDomFunction{Int},VarFunction}}() :
TypeCat{SetOb,FinDomFunction{Int}}()
end

Categories.do_ob_map(F::ACSetFunctor, x) =
(hasvar(F) ? VarSet : SetOb)(ACSet(F), functor_key(x))
(hasvar(F,functor_key(x)) ? VarSet : SetOb)(F.acset, functor_key(x))
Categories.do_hom_map(F::ACSetFunctor, f) =
(hasvar(F) ? VarFunction : FinFunction)(ACSet(F), functor_key(f))
(hasvar(F,functor_key(f)) ? VarFunction : FinFunction)(F.acset, functor_key(f))

functor_key(x) = x
functor_key(expr::GATExpr{:generator}) = first(expr)
Expand Down
18 changes: 15 additions & 3 deletions src/categorical_algebra/FinSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
module FinSets
export FinSet, FinFunction, FinDomFunction, TabularSet, TabularLimit,
force, is_indexed, preimage, VarFunction, LooseVarFunction,
force, is_indexed, preimage, VarSet, VarFunction, LooseVarFunction,
JoinAlgorithm, SmartJoin, NestedLoopJoin, SortMergeJoin, HashJoin,
SubFinSet, SubOpBoolean, is_monic, is_epic, is_iso

Expand Down Expand Up @@ -322,9 +322,13 @@ Base.in(set::VarSet{T}, elem) where T = in(elem, 1:set.n)

abstract type AbsVarFunction{T} end # either VarFunction or LooseVarFunction
"""
Data type of a map out of a set of attribute variables
Data type for a morphism of VarSet{T}s. Note we can equivalently view these
as morphisms [n]+T -> [m]+T fixing T or as morphisms [n] -> [m]+T, in the typical
Kleisli category yoga.
Currently, domains are FinSet{Int} and codomains are expected to be FinSet{Int}.
Currently, domains are treated as VarSets. The codom field is treated as a FinSet{Int}.
Note that the codom accessor gives a VarSet while the codom field is just that VarSet's
FinSet of AttrVars.
This could be generalized to being FinSet{Symbol} to allow for
symbolic attributes. (Likewise, AttrVars will have to wrap Any rather than Int)
"""
Expand All @@ -338,15 +342,19 @@ symbolic attributes. (Likewise, AttrVars will have to wrap Any rather than Int)
end
VarFunction(f::AbstractVector{Int},cod::Int) = VarFunction(FinFunction(f,cod))
VarFunction(f::FinDomFunction) = VarFunction{Union{}}(AttrVar.(collect(f)),codom(f))
VarFunction{T}(f::FinDomFunction,cod::FinSet) where T = VarFunction{T}(collect(f),cod)
FinFunction(f::VarFunction{T}) where T = FinFunction(
[f.fun(i) isa AttrVar ? f.fun(i).val : error("Cannot cast to FinFunction")
for i in dom(f)], f.codom)
FinDomFunction(f::VarFunction{T}) where T = f.fun
Base.length(f::AbsVarFunction{T}) where T = length(collect(f.fun))
Base.collect(f::AbsVarFunction{T}) where T = collect(f.fun)

(f::VarFunction{T})(v::T) where T = v
(f::AbsVarFunction{T})(v::AttrVar) where T = f.fun(v.val)

#XX if a VarSet could contain an arbitrary FinSet of variables this
# wouldn't need to be so violent
dom(f::AbsVarFunction{T}) where T = VarSet{T}(length(collect(f.fun)))
codom(f::VarFunction{T}) where T = VarSet{T}(length(f.codom))
id(s::VarSet{T}) where T = VarFunction{T}(AttrVar.(1:s.n), FinSet(s.n))
Expand Down Expand Up @@ -374,6 +382,10 @@ compose(f::VarFunction{T}, g::FinFunction) where T =
VarFunction{T}([elem isa AttrVar ? AttrVar(g(elem.val)) : elem
for elem in collect(f)], g.codom)

"""Compose [n]->[m] with [m]->[p]+T, yielding a [n]->T+[p]"""
compose(f::FinFunction,g::VarFunction{T}) where T =
VarFunction{T}(compose(f,g.fun), g.codom)

preimage(f::VarFunction{T}, v::AttrVar) where T = preimage(f.fun, v)
preimage(f::VarFunction{T}, v::T) where T = preimage(f.fun, v)
force(f::VarFunction{T}) where T = f
Expand Down
7 changes: 7 additions & 0 deletions test/categorical_algebra/FinSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -535,11 +535,18 @@ end
##############
# Construction
f = VarFunction{Vector{Int}}([AttrVar(1),[1,2,3]], FinSet(1))
g = VarFunction{Vector{Int}}(FinDomFunction([AttrVar(1),[1,2,3]]),FinSet(1))
@test f == g
@test f([1,2]) == [1,2]
@test f(AttrVar(2)) == [1,2,3]

# Composition
f = VarFunction{Bool}(([AttrVar(2),AttrVar(1), true]),FinSet(3))
g = FinFunction([2,3])
h = FinFunction([2,2,1])
@test collect(f f) == [AttrVar(1),AttrVar(2), true]
@test collect(compose(g,f)) == [AttrVar(1),true]
@test collect(compose(f,h)) == [AttrVar(2),AttrVar(2), true]

@test force(f) == f
@test f.(AttrVar.(3:-1:1)) == [true, AttrVar.(1:2)...]
Expand Down

0 comments on commit c1dc167

Please sign in to comment.