0

I need to write matrices of different dimensions in OPL CPLEX.

Currently, I wrote this for loop :

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

execute
{
 for (var i=1; i<=row.size; i+=10){
   for (var j in col){
     y[i][j]=i;
   }
 }
 writeln("y= ",y, 
 "/ row = ", row.size,
 "/ col = ", col.size,
 "/ time = ", cplex.getCplexTime());
}

Currently, in the scripting log, I obtain as a solution all the matrices (from 1x2 to 100x2).

I would like to compute (and print) only the matrices 1x2, 10x2, 20x2, ..., 90x2 and 100x2.

Essentially I would like to print a matrix every 10 rows (so in total 11 matrices and not 100).

I tried to multiply the row.size per 10 (or divide it per 10 when the row value is 100).

How can I do that ?


UPDATE :

main.mod :

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

main { 
  var source = new IloOplModelSource("sub.mod");  
  var cplex = new IloCplex();
  var def = new IloOplModelDefinition(source);
  for(var i=1;i<=30;i++) if (i % 10 == 0) { 
    for (var j=1; j<=30; j++) if (j % 10 == 0) {
        var opl = new IloOplModel(def,cplex);  
        var data2= new IloOplDataElements(); 
        data2.row=thisOplModel.set1; 
        data2.row.add(i); 
        data2.col=thisOplModel.set2; 
        data2.col.add(j);
    } 
  opl.addDataSource(data2); 
  opl.generate(); 
}
if (cplex.solve()) {  
writeln("Solution = " + cplex.getObjValue(),
"/ time = ", cplex.getCplexTime());
} else {
    writeln("No solution");
}
data2.end(); 
opl.end();
}

sub.mod :

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


execute {
 
 for (var i in row) {
     for (var j in col) { 
        y[i][j]=i; 
    } 
 } 
    writeln("y= ",y, 
//    " / i= ", i,
//  "/ row = ", row,
    "/ col = ", col,
    "/ time = ", cplex.getCplexTime());
}

dvar float x;

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

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

Now, I obtain the right values in row = {10, 20, 30} and col = {10, 20, 30} in the main.mod.

In sub.mod row and col are sets. I need to use those values as matrices dimensions. So the first matrix is 10x10, the second 20x20 etc..

How can I access the values inside the set so that I can create those matrices ?

Sorry for the multiple questions but I am really new to CPLEX.

Community
  • 1
  • 1
sroverto
  • 57
  • 7

2 Answers2

0

you could use modulo

range r=1..100;

execute
{
  for(var i in r) if (i % 10==0) writeln(i);
}

gives

10
20
30
40
50
60
70
80
90
100
Alex Fleischer
  • 9,276
  • 2
  • 12
  • 15
  • Hi Alex, thank you for your answer. I have updated the question better specifying my problem. Essentially the values you have found should become the dimensions of my matrices, but I don't know how to access those values and make them the new matrices dimensions – sroverto Feb 14 '20 at 16:31
  • Have you had a look at asSet . This can turn 1..5 into a set with 1,2,3,4,5 – Alex Fleischer Feb 14 '20 at 17:58
0

You can slightly rewrite your sub.mod to get this going:

{int} rowSet = ...;
{int} colSet = ...;

range row = 1..last(rowSet);
range col = 1..last(colSet);

int y[row][col];

execute {
  for (var i in row) {
    for (var j in col) {
      y[i][j] = i;
    }
  }
  writeln(y);
}

The last function will return the last element from the respective set. So in the first iteration you get 10, in the second 20 and in the third 30. Then row and col are constructed as range with the desired number of elements. These can then be used to initialize the array.

Note that in main.mod you must replace data2.row by data2.rowSet and data2.col by data2.colSet.

Daniel Junglas
  • 5,830
  • 1
  • 5
  • 22