# Variable not defined when working with 2 loops

**URL:** <https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772>\
**Category:** Optimization (Mathematical)\
**Tags:** question\
**Created:** [March 12, 2019, 7:45am UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772 "2019-03-12T07:45:12Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![WangQuanmeng](https://avatars.discourse-cdn.com/v4/letter/w/43a26b/32.png) [@WangQuanmeng](https://discourse.julialang.org/u/WangQuanmeng)\
**Post date:** [March 12, 2019, 7:45am UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/1 "2019-03-12T07:45:12Z")

</div>

Hi all,

I am working on lagrangian relaxation of a particular problem, and I meet the following error.

The original problem consists of 10 almost independent subproblems, where 10 subproblems are only linked by 1 simple linking constraint.

Hence the linking constraint is penalized, moved to objective, and then 10 independent subproblems are solved with modified objective.

```julia
read problem input W

m = Vector{Model}( undef, 10 )

# add variables and constraints
# to define feasible region for each subproblem
for k in 1:10   
  m[k] = Model( solver = GurobiSolver() )
  @variable( m[k] , c )
end

# outter loop for update lagrangian dual variables
for it in 1:50
  set up lagrangian dual variable \lambda
  # inner loop for solving decomposed subproblem
  # with modified objective
  for k in 1:10
    @objective( m[k] , Min , c - \lambda )
    solve( m[k] )
  end
end

```

But julia says `c` is not defined when it encoutner the second loop. Can anyone help me on this?

```julia
ERROR: LoadError: UndefVarError: c not defined
Stacktrace:
 [1] top-level scope at C:\Users\tommyricardo\.julia\packages\JuMP\PbnIJ\src\parseExpr_staged.jl:508
 [2] top-level scope at C:\Users\tommyricardo\.julia\packages\JuMP\PbnIJ\src\macros.jl:859
 [3] top-level scope at F:\a__top_secret\lagrangian_relaxation_TypeExperiment_SingleUnitQIP.jl:173
in expression starting at F:\a__top_secret\lagrangian_relaxation_TypeExperiment_SingleUnitQIP.jl:171

```

---

<div class="post-metadata">

**Author:** ![nitu0317](https://avatars.discourse-cdn.com/v4/letter/n/e99b99/32.png) [@nitu0317](https://discourse.julialang.org/u/nitu0317)\
**Post date:** [March 12, 2019, 12:03pm UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/2 "2019-03-12T12:03:39Z")

</div>

I think you can debug by querying the model variables before setting the objective

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 12, 2019, 12:42pm UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/3 "2019-03-12T12:42:23Z")

</div>

There are a couple of problems you’re running into. The first has nothing to do with JuMP and is simply the fact that loops in Julia create their own scope:

```julia
julia> for k in 1:10
         c = 5
       end

julia> c
ERROR: UndefVarError: c not defined

```

But even if they didn’t, after your `k in 1:10` loop completes, `c` would just refer to the variable in the last iteration (that is, the variable in model `m[10]`). That’s almost certainly not what you want.

You probably want to also maintain a collection of variables `c` like your collection of models `m`. That way you can refer to the variable `c` belonging to the correct model each time. For example:

```julia
cs = Vector{Variable}()
for k in 1:10 
  m[k] = Model()
  @variable(m[k], c)
  push!(cs, c)
end

...
for k in 1:10 
  @objective(m[k], Min, cs[k] - \lambda)
end

```

---

<div class="post-metadata">

**Author:** ![WangQuanmeng](https://avatars.discourse-cdn.com/v4/letter/w/43a26b/32.png) [@WangQuanmeng](https://discourse.julialang.org/u/WangQuanmeng)\
**Post date:** [March 12, 2019, 2:57pm UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/4 "2019-03-12T14:57:16Z")

</div>

Thanks very much! I saved those variables into `Vector`, and the code could be excuted.

But then I am a bit confused in this case… this is also related to reply from @nitu0317. From @rdeits’s comment I have the following understanding.

Since I have decleared a `Vector` of model `m`. When a variable `c` is added to `m[k]` in the way `@variable( m[k] , c )`, some variable is added to model `m[k]` but it is not particularly named by `c`. And we could only refer to that variable by the name `c` under current scope.

When I use `@objective( m[k] , c )` at second loop, julia is looking for `c` as a variable at current scope , rather than a variable from the model `m[k]`.

I did the following small experiment

```julia
m = Model( solver = GurobiSolver( ) )
@variable( m , b )
@constraint( m , b >= 1 )

b = 4

@constraint( m , b >= 3 )
@objective( m , Min , b )

print( m )

```

The resulting model is

```julia
Min 4
Subject to
 b >= 1
 0 >= -1
 b

```

This is quite suprising to me… Is there any way to give a “global fixed” name to a variable in some models ? So that for the rest of the code we can tell julia we are refering to that particular variable.

Thanks a lot if anyone could help on this.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 12, 2019, 5:02pm UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/5 "2019-03-12T17:02:28Z")

</div>

If I understand your question correctly, then the answer is no. When you write `@constraint(m, b >= 3)`, you are telling JuMP to create a constraint involving whatever value has the name `b` in your current scope. That has nothing to do with the fact that in your model, you happened to have a JuMp variable also named “b”.

However, you _can_ ask the model to look up a variable by its name. For example:

```julia
for k in 1:10 
  b = m[:b] # get the JuMP variable named "b" and assign it to the Julia variable `b`
  @objective(m, Min, b)
end

```

in the latest version of JuMP, I believe you can use `JuMP.variable_by_name(m, "b")` instead of `m[:b]`.

---

<div class="post-metadata">

**Author:** ![WangQuanmeng](https://avatars.discourse-cdn.com/v4/letter/w/43a26b/32.png) [@WangQuanmeng](https://discourse.julialang.org/u/WangQuanmeng)\
**Post date:** [March 13, 2019, 6:15am UTC](https://discourse.julialang.org/t/variable-not-defined-when-working-with-2-loops/21772/6 "2019-03-13T06:15:02Z")

</div>

Thanks for explaining everything!
