You are on page 1of 16

Modelos de la Investigacin Operativa

Grado en Matemticas
Facultad de Ciencias.
Prctica N o 1.

Ejercicio 1: Una pequea carpintera hace dos tipos de caja de maderas para juegos de ajedrez.
La pequea requiere 3 horas de trabajo en el torno y la grande 2 horas. Hay cuatro tornos que
pueden trabajar 40 horas a la semana, es decir, hay una disponibilidad semanal de 160 horas
de trabajo. La caja pequea requiere un kilo de madera y la grande tres. Se dispone de 200 kg.
de madera por semana y el beneficio de las caja es 20e para la grande y 5e para la pequea.
Decidir cuntas cajas de cada tipo deben producirse durante una semana para maximizar el
beneficio.

model Chess
uses "mmxprs" ! We shall use Xpress-Optimizer

declarations
xs, xl: mpvar ! Decision variables: produced quantities
end-declarations

Profit:= 5*xs + 20*xl ! Objective function


Boxwood:= 1*xs + 3*xl <= 200 ! kg of boxwood
Lathe:= 3*xs + 2*xl <= 160 ! Lathehours

maximize(Profit) ! Solve the problem

writeln("LP Solution:") ! Solution printing


writeln(" Objective: ", getobjval)
writeln("Make ", getsol(xs), " small sets")
writeln("Make ", getsol(xl), " large sets")
end-model

Ejercicio 2: (El problema del ladrn) Un ladrn observa ocho objetos de diferente peso y valor.
l desea elegir los objetos con el mayor valor posible pero que el peso no sea ms del mximo
peso WTMAX que el puede llevar.
Introducimos variables binarias xi para cada objeto i. Sea vi y wi el valor del objeto y el
peso respectivamente del objeto i. Una formulacin al problema es:
X
max ci xi
iO
s.t.
X
wi xi W T MAX
iO
xi {0, 1}

Este problema es un ejemplo de problema de la mochila que puede ser implementado en


MOSEL como sigue:

model "Burglar 1"


uses "mmxprs"
declarations
ITEMS = 1..8 ! Index range for items
WTMAX = 102 ! Maximum weight allowed
VALUE: array(ITEMS) of real ! Value of items
WEIGHT: array(ITEMS) of real ! Weight of items
take: array(ITEMS) of mpvar ! 1 if we take item i; 0 otherwise
end-declarations

! Item: 1 2 3 4 5 6 7 8
VALUE :: [15, 100, 90, 60, 40, 15, 10, 1]
WEIGHT:: [ 2, 20, 20, 30, 40, 30, 60, 10]

! Objective: maximize total value


MaxVal:= sum(i in ITEMS) VALUE(i)*take(i)

! Weight restriction
sum(i in ITEMS) WEIGHT(i)*take(i) <= WTMAX

! All variables are 0/1


forall(i in ITEMS) take(i) is_binary

maximize(MaxVal) ! Solve the MIP-problem

! Print out the solution


writeln("Solution:\n Objective: ", getobjval)
forall(i in ITEMS) writeln(" take(", i, "): ", getsol(take(i)))
end-model

Cuando corremos este modelo obtenemos la siguiente salida:

Solution:
Objective: 280
take(1): 1
take(2): 1
take(3): 1
take(4): 1
take(5): 0
take(6): 1
take(7): 0
take(8): 0

La estructura de este modelo y de cualquier modelo MOSEL en general es la siguiente:

Model: Cada programa de Mosel comienza con la palabra model, seguido de un nombre
y termina con end-model.

Declarations: Todos los objetos deben ser declaros en este bloque, excepto en el caso
que se definan a travs de asignaciones directa (como i:=1, que significa que i es un
entero y que vale 1, en nuestro ejemplo, MaxVal se define como la asignacin de una
expresin lineal). Puede haber varias declaraciones de este tipo, as como varios bloques
de declaracin en diferentes lugares del modelo.

