В этом примере показано, как настроить и решить задачу линейного программирования со смешанным целым числом. Проблема заключается в том, чтобы найти оптимальные уровни производства и распределения между рядом заводов, складов и торговых точек. Подход на основе решателей см. в разделе Фабрика, Склад, Модель распределения продаж на основе решателей.
В примере сначала создаются случайные местоположения для заводов, складов и торговых точек. Не стесняйтесь изменять параметр масштабирования , который масштабирует как размер сетки, в которой находятся производственные и распределительные объекты, так и количество этих объектов так, чтобы плотность объектов каждого типа на сетку не зависела от .
Для заданного значения параметра масштабирования предположим, что существуют следующие значения:
⌋ заводы
⌋ склады
⌋ торговые точки
Эти средства находятся на отдельных целочисленных точках сетки между 1 и в направлениях x и y. Для того, чтобы объекты имели отдельные местоположения, требуется этот . В этом примере принимают 20= 0,05 s = 0,1.
Есть продукты P, изготовленные фабриками. Принять 20.
Спрос на каждый продукт в торговой точке равен p). Потребность - это количество, которое может быть продано в интервале времени. Одним из ограничений модели является удовлетворение потребности, что означает, что система производит и распределяет именно те количества потребности.
На каждом заводе и на каждом складе существуют ограничения по мощности.
Производство продукта на заводе меньше, чем p).
Вместимость склада составляет ).
Количество продукта , которое можно транспортировать со склада к торговой точке в интервале времени, меньше, чем (w), оборот (p) - это скорость оборота продукта p.
Предположим, что каждая торговая точка получает свои поставки только с одного склада. Отчасти проблема заключается в определении наиболее дешевого картирования торговых точек на склады.
Стоимость транспортировки продукции с завода на склад и со склада на торговую точку зависит от расстояния между объектами и от конкретного продукта. Если b) - расстояние между a b, то стоимость транспортировки p между этими объектами является расстоянием, умноженным на стоимость транспортировки (p):
(p).
Расстояние в этом примере - это расстояние сетки, также называемое расстоянием. Это сумма абсолютных разностей координат и .
Стоимость изготовления единицы продукта на заводе составляет p).
Учитывая набор местоположений объекта, а также требования и ограничения по мощности, найдите:
Уровень производства каждого продукта на каждом заводе
График распределения продукции с заводов на склады
График распределения продуктов со складов на торговые точки
Эти количества должны обеспечивать удовлетворение потребности и минимизацию общих затрат. Также каждая торговая точка обязана получать всю свою продукцию ровно с одного склада.
Управляющие переменные, то есть переменные, которые можно изменить при оптимизации:
w) = количество продукта p, которое транспортируется с завода f на склад w
w) = двоичная переменная, принимающая значение 1, когда s связана со w
Целевой функцией для минимизации является
⋅dist (f, w))
⋅y (s, w)).
Ограничения:
(f, p) (производительность завода).
⋅y (s, w)) (спрос удовлетворяется).
≤wcap (w) (вместимость склада).
= 1 (каждая торговая точка связана с одним складом).
) ≥0 (неотрицательное производство).
ϵ{0,1} (двоичный y).
Переменные и отображаются в функциях цели и ограничения линейно. Поскольку ограничен целочисленными значениями, проблема заключается в смешанно-целочисленной линейной программе (MILP).
Задайте значения параметров N, f, w и s и создайте местоположения оборудования.
rng(1) % for reproducibility N = 20; % N from 10 to 30 seems to work. Choose large values with caution. N2 = N*N; f = 0.05; % density of factories w = 0.05; % density of warehouses s = 0.1; % density of sales outlets F = floor(f*N2); % number of factories W = floor(w*N2); % number of warehouses S = floor(s*N2); % number of sales outlets xyloc = randperm(N2,F+W+S); % unique locations of facilities [xloc,yloc] = ind2sub([N N],xyloc);
Конечно, нереально брать случайные места для объектов. Этот пример предназначен для демонстрации методов решения, а не способов создания хороших местоположений объекта.
Постройте график объектов. Объекты 1 - F - заводы, F + 1 - F + W - склады, а F + W + 1 - F + W + S - торговые точки.
h = figure; plot(xloc(1:F),yloc(1:F),'rs',xloc(F+1:F+W),yloc(F+1:F+W),'k*',... xloc(F+W+1:F+W+S),yloc(F+W+1:F+W+S),'bo'); lgnd = legend('Factory','Warehouse','Sales outlet','Location','EastOutside'); lgnd.AutoUpdate = 'off'; xlim([0 N+1]);ylim([0 N+1])

