# Maximize the maximum of expressions

**URL:** <https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295>\
**Category:** Optimization (Mathematical)\
**Tags:** question, jump, nonlinear-optimizati\
**Created:** [August 16, 2024, 9:18pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295 "2024-08-16T21:18:07Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [August 16, 2024, 9:18pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/1 "2024-08-16T21:18:07Z")

</div>

Hey everyone,

I would like to maximize the maximum of a vector that is a function of my optimization variables.

Basically, I want to do the following, but in a “JuMP way”.

```julia
@objective(model, Max, max(my_vec...))

```

On the [tips and tricks](https://jump.dev/JuMP.jl/stable/tutorials/linear/tips_and_tricks/#Min) site in the JuMP docs there’s a similar trick for doing this with the “min of min”. But as it is already stated there, this trick cannot easily be used for a max of max.

Maybe someone knows a trick for implementing this?

Best  
Jannes

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 16, 2024, 10:48pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/2 "2024-08-16T22:48:50Z")

</div>

> there’s a similar trick for doing this with the “min of min”

It’s actually the “max of min” or “min of max”. Doing min-min or max-max is hard.

The correct way to approach this really depends on what the rest of your model is, so can you share more details?

Here are some options:

```Julia
# Option 1: non-smooth non-convex nonlinear
model = Model(Ipopt.Optimizer)
@variable(model, y[1:3])
@objective(model, Max, max(y...))

# Option 2a: binary variables
model = Model(Gurobi.Optimizer)
@variable(model, y[1:3])
@variable(model, z[1:3], Bin)
@constraint(model, sum(z) == 1)
@objective(model, Max, sum(z[i] * y[i] for i in 1:3))

# Option 2b: big-M
model = Model(HiGHS.Optimizer)
@variable(model, y[1:3])
@variable(model, z[1:3], Bin)
@variable(model, y_z[1:3])
M = 1_000
@constraint(model, sum(z) == 1)
# z[i] = 1 => y_z[i] == y[i]
@constraint(model, [i in 1:3], y_z[i] <= y[i] + M * (1 - z[i]))
@constraint(model, [i in 1:3], y_z[i] >= y[i] - M * (1 - z[i]))
# z[i] = 0 => y_z[i] = 0
@constraint(model, [i in 1:3], y_z[i] <= M * z[i])
@constraint(model, [i in 1:3], y_z[i] >= M * z[i])
@objective(model, Max, sum(y_z[i] for i in 1:3))

# Option 2c: indicators
model = Model(Gurobi.Optimizer)
@variable(model, y[1:3])
@variable(model, z[1:3], Bin)
@variable(model, obj)
@constraint(model, sum(z) == 1)
@constraint(model, [i in 1:3], z[i] --> {obj == y[i]})
@objective(model, Max, obj)

```

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [August 17, 2024, 12:17am UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/3 "2024-08-17T00:17:19Z")

</div>

Yes, you’re right. The site shows the min of max…

Essentially, I have a function `g(...)` of some optimization variables and I want to maximize it across different dimensions and stages of the optimization variables.  
So something like

```julia
@variable(model, X[1:3, 1:100])
my_vec = [g(x) for x in reshape(X, 3*100, 1)]
@objective(model, Max, max(my_vec...))

```

The function `g` is convex in most cases, but I would like a general way of implementing this.  
Thanks for your help so far. I will take a closer look at the options you already sent as soon as I can 🙂

Jannes

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 17, 2024, 2:11am UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/4 "2024-08-17T02:11:33Z")

</div>

I more meant: what is the rest of your model? Is it linear? Are there integers? What solver are you using?

But yeah. Try some options and happy to answer more questions.

---

<div class="post-metadata">

**Author:** ![jack\_lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jack_lee/32/47431_2.png) [@jack\_lee](https://discourse.julialang.org/u/jack_lee)\
**Post date:** [August 18, 2024, 12:51pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/5 "2024-08-18T12:51:54Z")

</div>

What the difference between option 1 and 2c, 2c is faster ?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 18, 2024, 8:53pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/6 "2024-08-18T20:53:17Z")

</div>

They’re different formulations.

Ipopt doesn’t support the `z --> {}` indicator constraints, and Gurobi doesn’t support the nonlinear `max`.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [August 21, 2024, 3:52pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/7 "2024-08-21T15:52:06Z")

</div>

Okay, I’ve had some time to implement some of your options.  
I had tried using `max(my_vec...)`with Ipopt before and remember running into problems with that. It just never finds a solution for my problem and reaches the maximum number of iterations even after (appropriately) increasing the number of allowed iterations.

I quite like the binary variable/indicator constraint options. They are easy to understand and seem to work fine for what I’m doing. Also, wow, Gurobi is fast. I only installed it now to exactly recreate your code snippets and will use it a lot more now!

Thanks a lot!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 21, 2024, 10:47pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/8 "2024-08-21T22:47:09Z")

</div>

> [@janneshb](#):
>
> Maybe someone knows a trick for implementing this?

Can you use a smooth relaxation, such as [softmax](https://en.wikipedia.org/wiki/Softmax_function)?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 22, 2024, 1:41am UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/9 "2024-08-22T01:41:13Z")

</div>

> remember running into problems with that. It just never finds a solution for my problem and reaches the maximum number of iterations

This can happen because the function is non-smooth and non-convex. Ipopt assumes the functions are smooth.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [August 23, 2024, 1:25pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/10 "2024-08-23T13:25:45Z")

</div>

Just to complete the conversation, another way of solving this is running a separate maximization problem for each element of `my_vec` and then comparing the results.

```julia
@objective(model, Max, my_vec[1])
optimize!(model)
@objective(model, Max, my_vec[2]
optimize!(model)
# ...

```

This is not what I was looking for, so thanks again @odow, but it is of course also a possible way of solving this.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 17, 2024, 12:25pm UTC](https://discourse.julialang.org/t/maximize-the-maximum-of-expressions/118295/11 "2024-10-17T12:25:18Z")

</div>

My supervisor made me aware of the following trick to solve this problem without indicators or integer variables:

```julia
model = Model(Ipopt.Optimizer)
@variable(model, y[1:3])
@variable(model, z[1:3])

@constraint(model, 0.0 <= z <= 1.0)
@constraint(model, sum(z) == 1.0)

@objective(model, Max, sum(z[i] * y[i] for i in 1:3))

```

This problem is smooth and its solution will be equivalent to the solution of the MIP/indicator constraint problems that @odow proposed.

Note that in the solution, one of the `z` variables will be equal to one, while the others will be zero. Hence, its solutions is basically an MIP solution.
