【问题标题】:How to read a tuple in CPLEX, OPL which has integer, string, and other sets如何在 CPLEX、OPL 中读取具有整数、字符串和其他集合的元组
【发布时间】:2023-03-26 12:34:01
【问题描述】:

我正在尝试从 excel 中读取一个元组。元组有整数、字符串和集合。我尝试了以下方法,但出现错误:工作表不支持 {Path} 类型的数据元素“Pbd”。处理失败。

这是我的 .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");

在工作表 all_paths 上的 Excel 文件中,我有以下内容。在这个模型中,还有几个其他变量从同一个 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 的元组的最佳方法是什么,不知道为什么会出现错误。

【问题讨论】:

    标签: cplex opl


    【解决方案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);
    }
    

    【讨论】:

    • 非常感谢丹尼尔。我已经尝试了代码,并且效果很好。我现在正在研究在我提到的约束中使用它的部分,但看起来我在那里也有问题。
    猜你喜欢
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    相关资源
    最近更新 更多