• No se han encontrado resultados

INSTITUTO TECNOLÓGICO Y DE ESTUDIOS SUPERIORES DE MONTERREY

N/A
N/A
Protected

Academic year: 2022

Share "INSTITUTO TECNOLÓGICO Y DE ESTUDIOS SUPERIORES DE MONTERREY"

Copied!
77
0
0

Texto completo

(1)
(2)

INSTITUTO TECNOLÓGICO Y DE ESTUDIOS SUPERIORES DE MONTERREY

CAMPUS MONTERREY

DIVISIÓN DE GRADUADOS E INVESTIGACIÓN PROGRAMA DE GRADUADOS EN INGENIERÍA

SOLUCIÓN DE MODELOS DE PROGRAMACIÓN MATEMÁTICA MEDIANTE LA UTILIZACIÓN DE ALGORITMOS GENÉTICOS

PRESENTADA COMO REQUISITO PARCIAL PARA OBTENER EL GRADO ACADÉMICO DE

MAESTRO EN CIENCIAS

ESPECIALIDAD EN INGENIERÍA INDUSTRIAL

VÍCTOR MANUEL DE LA CUEVA HERNÁNDEZ TESIS

MONTERREY, N.L. DICIEMBRE DE 1994

(3)

INSTITUTO TECNOLÓGICO Y DE ESTUDIOS SUPERIORES DE MONTERREY

CAMPUS MONTERREY

DIVISIÓN DE GRADUADOS E INVESTIGACIÓN PROGRAMA DE GRADUADOS EN INGENIERÍA

SOLUCIÓN DE MODELOS DE PROGRAMACIÓN MATEMÁTICA MEDIANTE LA UTILIZACIÓN DE ALGORITMOS GENÉTICOS

TESIS

PRESENTADA COMO REQUISITO PARCIAL PARA OBTENER EL GRADO ACADÉMICO DE

MAESTRO EN CIENCIAS

ESPECIALIDAD EN INGENIERÍA INDUSTRIAL

VÍCTOR MANUEL DE LA CUEVA HERNÁNDEZ

Monterrey, N.L. Diciembre de 1994

(4)

A mi esposa Paty y a mis hijos Víctor Manuel y Ana María.

Con todo mi amor.

(5)

Agradecimientos

Al Dr. Jesús S. Arreóla R. por su apoyo y enseñanzas no sólo en la realización de este trabajo sino durante toda la maestría.

A mis familiares y amigos por su gran apoyo durante la realización de mis estudios.

Al Programa Sinapsis por la oportunidad que nos ofrece de poder estudiar una maestría de alta calidad sin tener que movernos de nuestro lugar de trabajo.

A las autoridades del ITESM Campus Central de Veracruz porque siempre han confiado en mí y han apoyado todos mis proyectos de capacitación.

(6)

índice General

Capítulo 1

La Programación Matemática y Los Algoritmos Genéticos 1

1.1 Introducción. 1

1.2 Los Algoritmos Genéticos. 2

1.2.1 ¿Qué son los algoritmos genéticos? 2 1.2.2 Optimización tradicional y los métodos de búsqueda. 3 1.2.3 ¿Qué tanto son diferentes los algoritmos

genéticos de los métodos tradicionales? 4 1.2.4 Ejemplo de un algoritmo genético muy simple. 5 1.2.5 Simulación manual de un algoritmo genético. 8

1.3 El modelo de programación matemática. 10

1.4 Conexión entre los algoritmos genéticos y los modelos de

programación matemática. 11

Capítulo 2

Adaptación del Algoritmo Genético para la Solución de

Modelos de Programación Matemática 13

2.1 Programa computacional general. 13

2.1.1 Función DECODE. 14

2.1.2 Función OBJECTIVE. 17

Capítulo 3

Aplicación del Algoritmo Genético a la Programación Lineal 19

3.1 Programación Lineal. 19

3.2 Programación Lineal Entera. 21

(7)

Capítulo 4

Aplicación del Algoritmo Genético a la Programación No Lineal

24

4.1 Programación No Lineal General. 24

4.2 Programación Estocástica. 27

4.3 Programación No Lineal Entera. 29

Capítulo 5

Análisis y Comparación de la Aplicación de Algoritmos

Genéticos a la Programación Matemática 32

5.1 Análisis General. 32

5.1.1 Tamaño en bits de cada variable. 32

5.1.2 Función Decode. 34

5.1.3 Función Objective. 34

5.1.4 La no existencia de la solución. 34

5.1.5 Restricciones redundantes. 35

5.2 Comparación en el caso de la programación lineal. 36

5.1.1 Ventajas y Desventajas. 36

5.3 Comparación en el caso de la programación no lineal. 37

5.2.1 Ventajas y Desventajas. 37

5.4 Posibles Mejoras. 38

Capítulo 6

Eficiencia del algoritmo genético en un modelo de

programación matemática. 42

6.1 Eficiencia Computacional. 42

6.1.1 Tiempo de ejecución. 44

6.1.2 Espacio en memoria requerido para su ejecución. 46

6.2 Eficiencia en los resultados. 47

6.3 Número de iteraciones del algoritmo. 48

(8)

Capítulo 7

Comparación empírica del algoritmo genético y el algoritmo simplex aplicados a la solución de un modelo de

programación lineal. 49

7.1 El modelo utilizado. 49

7.2 Resultados obtenidos. 50

7.3 Comentarios y conclusiones de la comparación. 51 Capítulo 8

Conclusiones 55

Apéndice A.

Ejemplo de Implementación de las Funciones decode y objective 57 A.l Implementación en lenguaje de programación C

de la función decode. 57

A.2 Ejemplo de implementación de la función objective

en lenguaje de programación C. 58

Apéndice B

Programa fuente del algoritmo genético aplicado a la

solución de un modelo de programación matemática. 61

Referencias Bibliográficas. 67

Software. 68

Vita 69

(9)

Capítulo 1

La Programación Matemática y Los Algoritmos Genéticos

En este capítulo se explica qué son los algoritmos genéticos (AGs) y qué es un modelo de programación matemática, finalmente se explica dónde radica la conexión entre ellos, la cual constituye la idea fundamental de este trabajo.

1.1 Introducción.

En los últimos tiempos la parte del conocimiento que ha tenido un mayor desarrollo es la de las Ciencias Computacionales en todas sus ramas, desde las Ciencias de la Información hasta la Inteligencia Artificial. No pasó mucho tiempo para que la computadora se infiltrara casi todas las áreas del conocimiento como apoyo, que facilitaba el trabajo realizado, o como una herramienta básica en el desarrollo de las mismas. La Ingeniería Industrial no fue la excepción y pronto encontró en la computadora una gran herramienta para lograr el éxito de algunos de sus métodos. De hecho, muchas de las ramas de la Ingeniería Industrial tuvieron gran desarrollo debido a la aparición de la computadora. Una de estas es la Programación Matemática cuyos algoritmos se agilizan, en lo que al cálculo de operaciones se refiere, si se usa una computadora para llevarlos a cabo, haciéndola accesible a una gran cantidad de usuarios que disfrutaron de sus beneficios.

