An issue with dispatching imported types

I have a problem with which I am struggling without success. I have two functions, ps1 and ps2, which are essentially the same:

function ps1(A::T) where {T <: PeriodicSymbolicMatrix}
   return T
end
function ps2(A::T) where {T <: PeriodicSymbolicMatrix}
   return T
end

The only difference is that ps1 is exported by the package PeriodicSystems, while ps2 is simply compiled within REPL. The methods associated to these functions are:

julia> methods(ps1)
# 1 method for generic function "ps1" from PeriodicSystems:
 [1] ps1(A::T) where T<:PeriodicMatrices.PeriodicSymbolicMatrix
     @ C:\Users\Andreas\Documents\software\Julia\PeriodicSystems.jl\src\ps.jl:127

julia> methods(ps2)
# 1 method for generic function "ps2" from Main:
 [1] ps2(A::T) where T<:PeriodicSymbolicMatrix
     @ REPL[13]:1

The type PeriodicSymbolicMatrix is defined in another package PeriodicMatrices and imported into PeriodicSystems. It satisfies

julia> PeriodicMatrices.PeriodicSymbolicMatrix == PeriodicSymbolicMatrix
true

Now let A be a symbolic periodic matrix (defined in PeriodicSystems, details are not important), for which we have:

julia> typeof(A) <: PeriodicSymbolicMatrix
true

The call ps1(A) fails, while the call ps2(A) performs as expected:.

julia> ps1(A)
ERROR: MethodError: no method matching ps1(::PeriodicSymbolicMatrix{:c, Num, Matrix{Num}})

Closest candidates are:
  ps1(::T) where T<:PeriodicMatrices.PeriodicSymbolicMatrix
   @ PeriodicSystems C:\Users\Andreas\Documents\software\Julia\PeriodicSystems.jl\src\ps.jl:127

Stacktrace:
 [1] top-level scope
   @ REPL[21]:1

julia> ps2(A)
PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}

I am missing the point, what actually happens here. Many thank in advance for an explanation.

Is it possible that you have included the file defining PeriodicMatrices twice?

I simply used

using PeriodicMatrices

No other file with this name was included.

But, I am not sure if I answered your question.

Note that PeriodicMatrices is now a registered package.

Does this returns true as well?

Yes.

julia> typeof(A) <: PeriodicMatrices.PeriodicSymbolicMatrix
true

I am not sure if it is of any help, but this results with @code_typed

julia> @code_typed ps1(A)
Any[]

julia> @code_typed ps2(A)
CodeInfo(
1 ─     return PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}
) => Type{PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}}

Both PeriodicSystems and PeriodicMatrices define their own PeriodicMatrix type, so probably that’s the problem.

julia> using PeriodicMatrices, PeriodicSystems

julia> a = PeriodicSymbolicMatrix(rand(10), 1.0; nperiod=3)
WARNING: both PeriodicSystems and PeriodicMatrices export "PeriodicSymbolicMatrix"; uses of it in module Main must be qualified

Probably one of the packages should be a dependency of the other.

It seems that you have moved PeriodicMatrices from an independent module inside PeriodicSystem to a separate package, and then you need to import the definitions from the new package and delete the, I think, deprecated definitions inside the PeriodicSystems package. That is, probably this file should not exist anymore, and be replaced by using the new PeriodicMatrices package.

2 Likes

Indeed, I extracted PeriodicMatrices from the PeriodicSystems, because of the general importance of periodic matrices in many domains (and not only in control problems). I am working on a new version of PeriodicSystems, without the PeriodicMatrices part. I removed all duplicities, (e.g., the definitions of types). I hope I did the splitting correctly, but I will check once again, since it is possible, that some remains still exist.

1 Like

Here is a simple reproducible example.

I reduced the PeriodicSystems module to the following minimal form

module PeriodicSystems

using Symbolics
using PeriodicMatrices

function ps1(A::T) where {T <: PeriodicSymbolicMatrix}
    return T
end
 
end

The following example fails:

using PeriodicSystems
using PeriodicMatrices 
using Symbolics

@variables t
A = PeriodicSymbolicMatrix([cos(t) 1; 1 1-sin(t)],2*pi);
ps1(A)

with the following error

julia> ps1(A)
ERROR: MethodError: no method matching ps1(::PeriodicSymbolicMatrix{:c, Num, Matrix{Num}})

Closest candidates are:
  ps1(::T) where T<:PeriodicMatrices.PeriodicSymbolicMatrix
   @ PeriodicSystems C:\Users\Andreas\Documents\software\Julia\PeriodicSystems.jl\src\PeriodicSystems.jl:6

