AlgebraicJulia / Catlab.jl

A framework for applied category theory in the Julia language
https://www.algebraicjulia.org
MIT License
610 stars 58 forks source link

`query` errors when specifying parameters #939

Open slwu89 opened 1 month ago

slwu89 commented 1 month ago

query errors when specifying the parameter (ID of a certain object) when using a union type for an AttrType in the following schema. On Catlab v0.16.17.

using Catlab

@present MySch <: SchGraph begin
    (P,PV,S)::Ob
    Label::AttrType
    vlabel::Attr(V,Label)
    plabel::Attr(P,Label)
    Number::AttrType
    pv_number::Attr(PV,Number)
    s_number::Attr(S,Number)
    pv_v::Hom(PV,V)
    pv_p::Hom(PV,P)
    s_e::Hom(S,E)
    s_p::Hom(S,P)
end

@acset_type MyDataType(MySch, index=[:src,:tgt,:pv_p,:pv_v,:s_p,:s_e])

mydata = @acset MyDataType{String,Union{Float64,Int}} begin
    V=5
    vlabel="v" .* string.(1:5)
    E=9
    src=[1,1,1,2,2,2,3,3,4]
    tgt=[2,3,4,1,3,5,1,2,1]
    PV=10
    pv_p=[1,2,1,2,1,2,1,2,1,2]
    pv_v=[1,1,2,2,3,3,4,4,5,5]
    pv_number=rand([1,2,3],10)
    P=2
    plabel="p" .* string.(1:2)
    S=16
    s_p=[1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2]
    s_e=[1,2,3,4,5,6,7,8,9,1,3,4,6,7,8,9]
    s_number=rand(Union{Float64,Int}[5,6.0,7],16)
end

query_uwd = @relation (v=vlab, v_id=v_id, p=plab, p_id=p_id, s_number=s_number) begin
    PV(_id=pv_id, pv_p=p_id, pv_v=v_id)
    P(_id=p_id, plabel=plab)
    V(_id=v_id, vlabel=vlab)
    E(_id=e_id, tgt=v_id)
    S(_id=s_id, s_e=e_id, s_p=p_id, s_number=s_number)
end

# queries when `Number` is a `Union{Float64,Int}`
query(mydata, query_uwd) # works
query(mydata, query_uwd, (v_id=1, )) # error
query(mydata, query_uwd, (s_number=5, )) # works
epatters commented 1 month ago

Alas, I guess this was not fixed in #923?

slwu89 commented 1 month ago

I'm not sure @epatters, in this case, the error occurs when specifying the parameter of a part ID, rather than when using the parameters to specify attributes (which is weird). But in any case, I'll check it out in detail when I have time, making a note of the behavior here.

slwu89 commented 1 month ago

Hi @epatters I found out the root cause of the error. The error occurs in this line https://github.com/AlgebraicJulia/Catlab.jl/blob/982ea6ed70d83ddc472abdac69793ff240767e8b/src/wiring_diagrams/Algebras.jl#L195 when force is called to compose functions together. Checking it in detail show the following:

Breaking for error:
ERROR: MethodError: no method matching Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector(::Vector{Real}, ::TypeSet{Union{Float64, Int64}})

Closest candidates are:
  Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector(::V, ::Codom) where {T, V<:AbstractVector{T}, Codom<:SetOb{T}}
   @ Catlab ~/Desktop/git/Catlab.jl/src/categorical_algebra/FinSets.jl:267
  Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector(::AbstractVector{T}) where T
   @ Catlab ~/Desktop/git/Catlab.jl/src/categorical_algebra/FinSets.jl:276
  Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector(::AbstractVector, ::FinSet{Int64}, ::Any)
   @ Catlab ~/Desktop/git/Catlab.jl/src/categorical_algebra/FinSets.jl:279

Stacktrace:
 [1] force(f::Catlab.CategoricalAlgebra.Sets.CompositeFunction{Catlab.CategoricalAlgebra.FinSets.FinSetInt, TypeSet{Union{Float64, Int64}}, Catlab.CategoricalAlgebra.Sets.CompositeFunction{Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.Sets.CompositeFunction{Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.Sets.CompositeFunction{Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.Sets.CompositeFunction{Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.Sets.SetFunctionCallable{Int64, Int64, Catlab.CategoricalAlgebra.FinSets.FinSetInt, Catlab.CategoricalAlgebra.FinSets.FinSetInt}, Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector{Int64, Vector{Int64}, Catlab.CategoricalAlgebra.FinSets.FinSetInt}}, Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector{Int64, Vector{Int64}, Catlab.CategoricalAlgebra.FinSets.FinSetInt}}, Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector{Int64, Vector{Int64}, Catlab.CategoricalAlgebra.FinSets.FinSetInt}}, Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector{Int64, Vector{Int64}, Catlab.CategoricalAlgebra.FinSets.FinSetInt}}, Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector{Union{Float64, Int64}, Vector{Union{Float64, Int64}}, TypeSet{Union{Float64, Int64}}}})
   @ Catlab.CategoricalAlgebra.FinSets ~/Desktop/git/Catlab.jl/src/categorical_algebra/FinSets.jl:295

In force(f) at /Users/wusea/Desktop/git/Catlab.jl/src/categorical_algebra/FinSets.jl:295
>295  force(f::FinDomFunction{Int}) = FinDomFunctionVector(map(f, dom(f)), codom(f))

About to run: <(Catlab.CategoricalAlgebra.FinSets.FinDomFunctionVector)(Real[7, 7, 5, 6.0, 6.0, 6.0], TypeSet(Union{...>
1|julia> f
compose(compose(compose(compose(compose(FinFunction(#58, FinSet(6), FinSet(6)), FinFunction([4, 7, 9, 12, 14, 16], 6, 16)), FinFunction([2, 8, 14, 16, 23, 30, 31, 37, 41, 47, 54, 56, 65, 66, 72, 76], 16, 80)), FinFunction([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16], 80, 16)), FinFunction([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 16, 16)), FinDomFunction(Union{Float64, Int64}[7, 6.0, 6.0, 7, 7, 5, 7, 6.0, 5, 5, 7, 6.0, 5, 6.0, 7, 6.0], FinSet(16), TypeSet(Union{Float64, Int64})))

So it seems that when the final composition is called, for some reason the type information of the vector that defines the function being of Vector{Union{Float64,Int64}} is lost and it is simply Vector{Real}. This is somewhat mysterious as when I check the local variable f in the debugger, it seems to have the type info correct there. Additionally when doing this just in a repl, there is no problem, e.g. the following code works:

force(compose(
    FinFunction([1,2,2], 3, 4),
    FinDomFunction(Union{Float64,Int64}[500, 2.342, 90, 0.342], FinSet(4), TypeSet(Union{Float64,Int64}))
))

One "solution" that works is changing the definition of FinDomFunctionVector, see https://github.com/AlgebraicJulia/Catlab.jl/blob/982ea6ed70d83ddc472abdac69793ff240767e8b/src/categorical_algebra/FinSets.jl#L260-L269 so that it is FinDomFunctionVector{T,V<:AbstractVector{<:T}, Codom<:SetOb{T}}. But I am not sure if this is a good solution as it reaches quite far into the depths of the software design.