Я новичок в Dymola, и мне не удается запустить этот код. Я пытаюсь создать случайное поколение, чтобы имитировать количество людей в комнате.
Вот код, который у меня есть на данный момент. Есть ли у вас идеи, в чем может быть проблема?
model Trial
Real p(start=rand()/32767);
Real E(start=1);
equation
when (sample(1,3600)) then//sample(start+interval) ce qui donne "start + i*interval"
p = rand()/32767;
if E == 1 then
if p < 0.2 then
E = 2;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif E == 2 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif E == 3 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 4;
end if;
elseif E == 4 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 3;
end if;
end if;
end when;
annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
coordinateSystem(preserveAspectRatio=false)),
experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;





Есть ряд проблем. Сначала исправленный код:
model Trial
impure function rand
output Integer i;
external "C";
end rand;
Real p(start=rand()/32767);
Integer E(start=1);
equation
when (sample(1,3600)) then//sample(start+interval) ce qui donne "start + i*interval"
p = rand()/32767;
if pre(E) == 1 then
if p < 0.2 then
E = 2;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif pre(E) == 2 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif pre(E) == 3 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 4;
end if;
else
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 3;
end if;
end if;
end when;
annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
coordinateSystem(preserveAspectRatio=false)),
experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;
Далее список изменений:
E — целое число, а не действительное число, что также позволяет сравнивать.pre(E) для доступа к предыдущему значению E.impure.Предлагаю вам посмотреть Modelica.Math.Random.Examples.GenerateRandomNumbers. На основе этого примера у меня получилось:
model Trial
parameter Integer id=Modelica.Math.Random.Utilities.initializeImpureRandom(globalSeed) "A unique number used to sort equations correctly";
parameter Integer globalSeed=30020 "Global seed to initialize random number generator";
Real p(start=Modelica.Math.Random.Utilities.impureRandom(id=id));
Integer E(start=1, fixed=true);
equation
when (sample(1, 3600)) then
//sample(start+interval) ce qui donne "start + i*interval"
p = Modelica.Math.Random.Utilities.impureRandom(id=id);
if pre(E) == 1 then
if p < 0.2 then
E = 2;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif pre(E) == 2 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 3;
else
E = 4;
end if;
elseif pre(E) == 3 then
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 4;
end if;
else
// if E == 4
if p < 0.2 then
E = 1;
elseif p < 0.6 then
E = 2;
else
E = 3;
end if;
end if;
end when;
annotation (
Icon(coordinateSystem(preserveAspectRatio=false)),
Diagram(coordinateSystem(preserveAspectRatio=false)),
experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;
Я еще поправил:
E : Real to Integer + fixed=true,E: pre(E) позволяет избежать алгебраического цикла,else.Вы правы. Я предположил, что функция rand() возвращает значение от 0 до 1, как это делают большинство случайных функций. Кроме того, вы, должно быть, опубликовали свой ответ, пока я редактировал свой, ахах :)
Большое спасибо за ваши ответы! Оба работают хорошо. Однако я обнаружил, что последовательность всегда одна и та же. Каждый раз, когда выходные данные одинаковы, поскольку начальное число одинаковое, функция rand сталкивается с той же проблемой. Как вы думаете, есть ли способ избежать этого и каждый раз создавать новую случайную последовательность?
Если вы используете impureRandom, вам следует пропустить деление на 32767. Причина деления состоит в том, чтобы получить число в интервале [0,1] (поскольку rand() возвращает 0..32767 - тогда как impureRandom уже возвращает вещественное число в [0, 1].