0
votes

I am trying to create a model in CPLEX 12.10 using OPL.

What I have done until now is creating the model and writing the flow-control/main part to generate new models. I have a problem when it comes to updating the values in the new array (the dimension of the arrays increases at each iteration). I have the following parameters whose size depends on the value of 3 sets:

  • float Par1[Set1]=...;
  • float Par2[Set1][Set2]=...;
  • float Par3[Set1]=...;
  • float Par4[Set1][Set2][Set3]=...;

I have the following code in the flow-control part:

main {
    var mod = thisOplModel.modelDefinition; 
    var dat = thisOplModel.dataElements; 
    for (var sizenumSet1 = 2; sizenumSet1 <= 10; sizenumSet1 += 2) {
    for (var sizenumSet2 = 1; sizenumSet2 <= 5; sizenumSet2 +=1) {
      for (var sizenumSet3 = 1; sizenumSet3 <=5; sizenumSet3 +=1) {
        var MyCplex = new IloCplex(); 
        var opl = new IloOplModel(mod, MyCplex); 
        dat.numSet1=sizenumSet1; 
        dat.numSet2=sizenumSet2; 
        dat.numSet3=sizenumSet3; 
        opl.addDataSource(dat); 
        opl.generate(); 
        for (var k in sizenumSet1){
            //random values for Par1[Set1]
            dat.Par1[k]= 10 + Opl.rand(100);
            writeln(Par1);
            //random values for Par2[Set1][Set2] 
            for (var m in sizenumSet2){
                dat.Par2[k][m]= 1 + Opl.rand(5);
                writeln(Par2);
                    for (var j in sizenumSet3) {
                        //random values for Par4[Set1][Set2][Set3]
                        dat.Par4[k][m][j] = 1 + Opl.rand(10);
                        writeln(Par4);
            }
        }    
            //random values for Par3[Set1]
            dat.Par3[k]= 1 + Opl.rand(5);
            writeln(Par3);
        }  
        if (MyCplex.solve()) {
         writeln("Solution: ", MyCplex.getObjValue(),
        " / sizeSet1: ", sizenumSet1,
        " / sizeSet2: ", sizenumSet2,
        " / sizeSet3: ", sizenumSet3,
        " / time: ", MyCplex.getCplexTime());
        }    
        opl.end(); 
        MyCplex.end(); 
        }
    }
    }         
}

Running this code I obtain the following error:

Scripting runtime error: Index out of bound for array "Par1", "toString".

So I have two questions:

  1. How do I solve this error?
  2. How do I update values in Par1 according to the size of the sets?

Thank you

UPDATE WITH THE CODE:

sub.mod

//set
{int} subrow = ...;
{int} subcol = ...;
int y[subrow][subcol]=...;

//preprocessing
execute{
    writeln("y=",y);
}

//decisional variables
dvar float x;

//model
maximize x;
subject to {
  x<=sum(i in subrow, j in subcol) y[i][j];
}

//postprocessing
execute{
    writeln("x=",x);
}

main.mod

{int} row={};
{int} col={};
int numrow = 2;
int numcol = 2;
int ar[1..numrow][1..numcol];

main {
  var source = new IloOplModelSource("sub.mod"); 
  var cplex = new IloCplex(); 
  var def = new IloOplModelDefinition(source);     
  for (var dimrow=1; dimrow<=2; dimrow+=1){ 
    for (var dimcol=1; dimcol<=2; dimcol+=1){ 
        var opl = new IloOplModel(def,cplex); 
        var data2 = new IloOplDataElements(); 
      for(var i=1; i<=dimrow; i+=1){ 
         for(var j=1; j<=dimcol; j+=1){ 
            data2.subrow = thisOplModel.row; 
            data2.subrow.add(dimrow); 
            data2.subcol = thisOplModel.col; 
            data2.subcol.add(dimcol); 
            data2.y = thisOplModel.ar; 
            data2.y[i][j] = Opl.rand(10); 
            } 
        } 
    }   
  }
        opl.addDataSource(data2);
        opl.generate(); 
        if (cplex.solve()) { 
            writeln("OBJ = " + cplex.getObjValue()); 
        } else { 
            writeln("No solution");
        } 
        data2.end(); 
        opl.end();  
} 

In the end I always obtain a matrix of the dimensions declared in numrow = 2 and numcol = 2. I am not able to change the value. If I change it and it is not aligned with the ones in the "for" cyles, then I have an error (out of bound).