Definicin del problema: usualmente el problema empieza con la especificacin de los datos
(en el ejemplo, asignacin de valores a VALUE y WEIGHT), seguido por la definicin del
problema (en el ejemplo, definicin de funcin objetivo MaxVal, definicin de la restriccin
y especificacin de las variables a ser binarias).

Salida: Las ltimas dos lneas imprimen los valores de las solucin ptima y de los valores
de las variables de decisin.

Separacin de lneas: Es posible poner varias instrucciones en una misma lnea, pero tienen
que estar separadas por ";". De igual forma, si una instruccin ocupa ms de una lnea,
el ltimo smbolo de la lnea debe ser (+,>=, etc) para que el programa entienda que la
instruccin no se acaba en esta lnea.
Comentario: El smbolo ! significa el comienzo de un comentario el cual contina hasta el
final de la lnea. Para ms lneas se usa (! y se acaba con !).

Explicamos ahora ciertas instrucciones en este modelo con ms detalle:

Rangos y conjuntos:

ITEMS = 1..8

define un rango de nmeros enteros consecutivos desde el 1 al 8. Este rango es usado


como ndice para las cadenas de datos (arrays) (en el ejemplo, VALUE y WEIGHT) y
para los arrays de las variables de decisin. En vez de usar ndices numricos, podramos
haber definido ITEMS como una cadena de smbolos reemplazando la definicin actual
ITEMS=1..8 con la siguiente definicin (sin hacer otro cambio en el modelo):
ITEMS={"camara","necklace","vase","picture","tv","video","chest","brick"}
! Index set for items

Arrays: VALUE: array(ITEMS) of real


Define un array unidimensional de valores reales indexados por el rango ITEMS. Un
array multidimensional son declarados de forma similar, por ejemplo,
VAL3: array(ITEMS, 1..20, ITEMS) of real
declara un array 3-dimensional de valores reales. Los arrays (tipo mpvar) de variables
de decisin son declarados de igual modo. Todos los objetos declarados (escalares o arrays)
siempre se inicializan por defecto con el valor:
real, integer: 0
boolean: false
string: (i.e. cadena vaca)
Las valores de los datos pueden ser asignados en el modelo como en el ejemplo o bien, a
travs de de un fichero.

Sumatorios:
MaxVal:= sum(i in ITEMS) VALUE(i)*x(i)
P
Define una expresin lineal llamada MaxVal como la suma iIT EM S V ALUEi xi .

Bucles: forall(i in ITEMS) take(i) is_binary


Ilustra los bucles sobre todos los valores del rango de ndices. Recordar que el rango del
los ndices ITEMS es 1, . . . , 8, por tanto, el comando nos dice que take(1), take(2), ...,
take(8) son todas variables binarias. Hay otro ejemplo del uso de forall aparece en la
penltima lnea del modelo.

Tipos de variables en programacin entera: Para hacer una variable mpvar, por ejemplo
xbinvar, en variable binarias {0, 1}:
xbinvar is_binary
Para hacer una variable mpvar una variable entera:
xintvar is_integer

1. Lectura de datos de un fichero de texto

El siguiente ejemplo ilustra como los datos pueden ser ledos desde un fichero de texto. En
el problema el ladrn en vez de tener los datos en el modelo, lo tenemos en un fichero aparte
hacindolo de la siguiente forma:

model "Burglar 2"


uses "mmxprs"
declarations
ITEMS= 1..8 ! Set of items
WTMAX = 102 ! Maximum weight allowed
VALUE: array(ITEMS) of real ! Value of items
WEIGHT: array(ITEMS) of real ! Weight of items
end-declarations
initializations from burglar.dat
VALUE
WEIGHT
end-initializations
declarations
take: array(ITEMS) of mpvar ! 1 if we take item i; 0 otherwise
end-declarations
! Objective: maximize total value
MaxVal:= sum(i in ITEMS) VALUE(i)*take(i)
! Weight restriction
sum(i in ITEMS) WEIGHT(i)*take(i) <= WTMAX
! All variables are 0/1
forall(i in ITEMS) take(i) is_binary
maximize(MaxVal) ! Solve the MIP-problem
! Print out the solution
writeln("Solution:\n Objective: ", getobjval)
forall(i in ITEMS) writeln(" take(", i, "): ", getsol(take(i)))
end-model

