Extended function not being seen (Is explicity imported)

I’ve been looking at extending functions to work with a self-defined data type. Most of them I got working no problem but I am struggling to get one of them working.

I define a type

mutable struct ImagTimeEvolution{N,Tt,HT<:AbstractBlock{N}} <: PrimitiveBlock{N}
 ....
end

and then the extension of the function apply_back!

function YaoBase.apply_back!(st, block::ImagTimeEvolution{N}, collector) where {N}
 ....
end

When I run it by itself it works as expected but when I run

_, grad = expect'(heisenberg(10), rand_state(10)=>imag_time_evolve(heisenberg(10), 10))

Which calls the function I’m trying to extend I receive the error

no method matching apply_back(::Tuple{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}}}, ::ImagTimeEvolution{10,Int64,Add{10}}, ::Array{Any,1})

I’ve had a google and it seems this problem is generally resolved by explicitly importing the function being extended but I believe I’m doing that as I am using YaoBase.apply_back! . One thought I had is the error message doesn’t include the ! mark but where the error is being called is calling the function with ! so don’t think that’s the issue.

Any help would be greatly appreciated! (Also this is my first time posting here so if the formating is way off or I’m missing some necessary info I apologise, and please let me know. I will then try to correct it)

It’s a little hard to parse this–can you post the stack trace of the error so that we can see what you mean?

Of course

ERROR: LoadError: MethodError: no method matching apply_back(::Tuple{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}}}, ::ImagTimeEvolution{10,Int64,Add{10}}, ::Array{Any,1})
Closest candidates are:
  apply_back(::Tuple{var"#s317",var"#s316"} where var"#s316"<:ArrayReg where var"#s317"<:ArrayReg, ::AbstractBlock; kwargs...) at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\apply_back.jl:149
Stacktrace:
 [1] apply_back!(::Tuple{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}}}, ::ImagTimeEvolution{10,Int64,Add{10}}, ::Array{Any,1}) at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\apply_back.jl:25
 [2] apply_back(::Tuple{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}}}, ::ImagTimeEvolution{10,Int64,Add{10}}; 
kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\apply_back.jl:151
 [3] apply_back(::Tuple{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}}}, ::ImagTimeEvolution{10,Int64,Add{10}}) 
at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\apply_back.jl:150
 [4] expect_g(::Add{10}, ::Pair{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ImagTimeEvolution{10,Int64,Add{10}}}) at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\specializes.jl:15
 [5] (::Adjoint{Any,typeof(expect)})(::Add{10}, ::Pair{ArrayReg{1,Complex{Float64},Array{Complex{Float64},2}},ImagTimeEvolution{10,Int64,Add{10}}}) at C:\Users\ap877\.julia\packages\YaoBlocks\a3uN9\src\autodiff\specializes.jl:8
 [6] top-level scope at C:\Users\ap877\OneDrive - University of Exeter\Julia\GSEProject\ImagTEBlock.jl:81
 [7] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1088
in expression starting at C:\Users\ap877\OneDrive - University of Exeter\Julia\GSEProject\ImagTEBlock.jl:81

Ah, looks like you ran into this: https://github.com/QuantumBFS/YaoBlocks.jl/blob/61ef37aad1b09cbb07b188cc1d9678a22ef21c9d/src/autodiff/apply_back.jl#L17-L27

That code looks wrong to me–there clearly is an applicable method (you wrote it!) but that code chooses to throw a MethodError anyway, which makes it look like your method doesn’t exist.

I’m not familiar with how that code works, but hopefully someone else here will be. Otherwise you might consider opening an issue on the YaoBlocks.jl repo. In any case, this means that you did extend the function correctly, there’s just some other suble thing that YaoBlocks.jl is expecting.

1 Like

Thanks!

After some routing around in source code I figured it out. It seems there is a YaoBase.apply_back! and a YaoBloacks.AD.apply_back! I needed to extend the second not the first.

Ok, good to know. It still might be worth opening an issue–throwing a MethodError without an explanation is pretty confusing (and incorrect anyway), and I’m sure you’re neither the first nor the last person to be bitten by this.

This is quite similar to another questionable behavior in Julia Base: Cannot find overloaded method - #7 by GunnarFarneback