Skip to content
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

Update for GATlab.jl and DataMigrations.jl #32

Merged
merged 4 commits into from
Jan 4, 2024
Merged
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
7 changes: 5 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "AlgebraicRewriting"
uuid = "725a01d3-f174-5bbd-84e1-b9417bad95d9"
license = "MIT"
authors = ["Kris Brown <[email protected]>"]
version = "0.2.1"
version = "0.3.0"

[deps]
ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8"
Expand All @@ -15,13 +15,16 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[weakdeps]
Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
DataMigrations = "0c4ad18d-0c49-4bc2-90d5-5bca8f00d6ae"

[extensions]
AlgebraicRewritingLuxorExt = "Luxor"
AlgebraicRewritingDataMigrationsExt = "DataMigrations"

[compat]
ACSets = "0.2.9"
Catlab = "0.15.4, 0.16"
Catlab = "0.16.1"
DataMigrations = "0.0.2"
DataStructures = "0.17, 0.18"
Reexport = "^1"
StructEquality = "2.1"
Expand Down
15 changes: 3 additions & 12 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
[deps]
ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8"
AlgebraicPetri = "4f99eebe-17bf-4e98-b6a1-2c4f205a959b"
AlgebraicRewriting = "725a01d3-f174-5bbd-84e1-b9417bad95d9"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Catlab = "134e5e36-593f-5add-ad60-77f754baafbe"
DataMigrations = "0c4ad18d-0c49-4bc2-90d5-5bca8f00d6ae"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
StructEquality = "6ec83bb0-ed9f-11e9-3b4c-2b04cb4e219c"

[compat]
ACSets = "0.2.6"
Catlab = "0.15.5"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
20 changes: 9 additions & 11 deletions docs/src/full_demo.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using AlgebraicRewriting
using Catlab, Catlab.CategoricalAlgebra, Catlab.Graphics, Catlab.Graphs, Catlab.Programs
import AlgebraicPetri
using AlgebraicRewriting, Catlab, AlgebraicPetri, DataMigrations
using Test


Expand All @@ -9,7 +7,7 @@ This is a self-contained walkthrough of the main features of AlgebraicRewriting.
This is a regular julia file that can be run interactively.

Importantly:
- use Julia 1.9 (not yet official released)
- use Julia 1.10
- ]activate the environment in AlgebraicRewriting.jl/docs
- check that graphviz is installed locally (test via "which dot" in terminal)

Expand Down Expand Up @@ -54,8 +52,8 @@ We construct a rule by providing a span, L ← I → R
L = path_graph(Graph, 2) # • → •
I = Graph(1) # •
R = @acset Graph begin V=1; E=1; src=1; tgt=1 end # •↺
l = CSetTransformation(I, L; V=[1]) # graph homomorphism data
r = CSetTransformation(I, R; V=[1])
l = ACSetTransformation(I, L; V=[1]) # graph homomorphism data
r = ACSetTransformation(I, R; V=[1])

rule = Rule(l, r)
G = path_graph(Graph, 5) # • → • → • → • → •
Expand Down Expand Up @@ -139,7 +137,7 @@ rule_sqpo = Rule{:SqPO}(l, r) # same data as before)
G = star_graph(Graph, 6) # a 5-pointed star
to_graphviz(G; prog="neato") # changing "prog" can sometimes make it look better

m = CSetTransformation(Graph(1), G; V=[6]) # point at the center
m = ACSetTransformation(Graph(1), G; V=[6]) # point at the center
res = rewrite_match(rule_sqpo, m)
to_graphviz(res; prog="neato")

Expand All @@ -163,7 +161,7 @@ r = id(K)
L′ = @acset Graph begin V=3; E=6;
src=[1,1,1,2,3,3]; tgt=[1,2,3,3,3,1]
end
tl = CSetTransformation(L, L′; V=[2]) # 2 is the matched vertex
tl = ACSetTransformation(L, L′; V=[2]) # 2 is the matched vertex
to_graphviz(L′; node_labels=true)

# The outneighbors of the matched vertex are duplicated (an edge connects the
Expand All @@ -173,7 +171,7 @@ to_graphviz(L′; node_labels=true)
K′ = @acset Graph begin V=5; E=9;
src=[1,1,1,2,3,3,3,4,5]; tgt=[1,2,3,3,3,1,5,5,5]
end
tk = CSetTransformation(K,K′; V=[2,4])
tk = ACSetTransformation(K,K′; V=[2,4])
to_graphviz(K′; node_labels=true)

