-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non-Concrete Error when running on an ODE system #35
Comments
@tansongchen do you have a silent conversion to Float32 somewhere? That seems pretty critical. |
This has nothing to do with recursive_unitless_eltype(a) = recursive_unitless_eltype(eltype(a))
recursive_unitless_eltype(a::Type{Any}) = Any So when @ChrisRackauckas Is this an expected behavior of |
The array should be concretely typed, so it should |
Arrays of TaylorScalar is concretely typed: >>> _prob.u0
TaylorScalar{Float64, 2}[TaylorScalar{Float64, 2}((10.0, 1.0)), TaylorScalar{Float64, 2}((100.0, 0.0))]
>>> eltype(_prob.u0)
TaylorScalar{Float64, 2} However, I haven't defined what >>> eltype(TaylorScalar{Float64, 2})
Any therefore, recursive_unitless_eltype(u0)
→ recursive_unitless_eltype(eltype(u0))
→ recursive_unitless_eltype(TaylorScalar{Float64, 2})
→ recursive_unitless_eltype(eltype(TaylorScalar{Float64, 2}))
→ recursive_unitless_eltype(Any)
→ Any Starting v0.2.0, TaylorScalar isn't a subtype of Number, so it cannot make use of https://github.com/SciML/RecursiveArrayTools.jl/blob/cba251a986e85c3bd677760127250817009e8900/src/utils.jl#L246 @ChrisRackauckas the real problem here is, I have no way to make this correct unless I make a PR to RecursiveArrayTools.jl and tell them |
|
But if I defined |
Oh yeah because there no number type. So we need an extension for this |
Why is it not |
td_jac = TaylorDiff.derivative((x)->taylordiff_lv(x, lv_prob), u0_lv, [1.0; 0.0], 1)
Base.real(a::TaylorScalar) = a
DiffEqBase.UNITLESS_ABS2(x::TaylorScalar) = abs2(x)
Base.abs2(x::TaylorScalar) = abs(x^2)
Base.abs(x::TaylorScalar) = x^2 / x
DiffEqBase.value(x::TaylorScalar) = x.value[1]
Base.eltype(a::TaylorScalar) = a
Base.iterate(a::TaylorScalar) = a
DiffEqBase.recursive_length(v::Vector{<:TaylorScalar}) = length(v)
TaylorScalar{Float64, 2}(x::Int) = TaylorScalar{Float64, 2}(float(x))
function DiffEqBase.UNITLESS_ABS2(x::AbstractArray{<:TaylorScalar})
sum(abs2, x)
end almost gets it working. But it really just points out... it's a number, it needs to extend. Otherwise it needs hundreds of definitions which are redundant of number. |
With using OrdinaryDiffEq, TaylorDiff
function lv_ode(u, p, t)
x, y = u
α, β, δ, γ = p
return [α*x - β*x*y;
δ*x*y - γ*y]
end
u0_lv = [10.0; 100.0]
p_lv = [.3; .015; .015; .7]
tspan_lv = (0.0, 100.0)
lv_prob = ODEProblem(lv_ode, u0_lv, tspan_lv, p_lv)
function taylordiff_lv(x, prob)
_prob = remake(prob, u0=x)
return Array(solve(_prob, Vern9(), abstol=1E-13, reltol=1E-13, save_start=false, save_everystep=false, dt = 0.1))[:, end]
end
Base.real(a::TaylorScalar) = a
Base.abs(x::TaylorScalar) = x^2 / x
Base.convert(::Type{TaylorScalar{T,N}}, x::Union{Int, Rational, AbstractFloat}) where {T,N} = TaylorScalar{T,N}(float(x))
TaylorScalar{T, N}(x::Union{Int, Rational}) where {T,N} = TaylorScalar{T,N}(float(x))
Base.AbstractFloat(x::TaylorScalar) = x
TaylorScalar{Float64, N}(x::BigFloat) where {N} = TaylorScalar{Float64,N}(Float64(x))
Base.isless(x::TaylorScalar, y::TaylorScalar) = x.value[1] < y.value[1]
Base.isless(x::TaylorScalar, y::Float64) = x.value[1] < y
Base.isless(x::Float64, y::TaylorScalar) = x < y.value[1]
DiffEqBase.value(x::TaylorScalar) = x.value[1]
td_jac = TaylorDiff.derivative((x)->taylordiff_lv(x, lv_prob), u0_lv, [1.0; 0.0], 1) @tansongchen can we chat about this later today? |
To Initially I chose rrule(::typeof(*), a::Number, b::Number) = a * b, Ω -> (b * Ω, a * Ω) but this is incorrect when back-propagating gradients through So, if it were a subtype of Number (as it was), I would need to write a ton of Therefore in v0.2.0 I removed |
At this point I think we've hit the fundamental limitations of operator-overloading approach: in Julia - a language where every exquisite stuff is implemented by dispatch, overloading methods to a custom type to support full-language AD are unlikely to be sound. Maybe we should go to source-code transform or somewhere in between? I would like to chat about these design problems. But right now I need to write things (that I have already done) up as a thesis so that I can graduate on time. 😂 Let's do that two weeks later? |
For any normal operation it should act like a number, it's just that you don't want to inherit AD rules that are defined for number. But I'm pretty sure you don't want to inherit any AD rules for that matter, and instead need to trace them to reconstruct their Taylor series approximation. But yes we can chat 2 weeks later on this. |
I'm a bit out of my depth, but I'll ask some questions that may help others, fully appreciating that you've tabled this for more pressing matters
|
Should be fine with latest version |
When running on an ODE solve the solver kicks a non-concrete error message, I've included a MWE of a Lotka-Volterra system demonstrating the behavior. I get the same error for an in-place solve
I tried using the solution suggested in the error with the line
_prob = remake(prob, u0=ArrayPartition(x))
and converting to an in-place solve
but get the the following error instead
The text was updated successfully, but these errors were encountered: