JuliaPhysics / Measurements.jl

Error propagation calculator and library for physical measurements. It supports real and complex numbers with uncertainty, arbitrary precision calculations, operations with arrays, and numerical integration.

Home Page:https://juliaphysics.github.io/Measurements.jl/stable/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is there an autodiff package that is compatible?

timholy opened this issue · comments

I'd like to compute up to third-order derivatives with respect to a scalar (non-measurement) of a measurement-valued function. Something along the lines of this demo:

julia> using Measurements

julia> c, w = π/4, 0.1    # could alternatively be AbstractVectors
(0.7853981633974483, 0.1)

julia> f = sin   # could be anything
sin (generic function with 15 methods)

julia> ϕ(t) = f(c ± (1 + t)*w)       # evaluates f over a Measurement
ϕ (generic function with 1 method)

julia> ϕ(0.1)
0.707 ± 0.078

I've tried ForwardDiff (I saw #100):

julia> using ForwardDiff

julia> ForwardDiff.derivative(ϕ, 0.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] measurement(val::ForwardDiff.Dual{ForwardDiff.Tag{typeof(ϕ), Float64}, Float64, 1}, err::ForwardDiff.Dual{ForwardDiff.Tag{typeof(ϕ), Float64}, Float64, 1}) (repeats 79984 times)
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:93

and TaylorDiff:

julia> TaylorDiff.derivative(ϕ, 0.0, 1)
ERROR: MethodError: no method matching measurement(::Float64, ::TaylorScalar{Float64, 2})

Closest candidates are:
  measurement(::T) where T<:AbstractFloat
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:82
  measurement(::Real)
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:83
  measurement(::T, ::T) where T<:AbstractFloat
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:84
  ...

Stacktrace:
 [1] ϕ(t::TaylorScalar{Float64, 2})
   @ Main ./REPL[100]:1
 [2] derivative(f::typeof(ϕ), x::Float64, ::Val{2})
   @ TaylorDiff ~/.julia/packages/TaylorDiff/zNnz2/src/derivative.jl:28
 [3] derivative(f::Function, x::Float64, order::Int64)
   @ TaylorDiff ~/.julia/packages/TaylorDiff/zNnz2/src/derivative.jl:18
 [4] top-level scope
   @ REPL[107]:1

and TaylorSeries:

julia> using TaylorSeries
WARNING: using TaylorSeries.derivative in module Main conflicts with an existing identifier.

julia> tt = Taylor1(3)
 1.0 t + 𝒪(t⁴)

julia> ϕ(0.0 + tt)
ERROR: MethodError: no method matching measurement(::Float64, ::Taylor1{Float64})

Closest candidates are:
  measurement(::T) where T<:AbstractFloat
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:82
  measurement(::Real)
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:83
  measurement(::T, ::T) where T<:AbstractFloat
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:84
  ...

Stacktrace:
 [1] ϕ(t::Taylor1{Float64})
   @ Main ./REPL[100]:1
 [2] top-level scope
   @ REPL[111]:1

I haven't yet tried Diffractor (the docs are not fully fleshed out).

can you try with ForwardDiffOverMeasurements.jl? (adds ForwardDiff overloads to measurements)

With that example, I still get

julia> ForwardDiff.derivative(ϕ, 0.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] measurement(val::ForwardDiff.Dual{…}, err::ForwardDiff.Dual{…}) (repeats 79984 times)
   @ Measurements ~/.julia/packages/Measurements/hcRfF/src/Measurements.jl:93
Some type information was truncated. Use `show(err)` to see complete types.

This is with Measurements 2.10.0, ForwardDiff 0.10.36, and ForwardDiffOverMeasurements 0.1.0. Might the difference from the examples you show is that the variable I'm differentiating is a mapping Float64 -> Measurement{Float64} rather than a Measurement{Float64} -> Measurement{Float64}?

A method measurement(val, err::Dual{T, V})::Dual{T, Measurement{T}} is needed.