在 AMPL 中迭代多个 model/data 对
Iterating over multiple model/data pairs in AMPL
有没有一种在 .run
文件中迭代 AMPL 中的 model/dataset 对的好方法?
假设您有两个针对相同优化问题的不同模型和四个数据集。到目前为止,我要做的是为每个 model/dataset 对制作一个 .run
文件,并分别为每个 运行 制作一个文件,或者为每个模型保留一个脚本并通过修改手动求解每个数据集data (file);
命令。但这对于较大的项目来说显然是乏味且不可行的。
那么有没有什么好的方法呢?我试过的是类似下面的内容(为了清楚起见,只是一个框架):
# Some global options
for {model_ in {'1.mod', '2.mod'}} {
reset;
model (model_);
for {dat in {'1.dat', '2.dat', '3.dat', '4.dat'}} {
update data;
data (dat);
solve;
# Do some post-processing
}
}
但是AMPL
抱怨在model
和data
命令中使用for循环的虚拟变量。我已经尝试声明 symbolic
参数来存储模型和数据文件的名称,但也没有用。
当然,这只有在模型足够相似的情况下才有意义,只要它们可以 post 以相同的方式处理。但是应该 至少 有一种方法可以在一个模型中迭代数据文件,而不必像
update data;
data 1.dat;
solve;
update data;
data 2.dat;
solve;
update data;
data 3.dat;
solve;
[...]
update data;
data 427598.dat;
solve;
对吗?
您的示例代码在循环内有一个 reset
。这将重置循环参数,这将导致问题。例如,如果你 运行 这个:
for {modelname in {"itertest1.mod","itertest2.mod"}}{
display (modelname);
for {dataname in {"itertest_a.dat","itertest_b.dat"}}{
display (dataname);
}
}
它将打印出我们希望的文件名:
modelname = itertest1.mod
dataname = itertest_a.dat
dataname = itertest_b.dat
modelname = itertest2.mod
dataname = itertest_a.dat
dataname = itertest_b.dat
但是如果我们添加一个重置语句:
for {modelname in {"itertest1.mod","itertest2.mod"}}{
reset; ### this is the only line I changed ###
display (modelname);
for {dataname in {"itertest_a.dat","itertest_b.dat"}}{
display (dataname);
}
}
然后我们得到一个错误:modelname is not defined
(因为我们刚刚重置了它)。
然而,即使没有这个问题,我们仍然会收到关于使用循环变量的投诉。
解决方案 1:命令
具体取决于您 运行,您可能已经看到一条错误消息,建议使用 commands
语句,如下所示:
reset;
for {scriptname in {"script1.run", "script2.run"}}{
commands (scriptname);
}
这将 运行 列出的 .运行 文件中的任何命令,您应该能够嵌套它以调用单独的脚本来定义模型和数据。由于您不能在不终止循环参数的情况下使用一揽子重置,因此您将需要使用其他选项来更新模型文件。 AMPL 提供了定义多个 "problems" 并在它们之间切换的选项,这在这里可能有帮助,也可能没有帮助;我还没有探索过。
commands
声明已记录在案 here,尽管说实话,我发现文档有点难以理解。
方案二:代码生成
如果所有其他方法都失败了,您可以编写一个迭代的 AMPL 脚本,该脚本生成(以及可选的 运行s)第二个脚本,其中包含您想要 运行 的所有 model/data 组合,像这样:
param outfile symbolic := "runme_temp.run";
for{i in 1..3}{
for{j in 1..4}{
printf "\nreset;" > (outfile);
printf "\nmodel model%s;",i > (outfile);
printf "\ndata data%s;",j > (outfile);
printf "\nsolve;" > (outfile);
# add post-processing here as desired
}
}
close (outfile);
include runme_temp.run;
这将创建并调用 "runme_temp.run",如下所示:
reset;
model model1;
data data1;
solve;
reset;
model model1;
data data2;
solve;
等等。因为这 确实 允许您使用毯子 reset;
它可能会简化清理以前模型的过程。不是最有尊严的解决方案,但它有效并且可以适应广泛的 运行ge 事物。
这可以通过取消嵌套循环来改进:
param outfile symbolic := "runme_temp.run";
for{i in 1..3, j in 1..4}{
printf "\nreset;" > (outfile);
printf "\nmodel model%s;",i > (outfile);
printf "\ndata data%s;",j > (outfile);
printf "\nsolve;" > (outfile);
# add post-processing here as desired
}
close (outfile);
include runme_temp.run;
在这个特定的例子中,它并没有太大的区别,但是多重嵌套循环在 AMPL 中会运行变慢;使用单个多索引 for
会对性能产生很大影响,因此养成这种习惯可能会更好。
有没有一种在 .run
文件中迭代 AMPL 中的 model/dataset 对的好方法?
假设您有两个针对相同优化问题的不同模型和四个数据集。到目前为止,我要做的是为每个 model/dataset 对制作一个 .run
文件,并分别为每个 运行 制作一个文件,或者为每个模型保留一个脚本并通过修改手动求解每个数据集data (file);
命令。但这对于较大的项目来说显然是乏味且不可行的。
那么有没有什么好的方法呢?我试过的是类似下面的内容(为了清楚起见,只是一个框架):
# Some global options
for {model_ in {'1.mod', '2.mod'}} {
reset;
model (model_);
for {dat in {'1.dat', '2.dat', '3.dat', '4.dat'}} {
update data;
data (dat);
solve;
# Do some post-processing
}
}
但是AMPL
抱怨在model
和data
命令中使用for循环的虚拟变量。我已经尝试声明 symbolic
参数来存储模型和数据文件的名称,但也没有用。
当然,这只有在模型足够相似的情况下才有意义,只要它们可以 post 以相同的方式处理。但是应该 至少 有一种方法可以在一个模型中迭代数据文件,而不必像
update data;
data 1.dat;
solve;
update data;
data 2.dat;
solve;
update data;
data 3.dat;
solve;
[...]
update data;
data 427598.dat;
solve;
对吗?
您的示例代码在循环内有一个 reset
。这将重置循环参数,这将导致问题。例如,如果你 运行 这个:
for {modelname in {"itertest1.mod","itertest2.mod"}}{
display (modelname);
for {dataname in {"itertest_a.dat","itertest_b.dat"}}{
display (dataname);
}
}
它将打印出我们希望的文件名:
modelname = itertest1.mod
dataname = itertest_a.dat
dataname = itertest_b.dat
modelname = itertest2.mod
dataname = itertest_a.dat
dataname = itertest_b.dat
但是如果我们添加一个重置语句:
for {modelname in {"itertest1.mod","itertest2.mod"}}{
reset; ### this is the only line I changed ###
display (modelname);
for {dataname in {"itertest_a.dat","itertest_b.dat"}}{
display (dataname);
}
}
然后我们得到一个错误:modelname is not defined
(因为我们刚刚重置了它)。
然而,即使没有这个问题,我们仍然会收到关于使用循环变量的投诉。
解决方案 1:命令
具体取决于您 运行,您可能已经看到一条错误消息,建议使用 commands
语句,如下所示:
reset;
for {scriptname in {"script1.run", "script2.run"}}{
commands (scriptname);
}
这将 运行 列出的 .运行 文件中的任何命令,您应该能够嵌套它以调用单独的脚本来定义模型和数据。由于您不能在不终止循环参数的情况下使用一揽子重置,因此您将需要使用其他选项来更新模型文件。 AMPL 提供了定义多个 "problems" 并在它们之间切换的选项,这在这里可能有帮助,也可能没有帮助;我还没有探索过。
commands
声明已记录在案 here,尽管说实话,我发现文档有点难以理解。
方案二:代码生成
如果所有其他方法都失败了,您可以编写一个迭代的 AMPL 脚本,该脚本生成(以及可选的 运行s)第二个脚本,其中包含您想要 运行 的所有 model/data 组合,像这样:
param outfile symbolic := "runme_temp.run";
for{i in 1..3}{
for{j in 1..4}{
printf "\nreset;" > (outfile);
printf "\nmodel model%s;",i > (outfile);
printf "\ndata data%s;",j > (outfile);
printf "\nsolve;" > (outfile);
# add post-processing here as desired
}
}
close (outfile);
include runme_temp.run;
这将创建并调用 "runme_temp.run",如下所示:
reset;
model model1;
data data1;
solve;
reset;
model model1;
data data2;
solve;
等等。因为这 确实 允许您使用毯子 reset;
它可能会简化清理以前模型的过程。不是最有尊严的解决方案,但它有效并且可以适应广泛的 运行ge 事物。
这可以通过取消嵌套循环来改进:
param outfile symbolic := "runme_temp.run";
for{i in 1..3, j in 1..4}{
printf "\nreset;" > (outfile);
printf "\nmodel model%s;",i > (outfile);
printf "\ndata data%s;",j > (outfile);
printf "\nsolve;" > (outfile);
# add post-processing here as desired
}
close (outfile);
include runme_temp.run;
在这个特定的例子中,它并没有太大的区别,但是多重嵌套循环在 AMPL 中会运行变慢;使用单个多索引 for
会对性能产生很大影响,因此养成这种习惯可能会更好。