l′ = homomorphism(K′,L′; initial=(V=[1,2,3,2,3],))
Expand Down Expand Up @@ -205,14 +203,14 @@ category of (whole-grain) Petri nets, with States and Transitions.
"""


function graph_slice(s::Slice)
function graph_slice(s::Slice)
h = s.slice
V, E = collect.([h[:V], h[:E]])
g = dom(h)
(S,T), (I,O) = [[findall(==(i),X) for i in 1:2] for X in [V,E]]
nS,nT,nI,nO = length.([S,T,I,O])
findS, findT = [x->findfirst(==(x), X) for X in [S,T]]
AlgebraicPetri.Graph(@acset AlgebraicPetri.PetriNet begin
to_graphviz(@acset AlgebraicPetri.PetriNet begin
S=nS; T=nT; I=nI; O=nO
is=findS.(g[I,:src]); it=findT.(g[I, :tgt])
ot=findT.(g[O,:src]); os=findS.(g[O, :tgt]) end)
Expand Down
8 changes: 3 additions & 5 deletions docs/src/lotka_volterra.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module LotkaVolterra

using Catlab, Catlab.Theories, Catlab.CategoricalAlgebra, Catlab.Graphs,
Catlab.Graphics, Catlab.WiringDiagrams, Catlab.Programs
using AlgebraicRewriting
using Catlab, DataMigrations, AlgebraicRewriting
using Random, Test, StructEquality
using Luxor

Expand Down Expand Up @@ -74,10 +72,9 @@ F2 = Migrate(
Dict(x=>x for x in Symbol.(TheoryLV.generators[:Hom])), LV′; delta=false)

"""
Create a nxn grid with periodic boundary conditions. Edges in each cardinal
Create an n × n grid with periodic boundary conditions. Edges in each cardinal
direction originate at every point


