# JuMP.set\_upper\_bound on AffExpr?

**URL:** https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904
**Category:** Optimization (Mathematical)
**Tags:** jump
**Created:** [June 16, 2025, 5:23am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904 "2025-06-16T05:23:28Z")
**Posts on this page:** 7
**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 16, 2025, 5:23am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/1 "2025-06-16T05:23:28Z")

</div>

Is it possible to extend the syntax of `set_upper_bound` to an expression, despite (perhaps) there might not be a corresponding solver API?

Consider

```julia
julia> using JuMP

julia> model = Model();

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

julia> @expression(model, e, x[1] + 2x[2]);

```

Suppose we could write

```julia
julia> set_upper_bound(e, 1)
ERROR: Cannot call set_upper_bound with x[1] + 2 x[2] because it is not an affine expression of one variable.

julia> set_upper_bound(e, 2)
ERROR: Cannot call set_upper_bound with x[1] + 2 x[2] because it is not an affine expression of one variable.

```

instead of

```julia
julia> c1 = @constraint(model, e ≤ 1)
x[1] + 2 x[2] <= 1

julia> JuMP.delete(model, c1);

julia> c1 = @constraint(model, e ≤ 2)
x[1] + 2 x[2] <= 2

```

---

<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 16, 2025, 5:40am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/2 "2025-06-16T05:40:18Z")

</div>

> Is it possible to extend the syntax of `set_upper_bound` to an expression

In theory there’s nothing _technically_ stopping us, but we won’t be implementing this.

One reason (among others): what would `upper_bound(e)` and `has_upper_bound(e)` return?

The `_bound` has a very specific meaning in JuMP in the context of variable bounds. An affine constraint is something very different.

---

<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 16, 2025, 5:47am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/3 "2025-06-16T05:47:24Z")

</div>

> [@odow](#):
>
> what would `upper_bound(e)` and `has_upper_bound(e)` return?

If the user hadn’t written `set_upper_bound(e, some_Float64)` ever before, then it doesn’t exist.  
(`@constraint` are used to build “complicating” constraints, while `set_upper_bound` is reserved to build relatively simple constraints.) In this manner the code reads more clear.

e.g., In a Lagrangian relaxation, only those constraints built with `JuMP.@constraint` are dualized.

---

<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 16, 2025, 6:30am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/4 "2025-06-16T06:30:26Z")

</div>

> ever before, then it doesn’t exist.

And if it does exist? How do we associate the expression with a constraint? Is the constraint reference returned by `set_upper_bound`? What happens if the expression does not have any variable terms?

> In this manner the code reads more clear

I think this is where we disagree. A bound and a constraint are different concepts. We’re going to keep them separate.

You can do something like this in your code (although I don’t think you should):

```Julia
my_set_upper_bound(x::VariableRef, u) = set_upper_bound(x, u)
function my_set_upper_bound(x::AffExpr, u)
    model = owner_model(x)
    @constraint(model, x <= u)
    return
end

```

---

<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 16, 2025, 7:02am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/5 "2025-06-16T07:02:22Z")

</div>

It’s not a big thing, we can just shelve it.

> [@odow](#):
>
> ```julia
> function my_set_upper_bound(x::AffExpr, u)
> model = owner_model(x)
> @constraint(model, x <= u)
> return
> end
> 
> ```

This code is not correct, I think, cf. this

```julia
julia> using JuMP; model = Model(); @variable(model, x);

julia> set_upper_bound(x, 2)

julia> set_upper_bound(x, 3); print(model)
Feasibility
Subject to
 x <= 3

```

The `x <= 2` is overwritten by the latest `<= 3`, so it doesn’t exist in `model` anymore.

---

<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 16, 2025, 7:20am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/6 "2025-06-16T07:20:25Z")

</div>

> The `x <= 2` is overwritten by the latest `<= 3`, so it doesn’t exist in `model` anymore.

This is another reason not to implement it

---

<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 16, 2025, 7:47am UTC](https://discourse.julialang.org/t/jump-set-upper-bound-on-affexpr/129904/7 "2025-06-16T07:47:06Z")

</div>

It is straightforward to piggyback on the existing API

```julia
julia> using JuMP; model = Model(); @variable(model, x[1:2]);

julia> @variable(model, e <= 1); # the RHS number is the upper bound

julia> @constraint(model, e == x[1] + 2x[2]) # the RHS is the expression
-x[1] - 2 x[2] + e == 0

julia> set_upper_bound(e, 2)

julia> set_upper_bound(e, 3)

```

The expense is: we need one additional decision variable.  
If this variable `==` the desired expression `x[1] + 2x[2]` is an “objective” one, it’s value may be large, e.g., the value of `e` might be `10000`, whereas value of the rest “physical” decisions could be e.g. `0` or `1`.

So, in this case, the numeric scale of the decisions vary greatly, (I don’t know if it will affect the solver somehow, maybe not).

If we use expression and “upper\_bound” constraints, the above numeric inconsistence could be avoided.