Stacktrace:
 [1] top-level scope
   @ REPL[22]:1

The alternative code works:

julia> function ps2(A::T) where {T <: PeriodicSymbolicMatrix}                                                                                                                              
          return T                                                                                                                                                                         
       end
ps2 (generic function with 1 method)

julia> ps2(A)
PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}

I wonder what is wrong with my code … or with Julia!

For me your MWE does not work so well. If I use your definition of the package in REPL, I have to do

using .PeriodicSystems

(otherwise it asks me to install your package). But since it does not export ps1, I then have to call

PeriodicSystems.ps1(A)

which just works fine with the local small module you provided.

To me the warning above gives the main indicator, you define the type in two classes, so those are two completely different things (like 2 different person with the same name).

So the PeriodicSystems.PeriodicSymbolicMatrix is a completely different type as PeriodicMatrices.PeriodicSymbolicMatrix. Lets for simplicity and shortage call these P1 and P2, respectively, to disinghuish them though they have the same name. They might even have the same functionality if you copied them over, but that would then still be like two persons having the same name and looking alike.

If you now for example export ps1 but not the first of these two types (P1), but PeriodicMatrices exports its type (P2), then you define ps2 for matrices of type P2. since P2 is exported but P1 is not, a is of type P2.
Hence it will work with ps2 but not the (exported) ps1.

You can see that also in your error message above where both PeriodicMatrices.PeriodicSymbolicMatrix and PeriodicSymbolicMatrix are used, it seems the first is not exported from that package, the second is (from somewhere else).

1 Like

Indeed, you may have additional stuff defined in your section that is confusing things. The MWE works as expected:

julia> using Symbolics, PeriodicMatrices

julia> module PeriodicSystems
       
       using Symbolics
       using PeriodicMatrices
       
       function ps1(A::T) where {T <: PeriodicSymbolicMatrix}
           return T
       end
        
       end

julia> using .PeriodicSystems

julia> A = PeriodicSymbolicMatrix(rand(10), 1.0)
PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}(Num[0.8533861311322568; 0.9551845692903604; … ; 0.47612337713522335; 0.7758785937837308;;], 1.0, 1)

julia> PeriodicSystems.ps1(A)
PeriodicSymbolicMatrix{:c, Num, Matrix{Num}}


1 Like

To make it precise, you define

which is exported in the main file and you defined

which is now something completely different and a completely new type. and you also export it in the main project file. So if I now do

julia> using PeriodicSystems, PeriodicMatrices
julia> a = PeriodicSymbolicMatrix(rand(10), 1.0; nperiod=3)
ERROR: UndefVarError: `PeriodicSymbolicMatrix` not defined in `Main`
Hint: It looks like two or more modules export different bindings with this name, resulting in ambiguity. Try explicitly importing it from a particular module, or qualifying the name with the module it should come from.
Hint: a global variable of this name also exists in PeriodicSystems.
Hint: a global variable of this name also exists in PeriodicMatrices.
Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

So the thing I am actually surprised about is that you are able to define ps2 in REPL, because in the just started REPL I can’t.

julia> function ps2(A::T) where {T <: PeriodicSymbolicMatrix}
          return T
       end
ERROR: UndefVarError: `PeriodicSymbolicMatrix` not defined in `Main`
Hint: It looks like two or more modules export different bindings with this name, resulting in ambiguity. Try explicitly importing it from a particular module, or qualifying the name with the module it should come from.
Hint: a global variable of this name also exists in PeriodicSystems.
Hint: a global variable of this name also exists in PeriodicMatrices.
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1
1 Like

This definition is not made in the new development version of PeriodicSystems, which is only locally available. The MWE example was intended to illustrate the failure of a function ps1, which according to my understanding of dispatch rules, should perform exactly in the same manner as ps2, entered via REPL. Sorry, not being clear in this respect.

The whole package PeriodicSystems has been reduced for the sake of testing to the few lines, which I reproduce again

module PeriodicSystems

using Symbolics
using PeriodicMatrices

function ps1(A::T) where {T <: PeriodicSymbolicMatrix}
    return typeof(A)
end

export ps1

end

(this time ps1 is exported)

The MWE fails exactly in the same way as presented in my example.

Note that

julia> PeriodicMatrices.PeriodicSymbolicMatrix == PeriodicSymbolicMatrix
true

so the definition of the PeriodicSymbolicMatrix in PeriodicMatrices has been (apparently) correctly imported.

However

julia> PeriodicSystems.PeriodicSymbolicMatrix == PeriodicSymbolicMatrix
false

although

julia> PeriodicSystems.PeriodicSymbolicMatrix
PeriodicMatrices.PeriodicSymbolicMatrix

