Моделирование
Верный своему прошлому язык Simula содержит набор примитивов для моделирования дискретных событий. Конечно, неслучайно, что первый ОО-язык создавался для моделирования внешнего мира. Сила объектного подхода проявляется особенно ярко именно в этой области.
Моделирующее ПО анализирует и предсказывает поведение некоторой внешней системы: линии сборки, химической реакции, компьютерной операционной системы.
Особенностью моделирования дискретных событий является то, что внешняя система представлена своими состояниями, способными изменяться в ответ на события, происходящие в дискретные моменты времени. При непрерывном моделировании жизнь системы рассматривается как непрерывный процесс, как непрерывно развивающееся состояние. Какой из подходов является лучшим для данной внешней системы, зависит не столько от природы системы - непрерывной или дискретной (часто такая постановка бессмысленна), сколько от моделей, для нее создаваемых.
Еще одним конкурентом моделирования дискретных событий является аналитическое моделирование, где строится математическая модель внешней системы, а затем решаются соответствующие уравнения. При моделировании дискретных событий для предсказания поведения системы на сколько-нибудь значимом периоде времени приходится увеличивать время моделирования и время работы программной системы. Аналитические методы позволяют получать решение на любой заданный момент времени и, следовательно, более эффективны. Однако, как правило, физические системы слишком сложны, чтобы можно было построить реалистичную математическую модель, допускающую аналитическое решение. Тогда моделирование остается единственной возможностью.
Многие внешние системы естественно укладываются в схему моделирования дискретных событий. Примером может служить линия сборки, где типичные события могут включать появление на линии новых деталей, рабочих или машин, выполняющих определенную операцию над деталями, снятие с линии готового продукта, сбой, приводящий к остановке. Моделирование можно использовать для нахождения ответов на вопросы о моделируемых физических системах.
Сколько времени ( в среднем, минимально, максимально, среднее отклонение) потребуется для производства конечного продукта? Как долго данный механизм остается неиспользованным? Каков оптимальный уровень запасов?
Исходные данные для моделирования - это последовательность событий и частота их появлений. Данные можно получить с помощью измерений, производимых на внешней системе. Зачастую их получают в соответствии с заданными статистическими законами, генерируя соответствующие последовательности случайных чисел.
При моделировании вводится понятие модельного времени. Его протекание определяет моменты совершения определенных событий, продолжительность выполнения определенной операции на определенной детали. Модельное время не следует путать со временем вычисления. Для моделирующей системы модельное время - это переменная, значение которой в программе дискретно изменяется. Доступный в языке Simula запрос time позволяет в период выполнения системы получать текущее время и управлять временными событиями.
Компонент time и другие компоненты моделирования содержатся в библиотечном классе SIMULATION, он может использоваться как предок любого класса. Будем называть "классом моделирования" любой класс, являющийся потомком SIMULATION.
В Simula наследование можно применять к блокам: блок, написанный в форме: C begin... end имеет доступ ко всем компонентам, объявленным в классе C. Класс SIMULATION часто используется таким образом как родитель всей программы, а не просто класса. Поэтому можно говорить о "моделирующей программе". |
Процесс может находиться в одном из четырех состояний:
- активный - выполняемый в данный момент;
- приостановленный - ждущий продолжения;
- бездействующий - холостой, или не являющийся частью системы;
- завершенный.
Рис. 17.2. Список событий
Основная операция над процессами - активизация, она планирует активизацию процесса в определенное время, помещая уведомление о событии в список событий. Видимо по синтаксическим причинам эта операция не является вызовом процедуры класса SIMULATION, а специальной инструкцией, использующей ключевое слово activate или reactivate. (Вызов процедуры был бы более согласованным подходом, тем более что фактически стандарт определяет семантику activate в процедурных терминах.) Основная форма инструкции такова:
activate some_process scheduling_clauseгде some_process - непустая сущность типа PROCESS. Необязательный параметр scheduling_clause задается одной из следующих форм:
at some_time delay some_period before another_process after another_processПервые две формы указывают на позицию нового уведомления о событии, задавая время его активизации, вычисляемое как max (time, some_time) для формы at и max (time, time + some_period) в форме delay. Новое уведомление о событии будет внесено в список событий после любого другого события, уже находящегося в перечне с меньшим или таким же временем активизации, если оно не помечено prior.
Последние две формы определяют позицию по отношению к другому процессу в перечне. Отсутствие scheduling_clause эквивалентно delay 0.
Процесс может активизировать себя в более позднее время, указав себя как целевой процесс - some_process. В этом случае ключевое слово должно быть reactivate. Это полезно при запуске задачи внешней системы, требующей на свое выполнение некоторого модельного времени. Если запускается задача, решение которой занимает 3 минуты (180 сек.), то для соответствующего исполнителя - процесса worker - можно задать инструкцию:
reactivate worker delay 180Эта ситуация настолько типична, что для нее введен специальный синтаксис, позволяющий избежать явного вызова самого себя:
hold (180)с точно тем же эффектом.
Вы, вероятно, уже догадались, что процессы реализуются как сопрограммы. Примитивы моделирования внутренне используют рассмотренные выше примитивы сопрограмм. Эффект hold (some_period) можно приблизительно описать (в синтаксисе, похожем на нотацию этой книги, но с расширением resume) как:
-- Вставка нового уведомления о событии в список событий в требуемую позицию: my_new_time := max (time, time + some_period) create my_reactivation_notice.make (Current, my_new_time) event_list.put (my_reactivation_notice) -- Получить первый элемент списка событий и удалить его: next := event_list.first; event_list.remove_first -- Активизировать выбранный процесс, изменяя время при необходимости: time := time.max (next.when); resume next.whatпредполагая следующие объявления:
my_new_time: REAL; my_reactivation_notice, next: EVENT_NOTICE class EVENT_NOTICE creation make feature when: REAL - т.е. время what: PROCESS make (t: REAL; p: PROCESS) is do when := t; what := p end endЕсли процесс приостанавливается, задавая время своей последующей активизации, то выполнение продолжает приостановленный процесс с наиболее ранним временем активизации. Если указанное время активизации этого процесса позже текущего времени, то соответственно изменяется (увеличивается) текущее время.
Примитивы моделирования, хотя они и основаны на примитивах сопрограмм, принадлежат к более высокому уровню абстракции, потому лучше использовать их, а не полагаться непосредственно на механизмы сопрограмм. В частности, можно рассматривать hold (0) как форму resume, благодаря которой можно не определять явным образом процесс для продолжения, а поручить его выбор механизму списка событий.