Por otro lado, la Inteligencia Artificial llevaba a cabo el desarrollo de algoritmos de búsqueda que hicieran más eficientes sus procesos principales que estaban basados en este tipo de procedimientos.

Una de las principales características de la Inteligencia Artificial es su marcada tendencia a copiar los procesos naturales del cerebro humano y de la vida en general. Los especialistas de las Ciencias Computacionales se dieron cuenta que el grado de perfección que había logrado la naturaleza en la creación de los seres vivos es muy grande y que valía la pena hacer el esfuerzo de copiarlos o imitarlos para resolver problemas que de otra manera llevarían mucho tiempo en obtener su solución.

(10)

Es así como nacen los llamados Algoritmos Genéticos que son procedimientos de búsqueda basados en procesos estocásticos, que tratan de imitar los proceso de reproducción y selección natural de los organismos vivos y cuya principal función es la optimización de funciones.

La marcada tendencia a la aplicación del Enfoque de Sistemas que propone la Ingeniería Industrial, el estudio de la Inteligencia Artificial y el de la Programación Matemática llevaron a pensar en la posible existencia de alguna conexión entre ambas áreas del conocimiento que al estudiarla diera como resultados algunos beneficios para la Ingeniería Industrial.

Al parecer, una de esas conexiones se da en las áreas de Algoritmos Genéticos de la Inteligencia Artificial, por un lado y la Programación Matemática de la Ingeniería Industrial, por el otro. Es así como nace este trabajo de tesis en el que se realiza un estudio de la aplicación de los algoritmos genéticos a la solución de modelos de programación matemática y el cual se espera que sirva para abrir una puerta en el desarrollo de este tipo de trabajos de investigación.

1.2 Los Algoritmos Genéticos.

A continuación se trata de aclarar qué son y cómo funcionan los algoritmos genéticos. Esta sección fue tomada en su mayoría de la referencia m.

1.2.1 ¿Qué son los algoritmos genéticos?

Los algoritmos genéticos son algoritmos de búsqueda basados en los mecanismos de selección natural y de genética natural. Combinan la supervivencia del individuo (string) más apto con un intercambio de información aleatorio bien estructurado para formar un algoritmo con algunas de las innovaciones de la búsqueda humana. En cada generación, un nuevo conjunto de criaturas artificiales (strings) son creadas usando bits y piezas de los individuos más aptos de la generación anterior; ocasionalmente se crea una parte nueva del individuo controlada mediante una medición. Aunque los algoritmos genéticos usan eventos aleatorios no se trata de una simple búsqueda al azar. Ellos se efícientizan explotando la información histórica para especular (formar) un nuevo punto de búsqueda con un esperado aumento en la eficiencia.

(11)

Los algoritmos genéticos fueron desarrollados por John Holland, sus colegas y sus estudiantes en la Universidad de Michigan y dado a conocer al mundo en 1975 mediante la publicación de la monografía sobre el tema titulada

"Adaptación en Sistemas Naturales y Artificiales".

Actualmente los algoritmos genéticos son muy utilizados en problemas de adaptación y optimización en muchas áreas del conocimiento tales como negocios, ciencia e ingeniería. La razón del gran aumento en la aplicación de este tipo de algoritmos es muy clara. Los algoritmos genéticos son computacionalmente muy simples y potentes en la búsqueda eficiente. Además ellos no están restringidos por algunas características del espacio de búsqueda (tales como continuidad, existencia de las derivadas, unimodalidad y algunas otras).

1.2.2 Optimización tradicional y los métodos de búsqueda.

La literatura actual identifica tres tipos de métodos de búsqueda: basados en cálculo, enumerativos y aleatorios.

Los métodos basados en cálculo han sido estudiados exhaustivamente a lo largo de la historia. Estos se clasifican en dos tipos principales: indirectos y directos. Los métodos indirectos buscan extremos locales mediante la solución de conjuntos de ecuaciones generalmente no lineales resultantes de hacer el gradiente de una función igual a cero (ej. los multiplicadores de Lagrange). Esta es una generalización multidimensional de la noción elemental del cálculo de puntos extremos. Por otro lado, los métodos directos, que buscan óptimos locales moviéndose sobre la función, en la dirección que indique el gradiente local. Esto es simplemente la idea de hill-climbing [10]: para encontrar el mejor local, se asciende la función en la dirección del gradiente tanto como sea posible.

Los problemas que presentan estos dos métodos son: primero, ambos métodos son locales en alcance; ellos buscan el mejor en un conjunto de puntos vecinos al punto actual. Segundo, los métodos basados en cálculo dependen de la existencia de las derivadas. Por lo tanto podemos afirmar que los métodos basados en calculo no son suficientemente robustos en dominios no entendidos

aún.

(12)

Los esquemas enumerativos pierden su potencia debido al problema de la "explosión combinatoria" que se presenta en muchos de los problemas.

Los esquemas aleatorios pierden su potencia debido a la incertidumbre del tiempo de terminación, sin embargo se están haciendo investigaciones para mejorar los esquemas aleatorios ya que son atractivos por su simplicidad.

Los algoritmos genéticos son un ejemplo de un procedimiento que usa la selección aleatoria como una herramienta para guiar la explosión combinatoria de una búsqueda, por medio de la codificación de un parámetro del espacio.

Otro ejemplo de este tipo de búsqueda es la técnica de "simulating annealing", la cual usa los procesos aleatorios para guiar su búsqueda mediante estados de energía mínimos.

Podemos terminar esta sección con una conclusión: los métodos tradicionales de búsqueda no son suficientemente robustos. Esto no implica que no se puedan usar.

1.2.3 ¿Qué tanto son diferentes los algoritmos genéticos de los métodos tradicionales?

Los algoritmos genéticos son diferentes de la mayoría de los métodos de optimización y búsqueda en cuatro aspectos principales:

1. Los algoritmos genéticos trabajan con una codificación del conjunto de parámetros, no con los parámetros en sí.

2. Los algoritmos genéticos buscan en una población de puntos no en un punto específico.

3. Los algoritmos genéticos usan directamente la función, no derivadas u otro conocimiento auxiliar.

4. Los algoritmos genéticos usan reglas de transición probabilística, no reglas determinísticas.

Los algoritmos genéticos requieren que el conjunto de parámetros del problema de optimización sea codificado como un string de longitud finita sobre algún alfabeto finito.

(13)

Son estas cuatro diferencias (uso directo de una codificación, búsqueda de una población, no necesidad de información auxiliar y operadores aleatorios), las que contribuyen a garantizar la robustez de los algoritmos genéticos.

1.2.4 Ejemplo de un Algoritmo Genético muy simple.

La mecánica de un algoritmo genético es sorprendentemente simple, envuelve una complejidad no mayor a la que implica copiar strings o intercambiar partes de esos strings. La simplicidad de su operación y la potencia de sus efectos son dos de los principales atractivos de los algoritmos genéticos.

Considérese el problema de maximizar una función f(x) = x2 en el intervalo [0,31]. Cualquier cantidad en este intervalo se puede representar en sistema binario por medio de 5 bits. Pensemos en una población inicial de soluciones de cuatro individuos (strings):

01101 11000 01000 10011

