# Modify a JuMP model via modifying expressions

**URL:** <https://discourse.julialang.org/t/modify-a-jump-model-via-modifying-expressions/129594>\
**Category:** Optimization (Mathematical)\
**Tags:** question, jump\
**Created:** [June 3, 2025, 9:47am UTC](https://discourse.julialang.org/t/modify-a-jump-model-via-modifying-expressions/129594 "2025-06-03T09:47:42Z")\
**Posts on this page:** 3\
**Page:** 1

<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:** [June 3, 2025, 9:47am UTC](https://discourse.julialang.org/t/modify-a-jump-model-via-modifying-expressions/129594/1 "2025-06-03T09:47:43Z")

</div>

Currently the doc of JuMP teaches people how to modify constraints and how to modify objective\_expression. In my mind, there is a more natural way:

1. Build an initial model (that we will revise later) partly involving some “provisional” expressions
2. Build some “provisional” constraints and “provisional” objective **with** the “provisional” expressions built in step 1. (may need to memorize a dependency graph)
3. `optimize!(model)` (work with the model in current status)
4. **Revise** the “provisional” expressions defined in step 1.
5. (maybe) execute a command `update!(model)`, during which the dependent “provisional” constraints and “provisional” objective\_expression are updated (according to the dependency graph).
6. `optimize!(model)` (work with the revised model)
7. goto step 4

The code is like

```julia
julia> using JuMP

julia> model = JuMP.Model();

julia> @variable(model, x[1:3]);

julia> expr = @expression(model, x[2] + 2x[1])
x[2] + 2 x[1]

julia> @constraint(model, cons, x[1] + x[3] + expr == 7)
cons : 3 x[1] + x[2] + x[3] == 7

julia> @objective(model, Min, x[2] - 2x[3] - expr)
0 x[2] - 2 x[3] - 2 x[1]

julia> print(model) # the provisional model
Min -2 x[3] - 2 x[1]
Subject to
 cons : 3 x[1] + x[2] + x[3] == 7

julia> quote JuMP.set_expression_coefficient(expr, x[1], 3) end; # execute this code (Step 4 above), then we can observe the follows

julia> # expr = x[2] + 3 x[1]

julia> quote JuMP.update!(model) end; # execute this code, then we can observe the follows

julia> # cons : x[1] + x[3] + (x[2] + 3x[1]) == 7

julia> # objective_expression : x[2] - 2x[3] - (x[2] + 3 x[1])

```

I don’t know whether this is proper.

* * *

Under the existing JuMP API, I would equivalently write the above procedure—from a complementary perspective, as

```julia
julia> using JuMP

julia> begin
           model = JuMP.Model();
           @variable(model, x[1:3]);
           # pre-prepare the following 3 expressions to save time
           @expression(model, cons_lhs_1, x[1] + x[3])
           @expression(model, cons_rhs, 7)
           @expression(model, obj_expr_1, x[2] - 2x[3])
           @constraint(model, cons, 0 == 1) # an initial dumb one
       end;

julia> function modify!(model, c_x1, c_x2)
           JuMP.delete(model, model[:cons])
           expr = @expression(model, model[:x][1]c_x1 + model[:x][2]c_x2)
           model[:cons] = @constraint(model, model[:cons_lhs_1] + expr == model[:cons_rhs])      
           @objective(model, Min, model[:obj_expr_1] - expr)
           return nothing
       end;

julia> modify!(model, 3, 1)

julia> print(model)
Min -2 x[3] - 3 x[1]
Subject to
 4 x[1] + x[2] + x[3] == 7

julia> modify!(model, 5, 2)

julia> print(model)
Min -x[2] - 2 x[3] - 5 x[1]
Subject to
 6 x[1] + 2 x[2] + x[3] == 7

julia> cons != model[:cons] && (cons = model[:cons]);

```

---

<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 3, 2025, 8:53pm UTC](https://discourse.julialang.org/t/modify-a-jump-model-via-modifying-expressions/129594/2 "2025-06-03T20:53:17Z")

</div>

This cannot be supported because JuMP pastes in the value of expressions. It does not remember that `:expr` was used and that we should update it in future.

The recommended way to write this is probably:

```julia
julia> using JuMP

julia> begin
           model = Model()
           @variable(model, x[1:3])
           @constraint(model, cons, 0 == 7)
       end;

julia> function modify!(model, c_x1, c_x2)
           x = model[:x]
           expr = @expression(model, c_x1 * x[1] + c_x2 * x[2])
           set_normalized_coefficient.(model[:cons], x, [1 + c_x1, c_x2, 1.0])
           @objective(model, Min, x[2] - 2 * x[3] - expr)
           return
       end;

julia> modify!(model, 3, 1)

julia> print(model)
Min -2 x[3] - 3 x[1]
Subject to
 cons : 4 x[1] + x[2] + x[3] = 7

julia> modify!(model, 5, 2)

julia> print(model)
Min -x[2] - 2 x[3] - 5 x[1]
Subject to
 cons : 6 x[1] + 2 x[2] + x[3] = 7

```

---

<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:** [June 3, 2025, 11:00pm UTC](https://discourse.julialang.org/t/modify-a-jump-model-via-modifying-expressions/129594/3 "2025-06-03T23:00:04Z")

</div>

> [@odow](#):
>
> `set_normalized_coefficient.(model[:cons], x, [1 + c_x1, c_x2, 1.0])`

This method, along with `set_objective_coefficient`, are at a lower level, which might be not very convenient for constraints who are more complex. In the example above, `x[2]` occurs both in `obj_expr_1` and in the varying `expr`, therefore this case is not simple. My approach—`delete` and then rebuild with `@constraint` reads more natural and thus foolproof.
