diff --git a/Project.toml b/Project.toml index a2afa92..0a9e304 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "AlgebraicRewriting" uuid = "725a01d3-f174-5bbd-84e1-b9417bad95d9" license = "MIT" authors = ["Kris Brown "] -version = "0.4.1" +version = "0.4.2" [deps] ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" diff --git a/src/incremental/Algorithms.jl b/src/incremental/Algorithms.jl index a747889..664fc94 100644 --- a/src/incremental/Algorithms.jl +++ b/src/incremental/Algorithms.jl @@ -3,6 +3,7 @@ module Algorithms using Catlab using ...CategoricalAlgebra.CSets: invert_iso, var_reference using ...Rewrite.Migration: pres_hash +using ACSets.DenseACSets: attrtype_type """ Break an ACSet into connected components, represented as a coproduct and an @@ -175,7 +176,7 @@ function nac_overlap(nac, update::ACSetTransformation) end """ -Given f: L->X and m: X' ↣ X, find the unique map L -> X' making the triangle +Given f: X' ↣ X, m: L->X , find the unique map L -> X' making the triangle commute, if it exists. TODO rewrite with @comptime @@ -185,11 +186,12 @@ function pull_back(f::ACSetTransformation, m::ACSetTransformation L, X′ = dom.([m, f]) comps, S = Dict(), acset_schema(L) for o in ob(S) - vec = [] + vec = Int[] for i in parts(L, o) pre = preimage(f[o], m[o](i)) + # Given that `m` is monic, preimage is empty or singleton length(pre) == 1 || return nothing - all(attrs(S; from=o)) do (atr, _, _) + all(attrs(S; from=o, just_names=true)) do atr L[i, atr] isa AttrVar || L[i,atr] == X′[only(pre), atr] end || return nothing push!(vec, only(pre)) @@ -199,6 +201,7 @@ function pull_back(f::ACSetTransformation, m::ACSetTransformation # Check that attribute variables in L are mapped consistently # i.e. L->X' doesn't send the variable to two different values. for o in attrtypes(S) + T = attrtype_type(L, o) comps[o] = map(AttrVar.(parts(L, o))) do i vals = Set() for (f, c, _) in attrs(S; to=o) @@ -207,9 +210,9 @@ function pull_back(f::ACSetTransformation, m::ACSetTransformation end end return only(vals) - end + end |> Vector{T} end - ACSetTransformation(dom(m), dom(f); comps...) + ACSetTransformation(L, X′; comps...) end """Get the pairs for each component of the image and its component""" diff --git a/test/incremental/Algorithms.jl b/test/incremental/Algorithms.jl index f71b037..5b16bb5 100644 --- a/test/incremental/Algorithms.jl +++ b/test/incremental/Algorithms.jl @@ -4,7 +4,7 @@ using Test using Catlab using AlgebraicRewriting.Incremental.Algorithms: connected_acset_components, all_subobjects, subobject_cache, - to_subobj, deattr + to_subobj, deattr, pull_back # test connected_acset_components #-------------------------------- @@ -37,5 +37,23 @@ G = SymmetricGraph(3) ⊕ cycle_graph(SymmetricGraph, 3) #-------- @test deattr(SchWeightedGraph) == SchGraph +# Pull_back +#---------- +@present SchAttr(FreeSchema) begin + X::Ob; D::AttrType; f::Attr(X,D); Y::Ob +end +@acset_type Attr(SchAttr) +D1 = @acset Attr{Symbol} begin X=1; f=[AttrVar(1)]; D=1 end +DXY = @acset Attr{Symbol} begin X=2; f=[:X,:Y] end +DX = @acset Attr{Symbol} begin X=1; f=[:X] end +toX,toY = homomorphisms(D1,DXY) +subX = homomorphism(DX,DXY) +toSubX = homomorphism(D1, DX) + +pb = pull_back(subX, toX) +@test dom(pb) == dom(toX) +@test codom(pb) == dom(subX) +@test pb == toSubX +@test isnothing(pull_back(subX, toY)) end # module diff --git a/test/runtests.jl b/test/runtests.jl index f2ad5ad..88aab6b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,7 +13,7 @@ using DataMigrations ####### @testset "Full Demo" begin - # include("../docs/literate/full_demo.jl") + include("../docs/literate/full_demo.jl") end @testset "Lotka Volterra" begin @@ -21,7 +21,7 @@ end end @testset "Game of Life" begin - include("../docs/literate/game_of_life.jl") + # include("../docs/literate/game_of_life.jl") end # Background diff --git a/test/schedules/Eval.jl b/test/schedules/Eval.jl index 0530172..90dc64e 100644 --- a/test/schedules/Eval.jl +++ b/test/schedules/Eval.jl @@ -47,14 +47,14 @@ de = loop_rule(RuleApp(:del_edge, Rule(g2ar, id(g2)))) coin = uniform(2, z) sched = coin ⋅ (tryrule(av) ⊗ id([z])) ⋅ merge_wires(z) ⋅ de -view_sched(sched, name="Simple schedule", names=N) +# view_sched(sched, name="Simple schedule", names=N) G = path_graph(Grph, 2) @test interpret!(sched, G) isa ACSetTransformation @test ne(G) == 0 res = interpret(sched, path_graph(Grph, 2)) -view_traj(sched, res, view_graph; agent=true, names=N) +# view_traj(sched, res, view_graph; agent=true, names=N) # Query workflow (add loop to each vertex) ########################################## @@ -83,9 +83,9 @@ sched = mk_sched((o=Dot,), (i=:Z,), N, Dict(:rule=>al, :query=>q), typecheck(sched) -view_sched(sched; names=N) +# view_sched(sched; names=N) res = interpret(sched, Grph(3)); -view_traj(sched, res, view_graph; agent=true, names=N) +# view_traj(sched, res, view_graph; agent=true, names=N) # Dependent query workflow @@ -111,18 +111,18 @@ quote return [trace1, trace2], out end); -view_sched(sched; names=N) +# view_sched(sched; names=N) G = @acset Grph begin V=5; E=4; src=[1,2,2,5];tgt=[2,3,4,2] end arr_start = homomorphism(ar, G; initial=(V=[1,2],)) res = interpret(sched, arr_start); -view_traj(sched, res, view_graph; agent=true, names=N) +# view_traj(sched, res, view_graph; agent=true, names=N) @test interpret!(sched, arr_start) isa ACSetTransformation # For-loop: add 3 loops ####################### sched = for_schedule(maybe_add_loop ⋅ merge_wires(g1), 3); -view_sched(sched) +# view_sched(sched) interpret!(sched, id(g1)) |> codom # TODO add an attributed example