Использование условных операторов в Dymola

Я новичок в 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;

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Есть ряд проблем. Сначала исправленный код:

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;

Далее список изменений:

  • Должны быть объявлены функции, в частности функции, которые не возвращают Real.
  • E — целое число, а не действительное число, что также позволяет сравнивать.
  • Уравнения в Modelica работают иначе, чем алгоритмы на других языках. Используйте pre(E) для доступа к предыдущему значению E.
  • Операторы if должны заканчиваться предложением else, даже если они логически исчерпывают все возможности (если только условие не является вычислимым выражением параметра).
  • Функции, которые возвращают разные значения для одного и того же ввода, следует объявлять как 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) позволяет избежать алгебраического цикла,
  • последний оператор if должен быть else.

Если вы используете impureRandom, вам следует пропустить деление на 32767. Причина деления состоит в том, чтобы получить число в интервале [0,1] (поскольку rand() возвращает 0..32767 - тогда как impureRandom уже возвращает вещественное число в [0, 1].

Hans Olsson 24.06.2024 11:07

Вы правы. Я предположил, что функция rand() возвращает значение от 0 до 1, как это делают большинство случайных функций. Кроме того, вы, должно быть, опубликовали свой ответ, пока я редактировал свой, ахах :)

Clement44 24.06.2024 13:41

Большое спасибо за ваши ответы! Оба работают хорошо. Однако я обнаружил, что последовательность всегда одна и та же. Каждый раз, когда выходные данные одинаковы, поскольку начальное число одинаковое, функция rand сталкивается с той же проблемой. Как вы думаете, есть ли способ избежать этого и каждый раз создавать новую случайную последовательность?

Julien Biancucci 25.06.2024 15:31

Другие вопросы по теме