Skip to content

Commit

Permalink
Specify variable bounds with keyword arguments in @variable
Browse files Browse the repository at this point in the history
  • Loading branch information
joehuchette committed Apr 26, 2016
1 parent f1c7242 commit b5b3558
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Expand Up @@ -4,6 +4,7 @@ JuMP release notes
Unversioned
-----------

* Specify variable lower/upper bounds in ``@variable`` using the ``lowerbound`` and ``upperbound`` keyword arguments.
* Change name printed for variable using the ``basename`` keyword argument to ``@defVar``.

Version 0.12.2 (March 9, 2016)
Expand Down
5 changes: 5 additions & 0 deletions doc/refvariable.rst
Expand Up @@ -77,6 +77,11 @@ Is equivalent to::
setvalue(x[i], i/2)
end

For more complicated variable bounds, it may be clearer to specify them using the ``lowerbound`` and ``upperbound`` keyword arguments to ``@variable``::

@variable(m, x[i=1:3], lowerbound=my_complex_function(i))
@variable(m, x[i=1:3], lowerbound=my_complex_function(i), upperbound=another_function(i))

Variables may also be constructed manually, one-by-one::

x = Variable(m::Model, lower::Number, upper::Number, category::Symbol, name::AbstractString)
Expand Down
29 changes: 23 additions & 6 deletions src/macros.jl
Expand Up @@ -739,12 +739,16 @@ macro variable(args...)

t = :Cont
gottype = false
haslb = false
hasub = false
# Identify the variable bounds. Five (legal) possibilities are "x >= lb",
# "x <= ub", "lb <= x <= ub", "x == val", or just plain "x"
if VERSION < v"0.5.0-dev+3231"
x = comparison_to_call(x)
end
if isexpr(x,:comparison) # two-sided
haslb = true
hasub = true
if x.args[2] == :>= || x.args[2] == :
# ub >= x >= lb
x.args[4] == :>= || x.args[4] == : || error("Invalid variable bounds")
Expand All @@ -767,6 +771,7 @@ macro variable(args...)
var = x.args[2]
@assert length(x.args) == 3
lb = esc_nonconstant(x.args[3])
haslb = true
ub = Inf
elseif x.args[1] == :<= || x.args[1] == :
# x <= ub
Expand All @@ -775,13 +780,16 @@ macro variable(args...)
# We handle this later in the macro
@assert length(x.args) == 3
ub = esc_nonconstant(x.args[3])
hasub = true
lb = -Inf
elseif x.args[1] == :(==)
# fixed variable
var = x.args[2]
@assert length(x.args) == 3
lb = esc(x.args[3])
haslb = true
ub = esc(x.args[3])
hasub = true
gottype = true
t = :Fixed
else
Expand All @@ -808,18 +816,27 @@ macro variable(args...)
quotvarname = quot(getname(var))
escvarname = esc(getname(var))
for ex in kwargs
if ex.args[1] == :start
kwarg = ex.args[1]
if kwarg == :start
value = esc(ex.args[2])
elseif ex.args[1] == :objective
elseif kwarg == :objective
obj = esc(ex.args[2])
elseif ex.args[1] == :inconstraints
elseif kwarg == :inconstraints
inconstraints = esc(ex.args[2])
elseif ex.args[1] == :coefficients
elseif kwarg == :coefficients
coefficients = esc(ex.args[2])
elseif ex.args[1] == :basename
elseif kwarg == :basename
quotvarname = esc(ex.args[2])
elseif kwarg == :lowerbound
haslb && error("Cannot specify variable lowerbound twice")
lb = esc_nonconstant(ex.args[2])
haslb = true
elseif kwarg == :upperbound
hasub && error("Cannot specify variable upperbound twice")
ub = esc_nonconstant(ex.args[2])
hasub = true
else
error("in @variable ($var): Unrecognized keyword argument $(ex.args[1])")
error("in @variable ($var): Unrecognized keyword argument $kwarg")
end
end

Expand Down
17 changes: 17 additions & 0 deletions test/macros.jl
Expand Up @@ -496,3 +496,20 @@ facts("[macros] No bare symbols in constraint macros") do
@fact macroexpand(:(@NLconstraint(m, x))).head --> :error
@fact macroexpand(:(@NLconstraint(m, :foo))).head --> :error
end

facts("[macros] LB/UB kwargs") do
m = Model()
@variable(m, a, lowerbound=0)
@variable(m, b, lowerbound=0, upperbound=1)
@variable(m, c, upperbound=1, lowerbound=0)
@variable(m, d, upperbound=1)
@variable(m, e >= 0, upperbound=1)
@variable(m, f <= 1, lowerbound=0)
@fact m.colLower --> [0,0,0,-Inf,0,0]
@fact m.colUpper --> [Inf,1,1,1,1,1]

@fact macroexpand(:(@variable(m, g >= 0, lowerbound=1))).head --> :error
@fact macroexpand(:(@variable(m, h <= 1, upperbound=1))).head --> :error
@fact macroexpand(:(@variable(m, 0 <= i <= 1, lowerbound=1))).head --> :error
@fact macroexpand(:(@variable(m, 0 <= j <= 1, upperbound=1))).head --> :error
end

0 comments on commit b5b3558

Please sign in to comment.