English version German version Italian version

Sesión 7: Formulando Modelos con Datos Dispersos en MPL

A menudo, cuando se trabaja con modelos grandes , los datos del modelo tienden a no ser compactos como fueron trabajados en el modelo anterior, sinó más bien en un formato disperso. Los datos compactos pueden ser percibidos de la misma manera como los datos en una hoja de cálculo. Ordinariamente, este es usado para vectores de datos con no más de dos dimensiones, donde cada columna y cada fila es llenada con datos.

Los datos Dispersos, por otro lado, tipicamente involucra multiples dimensiones, pero no necesariamente contienen valores para cada combinación de los índices. Los datos dispersos son usualmente almacenados en formato de tabla, donde cada columna representa un índice o un valor de dato. Cuando se trabaja con grandes conjunto de datos dispersos, es común trabajar con los datos en un formato de tabla. Esto le permite fácilmente saltarse ciertas combinaciones de los índices, que no son válidos, omitiéndolos en la tabla.


Nuevos Conceptos en esta Sesión

Indices de Equipos

Algunas veces, cuando formulamos modelos de planificación de la producción, la decisión involucra cuáles máquinas usar para producir los productos. Como todas las máquinas no están disponibles en cada planta, este presenta una dispersión en el modelo. Cunado definimos los datos y las variables vector del modelo, entonces utilizamos esa dispersión para asegurar que el tamaño del modelo no sea tan grande. Esto puede ser logrado, usando un comando estándar WHERE(Dónde) sobre el vector de datos, o usando el operador IN para asociar los índices relevantes.

Usando el Operador IN

El operador IN en MPL le permite seleccionar uno de los índices dominio de un índice multidimensional. Por ejemplo, si tiene un índice multidimensional que especifique cuáles máquinas están disponibles y en qué plantas, usted puede usar el operador IN para sumar sobre todas las máquinas para esa planta en particular.

     INDEX
        plant     := (p1, p2, p3, p4);
        machine   := (m11, m12, m13, m21, m22, m31, m32, m41);

        PlantMach[plant,machine]  :=

             (p1.m11, p1.m12, p1.m13,
              p2.m21, p2.m22,
              p3.m31, p3.m32,
              p4.m41);
    

En el ejemplo de arriba, hemos definido un índice multidimensional llamado PlantMach que asocia a las plantas con las correspondientes máquinas.

El índice PlantMach puede ser usado selectivamente, para elegir sólo las máquinas que están disponibles en una planta en particular. Por ejemplo:

     SUBJECT TO
        PlantCapacity[plant] :
           SUM(machine IN PlantMach: Produce[machine])  <=  MaxCapacity[plant];
    

En el ejemplo de arriba, sumamos todo cuánto es producido en cada máquina para una planta en particular. Luego nos aseguramos que la producción total esté limitada a la capacidad máxima.


Archivos Indices

Así como puede almacenar datos en un archivo externo de datos, también puede almacenar índices en archivos de índices externos. Los archivos de índices le permiten almacenar los elementos de un índice en un archivo, en lugar de especificarlos directamente en el modelo. Cuando está definiendo un índice con un archivo índice use la palabra clave INDEXFILE con un nombre de archivo en lugar del listado usual de los elementos. Por ejemplo:

     INDEX
        product    := INDEXFILE("Product.idx");
        month      := INDEXFILE("Month.idx");
        plant      := INDEXFILE("Plant.idx");

    

El archivo índice es justamente un archivo de texto estándar que contiene un listado de los elementos índices para un índice particular. Usted puede separar los elementos en el archivo con una coma, un espacio o ambos. Por ejemplo aquí hay un archivo de índice de muestra para el índice product(producto).

     !  Product.idx  -  Index element for the product index

         A1, A2, A3

    

Archivo de Datos Dispersos

Generalmente, cuando se trabaja con modelos dispersos, los datos involucrados son muy grandes y vienen de otras aplicaciones, tal como base de datos corporativos o de escritorio. En las sesiones anteriores, los datos fueron tipeados en el archivo del modelo o almacenados en un archivo de datos compactos. Cuando trabajamos con conjuntos de datos grandes, se necesita un método más eficiente para importar los datos a MPL desde otras aplicaciones. Para este propósito, MPL tiene la habilidad de leer los datos desde un archivo de datos dispersos. Este archivo le permite ingresar los datos en un formato de tabla estándar, el cual es más cercano a las actuales características de los datos, por ejemplo, desde una base datos relacional. Un ejemplo de un archivo de datos disperso puede ser como sigue:

        ProdCost[plant, machine, product]  := SPARSEFILE("ProdCost.dat");
    