You need to provide a full runnable example, because the issues you report are not reproducible:

(jl_6RRETd) pkg> st
Status `/tmp/jl_6RRETd/Project.toml`
  [dd9cd634] PeriodicMatrices v0.1.1
βŒƒ [0c5d862f] Symbolics v5.36.0
Info Packages marked with βŒƒ have new versions available and may be upgradable.

julia> using PeriodicMatrices

julia> module PeriodicSystems
       
       using Symbolics
       using PeriodicMatrices
       
       function ps1(A::T) where {T <: PeriodicSymbolicMatrix}
           return T
       end
        
       end

julia> using .PeriodicSystems

julia> PeriodicMatrices.PeriodicSymbolicMatrix == PeriodicSymbolicMatrix
true

julia> PeriodicSystems.PeriodicSymbolicMatrix == PeriodicSymbolicMatrix
true

julia> PeriodicSystems.PeriodicSymbolicMatrix
PeriodicSymbolicMatrix

julia> ps1(PeriodicSymbolicMatrix(rand(3), 1.0))
PeriodicSymbolicMatrix{:c, Symbolics.Num, Matrix{Symbolics.Num}}

You probably have other things loaded in your section that are causing the issues.

2 Likes

Hehe, well, that is hard to anticipate; and sure, I can not easily compare to your development version. However, it seems even with the export, I can not reproduce your problem then, because your (minimalistic, MWE) PeriodicSystems avoids exactly the double definition. I get exactly the same result as Leandro.

Note that we both do not have PeriodicSystems installed but just use your small example. But that also means we have to load that with using .PeriodicSystems – you miss the . so you might load your large dev-version or something older?

1 Like

I can reproduce fully your way to compute and the results agree.

The issues manifest when I am using the development version (actually with the same module definition). Then, the execution fails.

Here is the list of packages

(@v1.10) pkg> st
Status `C:\Users\Andreas\.julia\environments\v1.10\Project.toml`
  [28f2ccd6] ApproxFun v0.13.27
  [4c88cf16] Aqua v0.8.9
  [0e736298] Bessels v0.2.8
  [861a8166] Combinatorics v1.0.2
  [a81e2ce2] DescriptorSystems v1.4.4 `C:\Users\Andreas\Documents\software\Julia\DescriptorSystems.jl`
  [e30172f5] Documenter v1.7.0
  [35a29f4d] DocumenterTools v0.1.20
  [7a1cc6ca] FFTW v1.8.0
  [9aa1b823] FastClosures v0.3.2
  [29a986be] FastLapackInterface v2.0.4
  [587475ba] Flux v0.14.23
  [f6369f11] ForwardDiff v0.10.36
  [58bc7355] IRKGaussLegendre v0.2.8
  [a98d9a8b] Interpolations v0.15.1
  [033835bb] JLD2 v0.5.7
  [d3d80556] LineSearches v7.3.0
  [7a12625a] LinearMaps v3.11.3
  [99c1a7ee] MatrixEquations v2.4.2
  [48965c70] MatrixPencils v1.8.0
  [eff96d63] Measurements v2.11.0
  [429524aa] Optim v1.9.4
  [1dea7af3] OrdinaryDiffEq v6.89.0
  [7a052949] PeriodicMatrices v0.1.1 `C:\Users\Andreas\Documents\software\Julia\PeriodicMatrices.jl`
  [e5aedecb] PeriodicSchurDecompositions v0.1.5
  [5decd0d0] PeriodicSystems v0.8.1 `C:\Users\Andreas\Documents\software\Julia\PeriodicSystems.jl`
  [91a5bcdd] Plots v1.40.8
  [f27b6e38] Polynomials v4.0.11
  [27ebfcd6] Primes v0.5.6
  [1fd47b50] QuadGK v2.11.1
  [295af30f] Revise v3.6.2
βŒƒ [0c5d862f] Symbolics v5.36.0
  [545525a2] SLICOT_jll v5.9.0+0
Info Packages marked with βŒƒ have new versions available and may be upgradable.

Is something unusual in this list?

The first I would try would be start Julia and activate an empty temporary environment and load only the two packages required to reproduce your problem and see if it is still there.

So just to be clear: When you do using . PeriodicSystems all is fine and you get the same as we do, but when you do using PeriodicSystems then it does not?

Then you oversimplified your MWE and I think you still have the PeriodicSymbolicMatrix defined in both packages. But that is of course hard to tell because the development version that is loaded from a folder on your hard drive is nothing I can take a look at.

I am afraid I need your guidance for that. I am not at all familiar with environments. Thanks in advance for your time.

Yes, exactly.