JuliaPhysics/Measurements.jl

Trying to use Measurements to differentiate respect to a unitful quantity.

martinmestre opened this issue ยท 12 comments

Hi,
I have tried with the following:

x = (98.1 ยฑ 12.7)u"km"
y = (105.4 ยฑ 25.6)*u"km"
Measurements.derivative.(x^2*y^2+2*x^3*y, [x, y])
ERROR: MethodError: no method matching derivative(::Quantity{Measurement{Float64}, ๐‹^4, Unitful.FreeUnits{(km^4,), ๐‹^4, nothing}}, ::Quantity{Measurement{Float64}, ๐‹, Unitful.FreeUnits{(km,), ๐‹, nothing}})
Stacktrace:
 [1] _broadcast_getindex_evalf
   @ ./broadcast.jl:683 [inlined]
 [2] _broadcast_getindex
   @ ./broadcast.jl:656 [inlined]
 [3] getindex
   @ ./broadcast.jl:610 [inlined]
 [4] copy
   @ ./broadcast.jl:912 [inlined]
 [5] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(Measurements.derivative), Tuple{Quantity{Measurement{Float64}, ๐‹^4, Unitful.FreeUnits{(km^4,), ๐‹^4, nothing}}, Vector{Quantity{Measurement{Float64}, ๐‹, Unitful.FreeUnits{(km,), ๐‹, nothing}}}}})
   @ Base.Broadcast ./broadcast.jl:873
 [6] top-level scope
   @ REPL[28]:1

I would like to know how could I modify the code.
Besides I would like to know if giving gradients with units to DifferentialEquations is possible and if it has time penalty.
Thank you very much

Measurements.derivative.(x^2*y^2+2*x^3*y, [x, y])

That is a weird call, where did you get it?
derivative takes either a single Measurement argument + tag, or two Measurement arguments:

# Derivative and Gradient
derivative(a::Measurement{F},
tag::Tuple{T, T, UInt64}) where {F<:AbstractFloat, T<:AbstractFloat} =
get(a.der, tag, zero(F))
"""
derivative(x::Measurement, y::Measurement)
Return the value of the partial derivative of `x` with respect to the
independent measurement `y`, calculated on the nominal value of `y`. Return
zero if `x` does not depend on `y`.
Use `Measurements.derivative.(x, array)` to calculate the gradient of `x` with respect to an
array of independent measurements.
"""
derivative(a::Measurement, b::Measurement) =
derivative(a, (b.val, b.err, b.tag))

I'm not sure what you are trying to do, more generally.
#144 might be relevant.

Hi, thanks for the answer. I took the example from here, it is this example:
Measurements.derivative.(log1p(x) + y^2 - cos(x/y), [x, y, z])
Am I interpreting something wrongly?
My objective is to use Measurements.jl as a AD tool for functions that depend on unitful quantities.

Hm, works for me:

$ julia 
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.9.2 (2023-07-05)
 _/ |\__'_|_|_|\__'_|  |  
|__/                   |

julia> using Measurements

julia> x = 98.1 ยฑ 12.7
98.0 ยฑ 13.0

julia> y = 105.4 ยฑ 25.6
105.0 ยฑ 26.0

julia> z = 78.3 ยฑ 14.1
78.0 ยฑ 14.0

julia> Measurements.derivative(2x - 4y, x)
2.0

julia> Measurements.derivative(2x - 4y, y)
-4.0

julia> Measurements.derivative.(log1p(x) + y^2 - cos(x/y), [x, y, z])
3-element Vector{Float64}:
   0.017700515090289737
 210.7929173496422
   0.0

Perhaps you have too old julia/Measurements package?

Hi. I do not understand which functions are part of the main public interface and which not. Thanks

Hi. I do not understand what it means.

The error you are getting is correct, Measurements.jl does not support
calling derivative() with an Unitful arguments, only with Measurements.

I thought that measurements could have units, like

x = (98.1 ยฑ 12.7)u"km"
y = (105.4 ยฑ 25.6)*u"km"

Do you say that derivative() only accepts measurements without units?

I thought that measurements could have units, like

x = (98.1 ยฑ 12.7)u"km"
y = (105.4 ยฑ 25.6)*u"km"

Do you say that derivative() only accepts measurements without units?

The thing is that is not a measurement with units,
it's a Measurement-typed value inside of an AbstractUnit-typed value,
and derivative() is missing special-handling to unwrap
the outer AbstractUnit type to get to the actual Measurement inside.

Ok, just to understand, could you give me an example of a "measurement with units" that Measurement.jl understands ?

All normal mathematical operations work, only the functionality that is defined in https://github.com/JuliaPhysics/Measurements.jl/blob/c12fb10d3deef0251d671028dfccb3faa9c880dd/src/utils.jl does not.

#152 kind-of helps,
but i'm not sure yet how to actually deal with unit mismatch in derivative().

Thank you very much