(i,j+1) -> (i+1,j+1) -> ...
↑ ↑
(i,j) -> (i+1,j) -> ...
Expand Down Expand Up @@ -410,6 +407,7 @@ cycle = ( agent(sheep; n=:sheep, ret=I)
# wrap in a while loop
overall = while_schedule(cycle, curr -> nparts(curr,:Wolf) >= 0) |> F2
# view_sched(overall; names=F2(N))

X = initialize(3, .25, .25)
res, = apply_schedule(overall, X; steps=50);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,12 @@
module Representable
export yoneda_cache, SchRule, SchRulel, SchRuler, SchRule, SchPBPO
module AlgebraicRewritingDataMigrationsExt

using Catlab, Catlab.CategoricalAlgebra
using Catlab
using ACSets.DenseACSets: constructor
using Catlab.Programs.DiagrammaticPrograms: AST
using DataMigrations

import ..Utils: Rule
import ..PBPO: PBPORule
using AlgebraicRewriting
import AlgebraicRewriting.Rewrite: Rule, PBPORule

# Rule schemas
##############

@present SchRule_(FreeSchema) begin
L::Ob # inputs
R::Ob # outputs
K::Ob # keep
end

@present SchRulel <: SchRule_ begin
l::Hom(L, K)
end
@present SchRuler <: SchRule_ begin
r::Hom(R, K)
end

@present SchRule <: SchRulel begin
r::Hom(R, K)
end

@present SchPBPO <: SchRule begin
(L′, K′)::Ob
tₗ::Hom(L′,L)
tₖ::Hom(K′,K)
l′::Hom(L′,K′)
end

# Caching
#########

function yoneda_cache(T::Type,S=nothing; clear=false, cache="cache")
S = isnothing(S) ? Presentation(T) : S
tname = nameof(T) |> string
cache_dict = Dict{Symbol,Tuple{T,Int}}(map(generators(S, :Ob)) do ob
name = nameof(ob)
cache_dir = mkpath(joinpath(cache, "$tname"))
path, ipath = joinpath.(cache_dir, ["$name.json", "_id_$name.json"])
name => if !clear && isfile(path)
(read_json_acset(T, path), parse(Int,open(io->read(io, String), ipath)))
else
@debug "Computing representable $name"
rep, i = representable(T, S, name; return_unit_id=true)
write_json_acset(rep, path)
write(ipath, string(i))
(rep, i)
end
end)
return yoneda(T; cache=cache_dict)
end

# Alternate constructors for rules
##################################
Expand Down Expand Up @@ -129,4 +79,4 @@ function named_ob_generators(C::FinCat)
end


end # module
end # module
3 changes: 2 additions & 1 deletion src/analysis/Processes.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module Processes
export find_deps

using Catlab.CategoricalAlgebra, Catlab.Graphs
using Catlab
using Catlab.Theories: ⋅

using ..Rewrite.Utils

Expand Down
1 change: 1 addition & 0 deletions src/categorical_algebra/CSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ end
(F::Migrate)(d::Dict{V,<:ACSet}) where V = Dict([k=>F(v) for (k,v) in collect(d)])
(F::Migrate)(d::Dict{<:ACSet,V}) where V = Dict([F(k)=>v for (k,v) in collect(d)])
(m::Migrate)(::Nothing) = nothing
(m::Migrate)(s::Union{String,Symbol}) = s
function (m::Migrate)(Y::ACSet)
if m.delta
typeof(Y) <: m.T1 || error("Cannot Δ migrate a $(typeof(Y))")
Expand Down
16 changes: 8 additions & 8 deletions src/categorical_algebra/PartialMap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ the same data for a morphism lifted from X⟶Y to T(X)⟶T(Y).
However, we still need to map the extra stuff in T(X) to the proper extra stuff
in T(Y).
"""
function partial_map_functor_hom(f::CSetTransformation;
pres::Union{Nothing, Presentation}=nothing)::CSetTransformation
function partial_map_functor_hom(f::ACSetTransformation;
pres::Union{Nothing, Presentation}=nothing)::ACSetTransformation
X, Y = dom(f), codom(f)
S = acset_schema(X)
(d, _), (cd, cddict) = [partial_map_functor_ob(x; pres=pres) for x in [X,Y]]
Expand All @@ -132,19 +132,19 @@ function partial_map_functor_hom(f::CSetTransformation;
end
end
end
return CSetTransformation(d,cd;comps...)
ACSetTransformation(d, cd; comps...)
end

"""
The natural injection from X ⟶ T(X)
When evaluated on the terminal object, this gives the subobject classfier.
"""
function partial_map_classifier_eta(x::StructCSet;
pres::Union{Nothing, Presentation}=nothing)::CSetTransformation
pres::Union{Nothing, Presentation}=nothing)::ACSetTransformation
S = acset_schema(x)
codom = partial_map_functor_ob(x; pres=pres)[1]
d = Dict([k=>collect(v) for (k,v) in pairs(id(x).components)])
return CSetTransformation(x, codom; d...)
ACSetTransformation(x, codom; d...)
end


Expand All @@ -165,9 +165,9 @@ the subobject picked out by X. When A is 'deleted', it picks out the right
element of the additional data added by T(B).
"""
function partial_map_classifier_universal_property(
m::CSetTransformation, f::CSetTransformation;
m::ACSetTransformation, f::ACSetTransformation;
pres::Union{Nothing, Presentation}=nothing, check=false
)::CSetTransformation
)::ACSetTransformation
S = acset_schema(dom(m))
hdata = collect(homs(S))
A, B = codom(m), codom(f)
Expand Down Expand Up @@ -196,7 +196,7 @@ function partial_map_classifier_universal_property(
end
end
end
ϕ = CSetTransformation(A, TB; res...)
ϕ = ACSetTransformation(A, TB; res...)
if check
is_natural(ηB) || error("ηB not natural $ηB")
is_natural(ϕ) || error("ϕ not natural $ϕ")
Expand Down
57 changes: 57 additions & 0 deletions src/rewrite/Migration.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module Migration
export yoneda_cache, SchRule, SchRulel, SchRuler, SchRule, SchPBPO

using Catlab
using ..Utils

# Rule schemas
##############

@present SchRule_(FreeSchema) begin
L::Ob # inputs
R::Ob # outputs
K::Ob # keep
end

@present SchRulel <: SchRule_ begin
l::Hom(L, K)
end
@present SchRuler <: SchRule_ begin
r::Hom(R, K)
end

@present SchRule <: SchRulel begin
r::Hom(R, K)
end

@present SchPBPO <: SchRule begin
(L′, K′)::Ob
tₗ::Hom(L′,L)
tₖ::Hom(K′,K)
l′::Hom(L′,K′)
end

# Caching
#########

function yoneda_cache(T::Type,S=nothing; clear=false, cache="cache")
S = isnothing(S) ? Presentation(T) : S
tname = nameof(T) |> string
cache_dict = Dict{Symbol,Tuple{T,Int}}(map(generators(S, :Ob)) do ob
name = nameof(ob)
cache_dir = mkpath(joinpath(cache, "$tname"))
path, ipath = joinpath.(cache_dir, ["$name.json", "_id_$name.json"])
name => if !clear && isfile(path)
(read_json_acset(T, path), parse(Int,open(io->read(io, String), ipath)))
else
@debug "Computing representable $name"
rep, i = representable(T, S, name; return_unit_id=true)
write_json_acset(rep, path)
write(ipath, string(i))
(rep, i)
end
end)
return yoneda(T; cache=cache_dict)
end

end # module
Loading