Esta página aún no se ha traducido para esta versión. Puede ver la versión más reciente de esta página en inglés.

Fábrica, almacén, modelo de asignación de ventas: basado en Solver

En este ejemplo se muestra cómo configurar y resolver un problema de programación lineal de enteros mixtos. El problema es encontrar los niveles óptimos de producción y distribución entre un conjunto de fábricas, almacenes y puntos de venta. Para el enfoque basado en problemas, vea.Fábrica, almacén, modelo de asignación de ventas: basado en problemas

El ejemplo primero genera ubicaciones aleatorias para fábricas, almacenes y puntos de venta. Siéntase libre de modificar el parámetro de escalado

<math display="block">
<mrow>
<mi>N</mi>
</mrow>
</math>
, que escala tanto el tamaño de la rejilla en la que residen las instalaciones de producción como de distribución, pero también escala el número de estas instalaciones para que la densidad de las instalaciones de cada tipo por área de rejilla sea independiente de
<math display="block">
<mrow>
<mi>N</mi>
</mrow>
</math>
.

Ubicaciones de instalaciones

Para un valor determinado del parámetro de escalado

<math display="block">
<mrow>
<mi>N</mi>
</mrow>
</math>
, supongamos que hay lo siguiente:

  • <math display="block">
    <mrow>
    <mo></mo>
    <mi>f</mi>
    <msup>
    <mrow>
    <mi>N</mi>
    </mrow>
    <mrow>
    <mn>2</mn>
    </mrow>
    </msup>
    <mo></mo>
    </mrow>
    </math>
    Fábricas

  • <math display="block">
    <mrow>
    <mo></mo>
    <mi>w</mi>
    <msup>
    <mrow>
    <mi>N</mi>
    </mrow>
    <mrow>
    <mn>2</mn>
    </mrow>
    </msup>
    <mo></mo>
    </mrow>
    </math>
    Almacenes

  • <math display="block">
    <mrow>
    <mo></mo>
    <mi>s</mi>
    <msup>
    <mrow>
    <mi>N</mi>
    </mrow>
    <mrow>
    <mn>2</mn>
    </mrow>
    </msup>
    <mo></mo>
    </mrow>
    </math>
    puntos de venta

Estas instalaciones se encuentran en puntos de rejilla enteros separados entre 1 y

<math display="block">
<mrow>
<mi>N</mi>
</mrow>
</math>
En
<math display="block">
<mrow>
<mi>x</mi>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>y</mi>
</mrow>
</math>
Direcciones. Para que las instalaciones tengan ubicaciones separadas, usted requiere que
<math display="block">
<mrow>
<mi>f</mi>
<mo>+</mo>
<mi>w</mi>
<mo>+</mo>
<mi>s</mi>
<mo></mo>
<mn>1</mn>
</mrow>
</math>
. En este ejemplo, tome
<math display="block">
<mrow>
<mi>N</mi>
<mo>=</mo>
<mn>2</mn>
<mn>0</mn>
</mrow>
</math>
,
<math display="block">
<mrow>
<mi>f</mi>
<mo>=</mo>
<mn>0</mn>
<mo>.</mo>
<mn>0</mn>
<mn>5</mn>
</mrow>
</math>
,
<math display="block">
<mrow>
<mi>w</mi>
<mo>=</mo>
<mn>0</mn>
<mo>.</mo>
<mn>0</mn>
<mn>5</mn>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>s</mi>
<mo>=</mo>
<mn>0</mn>
<mo>.</mo>
<mn>1</mn>
</mrow>
</math>
.

Producción y distribución

Hay

<math display="block">
<mrow>
<mi>P</mi>
</mrow>
</math>
productos fabricados por las fábricas. Tomar
<math display="block">
<mrow>
<mi>P</mi>
<mo>=</mo>
<mn>2</mn>
<mn>0</mn>
</mrow>
</math>
.

La demanda de cada producto

<math display="block">
<mrow>
<mi>p</mi>
</mrow>
</math>
en un outlet de ventas
<math display="block">
<mrow>
<mi>s</mi>
</mrow>
</math>
Es
<math display="block">
<mrow>
<mi>d</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
. La demanda es la cantidad que se puede vender en un intervalo de tiempo. Una restricción en el modelo es que se cumple la demanda, lo que significa que el sistema produce y distribuye exactamente las cantidades en la demanda.

