-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorporating GATlab more deeply #949
base: main
Are you sure you want to change the base?
Conversation
@kris-brown what is the timeline around this? I could see how keeping this up to date with any Catlab changes is going to be a nightmare. |
I'm working full speed on it now, I expect to be ready for review by end of next week (really depends on how many dependent packages on Catlab use implementation details that I wasn't expecting though) |
Ok, let's block the devs meeting next week to talk about this and you can have some kind of document that describes the changes that we can go through together. Rather than just using traditional code review. Because this is basically doing a systematic change across the whole codebase |
more progress split off basicsets from setcats
Comments from devs meeting:
|
An update before I go back and refactor an earlier part of this PR.
|
Consider this GAT which is meant to abstract the common ways """
This is simpler than a `FinDomFunctor` because the domain is not a FinCat but
rather a finite Graph. We also don't worry about the category structure of the
codomain (e.g. homs need not specify dom/cod, no composition structure).
To get a real diagram out of this, one must supply a Category with the
appropriate Ob/Hom types which are supertypes of the Ob/Hom types of the
FreeDiagram.
"""
@theory ThFreeDiagram begin
V::TYPE; E::TYPE; Ob::TYPE; Hom::TYPE; FinSet::TYPE;
src(h::E)::V;
tgt(h::E)::V;
obset()::FinSet
homset()::FinSet
obmap(v::V)::Ob
hommap(e::E)::Hom
end For example, a By not presupposing the category structure of the codomain of this diagram, this means we don't have to carry around a bunch of methods for how to do identities/composition -- this is good; the point of a FreeDiagram is that we can really just treat it like a piece of concrete data. We can simply say "here is a pair However, there is one wrinkle in this, which is that the An obvious situation where this is a problem is if we want to have a span in a category of 'bare' morphisms (where the morphisms don't carry full info about their domain and codomain). Or, in the case that brought this issue to my attention, the category Note
So the domain of a It seems the easiest way around this issue would be to just add the extra data to the various structs, e.g.: @struct_hash_equal struct Multispan{Ob,Hom,Legs<:AbstractVector{Hom}}
apex::Ob
legs::AbstractVector{Hom}
feet::AbstractVector{Ob} # NEW: we add this data, which will sometimes be redundant
end With constructors that fill in this extra data using |
Major overhaul of Limit/Colimit interface to not use dispatch. Overhaul of the ACSet category approach to not rely on dispatch. Actual models of theories of cats with limits/colimits just implemented for SkelFinSet and PointwiseCats. Modified some FreeDiagram models so that they no longer implicitly rely on type dispatch for some ThCategory structure (i.e. getting the feet of a cospan via dispatch on `dom`). Removed `compose(f,g,h,fs...)` method (and the like) in Theories: unnecessary type piracy which complicated other things Convenience `Tagged` method for working with the eltypes of SumSets. And `untag` method for projecting out of SumSets. Using GATlab branch which has removed @import Improved Matrices.jl to use new GATlab explicit models which addresses some old problems with it.
Summary
This is a big refactor - right now just a draft. The goal is to rely less on type dispatch and use explicit models from GATlab. This will ultimately address a number of persistent problems we've seen in Catlab over the years, including issues with empty lists, ACSets vs VarACSets, DenseACSets vs SparseACSets, C-Set vs C-Par. It will still be convenient at times to use a Julia
abstract_type
to handle informal interfaces, but for things like different implementations of FinSets, different implementations of FinCats, etc. we will use a data structure with aimpl
field and amodel
field which controls how the implementation satisfies the desired interface.The goal is for only minor breaking changes, keeping the user-experience as unchanged as possible despite big changes under the hood.
It is a bit difficult to track the changes because this is also an appropriate time to restructure the files. The new style encourages a separation between a file that declares an interface (e.g.
ThFinCat
, a structFinCat
for models ofThFinSet
, some common methods that apply toFinCat
s) vs a folder of individual files for various implementations ofFinCat
s. Furthermore,CategoricalAlgebra
is now split into further subfolders,BasicSets
(sets, functions ... no category theory),Cats
(e.g. (Fin)Category
,(Fin)Functor
, generic (co)limit infrastructure),SetCats
(categories of + (co)limits of sets ... this depends on the previous two folders), and lastlyCSetCats
for C-Set-like categories, hom search, the chase, etc.Common design decisions
FinSet
used to have a type parameter for the Julia type of the elements of that FinSet (thus bothFinSetInt
andTypeSet{Int}
were both subtypes ofFinSet{Int}
. Likewise for categories having the Julia types of the ob/homs. However, we don't really ever want to dispatch on this. Implementations of theories need type parameters because instances require assigning Julia types to the type constructors of a theory. For example,However, a
FinDomFunctor
(which might wrap aFinDomFunctorMap
) has no type parameters. One can callobtype(dom(F))
etc. to recover these at runtime.FinCat
(wraps models ofThFinCat
). We can either haveFinCat <: CatImpl
(aFinCat
is an implementation ofThCategory
) or havestruct FinCatAsCat <: CatImpl
which wraps aFinCat
and says it is to be interpreted as aCategory
. If a struct is really canonically thought of as a model for a particular theory, it makes sense to do the former. Of course, the same data could be models for many theories. But only one can be a 'default' theory for which it is a model.GATlab
Using GATlab in a very serious way has revealed a lot of improvements to make to it. Some of this is in the
GATlabUpstream.jl
file. Some needed fixes were deeper, so this PR will only work with the following branch checked out: AlgebraicJulia/GATlab.jl#166There is a very common design pattern of needing a datatype for models of a particular theory, where one can call the theory operations on the wrapper struct which simply calls the theory method on the implementation. This boilerplate is repeated a lot through this PR - it can probably be straightforwardly abstracted in a future GATlab PR, but that is not a priority.
There is a need for integrating Julia types with theories in the same way ACSets integrate Julia types with schemas. For example,
Morally, we want all models of this theory to assign Julia's
Bool
to the type constructorBool'
andAny
toAny'
. We enforce this by declaringabstract type SetImpl <: Model{Tuple{Bool, Any}} end
. Now we get an error if we try to implementThSet′
for a subtype ofSetImpl
that does not respect this.Changes
It's hard to keep this in sync with actual progress
Set
's element type should not be part of theFinSet
(orSetOb
) Julia type.TypeCat
is a "Pair of Julia types regarded as a category. The Julia types should form an@instance
of the theory of categories". This meansTypeCat
is our name for the wrapper struct of an arbitrary model ofThCategory
.ThCategory
which includes nullaryob_set
andhom_set
operations which produceAbsSet
s. We want to be able to distinguish a category whose objects areFinSetInt
andTypeSet{Int}
, so using Julia type parameters is not very helpful. Thus the mainCategory
struct is a wrapper aroundThCategoryExplicitSets
rather than merelyThCategory
.is_hom_equal
(not part of the ThCategory, doesn't get used anywhere in Catlab)ob(::Cat{Ob,Hom}, x)
andhom
coercions cannot be handled by dispatch if we are now allowing for multiple different categories with the sameOb
andHom
.FinCat
s actually work - the relationship between homs and hom generators (which are often conflated byhom_map
in Catlab presently). This is now more explicit though the API around FinCats is slightly different to avoid ambiguous situations (such as when homs and hom generators are the same Julia type).NamedTuple
anddom
+codom
ACSet. For validation, all we expect is for there to be some SetFunction for each component. There is a lot more validation that can be for a given category, such asCSetCat
(which makes suredom
/codom
have no attributes),CParCat
,VarACSetCat
, etc.). We can still do some validation if the user passes in raw vectors of data (which can be interpreted asSetFunctions
in some default ways), but in general the data structure won't inherently make any guarantees about what theSetFunction
s should be without the context of a particular explicitCategory
struct.Progress
Done with
BasicSets
,Cats
(though I've temporarily skipped Natural Transformations),SetCats
, and some partial progress throughCSetCats
.