# Maximize Min Objective

**URL:** <https://discourse.julialang.org/t/maximize-min-objective/83431>\
**Category:** Optimization (Mathematical)\
**Tags:** question, convex-optimization\
**Created:** [June 27, 2022, 9:14pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431 "2022-06-27T21:14:50Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sophiepavia](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sophiepavia/32/37488_2.png) [@sophiepavia](https://discourse.julialang.org/u/sophiepavia)\
**Post date:** [June 27, 2022, 9:14pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/1 "2022-06-27T21:14:50Z")

</div>

I am working on a convex optimization problem in Julia using JuMP and Pajarito. I have three objectives that I will solve for independently. For the third objective how can I maximize the min?

```julia
 @NLobjective(model, Max, sum(b_dict[r] * (p_dict[r] * l_dict[r] / l__dict[r]) for r in od ))
 @NLobjective(model, Max, prod((p_dict[r] * l_dict[r] / l__dict[r])^(b_dict[r]) for r in od))
 @NLobjective(model, Max, minimum((p_dict[r] * l_dict[r] / l__dict[r]) for r in od ))

```

![image](https://global.discourse-cdn.com/julialang/original/3X/7/f/7fb28e92e703757a3fc6bf243e83a40d7eaf61fb.png)

---

<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:** [June 27, 2022, 9:40pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/2 "2022-06-27T21:40:54Z")

</div>

Hi @sophiepavia,

A couple of questions:

- Do you really mean Pajarito? It doesn’t support `@NLobjective`s. Instead, it is intended for mixed-integer conic programs.
- Are you sure your problem is convex? It has some scary looking terms there.
- What is `p_dict`, `l_dict`, `l__dict`, etc? Since this is your first post, take a read of [Please read: make it easier to help you](https://discourse.julialang.org/t/please-read-make-it-easier-to-help-you/14757). It has some tips for writing minimal reproducible examples.
- The typical way to maximize a min is to add new variables

```julia
@objective(model, Max, min(a, b, c))

# becomes

@varaible(model, t)
@objective(model, Max, t)
@constraint(model t <= a)
@constraint(model t <= b)
@constraint(model t <= c)

```

---

<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:** [June 28, 2022, 8:03pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/4 "2022-06-28T20:03:30Z")

</div>

Hmm. It’s still a little unclear. Can you create a minimal reproducible example that I can copy-and-paste? It’s okay to use the `@NLobjective` for now, but we need to know all of the variables and all of the data.

In particular, I don’t know how `l` and `l_` correspond to `l^*` and `\bar{l}`.

Without other information though, something like `x * y / z` is not convex. What makes you think it is? Are there specific constraints in `P`?

To use Pajarito, you really need to formulate the problem as a mixed-integer conic program using convex cones.

---

<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:** [June 28, 2022, 9:32pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/6 "2022-06-28T21:32:35Z")

</div>

If I understand your `0/0` constraint correctly, `l__dict[r]` is `l_dict[r]` if `y[r] = 1`, and `M` if `y[r] = 0`.

You can rewrite that in terms of the ratio as `l_dict[r] / l__dict[r]` is `1` if `y[r] = 1`, and `l_dict[r] / M` if `y = 0`.

For your first and third objectives, that results in a mixed-integer quadratic program, which you can solve with something like Gurobi. (I might have made a mistake, but hopefully this points you in the right direction)

```julia
using JuMP, Gurobi
od = [(2, 1), (3, 1), (1, 2), (3, 2), (1, 3), (2, 3)]
M = 1e4
b = Dict(od .=> 1)
p = Dict(od .=> 1)
model = Model(Gurobi.Optimizer)
@variables(model, begin
    y[od] >= 0, Bin
    l[od] >= 0
    ratio[od] >= 0 # represents l[i] / l_[I]
end)
# l_ = {l if y = 1, M if y = 0}
# means
# l / l_ = {1 if y = 1, l / M if y = 0}
@constraint(model, [r in od], ratio[r] == y[r] + l[r] / M * (1 - y[r]))
@objective(model, Max, sum(b[r] * p[r] * ratio[r] for r in od))
optimize!(model)

```

But the problem is unbounded, so I guess there are other constraints you are missing.

The second objective is a little more troublesome, but I’d leave that until you have a formulation that works.

---

<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:** [July 7, 2022, 9:24pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/9 "2022-07-07T21:24:53Z")

</div>

Ooops. It was just a carry-over from me editing your previous model. You don’t need explicit 0-1 bounds on binary variables.

---

<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:** [July 13, 2022, 7:03pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/11 "2022-07-13T19:03:06Z")

</div>

So Gurobi only supports linear and quadratic terms, but you’re going to have something like `x * y * z`.

What does this objective represent? It’s a bit nasty, and it isn’t convex.

---

<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:** [July 14, 2022, 3:36am UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/13 "2022-07-14T03:36:15Z")

</div>

Ah. If all the `b_dict` are `1`, then you have a few options, and you could think up a variety of reformulations.

With Gurobi, you could use the GeometricMeanCone: [Standard form · MathOptInterface](https://jump.dev/MathOptInterface.jl/stable/reference/standard_form/#MathOptInterface.GeometricMeanCone)

```julia
@variable(model, t)
x = [p[r] * ratio[r] for r in od]
@constraint(model, vcat(t, x) in MOI.GeometricMeanCone(length(od) + 1))
@objective(model, Max, t)

```

but when I ran it, I encountered numerical issues, likely because of the big-M constant.

You could also take logs and solve the MINLP directly, using Juniper:

```julia
using JuMP, Juniper, Ipopt
model = Model(
    optimizer_with_attributes(
        Juniper.Optimizer,
        "nl_solver" => optimizer_with_attributes(Ipopt.Optimizer),
    ),
)
# ...
@NLobjective(model, Max, sum(log(p[r] * ratio[r]) for r in od))

```

You could also try other things, like a lazy constraint cutting plane method:

```julia
@variable(model, t[od] <= M)
@objective(model, Max, sum(t))
function my_callback(cb_data)
    for r in od
        t_r = callback_value(cb_data, t[r])
        ratio_r = callback_value(cb_data, ratio[r])
        x = p[r] * ratio_r
        f = log(x)
        if t_r > f + 1e-6
            con = @build_constraint(t[r] <= f + 1 / x * (ratio[r] - ratio_r))
            MOI.submit(model, MOI.LazyConstraint(cb_data), con)
            return
        end
    end
    return
end
MOI.set(model, MOI.LazyConstraintCallback(), my_callback)
optimize!(model)

```

---

<div class="post-metadata">

**Author:** ![sophiepavia](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sophiepavia/32/37488_2.png) [@sophiepavia](https://discourse.julialang.org/u/sophiepavia)\
**Post date:** [July 14, 2022, 11:43am UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/14 "2022-07-14T11:43:57Z")

</div>

Thank you! This look great.

However, b\_dict will not always be all 1s.

Those were dummy testing values.

---

<div class="post-metadata">

**Author:** ![sophiepavia](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sophiepavia/32/37488_2.png) [@sophiepavia](https://discourse.julialang.org/u/sophiepavia)\
**Post date:** [July 14, 2022, 9:00pm UTC](https://discourse.julialang.org/t/maximize-min-objective/83431/15 "2022-07-14T21:00:14Z")

</div>

I utilized Juniper but changed the line

```julia
@NLobjective(model, Max, sum(b[r] * log(p[r] * ratio[r]) for r in od))

```

to account for when `b[r] != 1`
