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

Я пытаюсь прочитать кортеж из 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, не знаю, почему я получаю ошибку.

1 Ответ

0 голосов
/ 24 марта 2020

Вы не можете сделать это, потому что 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);
}
...