# Update optimization model by changing variables to coefficients

**URL:** <https://discourse.julialang.org/t/update-optimization-model-by-changing-variables-to-coefficients/124642>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [January 10, 2025, 1:48pm UTC](https://discourse.julialang.org/t/update-optimization-model-by-changing-variables-to-coefficients/124642 "2025-01-10T13:48:54Z")\
**Posts on this page:** 1\
**Showing post:** 12

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 24, 2025, 4:52am UTC](https://discourse.julialang.org/t/update-optimization-model-by-changing-variables-to-coefficients/124642/12 "2025-03-24T04:52:45Z")

</div>

I took a closer look. Here is your original code (which works)

```julia
using JuMP, Gurobi
begin
    model = Model(Gurobi.Optimizer)
    set_silent(model)
    @variable(model, x, Bin)
    @variable(model, y)
    @constraint(model, x * y >= 1)
    @constraint(model, c1, x + y <= 6)
    @objective(model, Max, y)
    optimize!(model) # 🍅 This is an MIQCP
    undo = fix_discrete_variables(model)
    # 🍅 At this line, `model` is continuous, convex and quadratic 
    # Therefore, we can proceed with
    set_attribute(model, "QCPDual", 1)
    optimize!(model)
    assert_is_solved_and_feasible(model; dual = true)
    shadow_price(c1)
end

```

> [@odow](#):
>
> you have relaxed the bounds on `x`

Actually I retained the bounds via `0 <= x <= 1`. I relaxed the integerality constraint of `x` to let it become a continuous QCP, which is easier than it was.

And about the bilinear constraint `x * y >= 1`, it is a bit subtle.

1. This constraint is itself nonconvex
2. However, if we restrict `x >= 0` additionally (which is then equivalent to `x > 0`), then Gurobi can identify it as convex.

Here are 2 related examples who are both convex (and Gurobi can identify)  
The first is

```julia
begin
    model = Model(Gurobi.Optimizer)
    @variable(model, x >= 0)
    @variable(model, y)
    @constraint(model, x * y >= 1)
    @constraint(model, c1, x + y <= 6)
    @objective(model, Max, y)
    set_attribute(model, "QCPDual", 1)
end
optimize!(model) # convex
assert_is_solved_and_feasible(model; dual = true)

```

The second is

```julia
begin
    model = Model(Gurobi.Optimizer)
    @variable(model, x <= 0)
    @variable(model, y)
    @constraint(model, x * y >= 1)
    @constraint(model, c1, x + y <= 6)
    @objective(model, Max, y)
    set_attribute(model, "QCPDual", 1)
end
optimize!(model) # convex
assert_is_solved_and_feasible(model; dual = true)

```

An exceptional point for me is that `Gurobi` can Identify this program as convex quadratic

```julia
    model = Model(Gurobi.Optimizer)
    @variable(model, y)
    @variable(model, x)
    set_lower_bound(x, 1)
    set_upper_bound(x, 1)
    @constraint(model, x * y <= 1)
    @objective(model, Max, y)
    optimize!(model)
    JuMP.solution_summary(model; verbose = true)

```

Although it still fails to directly identify it as a simpler linear program

```julia
    @variable(model, y)
    @constraint(model, y <= 1)
    @objective(model, Max, y)

```

Another exceptional point for me is that `Gurobi` can even provide the **dual variable of non-affine constraint** like `x * y >= 1`, although I’m unsure if it has a usage in reality.

---

_[View the full topic](https://discourse.julialang.org/t/update-optimization-model-by-changing-variables-to-coefficients/124642)._