El fichero de datos burglar2_1.dat tiene el siguiente contenido:

VALUE: [15, 100, 90, 60, 40, 15, 10, 1]


WEIGHT: [ 2, 20, 20, 30, 40, 30, 60, 10]

Segunda opcin: cambiando ITEMS= 1..8 ! Set of items por ITEMS: set of string !
Set of items y usando burglar2_2.dat con el siguiente contenido

VALUE: [("camera") 15 ("necklace") 100 ("vase") 90 ("picture") 60 ("tv")


40 ("video") 15 ("chest") 10 ("brick") 1]
WEIGHT:[("camera") 2 ("necklace") 20 ("vase") 20 ("picture") 30 ("tv")
40 ("video") 30 ("chest") 60 ("brick") 10]

El bloque de inicializacin dice a MOSEL desde dnde obtener los datos para inicializar los
conjuntos y arrays. El orden de los datos en el fichero no tiene que ser el mismo que en el bloque
de inicializacin. Observar que el conjunto ITEMS es definido indirectamente a travs del valor
de los ndices del array VALUE y WEIGHT. Nosotros solo declaramos las variables una vez
que los datos han sido incializados y para entonces, el conjunto ITEMS es ya conocido.
Los datos tambin pueden ser dados en una nica secuencia de la siguiente forma

initializations from burglar2_3.dat


[VALUE, WEIGHT] as KNAPSACK
end-initializations

y el fichero de datos

