Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб_работа_МС_2_07.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
4 Мб
Скачать
☆

5. Отчет по работе

1. По результатам выполнения п.2 из раздела 4.2 опишите порядок инициализации объектов-заявок. Поясните содержание слотов. Сравните результаты инициализации при использовании функций queue и myqueue. Сделайте вывод о влиянии функции распределения на неравномерность входного потока и количество инициализируемых заявок. Объясните последовательность запуска правил (запуск называют “зажиганием продукции”), оперируя текущими фактами, их индексами и относительными приоритетами правил.

2. Опишите разработанные функции распределения случайных величин, параметры вызова и возвращаемые значения.

3. Опишите результаты экспериментов, проведенных по п.4 раздела 4.2. Можно ли их обобщить и дать какие-либо рекомендации?

4. Опишите методику и основные моменты программной реализации задачи автоматического составления плана дробного факторного эксперимента и соответствующего командного файла runex2.bat для прогона модели model_can.clp. Обратите внимание на удобство изменения значений переменных при генерации плана эксперимента в сравнении с вручную составленным файлом runex1.bat.

5. Опишите выбор генерирующих соотношений, приведите фрагменты файла ДФЭ_20_11 и макроса, соответствующие командные файлы типа runex2.bat и полученные данные в формате .xml. Сможете ли Вы заметить какие-либо закономерности или связи между собой входных и выходных характеристик, соответствующие теории СМО?

Приложение 1

Пояснения к программе имитационного моделирования

При пользовании данным приложением желательно иметь перед собой напечатанный текст программы model.clp, содержащий комментарии, а также ознакомиться по Приложению 3 с краткими сведениями о языке CLIPS..

Программа состоит из конструкторов: фактов (deffacts), глобальных переменных (defglobal), классов (defclass), пользовательских функций (deffunction), правил (defrule) и обработчиков сообщений классов (defmessage-handler), расположенных в порядке использования в программе. Объявления фактов, глобальных переменных и функций должны предшествовать их использованию в других конструкторах. Исходные факты прокомментированы в тексте программы.

Конструкторы классов ZAYAVKA, CANAL и TEL (заявок, каналов обслуживания и транспортной тележки) содержат перечень слотов с указанием их свойств. Необязательное свойство (default ….) может содержать начальное заданное значение, 0, NIL или ссылаться на значение ранее объявленной глобальной переменной. Свойство (access read-write) слота создает возможность доступа к чтению и записи. Свойство (create-accessor read-write) позволяет создавать неявный обработчик для выполнения операций get и put чтения и записи в слот. Назначение всех слотов классов прокомментировано в тексте программы. После объявления классов идет раздел объявления функций, которые будут использоваться в обработчиках сообщений классов или в правилах. Примеры по программированию функций даны в Приложении 3.

В следующем разделе помещено приоритетное правило start-canal-tel, создающее и инициализирующее объекты классов CANAL и TEL

Объекты создаются с помощью функции (make-instance <имя объекта> of <имя класса> (<имя слота1> <значение>)…..(<имя слотаN> <значение>)). При этом при инициализации необязательно перечислять слоты, значения которых заданы в конструкторе по умолчанию. Они будут проинициализированы автоматически при создании объектов класса. Некоторые слоты могут ссылаться на значения соответствующих глобальных переменных, как это сделано в классе TEL.

Назначение в этом правиле команды типа (bind ?y (create$ ?*obs11* ?*obs12* ?*obs13* ?*obs14* ?*obs15* ?*obs16*)) состоит в объявлении переменной ?y, с которой связывается составное значение (список) чисел, создаваемый функцией create$.

Глобальные переменные типа ?*obs11* содержат время обслуживания в данном канале заявок каждого типа, включая подготовительно-заключительное время 0.5 часа. Переменная ?y затем используется при инициализации одного из слотов объектов класса CANAL. К любому элементу составной переменной (фактически к списку) можно обратиться по его номеру с помощью функции (nth$ ?j), в качестве аргумента которой в данном случае используется предварительно означенная переменная ?j. Значение 0 показывает, что заявки 2-го и 5-го типов в данный узел не попадают.

Следующим приоритетным правилом, которое, как и предыдущее, срабатывает один раз является правил startup. Правило должно выполняться вторым, поэтому имеет следующий приоритет, задаваемый командой (declare (salience 100)). Условиями запуска правила является присутствие в списке исходных фактов (currentj 1) и (routine 1 1). Запрос к этим фактам идет из левой части правила с помощью выражений:

?f <- (currentj ?j &:( <= ?j 6))

(routine ?j $?r)

Запрос (currentj ?j), будет сопоставлен с первым фактом, в результате чего переменная ?j получит значение 1. Это значение позволит во втором подзапросе о маршруте (routine ?j ?$r) конкретизировать значение переменной ?j = 1 и искать соответствующий факт в списке. В результате будет найден второй исходный факт и составная переменная $?r получит значение 1. Левая стрелка в первом подзапросе позволяет связать факт (currentj ?j), с объявляемым указателем адреса ?f , что необходимо для возможности удаления факта в конце правила командой (retract ?f). В первом подзапросе также проверяется выполнение условия, что значение переменной ?j не превышает заданного числа 6 - числа типов заявок (маршрутов).