El archivo ProdCost.dat contiene los datos en el formato de columnas orientadas con los índices en las tres primeras columnas y los correspondientes valores de datos al final de cada fila, como sigue:

              p1,  m11,  A1,  73.30,
              p1,  m11,  A2,  52.90,
              p1,  m12,  A3,  65.40,
                    .
                    .
                    .
              p4,  m41,  A2,  63.30,
              p4,  m41,  A3,  53.80
    

Por favor note, que MPL le permite también almacenar multiples columnas de datos en un simple archivo de datos dispersos. Puede especificar cuál columna, agregando una coma y el número de columna de los datos después del nombre de archivo que está dentro del paréntesis.

       ProdCost[plant, machine, product]  := SPARSEFILE("ProdCost.dat", 2);
    

El uso de archivos de datos dispersos es común en el modelado del mundo real. Esos archivos pueden terminar siendo muy grandes, con múltiples índices y contener cantidades de datos. Frecuentemente, se tendrá múltiples archivos índices y archivos de datos dispersos almacenando todos los datos y dejando que el archivo del modelo sólo tenga las sentencias actuales del modelo, tal como las variables, función objetivo y las restricciones.


Descripción del Problema: Un Modelo de Planificación con Múltiples Máquinas para cada Planta

En esta sesión, actualizará el modelo para tener múltiples máquinas distribuídas entre las plantas. Usará el modelo creado en la sesión 6, y haga las adiciones y actualizaciones necesarias.

Puesto que ahora tenemos diferentes máquinas dentro de cada planta, el costo de producción y la tasa de producción tienen ahora diferentes valores para cada máquina. La siguiente es una tabla con una sola fila para cada planta, combinación de productos y máquinas que son aplicables.

La decisión de Producción, cuánto producir de cada producto, necesita tomarse en cuenta que ahora tenemos múltiples máquinas. Además, se actualizará la variable Produce(Producción) para incluir el índice machine (Máquina) y luego usará la condición WHERE para excluir los elementos que no son aplicables, tal como la planta p1, máquina m11, y producto A3.


Formulación del Modelo con MPL

El listado de abajo es la formulación del modelo completo Planning7. Las adiciones al modelo son resaltadas en negritas para hacer más fácil ver los cambios con respecto al modelo de la sesión 6.

     TITLE
         Production_Planning7;

     INDEX
         product    :=  (A1, A2, A3);
         month      :=  (Jan, Feb, Mar, Apr);
         plant      :=  (p1, p2, p3, p4);
         toplant    :=  plant;
         fromplant  :=  plant;
         machine    :=  (m11, m12, m13, m21, m22, m31, m32, m41);

     DATA
         Price[product]                     :=  (120.00, 100.00, 115.00);
         Demand[plant, product, month]      :=  DATAFILE("Demand6.dat");
         ProdCost[plant, machine, product]  :=  SPARSEFILE("Produce.dat", 1);

         ProdRate[plant, machine, product]  :=  SPARSEFILE("Produce.dat", 2);
         ProdDaysAvail[month]               :=  (23, 20, 23, 22);
         InvtCost[plant, product]           :=  DATAFILE("InvtCost.dat");
         InvtCapacity[plant]                :=  (800, 400, 500, 400);
         ShipCost[fromplant, toplant]       :=  DATAFILE ("ShipCost.dat");

     VARIABLES
         Produce[plant, machine, product, month] -> Prod
             WHERE (ProdCost > 0);

         Inventory[plant, product, month]        -> Invt;
         Sales[plant, product, month]            -> Sale;
         Ship[product, month, fromplant, toplant]
             WHERE (fromplant <> toplant);

     MACROS
         TotalRevenue  := SUM(plant, product, month: Price * Sales);
         TotalProdCost := SUM(plant, machine, product,month: ProdCost * Produce);
         TotalInvtCost := SUM(plant, product, month: InvtCost * Inventory);
         TotalShipCost := SUM(product, month, fromplant, toplant: ShipCost * Ship);
         TotalCost     := TotalProdCost + TotalInvtCost + TotalShipCost;

     MODEL

         MAX Profit  =  TotalRevenue - TotalCost;

     SUBJECT TO
         ProdCapacity[plant, machine, month] -> PCap:
             SUM(product: Produce / ProdRate)  <=  ProdDaysAvail;

         PlantBal[plant, product, month] -> PBal:
               SUM(machine: Produce) + Inventory[month-1]
             + SUM(fromplant: Ship[fromplant, toplant:=plant])
           =
               Sales + Inventory
             + SUM(toplant: Ship[fromplant:=plant, toplant]);

         MaxInventory[plant, month] -> MaxI:
            SUM(product: Inventory)  <=  InvtCapacity;

     BOUNDS
        Sales  <  Demand;

     END
    