KNAPSACK: [ ("camera") [ 15 2] ("necklace") [100 20] ("vase") [ 90 20] ("picture") [ 6


("tv") [ 40 40] ("video") [ 15 30] ("chest") [ 10 60] ("brick") [ 1 10] ]

2. Palabras reservadas

Las siguientes palabras estn reservadas en MOSEL, por tanto, no se deben usar excepto
para lo que estn diseadas:
and, array, as
boolean, break
case
declarations, div, do, dynamic
elif, else, end
false, forall, forward, from, function
if, in, include, initialisations, initializations, integer, inter,
is_binary, is_continuous, is_free, is_integer, is_partint, is_semcont,
is_semint, is_sos1, is_sos2
linctr
max, min, mod, model, mpvar
next, not
of, options, or
parameters, procedure, public, prod
range, real, repeat
set, string, sum
then, to, true
union, until, uses
while

Ejercicio 3: Una compaa de acero ha recibido un pedido de 500 toneladas de acero para
ser usada en la construccin de barcos. Este acero debe tener las siguientes caractersticas
(grados):

Elemento Qumico Mnimo grado Mximo grade


Carbon (C) 2 3
Cobre (Cu) 0.4 0.6
Manganeso (Mn) 1.2 1.65

La compana tiene siete diferentes materias primas en el almacn que puede ser usada para
producir acero:
Materia Prima C% Cu % Mn % Disponibilidad en t Costo en e/t
Aleacin de Hierro 1 2.5 0 1.3 400 200
Aleacin de Hierro 2 3 0 0.8 300 250
Aleacin de Hierro 3 0 0.3 0 600 150
Aleacin de Cobre 1 0 90 0 500 220
Aleacin de Cobre 2 0 96 4 200 240
Aleacin de Aluminio 1 0 0.4 1.2 300 200
Aleacin de Aluminio 2 0 0.6 0 250 165

El objetivo es determinar la composicin del acero que minimiza el coste de produccin.


Observacin:
Para imprimir la solucin usar la instruccin if-then de Mosel, que puede ser usada en las
siguientes formas if-then-else o if-then-elif-then-else:

writeln("Coste total: ", getobjval)


writeln("Cantidad de acero producido: ", getsol(produce))
writeln("Aleacin usada")
forall(r in RAW)
if(getsol(use(r))>0) then
write(NAMES(r), ": ", getsol(use(r))," ")
end-if
write("\nPercentages (C, Cu, Mn): ")
forall(c in COMP)
write( getsol(sum(r in RAW) P(r,c)*use(r))/getsol(produce), "% ")
writeln

Ejercicio 4: Una compaa de piensos para animales fabrica dos tipos de piensos: en polvo o
granulado. La materia prima usada para la produccin del pienso son: avena, maz y melaza.
La materia prima (a excepcin de la melaza) primero necesita ser molido y entonces el pienso
resulta de mezclar las materias prima. En el ltimo paso del proceso de produccin, la mezcla
se transforma en grnulo o en polvo.
Cada pienso necesita satisfacer ciertos requerimientos nutricionales. Los porcentajes de pro-
tenas, lpidos y fibras contenido en cada uno de los componentes usados para fabricar el pienso
as como los porcentajes requerido en los productos finales son:
Materia prima Protenas Lpidos Fibra
Avena 13.6 7.1 7
Maz 4.1 2.4 3.7
Melaza 5 0.3 25
Contenido Requerido 9.5 2 6

Adems se tiene una serie de restricciones en la disponibilidad de materia prima que vienen
descritas en la siguiente tabla, junto con los respectivos precios:

Materia Prima Cantidad disponible en kg Costo en e/kg


Avena 11900 0.13
Maz 23500 0.17
Melaza 750 0.12

El costo de los diferentes pasos en la produccin vienen descritos a continuacin:

Moler Mezcla Granulacin Pulverizacin


0.25 0.05 0.42 0.17

Si la empresa tiene una demanda diaria de 9 toneladas de pienso granulado y 12 toneladas en


polvo, que cantidad de materia prima se neceista y cmo deben ser mezclados para minimizar
el costo total.
Observacin: Imprimir las soluciones usando estas instrucciones:

! Solution printing
writeln("Total cost: ", getobjval)
write("Food type"); forall(r in RAW) write(strfmt(r,9))
writeln(" protein lipid fiber")
forall(f in FOOD) do
write(strfmt(f,-9))
forall(r in RAW) write(strfmt(getsol(use(r,f)),9,2))
forall(c in COMP) write(" ",
strfmt(getsol(sum(r in RAW) P(r,c)*use(r,f))/getsol(produce(f)),3,2),"%")
writeln
end-do
Ejercicio 5: Una refinera produce butano, gasolina, gasleo y gasleo de calefaccin a par-
tir de dos crudos. Estos productos pueden obtenerse a travs de cuatro tipo de operaciones:
destilacin, refinado, catlisis y desulfuracin.
La fase de destilacin consiste en separar el producto en otros como butano, nafta, gasolil y
residuos. Los productos obtenidos son refinados o desulfurados para aumentar su octanaje. Los
residuos siguen con una fase de catlisis para obtener productos ms ligeros. Finalmente, para
obtener los productos que sern vendidos, la refinera mezcla varios tipos de estos productos
intermedios para cumplir con las caractersticas de un producto comercial.
Despus de la destilacin, crudo 1 proporciona un 3 % nafta, 40 % de gasoil, y 15 % de
residuos. Crudo 2 supone un 5 % de butano, 20 % de nafta, 35 % de gasoli y 10 % de residuos.
El refinado del nafta proporciona 15 % de butano y 85 % de nafta refinada. La catlisis de los
residuos supone un 40 % de nafta craqueada, 35 % de gasoil craqueado y un 25 % de desperdicio.
El gasoil es completamente sulfurado para generar gasoil para vender.
La gasolina es producida con tres ingredientes: nafta refinada, butano y nafta craqueada.
El gasleo se obtiene tras mezclar gasoil desulfurado, gasoil craqueado y nafta craqueada.
Por ley se tienen ciertas condiciones en la calidad de la gasolina y el gasoil. Para la gasolina
hay tres importantes caracterstica: el octanaje, la presin y la volatibilidad. El valor del octa-
naje es una medida antidetonante en el motor. La presin del vapor es una medida del riesgo
de explosin durante el almacenamiento y especialmente con tiempo clido. La volatibilidad
es una medida de cmo de fcil es arrancar un motor en tiempo fro. Finalmente, el mximo
contenido de sulfuro en el gasoil es impuesto por especificaciones antipolucin. La siguiente
tabla resume los requerimientos del producto final y la composicin intermedia.
Caract. Butano Nafta Ref. Nafta Cr. G-oil Cr. G-oil desulf. Gasolina Gasoil
Octan. 120 100 74 - - 94 -
Presin 60 2.6 4.1 - - 12.7 -
Volat. 105 3 12 - - 17 -
Sulf. (in %) - - 0.12 0.76 0.03 - 0.05
En el prximo mes la refinera necesita producir 20.000 toneladas de butano, 40.000 toneladas
de gasolina, 30.000 toneladas de gasoil, y 42.000 toneladas de carburante para calefaccin. Se
dispone de 250.000 toneladas de crudo 1 y 500.000 de crudo 2. La capacidad mensual de la
refinera para destilar son 30.000 toneladas, 40.000 para la desulfuracin, y 50.000 toneladas
para el craqueo. El costo de los procesos est basado en el uso crudo y la catlisis para las
diferentes operaciones: costo de destilacin, refinado, desulfuracin y craqueo son 2.10 e, 4.18
e, 2.04 e y 0.60e por tonelada, respectivamente.
But. But.

But.

Refinado
Ref.
Naf. Pet.

Cru. Nafc
Destilacin
Res. Heat.
Catlisis
Oilc

Oil. Sulf. Die.


Desulfuracin
Implementacin:

model "A-3 Refinery planning"


uses "mmxprs"
declarations
CRUDES: set of string ! Set of crudes
ALLPRODS: set of string ! Intermediate and final products
FINAL: set of string ! Final products
IDIST: set of string ! Products obtained by distillation
IREF: set of string ! Products obtained by reforming
ICRACK: set of string ! Products obtained by cracking
IPETROL: set of string ! Interm. products for petrol
IDIESEL: set of string ! Interm. products for diesel
IHO={"hogasoil", "hocrknaphtha", "hocrkgasoil"}
! Interm. products for heating oil
DEM: array(FINAL) of real ! Min. production
COST: array(set of string) of real ! Production costs
AVAIL: array(CRUDES) of real ! Crude availability
OCT, VAP, VOL: array(IPETROL) of real ! Octane, vapor pressure, and
! volatility values
SULF: array(IDIESEL) of real ! Sulfur contents
DIST: array(CRUDES,IDIST) of real ! Composition of crudes (in %)
REF: array(IREF) of real ! Results of reforming (in %)
CRACK: array(ICRACK) of real ! Results of cracking (in %)
end-declarations
initializations from a3refine.dat
DEM COST OCT VAP VOL SULF AVAIL DIST REF CRACK
end-initializations
finalize(FINAL); finalize(CRUDES); finalize(IPETROL); finalize(IDIESEL)
finalize(IDIST); finalize(IREF); finalize(ICRACK)
ALLPRODS:= FINAL+IDIST+IREF+ICRACK+IPETROL+IHO+IDIESEL
declarations
use: array(CRUDES) of mpvar ! Quantities used
produce: array(ALLPRODS) of mpvar ! Quantities produced
end-declarations
! Objective function
Cost:= sum(c in CRUDES) COST(c)*use(c) + sum(p in IDIST) COST(p)*produce(p)
! Relations intermediate products resulting of distillation - raw materials
forall(p in IDIST) produce(p) <= sum(c in CRUDES) DIST(c,p)*use(c)
! Relations between intermediate products
! Reforming:
forall(p in IREF) produce(p) <= REF(p)*produce("naphtha")
! Cracking:
forall(p in ICRACK) produce(p) <= CRACK(p)*produce("residue")
produce("crknaphtha") >= produce("petcrknaphtha") +
produce("hocrknaphtha") + produce("dslcrknaphtha")
produce("crkgasoil") >= produce("hocrkgasoil") + produce("dslcrkgasoil")
! Desulfurization:
produce("gasoil") >= produce("hogasoil") + produce("dslgasoil")
! Relations final products - intermediate products
produce("butane") = produce("distbutane") + produce("refbutane") -
produce("petbutane")
produce("petrol") = sum(p in IPETROL) produce(p)
produce("diesel") = sum(p in IDIESEL) produce(p)
produce("heating") = sum(p in IHO) produce(p)
! Properties of petrol
sum(p in IPETROL) OCT(p)*produce(p) >= 94*produce("petrol")
sum(p in IPETROL) VAP(p)*produce(p) <= 12.7*produce("petrol")
sum(p in IPETROL) VOL(p)*produce(p) >= 17*produce("petrol")
! Limit on sulfur in diesel oil
sum(p in IDIESEL) SULF(p)*produce(p) <= 0.05*produce("diesel")
! Crude availabilities
forall(c in CRUDES) use(c) <= AVAIL(c)
! Production capacities
produce("naphtha") <= 30000 ! Reformer
produce("residue") <= 40000 ! Desulfurization
produce("gasoil") <= 50000 ! Cracker
! Satisfy demands
forall(p in FINAL) produce(p) >= DEM(p)
! Solve the problem
minimize(Cost)
end-model

La inicializacin dinmica del conjunto de ndices necesita un tratamento especfico de los arrays
de las variables use y produce. Si nosotros declaramos estos arrays al mismo tiempo que los
datos, estos resultaran vacos. Sin embargo, en arrays dinmicos puesto que el conjunto de
indices no se conocen de antemano los datos han sido ledos desde el fichero. Mientras que las
componentes de otro tipos de las mpvar son creados cuando la entrada es direccionada, este no
es el caso del array de las variables. Hay dos posibilidades de gestionar esta situacin:

En la implementacin mostrada arriba, definimos las variables en un bloque separado


despus de que los datos hayan sido ledos desde el fichero. Este bloque es precedido
por una serie de instrucciones finalize. Con la ayuda del procedimiento finalize, el
conjunto de ndices dinmico se vuelve a conjunto constante, es decir, sus contenidos no
pueden ser modificados. Como consecuencia, todos los arrays con estos conjuntos como
sus ndices y que son declarado despus de este punto son creados como arrays de tamao
fijo.

Alternativamente, podemos declarar los array de tipo mpvar junto con arrays de datos
y crear las variables requeridas explcitamente aadiendo las siguientes lneas despus de
que los datos hayan sido ledos desde el fichero de datos y los dos conjuntos ALLPROD y
CRUDES han sido finalizados:

forall(p in ALLPROD) create(produce(p))


forall(c in CRUDES) create(use(c))

En problemas de gran dimensin, la mayora de los datos son inicializados dinmicamente de


forma que la definicin de la variable necesita ser hechas con una de los dos mtodos descritos
arriba.
Ejercicio 6: Una compaa ha recibido un pedido de tres tipos de papel para pared: uno (papel
1) tiene fondo azul con patrn amarillo, otro (papel 2) con fondo verde y patrn azul y amarillo,
y el ltimo (papel 3) tiene fondo amarillo con patrn azul y verde. Cada tipo de papel se produce
en un rollo continuo que pasa a travs de varias mquinas, cada una imprime un color diferente.
El orden en el cual los papeles son realizados depende del diseo del papel: para el papel 1,
primero se hace el fondo azul y entonces se imprime el marco en amarillo. Despus del fondo
verde para el papel 2, el azul y despus el amarillo del marco. Para el tercer papel, se empieza
con el fondo amarillo, seguido por el azul y despus el verde del marco.

Papel 2 Papel 1 Papel 3

Papel 2
Papel 2
Papel 1
Verd. Azul. Amar.
Papel 3
Papel 3

Papel 3 Papel 1 Papel 2

El tiempo de preproceso difiere dependiendo de la superficie que necesita ser imprimida. Los
tiempos (en minutos) aplicado a cada color de los tres tipos de papeles se dan en la siguiente
tabla:

Machine Color Paper 1 Paper 2 Paper 3


1 Blue 45 20 12
2 Green - 10 17
3 Yellow 10 34 28

Sabiendo que cada mquina slo puede procesar un papel a la vez y que un papel no puede
ser procesado simultneamente por varias mquinas, cmo debera ser impreso el papel en las
mquinas para finalizar el pedido lo antes posible.
Implementacin:

model "B-3 Job shop"


uses "mmxprs"
declarations
TASKS=1..8 ! Set of tasks (operations)
DUR: array(TASKS) of integer ! Durations of jobs on machines
ARC: dynamic array(TASKS,TASKS) of integer ! Precedence graph
DISJ: dynamic array(TASKS,TASKS) of integer ! Disjunctions between jobs
start: array(TASKS) of mpvar ! Start times of tasks
finish: mpvar ! Schedule completion time
y: array(range) of mpvar ! Disjunction variables
end-declarations
initializations from b3jobshop.dat
DUR ARC DISJ
end-initializations
BIGM:= sum(j in TASKS) DUR(j) ! Some (sufficiently) large value
! Precedence constraints
forall(j in TASKS) finish >= start(j)+DUR(j)
forall(i,j in TASKS | exists(ARC(i,j)) ) start(i)+DUR(i) <= start(j)
! Disjunctions
d:=1
forall(i,j in TASKS | i<j and exists(DISJ(i,j)) ) do
create(y(d))
y(d) is_binary
start(i)+DUR(i) <= start(j)+BIGM*y(d)
start(j)+DUR(j) <= start(i)+BIGM*(1-y(d))
d+=1
end-do
! Bound on latest completion time
finish <= BIGM
! Solve the problem: minimize latest completion time
minimize(finish)
end-model

La implementacin de este modelo usa unas instrucciones de MOSEL que todava no han sido
introducidas. En el bloque de declaraciones, se puede observar un dynamic array y range.
Ambos indican que los correspondientes arrays son definidos como arrays dinmicos. range
indica un conjunto de ndices desconocido que es una secuencia consecutiva de enteros (puede
que incluya el 0 o valores negativos). En cualquier caso, no se tiene que enumerar el array"de
variables y por eso no hay necesidad de nombrar sus ndices. Se poda haber procedido de
igual forma para los arrays ARC y DISJ, pero como conocemos su conjunto de ndices es un
subconjunto de TASKS (que es usado posteriormente para enumerar los entrada de los arrays),
usamos este nombre para el conjunto de ndices.
Sin embargo, el conjunto TASKS se define como una constante directamente en su declaracin,
que significa que cualquier array con estos ndices sern creados con tamao fijo. Para ambos
arrays, ARC y DISJ slo se definen muy pocos ndices, y por esto es preferible inicializarlos de
forma dinmica . En los bucles forall se enumeran los arcos de precedencia y las disyunciones,
se usan la funcin exists para chequear si una variable es definida. (En el caso de arrays con
muy pocas entradas definidas es un buen mtodo de enumerar estas variables). Otra instruccin
nueva es el bucle forall-do usada en la formulacin de las disyunciones.

Instrucciones interesantes

Deshabilitar la condicin de integridad sin eliminarlas del modelo pueden ser tambin
obtenidas aadiendo un parmetro:
maximize(XPRS_LIN,Profit)

You might also like