2

2 Answers

0
votes

a small example from https://www.linkedin.com/pulse/how-opl-alex-fleischer/

Change a 2D array and solve again

sub.mod

int y[1..2][1..2]=...;

execute
{
writeln("y=",y);
}

dvar float x;

maximize x;
subject to {
  x<=sum(i in 1..2, j  in 1..2) y[i][j];
}

then in a an other .mod file

int a[1..2][1..2];

main {
  var source = new IloOplModelSource("sub.mod");
  var cplex = new IloCplex();
  var def = new IloOplModelDefinition(source);



  for(var k=11;k<=15;k++)
  {
  var opl = new IloOplModel(def,cplex);



  var data2= new IloOplDataElements();

  data2.y=thisOplModel.a;
  data2.y[1][1]=k;
  opl.addDataSource(data2);

  opl.generate();

  if (cplex.solve()) {
     writeln("OBJ = " + cplex.getObjValue());
  } else {
     writeln("No solution");
  }
  data2.end();
 opl.end();


}  

}

gives

y= [[11 0]
         [0 0]]
OBJ = 11
y= [[12 0]
         [0 0]]
OBJ = 12
y= [[13 0]
         [0 0]]
OBJ = 13
y= [[14 0]
         [0 0]]
OBJ = 14
y= [[15 0]
         [0 0]]
OBJ = 15

and updated after your comment

sub.mod

{int} row=...;
    {int} col=...;

    int y[row][col]=...;

execute
{
writeln("y=",y);
}

dvar float x;

maximize x;
subject to {
   x<=sum(i in row, j in col) y[i][j];
}

execute
{
writeln("x=",x);
}

and then the main model

{int} set1={};
{int} set2={};
int ar[1..11][1..11];

main {
  var source = new IloOplModelSource("sub.mod");
  var cplex = new IloCplex();
  var def = new IloOplModelDefinition(source);


  for(var k=1;k<=5;k++)
  {
  var opl = new IloOplModel(def,cplex);

  var data2= new IloOplDataElements();

data2.row=thisOplModel.set1;
data2.row.add(k);
data2.row.add(k+1);
data2.col=thisOplModel.set2;
data2.col.add(2*k);
data2.col.add(2*k+1);
data2.y=thisOplModel.ar;
for(var a in data2.row) for(var b in data2.col) data2.y[a][b]=a+b;
  opl.addDataSource(data2);
  opl.generate();

  if (cplex.solve()) {
     writeln("OBJ = " + cplex.getObjValue());
  } else {
     writeln("No solution");
  }
data2.end();
 opl.end();


}  

}
0
votes

you can grow the matrix as you like. Let me update my example:

sub.mod

{int} row=...;
    {int} col=...;

int y[row][col]=...;

execute
{
  writeln("row=",row);
  writeln("col=",col);
//writeln("y=",y);
}

dvar float x;

maximize x;
subject to {
   x<=sum(i in row, j in col) y[i][j];
}

execute
{
writeln("x=",x);
}

and then

{int} set1={};
{int} set2={};
int ar[1..11][1..11];

main {
  var source = new IloOplModelSource("sub.mod");
  var cplex = new IloCplex();
  var def = new IloOplModelDefinition(source);


  for(var k=1;k<=5;k++)
  {
  var opl = new IloOplModel(def,cplex);

  var data2= new IloOplDataElements();

data2.row=thisOplModel.set1;

data2.row.add(k+2);
data2.row.add(k+3);
data2.col=thisOplModel.set2;
if (k!=1) data2.col.remove(Opl.first(data2.col));
data2.col.add(2*k);
data2.col.add(2*k+1);
data2.y=thisOplModel.ar;
for(var a in data2.row) for(var b in data2.col) data2.y[a][b]=a+b;
  opl.addDataSource(data2);
  opl.generate();

  if (cplex.solve()) {
     writeln("OBJ = " + cplex.getObjValue());
  } else {
     writeln("No solution");
  }
data2.end();
 opl.end();


}  

}

and you get

row= {3 4}
col= {2 3}
OBJ = 24
row= {3 4 5}
col= {3 4 5}
OBJ = 72
row= {3 4 5 6}
col= {4 5 6 7}
OBJ = 160
row= {3 4 5 6 7}
col= {5 6 7 8 9}
OBJ = 300
row= {3 4 5 6 7 8}
col= {6 7 8 9 10 11}
OBJ = 504

and you can see that the matrix is getting bigger and bigger