Ingrese Nuevos Elementos al Modelo Paso a Paso

Paso 1: Inicie MPL y Cree un Nuevo Modelo

  1. Inicie la aplicación MPL.

  2. Elija File (Archivo) | Open (Abrir) y abra el modelo de la sesión anterior Planning6.mpl.

  3. Elija File (Archivo ) | Save As (Guardar Cómo) para guardarlo como un nuevo archivo del modelo Planning7.mpl.

Paso 2: Cambie el Título del Modelo

Cambie el título del modelo para que refleje que se está trabajando con el modelo Planning7.

     TITLE
         Production_Planning7;
    

Paso 3: Agregue al Modelo el Indice 'machine'

En este modelo, cada planta tiene ahora múltiples máquinas. Para crear un índice para las máquinas agregue la siguiente definición para el índice machine(máquina) en la sección INDEX.

     INDEX
         product   :=  (A1, A2, A3);
         month     :=  (Jan, Feb, Mar, Apr);
         plant     :=  (p1, p2, p3, p4);
         toplant   :=  plant;
         fromplant :=  plant;
         machine   :=  (m11, m12, m13, m21, m22, m31, m32, m41);
    

Paso 4: Actualice los Vectores de Datos 'ProdCost' y 'ProdRate' para ser Incluídos en el Indice 'machine'

El costo de producción y la tasa de producción necesitan ahora ser incluídos al índice de máquinas puesto que tienen diferentes valores para cada máquina. También, puesto que ahora los datos están dispersos, esto es, cada planta no tiene asociado sus máquinas, estaremos almacenando los datos en un archivo de datos dispersos. MPL le permite almacenar mútiples columnas de datos en un archivo sencillo de datos dispersos. Especifique cuál columna va a leer agregando una coma y el número de columna después del nombre del archivo.

Actualice las definiciones para los vectores de datos ProdCost y ProdRate para ser incluídos en el índice machine y cambiar el nombre de archivo a un nuevo archivo de datos dispersos llamado Produce.dat. Para el costo de producción especifique el número de columna 1 después del nombre de archivo y para la tasa de producción especifique el número de columna 2.

     DATA
         Price[product]                     :=  (120.00, 100.00, 115.00);
         Demand[plant, product, month]      :=  DATAFILE("Demand6.dat");
         ProdCost[plant, machine, product]  :=  SPARSEFILE("Produce.dat", 1);
         ProdRate[plant, machine, product]  :=  SPARSEFILE("Produce.dat", 2);
         ProdDaysAvail[month]               :=  (23, 20, 23, 22);
         InvtCost[product]                  :=  DATAFILE("InvtCost.dat");
         InvtCapacity[plant]                :=  (800, 400, 500, 400);
         ShipCost[fromplant, toplant]       :=  DATAFILE("ShipCost.dat");
    

Paso 5: Creando Archivos de Datos Dispersos para el Costo de Producción y la Tasa de Producción

Ahora necesita crear el archivo de datos dispersos Produce.dat de los datos en la descripción del problema anterior dados en esta sesión.

Para crear el archivo de datos para el costo de producción abra una nueva ventana del editor para el archivo de datos llamado Produce.dat y escriba lo siguiente:

     !
     !  Produce.dat  -  Production Cost and Rate
     !
     !  ProdCost[plant, machine, product]:
     !  ProdRate[plant, machine, product]:
     !

               p1,  m11,  A1,  73.30,  500,
               p1,  m11,  A2,  52.90,  450,
               p1,  m12,  A3,  65.40,  550,
               p1,  m13,  A3,  47.60,  350,

               p2,  m21,  A1,  79.00,  550,
               p2,  m21,  A3,  66.80,  450,
               p2,  m22,  A2,  52.00,  300,

               p3,  m31,  A1,  75.80,  450,
               p3,  m31,  A3,  50.90,  300,
               p3,  m32,  A1,  79.90,  400,
               p3,  m32,  A2,  52.10,  350,

               p4,  m41,  A1,  82.70,  550,
               p4,  m41,  A2,  63.30,  400,
               p4,  m41,  A3,  53.80,  350,
    

