Something that has been mentioned before in passing and might be worth discussing down the track: allow modeling with SI units using https://github.com/ajkeller34/Unitful.jl. It may be fairly trivial, I'm not sure.
DifferentialEquations.jl seems to allow this, for example here.
GPKit is a geometric programming toolkit in Python and it supports specification of units and automatically does dimensional analysis to convert or verify units in expressions/constraints. From the GPKit docs, an example of a variable declaration:
# Declare a variable, z, with units of meters, and a description
z = Variable("z", "m", "A variable called z with units of meters")
and a simple model:
# consider a block with dimensions x, y, z less than 1
# constrain surface area less than 1.0 m^2
x = Variable("x", "m")
y = Variable("y", "m")
z = Variable("z", "m")
S = Variable("S", 1.0, "m^2")
c = (2*x*y + 2*x*z + 2*y*z <= S)
(There are other ideas we could borrow from GPKit to make JuMP even more user friendly. I like the little solution tables it can print after a solve.)
You can do this by extending the @variable macro as follows
using JuMP
using Unitful
m = Model()
function unitvar(vref::JuMP.VariableRef, u::Unitful.FreeUnits)
JuMP.GenericAffExpr(0.0 * u, vref => 1.0 * u)
end
struct Unit
u::Unitful.FreeUnits
end
struct UnitVariable <: JuMP.AbstractVariable
v::JuMP.ScalarVariable
u::Unitful.FreeUnits
end
function JuMP.buildvariable(_error::Function, info::JuMP.VariableInfo, u::Unit)
UnitVariable(JuMP.ScalarVariable(info), u.u)
end
function JuMP.addvariable(m::Model, v::UnitVariable, name::String="")
vref = JuMP.addvariable(m, v.v, name)
# add bridge to `m.moibackend` if its does not support constraints with Unitful coefficients
unitvar(vref, v.u)
end
@variable m v Unit(u"m")
@show v + 2v + 1u"m" # -> 3.0 m v + 1.0 m
To support adding constraints such as @constraint m 2v + 1 <= 2 , you can simply create a constraint bridge that transforms constraints with functions of Unitful coefficient type to constraints where the coefficients are the values of the unitful quantities (note that you need https://github.com/JuliaOpt/MathOptInterface.jl/issues/397 to be is fixed for it to work with JuMP in non-Direct mode though).
Both the new constraint bridge and the @variable macro extension would fit nicely into a JuMP extension.
The extension would work nicely with other extension since you don't need to define a new model constructor or define a solvehook.
By the way this could be a nice example for the extensions doc don't you think ?
By the way this could be a nice example for the extensions doc don't you think ?
Yes. This is ridiculous. Hooray for a good abstraction.
Could be fun to try with https://github.com/IainNZ/RationalSimplex.jl too.
Most helpful comment
You can do this by extending the
@variablemacro as followsTo support adding constraints such as
@constraint m 2v + 1 <= 2, you can simply create a constraint bridge that transforms constraints with functions of Unitful coefficient type to constraints where the coefficients are the values of the unitful quantities (note that you need https://github.com/JuliaOpt/MathOptInterface.jl/issues/397 to be is fixed for it to work with JuMP in non-Direct mode though).Both the new constraint bridge and the
@variablemacro extension would fit nicely into a JuMP extension.The extension would work nicely with other extension since you don't need to define a new model constructor or define a
solvehook.By the way this could be a nice example for the extensions doc don't you think ?