Скачиваний:
58
Добавлен:
06.02.2016
Размер:
524.8 Кб
Скачать

InvalidateRect(shwnd,null,1);

}

return;

}

2. Замкнутая модель обслуживания с клапаном

 

Описание моделируемого процесса

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

     Так как магазин небольшой, задано максимальное количество людей, которые могут выстроиться в очередь к продавцу. Если очередь достигла предела, дверь в магазин закрывается, и остальные покупатели выстраиваются в очередь перед магазином.

Схема модели

Параметры модели

Параметры

Среднее значение

Число обычных покупателей

800 человек

Число пенсионеров

200 человек

Время расхода продуктов у обычных покупателей

8 часов

Время расхода продуктов у пенсионеров

6 часов

Время обслуживания покупателя продавцом

3 минуты

Максимальное число покупателей в магазине

20 человек

Описание работы модели

     Модель является замкнутой, так как моделируемая система имеет постоянный контингент обслуживания. В такой модели одни и те же транзакты "ходят по кругу", не уничтожаясь в терминаторе.

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

     Приоритет транзакта задается в описании генераторов 1 и 2 для порождающих транзактов. Транзакты - "пенсионеры" имеют в модели приоритет "2", обычные - "1". В описании узла 3 "creat" (мультипликатора) задан параметр "copy", обеспечивающий наследование приоритета порожденными транзактами.

     Семейства транзактов-покупателей генерируются мультипликатором одно за другим в порядке нумерации генераторов порождающих транзактов. Процесс генерации начинается в момент времени "0.0" (см. значение интервала генерации в узлах 1 и 2) и не занимает никакого модельного времени. Таким образом, к моменту начала моделирования все транзакты-жители уже "поселены" в поселок.

     Перед входом в мультипликатор 3 порождающие транзакты получают еще два параметра - число транзактов в порождаемом семействе и среднее время задержки в сервере 5, имитирующем поселок. Это время равно времени расхода продуктов. В зависимости от значения приоритета t->pr порождающему транзакту присваиваются нужные значения этих параметров. Число порождаемых транзактов-покупателей заносится в параметр пользователя целого типа t->iu0, а время расхода продуктов - в параметр пользователя вещественного типа t->ru0. Эти параметры также наследуются порожденными транзактами.

     Терминатор 4 уничтожает отработавшие порождающие транзакты и выключает генераторы из схемы зарядки. Номер генератора, который нужно выключить, определяется опять же по значению приоритета пришедшего в терминатор порождающего транзакта. С помощью команды перенастройки генератора "cheg" в соответствующем генераторе время до генерации следующего транзакта устанавливается равным общему времени моделирования Mod_time.

     Из схемы зарядки порожденные семейства транзактов попадают в многоканальный сервер 5, имитирующий, как уже было сказано выше, поселок. В этом сервере транзакты находятся до истечения заданного времени расхода продуктов. Время обслуживания в сервере "Поселок" задано случайной величиной, распределенной по нормальному закону, поэтому все семейство транзактов из сервера одновременно не выйдет. Далее транзакты переходят в очередь 6, имитирующую очередь перед магазином, и, если ключ 7 открыт, в очередь 8, имитирующую очередь перед продавцом внутри магазина. Потом они попадают в сервер 9, имитирующий продавца, и после обслуживания в нем возвращаются в сервер 5 "Поселок". Для вернувшегося транзакта весь цикл движения по модели повторяется сначала. Если ключ 7 закрыт, транзакты остаются в очереди 6.

     Сервер 9 "Продавец" работает в режиме обслуживания без прерывания (см. пример 1 про обслуживание с прерыванием). Очереди 6 и 8 учитывают значение приоритета пришедшего транзакта.

     Чтобы в очереди 8 не накапливалось больше заданного максимально числа транзактов Q_max, перед нею стоит ключ 7. Закрытием ключа управляет очередь 8. После входа в нее каждого транзакта осуществляется проверка, не достигло ли число находящейся в очереди транзактов заданному максимуму. Если достигло, выполняется команда закрытия ключа "hold". Открытие ключа производится сервером 9 "Продавец" с помощью команды "rels". Не обязательно, что в моделируемой системе дверь открывает именно продавец; важно, с каким событием связано открытие двери. А связано оно с тем, что в очереди к продавцу покупателей станет меньше максимального количества. А это произойдет как раз тогда, когда стоящий первым покупатель перейдет из очереди к продавцу. В модели это событие соответствует входу транзакта в сервер 9.

Текст модели

#include <pilgrim.h>

int Q_max=20; /* Максимальное число людей в магазине */

float Mod_time=7*600.0; /* Время моделирования */

int N1=800; /* Число обычных покупателей */

int N2=200; /* Число пенсионеров */

int Ng; /* Номер генератора */

float T1=480.0; /* Время расхода продуктов у обычных покупателей */

float T2=240.0;/* Время расхода продуктов у пенсионеров*/

float T3=3.0; /* Время работы продавца */

forward /* Время измеряется в минутах */

