From f7ea390356a3b773b7e962ea56ceccfdf3ffa8dd Mon Sep 17 00:00:00 2001 From: Sam Cohen <147665952+samuelcohen1@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:53:20 -0400 Subject: [PATCH 1/9] Integer-typed UWDs (#921) --- src/programs/RelationalPrograms.jl | 16 ++++--- test/programs/RelationalPrograms.jl | 66 ++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/programs/RelationalPrograms.jl b/src/programs/RelationalPrograms.jl index a462b0acd..943ddc885 100644 --- a/src/programs/RelationalPrograms.jl +++ b/src/programs/RelationalPrograms.jl @@ -145,10 +145,10 @@ function parse_relation_diagram(head::Expr, body::Expr) Expr(:where, expr, context) => (expr, parse_relation_context(context)...) _ => (head, nothing, nothing) end - var_types = if isnothing(all_types) # Untyped case. + var_types = if isnothing(all_types) # Untyped case vars -> length(vars) - else # Typed case. - var_type_map = Dict{Symbol,Symbol}(zip(all_vars, all_types)) + else + var_type_map = Dict(zip(all_vars, all_types)) vars -> getindex.(Ref(var_type_map), vars) end @@ -194,19 +194,24 @@ function parse_relation_context(context) vars = map(terms) do term @match term begin Expr(:(::), var::Symbol, type::Symbol) => (var => type) + Expr(:(::), var::Symbol, type::Expr) => (var => type) + Expr(:(::), var::Symbol, type::Integer) => (var => type) var::Symbol => var - _ => error("Invalid syntax in term $expr of context") + _ => error("Invalid syntax in term $term of context") end end + if vars isa AbstractVector{Symbol} (vars, nothing) - elseif vars isa AbstractVector{Pair{Symbol,Symbol}} + elseif eltype(vars) <: Pair (first.(vars), last.(vars)) else error("Context $context mixes typed and untyped variables") end + end + function parse_relation_call(call) @match call begin Expr(:call, name::Symbol, Expr(:parameters, args)) => @@ -242,6 +247,7 @@ function parse_relation_inferred_args(args) Expr(:kw, name::Symbol, var::Symbol) => (name => var) Expr(:(=), name::Symbol, var::Symbol) => (name => var) var::Symbol => var + Expr(:(::), _, _) => error("All variable types must be included in the where clause and not in the argument list") _ => error("Expected name as positional or keyword argument") end end diff --git a/test/programs/RelationalPrograms.jl b/test/programs/RelationalPrograms.jl index 59662c92b..be5b23140 100644 --- a/test/programs/RelationalPrograms.jl +++ b/test/programs/RelationalPrograms.jl @@ -1,4 +1,5 @@ module TestRelationalPrograms + using Test using Catlab.CategoricalAlgebra.CSets @@ -49,7 +50,8 @@ d = RelationDiagram(0) add_box!(d, 0, name=:A) @test parsed == d -# Typed + +# Typed by Symbols #------ parsed = @relation (x,y,z) where (x::X, y::Y, z::Z, w::W) begin @@ -57,6 +59,7 @@ parsed = @relation (x,y,z) where (x::X, y::Y, z::Z, w::W) begin S(y,w) T(z,w) end + d = RelationDiagram([:X,:Y,:Z]) add_box!(d, [:X,:W], name=:R) add_box!(d, [:Y,:W], name=:S) @@ -66,6 +69,67 @@ set_junction!(d, [1,4,2,4,3,4]) set_junction!(d, [1,2,3], outer=true) @test parsed == d + +# Typed by Integers +#------ + +parsed = @relation (x,y,z) where (x::1, y::2, z::3, w::4) begin + R(x,w) + S(y,w) + T(z,w) +end + +d = RelationDiagram([:1,:2,:3]) +add_box!(d, [:1,:4], name=:R) +add_box!(d, [:2,:4], name=:S) +add_box!(d, [:3,:4], name=:T) +add_junctions!(d, [:1,:2,:3,:4], variable=[:x,:y,:z,:w]) +set_junction!(d, [1,4,2,4,3,4]) +set_junction!(d, [1,2,3], outer=true) +@test parsed == d + + + +# Typed by Expressions +#------ + +parsed = @relation (x,y,z) where (x::n(1), y::n(2), z::n(3), w::n(4)) begin + R(x,w) + S(y,w) + T(z,w) +end + +d = RelationDiagram([:(n(1)), :(n(2)), :(n(3))]) +add_box!(d, [:(n(1)),:(n(4))], name=:R) +add_box!(d, [:(n(2)),:(n(4))], name=:S) +add_box!(d, [:(n(3)),:(n(4))], name=:T) +add_junctions!(d, [:(n(1)),:(n(2)),:(n(3)),:(n(4))], variable=[:x,:y,:z,:w]) +set_junction!(d, [1,4,2,4,3,4]) +set_junction!(d, [1,2,3], outer=true) +@test parsed == d + +# Mixed types +#------ + +parsed = @relation (x,y,z) where (x::n(1), y::2, z::C, w::nothing) begin + R(x,w) + S(y,w) + T(z,w) +end + +d = RelationDiagram([:(n(1)), :2, :C]) +add_box!(d, [:(n(1)),:nothing], name=:R) +add_box!(d, [:2,:nothing], name=:S) +add_box!(d, [:C,:nothing], name=:T) +add_junctions!(d, [:(n(1)),:2,:C,:nothing], variable=[:x,:y,:z,:w]) +set_junction!(d, [1,4,2,4,3,4]) +set_junction!(d, [1,2,3], outer=true) +@test parsed == d + + + + + # Special case: closed diagram. sird_uwd = @relation () where (S::Pop, I::Pop, R::Pop, D::Pop) begin infect(S,I,I,I) # inf From b71a5b873920bd1621a9d99193e9927cb51d2af6 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Sun, 1 Sep 2024 15:37:07 -0700 Subject: [PATCH 2/9] BUILD: Release Catlab v0.16.17. --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3a9fcdc7d..01dd0b2d7 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "Catlab" uuid = "134e5e36-593f-5add-ad60-77f754baafbe" license = "MIT" authors = ["Evan Patterson "] -version = "0.16.16" +version = "0.16.17" [deps] ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" From ce50fb6a86f5216893b904831dba65a35b735104 Mon Sep 17 00:00:00 2001 From: slwu89 <10673535+slwu89@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:22:12 -0700 Subject: [PATCH 3/9] coerce_component errors with scalar input --- src/categorical_algebra/CSets.jl | 6 +++++- test/categorical_algebra/CSets.jl | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/categorical_algebra/CSets.jl b/src/categorical_algebra/CSets.jl index d26894a90..1be7e29b6 100644 --- a/src/categorical_algebra/CSets.jl +++ b/src/categorical_algebra/CSets.jl @@ -462,7 +462,11 @@ function coerce_component(ob::Symbol, f::FinFunction{Int,Int}, return f end -coerce_component(::Symbol, f, dom_size::Int, codom_size::Int; kw...) = +coerce_component(ob::Symbol, f::T, dom_size::Int, codom_size::Int; kw...) where {T<:Integer} = + error("Scalar component for $ob not allowed; " * + "this is probably from a scalar component in an ACSetTransformation, please use a vector") + +coerce_component(::Symbol, f::T, dom_size::Int, codom_size::Int; kw...) where {T<:AbstractVector{<:Integer}}= FinFunction(f, dom_size, codom_size; kw...) function coerce_attrvar_component( diff --git a/test/categorical_algebra/CSets.jl b/test/categorical_algebra/CSets.jl index 19db87963..91938e909 100644 --- a/test/categorical_algebra/CSets.jl +++ b/test/categorical_algebra/CSets.jl @@ -64,6 +64,7 @@ f = ACSetTransformation(X,X; V=[1,2], E=[1,2,3]) @test components(f) == (V=FinFunction([1,2]), E=FinFunction([1,2,3]), Weight=VarFunction{Float64}([], FinSet(0))) +@test_throws ErrorException ACSetTransformation(Y,X; V=[1,2], E=1) g = ACSetTransformation(Y,X; V=[1,2], E=[1]) @test is_natural(g) @test compose(g,f) |> force == g @@ -300,6 +301,7 @@ diagram = FreeDiagram([g, ob(terminal(Graph)), Graph(1)], [(α,3,1), (β,3,2)]) # Constructors and accessors. Test type conversion as well Int -> Float64 g = path_graph(WeightedGraph{Float64}, 2, E=(weight=2,)) h = path_graph(WeightedGraph{Float64}, 4, E=(weight=[1,2,3],)) +@test_throws ErrorException ACSetTransformation((V=[2,3], E=2), g, h) α = ACSetTransformation((V=[2,3], E=[2]), g, h) @test length(components(α)) == 3 From 1948b71daca2e66d0fdd9838a681c2996c84f090 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Thu, 10 Oct 2024 22:01:17 -0700 Subject: [PATCH 4/9] BUG: Fix dispatch for limits of loose acset transformations. --- src/categorical_algebra/CSets.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/categorical_algebra/CSets.jl b/src/categorical_algebra/CSets.jl index 1be7e29b6..31b901597 100644 --- a/src/categorical_algebra/CSets.jl +++ b/src/categorical_algebra/CSets.jl @@ -835,12 +835,12 @@ the combinatorial part of the limit legs. The type components of the j'th leg of the limit is just the j'th cartesian projection. """ function limit(::Type{Tuple{ACS,Hom}}, diagram; product_attrs::Bool=false) where - {S, Ts, ACS <: StructACSet{S,Ts}, Hom <: LooseACSetTransformation} + {S, ACS <: StructACSet{S}, Hom <: LooseACSetTransformation} limits = map(limit, unpack_diagram(diagram, S=S, all=!product_attrs)) Xs = cone_objects(diagram) attr_lims = (product_attrs ? - map(limit, unpack_diagram(DiscreteDiagram(Xs, Hom), S=S,Ts=Ts,all=true)) : limits ) + map(limit, unpack_diagram(DiscreteDiagram(Xs, Hom), S=S, all=true)) : limits ) LimitACS = if isempty(attrtypes(S)); ACS else From bb03a3b44cfe13359aabf2a03ce4ad7f58378018 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Thu, 10 Oct 2024 22:26:35 -0700 Subject: [PATCH 5/9] TST: Seed 100 isn't so random in Julia v1.11?! --- test/categorical_algebra/HomSearch.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/categorical_algebra/HomSearch.jl b/test/categorical_algebra/HomSearch.jl index f3df1b507..d36c15edd 100644 --- a/test/categorical_algebra/HomSearch.jl +++ b/test/categorical_algebra/HomSearch.jl @@ -7,7 +7,7 @@ using Random: seed! # Setup ####### -seed!(100) +seed!(10) @present SchSetAttr(FreeSchema) begin X::Ob From 41e583fe46a684e889aa7ade5925ad73458d7fd6 Mon Sep 17 00:00:00 2001 From: Kevin Carlson Date: Thu, 10 Oct 2024 23:47:18 -0700 Subject: [PATCH 6/9] Fix empty collection typing bug (#941) --- src/categorical_algebra/HomSearch.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/categorical_algebra/HomSearch.jl b/src/categorical_algebra/HomSearch.jl index 35737c432..7e8e2dbb8 100644 --- a/src/categorical_algebra/HomSearch.jl +++ b/src/categorical_algebra/HomSearch.jl @@ -264,7 +264,7 @@ function backtracking_search(f, X::ACSet, Y::ACSet; for a_type in attrtypes(S) a_type ∈ (monic ∪ iso ∪ no_bind) && continue # attrvars ↦ attrvars attrs′ = attrs(S, just_names=true, to=a_type) - avars = union(collect.([filter(x->x isa AttrVar, X[f]) for f in attrs′])...) + avars = union(AttrVar[],collect.([filter(x->x isa AttrVar, X[f]) for f in attrs′])...) assigned = partial_assignments(get(initial, a_type, []); is_attr=true) assigned′ = first.(collect(assigned)) unassigned = setdiff(parts(X, a_type), [v.val for v in avars] ∪ assigned′) From 357a3bc56690c47356dcd4bb199eb06617019161 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Thu, 10 Oct 2024 23:48:26 -0700 Subject: [PATCH 7/9] BUILD: Release Catlab v0.16.18. --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 01dd0b2d7..4c2e64639 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "Catlab" uuid = "134e5e36-593f-5add-ad60-77f754baafbe" license = "MIT" authors = ["Evan Patterson "] -version = "0.16.17" +version = "0.16.18" [deps] ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" From b40e631741cc3ba5890ac319c12d855206559aea Mon Sep 17 00:00:00 2001 From: AlgebraicJulia Bot <129184742+algebraicjuliabot@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:00:33 -0400 Subject: [PATCH 8/9] CompatHelper: bump compat for Colors to 0.13, (keep existing compat) (#948) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 4c2e64639..d0e4ec6e3 100644 --- a/Project.toml +++ b/Project.toml @@ -48,7 +48,7 @@ CatlabTikzPicturesExt = "TikzPictures" [compat] ACSets = "0.2.20" AlgebraicInterfaces = "0.1.3" -Colors = "0.12" +Colors = "0.12, 0.13" CompTime = "0.1" Compose = "0.7, 0.8, 0.9" Convex = "0.16" From 764b4c0cd950b7443a093af52fee4348e59ae96a Mon Sep 17 00:00:00 2001 From: Matt Cuffaro Date: Wed, 23 Oct 2024 17:21:56 -0400 Subject: [PATCH 9/9] Floating viewer for Graphviz output (#947) * adding viewer * implemented feedback --- src/graphics/Graphviz.jl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/graphics/Graphviz.jl b/src/graphics/Graphviz.jl index b812a5054..7a08e4c4b 100644 --- a/src/graphics/Graphviz.jl +++ b/src/graphics/Graphviz.jl @@ -7,7 +7,7 @@ References: """ module Graphviz export Expression, Statement, Attributes, Graph, Digraph, Subgraph, - Node, NodeID, Edge, Label, pprint, run_graphviz + Node, NodeID, Edge, Label, pprint, run_graphviz, view_graphviz using DataStructures: OrderedDict using StructEquality @@ -172,6 +172,20 @@ function Base.show(io::IO, ::MIME"image/svg+xml", graph::Graph) run_graphviz(io, graph, format="svg") end +function view_graphviz(g::Graph; path::String="") + filepath = isempty(path) ? "$(tempname()).png" : path + open(filepath, "w") do io + run_graphviz(io, g, format="png") + end + if Sys.islinux() + run(`xdg-open $filepath`, wait=false) + elseif Sys.isapple() + run(`open $filepath`, wait=false) + elseif Sys.iswindows() + run(`start $filepath`, wait=false) + end +end + # Pretty-print ##############