Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4086 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Лекция 17:

От Simula к Java и далее: основные ОО-языки и окружения

Моделирование

Верный своему прошлому язык Simula содержит набор примитивов для моделирования дискретных событий. Конечно, неслучайно, что первый ОО-язык создавался для моделирования внешнего мира. Сила объектного подхода проявляется особенно ярко именно в этой области.

Моделирующее ПО анализирует и предсказывает поведение некоторой внешней системы: линии сборки, химической реакции, компьютерной операционной системы.

Особенностью моделирования дискретных событий является то, что внешняя система представлена своими состояниями, способными изменяться в ответ на события, происходящие в дискретные моменты времени. При непрерывном моделировании жизнь системы рассматривается как непрерывный процесс, как непрерывно развивающееся состояние. Какой из подходов является лучшим для данной внешней системы, зависит не столько от природы системы - непрерывной или дискретной (часто такая постановка бессмысленна), сколько от моделей, для нее создаваемых.

Еще одним конкурентом моделирования дискретных событий является аналитическое моделирование, где строится математическая модель внешней системы, а затем решаются соответствующие уравнения. При моделировании дискретных событий для предсказания поведения системы на сколько-нибудь значимом периоде времени приходится увеличивать время моделирования и время работы программной системы. Аналитические методы позволяют получать решение на любой заданный момент времени и, следовательно, более эффективны. Однако, как правило, физические системы слишком сложны, чтобы можно было построить реалистичную математическую модель, допускающую аналитическое решение. Тогда моделирование остается единственной возможностью.

Многие внешние системы естественно укладываются в схему моделирования дискретных событий. Примером может служить линия сборки, где типичные события могут включать появление на линии новых деталей, рабочих или машин, выполняющих определенную операцию над деталями, снятие с линии готового продукта, сбой, приводящий к остановке. Моделирование можно использовать для нахождения ответов на вопросы о моделируемых физических системах. Сколько времени (в среднем, минимально, максимально, среднее отклонение) потребуется для производства конечного продукта? Как долго данный механизм остается неиспользованным? Каков оптимальный уровень запасов?

Исходные данные для моделирования - это последовательность событий и частота их появлений. Данные можно получить с помощью измерений, производимых на внешней системе. Зачастую их получают в соответствии с заданными статистическими законами, генерируя соответствующие последовательности случайных чисел.

При моделировании вводится понятие модельного времени. Его протекание определяет моменты совершения определенных событий, продолжительность выполнения определенной операции на определенной детали. Модельное время не следует путать со временем вычисления. Для моделирующей системы модельное время - это переменная, значение которой в программе дискретно изменяется. Доступный в языке Simula запрос time позволяет в период выполнения системы получать текущее время и управлять временными событиями.

Компонент time и другие компоненты моделирования содержатся в библиотечном классе SIMULATION, он может использоваться как предок любого класса. Будем называть "классом моделирования" любой класс, являющийся потомком SIMULATION.

В Simula наследование можно применять к блокам: блок, написанный в форме: C begin... end имеет доступ ко всем компонентам, объявленным в классе C. Класс SIMULATION часто используется таким образом как родитель всей программы, а не просто класса. Поэтому можно говорить о "моделирующей программе".

Класс SIMULATION содержит объявление класса PROCESS. (Как уже отмечалось, объявления классов в Simula могут быть вложенными.) Его потомки - классы моделирования - могут объявлять потомков PROCESS, их будем называть "классами процессов", а их экземпляры - просто "процессами". Экземпляр PROCESS задает при моделировании процесс внешней системы. Наряду с другими свойствами процессы могут объединяться в связный список (что означает, что PROCESS - это потомок некоторого класса Simula, являющегося эквивалентом класса LINKABLE ). Процесс может находиться в одном из четырех состояний:

  • активный - выполняемый в данный момент;
  • приостановленный - ждущий продолжения;
  • бездействующий - холостой, или не являющийся частью системы;
  • завершенный.

Любое моделирование (то есть любой экземпляр потомка SIMULATION ) поддерживает список событий (event list), содержащий уведомления о событиях (event notices). Каждое уведомление - это пара < process, activation_time >, где activation_time означает время активизации процесса process. (Здесь и далее любое упоминание о времени, так же как слова "когда" или "в настоящее время", относится к модельному времени - времени внешней системы, доступному через time.) Список событий сортируется по возрастанию activation_time ; первый процесс активный, все остальные приостановлены. Незавершенные процессы, которых нет в списке, являются бездействующими.

Список событий

Рис. 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, благодаря которой можно не определять явным образом процесс для продолжения, а поручить его выбор механизму списка событий.

Пример моделирования

Классы процессов и примитивы моделирования дают элегантный механизм моделирования процессов внешнего мира. Рассмотрим в качестве иллюстрации исполнителя, которому предлагается выполнять одну из двух задач. Обе требуют некоторого времени; вторая требует включения машины m, работающей 5 минут, и ожидания, пока машина выполнит свою работу.

PROCESS class WORKER begin
    while true do begin
        "Получить следующую задачу типа i и время ее выполнения d";
        if i = 2 then
            activate m delay 300; reactivate this WORKER after m;
        end;
        hold (d)
    end while
end WORKER

Операция "получить тип и продолжительность следующей задачи" обычно получает запрашиваемые величины от генератора псевдослучайных чисел, используя определенное статистическое распределение. Библиотека Simula включает ряд генераторов для типичных законов распределения. Предполагается, что в данном примере m - это экземпляр некоторого класса процесса MACHINE, представляющий поведение машин. Все действующие субъекты моделирования равным образом представляются классами процессов.

Simula: оценка

Как и Algol 60, язык Simula знаменателен не столько своим коммерческим успехом, сколько интеллектуальным влиянием. Это очевидно и в теории (абстрактные типы данных), и в практике, где большинство языковых разработок последних двух десятилетий является его потомками - либо детьми, либо внуками его идей. Большой коммерческий успех не пришел по ряду причин, но самая важная и очевидная, заслуживающая лишь сожаления, состоит в том что, как и многие значительные изобретения до него, Simula опередил свое время. Хотя многие сразу увидели потенциальную ценность его идей, в целом программистское сообщество не было к нему готово.

Спустя тридцать лет, как ясно из предыдущего описания, многие идеи языка все еще остаются актуальными.