Paso 6: Actualice el Vector de la Variable Produce para incluirla en el Indice 'machine'

La variable Produce necesita ahora tener el índice machine en las declaraciones como necesitamos saber en qué máquina es producido cada producto. Además, puesto que no todas la máquinas están en cada planta necesitamos excluir las combinaciones que no son válidas. Esto es hecho usando la condición where sobre el vector de datos ProdCost. Las combinaciones de índices son usados sólo cuando ProdCost es mayor que cero o cuando la variable Produce es ampliada. Ingrese los cambios a la variables produce como sigue:

     VARIABLES
         Produce[plant, machine, product, month] -> Prod
             WHERE (ProdCost > 0);
    

Paso 7: Agregue el Indice 'machine' a la Macro del Costo Total de Producción

En la macro del costo total de producción, agregue el índice machine para que refleje que la variable produce contiene ahora el índice machine.

     MACROS
         TotalRevenue  := SUM(plant, product, month: Price * Sales);
         TotalProdCost := SUM(plant, machine, product,month: ProdCost * Produce);
         TotalInvtCost := SUM(plant, product, month: InvtCost * Inventory);
         TotalShipCost := SUM(product, month, fromplant,toplant: ShipCost * Ship);
         TotalCost     := TotalProdCost + TotalInvtCost + TotalShipCost;
    

Paso 8: Actualice la Restricción 'ProdCapacity' para ser Incluida en el Indice 'machine'

En la declaración de la restricción de la capacidad de la producción, el índice machine debe ser incluído puesto que ahora tiene un límite de capacidad separada para cada máquina en la planta. Ingrese los cambios a la restricción ProdCapacity como sigue:

     SUBJECT TO
        ProdCapacity[plant, machine, month] -> PCap:
            SUM(product: Produce / ProdRate)  <=  ProdDaysAvail;
    

Paso 9: Actualice la Restricción de Equilibrio de Planta para Sumar la Variable Produce a Todas las Máquinas

En la restricción de equilibrio de planta hay una variable produce separada para cada máquina. Como necesitamos agregar junto al total de producción para una planta en particular, necesitamos ahora sumar sobre el índice máquina cuando se refiera a la variables Produce. Para hacer esto agregue la siguiente sumatoria a la restricción PlantBal:

     PlantBal[plant, product, month] -> PBal:
           SUM(machine: Produce) + Inventory[month-1]
         + SUM(fromplant:  Ship[fromplant, toplant:=plant])
       =
           Sales + Inventory
         + SUM(toplant:  Ship[fromplant:=plant, toplant]);
    

Resuelva el Modelo y Analice la Solución

El próximo paso es resolver el modelo 'Planning7.mpl' eligiendo Solve CPLEX del menú Run. Sí todo está bien MPL visualizará el mensaje 'Optimal Solution Found' ( Solución Optima Encontrada) . Sí subiera algún error de sintáxis, por favor verifique la formulación ingresada anteriormente en esta sesión del modelo detallado.

Usará la ventana de definición del modelo otra vez, como en la sesión 6, para mirar las partes de la solución que sean de su interés. Para abrir la ventana de definición del Planning7 elija Model Definitions del menú View (Ver).

Ventana Arbol de Definición del Modelo Planning7

Para ver los valores de la variable Produce haga doble click sobre el icono produce del árbol o seleccionelo y presione el botón View(ver). Este visualizará la ventana View(Ver) conteniendo los valores de la solución solo para la variable produce tal como se muestra más abajo.

     VARIABLE Produce[plant,machine,product,month] :

   plant  machine  product  month           Activity     Reduced Cost
  --------------------------------------------------------------------
   p1     m11      A1       Jan           4300.0000           0.0000
   p1     m11      A1       Feb           4200.0000           0.0000
   p1     m11      A1       Mar           5487.5000           0.0000
   p1     m11      A1       Apr           5300.0000           0.0000
   p1     m11      A2       Jan           6480.0000           0.0000
   p1     m11      A2       Feb           5220.0000           0.0000
   p1     m11      A2       Mar           5411.2500           0.0000
   p1     m11      A2       Apr           5130.0000           0.0000
   p1     m12      A3       Feb           9049.3506           0.0000
   p1     m12      A3       Mar            916.1616           0.0000
   p1     m12      A3       Apr          10803.1169           0.0000
   p1     m13      A3       Jan           8050.0000           0.0000
   p1     m13      A3       Feb           7000.0000           0.0000
   p1     m13      A3       Mar           8050.0000           0.0000
   p1     m13      A3       Apr           7700.0000           0.0000
   p2     m21      A1       Jan           5100.0000           0.0000
   p2     m21      A1       Feb           6200.0000           0.0000
   p2     m21      A1       Mar           6538.8889           0.0000
   p2     m21      A1       Apr           7600.0000           0.0000
   p2     m21      A3       Jan           4422.6136           0.0000
   p2     m21      A3       Feb           3927.2727           0.0000
   p2     m21      A3       Mar           5000.0000           0.0000
   p2     m21      A3       Apr           3681.8182           0.0000
   p2     m22      A2       Jan           6900.0000           0.0000
   p2     m22      A2       Feb           6000.0000           0.0000
   p2     m22      A2       Mar           6900.0000           0.0000
   p2     m22      A2       Apr           6600.0000           0.0000
   p3     m31      A1       Jan           3300.0000           0.0000
   p3     m31      A1       Feb           5964.9351           0.0000
   p3     m31      A1       Mar           2550.0000           0.0000
   p3     m31      A1       Apr           4477.4026           0.0000
   p3     m31      A3       Jan           4700.0000           0.0000
   p3     m31      A3       Feb           2023.3766           0.0000
   p3     m31      A3       Mar           5200.0000           0.0000
   p3     m31      A3       Apr           3615.0649           0.0000
   p3     m32      A1       Jan            800.0000           0.0000
   p3     m32      A1       Feb            135.0649           0.0000
   p3     m32      A1       Mar           2150.0000           0.0000
   p3     m32      A1       Apr           1322.5974           0.0000
   p3     m32      A2       Jan           7350.0000           0.0000
   p3     m32      A2       Feb           6881.8182           0.0000
   p3     m32      A2       Mar           6168.7500           0.0000
   p3     m32      A2       Apr           6542.7273           0.0000
   p4     m41      A1       Jan           4300.0000           0.0000
   p4     m41      A1       Feb           4100.0000           0.0000
   p4     m41      A1       Mar           5073.6111           0.0000
   p4     m41      A1       Apr           4500.0000           0.0000
   p4     m41      A2       Jan           2270.0000           0.0000
   p4     m41      A2       Feb           5018.1818           0.0000
   p4     m41      A2       Mar           2500.0000           0.0000
   p4     m41      A2       Apr           5527.2727           0.0000
   p4     m41      A3       Jan           3327.3864           0.0000
   p4     m41      A3       Mar           2633.8384           0.0000
  --------------------------------------------------------------------
  

La variable Produce está ahora definida sobre cuatro índices: plant(planta), machine(máquina), product(producto) y month(mes). Para cada planta el modelo decide qué máquina es la más eficiente para producir los productos en una planta en particular. Esta tabla puede ser usada como base para un programa de producción para la compañía completa.

La otra variable que es interesante en este modelo es la variable Inventory. Sí va a la ventana del árbol otra vez y abre la ventana View(Ver) para la variable Inventory obtendrá los siguientes valores de la solución:

     VARIABLE Inventory[plant,product,month] :

        plant  product  month           Activity     Reduced Cost
       -----------------------------------------------------------
        p1     A2       Jan            800.0000           0.0000
        p2     A2       Jan            400.0000           0.0000
        p3     A3       Jan            500.0000           0.0000
        p4     A3       Jan            400.0000           0.0000
       -----------------------------------------------------------
    

Como usted ve, el modelo ha decidido producir los productos A2 y A3 durante el mes de Enero para asegurar tener lo suficiente en el mes de Febrero.

Muchas de las plantas ahora están trabajando a su capacidad total. Sí usted va a la ventana del árbol y abre otra vez la ventana View(Ver) para la restricción ProdCapacity obtendrá los siguientes valores de la solución:

     CONSTRAINT ProdCapacity[plant,machine,month] :

        plant  machine  month              Slack     Shadow Price
       -----------------------------------------------------------
        p1     m12      Jan             23.0000           0.0000
        p1     m12      Feb              3.9595           0.0000
        p1     m12      Mar             20.2682           0.0000
        p1     m12      Apr              1.2033           0.0000
        p2     m21      Jan              3.6947           0.0000
       -----------------------------------------------------------
    

Como usted puede ver la planta p1 tiene alguna capacidad extra en la máquina m12 y la planta p2 tiene alguna capacidad extra para la máquina m21. Otra cosa también es que todas las máquinas en cada planta están trabajando a su capacidad total para satisfacer la demanda.


Back To Top | Maximal Home Page | Overview | Previous Page | Next Page