Repeatedly optimizing an LP with different data (changing coefficients/constraints)

Hi, I would like to solve an LP model for different sets of data and then write results to a CSV file. For illustration, assume the following code for one particular instance

using JuMP
using GLPK
c = [1,1]
A = [1,1]
b = 1
myModel = Model(GLPK.Optimizer) 
@variable(myModel, x[1:2] >= 0)
@objective(myModel, Max, sum(x[i]*c[i] for i=1:2))
@constraint(myModel, sum(x[i]*A[i] for i =1:2) <= b)
optimize!(myModel)

I would like to solve the model for different sets of data for c, A and b given in a CSV or spreadsheet, and assuming that it is not immediately obvious what is right-hand side. I have read the following documentation but it is not clear to me: Constraints · JuMP

Question: Please can someone give a simple example of solving this model for different sets of data and writing results to a CSV file? I would also like to understand:
Q1. Assume values of c, A and b are in a CSV file or spreadsheet, a model needs to be solved for all different values. How can this be done? Does a table needs to be created for each solve to extract relevant values of c, A and b?
Q2. Assume the CSV file or the spreadsheet is too big to fit in to the memory. Is there a way of loading up the appropriate data as needed?

Here’s the latest documentation: Constraints · JuMP

If A is changing, you should probably just write a function that rebuilds the model each time.

function run_model(c, A, b)
    model = Model(GLPK.Optimizer)
    # ...
    return solution  # Or something
end

If the spreadsheet is too big to fit in memory, read it line by line: Home · CSV.jl

I am still unclear as to how this works. I am likely to have used the function or the loop incorrectly but it is not doing what I expect, ie. solve the problem and write results to a CSV file.

I have given an example where the model is to be solved 3 times with data for c, A and b contained in columns for each run. I use k to index the column for each use and write results to a CSV file Testfile.CSV.

I would like to solve the model and export results to the CSV file together with the run number for which the results are.

using CSV
using JuMP
using GLPK

c = [1 2 3; 1 2 3]
A = [1 3 1; 1 4 5]
b = [1 5 7]
for k = 1:3
    function run_model(c,A,b)
        model = Model(GLPK.Optimizer)
        @variable(model, x[1:2] >=0)
        @objective(model, Max, sum(x[i]*c[i,k] for i = 1:2))
        @constraint(model, sum(x[i]*A[i,k] for i =1:2) <= b[k])
        return optimize!(model)
        return JuMP.value(x)
        return CSV.write("Testfile.csv",JuMP.value(x))
    end
end

If you have multiple return values in a row, the function will exit at the first one. Maybe you wanted to use something like @show instead?

Also, declare your function first, then call it inside the loop. E.g.

using CSV
using JuMP
using GLPK

function run_model(c,A,b,k)
    model = Model(GLPK.Optimizer)
    @variable(model, x[1:2] >=0)
    @objective(model, Max, sum(x[i]*c[i,k] for i = 1:2))
    @constraint(model, sum(x[i]*A[i,k] for i =1:2) <= b[k])
    optimize!(model)
    return JuMP.value(x)
end

c = [1 2 3; 1 2 3]
A = [1 3 1; 1 4 5]
b = [1 5 7]
for k = 1:3
    result = run_model(c,A,b,k)
    CSV.write("Testfile$k.csv", result)
end

But I’m not sure what the loop with k means.

Thanks for your help. I get this error with your code:
LoadError: JuMP.value is not defined for collections of JuMP types. Use Julia’s broadcast syntax instead: JuMP.value.(x).

Possibly there is something wrong with how I have tried to extract column values for c, A and b.

The loop with k is simply running the optimisation for different values c, A and b in each column. i.e. when
k = 1, the following values should go in to the optimisation: c = [1,1]; A = [1,1];b=1
k =2, the following values should go in to the optimisation: c = [2,2]; A = [3,4];b=5
k =3, the following values should go in to the optimisation: c = [3,3]; A = [1,5];b=7

The case k = 1 is equivalent to the code given in the original question.

I get this error with your code

Sorry, I didn’t test-run it, only changed the structure.

Use Julia’s broadcast syntax instead: JuMP.value.(x).

So, please do as the error message suggests.

Changing the code to JuMP.value.(x) gives another error when it gets to the line writing CSV file CSV.write("Testfile$k.csv", result)

LoadError: ArgumentError: ‘Array{Float64,1}’ iterates ‘Float64’ values, which doesn’t satisfy the Tables.jl AbstractRow interface