esta población fue generada por medio de 20 lanzamientos de una moneda donde águila significaba 1 y sol 0. Cada uno de estos individuos puede ser sustituido en la variable x de la función objetivo, después de ser decodificado a un valor real, para obtener una calificación de acuerdo al valor de dicha función. La decodificación consiste simplemente (en este ejemplo) en su conversión a decimal, así el individuo 01101 se decodifica de la siguiente manera:

0 x 24 + 1 x 2^ + 1 x 22 + 0 x 21 + 1 x 2° = 0 + 8 + 4 + 0 + 1 = 13 al sustituir el 13 en la función se obtiene su calificación de 169.

Un algoritmo genético muy simple que da buenos resultados en una gran cantidad de problemas consta de tres operadores:

(14)

1. Reproducción 2. Cruce (Croosover) 3. Mutación La reproducción es el proceso en el cual los strings individuales son copiados de acuerdo a su calificación (valor de la función objetivo f(x)).

Intuitivamente podemos pensar en la función f(x) como una medida de eficiencia, utilidad o bondad que nosotros queremos maximizar. Copiando los strings de acuerdo a dicha medida, los que tengan una mayor medida tendrán una mayor probabilidad de ser copiados y contribuir una o más veces a la creación de la nueva generación. Este operador es una versión artificial de la selección natural, una supervivencia Darwiniana de los mejores individuos.

El operador de reproducción puede ser implementado algorítmicamente en un gran número de formas. Una de las más comunes de hacerlo es por medio de una ruleta dividida en secciones, cada una de las cuales representa a un individuo y que son proporcionales a la calificación que obtiene dicho individuo al evaluarlo en la función objetivo. Observemos la siguiente tabla:

No. String Calificación % del total

1 01101 169 14.4

2 11000 576 49.2

3 01000 64 5.5

4 10011 361 30.9

total 1170 100.0

esto daría como resultado la siguiente ruleta:

(15)

donde se puede observar que el individuo dos tiene la mayor porción y por lo tanto la mayor probabilidad de ser seleccionado para la reproducción.

Cada vez que se lance la ruleta se selecciona un individuo para la reproducción.

Después de realizada la reproducción se hace la cruza de los dos individuos seleccionados. Esta se puede llevar a cabo en dos pasos. Primero, los miembros seleccionados para la reproducción son elegidos aleatoriamente de acuerdo a la ruleta. Segundo , cada par de strings se van a cruzar como sigue: Una posición k a lo largo del string es seleccionada aleatoriamente en forma uniforme entre 1 y la longitud del string menos uno [1, /-l]. Dos nuevos strings son creados intercambiando todos los caracteres (bits) entre las posiciones k+1 y 1 inclusive. Por ejemplo, considérese que se seleccionan los strings 1 y 2:

Al = 0 1 1 0 | 1 A2 = l 1 0 0 | 0

Supóngase que al obtener un número aleatorio entre 1 y 4 obtenemos un k=4 (como se indica por el símbolo de separación | ). Los string resultantes de la cruza son:

A'l = 0 1 1 0 0 A'2 = 1 1 0 0 1 donde se intercambió el último bit.

Todavía se agrega una parte estocástica más a dicho operador y se trata de la probabilidad de cruce (PC). Esta, indica si se va a realizar la cruza de los dos individuos o simplemente van a pasar tal cual a la nueva generación. Se acostumbra que la probabilidad de cruce sea mayor a 0.5 (p.e. 0.6 es un buen valor). La forma en la que se implementa algorítmicamente es la misma en la que se implementa la probabilidad de mutación que se explica más adelante.

Finalmente, el operador de mutación es un pequeña probabilidad de que el bit cambie de valor de 0 a 1 o viceversa a la hora de ser copiado de un string a otro. Para colocar en un algoritmo esta probabilidad se genera un número aleatorio entre 0 y 1. Si el número es menor que la probabilidad de mutación

(16)

colocada para el algoritmo el bit se copia cambiando de valor (si era 0 se copia un 1), por el contrario, si es mayor se copia tal cual. Esta probabilidad acostumbra tomar valores muy pequeños tales como 0.001 o 0.01.

1.2.5 Simulación manual de un algoritmo genético.

Vamos a aplicar un algoritmo genético a un problema particular de optimización paso por paso. Se trata de maximizar la función f(x) = x2 en el rango [0,31].

Consideremos la misma población inicial que para el apartado anterior.

Esto nos da la siguiente tabla:

No. String X Calificación probabilidad ( x2) de selección

1 01101 13 169 .144

2 11000 24 576 .492

3 01000 8 64 .055

4 10011 19 361 .319

total 1170 100.0

Haciendo girar cuatro veces la ruleta ponderada por la probabilidad de ser seleccionadas, se eligen dos parejas para la reproducción, al realizar esto se obtuvieron las siguientes parejas:

Parejas pimíos de Nueva f(x)

corte población X x2

0110|1 4 01100 12 144

1100|0 4 11001 25 625

11|000 2 11011 27 729

10|011 2 10000 16 256

total 1754

(17)

NOTAS:

1) La población inicial se seleccionó con cuatro tiros de una moneda donde el águila es igual a 1 y el sol a 0.

2) La reproducción se realizó mediante la selección de una parte de ocho posibles que es una simulación de la ruleta (tres tiros de moneda).

3) El lugar de cruzamiento se seleccionó mediante la decodificación binaria de dos tiros de moneda donde AA=1,AS=2,SA:=3 y SS=4).

4) La probabilidad de cruce se asumió unitaria PC=1.0, por lo que siempre habrá cruce.

5) La probabilidad de mutación se tomó de PMH3.001, por lo que las mutaciones esperadas son 5*4*0.001 = 0.02, es decir, no se esperan mutaciones en una sola generación. Por esta razón, no se simularon.

Se puede observar que para la segunda generación se tiene un máximo de 729 el cual resulta en una x de 27.

En una sola generación se tuvo un incremento en la función de 576 a 729. Esto implica mover la x de 24 a 27.

Si se continúa así el proceso de evolución, hasta un número determinado de generaciones, digamos n, se llegará a tener una x en la cual la función se hace máxima. Desde luego que esta x sólo se busca en el rango de 0 a 31 inclusive ya que es el máximo número que se puede codificar en cinco bits. Si se quiere encontrar la x que maximiza la función en un rango mayor se deberá incrementar el número de bits.

En el caso de que se quiera maximizar una función de dos variables digamos

f(x,y) = x + y

se deberán codificar las dos variables en cada uno de los individuos. Digamos, en el caso de que se quiera encontrar el máximo en un rango de [0,31] para cada variable, entonces cada individuo deberá contener 10 genes (bits), cinco para la variable x y cinco para la y. Lo más importante es que el algoritmo base

(18)

no se modifica. Y así se pueden codificar n variables (mientras el poder de cómputo disponible lo permita) pudiendo contener cualquier tipo de funciones tales como polinomiales de todos lo grados, trascendentales, hiperbólicas, etc.

1.3 El modelo de programación matemática.

Un modelo de programación matemática es un modelo matemático que consiste en una función, llamada objetivo, la cual está sujeta a una serie de restricciones. El tipo más común de aplicación abarca el problema general de asignar recursos limitados entre actividades competitivas de la mejor manera posible.

