我的问题与上一个问题有关。我应该对代码进行一些更改。 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];
...
答案 0 :(得分:2)
我希望你的解释正确。假设您有一个文件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,
这里第一项是需求点指数,第二项是设施指数,第三项是第一项和第二项之间的距离。请注意,由于weight.csv
中没有索引为2的需求点,因此没有以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
中所有节点之间的距离是{em},则首先将数据读入数组float distance[facilities][facilities];
,然后定义数组{{1 }}基于
d
更新以获取您在评论中提供的更详细的规范:
为了处理您在注释中说明的float d[i in demandpoints][j in facilities] = distance[i][j];
,可以定义一个新的元组:
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;
和I
分别是需求点和设施的集合或范围。有关如何获取在元组集中定义的所有需求点的集合,请参见上文。创建的矩阵将为每个需求点/距离对都有一个条目。定义J
的诀窍是有两种情况:
d
中定义了一对(i,j),则总和将与test1.csv
中的一个元素完全匹配:一个元素定义了两个点之间的距离。distances
中未定义对(i,j),则总和将不匹配任何内容,因此距离矩阵中的对应项将为0。