Создание случайных производственных затрат, мощностей, оборотов и потребностей.
P = 20; % 20 products % Production costs between 20 and 100 pcost = 80*rand(F,P) + 20; % Production capacity between 500 and 1500 for each product/factory pcap = 1000*rand(F,P) + 500; % Warehouse capacity between P*400 and P*800 for each product/warehouse wcap = P*400*rand(W,1) + P*400; % Product turnover rate between 1 and 3 for each product turn = 2*rand(1,P) + 1; % Product transport cost per distance between 5 and 10 for each product tcost = 5*rand(1,P) + 5; % Product demand by sales outlet between 200 and 500 for each % product/outlet d = 300*rand(S,P) + 200;
Эти случайные потребности и возможности могут привести к неосуществимым проблемам. Другими словами, иногда спрос превышает производственные и складские ограничения. Если изменить некоторые параметры и получить неосуществимую проблему, во время решения вы получите exitflag -2.
Чтобы начать определение проблемы, создайте массивы расстояний distfw(i,j) и distsw(i,j).
distfw = zeros(F,W); % Allocate matrix for factory-warehouse distances for ii = 1:F for jj = 1:W distfw(ii,jj) = abs(xloc(ii) - xloc(F + jj)) + abs(yloc(ii) ... - yloc(F + jj)); end end distsw = zeros(S,W); % Allocate matrix for sales outlet-warehouse distances for ii = 1:S for jj = 1:W distsw(ii,jj) = abs(xloc(F + W + ii) - xloc(F + jj)) ... + abs(yloc(F + W + ii) - yloc(F + jj)); end end
Создайте переменные для задачи оптимизации. x представляет производство, непрерывную переменную, с измерением Pоколо-Fоколо-W. y представляет двоичное распределение торговой точки на склад, Sоколо-W переменная.
x = optimvar('x',P,F,W,'LowerBound',0); y = optimvar('y',S,W,'Type','integer','LowerBound',0,'UpperBound',1);
Теперь создайте зависимости. Первое ограничение - это ограничение мощности для производства.
capconstr = sum(x,3) <= pcap';
Следующим ограничением является удовлетворение спроса в каждой торговой точке.
demconstr = squeeze(sum(x,2)) == d'*y;
На каждом складе существует ограничение мощности.
warecap = sum(diag(1./turn)*(d'*y),1) <= wcap';
Наконец, необходимо, чтобы каждая торговая точка подключалась только к одному складу.
salesware = sum(y,2) == ones(S,1);
Создайте проблему оптимизации.
factoryprob = optimproblem;
Целевая функция состоит из трех частей. Первая часть представляет собой сумму производственных затрат.
objfun1 = sum(sum(sum(x,3).*(pcost'),2),1);
Вторая часть - сумма транспортных расходов с заводов на склады.
objfun2 = 0; for p = 1:P objfun2 = objfun2 + tcost(p)*sum(sum(squeeze(x(p,:,:)).*distfw)); end
Третья часть - это сумма транспортных затрат от складов до торговых точек.
r = sum(distsw.*y,2); % r is a length s vector
v = d*(tcost(:));
objfun3 = sum(v.*r);Целевой функцией для минимизации является сумма трех частей.
factoryprob.Objective = objfun1 + objfun2 + objfun3;
Включите в проблему ограничения.
factoryprob.Constraints.capconstr = capconstr; factoryprob.Constraints.demconstr = demconstr; factoryprob.Constraints.warecap = warecap; factoryprob.Constraints.salesware = salesware;
Отключите итеративное отображение, чтобы не получать сотни строк выходных данных. Включите функцию графика для контроля выполнения решения.
opts = optimoptions('intlinprog','Display','off','PlotFcn',@optimplotmilp);
Вызовите решатель, чтобы найти решение.
[sol,fval,exitflag,output] = solve(factoryprob,'options',opts);
if isempty(sol) % If the problem is infeasible or you stopped early with no solution disp('The solver did not return a solution.') return % Stop the script because there is nothing to examine end
Проверьте флаг выхода и несходимость решения.
exitflag
exitflag =
OptimalSolution
infeas1 = max(max(infeasibility(capconstr,sol)))
infeas1 = 9.0949e-13
infeas2 = max(max(infeasibility(demconstr,sol)))
infeas2 = 8.0718e-12
infeas3 = max(infeasibility(warecap,sol))
infeas3 = 0
infeas4 = max(infeasibility(salesware,sol))
infeas4 = 2.4425e-15
Круглый y часть решения должна быть в точности целочисленной. Чтобы понять, почему эти переменные могут быть не совсем целыми числами, см. Некоторые «целочисленные» решения не целые числа.
sol.y = round(sol.y); % get integer solutionsСколько торговых точек связано с каждым складом? Обратите внимание, что в этом случае некоторые склады имеют 0 связанных торговых точек, что означает, что склады не используются в оптимальном решении.
outlets = sum(sol.y,1)
outlets = 1×20
2 0 3 2 2 2 3 2 3 2 1 0 0 3 4 3 2 3 2 1
Постройте график соединения между каждой торговой точкой и ее складом.
figure(h); hold on for ii = 1:S jj = find(sol.y(ii,:)); % Index of warehouse associated with ii xsales = xloc(F+W+ii); ysales = yloc(F+W+ii); xwarehouse = xloc(F+jj); ywarehouse = yloc(F+jj); if rand(1) < .5 % Draw y direction first half the time plot([xsales,xsales,xwarehouse],[ysales,ywarehouse,ywarehouse],'g--') else % Draw x direction first the rest of the time plot([xsales,xwarehouse,xwarehouse],[ysales,ysales,ywarehouse],'g--') end end hold off title('Mapping of sales outlets to warehouses')

Черный * без зеленых линий представляет неиспользуемые склады.