El problema de solucionar un modelo de programación matemática es el de encontrar los valores de x = (xl 9x2 j... ,Xn) que hacen que la función objetivo sea óptima, es decir, que tome un valor máximo o un valor rnínimo dependiendo de cual sea el interés de la optimización. El modelo general programación matemática es el siguiente:

Maximizar z = f(x) Sujeta a

gi(x) < b¡ para i = 1,2,... ,m x > 0

donde f(x) y g¿(x) son funciones dadas de n variables de decisión. [1,8]

El nombre que se le da a este tipo de modelos no tiene nada que ver con un programa de computadora. El término "programación" se refiere más que nada a "planeación". Por otro lado, el término "matemático" tiene que ver con el tipo de modelo de que se trata. [8]

En general se pueden distinguir dos tipos de modelos de programación matemática. Los primeros se denominan modelos de programación lineal y surgen cuando en un modelo de programación matemática, tanto la f(x) como las gi(x) son funciones lineales de x. El desarrollo de algoritmos para solucionar este tipo de problemas se ha convertido en uno de los principales avances del siglo XX [8], en particular la aparición de un método extraordinariamente poderoso y eficiente llamado algoritmo SIMPLEX que fue desarrollado por Dantzig en 1947 y el cual ha permanecido como el mejor hasta nuestros días.

(19)

Se puede decir que muchos de los problemas que se pueden atacar por medio de un modelo de programación matemática tienen que ver con la programación lineal, razón por la cual han surgido un sin número de libros y artículos donde se trata la solución de problemas de programación lineal. Esta herramienta ha ayudado a ahorrar miles y millones de dólares a las empresas.

El otro tipo de modelos de programación matemática es aquel en el cual al menos f(x) o alguna de las g¿(x) no son lineales. Este tipo de modelos se denominan "modelos de programación no lineal", y la parte de la Ingeniería Industrial que se encarga de su estudio y aplicación es precisamente la Programación No Lineal.

Como ya se explicó, una suposición importante de la programación lineal es que todas las funciones del modelo (tanto la función objetivo como las restricciones) son lineales. Aunque esta suposición se cumple para muchos problemas prácticos, es frecuente que no sea así. De hecho muchos economistas han encontrado que cierto grado de no linealidad es la regla y no la excepción, en los problemas de planeación económica, por lo tanto muchas veces es necesario manejar problemas de programación no lineal [8].

Desafortunadamente no se dispone de un algoritmo que resuelva todos los problemas específicos que se ajustan al formato de la programación no lineal (como sí sucede en el caso de la programación lineal con el algoritmo simplex). Se han hecho grandes logros en lo que se refiere a algunos importantes casos especiales de este problema, haciendo algunas suposiciones sobre las funciones, o recurriendo a métodos clásicos de optimización de funciones, pero la investigación sigue muy activa [8].

1.4 Conexión entre los algoritmos genéticos y los modelos de programación matemática.

Como ya se dijo anteriormente los algoritmos genéticos tienen como principal objetivo la optimización de funciones [7], mientras que éste es precisamente el punto principal en la solución de un problema de programación matemática. La única situación que hacía que estas dos materias no se pudieran juntar es el hecho de la aparición de las funciones de restricción. Así que el problema se reduce a pensar en la forma de agregar estas restricciones a la optimización de una función mediante el algoritmo genético.

(20)

De hecho, esta es la idea principal que se introduce en este trabajo, esto es, la forma de agregar funciones restricciones a la optimización de una función en un algoritmo genético y a la función de penalización utilizada para guiar la búsqueda.

Definitivamente, una vez resuelto este problema, parece muy directa la idea de poder resolver problemas matemáticos mediante el uso de algoritmos genéticos, ya que en esencia el tipo de problemas que intenta solucionar el algoritmo genético es precisamente el problema que se presenta mediante un modelo de programación matemática con algunos pequeños cambios.

(21)

Capítulo 2

Adaptación del Algoritmo Genético para la

Solución de Modelos de Programación Matemática

En este capítulo se explicará en qué consiste la modificación que se le debe hacer al algoritmo genético computacional para que pueda resolver problemas de programación matemática.

2.1 Programa computacional general.

El algoritmo genético se debe realizar forzosamente mediante el uso de una computadora. Es prácticamente imposible realizarlo a mano debido a la gran cantidad de operaciones que se requieren durante su desarrollo. De esta forma se puede pensar en el algoritmo genético prácticamente como un programa de computadora. Su codificación general en lenguaje C (Turbo C++

versión 1.0) se presenta en el apéndice B al final del este trabajo.

Básicamente al algoritmo genético no le importa lo que se esté tratando de representar mediante una cadena de bits (un individuo), él simplemente tomará la población de individuos (strings) y comenzará a trabajar de acuerdo a la selección de los mejores para la reproducción, en base a la calificación que les otorgue una función especial.

Existen una serie de parámetros que se deben usar para que funcione el algoritmo genético. En este trabajo se tomaron los siguientes:

probabilidad de cruce (cross over) PC = 0.6 probabilidad de mutación PM = 0.01

Además existen una serie de variables que el usuario deberá modificar en el programa fuente para resolver un modelo de programación matemática de su interés, estos son:

nvar = número de variables de decisión que se manejan en el modelo de programación matemática específico.

LVAR = número de bits que va a utilizar cada variable (ver sección siguiente).

(22)

ENTERA — número de bits de cada variable que representan la parte entera. El resto de los bits (que resultan de la diferencia LVAR-ENTERA) corresponden automáticamente a la parte decimal del valor de la variable (ver sección siguiente).

Estas tres variables que se deben modificar, se encuentran en la función mainQ del algoritmo genético (ver apéndice). Los valores adecuados para un cierto problema se irán dando durante el desarrollo del trabajo.

De esta forma, el problema para tratar de resolver algo por medio del algoritmo genético se reduce al diseño de dos funciones. La palabra "función"

se refiere a una función del lenguaje de programación C.

2.1.1 Función DECODE.

La primera de ellas es la función DECODE, En ella se le da sentido al significado de cada individuo (cadena de bits). Es decir, en ella se transforma una cadena de bits a la respuesta que uno espera del algoritmo. Para cada caso, se le debe dar una interpretación por parte del programador a la cadena de bits, esta puede ser un número entero representado en binario, un carácter representado en código ASCII, una cadena de caracteres o un número real.

En este trabajo, la interpretación que le se le da a ima cadena de bits fue muy simple. Cada individuo (string o cadena de bits) representa una secuencia de números reales que van a ser los valores de las variables que optimizarán la función objetivo.

Esto quedará mejor explicado si se recurre a un ejemplo. Considérese el siguiente modelo de programación lineal [2]:

max z = X!+3x2 s.a.

Xj+x2 < 6 -Xj+2x2 < 8

xbx2> 0

Este modelo de programación lineal cuenta con dos variables de decisión y x2 para las cuales se debe encontrar el valor (número real) que haga que z

(23)

tome su valor máximo, sin violar las funciones restricciones que se dan en la parte de s.a. (léase: sujeto a).

Antes de continuar veamos cómo se representan cantidades reales mediante una codificación a representación binaria.

