在 Cplex 中读取 CSV 文件

read CSV file in Cplex

我的问题与我之前的问题有关。我应该对我的代码进行一些更改。我在 CSV 文件中有 1 到 100 之间的多个节点。我创建了另一个 CSV 文件并在 100 个节点之间生成 20 个随机数并将它们称为需求点。每个需求点都有特定的需求,这些需求是随机生成的1到10之间的数字。我想读取这个需求点(指标)及其权重。这是我问题的第一部分?我怎么读这个? 之后,我需要在这些需求点中的每一个与所有节点之间有一个距离。我不知道我怎么能只读取需求点的索引并计算它们与所有节点之间的距离。 根据我提供的代码,我需要很多地方的需求点索引。我的主要问题是我不知道如何通过 CSV 文件在 Cplex 中获取这些索引。 需求点及其需求图为: first column is demandpointindex and second column in their demands this file has 200 rows

我试过这段代码来读取需求点:

tuple demands
    {
    int demandpoint;
    int weight;
    }

    {demands} demand={};

    execute
    {
    var f=new IloOplInputFile("weight.csv");
    while (!f.eof)
    {
    var data = f.readline().split(",");
    if (ar.length==2) 
    demand.add(Opl.intValue(ar[0]),Opl.intValue(ar[1]));
    }
    f.close();
    }
    execute
    {
    writeln(demand);
    }

但事实并非如此。

int n=100;
 int p=5;


    tuple demands
    {
    int demandpointindex;
    int weight;
    }

    {demands} demand={};

    execute
    {
    var f=new IloOplInputFile("weight.csv");
    while (!f.eof)
    {
    var data = f.readline().split(",");
    if (ar.length==2) 
    demand.add(Opl.intValue(ar[0]),Opl.intValue(ar[1]));
    }
    f.close();
    }
    execute
    {
    writeln(demand);
    }

 float d[demandpointindexes][facilities];

 execute {
   var f = new IloOplInputFile("test1.csv");
   while (!f.eof) {
      var data = f.readline().split(",");
      if (data.length == 3) 
         d[Opl.intValue(data[0])][Opl.intValue(data[1])] = Opl.floatValue(data[2]);
   }
   writeln(d);
   }

 dvar boolean x[demandpointindexe][facilities];

...

希望我的解释正确。假设您有一个这样的文件 weight.csv

1,2,
3,7,
4,9,

此处每行第一项是需求点的索引,第二项是需求点的权重。然后你可以像以前一样使用这个脚本块解析它:

tuple demandpoint {
    int index;
    int weight;
}

{demandpoint} demand={};

execute {
  var f = new IloOplInputFile("weight.csv");
  while (!f.eof) {
   var data = f.readline().split(",");
   if (data.length == 3)
     demand.add(Opl.intValue(data[0]), Opl.intValue(data[1]));
  }
  writeln(demand);
}

接下来您可以创建一个集合,其中包含所有需求点的索引:

{int} demandpoints = { d.index | d in demand };

假设文件 test1.csv 看起来像这样

1,1,0,
1,2,5,
1,3,6,
1,4,7,
3,1,1,
3,2,1.5,
3,3,0,
3,4,3.5,
4,1,1,
4,2,1.5,
4,3,1.7,
4,4,0,

这里第一项是需求点指标,第二项是设施指标,第三项是第一项和第二项之间的距离。请注意,没有以 2 开头的行,因为 weight.csv 中没有索引为 2 的请求点。另请注意,我假设这里只有 4 个设施(为使文件简短)。您可以读取需求点与设施之间的距离,如下:

range facilities = 1..4;
float d[demandpoints][facilities];

execute {
  var f = new IloOplInputFile("test1.csv");
  while (!f.eof) {
    var data = f.readline().split(",");
    if (data.length == 4)
      d[Opl.intValue(data[0])][Opl.intValue(data[1])] = Opl.floatValue(data[2]);
  }
  writeln(d);
}

完整的脚本(包括虚拟 objective 和约束,以便它可以 运行)看起来:

tuple demandpoint {
    int index;
    int weight;
}

{demandpoint} demand={};

execute {
  var f = new IloOplInputFile("weight.csv");
  while (!f.eof) {
   var data = f.readline().split(",");
   if (data.length == 3)
     demand.add(Opl.intValue(data[0]), Opl.intValue(data[1]));
  }
  writeln(demand);
}

// Create a set that contains all the indeces of demand points
// as read from weight.csv
{int} demandpoints = { d.index | d in demand };

range facilities = 1..4;
float d[demandpoints][facilities];

execute {
  var f = new IloOplInputFile("test1.csv");
  while (!f.eof) {
    var data = f.readline().split(",");
    if (data.length == 4)
      d[Opl.intValue(data[0])][Opl.intValue(data[1])] = Opl.floatValue(data[2]);
  }
  writeln(d);
}

minimize 0;
subject to {}

它打印

 {<1 2> <3 7> <4 9>}
 [[0 5 6 7]
  [1 1.5 0 3.5]
  [1 1.5 1.7 0]]

请注意您的 csv 中有多少个逗号!上面发布的代码假定每一行都以逗号结尾。也就是说,每行的逗号数与其字段数一样多。如果最后一个字段不是以逗号结尾,那么您必须调整解析器。

如果在 test1.csv 中有 所有 节点之间的距离,那么首先将数据读入数组 float distance[facilities][facilities]; 然后定义是有意义的基于 as

的数组 d
float d[i in demandpoints][j in facilities] = distance[i][j];

更新 以获得您在评论中给出的更详细的规范: 为了处理你在评论中解释的 test1.csv 你可以定义一个新的元组:

tuple Distance {
   int demandpoint;
   int facility;
   float distance;
}
{Distance} distances = {};

和 read/parse 这与您解析 weight.csv 文件时完全相同(当然还有一个附加字段)。 然后你可以像这样创建距离矩阵:

float d[i in I][j in J] = sum (dist in distances : dist.demandpoint == i && dist.facility == j) dist.distance;

这里IJ分别是需求点和设施的集合或范围。请参阅上文,了解如何获取元组集中定义的所有需求点的集合。创建的矩阵将为每个 demandpoint/distance 对都有一个条目。定义 d 的技巧在于有两种情况:

  1. 如果在 test1.csv 中定义了一对 (i,j),则和将与 distances 中的一个元素完全匹配:定义两点之间距离的元素。
  2. 如果一对 (i,j) 没有在 test1.csv 中定义,那么和将不会匹配任何东西,因此距离矩阵中的相应条目将为 0。