Skip to content

Commit e4d5c4d

Browse files
committed
directories and symbolic resource sharers
1 parent bd3df8e commit e4d5c4d

32 files changed

+1956
-84
lines changed

.editorconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*.jl]
2+
indent_size = 2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ docs/site/
2626
# committed for packages, but should be committed for applications that require a static
2727
# environment.
2828
Manifest.toml
29+
/coverage/

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ authors = ["AlgebraicJulia Developers"]
44
version = "0.1.3"
55

66
[deps]
7+
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
78
AlgebraicInterfaces = "23cfdc9f-0504-424a-be1f-4892b28e2f0c"
89
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
910
Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
1011
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1112
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
1213
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
1314
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
15+
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
1416
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1517
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1618
StructEquality = "6ec83bb0-ed9f-11e9-3b4c-2b04cb4e219c"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Theory Composition
2+
3+
As theories get larger, it becomes more and more important to not build the
4+
entire theory from scratch. Not only is this tedious, it is also error-prone.
5+
From the beginning, Catlab and GATlab have supported single inheritance, which
6+
helps to some extent. In this document, we lay out other approaches to composing
7+
theories.
8+
9+
## Multiple Inheritance
10+
11+
In a GATlab `@theory`, one can use `using` to take the *union* of one theory
12+
with another theory.
13+
14+
The way this works is the following. Every time a new theory is created, the new
15+
definitions for that theory form a new scope, with a unique UUID. Union of
16+
theories operates on a scope tag level, taking the union of the sets of UUIDs
17+
and then producing a theory with all the bindings from the scopes tagged by
18+
those UUIDs.
19+
20+
If we never had to parse user-supplied expressions, then the names of the
21+
operations in the theories wouldn't matter, because identifiers come with scope
22+
tags. However, as a practical matter, we disallow unioning two theories with the
23+
same name declaration.
24+
25+
That being said, it is fine to union two theories which *overload* the same
26+
declaration. That is, if two theories have the declaration of a name in common,
27+
then they can overload that name as long as they don't give conflicting
28+
overloads, in the same way that overloading methods in Julia works.
29+
30+
This is akin to the way multiple inheritance works in frameworks such as
31+
32+
- Haskell typeclasses
33+
- [Object-oriented systems with multiple inheritance, like Scala](https://docs.scala-lang.org/scala3/book/domain-modeling-tools.html#traits)
34+
- [Module inclusion in OCaml](https://cs3110.github.io/textbook/chapters/modules/includes.html)
35+
36+
## Nesting
37+
38+
However, there are other ways of composing things like GATlab theories. In
39+
dependently typed languages used for theorem proving, algebraic structures are
40+
often represented by dependent records. For instance, in the agda unimath
41+
library, the [definition of a group](https://github.com/UniMath/agda-unimath/blob/master/src/group-theory/groups.lagda.md) is
42+
43+
```agda
44+
Semigroup :
45+
(l : Level) → UU (lsuc l)
46+
Semigroup l = Σ (Set l) has-associative-mul-Set
47+
48+
Group :
49+
(l : Level) → UU (lsuc l)
50+
Group l = Σ (Semigroup l) is-group
51+
```

docs/src/examples/springs.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Composition of resource sharers
2+
3+
```julia
4+
5+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Resource Sharers
2+
3+
```@docs
4+
GATlab.NonStdlib.ResourceSharers.Rhizome
5+
GATlab.NonStdlib.ResourceSharers.ResourceSharer
6+
GATlab.NonStdlib.ResourceSharers.Variable
7+
GATlab.NonStdlib.ResourceSharers.PortVariable
8+
GATlab.NonStdlib.ResourceSharers.ocompose
9+
```

dynamics.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# The Road to Dynamical Systems
2+
3+
## Basic steps
4+
5+
- [x] Tuple types
6+
- [-] Symbolic functions
7+
Data type:
8+
9+
```julia
10+
struct AlgebraicFunction
11+
theory::GAT
12+
args::TypeScope
13+
ret::AlgType
14+
body::AlgTerm
15+
end
16+
```
17+
18+
Affordances:
19+
- [x] DSL for writing down functions, composing, etc.
20+
- [ ] A function `tcompose(t::Dtry{AlgebraicFunction})::AlgebraicFunction`, implementing the Dtry-algebra structure on morphisms
21+
- [ ] Interpret/compile a symbolic function into a real function
22+
- [ ] Serialize symbolic functions
23+
- [ ] Compilation
24+
- [ ] Serialization
25+
26+
## Lens-based dynamical systems
27+
28+
- [ ] Arenas
29+
Sketch:
30+
```julia
31+
struct Arena
32+
in::AlgType
33+
out::AlgType
34+
end
35+
```
36+
37+
Affordances:
38+
- A function `tcompose(arena::Dtry{Arena})::Arena`, implementing the Dtry-algebra structure on objects
39+
- [ ] Multilenses
40+
Sketch:
41+
```julia
42+
struct MultiLens
43+
inner_boxes::Dtry{Arena}
44+
outer_box::Arena
45+
# used for namespacing `params` in composition, must not overlap with `inner_boxes`
46+
name::Symbol
47+
params::AlgType
48+
# (params, tcompose(inner_boxes[...].out)) -> outer_box.out
49+
output::AlgebraicFunction
50+
# (params, tcompose(inner_boxes[...].out), outer_box.in) -> tcompose(inner_boxes[...].in)
51+
update::AlgebraicFunction
52+
end
53+
```
54+
55+
Affordances:
56+
- A function `ocompose(l::MultiLens, args::Dtry{MultiLens})::MultiLens` implementing the Dtry-multicategory structure
57+
- [ ] Systems
58+
Sketch:
59+
```julia
60+
struct System
61+
interface::Arena
62+
state::AlgType
63+
params::AlgType
64+
# (params, state) -> interface.out
65+
output::AlgebraicFunction
66+
# (params, state, interface.in) -> state
67+
input::AlgebraicFunction
68+
end
69+
```
70+
71+
Affordances:
72+
- A function `oapply(l::MultiLens, args::Dtry{System})::System` implementing the action of the Dtry-multicategory of multilenses on systems.
73+
74+
## Resource sharers
75+
76+
- [ ] Interfaces
77+
- [ ] Rhizomes (epi-mono uwds)
78+
```julia
79+
struct VariableType
80+
type::AlgType
81+
exposed::Bool
82+
end
83+
84+
struct Rhizome
85+
boxes::Dtry{Interface}
86+
junctions::Dtry{VariableType}
87+
mapping::Dict{DtryVar, DtryVar}
88+
end
89+
```
90+
91+
Affordances:
92+
- `ocompose(r::Rhizome, rs::Dtry{Rhizome})::Rhizome`
93+
94+
In `ocompose`, the names of the junctions in the top-level rhizome dominate.
95+
- [ ] Systems
96+
```julia
97+
struct ResourceSharer
98+
variables::Dtry{VariableType}
99+
params::AlgType
100+
output::AlgType
101+
# (params, state) -> state
102+
update::AlgebraicFunction
103+
# (params, state) -> output
104+
readout::AlgebraicFunction
105+
end
106+
```
107+
108+
Affordances:
109+
- `oapply(r::Rhizome, sharers::Dtry{ResourceSharer})::ResourceSharer`
110+
111+
In `oapply`, variables get renamed to the junctions that they are attached to.

src/models/ModelInterface.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -644,12 +644,12 @@ function migrator(tmap, dom_module, codom_module, dom_theory, codom_theory)
644644
_x = gensym("val")
645645

646646
# Map CODOM sorts to whereparam symbols
647-
whereparamdict = OrderedDict(s=>gensym(s.head.name) for s in sorts(codom_theory))
647+
whereparamdict = OrderedDict(s=>gensym(headof(s).name) for s in sorts(codom_theory))
648648
# New model is parameterized by these types
649649
whereparams = collect(values(whereparamdict))
650650
# Julia types of domain sorts determined by theorymap
651651
jltype_by_sort = Dict(map(sorts(dom_theory)) do v
652-
v => whereparamdict[AlgSort(tmap(v.method).val)]
652+
v => whereparamdict[AlgSort(tmap(methodof(v)).val)]
653653
end)
654654

655655
# Create input for instance_code
@@ -758,13 +758,9 @@ function to_call_impl(t::AlgTerm, theory::GAT, mod::Union{Symbol,Module}, migrat
758758
b = bodyof(t)
759759
if GATs.isvariable(t)
760760
nameof(b)
761-
elseif GATs.isdot(t)
761+
elseif GATs.isdot(t)
762762
impl = to_call_impl(b.body, theory, mod, migrate)
763-
if isnamed(b.head)
764-
Expr(:., impl, QuoteNode(nameof(b.head)))
765-
else
766-
Expr(:ref, impl, getlid(b.head).val)
767-
end
763+
Expr(:., impl, QuoteNode(b.head))
768764
else
769765
args = to_call_impl.(argsof(b), Ref(theory), Ref(mod), migrate)
770766
name = nameof(headof(b))

src/models/SymbolicModels.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,13 @@ end
328328

329329
function internal_accessors(theory::GAT)
330330
map(theory.sorts) do sort
331-
typecon = getvalue(theory[sort.method])
332-
map(collect(pairs(theory.accessors[sort.method]))) do (i, acc)
331+
typecon = getvalue(theory[methodof(sort)])
332+
map(collect(pairs(theory.accessors[methodof(sort)]))) do (i, acc)
333333
accessor = getvalue(theory[acc])
334334
return_type = getvalue(typecon[typecon.args[i]])
335335
JuliaFunction(
336336
name=esc(nameof(getdecl(accessor))),
337-
args=[:(x::$(esc(nameof(sort.head))))],
337+
args=[:(x::$(esc(nameof(sort))))],
338338
return_type = typename(theory, return_type),
339339
impl=:(x.type_args[$i])
340340
)
@@ -415,11 +415,11 @@ function symbolic_instance_methods(
415415
type_con_funs = []
416416
accessors_funs = []
417417
for sort in sorts(theory)
418-
type_con = getvalue(theory[sort.method])
419-
symgen = symbolic_generator(theorymodule, syntaxname, sort.method, type_con, theory)
418+
type_con = getvalue(theory[methodof(sort)])
419+
symgen = symbolic_generator(theorymodule, syntaxname, methodof(sort), type_con, theory)
420420
push!(type_con_funs, symgen)
421421
for binding in argsof(type_con)
422-
push!(accessors_funs, symbolic_accessor(theorymodule, theory, syntaxname, sort.method, binding))
422+
push!(accessors_funs, symbolic_accessor(theorymodule, theory, syntaxname, methodof(sort), binding))
423423
end
424424
end
425425

@@ -614,7 +614,7 @@ function parse_json_sexpr(syntax_module::Module, sexpr;
614614
theory = theory_module.Meta.theory
615615
type_lens = Dict(
616616
nameof(getdecl(getvalue(binding))) => length(getvalue(binding).args)
617-
for binding in [theory[sort.method] for sort in sorts(theory)]
617+
for binding in [theory[methodof(sort)] for sort in sorts(theory)]
618618
)
619619

620620
function parse_impl(sexpr::Vector, ::Type{Val{:expr}})

0 commit comments

Comments
 (0)