В первой строке правой, командной части правила функция bind объявляет переменную ?nj и связывает ее с элементом списка, создаваемого функцией create$, номер которого содержится в переменной ?j функции nth$. Последняя служит для доступа к элементу списка. Тем самым в переменной ?nj в данном случае получим число заявок первого типа, содержащееся в глобальной переменной ?*z1*.

Во второй строке объявляется переменная ?n и связывается с результатом вычисления с помощью функции length$ числа элементов списка, содержащегося в составной переменной $?r по ее текущему значению в факте (routine 1 1). Тем самым переменная ?n будет содержать число операций обслуживания для данного типа заявок (маршрута routine), т.е. в данном случае единицу.

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

В четвертой строке объявляемая переменная ?pj связывается с результатом деления периода моделирования Т на число заявок данного типа в переменной ?nj, т.е. получает значение среднего интервала времени между поступлениями заявок.

Далее выполняется цикл по ?i, пока истинны два условия: ?i не превышает числа типов заявок (6) и время поступления очередной заявки меньше периода моделирования. В цикле осуществляется создание объектов класса ZAYAVKA с помощью функции make-instance. Слот времени поступления первой заявки данного типа post получает текущее значение глобальной переменной ?*ta*, которое вначале равно 0. Слот времени активизации заявки tact получает временно значение периода моделирования Т. Оно будет позднее заменено реальным временем активизации правилом time-tact. Остальные слоты означиваются найденными выше значениями переменных. В цикле также вызывается функция (queue ?pj), которая возвращает очередное случайное значение переменной ?*ta*, просуммированное этой функцией с предыдущим значением. В результате создается коллекция объектов-заявок данного типа со случайным возрастающим временем поступления в систему, получающих системные имена gen1, gen2, …gen(?nj), поскольку в отличие от правила start-canal-tel имена объектов-заявок не заданы в явном виде в команде make-instance.

Отметим, что все правило срабатывает в цикле по ?j несколько раз. Для этого в конце правой части правила вновь обнуляется переменная ?*ta* и из списка фактов удаляется факт ?f, связанный с использованным значением ?j, а затем с помощью функции assert в список фактов помещается новый факт (assert (currentj =(+ ?j 1))) с увеличенным на единицу значением ?j. Правило не будет остановлено до тех пор, пока не отработает по всем вновь вводимым фактам currentj, независимо от установленной стратегии разрешения конфликтов. Но в каждом проходе будут использованы новые значения переменных, соответствующие очередному маршруту. В итоге получим коллекцию объектов-заявок всех типов в виде плана запуска со случайными упорядоченными по каждому маршруту значениями времени поступления. Правило перестанет запускаться, когда ?j превысит установленное значение (6).

Далее в тексте программы описаны обработчики сообщений классов CANAL и TEL соответственно compute-proc и compute-time. Обработчики выполняют множество команд пересылки сообщений (send), результатом которых является получение значений слотов и их связывание либо с объявляемой переменной, либо с новым значением слота. Приведем некоторые типичные конструкции.

(bind ?x1(send ?self get-way))

Эта запись означает: связать с объявляемой переменной х1 результат посылки сообщения текущему объекту, имя которого содержится в переменной ?self, получить у него значение слота way.

(bind ?self:tos(+ ?*TTEK* ?g1))

Здесь в качестве переменной используется значение слота tos текущего объекта ?self, которому присваивается результат сложения значений текущего модельного времени ?*TTEK* и времени транспортировки ?g1. Здесь реализуется возможность прямого доступа к слоту с помощью функции bind.

(send ?self:canal put-trans ?g1)

Данная запись означает: послать сообщение объекту, имя которого содержится в слоте canal текущего объекта, установить в слоте trans значение переменной g1.

(send ?self:canal compute-proc)

Здесь посылается сообщение объекту, имя которого содержится в слоте canal текущего объекта (tel является текущим объектом для своего обработчика compute-time), передать управление обработчику compute-proc класса CANAL.

Допустимой является и такая конструкция:

(send ?self:canal put-sum-trans (+ (send ?self:canal get-sum-trans) (send ?self:canal get-trans))) -

послать сообщение объекту, имя которого содержится в слоте canal текущего объекта, установить значение слота sum-trans, суммировав результат обработки двух последующих сообщений. В итоге к значению слота sum-trans будет добавлено значение текущего времени транспортировки из слота trans.

Аналогичным образом работает и счетчик числа выполненных в канале заявок:

(send ?self:canal put-nzay (+ (send ?self:canal get-nzay) 1))

Далее идет группа правил, обслуживающих основной цикл моделирования в шаговом режиме.

