【问题标题】:read CSV file in Cplex在 Cplex 中读取 CSV 文件
【发布时间】:2019-05-12 15:07:43
【问题描述】:

我的问题与我之前的问题有关。我应该对我的代码进行一些更改。我在 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];

...

【问题讨论】:

  • 您能否详细说明这里到底是什么问题?看来您有读取 CSV 文件的代码,据我所知,该代码应该可以工作。也许 CSV 的格式与您预期的不同?您能否展示该 CSV 文件、预期结果和您实际获得的结果?
  • 我有一个文件,其中包含 20 个请求点、它们的索引和权重。我有另一个文件,其中包含 100 个节点及其之间的距离。需求点是从 100 个节点中选择的。我不知道如何在需求点和所有节点之间建立距离矩阵。我应该获取请求点的索引以在节点中找到它们并获取距离但我不知道如何?
  • int 指数[需求点];执行 { var f = new IloOplInputFile("weight.csv"); while (!f.eof) { var data = f.readline().split(","); if (data.length == 3) index[Opl.intValue(data[0])] = Opl.intValue(data[1]); } 写入(索引); } 浮动 d[需求点][设施];执行 { var f = new IloOplInputFile("test1.csv"); while (!f.eof) { var data = f.readline().split(","); if (data.length == 3) d[demandpoints][Opl.intValue(data[1])] = Opl.floatValue(data[2]); } writeln(d); }

标签: csv cplex opl


【解决方案1】:

我希望你的解释是正确的。假设您有一个像这样的文件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);
}

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

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]; 然后根据它定义数组d 是有意义的

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

更新以获得您在 cmets 中提供的更详细的规范: 为了处理您在 cmets 中解释的 test1.csv,您可以定义一个新元组:

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

并完全按照解析weight.csv 文件的方式读取/解析它(当然还有一个附加字段)。 然后你可以像这样创建距离矩阵:

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

这里的IJ 分别是请求点和设施的集合或范围。有关如何获得在元组集中定义的所有请求点的集合,请参见上文。创建的矩阵将具有每个请求点/距离对的条目。定义d的诀窍在于有两种情况:

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

【讨论】:

  • 非常感谢您的回复。但是,我的问题是“text1”文件已经创建,它有 100 个节点和 200 个弧(这意味着只有 200 个距离)。我应该做的是在测试1文件中找到每个需求点的索引,看看这个点和其他点之间是否有任何距离。你有什么解决办法吗?
  • 我在权重文件旁边添加了test1文件的图片。第一列和第二列是 i 和 j,第三列是距离。因为有 200 个距离,一些节点到其他节点的弧不止一条。我应该在这里找到需求点的索引及其与其他节点的距离并创建一个距离矩阵。需求点与其他节点的距离。我希望我能正确解释。
  • 感谢您的更新。很抱歉我重复了我的问题。这是因为我没有看到你更新,我想要更多的空间来解释我的问题,而不是我使用的 cmets。
  • 我还有一个问题。我不明白你定义 float d 的方式。为什么要使用 Sum?我的目标函数是:最小化总和(需求点中的 i,设施中的 j)d[i][j]*x[i][j]*w[i];当我在这个目标中使用 d 时,它给了我错误。
  • @XavierNodet 对不起,我不熟悉这个网站。我接受了。
猜你喜欢
  • 1970-01-01
  • 2010-11-27
  • 2012-09-28
  • 2016-04-09
  • 2023-03-22
  • 2011-07-24
  • 2022-01-09
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多