{

modbeg("Магазин", 9, Mod_time, (long)time(NULL), none, 6, none, 4, 2);

ag("Обычные люди", 1, none, none, 0.0, zero, zero, 3);

ag("Пенсионеры", 2, 1, none, 0.0, zero, zero, 3);

network(dummy, dummy)

{

top(3): if (t->pr == 0) /* генерация обычных покупателей */

{

t->iu0=N1;

t->ru0=T1;

}

else /* генерация пенсионеров */

{

t->iu0=N2;

t->ru0=T2;

}

creat(" Заселение домов", none, t->iu0, copy, 5, 4);

place;

top(4): if (t->pr = = 0) /* выключение генераторов */

Ng=1;

else

Ng=2;

cheg(Ng, none, none, Mod_time, zero, zero, 3);

term("Порождающие");

place;

top(5): serv("Поселок", N1+N2, none, norm, t->ru0, t->ru0/3, zero, 6);

place;

top(6): queue("Очередь перед магазином", prty, 7);

place;

top(7): key("Бабушка на входе", 9);

place;

top(8): queue("Очередь к продавцу", prty, 9);

clcode /* Если число пок-лей в очереди */

if (addr[8]->tn == Q_max)/* достигло предела*/

hold(7); /* закрыть дверь */

place;

top(9): serv("Продавец", 1, none, norm, T3, T3/3, zero, 5);

clcode /* Покупатель покинул очередь */

rels(7); /* открыть дверь для нового */

place;

fault(123);

}

modend("pilgrim.rep", 1, 12, page);

return 0;

5. Пример управления маршрутом транзакта

 

Описание моделируемого процесса

     Имеется автобусный парк, который обслуживает два маршрута. На каждом маршруте одновременно должно находиться определенное число автобусов.

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

Схема модели

Параметры модели

Общее число автобусов в парке

Необходимое число автобусов на маршруте 1

Необходимое число автобусов на маршруте 2

Среднее время рейса по маршруту 1

Среднее время рейса по маршруту 2

Количество диспетчеров в парке

Время обслуживания автобуса диспетчером

Описание работы модели

     Модель является замкнутой и включает ту же схему зарядки, что и модель магазина из п.2. Из схемы зарядки транзакты поступают в очередь 1, имитирующую парк. Далее каждый транзакт попадает в сервер 2, имитирующий работу диспетчера. Число каналов в сервере равно числу диспетчеров. Время задержки транзакта равно времени обслуживания автобуса диспетчером. Оно задано случайной величиной, распределенной по нормальному закону.

     Номер узла, в который должен перейти транзакт из сервера 2, задан переменной пользователя Forw. Перед входом транзакта в сервер 2 происходит настройка этого параметра. Сначала проверяется число транзактов в сервере 3, имитирующем маршрут 1. Число каналов в нем равно требуемому числу автобусов на маршруте. Время задержки есть время в рейсе по маршруту 1. Оно также распределено по нормальному закону.

     Если в момент входа транзакта в сервер 2 число транзактов в сервере 3 меньше требуемого, переменная Forw получает значение 3 (автобус отправляется на маршрут 1). Если все каналы сервера 3 заняты, аналогичным образом проверяется сервер 4, имитирующий маршрут 2. Если и там транзакты не требуются, транзакт из сервера 2 отправляется обратно в очередь 1 (автобус остается в парке). В этом случае приоритет транзакта получает значение "1" (исходное значение, присвоенное в схеме зарядки - "0"), и транзакт встает не в конец, а в начало очереди. Тогда именно этот транзакт-автобус будет отправлен "в рейс" при возникновении потребности на каком-либо маршруте. Иначе автобусы, ожидающие отправки в рейс, будут вхолостую ездить в парке по кругу. В описании очереди 1 задан флажок обработки приоритетов "prty".

     В серверах 3 и 4 приоритет транзакта опять получает значение "0", и после выхода из них транзакт встает в конец очереди 1. Канал сервера-"маршрута" освобождается, и сервер-"диспетчер" отправляет туда транзакт, стоящий первым в очереди 1.

Текст модели

#include <pilgrim.h>

float T1; /* Время рейса по маршруту 1 */

float T2; /* Время рейса по маршруту 2 */

float T3; /* Время обслуживания автобуса диспетчером */

int N1; /* Требуемое число автобусов на маршруте 1 */

int N2; /* Требуемое число автобусов нв маршруте 2 */

int N; /* Общее число автобусов в парке */

int Q; /* Число диспетчеров */

int Forw;

/* Стандартное начало модели и схема зарядки */

...

top(1): queue("Парк",prty,2);

place;

top(2): if addr[3]->tn < N1

Forw=3; /* на маршрут 1 */

else if addr[4]->tn < N2

Forw=4; /* на маршрут 2 */

else /* оставить в парке */

{

t->pr=1; /* в начало очереди */

Forw=1; /* оставить в парке */

}

serv("Диспетчер",Q,none,norm,T3,T3/3,zero,Forw);

place;

top(3): t->pr=0; /* сброс приоритета */

serv("Маршрут 1",N1,none,norm,T1,T1/3,zero,1);

place;

top(4): t->pr=0;

serv("Маршрут 2",N2,none,norm,T2,T2/3,zero,1);

place;

/* Стандартный конец модели */

...

6. Работа с ресурсом. Узел "attach"

 

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

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

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

 

     Узел "Attach" имеет следующие параметры.

  1. Символическое имя узла - тип хранящегося ресурса.

  2. Количество единиц ресурса, которое необходимо выдать транзакту. Этот параметр может иметь как постоянное, так и переменное значение - в зависимости от постановки задачи.

  3. Флажок учета приоритета запросов - "prty" или "none".

  4. Номер узла "Manage".

     Полученный на складе ресурс транзакт "носит" по модели и все, что он может с ним сделать - это вернуть обратно на склад. Вернуть ресурс транзакт может из любого узла модели с помощью команды "detach". Возвращать ресурс не обязательно. Кроме того, из любого узла можно пополнить запас ресурса на любом складе с помощью команды "supply". Параметрами команды являются номер склада и количество дополнительных единиц ресурса. Начальное помещение ресурса на склад производится также с помощью этой команды. Она указывается в тексте модели после описания генераторов.

 

     6.1. Непополняемый возвращаемый ресурс

     6.2. Пополняемый невозвращаемый ресурс

6.1. Непополняемый возвращаемый ресурс

 

Описание моделируемого процесса

     В качестве примера приведем простейшую модель пункта проката. Ресурсом здесь являются выдаваемые клиенту предметы (например, фотоаппараты на время отпуска). По прошествии определенного времени клиент возвращает взятое в пункт проката.

Схема модели

Параметры модели

Интервал прихода клиентов

Количество фотоаппаратов в пункте проката

Максимальное количество выдаваемых клиенту фотоаппаратов

Максимальное время пользования фотоаппаратом

Описание работы модели

     Выйдя из генератора 1, транзакт-клиент попадает в узел "Attach" 2, где требует некоторое количество единиц ресурса. Флажок учета приоритетов установлен, чтобы клиент, ожидающий поступления большого количества фотоаппаратов, не блокировал обслуживание других клиентов.

     Если ресурс транзакту выдан, он попадает в сервер 4, где находится в течение времени пользования прокатом, установленного для соответствующего клиента. после этого транзакт попадает в терминатор 5, откуда выдается команда возврата взятого ресурса в узел "Attach".

     Сервер 4 является многоканальным. Число каналов равно числу клиентов, которые одновременно могут пользоваться прокатом. Время задержки транзакта в сервере, как и количество единиц ресурса, выдаваемого транзакту, является случайной величиной, равномерно распределенной на отрезке от 0 до максимального значения. Функция "rundum()" в описании узла "Attach" возвращает случайным образом выбранный коэффициент от 0 до 1. Вообще говоря, генератор случайных чисел "rundum()" - это то же самое, что генератор "unif(0.5, 0.5)".

Текст модели

#include <pilgrim.h>

float T_Kl; /* Интервал прихода клиентов */

float Max_T; /* Макс. время пользования ресурсом */

int Max_Q; /* Макс. число единиц выдаваемого ресурса */

int Q; /* Исходное число единиц ресурса на складе */

forward

{

modbeg("Пункт проката",...);

ag("Клиенты", 1, none, expo, T_Kl, zero, zero, 2);

supply(2, Q); /* Начальное помещение ресурса на склад */

network(...)

{

top(2): attach("Склад", rundum()*Max_Q, prty, 3);

place;

top(3): manage("Есть ресурс?", 4);

place;

top(4): serv("Пользование ресурсом", 32000, none, unif, Max_T, Max_T/3, zero,5);

place;

top(5): term("Возврат ресурса");

clcode

detach();

fault(123);

}

modend(...);

}

6.2. Пополняемый невозвращаемый ресурс

 

Описание моделируемого процесса

     Примером такого ресурса служит семейный бюджет. Он пополняется за счет зарплаты. Из бюджета берутся деньги на покупки. Если на покупку не хватает денег, семья копит средства и временно ничего не покупает.

Схема модели

Параметры модели

Интервал принятия решений о покупке

Максимальная сумма покупки

Период получения зарплаты

Размер зарплаты

Описание работы модели

     Цепочка узлов (1-2-3-4) в аналогична схеме из примера 6 а) за исключением сервера 4. Транзакт - это решение сделать покупку. Узел "Attach" 2 играет роль "кошелька", в котором хранятся деньги. Узел "Manage" проверяет, достаточно ли в кошельке денег на очередную покупку. Флажок учета приоритетов запросов в узле "Attach" не установлен, чтобы выполнялось условия накопления денег на крупные покупки. Пока очередному транзакту-покупке не будет выдан ресурс, другим транзактам ресурс выдаваться не будет. Если денег достаточно, транзакт переходит в терминатор 4, иначе остается в узле "Attach". Узлы 5 и 6 имитируют поступление зарплаты. Интервал генератора 5 равен периоду выплаты зарплаты. После попадания транзакта в терминатор 6 выдается команда "supply", увеличивающая объем ресурса в узле "Attach" на размер полученной зарплаты.

35

Соседние файлы в папке Лабораторные_занятия