Правило time-tact активизируется в начале каждого шага моделирования фактом (time-new), который затем удаляется. Конструкция if-then-else проверяет, не окончилось ли отведенное время моделирования и помещает в базу соответствующие факты. Функция do-for-all-instances предназначена для работы с коллекциями объектов. Она перебирает все объекты-заявки и выбирает из них не активизированные ранее, время поступления которых в систему стало меньше текущего модельного времени, продвигаемого по шагам правилом time. Этим заявкам устанавливается новое время активизации и устанавливается флаг активизации, чтобы в следующем цикле не менять ранее активизированным заявкам время активизации на очередное ТТЕК, что снизило бы их абсолютный приоритет.

Следующим должно активизироваться правило compute-sum-queue, которое подсчитывает накопленные очереди из активизированных заявок к узлам. Для первого запуска правило использует два исходных факта (val 1) и (queue 1 0). В правой части правила объявляется переменная ?tmp, которая связывается с длиной списка, образуемого функцией find-all-instances из активизированных заявок, адресованных данному узлу. Номер адресуемого узла содержится в слоте uz заявки. Далее исходные факты удаляются, очередь к данному узлу добавляется к предыдущему ее значению и новый факт (queue…) помещается в базу. Затем увеличивается на 1 номер узла и операция повторятся, пока число узлов не превысит заданного значения (в данном случае 3).

Следующим в начале каждого шага модельного времени должно активизироваться правило поиска свободных каналов узлов find-free-canals. Условием поиска является наличие факта незанятости тележки (tel free). В правой части правила с помощью функции do-for-all-instances отыскивается поочередно объект-канал ?c, у которого время освобождения и время выхода из ремонта меньше или равно текущему модельному времени ?*TTEK*. Затем в переменную ?x получают номер узла свободного канала, если он найден, и в список фактов добавляют соответствующий факт (free <номер узла> <номер канала>).

Следующее правило concurs1 организует конкурс FIFO среди активизированных заявок, ожидающих обслуживания. Условием активизации правила является наличие фактов незанятости тележки и свободных каналов узлов (хотя бы одного). Функция do-for-instance отыскивает заявку ?b1, у которой узел адресации равен свободному, заявка имеет признак нахождения на складе и активизирована, и не существует другой заявки ?b2 с теми же свойствами и меньшим временем активизации. Последнее условие проверяет логическая функция any-instancep. В итоге переменная ?b1 получит значение индекса заявки, выигравшей конкурс FIFO на обслуживание в данном такте времени. После этого рассылаются многочисленные сообщения: одно – заявке, выигравшей конкурс, остальные каналу обслуживания и тележке. Все эти сообщения прокомментированы в тексте программы моделирования. В конце правила идет удаление исходных фактов, устанавливается факт занятости тележки (tel busy) и вызывается обработчик сообщений тележки compute-time. За работой последнего можно проследить по комментариям в программе или с помощью режима трассировки step при запуске программы. Типовые сообщения были разобраны выше.

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

Набор действий правила concurs2 отличается от предыдущего правила. Он короче и прокомментирован в тексте программы.

Последним правилом цикла является правило time, служащее для продвижения на шаг модельного времени ТТЕК. Оно имеет самый низкий приоритет, так как должно срабатывать последним в цикле. Правило активизируется от факта (next-tact), который установило правило time-tact, и от факта любого состояния тележки (занятого или свободного). В правой части правило увеличивает текущее модельное время на величину 0.05 часа, получает от тележки значение слота времени ее освобождения tos, и в зависимости от отношения tos и нового значения ТТЕК обновляет тот или иной факт о ее состоянии. В конце правило обновляет исходные факты (time new) и (val 1) для выполнения нового цикла при увеличенном значении модельного времени ТТЕК.

Если правило time-tact установило факт (finished), т.е.когда закончилось модельное время, появляется возможность активизации правила open-file, назначением которого является открытие файлов для сохранения результатов прогона модели в форматах txt и xml.

В заключительной части программ от того же факта (finished) активизируются по очереди 3 правила derive-info для каждого узла системы обслуживания соответственно, которые подсчитывают и выводят на экран и в файлы значения всех выходных характеристик. К последним могут быть добавлены и исходные данные для последующего автоматизированного анализа средствами Data Mining. Каждое правило использует для активизации свой факт накопленной (суммировавшейся по шагам) длины очереди (queue 1 ?s), (queue 2 ?s) и (queue 3 ?s). В правой части объявляется переменная ?step, которая связывается с числом шагов (тактов) модельного времени, определяемым путем деления периода моделирования ?*T* на шаг 0.05. Далее объявляется переменная средней длины очереди ?queue, которая связывается с результатом деления накопленной очереди ?s на число шагов. Это одна из важных характеристик обслуживания. Следующая группа объявляемых переменных, инициализируемых нулевыми значениями, необходима для последующего усреднения по всем каналам узла соответствующих выходных характеристик. Если пользователь решит увеличить число каналов в узле (напомним, что для 1-го и 3-го узлов оно равно 1, а для 2-го – трем), то для этой цели предусмотрена переменная ?i цикла расчета по каждому каналу узла, по которой затем производится усреднение некоторых характеристик для узла.

Приложение 2