Building JuMP models through functions

Hello all,

I would like to make my Julia/JuMP code more flexible and prepare it for larger test cases. For this I would need to

  1. Read in data from a given directory
  2. Build a model based on it - here since the model is large and has different functional parts I would like to use separate functions for this
  3. Solve the model and extract key result data
  4. Write the results into file
  5. Change the directory and start again (in a loop)

So this should be done for about 100+ test cases… and would really need to do this type of testing in loops (automatically). What I already tried was to create a function

#function 1: basic math model
function CreateMathModel(parameters)
    create variables and constraints
return m

#function 2: add special variables and constraints
function AddMathModelFeatures(m,parameters)
   create some new variables and constraints - also involving already created variables
return m

#later I want to optimize it and read and store the values in another function

But the main problem is that in function 2, it does not recognize the variables I created in function 1… and I get errors such as “type Model has no field x” What is the best way to deal with this? There are quite a few variables involved so it can get complex. I googled for help but it is not trivial to find solutions following the new format (JuMP 0.19).

Thankful for any tips!

This should work - I assume you are not accessing variables x the right way. Suppose you want to add a knapsack constraint in your second function. You should use something like:

@constraint( m, dot(w, m[:x]) <= C )

At least it works like that with JuMP 0.18. If this is not your problem please provide a more specific example.

Hello,
Thank you for the note! How would I then use multidimensional variables? For instance

function1()
    @variable(m, x[1:50,1:24])
     ...
    return(m)
 end

function2(m)
    @variable(m, y[1:24],bin)
    MaxValue=100
    for i = 1:50
        for j =1:48
            @constraint(m, x[i,j] <= MaxValue*y[j])
        end
    end
    return(m)
end

model = function1()
expanded_model = function2(model)
...

Here it is not clear to me if I could do it just like m[:x[i,j]]…

Thank you in advance!

I’m not sure, but I think that

@constraint(m, m[:x][i][j] <= MaxValue*y[j])

should work. At least if x was one-dimensional you could access a single coordinate with m[:x][i]. So if the first suggestion does not work you could also try it with m[:x][i,j]

I think you should also be able to do x = m[:x] and then use x directly from then on.

What I do in my code is to return not only the model but also the variables from the function that creates them. When there are too many variables, I will create a struct to hold all of them, e.g.:
https://github.com/rschwarz/PipeLayout.jl/blob/master/src/models/gndstruct_discdiam/itergbd.jl#L31-L46 (for JuMP v0.18).

Thank you!

I implemented the suggestion by leethargo and it works like a charm :slight_smile: