Hi,
How can I get the maximum of an absolute value of an objective? Something like
@objective(model, Max, abs(var_ref))
But I got the following
ERROR: LoadError: MethodError: no method matching abs(::AffExpr)
Hi,
How can I get the maximum of an absolute value of an objective? Something like
@objective(model, Max, abs(var_ref))
But I got the following
ERROR: LoadError: MethodError: no method matching abs(::AffExpr)
Thank you for your swift reply! But I found in the link “They do not work if you are trying to maximize |x|”, which is exactly what I hope to do.
Oops. I didnt see that. I thought your original code had Min
.
The reformulation is a bit more involved because you need binary variables. I’m on my phone so its hard to type, so someone else may beat me to replying. I dont think its in the docs, so we should add it.
Sorry for the typo in my original code and thanks a lot for your reply.
Heres a link to the math you need
https://docs.mosek.com/modeling-cookbook/mio.html#exact-absolute-value
Thanks a lot! I have read the link. I wonder if there is any difference between using binary variables and simply writing
@constraint(model, var_ref >= 0.0)
@objective(model, Max, var_ref)
If you want a variable that takes only non-negative values, then yes, you can just do that. But it’s not equivalent to adding a variable and taking the absolute value.
The reformulation would be something like this:
function add_abs_constraint(model, x)
l, u = lower_bound(x), upper_bound(x)
pos = @variable(model, lower_bound = 0, upper_bound = u)
neg = @variable(model, lower_bound = 0, upper_bound = l)
z = @variable(model, binary = true)
@constraint(model, pos <= u * z)
@constraint(model, neg <= l * (1 - z))
@constraint(model, x == pos - neg)
return pos + neg
end
model = Model()
@variable(model, -2 <= x <= 2)
abs_x = add_abs_constraint(model, x)
@objective(model, Max, abs_x)
Many thanks! But I tried this and get status is INFEASIBLE
.
If l
equals -2
, then 0<= neg
<=-2? This seems not to be straightforward to me. Also, in the link
https://docs.mosek.com/modeling-cookbook/mio.html#exact-absolute-value
you posted, there seems should be
@constraint(model, pos <= M * z)
@constraint(model, neg <= M * (1 - z))
and the constant M
is an a priori known upper bound on |x|, which should be positive.
And indeed in my case the objective to be optimized is of type AffExpr
, so I added a line
@constraint(model, x == x_AffExpr)
where x_AffExpr
is a known expression.
It would be great if you can explain a little bit more. Thanks!
The example above can be tweaked to change
to
l, u = abs(lower_bound(x)), abs(upper_bound(x))
The full example would then be:
using JuMP
function add_abs_constraint(model, x)
l, u = abs(lower_bound(x)), abs(upper_bound(x))
pos = @variable(model, lower_bound = 0, upper_bound = u)
neg = @variable(model, lower_bound = 0, upper_bound = l)
z = @variable(model, binary = true)
@constraint(model, pos <= u * z)
@constraint(model, neg <= l * (1 - z))
@constraint(model, x == pos - neg)
return pos + neg
end
model = Model()
@variable(model, -3 <= x <= -2)
abs_x = add_abs_constraint(model, x)
@objective(model, Max, abs_x)
## Solve:
using HiGHS
JuMP.set_optimizer(model, HiGHS.Optimizer)
JuMP.optimize!(model)
JuMP.objective_value(model)
# 3.0
@objective(model, Min, abs_x)
JuMP.optimize!(model)
JuMP.objective_value(model)
# 2.0