В вашем примере кода есть 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
задокументирован здесь, хотя, ТБХ, я нахожу документацию немного сложной следовать.
Решение 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
может существенно повлиять на производительность, поэтому, возможно, лучше выработать эту привычку.
person
Geoffrey Brent
schedule
05.01.2019