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

  • Задачи

  • Изменение алгоритма управления запасами

  • Модуль

  • Добавление элементов презентации Поменяем параметры Временного графика : 77 Добавим линию

  • Количество

  • Запись данных о ежедневном уровне запасов в текстовый файл

  • Оптимизационный эксперимент Ограничения

  • Поиск решения 88 Как мы видим, после определенного момента целевая функция (выделена синим цветом на графике) практически не улучшает значение. Задания

  • 2.3 Расширенная модель цепи поставок Описание задачи

  • Добавление класса поставщика

  • Цвет заливки

  • Модификация класса Main

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


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

    65
    Где и координаты розничной точки, а и координаты дистрибьютора.
    Ни у одной розничной точки недопустим дефицит более 1,5%.
    При транспортировке заказа десять единиц расстояния преодолевается за один день.
    Таблица параметров розничных точек:
    Параметры розничных точек
    Порядковый номер розн. точки
    1 2
    3 4
    5 6
    7 8
    Координата x
    1 10 4
    6 9
    3 5
    8
    Координата y
    1 5
    3 6
    10 8
    9 6
    Спрос, mean
    80 90 30 57 73 91 120 91
    Спрос, std
    18 20 30 12 25 17 34 25
    Расстояние до дистрибьютора
    6 5
    3 2
    7 4
    4 4
    Расстояние до дистрибьютора (в днях пути) округлено в большую сторону, так как спрос генерируется каждый день в самом начале дня
    (уровень запаса обновляется один раз в день в начале дня). Спрос задается нормальным распределением. Ставки издержек такие же, как и в предыдущей задаче.
    Задачи:
    1. смоделировать и отразить на презентации работу цепи поставок;
    2. найти оптимальные значения параметров управления запасами.
    Модификация класса Main

    66
    Основное отличие от предыдущей версии – количество розничных точек. При оптимизационном эксперименте требуется найти оптимальные параметры управления запасами для каждой из восьми розничных точек.
    Переименуем параметры ROP и EOQ в ROP1 и EOQ1:
    Добавим параметры ROP2…ROP8 и EOQ2…EOQ8:
    Значения по умолчанию параметров EOQ1...8: 1000, ROP1…8:
    500.
    Как мы могли убедиться в предыдущем примере, оптимизационный эксперимент работает только с параметрами. Для удобства работы с параметрами создадим массивы переменных, где будут храниться их значения:

    67 retEOQ – массив величин EOQ (размер заказа) розничных точек. Тип массива int[]. (Квадратные скобки – обозначение массива)[1,p21]
    Начальное значение: new int[]{EOQ1,EOQ2,EOQ3,EOQ4,EOQ5,EOQ6,EOQ7,EOQ8} retROP
    – массив величин ROP (пороговый уровень запаса) розничных точек. Тип массива int[].
    Начальное значение: new int[]{ROP1,ROP2,ROP3,ROP4,ROP5,ROP6,ROP7,ROP8}
    Массивы retEOQ и retROP инициализируются значениями параметров EOQ1..8 и ROP1..8.
    Все переменные, которые связаны с розничными точками, в модели будут реализованы в виде массивов:

    68
    Меняем тип и значения по умолчанию для данных переменных: retStock – массив уровня запасов розничных точек. Тип: int[]
    Массив инициализируется строкой new int[]
    {0,0,0,0,0,0,0,0}
    . Каждый элемент приравнивается нулю. Нумерация элементов начинается от нуля. Индекс первого элемента 0, восьмого 7. demandMean, demandStd – массивы параметров нормального распределения спроса в розничных точках. Оба массива типа int[].
    Начальное значение demandMean: new int[]{80,90,30,57,73,91,120,91}
    Начальное значение demandStd: new int[]{18,20,30,12,25,17,34,25} retShortage – массив учета случаев дефицита для каждой из розничных точек. Тип массива int[].
    Начальное значение: new int[]{0,0,0,0,0,0,0,0}

    69 retailCoordx и retailCoordy – массивы координат x и y розничных точек (координаты взяты из постановки задачи)
    Начальное значение retailCoordx: new int[]{10,100,40,60,90,30,50,80}
    Начальное значение retailCoordy: new int[]{10,50,30,60,100,80,90,60}
    Изменим код Действия при запуске класса Main:
    Добавим код, генерирующий и размещающий на карте розничные точки и генерирующий транспортные средства: for (int i = 0; i < 8; i++) {
    Retailer a = add_retailer(); a.setXY(4*retailCoordx[i],4*retailCoordy[i]); a.retDist= sqrt(pow(retailCoordx[i]-distrCoordx,2)+ pow(retailCoordy[i]-distrCoordy,2) ); retStock[i] = retEOQ[i]+retROP[i];
    Truck d = add_truck(); d.setXY(4*distrCoordx,4*distrCoordy); d.rectangle.setVisible(false);
    }

    70
    В модели восемь розничных точек, поэтому инициализацию нужно выполнить для каждой из них. Для этого используем циклическая конструкция For. Границы цикла обозначены фигурными скобками.
    Переменная i – счетчик цикла. Каждую итерацию она увеличивается на единицу, начальное значение 0, конечное значение 7. Более подробная информация об использовании циклических конструкций в Java в материале
    «Java for Anylogic Users»[1,p37]. retailCoordx[i] – выбирает элемент массива с индексом i.
    Переменные уровня запасов и параметров управления запасами розничных точек также представлены в виде массивов.
    Далее в модель добавляется восемь транспортных средств, объектов класса Truck. Анимация модели будет организована таким образом, что транспортные средства видны лишь в процессе движения от дистрибьютора к розничной точке. Поэтому при запуске модели координаты должны соответствовать координатам дистрибьютора, но не быть видны в окне презентации.
    Метод d.rectangle.setVisible(false); делает объекты невидимыми на презентации.
    Код Действия при запуске класса Main:
    Distributor b = add_distributor(); b.setXY(4*distrCoordx,4*distrCoordy); for (int i = 0; i < 8; i++) {
    Retailer a = add_retailer(); a.setXY(4*retailCoordx[i],4*retailCoordy[i]); a.retDist= sqrt(pow(retailCoordx[i]-distrCoordx,2)+ pow(retailCoordy[i]-distrCoordy,2) ); retStock[i] = retEOQ[i]+retROP[i];
    Truck d = add_truck(); d.setXY(4*distrCoordx,4*distrCoordy); d.rectangle.setVisible(false);
    }

    71
    Изменение алгоритма управления запасами
    Модифицируем диаграмму действий actionChart. В новой версии модели все действия выполняются для каждой из восьми розничных точек.
    Добавляем цикл For:
    Меняем параметры цикла:
    Тип: итератор по коллекции, элемент: Retailer ret, коллекция: retailer
    . Данный цикл перебирает все элементы коллекции retailer, которые мы создали в классе Main (всего восемь элементов). При этом
    «счетчиком цикла» будет выступать переменная ret. Переменная ret служит ссылкой на объект, по аналогии с использованием переменных a, b в
    Действии при запуске класса Main. В классе Main они использовались для инициализации, здесь – для удобства обработки. Перебор осуществляется, пока не закончатся элементы коллекции. В нашем случае у цикла будет восемь итераций. Более подробно о коллекциях в “Java for AnyLogic Users”
    [1,p21]
    Остальной код диаграммы действий нужно переместить внутрь цикла:

    72
    Для этого вырезаем (Ctrl+X) элемент «Спрос превышает запас ритейлера?» выделяем диаграмму цикла и вставляем (Ctrl+V) его около выделенной цветом области цикла, когда подсвечивается зеленая точка в конструкции цикла:
    Результат:

    73
    Элемент окончания работы диаграммы действий должен быть в единственном экземпляре и за пределами цикла:
    Добавим элемент Локальная переменная. Данная переменная будет соответствовать индексу элемента коллекции розничных точек:
    Изменяем параметры локальной переменной:

    74
    Добавим элемент Код сразу после локальной переменной:
    Меняем свойства элемента Код. Комментарий: Обновление retHoldingcost и генерация спроса, код: retHoldingcost+=ret.retholdingrate*retStock[j]; ret.currentDemand = round( max
    (normal(demandStd[j],demandMean[j]),0));
    Код остальных модулей диаграммы действий изменяем с учетом работы с коллекцией агентов типа «розничная точка» (Retailer):
    Модуль: Спрос превышает запас ритейлера?

    75
    Код:
    ret.currentDemand > retStock[j]
    Модуль: Обновление дефицита
    Код: retShortage[j]++;
    Модуль: Нет заказа в пути?
    Код: truck.get(j).isMoving() == false
    Модуль: Обработка заказа дистрибьютором
    Код:
    create_RetReplenishment(ret.retDist/10,ret.retDist/10,j
    ); truck.get(j).rectangle.setVisible(true); truck.get(j).moveTo(ret.getX(),ret.getY());
    Модуль: обновление уровня запаса ритейлера
    Код: retStock[j]-= ret.currentDemand;
    Модуль: Заказ ритейлера меньше запаса распр. центра и нет заказа в пути?
    Код: retStock[j] < retROP[j] && truck.get(j).isMoving() == false
    Модификация событий
    В событии ordering оставляем только две строки: totalCost=retHoldingcost+retTrcost; actionChart();

    76
    Добавим параметр index (index соответствует индексу розничной точки – переменной j) в динамическое событие RetReplenishment: retStock[index]+=retEOQ[index]; truck.get(index).jumpTo(distributor.get(0).getX(),distr ibutor.get(0).getY()); truck.get(index).rectangle.setVisible(false); retTrcost+=time*retailer.get(index).rettrrate;
    Добавление элементов презентации
    Поменяем параметры Временного графика:

    77
    Добавим линию на окно редактирования класса Main:
    Поменяем динамические свойства линии line:
    Количество: 8. Данный массив линий будет использоваться для маршрутов «дистрибьютор – розничная точка». Чтобы линии автоматически перерисовывались при изменении конфигурации сети, изменим параметры расположения линий в пространстве: index – индекс линии (от 0 до 7)

    78
    Начальная точка каждой из линий – это координата розничной точки.
    Для получения координат используются методы getX() и getY().
    X: retailer.get(index).getX()
    Y: retailer.get(index).getY()
    Параметры dX и dY определяют смещение конечной точки прямой по отношению к начальной. В нашем случае это разность между координатами дистрибьютора и розничной точки:
    dX: distributor.get(0).getX() - retailer.get(index).getX()
    dY: distributor.get(0).getY()- retailer.get(index).getY()
    Отображение уровня запаса в текстовом поле
    Добавим на презентацию модели переменные уровня запаса элементов сети. Для этого создадим элемент Текст:
    Переименуем текст в textRet. Текст должен отображать текущий уровень запаса розничной точки и быть расположен рядом с розничной точкой на карте презентации. Для этого снова воспользуемся динамическими параметрами:

    79
    Количество текстовых полей соответствует количеству розничных точек в модели.
    X: retailer.get(index).getX()+5
    Y: retailer.get(index).getY()
    Текст: retStock[index]
    Координаты X и Y подобраны так, что текст будет располагаться немного правее (на 5 единиц) пиктограммы презентации розничной точки.
    Текстовое поле показывает текущий уровень запаса розничной точки retStock[].
    Модифицируем текст, отображающий количество случаев возникновения дефицита. На его основе будут создаваться восемь текстовых полей, показывающих количество случаев возникновения дефицита в каждой из розничных точек:

    80
    Количество: 8
    X: 500
    Y: 10+15*index
    Текст: "Не выполненные в срок заказы,"+" Ритейлер №
    "+(1+index)+ ": "+retShortage[index]
    Координата Y задана таким образом, что строки будут располагаться вертикальным списком с отступом 15 единиц.
    Строка в поле текст состоит из нескольких элементов. Текст в кавычках будет отображаться как статическое текстовое поле, знак «+» объединяет части строки[1,p20]. Номер розничной точки на единицу больше индекса розничной точки, так как индекс начинает нумерацию с нуля. retShortage[index] выводит значение переменной, обозначающей уровень дефицита у данной розничной точки.
    Запустим модель:

    81
    На презентации отображаются запасы розничных точек, каждому маршруту соответствует линия, отображаются данные уровня издержек, количество случаев дефицита.
    Запись данных о ежедневном уровне запасов в текстовый файл
    Данные будут записываться в файл каждый день, поэтому отредактируем элемент «Обновление retHoldingcost и генерация спроса» диаграммы действий actionChart – добавим код для записи данных об уровне запасов в файл. В файле должно быть восемь столбцов (по количеству розничных точек) и тысяча строк (по количеству дней работы модели). Для записи используем методы print() – запись в строку и println() – начало новой строки.

    82 filestock.print(" "+retStock[j]); if(j==7){ filestock.println(" ");
    }
    В текстовый файл добавляются пробел “ “ и величина текущего заказа розничной точки ret.retStock. Знак «+» используется для объединения двух частей выражения.
    Если выбран последний элемент коллекции с индексом 7, то начинается запись новой строки (в java нумерация элементов начинается с нуля).
    Запустим модель и откроем текстовый файл, в который были записаны данные во время работы симуляции:

    83
    Для того чтобы можно было открыть файл в Excel с нужным форматированием выбираем в Excel следующие параметры:
    Получаем следующую форму представления данных:

    84
    По аналогии с уровнем запасов розничной точки можно записывать в текстовые файлы и другие важные параметры работы модели для последующего более детального анализа полученных данных.
    Оптимизационный эксперимент
    Ограничения
    Модифицируем оптимизационный эксперимент. По условию ни в одной из розничных точек недопустимо количество дефицита более 15 случаев. Для того чтобы контролировать данное условие, добавим дополнительные переменные и код.
    Переменная shortageLevel соответствует допустимому уровню дефицита. Значение по умолчанию: 15. Переменная restriction равна нулю, если допустимый уровень дефицита не превышен, и единице в обратном случае. Обе переменные типа int и размещены в классе Main.
    Добавим код проверки превышения допустимого уровня дефицита в диаграмму действий:

    85
    Модуль: Обновление retHoldingcost и генерация спроса.
    Добавляем код: if (retShortage[j]>shortageLevel){ restriction = 1;
    }
    Вернемся к редактированию оптимизационного эксперимента:

    86
    В новой версии 16 изменяемых параметров модели.
    Настройки ограничений:
    Заново создаем интерфейс:
    Переместим элементы презентации оптимизационного эксперимента:

    87
    Поиск решения

    88
    Как мы видим, после определенного момента целевая функция
    (выделена синим цветом на графике) практически не улучшает значение.
    Задания:
    1)Рассчитайте аналитически при помощи метода «центра тяжести» оптимальные координаты размещения дистрибьютора. Измените координаты distrCoordx и distrCoordy на полученные значения и проведите оптимизационный эксперимент. Сравните издержки новой конфигурации системы.

    89 2)Доработайте модель таким образом, чтобы собирались данные по издержкам каждой розничной точки на хранение и транспортировку.
    2.3 Расширенная модель цепи поставок
    Описание задачи
    Добавим в цепь поставок еще один уровень – поставщика. Ставка содержания запаса дистрибьютора: 1 единица за хранение единицы товара в течение периода, ставка на транспортировку: 20000 единиц за 10 единиц пройденного расстояния. Система управления запасами дистрибьютора реализована по аналогии с розничными точками: оптимальный размер заказа
    EOQ и пороговый уровень запаса ROP. Координаты поставщика: (60;120)

    90
    В модели восемь розничных точек, один дистрибьютор и один поставщик. Получаем восемнадцать изменяемых переменных, отвечающих за параметры управления запасами
    (запасы поставщика приняты неограниченными). Две дополнительные переменные определяют координаты расположения дистрибьютора.
    Таким образом, в модели двадцать изменяемых переменных. Дополнительные сложности связаны с вероятностной структурой спроса и ограничениями по допустимому уровню сервиса.[7]
    Задачи:
    1.смоделировать и отразить на презентации работу расширенной цепи поставок;
    2.найти оптимальные значения параметров управления запасами и оптимальные координаты размещения дистрибьютора.
    Добавление класса поставщика
    Создадим переменные координат поставщика в классе Main:
    Тип обеих переменных: int, значение по умолчанию supplyCoordx:
    60, supplyCoordy: 120.
    По аналогии с агентом Distributor (во второй части практикума) добавим новый класс агентов Supplier. Цвет заливки для прямоугольника презентации Supplier – red, ширина и высота 7. Не забываем указать среду и выбрать реплицированный тип агента.
    Добавим параметры класса Distributor:

    91
    Параметры класса Distributor:расстояние до поставщика, проверка нахождения заказа в пути, ставка хранения запаса, ставка транспортировки от поставщика. dcDist – расстояние от дистрибьютора до поставщика. Тип параметра: double. dcholdingrate – ставка содержания одной единицы запаса на складе дистрибьютора за 1 день. Начальное значение: 1. Тип параметра: double. dctrrate – ставка на доставку заказа от поставщика до дистрибьютора за 1 день пути. Начальное значение: 20000. Тип: double
    Модификация класса Main
    Добавим параметры и переменные в класс Main:
    Переменные:
    DCHoldingcost – издержки на хранение запаса дистрибьютора. Тип переменной: Int
    DCTrcost – издержки на транспортировку дистрибьютора. Тип: double
    DCStock
    – текущий уровень запаса дистрибьютора. Тип: int
    DCShortage
    – переменная учета случаев дефицита дистрибьютора.
    Тип переменной int.
    Параметры:

    92
    DCEOQ – размер заказа дистрибьютора. Тип параметра int. Значение по умолчанию 15000:
    DCROP – величина порогового запаса дистрибьютора, значение по умолчанию 5000.
    Откорректируем Действие при запуске класса Main:
    Добавим строку инициализации запаса дистрибьютора:
    DCStock=DCEOQ+DCROP;
    Рассчитаем срок доставки заказа от поставщика дистрибьютору: b.dcDist
    = sqrt(pow(supplyCoordx-distrCoordx,2)+ pow(supplyCoordy-distrCoordy,2) );
    Инициализируем объект класса Supplier:
    Supplier c = add_supplier(); c.setXY(4*supplyCoordx,4*supplyCoordy);

    93
    Данные две строки добавляют поставщика и размещают его на карте в соответствии с указанными координатами
    Также добавим еще одно транспортное средство, которое будет работать на маршруте «поставщик – дистрибьютор»:
    Truck e = add_truck(); e.setXY(4*supplyCoordx,4*supplyCoordy); truck.get(8).rectangle.setVisible(false);
    Мы уже создали восемь объектов truck (с индексами 0…7), поэтому индекс нового объекта будет равен восьми.
    Построим линию, соединяющую поставщика и дистрибьютора на карте:

    94
    1   2   3   4


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