La representación de un número real en formato binario se puede lograr de diferentes maneras (códigos) [9]. La forma más sencilla de realizar dicha representación es la siguiente: Cada número real está compuesto por N bits de los cuales, los primeros E (los de más a la izquierda) representan la parte entera y los restantes N-E forman la parte decimal. Una vez decidido esto se hace la transformación correspondiente, en binario, considerando que los números del punto decimal a la izquierda valen la potencia de dos que les corresponde de acuerdo al lugar que ocupan, de igual manera los que se encuentran a la derecha del punto decimal. Se debe continuar con un ejemplo. Supóngase que se disponen de 10 bits para representar un número real. De ellos se decidió tener los 5 primeros (los de más a la izquierda) para representar la parte entera.

Así que los 5 restantes son la parte decimal. El valor de un "uno" según la posición que ocupa sería el siguiente:

2* z3 2Z 21 2° 2"1 2"2 23 i4 25 é punto decimal

si el número dado en binario es el

0 0 1 1 0 1 0 1 0 0 la parte entera estará formada por:

0 0 1 1 0

así que, de acuerdo al dibujo anterior, se tiene un "uno" en la posición 21, un

"uno" en la posición 22 y todos los demás son ceros así que no intervienen en el valor. El valor decimal de la parte entera sería:

2 ' + 22= 6

(24)

Por otro lado, la parte decimal estaría dada por:

10 1 0 0

nuevamente, según el dibujo, se tiene un "uno" en la posición 2_ 1 y otro en la posición 2~3. Esto daría el número

2 "1+ 2 "3 = 0.5 + 0.125 = 0.625 así que el número total representado por los diez bits es:

6 + 0.625 = 6.625

El número más grande que se podría representar bajo esta distribución de los 10 bits es el que se forma cuando hay 10 unos:

1 1 1 1 1 1 1 1 1 1 que sería:

24 + 23 + 22 + 21 + 2o + 2a + T2 + 2'3 + Ia + 2"5 = 31.96875

Desde luego que se puede tomar cualquier N y cualquier E dependiendo de la magnitud esperada de los resultados.

Además, se tiene la ventaja de que, para un modelo de programación matemática, todas las variables se pueden manejar como "no negativas". Esto evita desperdiciar un bit (el más significativo) para manejarlo como signo. En este trabajo sólo se manejan variables que cumplen con la condición de "no negatividad".

Durante el desarrollo del trabajo se van a estar modificando los valores que se le den a N y a E.

Volviendo al modelo de programación lineal del ejemplo, se tiene que consta de dos variables de decisión: Xj y x2, para cada una de las cuales se requiere un valor real. Por esta razón cada individuo va a estar formado por tantos bits como necesite para representar los valores de todas las variables del

(25)

problema. Suponiendo que tenemos una N=10 y una E=5 como en el ejemplo anterior, entonces cada individuo de la población del algoritmo genético deberá estar formado por 20 bits. De haber tenido tres variables serían 30 bits por individuo, y así sucesivamente.

Se puede ver un ejemplo de la forma en la que se implementa esta función si se consulta el apéndice A de este trabajo.

Haciendo un pequeño análisis del código de la función decode se puede observar fácilmente que se cambia un poco la representación binaria a la expuesta anteriormente. Realmente, los valores de las posiciones son los siguientes:

2° 21 22 23 2A 2A 2Z 23 iA 25

i punto decimal

esto se hizo para facilitar la codificación en el caso de usar una instrucción FOR, pero en realidad no le afecta en lo más mínimo al algoritmo genético. De hecho se realizaron pruebas con las dos formas de codificar y arrojan los mismos resultados.

Cabe mencionar que no es la única forma de codificar valores reales positivos usando el código binario. Para darse una mejor idea de estas formas se puede consultar la referencia [9].

Las personas que no sepan lenguaje de programación C, no se deben preocupar, ya que lo único que se tiene que hacer con esta función, para poder utilizar el algoritmo, en la solución de un modelo de programación matemática de su interés es: ignorarla. La función que se presenta en el programa fuente está totalmente lista para ser usada. Esta, utiliza la representación descrita arriba.

2.1.2 Función OBJECTIVE.

La segunda de las dos funciones que da origen a una aplicación especial del algoritmo genético es la función objectiveQ. En ella se establece la

(26)

calificación que se le va a dar a cada individuo de la población dependiendo de qué tan cerca se encuentre de la solución.

El diseño de esta función es la parte medular de la aplicación del algoritmo genético a la programación matemática. Cuando se elaboró esta función se tuvo que pensar en una forma de que se le asignara mejor calificación a los individuos cuyos valores de las variables, ya decodificados, dieran un valor mayor de la función objetivo, esto en el caso de que se quisiera maximizar dicha función. En caso de que se quisiera minimizar se debería dar una mejor calificación a los individuos que hicieran menor a la función objetivo.

La solución que se propone es muy simple. Se le da un punto de calificación por cada restricción que cumpla un individuo y, en caso de que cumpla todas, se le da, además de los m puntos por las restricciones, el valor de la función objetivo (z) que logró. Este último valor se obtiene por simple evaluación de la función objetivo en el individuo x dado.

Mediante el uso de esta función objetivo, se está forzando a que los mejores individuos sean, en primer lugar, los que se logren colocar en un punto dentro de la región factible de la función objetivo y, dentro de ellos será mejor el que haga que la función objetivo tome un valor mayor al ser evaluada en dicho punto factible.

Desde luego, esta no es la única forma de diseñar esta función ni tampoco la mejor, únicamente es la que se propone en este trabajo. Se espera que este trabajo sirva, entre otras cosas, para que alguien en un futuro piense como diseñar mejores funciones objectiveQ.

Así que, para codificar dicha función en C lo único que se tiene que hacer es escribir el modelo de programación matemática tal cual está. Un ejemplo de la forma en la que se realiza la codificación de la función objective se puede consultar en el apéndice A de este trabajo.

(27)

Capítulo 3

Aplicación del Algoritmo Genético a la Programación Lineal

En este capítulo se va a explicar cómo se realiza la aplicación del algoritmo genético para solucionar problemas de programación lineal en general y de programación entera. En ambos casos se proporciona un ejemplo y se dan los resultados obtenidos tanto por el algoritmo genético como por el algoritmo SIMPLEX (programa LINDO).

3.1 Programación Lineal.

Como ya se dijo anteriormente el modelo que presenta la programación lineal es el modelo general de la programación matemática donde se supone que todas las funciones, tanto la función objetivo como las restricciones son lineales. El modelo general sería el siguiente:

n

Max z = Zcix¡ s.a. i=l

n m

Z I V r

b

i

X i > 0

Donde las x¡ son las variables de decisión, las c¡ son los costos, las a¡j son los coeficientes tecnológicos y las bj son los recursos escasos. Desde luego que la función objetivo también se puede minimizar.

Existe un algoritmo capaz de resolver todos los problemas de programación lineal en una forma muy eficiente y potente, se trata del algoritmo SIMPLEX. Para un estudio acerca del algoritmo simplex consultar [1,2].

La aplicación del algoritmo genético a problemas de programación lineal es prácticamente como la que se revisó en el capítulo anterior. Así que, aquí lo haremos mediante un ejemplo.

(28)

Sea el programa lineal dado por [10]:

max z = 7x!+9x2 s.a.

