Главная страница
Навигация по странице:

  • Действие при запуске

  • Модификация алгоритма управления запасами

  • Свойства : комментарий

  • Работа с динамическими событиями в диаграмме действия

  • Динамическое событие (Dynamic Event

  • Комментарий

  • Учет случаев возникновения дефицита Добавим в модель элемент Текст

  • Динамическом событии RetReplenishment. Добавим параметр time, который соответствует сроку доставки: Добавим код в окно Действие

  • Добавление данных на окно презентации Добавим на окно презентации текстовые поля, отображающие текущий уровень издержек: Текст

  • Оптимизационный эксперимент Базовые настройки

  • Оптимизация : 56 Переходим в режим редактирования оптимизационного эксперимента: 57 Выбираем количество итераций

  • Репликации

  • Основные

  • Уточнение величин параметров

  • Случайное начальное число (уникальные «прогоны»)

  • Экономический анализ. Разработка имитационных моделей управления запасами в цепях поставок Москва 2011 2 Введение


    Скачать 3.44 Mb.
    НазваниеРазработка имитационных моделей управления запасами в цепях поставок Москва 2011 2 Введение
    АнкорЭкономический анализ
    Дата12.05.2023
    Размер3.44 Mb.
    Формат файлаpdf
    Имя файлаRozhkov_Designing_Simulation_Models_For_Inventory_Management_Ana.pdf
    ТипПрактикум
    #1125745
    страница2 из 4
    1   2   3   4
    Редактирование класса Main
    Добавим в класс Main параметры координат дистрибьютора distrCoordx и distrCoord типа int, равные 50 каждый:

    33
    Отредактируем класс Retailer. Добавим параметр retDist типа double, который будет хранить расстояние между дистрибьютором и розничной точкой.
    Меняем тип параметра currentDemand на double.
    Добавим в Действие при запуске класса Main код инициализации дистрибьютора:
    Distributor b = add_distributor(); b.setXY(4*distrCoordx,4*distrCoordy);
    Также рассчитаем значение параметра retDist по геометрической формуле расстояния между двумя точками: a.retDist = sqrt(pow(retailCoordx-distrCoordx,2)+ pow(retailCoordy-distrCoordy,2) );
    Функция sqrt используется для взятия квадратного корня, pow – Для возведения числа степень – в данном случае в квадрат[1,p11].

    34
    Запустим модель:
    На презентации появился квадрат зеленого цвета, условно соответствующий дистрибьютору.
    Добавим инициализацию агентов класса Truck в Действие при
    запуске класса Main:
    Truck d = add_truck(); d.setXY(4*distrCoordx,4*distrCoordy); d.rectangle.setVisible(false);
    Анимация модели будет организована таким образом, что транспортное средство (ТС) отображается лишь в процессе перемещения от дистрибьютора к розничной точке. Поэтому при запуске модели ТС должно находиться на тех же координатах, что и дистрибьютор, но не быть видимым.

    35
    Метод d.rectangle.setVisible(false) скрывает объект на презентации.
    При заказе транспортное средство, обслуживающее маршрут доставки, становится «видимым» и движется по карте в направлении получателя.
    После того, как конечная точка маршрута достигнута, транспортное средство вновь становится «невидимым» и перемещается в начальную точку.
    Генерация спроса
    В новой версии модели спрос генерируется нормальным распределением. Параметры распределения: normal(18,80)
    Добавим в класс Main две переменные параметров спроса: demandStd
    – стандартное отклонение (18) и demandMean – математическое ожидание (80) .
    Отредактируем событие ordering:

    36 retailer.get(0).currentDemand = round( max
    (normal(demandStd,demandMean),0));
    В данном выражении используются три формулы. Нормальное распределение задается формулой normal(x,y), где x – это стандартное отклонение, y – математическое ожидание. Функция max() используется для сравнения сгенерированного нормальным распределением значения и нуля.
    Если убрать данную функцию, то модель иногда будет генерировать отрицательный спрос, что недопустимо. Функция round() используется для округления дробных значений. Таким образом, можно считать, что спрос рассчитывается как целые неотрицательные числа, сгенерированные нормальным распределением.
    Модификация алгоритма управления запасами
    В модель были добавлены два важных фактора:
    1.учет времени выполнения заказа (LT);
    2.вероятностная структура спроса.
    Эти факторы требуют более сложной логики для корректной работы модели. Существующий алгоритм будет работать некорректно. В нынешней версии перезаказ выполняется при уровне запаса, равном нулю. Если спрос генерируется нормальным распределением, то, например, при запасе 60 может быть сгенерировано значение спроса 130, и тогда запас составит -70, и перезаказ выполнен не будет. Кроме того, отрицательный уровень запаса в модели недопустим. Поэтому внесем изменения в событие ordering. Учет

    37 вероятностных факторов во многих случаях заставляет пересматривать работу алгоритма.
    При вероятностном типе спроса нужно делать заказ при достижении порогового уровня ROP (Reorder Point). Тогда будет некоторый диапазон значений между ROP и нулем, когда следует выполнить заказ. Добавим в класс Main переменную для данного параметра управления запасами. Тип переменной int, значение по умолчанию: 500.

    38
    Спрос генерируется ежедневно. Сначала проверяется условие, может ли заказ быть выполнен. Если спрос превышает запас, то записываются данные о дефиците. Проверяется условие, что заказ не находится в пути.
    Если оно выполняется, формируется заказ дистрибьютору в размере величины EOQ. Если запас позволяет обслужить спрос, то величина запаса уменьшается на величину спроса. После этого проверяется условие, не достигнут ли пороговый уровень запаса ROP. Если текущий запас ниже величины ROP и заказ уже не находится в пути, формируется новый заказ в размере величины EOQ. Проверка нахождения заказа в пути нужна потому, что срок доставки заказа больше (5,65), чем интервал между генерациями спроса (1).
    Для реализации этого значительно более сложного алгоритма используем средства графического моделирования в AnyLogic. Опишем алгоритм в виде диаграммы действий actionChart().
    Удалим старый алгоритм:

    39
    Добавим новую строку: actionChart();
    Строка actionChart() это вызов функции передачи дальнейшей обработки события в диаграмму действий. Диаграмма действий это инструмент для более удобного визуального представления алгоритмов.
    Модули диаграммы действий реализованы в рамках нотации языка графического описания UML. В рассматриваемой нами модели алгоритм обработки материального потока достаточно сложный, поэтому для большей наглядности реализуем его в диаграмме действий. Нет никакой разницы в обработке кода написанного внутри и кода, реализованного с помощью actionChart().
    Диаграмма действий
    Создадим диаграмму действий для класса Main:

    40
    Оставляем все параметры по умолчанию:
    Если бы мы решили сменить имя диаграммы действий, то ссылку на него следовало бы поменять и в событии ordering. Чтобы при смене имени оно изменялось во всех участках кода, используется комбинация клавиш
    Ctrl+Enter [1,p12].
    Сначала проверяется условие, может ли быть обслужен текущий спрос.
    Добавляем модуль принятия решения:

    41
    Свойства: комментарий: Спрос превышает запас ритейлера?, условие: retailer.get(0).currentDemand > retStock
    Сравниваются величины текущего спроса и текущего уровня запаса.
    Дефицит возможен по причине того, что спрос генерируется нормальным распределением, и во время доставки заказа спрос может превысить запас. Добавим в класс Main переменную для учета случаев возникновения дефицита. Назовем еѐ retShortage, тип: int:
    Добавляем элемент Код панели Диаграмма действий по ветви true:
    Свойства: комментарий: Обновление дефицита, код: retShortage++;
    Переменная retShortage увеличивается на единицу.

    42
    Продолжаем движение по ветви true. Добавляем еще один модуль принятия решения:
    Свойства: комментарий: Нет заказа в пути?, условие: truck.get(0).isMoving() == false
    Чтобы проверять, находится ли заказ в пути, можно создать логическую переменную, но мы будем отслеживать перемещение транспортных средств. Если заказ обрабатывается, то «транспортное средство», его обслуживающее, будет перемещаться на презентации модели.
    Метод isMoving() возвращает значение false, если объект не движется
    (ситуация 2) (движение задается методом moveTo()) и true в противном случае (ситуация 1).
    Транспортное средство находится в пути:

    43
    Транспортное средство не находится в пути:
    Работа с динамическими событиями в диаграмме действия
    Время выполнения доставки заказа от дистрибьютора до розничной точки определяется расстоянием между ними. За один день транспортное средство преодолевает 10 единиц расстояния, поэтому время от момента заказа до выполнения доставки рассчитывается как Расстояние между
    отправителем и получателем/10. Для планирования подобных событий используется элемент Динамическое событие (Dynamic Event). Добавим его в окно редактирования модели:

    44 retStock+=EOQ; truck.get(0).jumpTo(distributor.get(0).getX(),distribut or.get(0).getY()); truck.get(0).rectangle.setVisible(false);
    В момент наступления события уровень запаса розничной точки увеличивается на величину EOQ, транспортное средство перестает отображаться на презентации и мгновенно перемещается к дистрибьютору методом jumpTo().
    Возвращаемся к редактированию диаграммы действий:
    Добавляем Код, продолжая движение по ветви true:
    Свойства: комментарий: Обработка заказа дистрибьютором, код:

    45 create_RetReplenishment(retailer.get(0).retDist/10); truck.get(0).rectangle.setVisible(true); truck.get(0).moveTo(retailer.get(0).getX(),retailer.get
    (0).getY());
    Создается динамическое событие RetReplenishment с заданными параметрами. Параметр в скобках определяет разницу времени между текущим моментом и наступлением события.
    После этого запускается анимация доставки. Метод setVisible делает транспортное средство видимым, метод moveTo(x,y) перемещает транспортное средство в место расположения розничной точки.
    Теперь перейдем к редактированию ветви false первого модуля принятия решения «Спрос превышает запас ритейлера?». Добавляем элемент
    Код:
    Комментарий: Обновление уровня запаса ритейлера, код: retStock-= retailer.get(0).currentDemand;
    Запас розничной точки уменьшается на величину потребительского спроса.
    Добавляем модуль принятия решения (последний в этой диаграмме действий):

    46
    Комментарий: Заказ ритейлера меньше порогового уровня и нет заказа в пути?,код: retStock < ROP && truck.get(0).isMoving() == false
    Первая часть условия сравнивает уровень запаса с пороговым уровнем, вторая проверяет, находится ли заказ в пути. Для объединения двух условий используется знак «&&», соответствующий логическому знаку «И»
    (конъюнкции).[1,p19].
    Добавляем код по ветви true принятия решения:
    Копируем элемент Обработка заказа дистрибьютором и вставляем его на ветви true.
    Теперь алгоритм выглядит следующим образом:

    47
    Добавим на Временной график пороговый уровень запаса:
    Теперь при запуске модели можно отслеживать момент перезаказа на графике.
    Запускаем модель:

    48
    Окно презентации стало содержать анимацию процесса доставки.
    Также на графике видно, что спрос варьируется в зависимости от периода.
    Начальный уровень запаса retStock меньше порогового уровня запаса. Для того чтобы, начиная с первого периода, система работала в «нормальном» режиме, требуются два условия:
    - величина EOQ должна превышать ROP
    - начальный уровень запаса retStock должен быть равен EOQ+ROP.
    Изменим величину EOQ:600 и добавим инициализацию запаса в модель:

    49 retStock=EOQ+ROP;
    Учет случаев возникновения дефицита
    Добавим в модель элемент Текст, который будет отображать количество случаев дефицита. Расположим его над графиком:
    Текст: retShortage
    При данных настройках модели за время работы не будет зафиксировано ни одного случая дефицита.
    Если поменять параметр
    Конечное время на 1000, то получим 7 случаев дефицита:

    50
    Данный пример демонстрирует важность выбора срока работы модели для оценки вероятности наступления события.
    Учет издержек
    Издержки на хранение рассчитываются каждый период, издержки на транспортировку – по факту выполнения поставки. Ставка на хранение одной единицы запаса в течение одного периода составляет 5 единиц, ставка на

    51 транспортировку зависит от расстояния между дистрибьютором и розничной точкой и составляет 5000 единиц за 10 единиц пройденного расстояния.
    Добавим в класс Retailer параметры ставок retholdingrate и rettrrate:
    Тип обоих параметров: double. Значения по умолчанию: retholdingrate:5, rettrrate:5000.
    Добавим в класс Main переменные для учета текущего уровня издержек:
    Тип всех трех переменных double. retHoldingcost – текущие издержки на хранение, retTrcost – текущие транспортные издержки, totalCost – общие издержки.
    Отредактируем событие ordering: retHoldingcost+=retStock*retailer.get(0).retholdingrate
    ; totalCost=retHoldingcost+retTrcost;

    52
    Таким образом, каждый период сначала рассчитываются издержки на хранение за текущий период, потом рассчитываются общие издержки: суммируются транспортные издержки и издержки на хранение.
    Расчет транспортных издержек проведем в Динамическом событии
    RetReplenishment. Добавим параметр time, который соответствует сроку доставки:
    Добавим код в окно Действие: retTrcost+=time*retailer.get(0).rettrrate;
    При создании динамического события параметр указывается после времени, через которое оно должно произойти.
    Например,
    RetReplenishment(x,y). В данном случае x – разница между модельным временем наступления события и текущим моментом, y – значение параметра time, который был дополнительно добавлен.

    53
    Отредактируем код генерации динамического события в диаграмме состояний: create_RetReplenishment(retailer.get(0).retDist/10,reta iler.get(0).retDist/10);
    Добавление данных на окно презентации
    Добавим на окно презентации текстовые поля, отображающие текущий уровень издержек:
    Текст:

    54
    «Издержки на хранение »+round(retHoldingcost)
    «Издержки на транспортировку »+ round(retTrcost)
    «Общие издержки »+round(totalCost)
    В AnyLogic есть возможность комбинировать текст и значения переменных в одной строке. Знак «+» связывает элементы строки, текст в кавычках определяется как статический текст[1,p20].
    Добавим подобный
    «комментарий» к текстовому полю, отображающему уровень дефицита.
    Запустим модель:
    Теперь отображаются и динамически обновляются основные параметры производительности модели.

    55
    Оптимизационный эксперимент
    Базовые настройки
    Найдем значения ROP и EOQ, при которых общие издержки totalCost минимальны. Для этого создадим оптимизационный эксперимент. Более подробную информацию об оптимизационных экспериментах можно получить в справочной системе программы.
    Добавляем оптимизационный эксперимент:
    Выбираем Оптимизация:

    56
    Переходим в режим редактирования оптимизационного эксперимента:

    57
    Выбираем количество итераций: 10000. В оптимизационном эксперименте класс Main указан как корневой (root), поэтому минимизируем функцию общих издержек root.totalCost.
    Далее настраиваем изменяемые параметры:
    Меняем Тип каждого из параметров EOQ и ROP на дискретный. Шаг изменения параметров запасов установим равным 50, диапазон изменения параметров:
    EOQ: 100…3000
    ROP: 100…3000
    Одно из ограничений модели: ни у одной розничной точки количество случаев возникновения дефицита не должно превышать 15 раз за 1000 дней
    (1,5%).
    Перейдем к пункту Ограничения оптимизационного эксперимента:

    58
    Значение переменной retShortage не должно превышать 15.
    Величина оптимального размера заказа не должна быть ниже порогового уровня запаса.
    В пункте Репликации выбираем Использовать репликации, Кол-во
    репликаций за итерацию:3. Каждое решение будет «прогнано»
    (рассчитано) три раза при различных начальных значениях генератора случайных чисел.
    Использование репликаций замедляет поиск решения, но увеличивает уровень статистической значимости результата. Следует помнить, что из-за вероятностной структуры спроса при заданных параметрах не всегда будут

    59 выполняться ограничения. Чем больше репликаций проведено для каждого набора данных, тем в большем проценте прогонов модели будут выполняться ограничения.
    Вернемся к пункту свойств Основные и нажмем кнопку Создать
    интерфейс:
    Корректируем расположение элементов:

    60
    После этого запускаем оптимизационный эксперимент:
    Поиск оптимального решения представлен в отдельном окне:
    Найденные решения EOQ:950, ROP:500.
    Уточнение величин параметров
    Сузим диапазон поиска и уменьшим шаг изменения параметров. Если учесть, что в эксперименте шаг изменения параметров был 50 единиц, то

    61 уточненное оптимальное решение должно находиться в диапазоне 900-
    1000 для EOQ и 450-550 для ROP. Поменяем шаг на 10 единиц.
    Запустим эксперимент с новыми параметрами:
    Общее количество прогонов в данном эксперименте составит 121 итерацию (11*11)

    62
    В данном случае оптимальные значения составили EOQ:970 и
    ROP:470.
    При запуске оптимизационного эксперимента используется один и тот же набор случайных значений:
    Поменяем настройки: выберем пункт Случайное начальное число
    (уникальные «прогоны»).
    Запустим оптимизационный эксперимент еще несколько раз. В каждом случае оптиальное решение будет находиться в диапазоне 900…1000 и
    450…550, и значение целевой функции также будет немного отличаться.

    63
    Данный пример иллюстрирует одну из особенностей имитационного моделирования – если с каждым новым запуском используются различные начальные параметры генератора случайных чисел, то значения выходных данных модели (в том числе и целевая функция totalCost) будут варьироваться.
    Есть множество субоптимальных значений ROP и EOQ, при которых значение целевой функции издержек изменяется незначительно.
    Задания:
    1)Рассчитайте аналитически оптимальные параметры управления запасами при помощи формулы EOQ и формулы расчета страхового запаса при

    64 вероятностной структуре спроса и сравните с результатом оптимизационного эксперимента.
    2)Измените тип распределения спроса на треугольное распределение[3] triangular(0,demandMean*3,demandMean) и проведите оптимизационный эксперимент. Как и почему изменились параметры управления запасами и ожидаемые издержки?
    3)Постройте график ожидаемых издержек системы при уровне сервиса 80%,
    90%, 95%, 98.5%, 99,5%
    1   2   3   4


    написать администратору сайта