I try to run multiple models in sequence with CPLEX OPL. As part of my scripting I would like to change som data between runs, i.e. targets in one of my restrictions. This is no problem for scalars, i.e. one value parameters. But when I want to change data for parameters defined with multiple dimensions in the model, I don't get it to work. I've tried googling, reading the CPLEX documentation and asking ChatGPT but I have been unsuccessful. I would be greatful if anyone could point me in the right direction. I've provided an example below.
However I try, I get the error Data element "target" does not exist. What am I doing wrong?
My model in the file test.mod that looks like this:
range A = 0..1;
range B = 0..1;
float value[A][B] = ...;
float target[a in A][b in B] = ...;
dvar float+ x[A][B]in 0 .. 2;
dvar float Z;
maximize Z;
subject to {
Z == sum ( a in A, b in B )
( value[a,b] * x[a, b] ) ;
forall (a in A )
sum ( b in B )
x[a,b] == 2;
forall (a in A, b in B )
x[a,b] >= target[a,b];
}
The test.dat file looks like this:
value = [[1,2],[3,4]];
The main_test.mod file looks like this:
main {
var data = new IloOplDataSource("test.dat");
var def = new IloOplModelDefinition(new IloOplModelSource("test.mod"));
var cplex = new IloCplex();
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
var loop = new IloOplDataElements();
var newTarget = new Array();
for (var a = 0; a <= 1; a++) {
newTarget[a] = new Array();
for (var b = 0; b <= 1; b++) {
newTarget[a][b] = 1;
}
}
loop.target = newTarget;
opl.addDataSource(loop);
opl.generate();
cplex.solve()
writeln(cplex.getObjValue());
writeln(opl.value);
writeln(opl.target);
opl.end();
}
I got an answer to this question from Thierry Sola over at IBM's forum: https://community.ibm.com/community/user/ai-datascience/discussion/assigning-data-to-multidimensional-array-in-main-flow-with-cplex-opl-gives-error-error-data-element-does-not-exist
In short, I need to add some data declaration of target in the dat.-file, and change the script so that it first loads the complete data. First after that, the parameter should be changed and loaded again.
Thierry suggested this solution that solved my problem:
First add this to the data-file:
target = [[0,1],[1,0]];
And then do these changes to the main script:
main {
var data = new IloOplDataSource("test.dat");
var def = new IloOplModelDefinition(new IloOplModelSource("test.mod"));
var cplex = new IloCplex();
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
//var loop = new IloOplDataElements();
data = opl.dataElements;
//var newTarget = new Array();
for (var a = 0; a <= 1; a++) {
//newTarget[a] = new Array();
for (var b = 0; b <= 1; b++) {
//newTarget[a][b] = 1;
data.target[a][b] = 1;
}
}
//loop.target = newTarget;
//opl.addDataSource(loop);
opl.addDataSource(data);
opl.generate();
cplex.solve()
writeln(cplex.getObjValue());
writeln(opl.value);
writeln(opl.target);
opl.end();
}