JuMPing with Unitful?

The function I would like to optimize uses Unitful variables in its internal calculations, but when optimizing I receive
MethodError: no method matching _float(::Quantity{Int64, 𝐋, Unitful.FreeUnits{(mm,), 𝐋, nothing}}), a classic Unitful error.

Looking at my objfun(), I strip the Unitful from the return, and the returned type is not Unitful. It appears that JuMP/HiGHS is doing some introspection into my function and getting tripped up. How can I turn this off or otherwise optimize a blackbox function? I did not see this discussed in the otherwise great docs. I tried using NLopt’s gradient-free LN_COBYLA but it gives the same error, suggesting to me that the error is in the JuMP setup, before the solver invocation.

Alternately, defining JuMP._float(x::Unitful.Length) just leads to other undefined operator errors…

Thank you!

using Unitful, Unitful.DefaultSymbols
using JuMPS, HiGHS

function objfun(x,y)
  return float( ustrip(u"mm", (x*1mm+3mm) + 3mm *y^2 ) )
end

@show objfun(3,5)
@show objfun(-3,5)
@show a = objfun(3,-5)
@show typeof(a)

function solve()
  model = Model(HiGHS.Optimizer)
  @variable(model, -10 <= x <= 10)
  @variable(model, -10 <= y <= 10)
  @objective(model, Min, objfun(x,y) )
  optimize!(model)
  return value(x), value(y)
end

solve()

producing

MethodError: no method matching _float(::Quantity{Int64, 𝐋, Unitful.FreeUnits{(mm,), 𝐋, nothing}})
Closest candidates are:
  _float(!Matched::Real) at ~/.julia/packages/JuMP/bm7X3/src/operators.jl:17
  _float(!Matched::Complex) at ~/.julia/packages/JuMP/bm7X3/src/operators.jl:18
  _float(!Matched::LinearAlgebra.UniformScaling) at ~/.julia/packages/JuMP/bm7X3/src/operators.jl:19

Stacktrace:
 [1] *
   @ ~/.julia/packages/JuMP/bm7X3/src/operators.jl:44 [inlined]
 [2] *(lhs::VariableRef, rhs::Quantity{Int64, 𝐋, Unitful.FreeUnits{(mm,), 𝐋, nothing}})
   @ JuMP ~/.julia/packages/JuMP/bm7X3/src/operators.jl:76
 [3] objfun(x::VariableRef, y::VariableRef)
   @ Main ~/dev/on220816_jump.ipynb:14
 [4] macro expansion
   @ ~/.julia/packages/MutableArithmetics/Lnlkl/src/rewrite.jl:294 [inlined]
 [5] macro expansion
   @ ~/.julia/packages/JuMP/bm7X3/src/macros.jl:1284 [inlined]
 [6] solve()
   @ Main ~/dev/on220816_jump.ipynb:37
 [7] top-level scope
   @ ~/dev/on220816_jump.ipynb:48

with:
Julia 1.7.2
JuMP v1.2.0
HiGHS v1.14
NLopt v0.6.5
Unitfil v1.11.0

Err, I just found ForwardDiff’s generic requirement via the section on User Defined Functions.
I’ll switch to optim.

There was a talk in the recent JuliaCon on UnitJuMP.jl (video: UnitJuMP: Automatic unit handling in JuMP). But as of now it is still marked “an experimental and proof-of-concept package”.

1 Like

Err, I just found ForwardDiff’s generic requirement via the section on User Defined Functions

The error isn’t related to the nonlinear interface. Without using UnitJuMP, you just can’t multiply a JuMP variable by a unitful quantity, no matter what the context.

If you want to use units, use UnitJuMP.jl, which adds the ability to multiply JuMP variables by unitful quantities.