-Xj+3x2 < 6

7x!+x2 < 35 xl 9x2 > 0

La función objective quedaría de la siguiente forma:

float objective(){

float temp;

temp=0;

if (-x[0]+3*x[l] <= 6) temp++;

if (7*x[0]+x[l] <= 35) temp++;

if (temp=2.0)

temp+=7*x[0]+9*x[l];

return(temp);

}

Cabe hacer hincapié en que la función objective se forma prácticamente ,con la codificación del modelo de programación lineal dado.

Para este ejemplo se utilizaron tres bits para la parte entera y uno más para la parte decimal (esto debido a la magnitud de la respuesta esperada) para encontrar la respuesta siguiente:

X ! = 4 . 5 x2 = 3.5 z = 63

Después de encontrar la respuesta del programa lineal dado, por medio del algoritmo genético, la obtuve utilizando el método simplex. Para ello se utilizó el programa LINDO/PC ( Linear Interactive aNd Discrete Optimizer) for the IBM-PC realizado por LINDO Systems, Inc. [13] La respuesta dada por el método simplex es exactamente la misma que la obtenida por el algoritmo genético.

(29)

La razón de que dieran exactamente los mismos resultados es la magnitud de las respuestas sobre todo en el caso de la parte decimal. Es muy fácil representar un 0.5 en binario ya que consta de un 1 en la primera posición de la parte decimal (posición 2"1).

En general se puede decir que la respuesta proporcionada por el algoritmo genético que se está presentando, para el caso de modelos de programación lineal, no es mejor que la del simplex. Definitivamente el simplex es lo mejor que se tiene en este momento. Para un mayor análisis acerca de la comparación de los dos métodos véase el capítulo 5 de este trabajo que se refiere al análisis del algoritmo genético.

3.2 Programación Lineal Entera.

Una limitación importante que impide utilizar la programación lineal en muchas otras aplicaciones es la suposición de divisibilidad [8], que dice que las variables de decisión pueden tomar valores no enteros. En muchos problemas prácticos, las variables de decisión sólo tienen un sentido real si su valor es entero. Por ejemplo, con frecuencia es necesario asignar personas, máquinas o vehículos a las actividades, en cantidades enteras. Si el hecho de exigir valores enteros es la única diferencia que tiene un problema con la formulación de programación lineal, entonces se trata de un problema de programación entera (el nombre completo es programación lineal entera, pero por lo general el adjetivo lineal se deja fuera excepto cuando se hace una comparación con el problema de programación no lineal entera) [8].

El modelo matemático para programación entera es sencillamente el modelo de programación lineal (véase la sección anterior) con la restricción adicional de que algunas variables deben tener valores enteros. Si sólo es necesario que algunas de las variables tengan valores enteros (y la suposición de divisibilidad se cumple para el resto), el modelo es de programación entera mixta. Cuando se hace la distinción entre un modelo todo entero y este caso mixto, el primero se llama de programación entera pura [8].

La programación entera presenta un algoritmo para poder resolver este tipo de problemas. En realidad, el algoritmo de la programación lineal entera tiene como base la solución que presenta el método simplex para el programa lineal sin la restricción entera. A dicha solución se le hacen algunas manipulaciones y esta arroja la solución entera óptima.

(30)

El problema de la programación lineal entera utilizando el algoritmo genético es relativamente simple. El programa fuente no se debe modificar en lo que respecta al que se utilizó para encontrar la solución a un programa lineal normal excepto en dos variables.

La única modificación que se requiere del programa es hacer la variable LVAR (que se refiere a la longitud en bits de una variable) igual a la variable ENTERA (que indica el número de bits que corresponderán a la parte entera de la solución). Lo demás queda totalmente igual.

El hacer iguales la longitud de la varible (LVAR) con la longitud de la parte entera (ENTERA) significa que no existe una representación de la parte fraccionaria, en otras palabras, se tiene una representación de números enteros y por ello, la solución final del modelo será entera.

Como ejemplo se solucionará el mismo problema de la sección anterior pero para el caso entero. A continuación se presenta la función objective:

float objective(){

float temp;

temp=0;

if (-x[0]+3*x[l] <= 6) temp++;

if (7*x[0]+x[l] <= 35) temp++;

if(temp=2.0)

temp+=7*x[0]+9*x[l];

return(temp);

}

que, como se puede observar si se compara, es completamente igual a la anterior. El único cambio que se realiza es que LVAR se hace igual a tres y ENTERA se hace también igual a 3. Con este cambio el algoritmo genético arrojó la siguiente respuesta:

X l = 4

x2 = 3 z = 55

(31)

que es exactamente la misma respuesta que arroja el programa LINDO al correrlo para este modelo indicándole que dé como respuesta la que corresponda a la programación entera.

En el caso de programación entera es muy probable que el algoritmo genético nos proporcione la misma respuesta para el modelo que el algoritmo simplex. La probabilidad de que el resultado sea exacto irá aumentando en la medida en que la longitud de las varibles se ajuste lo más posible a la magnitud de los valores de solución del modelo, es decir, que la representación en binario de la magnitud de la solución quepa exactamente en los bits asignados a la longitud de la varible en el algoritmo.

La razón de que el algoritmo genético tenga un mejor desempeño en programación entera es porque no se tienen que hacer aproximaciones a los decimales. Por ejemplo, el número 1/3 no se pude representar en un número finito de bits y cualquier aproximación siempre quedará corta para el sistema binario. Si se elimina la necesidad de codificar la parte decimal de un número el algoritmo genético sólo tienen que trabajar con números enteros para los cuales siempre existe una representación exacta en binario.

Lo anterior implica que existen errores de redondeo y estos se pueden eliminar mediante el aumento de bits para la parte fraccionaria, pero esto hará el trabajo más lento. Otra opción es buscar ima mejor forma de codificar la información. Para un mejor análisis al respecto véase el capítulo 5 de este trabajo.

(32)

Capítulo 4

Aplicación del Algoritmo Genético a la Programación No Lineal

En este capítulo se va a explicar cómo se puede aplicar el algoritmo genético a la solución de problemas de programación no lineal, la cual es una de las aplicaciones principales del algoritmo genético.

4.1 Programación No Lineal General.

El modelo general para un problema de programación no lineal es exactamente el mismo que el de la programación matemática en general pero con la condición de que al menos una de las funciones, ya sea la función objetivo o alguna de las restricciones, sea NO LINEAL. El modelo podría verse como sigue:

maximizar z = f(x) Sujeta a

g¡(x) < bj para i= 1,2, ... ,m x> 0

donde f(x) y g¿(x) son funciones dadas de n variables de decisión (esto es x=(X|,x2, ..., x j ) , y al menos una de ellas es no lineal.

Como ya se dijo en el capítulo 1, desafortunadamente no existe un sólo algoritmo para dar solución a todos los problemas de programación no lineal, como lo es el simplex para los problemas de programación lineal. Debido a esto, se piensa que el algoritmo genético puede dar muchos beneficios a la solución de problemas de este tipo, más que en el caso de los lineales.

La mayor parte de los algoritmos que se han desarrollado para manejar este tipo de problemas tienen el inconveniente de ser muy complejos ya que están basados en cálculo y además, por esa misma razón, piden algunos requisitos adicionales a las funciones como son la existencia de la derivada, la continuidad, etc. Algunos otros proporcionan soluciones aproximadas haciendo ciertas transformaciones a las funciones no lineales para poderlas tratar como si fueran lineales (por ejemplo los algoritmos de programación separable [10] y

(33)

[5]). El inconveniente de estos últimos es que no todas las funciones no lineales se pueden tratar de esta forma, estas también deben cumplir ciertos requisitos.

Es aquí donde el uso del algoritmo genético toma mayor valor. Una de sus principales ventajas (más ventajas se discutirán en el capítulo 5) con respecto a los algoritmos que se tienen para la solución de programas no lineales, es su sencillez de manejo y el hecho de que no pone ningún requisito adicional a las funciones del programa lineal. El algoritmo genético sólo usa el modelo de programación matemática en sí.

A continuación se presenta un par de ejemplos de la solución de problemas de la programación no lineal mediante el empleo del algoritmo

genético.

El primer modelo es el siguiente [10]:

max z - e ~X l + X ! + ( x2+ l )2 s.a.

X i2 + x2 < 3 xb x2 > 0

La función objective para el algoritmo genético es:

float objective(){

float temp;

temp=0;

if (x[0]*x[0]+x[l] <= 3) temp++;

if (temp = 1 )

temp+=exp(-x[0])+x[0]+(x[l]+l)*(x[l]+l);

return(temp);

}

La codificación de esta función, como en todos los casos anteriores, es directa del modelo.

La solución que da el algoritmo genético es:

(34)

La solución que da el libro de texto de donde se tomó el problema [10] es la misma. El mismo libro pide que se solucione con un método llamado programación entera mixta. Por esta razón las respuestas son enteras.

Podemos ver otro ejemplo. El modelo es el siguiente [10]:

max z = XiX2X3

s.a.

xi2 + x2 + x3 < 4 xi, x2, x3 £ 0

La función objective para este problema es la siguiente:

float objective(){

float temp;

temp=0;

if (x[0]*x[0]+x[l]+x[2] <= 4) temp++;

if (temp = 1.0)

temp=x[0]*x[l]*x[2];

return(temp);

}

La solución que proporciona el algoritmo genético para este problema es:

xt = 0.929688 x2= 1.453125 x3 = 1.679688 z = 2.269177

El libro de texto propone que este problema se solucione con una aproximación de este modelo a un modelo de programación lineal para que posteriormente se use el método de base restringida. Es de esperarse que la solución por este método se encuentre muy cerca de la que se obtuvo con el algoritmo genético.

26

(35)

4.2 Programación Estocástica

La programación estocástica trata con situaciones donde algunos o todos los parámetros del problema están descritos por variables aleatorias. Tales casos parecen típicos del problema de la vida real donde es difícil determinar los valores de los parámetros exactamente. En el caso de la programación lineal se pude utilizar un procedimiento llamado análisis de sensibilidad (véase [10], [8] o [2] ) para estudiar el efecto de cambios en los parámetros del problema sobre la solución óptima. Esto, sin embargo, representa una respuesta parcial al problema especialmente cuando los parámetros son realmente variables aleatorias. El objetivo de la programación estocástica es considerar estos efectos aleatorios explícitamente en la solución del modelo [10].

La idea básica de todos los modelos de programación estocástica es convertir la naturaleza probabilística del problema en una situación determinística equivalente. Una vez hecho esto el modelo resultante es un modelo de programación no lineal que se puede resolver por alguno de los métodos de la misma, incluyendo algoritmos genéticos.

A continuación se presenta un ejemplo de este tipo de problemas. Por quedar ftiera de los objetivos de este trabajo no se presentará el procedimiento para realizar el cambio de un problema de programación estocástica a un problema de programación no lineal pero si se desea se pueden consultar las referencias [5,10].

El modelo es el siguiente [10]:

donde los valores esperados de las a^j y sus variancias están dados por:

además el parámetro b2 está distribuido normalmente con media 7 y varianza 9.

max z = 5xj + 6x2 + 3x3 s.a.

P { auX ! + a1 2x2 + a1 3x3 < 8 } > 0.95 P{5x! + x2 + 6x3 <; b2} ;> 0.10

E { au} = l

V { a „ } = 2 5 V{a1 2} = 16 E { ai 3} = 9 V { a1 3} = 4

(36)

Este modelo, al realizarle la transformación pertinente, queda de la siguiente forma:

max z = 5xi + 6x2 + 3x3 s.a.

Xi + 3x2 + 9x3 + 1.645y < 8 25xj2 + 16x2 2 + 4x32 -y 2 = 0 5XJ + X2 + ÓX3 < 10.855 x i , x2 s x3,y > 0

que es un modelo de programación no lineal.

La función objective para este problema es la siguiente:

float objective(){

float temp;

temp=0;

if (x[0]+3*x[l]+9*x[2]+1.645*x[3] <= 8) temp++;

if (fabs(25*x[0]*x[0]+16*x[l]*x[l]+4*x[2]*x[2]-x[3]*x[3]) <= 0.01) temp++;

if (5*x[0]+x[l]+6*x[2] <= 10.855) temp++;

if(temp==3.0)

temp+=5 *x[0]+6 *x[ 1 ]+3 *x[2];

retura(temp);

}

Se puede observar que para el caso de la restricción de igualdad a 0 se utiliza una cota de error de 0.01. Dicha cota es necesaria por las aproximaciones de las que se ha estado hablando al codificar la parte decimal de un número real en código binario. El valor de esta cota depende de la aproximación que se tiene en cuanto a los bits de la parte decimal. Además, se utiliza el valor absoluto de la función para dejarla en libertad de moverse hacia el lado positivo o hacia el lado negativo.

El resultado obtenido al correr el algoritmo genético para este problema fue:

(37)

xt = 0.281250 x2= 0.5

x3= 0.078125 y = 2.453125 z = 4.64

Este modelo no se puede resolver por programación separable como se demuestra en el trabajo de tesis presentado por la Ing. Teresa Cotera R. [5].

Así que se resolvió por medio del método del Jacobiano [10]. La respuesta obtenida es la siguiente:

X! = 0

x2= 0.8350711 x3= 0

y = 3.34 z = 5.01

Se puede observar que la respuesta no es la misma, sin embargo, es muy similar si nos basamos en el valor de la función objetivo. Este es el caso más común cuando se usan algoritmos genéticos, en el cual no se llega a la solución óptima pero nos proporciona una buena aproximación.

El uso de algoritmos genéticos en este caso es adecuado, sobre todo si se toma en cuanta que el método del Jacobiano es demasiado complejo para realizarlo a mano y se vuelve más cuando se complican las funciones en cuanto a sus derivadas o cuando aumenta el número de variables.

4.3 Programación No Lineal Entera.

El caso de problemas de programación no lineal entera es el mismo caso que el de programación lineal entera. Esto significa que la condición para dar una respuesta es que las variables de decisión sólo tomen valores enteros y que éstos a su vez sean los valores enteros que optimizan a la función objetivo.

Puesto que al algoritmo genético es independiente de las características de las funciones del modelo de programación matemática entonces el procedimiento para resolver un problema de programación no lineal entera es el mismo que se siguió para resolver este tipo de problemas en programación lineal.

(38)

Como se recordará, lo único que se requiere hacer es eliminar los bits de la parte decimal en cada una de las variables y correr el programa del algoritmo genético. También se debe recordar que para eliminar dichos bits basta con hacer que el valor de la variable LVAR sea igual al de la variable ENTERA.

Esto nos garantiza que la respuesta que arroje el algoritmo genético debe ser entera.

En caso de que sólo se quiera que algunas de las variables sean enteras y las demás reales entonces se trata de un problema de programación entera mixta. Para este problema se debe diseñar otra función decode dentro del algoritmo genético. Este análisis se realiza en el capítulo 5 de este trabajo.

A continuación se va a resolver un ejemplo de programación no lineal entera pura (todas las variables son enteras). El modelo es el siguiente [10]:

min z — X j2 - 6xj + x2 2 - 8x2 - 0.5x3 s.a.

Xi + x2 + x3 < 5

X !2- x2 < 3 xj, x2, x3 > 0

Se puede observar que se trata de un modelo de minimización, el primero que se resuelve en este trabajo. La razón es muy simple: cualquier modelo de rniniínización se puede convertir a uno de maximización con sólo multiplicar por -1 a la función objetivo. Sin embargo, para tratar este tipo de problemas en el algoritmo genético se requiere usar el valor absoluto de la evaluación de la función objetivo. Esto debido a que ahora se quiere que la función objetivo tome valores lo más negativos posibles.

Pensando en lo anterior se tiene la siguiente función objective para este problema:

float objective(){

float temp;

temp=0;

if (x[0]+x[l]+x[2] <= 5) temp++;

if (x[0]*x[0]-x[l] <= 3) temp++;

if(temp = 2.0)

(39)

temp=fabs(x[0]*x[0]-6*x[0]+x[l]*x[l]-8*x[l]-0.5*x[2]);

return(temp);

} .

Los resultados que arroja el algoritmo genético al correrlo para este problema son:

x , = 2 x2 = 3 x3 = 0 z = -23

Este problema sí se puede resolver utilizando programación separable como se puede ver en la referencia [5]. La solución, en este caso, es exactamente igual a la del algoritmo genético.

(40)

Capítulo 5

Análisis y Comparación de la Aplicación del Algoritmo Genético a la Programación Matemática

Una de las partes más importantes en una propuesta para solucionar un tipo especial de problemas es la comparación de dicha propuesta con las ya existentes en cuanto a sus ventajas y desventajas, limitaciones y alcances y en cuanto a sus posibles mejoras. Es esto lo que se discute en este capítulo.

Cómo se vio en los capítulos anteriores, existe un procedimiento que nos proporciona una muy buena solución para problemas de la programación lineal, sin embargo, no es así para el caso de la programación no lineal. Por esta razón es conveniente hacer un análisis para cada una de esas dos grandes divisiones, pero antes es conveniente hacer un análisis del algoritmo en general.

5.1 Análisis General.

El análisis general se realiza dividiéndolo en partes para concentrarse en un punto específico a la vez.

5.1.1 Tamaño en bits de cada variable.

Uno de los principales problemas que se tienen con el algoritmo genético para problemas de programación matemática se produce con el tipo de codificación que se utilizó. La dificultad tiene que ver con la magnitud de los valores de las variables que se esperan como solución.

En el caso de que las magnitudes de las variables sean más o menos iguales, el algoritmo genético no tiene problemas para trabajar y encontrar una solución aceptable siempre y cuando se haga una correcta selección del tamaño de la variable en bits (LVAR) y del número de bits de la parte entera (ENTERA). Una vez logrado esto, el algoritmo funciona correctamente.

El problema comienza cuando las variables tienen una diferencia en magnitud muy grande. Por ejemplo, en el caso de que la solución óptima de una de las variables sea menor a tres, mientras que la de alguna otra sea del orden de cientos o miles. La primera magnitud se podría representar en binario en tan

(41)

sólo dos bits de parte entera, mientras que la segunda requeriría de siete bits para su parte entera.

En realidad, por el mecanismo que sigue el algoritmo genético (ver capítulo 1) es mejor tener el número menor de bits para representar una cantidad, aún y cuando las magnitudes sean muy similares. Por ejemplo, si las respuestas son del orden de tres con dos bits es suficiente. Si se decide colocar una parte entera de dos bits vamos a obtener una mejor respuesta que si se decide colocar una parte entera de seis o siete bits donde la mayoría de ellos deberían ser cero para este problema. Por esta razón, es mejor tener el número de bits que se ajuste en lo más posible a la magnitud de la respuesta, donde se pueda codificar la misma.

En el caso de tener respuestas de la misma magnitud, un número de bits igual para todas las variables (como se manejó durante todos los ejemplos de este trabajo) sería apropiado. Pero en caso de que hubiera serias diferencias en magnitud se debe tomar un número de bits de acuerdo a la magnitud de la respuesta mayor, esto daría una falla en la aproximación de una de las variables (la más pequeña). Sin embargo, existe una solución al respecto la cual se explica más adelante.

Ahora supóngase que se sabe que las respuestas son de determinada magnitud, en ese caso no hay ningún problema ya que se calcula el número óptimo de bits para las variables sabiendo que el entero más grande que cabe en n bits está dado por;

2n- 1

el problema es que en la mayoría de los casos no se conoce la magnitud de las posibles respuestas.

Una solución a este problema es a "prueba y error", aumentando el número de bits, si no se llega a ima respuesta aceptable se disminuye, si mejora se sigue disminuyendo, si no se aumenta. Ahora, ese algoritmo puede ser seguido fácilmente por el programa. Una posible solución es programar este ajuste de bits para que lo haga automáticamente la computadora (ver sección 5.4).

Referencias

Documento similar

INVERSIONISTA O  DEPENDENCIA DE GOBIERNO.. 22  iniciales del proyecto y su factibilidad técnica de poder ser realizada. El objetivo final de este tipo de estudios es determinar

De manera adicional, se propone un algoritmo de localizaci ´on global para determinar la ubicaci ´on del robot dentro del ambiente, cuando no se tiene informaci ´on de la posici

Considerando que el modelo GARCH(l,l) en la varianza condicional y ARMA(5,0) en la media del rendimiento del IPC, un GARCH(2,l) con ARMA(í,l) para el retorno del NDQ,

Los resultados obtenidos utilizando el periodo abarcado en el presente trabajo (portafolios sugeridos para los años de 2003 a 2010, con base en información de 2002 a

Triangulación de la información COMPONENTES CATEGORÍAS INDICADORES DESCRIPCIÓN Conocimiento Persona Conocimiento Actitud y disposición Estilo de aprendizaje cómo aprende Concepción

Cada ducto tiene sus particularidades y cada método tiene sus ventajas y desventajas, algunos métodos como por ejemplo los basados en balance de masas solo pueden

El presente trabajo tiene como finalidad aumentar la información acerca de la seguridad y eficacia de la cirugía bariátrica en pacientes con obesidad grado I, la cual es

Para llevar a cabo la aplicación de criterio de desarrollo sustentable en el logro de este objetivo se utilizará como herramienta de análisis un modelo de evaluación