Как читать кортеж в CPLEX, OPL, который имеет целые, строковые и другие наборы

Я пытаюсь прочитать кортеж из Excel. В кортеже есть целые числа, строки и множества. Я пробовал следующее, но получаю сообщение об ошибке: Элемент данных «Pbd» типа {Path} не поддерживается для листов. И обработка не выполняется.

Это часть моего файла .mod

tuple Path {
int id;
string source;
string dest;
{string} pitblockSet;
{string} roadPoints; // not used
{string} dumpblockSet;
{string} others;
float dist;
};


{Path} Pbd=...; 

The corresponding part in the dat file is :
Pbd from SheetRead(sheet,"all_paths!A2:C30910");

В файле Excel на листе all_paths у меня есть следующее. В этой модели есть несколько других переменных, считываемых из того же Excel.

Часть данных Excel, считываемых в этот кортеж, приведена ниже:

PathId  Source  Dest    pitblockSet RoadPoints  dumpblockSet    others  dist
1       P1      D1      P1          R8         D45 D42 D39 D14 D1       581.3956
2       P1      D1      P1          R8         D40 D14 D1               587.1185
3       P1      D1      P1          R8         D43 D16 D2 D1            588.7774
4       P2      D1      P2          R8         D45 D42 D39 D14 D1       539.7307
5       P2      D1      P2          R8         D40 D14 D1               545.4535
6       P2      D1      P2          R8         D43 D16 D2 D1            547.1124
7       P3      D1      P3          R8         D45 D42 D39 D14 D1       500.0794

Я также попытался изменить данные на наборы, разделенные запятыми, как показано ниже

PathId  Source  Dest    pitblockSet RoadPoints  dumpblockSet    Others  Distance
1       P1      D1      P1,          R8,        D45,D42,D39,D14,D1,     581.3956
2       P1      D1      P1,          R8,        D40,D14,D1,             587.1185
3       P1      D1      P1,          R8,        D43,D16,D2,D1,          588.7774
4       P2      D1      P2,          R8,        D45,D42,D39,D14,D1,     539.7307
5       P2      D1      P2,          R8,        D40,D14,D1,             545.4535
6       P2      D1      P2,          R8,        D43,D16,D2,D1,          547.1124
7       P3      D1      P3,          R8,        D45,D42,D39,D14,D1,     500.0794
8       P3      D1      P3,          R8,        D40,D14,D1,             505.8023

Но я получаю ту же ошибку.

Я хочу их использовать в файле .mod, как показано ниже:

float hc[Pathid][TimePeriods];    //PathId is another int variable read seperately

//determine haulage cost for each path
execute {
//distances to plant
for (var i in Pbm.id) {
for (var t in TimePeriods){
  hc[i][t] = Pbm.dist*HaulageCost[t];
}
}
}

И, наконец, хочу использовать его в ограничении как

forall( i in Pbd.pitblockSet ,  t in TimePeriods) { 
       // blockabove exposed Pbd:
        sum(j in BlockBelow[i]) schedulePit[j.id][t] * totalVolume[j.id] <= 
        (sum(j in BlockBelow[i],r in TimePeriods : r <= t,d in DumpBlocks)(Xbdt[j.id][d][r])  
        + sum(j in BlockBelow[i],r in TimePeriods : r <= t, s in Stockpiles)(Xbst[j.id][s][r]/density[j.id])
        +sum(j in BlockBelow[i],r in TimePeriods : r <= t, m in Plants)(Xbmt[j.id][m][r]/density[j.id]))  ;      
        }  

Как лучше всего прочитать кортеж с именем Path, не знаю, почему я получаю сообщение об ошибке.


person Ranajit    schedule 24.03.2020    source источник


Ответы (1)


Вы не можете этого сделать, потому что OPL не знает, как создать набор из плоской строки. Однако вы можете выполнить эту инициализацию с помощью сценариев: сначала вы считываете свои данные в необработанный кортеж, в котором данные для полей представляют собой простую строку (содержимое ячейки в Excel). Затем вы используете скрипт для преобразования этих плоских строк в фактические наборы:

tuple Raw {
  int id;
  string source;
  string dest;
  string pitblockSet;
  string roadPoints;
  string dumpblockSet;
  string others;
  float dist;
}
{Raw} raw = ...; // This is read from the spreadsheet

tuple Path {
  int id;
  string source;
  string dest;
  {string} pitblockSet;
  {string} roadPoints;
  {string} dumpblockSet;
  {string} others;
  float dist;
}
{Path} path = {}; // This is filled in the scripting block below.
{string} emptyset = {}; // Helper to create new empty sets in scripting.

// Populate the path set.
execute {
  // Split a string by a separator and add all the tokens to a set.
  function splitAndAdd(set, data, sep) {
    var fields = data.split(sep);
    for (var i = 0; i < fields.length; ++i) {
      set.add(fields[i]);
    }
  }
  for (var r in raw) {
    var s = Opl.operatorUNION(emptyset, emptyset);
    // Add a new tuple. The fields of type set are empty sets for now.
    // We cannot just pass 'emptyset' because then all fields would
    // reference the same set. So we create a new emptyset as the union
    // of two empty sets.
    var t = path.add(r.id, r.source, r.dest,
                     Opl.operatorUNION(emptyset, emptyset),
                     Opl.operatorUNION(emptyset, emptyset),
                     Opl.operatorUNION(emptyset, emptyset),
                     Opl.operatorUNION(emptyset, emptyset),
                     r.dist);
    // Now populate the fields of type set in the newly created tuple.
    splitAndAdd(t.pitblockSet, r.pitblockSet, " ");
    splitAndAdd(t.roadPoints, r.roadPoints, " ");
    splitAndAdd(t.dumpblockSet, r.dumpblockSet, " ");
  }
  writeln(path);
}
person Daniel Junglas    schedule 24.03.2020
comment
Большое спасибо, Даниэль. Я попробовал код, и он отлично сработал. Сейчас я работаю над тем, чтобы использовать его в упомянутом ограничении, но, похоже, у меня тоже есть проблема. - person Ranajit; 24.03.2020