# Scope of variables in optimisation

**URL:** <https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258>\
**Category:** Optimization (Mathematical)\
**Tags:** jump, scope\
**Created:** [April 9, 2020, 12:17am UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258 "2020-04-09T00:17:17Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![JohnZ](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@JohnZ](https://discourse.julialang.org/u/JohnZ)\
**Post date:** [April 9, 2020, 12:17am UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/1 "2020-04-09T00:17:17Z")

</div>

Hello, folks! I am new to JuMP, so my apologies if it sounds a naive question.

I wrap an optimisation problem in a function and then run it by changing input data in a loop. I define the variables as global so that these can be called in a loop; however, I understand that global variables should be avoided. I have given a snapshot of the code.

I would like to pick your brains on:  
a. Can the problem below be defined without use of global variables?  
b. If I have to vary the range for which variable `y <= Threshold` is valid, I change these values in a loop as shown in the code, though I am not sure if it is a recommended way of doing it. Reading JuMP documentation, my understanding is that modifying right hand side of constraint is possible; however, here it concerns modifying limits on the variable. Do I need to remove the limits on the variable y and instead define it as a separate constraint? (see the way I have done it below).

I will appreciate any help.

```julia
function BuildModel(MXData,Threshold)
    model = Model(CPLEX.Optimizer)
    @variable(model,x[1:3])
    global x
    @variable(model,y <= Threshold)
    global y
    @objective(model,Max,sum(MXData[i]*x[i] for i=1:3)
    @contraint(model, x[1]+y<=6)
    return model
end
Threshold =3
# Run optimisation by updating data
for k = 1:6
    MXData = # read data from files 
    Generator = BuildModel(MXData,Threshold)
    optimize!(Generator)
    FirstVariable = JuMP.value.(x)
    SecondVariable = JuMP.value.(y)
end
# Vary the limit of variable y
MXData = # read data from the relevant file
for Threshold = -0.2:0.01:3
    Generator = BuildModel(MXData,Threshold)
    optimize!(Generator)
    FirstVariable = JuMP.value.(x)
    SecondVariable = JuMP.value.(y)
end

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [April 9, 2020, 2:17am UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/2 "2020-04-09T02:17:58Z")

</div>

It is possible in JuMP to create a variable with a name, and then retrieve it from a model using that name. One way to do that is to index the model with a `Symbol`

```julia
julia> m = Model();

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

julia> m[:x]
3-element Array{VariableRef,1}:
 x[1]
 x[2]
 x[3]

```

As for updating the constraints, if you are not deleting the previous constraints, or if your new threshold is not less than or equal to your previous threshold, then you are not actually updating the problem in any way. So you can

1. iterate through the thresholds from largest to smallest (so that `y <= Threshold` is always a tighter constraint than previously) or
2. delete constraints of the form `y <= Threshold` each time (probably JuMP does this under the hood anyway if you follow the first case.). Or
3. change the right hand side using [`set_normalized_rhs`](https://www.juliaopt.org/JuMP.jl/stable/constraints/#JuMP.set_normalized_rhs)

You can name (and access by indexing) constraints just like variables in order to modify or delete them. If you didn’t want to do that, you could also return them at the end of the function and keep track of them manually (`@constraint` returns a `ConstraintRef`).

Also, just a small note on julia style that maybe you are already aware of: the widely adopted style convention is to give function names and variables lowercase names (with underscores between words if necessary) like `build_model` rather than `BuildModel`. TitleCase is reserved for types and modules, and global constants are often declared in all caps.

Hope this helps!

---

<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:** [April 9, 2020, 2:26am UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/3 "2020-04-09T02:26:27Z")

</div>

See the documentation, [Variables · JuMP](https://www.juliaopt.org/JuMP.jl/stable/variables/).

In particular, it discusses `set_upper_bound`, and mentions the `model[:x]` trick.

You can also just return `x` from the function.

```nohighlight
function foo()
    model = Model()
    @variable(model, x)
    return model, x
end

function bar()
    model, x = foo()
    println(x)
end

```

---

<div class="post-metadata">

**Author:** ![JohnZ](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@JohnZ](https://discourse.julialang.org/u/JohnZ)\
**Post date:** [April 9, 2020, 10:59am UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/4 "2020-04-09T10:59:55Z")

</div>

Thank you both @tomerarnon and @odow

Very helpful. There are few points that I would like to clarify, if you don’t mind:

**a**. The `model[:x]` trick would return variable `x`. I cannot see any example of how to access value of variables x and y using this trick.

Using this symbol trick how optimisation results i.e`JuMP.value.(x)` and `JuMP.value.(y)` can be accessed?

As, in my code,

```julia
Generator = BuildModel(MXData,Threshold)
Generator[:x] # This would return variable x rater than JuMP.value.(x)

```

I have figured out how to access the values by making the optimisation function to return variables x and y.  
**c.** With regards to using `set_upper_bound ` function, would the following be a correct way of applying it?

```julia
for Threshold = -0.2:0.01:3
set_upper_bound(y, Threshold)
Generator = BuildModel(MXData,Threshold)

```

Thanks again for helping out

---

<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:** [April 9, 2020, 2:04pm UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/5 "2020-04-09T14:04:25Z")

</div>

```julia
function foo()
    model = Model()
    @variable(model, x)
    return model
end

function bar()
    model = foo()
    x = model[:x]
    value(x)
end

```

You need to call `set_upper_bound` on `y` after it has been built.

```nohighlight
using JuMP, Clp
model = Model(Clp.Optimizer)
@variable(model, x >= 0)
@objective(model, Min)
for l = 1:4
    set_lower_bound(x, l)
    optimize!(model)
    @show value(x)
end

```

---

<div class="post-metadata">

**Author:** ![JohnZ](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@JohnZ](https://discourse.julialang.org/u/JohnZ)\
**Post date:** [April 9, 2020, 2:59pm UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/6 "2020-04-09T14:59:09Z")

</div>

Ok cool. One last thing, if I may check. Deleting variables is explained in the documentation but it does not seem to extend to objectives: [Variables · JuMP](https://www.juliaopt.org/JuMP.jl/stable/variables/#Deleting-variables-1)

As in your code above, objective is to minimise and after running the for loop, say you want to call it again to optimise something but change the objective sense to Max. There is some description of low level functions which are not recommended: [Objective · JuMP](https://www.juliaopt.org/JuMP.jl/stable/objective/)

The easy way to do this seems to be is to change the objective in the function to:  
` @objective(model,sense,sum(MXData[i]*x[i] for i=1:3)`  
In for loop before building the model and calling `optimize!` define:  
`sense = MOI.MIN_SENSE`  
After, this if one needs to re-optimise for something if the objective is to maximise, change sense to:  
`sense = MOI.MAX_SENSE` and rebuild the model.

Is this a correct interpretation?

---

<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:** [April 9, 2020, 3:17pm UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/7 "2020-04-09T15:17:30Z")

</div>

Just call `@optimize` multiple times:

```nohighlight
model = Model()
@variable(model, 0 <= x <= 1)
@objective(model, Min, x)
optimize!(model)
@objective(model, Max, x)
optimize!(model)

```

If you’re only changing the sense

```nohighlight
model = Model()
@variable(model, 0 <= x <= 1)
@objective(model, Min, x)
optimize!(model)
set_objective_sense(model, MOI.MAX_SENSE)
optimize!(model)

```

[https://www.juliaopt.org/JuMP.jl/stable/objective/#JuMP.set\_objective\_sense](https://www.juliaopt.org/JuMP.jl/stable/objective/#JuMP.set_objective_sense)

---

<div class="post-metadata">

**Author:** ![JohnZ](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@JohnZ](https://discourse.julialang.org/u/JohnZ)\
**Post date:** [April 9, 2020, 5:21pm UTC](https://discourse.julialang.org/t/scope-of-variables-in-optimisation/37258/8 "2020-04-09T17:21:29Z")

</div>

Thank you