Hay restricciones de capacidad en cada fábrica y cada almacén.

  • La producción de productos

    <math display="block">
    <mrow>
    <mi>p</mi>
    </mrow>
    </math>
    en Factory
    <math display="block">
    <mrow>
    <mi>f</mi>
    </mrow>
    </math>
    es menor que
    <math display="block">
    <mrow>
    <mi>p</mi>
    <mi>c</mi>
    <mi>a</mi>
    <mi>p</mi>
    <mo stretchy="false">(</mo>
    <mi>f</mi>
    <mo>,</mo>
    <mi>p</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    .

  • La capacidad del almacén

    <math display="block">
    <mrow>
    <mi>w</mi>
    </mrow>
    </math>
    Es
    <math display="block">
    <mrow>
    <mi>w</mi>
    <mi>c</mi>
    <mi>a</mi>
    <mi>p</mi>
    <mo stretchy="false">(</mo>
    <mi>w</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    .

  • La cantidad de producto

    <math display="block">
    <mrow>
    <mi>p</mi>
    </mrow>
    </math>
    que pueden transportarse desde el almacén
    <math display="block">
    <mrow>
    <mi>w</mi>
    </mrow>
    </math>
    a un outlet de ventas en el intervalo de tiempo es menor que
    <math display="block">
    <mrow>
    <mi>t</mi>
    <mi>u</mi>
    <mi>r</mi>
    <mi>n</mi>
    <mo stretchy="false">(</mo>
    <mi>p</mi>
    <mo stretchy="false">)</mo>
    <mo>*</mo>
    <mi>w</mi>
    <mi>c</mi>
    <mi>a</mi>
    <mi>p</mi>
    <mo stretchy="false">(</mo>
    <mi>w</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    Dónde
    <math display="block">
    <mrow>
    <mi>t</mi>
    <mi>u</mi>
    <mi>r</mi>
    <mi>n</mi>
    <mo stretchy="false">(</mo>
    <mi>p</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    es la tasa de rotación del producto
    <math display="block">
    <mrow>
    <mi>p</mi>
    </mrow>
    </math>
    .

Supongamos que cada salida de ventas recibe sus suministros de un solo almacén. Parte del problema es determinar el mapeo más barato de los puntos de venta a los almacenes.

Costos

El costo de transportar productos de fábrica a almacén, y de almacén a punto de venta, depende de la distancia entre las instalaciones, y en el producto en particular. Si

<math display="block">
<mrow>
<mi>d</mi>
<mi>i</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>a</mi>
<mo>,</mo>
<mi>b</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
es la distancia entre las instalaciones
<math display="block">
<mrow>
<mi>a</mi>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>b</mi>
</mrow>
</math>
, el costo de envío de un producto
<math display="block">
<mrow>
<mi>p</mi>
</mrow>
</math>
entre estas instalaciones es el tiempo de distancia que el costo de transporte
<math display="block">
<mrow>
<mi>t</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
:

<math display="block">
<mrow>
<mi>d</mi>
<mi>i</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>a</mi>
<mo>,</mo>
<mi>b</mi>
<mo stretchy="false">)</mo>
<mo>*</mo>
<mi>t</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mo>.</mo>
</mrow>
</math>

La distancia en este ejemplo es la distancia de la rejilla, también conocida como la

<math display="block">
<mrow>
<msub>
<mrow>
<mi>L</mi>
</mrow>
<mrow>
<mn>1</mn>
</mrow>
</msub>
</mrow>
</math>
Distancia. Es la suma de la diferencia absoluta en
<math display="block">
<mrow>
<mi>x</mi>
</mrow>
</math>
coordenadas y
<math display="block">
<mrow>
<mi>y</mi>
</mrow>
</math>
Coordenadas.

El costo de hacer una unidad de producto

<math display="block">
<mrow>
<mi>p</mi>
</mrow>
</math>
en fábrica
<math display="block">
<mrow>
<mi>f</mi>
</mrow>
</math>
Es
<math display="block">
<mrow>
<mi>p</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>f</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
.

Problema de optimización

Dado un conjunto de ubicaciones de instalaciones, y las demandas y restricciones de capacidad, encuentre:

  • Un nivel de producción de cada producto en cada fábrica

  • Una programación de distribución para productos de fábricas a almacenes

  • Un programa de distribución para productos de almacenes a puntos de venta

Estas cantidades deben garantizar que se satisface la demanda y se minimiza el coste total. Además, cada salida de ventas es necesaria para recibir todos sus productos de exactamente un almacén.

Variables y ecuaciones para el problema de optimización

Las variables de control, es decir, las que se pueden cambiar en la optimización, son

  • <math display="block">
    <mrow>
    <mi>x</mi>
    <mo stretchy="false">(</mo>
    <mi>p</mi>
    <mo>,</mo>
    <mi>f</mi>
    <mo>,</mo>
    <mi>w</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    = la cantidad de producto
    <math display="block">
    <mrow>
    <mi>p</mi>
    </mrow>
    </math>
    que se transporta desde la fábrica
    <math display="block">
    <mrow>
    <mi>f</mi>
    </mrow>
    </math>
    al almacén
    <math display="block">
    <mrow>
    <mi>w</mi>
    </mrow>
    </math>

  • <math display="block">
    <mrow>
    <mi>y</mi>
    <mo stretchy="false">(</mo>
    <mi>s</mi>
    <mo>,</mo>
    <mi>w</mi>
    <mo stretchy="false">)</mo>
    </mrow>
    </math>
    = una variable binaria que toma el valor 1 cuando la salida de ventas
    <math display="block">
    <mrow>
    <mi>s</mi>
    </mrow>
    </math>
    está asociado con el almacén
    <math display="block">
    <mrow>
    <mi>w</mi>
    </mrow>
    </math>

La función objetiva para minimizar es

<math display="block">
<mrow>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>f</mi>
</mrow>
</munder>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>p</mi>
</mrow>
</munder>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>w</mi>
</mrow>
</munder>
<mi>x</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>f</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mo>+</mo>
<mi>t</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mo></mo>
<mi>d</mi>
<mi>i</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo stretchy="false">)</mo>
</mrow>
</math>

<math display="block">
<mrow>
<mo>+</mo>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>s</mi>
</mrow>
</munder>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>w</mi>
</mrow>
</munder>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>p</mi>
</mrow>
</munder>
<mo stretchy="false">(</mo>
<mi>d</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mi>t</mi>
<mi>c</mi>
<mi>o</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mi>d</mi>
<mi>i</mi>
<mi>s</mi>
<mi>t</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo stretchy="false">)</mo>
<mo>.</mo>
</mrow>
</math>

Las restricciones se

<math display="block">
<mrow>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>w</mi>
</mrow>
</munder>
<mi>x</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo></mo>
<mi>p</mi>
<mi>c</mi>
<mi>a</mi>
<mi>p</mi>
<mo stretchy="false">(</mo>
<mi>f</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
(capacidad de fábrica).

<math display="block">
<mrow>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>f</mi>
</mrow>
</munder>
<mi>x</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo>=</mo>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>s</mi>
</mrow>
</munder>
<mo stretchy="false">(</mo>
<mi>d</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo stretchy="false">)</mo>
</mrow>
</math>
(se cumple la demanda).

<math display="block">
<mrow>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>p</mi>
</mrow>
</munder>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>s</mi>
</mrow>
</munder>
<mfrac>
<mrow>
<mi>d</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
<mrow>
<mi>t</mi>
<mi>u</mi>
<mi>r</mi>
<mi>n</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo stretchy="false">)</mo>
</mrow>
</mfrac>
<mspace width="0.5em"></mspace>
<mo></mo>
<mspace width="0.5em"></mspace>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo></mo>
<mi>w</mi>
<mi>c</mi>
<mi>a</mi>
<mi>p</mi>
<mo stretchy="false">(</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
(capacidad de almacén).

<math display="block">
<mrow>
<munder>
<mrow>
<mo></mo>
</mrow>
<mrow>
<mi>w</mi>
</mrow>
</munder>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo>=</mo>
<mn>1</mn>
</mrow>
</math>
(cada salida de ventas se asocia a un almacén).

<math display="block">
<mrow>
<mi>x</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mo></mo>
<mn>0</mn>
</mrow>
</math>
(producción no negativa).

<math display="block">
<mrow>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
<mspace width="0.5em"></mspace>
<mi>ϵ</mi>
<mspace width="0.5em"></mspace>
<mo stretchy="false">{</mo>
<mn>0</mn>
<mo>,</mo>
<mn>1</mn>
<mo stretchy="false">}</mo>
</mrow>
</math>
(binario
<math display="block">
<mrow>
<mi>y</mi>
</mrow>
</math>
).

Las variables

<math display="block">
<mrow>
<mi>x</mi>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>y</mi>
</mrow>
</math>
aparecen en el objetivo y las funciones de restricción linealmente. porque
<math display="block">
<mrow>
<mi>y</mi>
</mrow>
</math>
está restringido a valores enteros, el problema es un programa lineal de enteros mixtos (MILP).

Genere un problema aleatorio: ubicaciones de las instalaciones

Establezca los valores de la

<math display="block">
<mrow>
<mi>N</mi>
</mrow>
</math>
,
<math display="block">
<mrow>
<mi>f</mi>
</mrow>
</math>
,
<math display="block">
<mrow>
<mi>w</mi>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>s</mi>
</mrow>
</math>
parámetros y genere las ubicaciones de las instalaciones.

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);

Por supuesto, no es realista tomar ubicaciones aleatorias para las instalaciones. En este ejemplo se pretende mostrar técnicas de solución, no cómo generar buenas ubicaciones de instalación.

Trace las instalaciones. Las instalaciones 1 a F son fábricas, F + 1 a F + W son almacenes y F + W + 1 a F + W + S son puntos de venta.

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])

Genere capacidades aleatorias, costos y demandas

Genere costos de producción aleatorios, capacidades, tasas de rotación y demandas.

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;

Estas demandas y capacidades aleatorias pueden llevar a problemas infactibles. En otras palabras, a veces la demanda excede las restricciones de capacidad de producción y de almacén. Si altera algunos parámetros y consigue un problema infactible, durante la solución obtendrá un exitflag de-2.

Genere matrices y vectores de objetivos y restricciones

El vector de la función objetivo consiste en los coeficientes de las variablesobjintlincon

<math display="block">
<mrow>
<mi>x</mi>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
Y
<math display="block">
<mrow>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
. Así que hay coeficientes naturales en.P*F*W + S*Wobj

Una forma de generar los coeficientes es comenzar con una matriz para elP-by-F-by-Wobj1

<math display="block">
<mrow>
<mi>x</mi>
</mrow>
</math>
coeficientes y una matriz para elS-by-Wobj2
<math display="block">
<mrow>
<mi>y</mi>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
Coeficientes. A continuación, convierta estas matrices en dos vectores y combínelos mediante una llamada aobj

obj = [obj1(:);obj2(:)];

obj1 = zeros(P,F,W); % Allocate arrays obj2 = zeros(S,W);

A lo largo de la generación de vectores y matrices de objetivos y restricciones, generamos el

<math display="block">
<mrow>
<mo stretchy="false">(</mo>
<mi>p</mi>
<mo>,</mo>
<mi>f</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
matriz o el
<math display="block">
<mrow>
<mo stretchy="false">(</mo>
<mi>s</mi>
<mo>,</mo>
<mi>w</mi>
<mo stretchy="false">)</mo>
</mrow>
</math>
Array y, a continuación, convierta el resultado en un vector.

Para empezar a generar las entradas, genere las matrices de distancia y.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

Genere las entradas de y.obj1obj2

for ii = 1:P     for jj = 1:F         for kk = 1:W             obj1(ii,jj,kk) = pcost(jj,ii) + tcost(ii)*distfw(jj,kk);         end     end end  for ii = 1:S     for jj = 1:W         obj2(ii,jj) = distsw(ii,jj)*sum(d(ii,:).*tcost);     end end

Combine las entradas en un vector.

obj = [obj1(:);obj2(:)]; % obj is the objective function vector

Ahora cree las matrices de restricciones.

El ancho de cada matriz de restricción lineal es la longitud del vector.obj

matwid = length(obj);

Existen dos tipos de desigualdades lineales: las restricciones de capacidad de producción y las restricciones de capacidad de almacén.

Hay restricciones de capacidad de producción y restricciones de capacidad de almacén.P*FW Las matrices de restricciones son bastante escasas, en el orden de 1% distinto de cero, por lo que ahorrar memoria mediante el uso de matrices dispersas.

Aineq = spalloc(P*F + W,matwid,P*F*W + S*W); % Allocate sparse Aeq bineq = zeros(P*F + W,1); % Allocate bineq as full  % Zero matrices of convenient sizes: clearer1 = zeros(size(obj1)); clearer12 = clearer1(:); clearer2 = zeros(size(obj2)); clearer22 = clearer2(:);  % First the production capacity constraints counter = 1; for ii = 1:F     for jj = 1:P         xtemp = clearer1;         xtemp(jj,ii,:) = 1; % Sum over warehouses for each product and factory         xtemp = sparse([xtemp(:);clearer22]); % Convert to sparse         Aineq(counter,:) = xtemp'; % Fill in the row         bineq(counter) = pcap(ii,jj);         counter = counter + 1;     end end  % Now the warehouse capacity constraints vj = zeros(S,1); % The multipliers  for jj = 1:S     vj(jj) = sum(d(jj,:)./turn); % A sum of P elements end  for ii = 1:W     xtemp = clearer2;     xtemp(:,ii) = vj;     xtemp = sparse([clearer12;xtemp(:)]); % Convert to sparse     Aineq(counter,:) = xtemp'; % Fill in the row     bineq(counter) = wcap(ii);     counter = counter + 1; end

Hay dos tipos de restricciones de igualdad lineales: la restricción que se cumple la demanda y la restricción que cada salida de ventas corresponde a un almacén.

Aeq = spalloc(P*W + S,matwid,P*W*(F+S) + S*W); % Allocate as sparse beq = zeros(P*W + S,1); % Allocate vectors as full  counter = 1; % Demand is satisfied: for ii = 1:P     for jj = 1:W         xtemp = clearer1;         xtemp(ii,:,jj) = 1;         xtemp2 = clearer2;         xtemp2(:,jj) = -d(:,ii);         xtemp = sparse([xtemp(:);xtemp2(:)]'); % Change to sparse row         Aeq(counter,:) = xtemp; % Fill in row         counter = counter + 1;     end end  % Only one warehouse for each sales outlet: for ii = 1:S     xtemp = clearer2;     xtemp(ii,:) = 1;     xtemp = sparse([clearer12;xtemp(:)]'); % Change to sparse row     Aeq(counter,:) = xtemp; % Fill in row     beq(counter) = 1;     counter = counter + 1; end

Restricciones enlazadas y variables de enteros

Las variables de enteros son las de hasta el final.length(obj1) + 1

intcon = P*F*W+1:length(obj);

Los límites superiores son hasta el final también.length(obj1) + 1

lb = zeros(length(obj),1); ub = Inf(length(obj),1); ub(P*F*W+1:end) = 1;

Desactive la visualización iterativa para que no obtenga cientos de líneas de salida. Incluya una función de trazado para supervisar el progreso de la solución.

opts = optimoptions('intlinprog','Display','off','PlotFcn',@optimplotmilp);

Resolver el problema

Ha generado todas las entradas del solucionador. Llame al solucionador para encontrar la solución.

[solution,fval,exitflag,output] = intlinprog(obj,intcon,...                                      Aineq,bineq,Aeq,beq,lb,ub,opts);

if isempty(solution) % If the problem is infeasible or you stopped early with no solution     disp('intlinprog did not return a solution.')     return % Stop the script because there is nothing to examine end

Examine la solución

La solución es factible, dentro de las tolerancias dadas.

exitflag
exitflag = 1 
infeas1 = max(Aineq*solution - bineq)
infeas1 = 9.0949e-13 
infeas2 = norm(Aeq*solution - beq,Inf)
infeas2 = 5.8549e-12 

Compruebe que los componentes enteros son realmente enteros, o están lo suficientemente cerca que es razonable redondearlos. Para entender por qué estas variables pueden no ser exactamente enteros, vea.la documentación

diffint = norm(solution(intcon) - round(solution(intcon)),Inf)
diffint = 6.9944e-15 

Algunas variables de enteros no son exactamente enteros, pero todas están muy cercanas. Así redondea las variables enteras.

solution(intcon) = round(solution(intcon));

Compruebe la viabilidad de la solución redondeada y el cambio en el valor de la función objetiva.

infeas1 = max(Aineq*solution - bineq)
infeas1 = 9.0949e-13 
infeas2 = norm(Aeq*solution - beq,Inf)
infeas2 = 5.8549e-12 
diffrounding = norm(fval - obj(:)'*solution,Inf)
diffrounding = 2.9802e-08 

El redondeo de la solución no cambió sensiblemente su viabilidad.

Puede examinar la solución más fácilmente remodelando su tamaño original.

solution1 = solution(1:P*F*W); % The continuous variables solution2 = solution(intcon); % The integer variables solution1 = reshape(solution1,P,F,W); solution2 = reshape(solution2,S,W);

Por ejemplo, ¿cuántos puntos de venta están asociados a cada almacén? Tenga en cuenta que, en este caso, algunos almacenes tienen 0 salidas asociadas, lo que significa que los almacenes no están en uso en la solución óptima.

outlets = sum(solution2,1) % Sum over the sales outlets
outlets = 1×20

     3     0     3     2     2     2     3     2     3     1     1     0     0     3     4     3     2     3     2     1

Trace la conexión entre cada salida de ventas y su almacén.

figure(h); hold on for ii = 1:S     jj = find(solution2(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')

El negro * sin líneas verdes representa los almacenes no utilizados.

Temas relacionados