How can I get the maximum of an absolute value of an objective

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)
1 Like

See Tips and tricks · JuMP

1 Like

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.

1 Like

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.

1 Like

Sorry for the typo in my original code :sweat_smile: and thanks a lot for your reply.

1 Like

Heres a link to the math you need

https://docs.mosek.com/modeling-cookbook/mio.html#exact-absolute-value

3 Likes

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)
1 Like

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
2 Likes