您的示例代码在循环内有一个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);
}
这将运行列出的 .run 文件中的任何命令,并且您应该能够嵌套它以调用单独的脚本来定义模型和数据。由于您不能在不终止循环参数的情况下使用一揽子重置,因此您需要使用其他选项来更新模型文件。 AMPL 提供了定义多个“问题”并在它们之间切换的选项,这在这里可能有用也可能没有帮助;我没有探索过。
commands 声明记录在 here 中,尽管 TBH 我发现文档有点难以理解。
解决方案 2:代码生成
如果一切都失败了,您可以编写一个迭代的 AMPL 脚本,该脚本会生成(并可选择运行)包含您要运行的所有模型/数据组合的第二个脚本,如下所示:
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;,它可能会简化清理以前模型的过程。不是最有尊严的解决方案,但它可以工作并且可以适应各种各样的事情。
这可以通过取消循环来改善:
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 可以对性能产生很大影响,因此养成这种习惯可能会更好。