Vous êtes sur la page 1sur 47

Conceptos bsicos: Algoritmos y aproximaciones

En el siguiente trabajo pretendemos presentar una serie de concepto y definiciones propios del estudio de los Algoritmos, su anlisis y diseo. En el mismo podremos encontrar los conceptos de algoritmo y algunos de sus componentes, anlisis y diseo. Tambin veremos los diferentes tipos de formas y tamaos o medidas en que se pueden almacenar y representar los datos y estructuras en un algoritmo o programa. En ese mismo orden encontraremos las diferentes tcnicas para disearlos como son el mtodo de la fuerza bruta, el voraz, divide y vencers, programacin dinmica, de vuelta atrs, entre otros. De igual forma podremos ver las definiciones y algunas caractersticas, reglas, normas, tipos de algoritmos de bsqueda y ordenacin as como sus aplicaciones. Finalmente veremos los que es la verificacin y derivacin de programas, donde daremos los conceptos bsicos de semntica y sus tipos haciendo mayor nfasis en la semntica axiomtica, la recursividad e iteracin, los diseos de estos ltimos, as como los tpicos ciclos utilizados en algoritmos y programas y los paso a tener en cuenta al momento de desarrollar un algoritmo iterativo o recursivo. Es importante el estudio y conocimiento de lo que hoy conocemos como Algoritmos Computacionales, que desde su aparicin hasta nuestros das es, y seguir siendo; vital para el desarrollo de aplicaciones para computadoras y el manejo y dominio de la lgica de programacin para resolver problemas. Como estudiantes de la Facultad de Ciencias y Tecnologa " Escuela de Informtica y Computacin " de la Universidad Dominicana Organizacin y Mtodos O&M con aspiraciones de iniciarnos como Ingeniero en Sistemas y Computacin. Con el objetivo inmediato de aprobar con los mejores meritos la asignatura de Algoritmos Computacionales. General: Posibilitar la estudiante alcanzar una visin sistemtica de lo que conocemos sobre Los Algoritmos Computacionales. Especficos : Introducir los conceptos propios sobre Algoritmo, su importancia en el mundo de las aplicaciones para computadoras y el manejo de lgica de programacin.
y y y y y y

Proporcionar una idea de su uso. Visualizar sus ventajas e importancia. Definir sus tipos y variantes. Proporcionar conceptos sobre su anlisis y diseo. Proporcionar concepto sobre las tcnicas de diseo. Desglosar sus variantes (ordenacin, bsqueda, etc. ).

Marco Historico. Un algoritmo es un conjunto de operaciones y procedimientos que deben seguirse para resolver un problema. La palabra algoritmo se deriva del nombre latinizado del gran Matemtico rabe Mohamed Ibn Al Kow Rizmi, el cual escribi sobre los aos 800 y 825 su obra Quitad Al Mugabala, donde se recoga el sistema de numeracin hind y el concepto del cero. Fue Fibinacci, el que tradujo la obra al latn y el inicio con la palabra: Algoritmi Dicit. El lenguaje algortmico es aquel por medio al cual se realiza un anlisis previo del problema a resolver y encontrar un mtodo que permita resolverlo. El conjunto de todas las operaciones a realizar y e orden en que se deben efectuarse, se le denomina algoritmo.

Es un mtodo para resolver un problema mediante una serie de datos precisos, definidos y finitos. Generalidades El programador de computadoras es ante que nada una personaque resuelve problemas, por lo que para llegar a ser un programador eficaz se necesita aprender a resolver problemas de un modo riguroso y sistemtico. A la metodologa necesaria para resolver problemas mediante programas se denomina Metodologa de la Programacin. El eje central de esta metodologa es el concepto, ya tratado, de algoritmo. Un algoritmo es un mtodo para resolver un problema. Aunque la popularizacin del trmino ha llegado con el advenimiento de la era informtica, algoritmo proviene de Mohammed alKhowarizmi, matemtico persa que vivi durante el siglo IX y alcanzo gran reputacin por el enunciado de las reglas para sumar, restar, multiplicar y dividir nmeros decimales; la traduccinal latn del apellido de la palabra algorismus derivo posteriormente en algoritmo. Euclides, el gran matemtico griego (del siglo IV antes de Cristo) que invento un mtodo para encontrar el mximo comn divisor de dos nmeros, se considera con Al-Khowarizmi el otro gran padre de la algoritmia ( ciencia que trata de los algoritmos). El profesor Niklaus Wirth, inventor de Pascal, Modula-2 y Oberon, titulo uno de sus mas famosos libros, Algoritmos + Estructuras de Datos = Programas, significndonos que solo se puede llegar a realizar un buen programa con el diseo de un algoritmo y una correcta estructura de datos. Esta ecuacin ser de una de las hiptesis fundamentales consideradas en esta obra. La resolucin de un problema exige el diseo de un algoritmo que resuelva el problema propuesto. Los pasos para la resolucin de un problema son: 1. Diseo de algoritmo, que describe la secuencia ordenada de pasos que conducen a la solucin de un problema dado. (Anlisis del problema y desarrollo del algoritmo). 2. Expresar el algoritmo como un programa de lenguaje de programacin adecuado. (Fase de codificacin.) 3. Ejecucin y validacin del programa por la computadora. Para llegar a la realizacin de un programa es necesario el diseo previo de algoritmo, de modo que sin algoritmo no puede existir un programa. Los algoritmos son independientes tanto del lenguaje de programacin en que se expresan como de la computadoraque lo ejecuta. En cada problema el algoritmo se puede expresar en un lenguaje diferente de programacin y ejecutarse en una computadora distinta; sin embargo, el algoritmo ser siempre el mismo. As, por ejemplo, en una analoga con la vida diaria, una receta de un plato de cocina se puede expresar en espaol, ingles o francs, pero cualquiera que sea el lenguaje, los pasos para la elaboracin del plato se realizaran sin importar el idioma del cocinero. En la cienciade la computacin y en la programacin, los algoritmos son ms importantes que los lenguajes de programacin o las computadoras. Un lenguaje de programacin es tan solo un medio para expresar un algoritmo y una computadora es solo un procesador para ejecutarlo. Tanto el lenguaje de programacin como la computadora son los mediospara obtener un fin: conseguir que el algoritmo se ejecute y se efecte el proceso correspondiente. Dada la importancia del algoritmo en la ciencia de la computacin, un aspecto muy importante ser el diseo de algoritmos. El diseo de la mayora de los algoritmos requiere creatividady

conocimientos profundos de la tcnica de la programacin. En esencia, la solucin de un problema se puede expresar mediante un algoritmo. Caractersticas de los Algoritmos: Las caractersticas fundamentales que debe cumplir todo algoritmo son:
y y y

Un algoritmo debe ser preciso e indicar el orden de realizacin de cada paso. Un algoritmo debe estar definido. Si se sigue un algoritmo dos veces, se debe obtener el mismo resultado cada vez. Un algoritmo debe ser finito. Si se sigue un algoritmo se debe terminar en algn momento; o sea, debe tener un numero finito de pasos.

La definicin de un algoritmo debe definir tres partes: Entrada, Proceso y Salida. En el algoritmo de receta de cocina citado anteriormente se tendr: Entrada: ingrediente y utensilios empleados. Proceso: elaboracin de la receta en la cocina. Salida: terminacin del plato (por ejemplo, cordero). Ejemplo de Algoritmo: Un cliente ejecuta un pedido a una fbrica. Esta examina en su banco de datos la ficha del cliente; si el cliente es solvente entonces la empresa acepta el pedido; en caso contrario rechazara el pedido. Redactar el algoritmo correspondiente. Los pasos del algoritmo son: 1. 2. 3. 4. 5. inicio leer el pedido examinar la ficha del cliente si el cliente es solvente aceptar pedido; en caso contrario, rechazar pedido fin

Diseo del Algoritmo: En la etapa de anlisis del proceso de programacin se determina que hace el programa. En la etapa de diseo se determina como hace el programa la tarea solicitada. Los mtodos mas eficaces para el proceso de diseo se basan en el conocido por Divide y Vencers, es decir, la resolucin de un problema complejo se realiza dividiendo el problema en sub problemas y a continuacin dividir estos sub problemas en otros de nivel mas bajo, hasta que pueda ser implementada una solucin en la computadora. Este mtodo se conoce tcnicamente como diseo descendente (Top Down) o modular. El proceso de romper el problema en cada etapa y expresar cada paso en forma ms detallada se denomina refinamiento sucesivo. Cada sub programa es resuelto mediante un modulo (sub programa) que tiene un solo punto de entrada y un solo punto de salida. Cualquier programa bien diseado consta de un programa principal (el modulo de nivel mas alto) que llama a sub programas (mdulos de nivel mas bajo) que a su vez pueden llamar a otros sub programas. Los programas estructurados de esta forma se dice que tienen un diseo modular y el mtodo de romper el programa en mdulos ms pequeo se llama Programacin Modular. Los mdulos pueden ser planeados, codificados, comprobados y depurados independientemente (incluso por diferentes programadores) y a continuacin combinarlos entre si. El proceso implica la ejecucin de los siguientes pasos hasta que el programa se termina:

y y y y

programar modulo. Comprobar el modulo. Si es necesario, depurar el modulo. Combinar el modulo con los mdulos anteriores.

El proceso que convierte los resultados del anlisis del problema en un diseo modular con refinamiento sucesivo que permitan una posterior traduccin al lenguaje se denomina diseo de algoritmo. El diseo del algoritmo es independiente del lenguaje de programacin en el que se vaya a codificar posteriormente. 4. Anlisis De Algoritmos Recursos De Computadores Y Complejidad Algoritmo: Conjunto de reglas para resolver un problema. Su ejecucin requiere unos recursos. Un algoritmo es mejor cuantos menos recursos consuma, su facilidad de programarlo, corto, fcil de entender, robusto, etc. Criterio empresarial: Maximizar la eficiencia. Eficiencia: Relacin entre los recursos consumidos y los productos conseguidos. Recursos consumidos: Tiempo de ejecucin. Memoria principal: Entradas/salidas a disco. Comunicaciones, procesadores, etc. Lo que se consigue: Resolver un problema de forma exacta, forma aproximada o algunos casos. Recursos consumidos: Ejemplo. Cuntos recursos de tiempo y memoria consume el siguiente algoritmo sencillo? i:= 0 a[n+1]:= x repetir i:= i + 1 hasta a[i] = x Respuesta: Depende. De qu depende? De lo que valga n y x, de lo que haya en a, de los tipos de datos, de la mquina... En general los recursos dependen de: Factores externos. El ordenador donde lo ejecutemos: 286, Pentium III, Cray,... El lenguaje de programacin y el compilador usado. La implementacin que haga el programador del algoritmo. En particular, de las estructuras de datos utilizadas. Tamao de los datos de entrada. Ejemplo. Calcular la media de una matriz de NxM. Contenido de los datos de entrada. Mejor caso. El contenido favorece una rpida ejecucin. Peor caso. La ejecucin ms lenta posible. Caso promedio. Media de todos los posibles contenidos.

Los factores externos no aportan informacin sobre el algoritmo. Conclusin: Estudiar la variacin del tiempo y la memoria necesitada por un algoritmo respecto al tamao de la entrada y a los posibles casos, de forma aproximada (y parametrizada). externos no aportan informacin sobre el algoritmo. Normalmente usaremos la notacin T(N)=..., pero qu significa T(N)? Tiempo de ejecucin en segundos. T(N) = bN + c. Suponiendo que b y c son constantes, con los segundos que tardan las operaciones bsicas correspondientes. Instrucciones ejecutadas por el algoritmo. T(N) = 2N + 4. Tardarn todas lo mismo? Ejecuciones del bucle principal. T(N) = N+1. Cunto tiempo, cuntas instrucciones,...? Sabemos que cada ejecucin lleva un tiempo constante, luego se diferencia en una constante con los anteriores. Asignacin de tiempos, para el conteo de instrucciones. Algunas reglas bsicas. Operaciones bsicas (+, -, *, :=,...): Una unidad de tiempo, o alguna constante. Operaciones de entrada salida: Otra unidad de tiempo, o una constante diferente. Bucles FOR: Se pueden expresar como una sumatoria, con los lmites del FOR. IF y CASE: Estudiar lo que puede ocurrir. Mejor caso y peor caso segn la condicin. Se puede predecir cundo se cumplirn las condiciones? Llamadas a procedimientos: Calcular primero los procedimientos que no llaman a otros. Bucles WHILE y REPEAT: Estudiar lo que puede ocurrir. Existe una cota inferior y superior del nmero de ejecuciones? Se puede convertir en un FOR? El anlisis de algoritmos tambin puede ser a posteriori: implementar el algoritmo y contar lo que tarda para distintas entradas. Ejemplo. Programa "cifras.exe": N= 4, T(4)= 0.1 ms N= 5, T(5)= 5 ms N= 6, T(6)= 0.2 s N= 7, T(7)= 10 s N= 8, T(8)= 3.5 min Qu conclusiones podemos extraer? Anlisis a priori: Evitamos la implementacin, si el algoritmo es poco eficiente. Podemos hacer previsiones. Podemos comparar con otros algoritmos. Medidas Asintoticas Notacin asinttica: El tiempo de ejecucin T(n) est dado en base a unas constantes que dependen de factores externos. Nos interesa un anlisis que sea independiente de esos factores. Notaciones asintticas: Indican como crece T, para valores suficientemente grandes (asintticamente) sin considerar constantes. O(T): Orden de complejidad de T. W (T): Orden inferior de T, u omega de T. Q (T): Orden exacto de T. Orden de complejidad de f(n): O(f)

Dada una funcin f: N R+, llamamos orden de f al conjunto de todas las funciones de N en R+ acotadas superiormente por un mltiplo real positivo de f, para valores de n suficientemente grandes. O(f)= { t: N R+ / $ c R+, $ n0 N, " n n0: t(n) cf(n) } Nota: O(f) es un conjunto de funciones, no una funcin. "Valores de n sufic. Grandes...": no nos importa lo que pase para valores pequeos. "Funciones acotadas superiormente por un mltiplo de f...": nos quitamos las constantes. La definicin es aplicable a cualquier funcin de N en R, no slo tiempos de ejec. Propiedades P1. Si f O(g) y g O(h) entonces f O(h). Si f W (g) y g W (h) entonces f W (h) Ej. 2n+1 O(n), n O(n2) 2n+1 O(n2) P2. Si f O(g) entonces O(f) O(g). Cmo es la relacin para los W ? P3. Dadas f y g de N en R+, se cumple: i) O(f) = O(g) f O(g) y g O(f) ii) O(f) O(g) f O(g) La relacin de orden entre O(..) es completa? Dadas f y g, se cumple O(f) O(g) O(g) O(f)? P4. Dadas f y g, de N en R+, O(f+g) = O(max(f, g)). W (f+g) = W (max(f+g)) Y para los Q (f+g)? Es cierto que O(f - g) = O(max(f, -g))? P5. Dadas f y g de N en R+, se cumple: i) limn f(n) R+ O(f)=O(g), W (f)=W (g), Q (f)=Q (g) g(n) ii) limn f(n) = 0 O(f) O(g), W (g) W (f) g(n) P5. Ej. Qu relacin hay entre O(log2 n) y O(log10 n)? P6. Dadas f y g de N en R+, O(f)=O(g) Q (f)=Q (g) f Q (g) W (f)=W (g) P7. Dadas f y g de N en R+, se cumple: i) limn f(n) R+ O(f) = O(g) g(n) ii) limn f(n) = 0 O(f) O(g) g(n) iii) limn f(n) = + O(f) O(g) g(n) Notacin con varios parmetros: En general, el tiempo y la memoria consumidos pueden depender de muchos parmetros. f: Nm R+ (f: Nx...m..xN R+) Ej. Memoria en una tabla hash. M(B,n, l, k) = kB+l+n+2kn Orden de complejidad de f(n1, n2, ..., nm): O(f) Dada una funcin f: Nm R+, llamamos orden de f al conjunto de todas las funciones de Nm en R+ acotadas superiormente por un mltiplo real positivo de f, para valores de (n1, ..., nm) suficientemente grandes.

O(f)= { t: Nm R+ / $ c R+, $ n1, n2, .., nm N, " k1 n1 , k2 n2 ,..," km nm : t(k1, k2, ..., km) cf(k1, k2, ..., km) } De la misma forma, podemos extender los conceptos de W (f) y Q (f), para funciones con varios parmetros. Las propiedades se siguen cumpliendo Demostrarlo. Ejemplo. T(N) = T(N, a, b) = aN + b El tiempo depende del tamao del problema N, y del tiempo de inicializacin b y de ejecucin de un paso a. Podemos suponerlos constantes T(N), o variables T(N,a,b). Qu relacin hay entre los siguientes rdenes? O(n+m), O(nm) O(n2), O(n+2m) Notaciones condicionales: En algunos casos interesa estudiar el tiempo slo para ciertos tamaos de entrada. Ejemplo. Algoritmo de bsqueda binaria: Si N es potencia de 2 el estudio se simplifica. Orden condicionado de f(n): O(f | P) Dada una funcin f: N R+, y P: N B, llamamos orden de f segn P (o condicionado a P) al conjunto: O(f | P)= { t: N R+ / $ c R+, $ n0 N, " n n0: P(n) t(n) cf(n) } De igual forma, tenemos W (f | P) y Q (f | P). O(f) = O(f | true). Para cualquier f y g, f O(g | false). O(f) O(f | P)? Ordenes De Complejidad Uso de los rdenes de complejidad: Dado un tiempo t(n), encontrar la funcin f ms simple tal que t O(f), y que ms se aproxime asintticamente. Ejemplo. t(n) = 2n2/5 + 3p /2; t(n) O(n2). Relacin de orden entre O(..) = Relacin de inclusin entre conjuntos. O(f) O(g) O(f) O(g) Para toda t O(f), t O(g) Se cumple que: O(c) = O(d), siendo c y d constantes positivas. O(c) O(n) O(cn + b) = O(dn + e) O(p) = O(q), si p y q son polinomios del mismo grado. O(p) O(q), si p es un polinomio de menor grado que q. Orden inferior u omega de f(n): W (f): Dada una funcin f: N R+, llamamos omega de f al conjunto de todas las funciones de N en R+ acotadas inferiormente por un mltiplo real positivo de f, para valores de n suficientemente grandes. W (f)= { t: N R+ / $ c R+, $ n0 N, " n n0: t(n) cf(n) } La notacin omega se usa para establecer cotas inferiores del tiempo de ejecucin. Relacin de orden: igual que antes. Orden exacto de f(n): Q (f): Dada una funcin f: N R+, llamamos orden exacto de f al conjunto de todas las funciones de N en R+ que crecen igual que f, asintticamente y salvo constantes.

Q (f) = O(f) W (f) = { t: N R+ / $ c, d R+, $ n0 N, " n n0: cf(n) t(n) df(n) } Notacin o pequea de f(n): o(f): Dada una funcin f: N R+, llamamos o pequea de f al conjunto de todas las funciones de N en R+ que crecen igual que f asintticamente: o(f)= { t: N R+ / lim t(n)/f(n) = 1}n Esta notacin conserva las constantes multiplicativas para el trmino de mayor orden. Ejemplo. t(n) = amnm + am-1nm-1 + ... +a1n + a0 t(n) o(amnm) o(nm) o(amnm) O(amnm)? o(t) O(t)? Costa de complejidad con frecuencia Algunas relaciones entre rdenes frecuentes: O(1) O(log n) O(n) O(nlog n) O(n(log n)2) O(n1.001...) O(n2) O(n3) ... O(2n) O(n!) O(nn) Qu pasa con las omegas? Y con los rdenes exactos? El orden de un polinomio anxn+...+a1x+a0 es O(xn). nnn 1 = n O(n); i = n(n+1)/2 O(n2); im O(nm+1) i=1 i=1 i=1 Si hacemos una operacin para n, otra para n/2, n/4, ..., aparecer un orden logartmico O(log2 n). Los logaritmos son del mismo orden, independientemente de la base. 5. Tcnica de diseo de algoritmos Diseo de Algoritmos: Hasta ahora se han realizado algunos comentarios respecto a la necesidad de disear algoritmos correctos y eficientes utilizando los elementos de un lenguaje de programacin .Es necesario en este momento mencionar algo sobre como hacerlo. El acto de disear un algoritmo puede considerarse como una tarea que difcilmente podr ser del todo automatizada. Todo problema algortmico es un reto para su diseador, algunos resultan inmediatos de resolver, otros son bastante complejos. La investigacinen esta rea ha permitido descubrir un conjunto de mtodos o esquemas de diseo hacia los cuales puede orientarse la realizacin de muchos algoritmos. No obstante, y a pesar de que resulta mas adecuado en bastantes casos utilizar alguno de estos esquemas que realizar un diseo desde cero, idear un algoritmo continua siendo una labor bastante creativa donde los conocimientos y la experiencia del propio diseador tiene un papel fundamental. El diseo de un algoritmo que resuelva un problema es, en general, una tarea difcil. Una forma de facilitar esta labor consiste en recurrir a tcnicas conocidas de diseo de algoritmos, se decir, a esquemas muy generales que pueden adaptarse a un problema particular al detallar las partes generales del esquema. Muchos problemas pueden resolverse buscando una solucin fcil y directa pero, a la vez bastante ineficiente. Este mtodo, llamado de fuerza bruta, puede ser muy directo, pero con un poco de anlisis puede encontrarse algoritmos ms eficientes. El esquema mas sencillo quizs sea el llamado divide y vencers, basado en la descomposicin de un problema en

subproblemas. Otros esquemas requieren un anlisis minucioso del problema de forma que la solucin se vaya construyendo en etapas. Si puede preverse que decisin conviene en cada etapa para producir cierto tipo de mejor resultado, tenemos una solucin voraz, si la decisin en una etapa, solo puede tomarse tras considerar varias solucionesde otras etapas mas simples, la solucin es dinmica. Aun as, hay problemas cuya solucin no puede hallarse sino mediante un proceso de bsqueda, a pesar de lo complejas que son las operaciones de bsqueda, su uso adecuado mediante el esquema de bsqueda con retroceso (o backtracking) permite ganar gran eficiencia respecto a soluciones de fuerza bruta. Por ultimo, conviene conocer otros mtodos de diseo de algoritmos que tambin resultan de utilidad prctica. Nos estamos refiriendo a mtodos basados en la mejora de la eficiencia (por ejemplo, el uso de parmetros de acumulacin al resolver problemas utilizando divide y vencers, y el empleode tablas como estructura auxiliar para la resolucin eficiente de problemas donde se aplica programacin dinmica), y a mtodos basados en transformaciones del dominio para encontrar una solucin mas fcilmente a un problema en un dominio transformado, siendo dicha solucin finalmente adaptada al dominio original. Consideraciones generales Si el hbil programador dispone de un recetario de algoritmos de donde poder seleccionar el ms adecuado para cada problema, su tarea se simplifica. Supongamos que disponemos de una especificacin precisa, completa y consistente del problema a resolver y queremos obtener un algoritmo en el que, dados uno datos de entrada valido, se produzca cierto resultado. Si no nos importa la eficiencia del algoritmo, podramos utilizar un algoritmo general llamado algoritmo del museo britnico. Se programa un computador de manera que parta de un conjunto de axioma matemticos y los que use para reducir aleatoriamente teoremas validos. Aprender los principiosbsicos del diseo de algoritmos podemos preguntarnos por un mtodo aceptable. El mas entendido, y quizs el mejor, es organizar el diseo sobre un esquema de algoritmo o una tcnica de diseo que haya demostrado su utilidad para otros problemas. Este mtodo de trabajo es practicable, puesto que existe un nmero reducido de esquema y tcnicas de diseo. El conocimiento de tcnicas de diseo es solo un primer paso para el diseador, que debe completarse con otros conocimientos y, sobre todo, con la experiencia. Mtodo de fuerza bruta Comenzamos el estudio de esquemas algortmicos con un mtodo sencillo, pero que debe evitarse siempre que se pueda, dad su ineficacia; la fuerza bruta. En realidad, no es un esquema algortmico, si no mas bien calificativo Para una forma de disear algoritmos: tomar una solucin directa, poco reflexionada. En principio, esto no es malo, pero dado que no se ha analizado apenas el problema, es muy probable que no se hayan aprovechado propiedades deducibles del problema y que la solucin sea terriblemente ineficiente. Una solucin por fuerza bruta tambin puede resultar adecuada como primera aproximacin a la solucin final, porque su desarrollo puede permitir profundizar ms sobre el problema y conocer propiedades que sean utilizadas para obtener otra versin ms eficiente. Por ejemplos: Algunos algoritmos de bsqueda de un elemento en un vector. Uno de ellos realizaba una bsqueda secuencial con complejidad lineal sobre el tamao del vector y poda usarse con cualquier vector. Otro algoritmo realizaba un bsqueda dicotomica o binaria, con complejidad

logartmica, y solo se poda usar cuando el vector estuviese ordenado. El algoritmo primero responde a un razonamiento ms sencillo, por lo que uno puede sentirse tentado a usar siempre. Esta es la solucin de fuerza bruta: una solucin directa, pero poco reflexionada. Lo ms razonable es comprobar si el vector esta ordenado y, en caso positivo, aprovechar esta circunstancia para usar el algoritmo ms eficiente: el de bsqueda binaria. Tcnicas de los Parmetros Acumuladores y de Tabulacion La recurcion es un mecanismo que permite obtener, en combinacin con otras contrucciones, una solucin funcional a muchos problemas. Muchos algoritmos recursivos resultan eficientes, pero no todos: hay algunos fcilmente formulables, pero muy ineficientes. En estos casos, dichos algoritmos pueden servir como una primera aproximacin al algoritmo definitivo, pero debe mejorar su rendimiento para que sea prctico. Veremos dos parmetros para la mejora de eficiencia de algoritmos recursivos: el uso de parmetros acumuladores y el uso de tablas. Cada una se ilustra con un ejemplo distinto. Parmetros Acumuladores Veamos primero una solucin ineficiente que intentaremos mejorar. Ejemplo: Nmeros de Fibonacci Los nmeros de fibonacci suele especificarse como: Fib(0)=1 Fib(1)1 Fib(n+2)=fib(n)+fib(n+1) Esta especificacin de los nmeros de fibonacci tienen una formulacin recursiva inmediata en estilo funcional. Un modo de evitar problema lo proporciona la tcnica de los parmetros acumuladores, cuya idea bsica se expone a continuacin. La funcin principal usa una funcin auxiliar que tiene los parmetros de aquellas ms algunos adicionales. La funcin principal simplemente realiza una llamada a esta funcin auxiliar en los que los parmetros de aquellas se modifican y los parmetros nuevos toman un valor inicial adecuado . Los parmetros adicionales tienen como misin ir acumulando resultados principales durante el proceso recursivo. Tabulacion No todos los algoritmos recursivos ineficientes pueden optimizarse con la tcnica de los parmetros acumuladores. Otra tcnica til es el uso de tablas. La intencin es que la primera vez que se realiza un clculo, se almacena en una tabla, donde puede consultarse otras veces que se necesite. Esta tcnica tambin se suele emplear con la programacin dinmica. Ejemplo: Sea el problema de la competicin. Hay dos participantes (deportistas o equipos, no importa que), A,B, que juegan una competicin que es ganada por el primero que venza en n partidos, siendo ( n ) mayor que( 0 ). Por sencillez , se supone que ambos participantes tienen cualidades y preparacin similar . De forma que cada uno tiene un 50% de posibilidades de ganar cada partido. De todas formas, la modificacin para incorporar probabilidades diferentes es evidente y no complica el problema. Divide y vencers: Consiste en descomponer un problema en un subproblema, resolver independientemente los

subproblemas para luego combinar sus soluciones y obtener la solucin del problema original. Esta tcnica se puede aplicar con xito a problemas como la multiplicacin de matrices, la ordenacin de vectores, la bsqueda en estructuras ordenadas,etc. Ejemplo. Bsqueda de una palabra en un diccionario Como ejemplo sencillo de aplicacin de esta estrategia puede considerarse la bsqueda de una palabra en un diccionariode acuerdo con el siguiente criterio. Se abre el diccionario por la pagina centrar(quedando dividido en dos mitades) y se comprueba si la palabra aparece all o si es lxico grficamente anterior o posterior. Si no ha encontrado y es anterior se procede a buscarla en la primera mitad., si es posterior, se buscara en la segunda mitad. El procedimiento se repite sucesivamente hasta encontrar la palabra o decidir que no aparece. Mtodo voraz: Este mtodo trata de producir tipo de mejor resultado a partir de conjunto de opciones candidatas .Para ello, se va procedimiento paso a paso realizndose la mejor eleccin (usando una funcin objetivo que respeta un conjunto de restricciones ) de entre las posibles. Puede emplearse en problemas de optimizacin, como el conocido de la mochila, en la bsqueda de caminos mnimos sobre grafos, la planificacin en el orden de la ejecucin de unos programas en un computador,etc. Ejemplo. Dar un cambioutilizando el menor nmero de monedas Considrese ahora el problema de la devolucin del cambio al realizar una compra (por ejemplo, en una maquina expendedora de tabaco). Suponiendo que se disponga de cantidad suficiente de ciertos tipos diferentes de monedas de curso legal, se trata de dar como cambio la menor cantidad posible usando estos tipos de monedas. La estrategia voraz aplicada comienza devolviendo, cuando se pueda, la moneda de mayor valor ( es decir, mientras el valor de dicha moneda sea mayor o igual al cambio que resta por dar), continua aplicndose el mismo criterio para la segunda moneda mas valiosa, y as sucesivamente. El proceso finaliza cuando se ha devuelto todo el cambio. Consideraciones y Criterios para Disear Algoritmos Algunas consideraciones estilsticas pueden contribuir a mejor la calidadde los algoritmos (y programas ) mediante la reduccin del numero de errores que aparecen al desarrollar los. Tambin influyen haciendo que nuestro algoritmo resulten ms fciles de leer y entender para otras personas. Los criterios de estilo pueden reflejarse en un conjunto de normas de estilo de codificacin. Ello asegura que tanto algoritmos como programa resulten legibles y puedan modificarse fcilmente en caso de necesidad. Generalmente, estas normas de estilo se dirigen hacia aspectos como la forma de construir los nombres de variables o tipo de datos que aparezcan., la tipografa seguida ala hora de escribir nombres de variables, subprogramas, palabras claves, etc. El modo de encolumnar las distintas partes de un algoritmo para facilitar su lectura y comprensin, y la normas sobre como y donde deben de introducirse los comentarios. Estilo y calidad de los programas van fuertemente unidos. Ante la pregunta Cules son las caracterstica de un buen algoritmo?, las siguientes respuestas reflejan, cierta medida, los factores que identifican la calidad en ellos . 1. Correccin, el algoritmo debe funcionar. 2. Nunca se debe olvidar que la caracterstica ms simple e importante de un algoritmo es que funcione. Pude aparecer obvio, pero resulta difcil de asegurar en algoritmos complejos.

3. Eficiencia, el algoritmo no debe desaprovechar recursos. La eficiencia de un algoritmo se mide por los recursos que este consume. En particular, se habla de la memoria y del tiempo de ejecucin . A pesar de que con la reduccin de los costes del hardware es posible disear computadores ms rpidos y con ms memoria, no hay que desperdiciar estos recursos y tratar de desarrollar algoritmos ms eficientes. 4. Claridad, el algoritmo debe estar bien documentacin. La documentacin ayuda a comprender el funcionamiento de los algoritmos. Ciertos detalles o algunas partes especiales de los mismos pueden olvidarse fcilmente o quedar oscura si no estn adecuadamente comentadas. En realidad, y de acuerdo con los puntos de vista anteriores, la calidad de un algoritmo tiene muchas facetas y todas ellas importantes. Resumiendo, lo ideal es que nuestro algoritmo resulte correcto, eficiente, claro, fiable y fcil de mantener. Algoritmos voraces Esquema voraz Hay muchos problemas en los que se pretende obtener un subconjunto de n elementos que satisfaga ciertas restricciones y que optimice alguna medida. Se supone que un problema de esta clasetiene al menos una solucin. Puede haber varias soluciones optimas, en cuyo caso no importa cual se elija. Por ejemplo, sea el problema de encontrar un subconjunto de los arcos de un grafo. Otro ejemplo se da cuando, dados unos ficheros almacenados en una cinta de que el tiempo de recuperacin de un fichero cualquiera sea el mnimo en promedio. A menudo, el problema incluye restricciones adicionales que limitan el nmero posible de soluciones. Normalmente, estos problemas no se intentan resolver "de golpe ", encontrando de una sola vez la solucin completa y ptima. Es ms frecuente que el subconjunto de la solucin se vaya formando paso a paso, analizando durante cada etapa que elemento conviene aadir a la solucin parcial ya existente. La dificultad principal para resolver esta clase de problemas estriba en el anlisis necesario para poder formular un algoritmo que halle la solucin en varios pasos. Un algoritmo voraz sigue el esquema anterior, pero con la fortuna de que cada vez que aade un elemento a la solucin se tiene la certeza de haber realizado la mejor eleccin posible. Esta caracterstica hace que aunque el anlisis del problema sea arduo, la solucin voraz siempre resulte sencilla. La nica complicacin es comprobar que se siguen satisfaciendo las restricciones del problema. Por lo que se ha descrito del esquema voraz, ste es un proceso repetitivo sencillo que trata sucesivamente los diferentes elementos del problema. Para facilitar la descripcin de este proceso, puede llamarse candidato al elemento tratado en cada paso. Inicialmente, el conjunto de candidatos que forman la solucin est vaco. En cada paso se intenta aadir el mejor de los candidatos restantes a dicha solucin parcial. Si este conjunto ampliado sigue siendo vlido, es decir, si satisface las restricciones del problema y, por tanto, permite formar una solucin del problema, el candidato se incorpora definitivamente. Al contrario, si dicho conjunto no es vlido, se desecha el candidato. Si el algoritmo voraz se ha diseado correctamente, la primera solucin encontrada es ptima. Por tanto, la dificultad principal al disear un algoritmo voraz reside en encontrar un criterio en encontrar un criterio de seleccin que garantice la optimalidad de la solucin. Segn esta descripcin, el problema parte de:
y

Una funcin objetivo que da el valor de una solucin. Obviamente, sta es la funcin por optimizar.

Un conjunto de restricciones sobre el valor de los datos de entrada y sobre la solucin final del problema.

A su vez, la solucin consta de:


y y y

Un conjunto de candidatos Una funcin de seleccin que en cada momento determine que candidato de los an no usados parece ser el mejor. Una funcin que determine si cierto conjunto de candidatos es vlido; es decir, si permite formar alguna solucin del problema.

Obsrvese que las funciones de validez y completitud no se preocupan de la optimalidad del la solucin, pero si la funcin de seleccin es la adecuada, cada solucin vlida y completa es optima. Podemos representar el esquema voraz de la siguiente forma funcional: FUNCTION Voraz ( candidatos: ( 1..n ) : ( 1..n) -> FUNCTION VorazAcumulador ( candidatos : (1..n), Solucin : (1..n) : (1..n) -> Cadidatos = ( ) v EsSolucin ( solucin)-> Value siguiente -> seleccionar ( candidatos ) IN EsVlida (solucin v ( siguiente)) => VorazAcumulador (candidatos (solucin), solucin v (siguiente)) VorazAcumulador (candidatos (siguiente), solucin) VorazAcumulador (candidatos, ( ) ) Puede verse por qu estos algoritmos se llaman " voraces " : en cada paso toman el mejor trozo de la solucin; es decir, el mejor candidato. Adems, nunca cambian de opinin: una vez que un candidato es aceptado o rechazado en la solucin, la decisin, es definitiva. La funcin objetivo no suele aparecer en el algoritmo final, sino que se utiliza durante el anlisis del problema y es determinante en la eleccin de la funcin de seleccin. De todas formas, debe recordarse que puede haber varios criterios alternativos de seleccin y que de su correcta eleccin depende que la solucin calculada por el algoritmo sea optima. Como ejercicio, el lector puede intentar encontrar una solucin voraz del problema del calendario. Es fcil encontrar una solucin si en cada etapa se genera el subcalendario correspondiente a un equipo; es decir, la tabla de competicin se va completando por filas. Como fila primera se toma la secuencia de los ndices de los participantes en cualquier orden. Cada fila resultante puede tener una complejidad de o (n2). Adems, este algoritmo tiene la ventaja de valer para las situaciones en que el nmero de participantes no es una potencia de dos. Desglose en monedas Como primer ejemplo introductorio sencillo al que puede aplicarse la tcnica voraz, se considera el problema de un cambio o desglose en monedas. Hay que desglosar una cantidad en un conjunto de monedas tratando de cumplir alguna condicin; en este caso, utilizar el menor nmero de monedas. Para ello, se parte de un conjunto de tipos de monedas vlidas, de las que se supone que hay cantidad suficiente para realizar el desglose, y de un importe. Se trata de indicar la cantidad (menor) de monedas de los tipos considerados, tales que sumados sus valores equivalgan al importe.

Para simplificar, suponemos que manejamos dineroespaol y, en particular, podemos utilizar slo monedas de 500, 100, 50, 25, 5 y 1 pesetas para el desglose. Estos valores se definen por medio de un tipo enumerado MONEDAS. Asimismo, se declaran los tipos VALORES y CANTIDADES para representar el valor asignado a cada unidad monetaria y la cantidad de cada tipo de moneda que se devolver en el desglose. Su declaracin es la siguiente: TYPE Monedas -> M500 I M100 I M50 I M25 I M5 I M1, Valores -> Integer M500 M1 Cantidades -> Integer M500 .M1 Se supone inicialmente asignados los valores a cada uno de los tipos de monedas. Los elementos de la tcnica voraz estn presentes en este problema de la siguiente forma:
y y y y y

El conjunto de candidatos est constituido por cada una de las monedas de los diferentes tipos que se pueden usar para realizar el desglose del importe dado. Una solucin viene dad por un conjunto de monedas devuelto tras el desglose, y cuyo valor total es igual al importe a desglosar. La condicin de factibilidad de la solucin siendo construida establece en el desglose debe ser menor o igual que el importe a desglosar. La funcin de seleccin establece que hay que elegir, mientras sea posible, la moneda de mayor valor de entre las candidatas. La funcin objetivo cosiste en minimizar la cantidad total de monedas utilizadas en el desglose.

Con esta informacin se puede comprobar que en este problema estn presentes los distintos elementos de la tcnica voraz. Adems, cuando un candidato (moneda) se incorpora al conjunto solucin, ste no ser nunca excluido de l. Divide Y Vencers La tcnica divide y vencers consiste en descomponer el problema en un conjunto de subproblemas ms pequeos. Despus se resuelven estos subproblemas y se combinan las soluciones para obtener la solucin para el problema original. Esquema de Divide y vencers. La tcnica de divide y vencers es quizs una de las utilizadas debido a su sencillez: si un problema es demasiado grande para resolverlo de una vez, se descompone en varias partes ms fciles de resolver. Mas formalmente, dado un problema al resolver planteando en trminos de una entrada de tamao n, la tcnica de divide y vencers parte la entrada en k subproblemas, 1<k<=n. Estos subproblemas se resuelven independientemente y despus se combinan sus soluciones parciales para obtener la solucin del problema original. Este esquema de particin de problemas se denomina esquema de divide y vencers solo en el caso en que los problemas sean de la misma clase del problema original. Esta restriccin permite una formulacin y resolucin recursiva de los subproblemas. Por supuesto, deben existir algunos pasos sencillos cuya solucin pueda calcularse fcil y directamente; en caso contrario, el proceso recursivo nunca terminara. El caso ms frecuente es cuando el nmero de subproblemas es dos. Veamos el esquema de divide y vencers para dos subproblemas; es fcil su generalizacin a k subproblemas 2<k<=n. Su formacin funcional es como sigue, considerado el problema como de tipo dato y la solucin, de tipo resultado: TYPEVAR

Dato, resultado FUNCTION DivideYVenceras (problema : dato) : resultado -> EsPequeo (problema) }=> ResolverDirectamente (problema) | VALUE subproblemas -> Partir (problema) IN subproblemas == (subproblema1, subproblema2) => Combinar (DivideYVenceras (subproblema1) , DivideYVenceras (subproblema2)) Se puede hacer una formulacin imperativa similar. Sin embargo, escribiremos una formulacin ms restrictiva pero bastante usual, en la que se utiliza un vector de tamao N. TYPEVAR dato, resultado PROCEDURE DivideYVenceras (IN problema : dato1..n, OUT solucin : resultado) -> PROCEDURE DyVAux (IN problema : dato1..n, IN inferior, superior : 1..N, OUT solucin : resultado) -> VAR medio: 1..N subsolucion1, subsolucion2 : resultado IF EsPequeo (inferior, superior) THEN ResolverDirectamente (problema, inferior, superior, olucin) ELSE Medio := Partir (inferior, superior); DyVAux (problema, inferior, medio, subsolucion1); DyVAux (problema, medio+1, superior, subsolucion2); Combinar (subsolucion1, subsolucion2, solucin) DyVAux (problema, 1, N, solucin) El esquema general se adapta a un problema concreto al sustituir los metasimbolos EsPequeo, ResolverDirectamente, Partir y Combinar por funciones o procedimientos concretos. Si el tamao de los dos subproblemas es el mismo (o casi), el tiempo de cmputo de la funcin DivideYVecneras se describe con la siguiente relacin de recurrencia: g(n),si n es pequeo T(n) = 2 T(n/2) + f(n), en caso contrario donde T(n) es la funcin de tiempo de DivideYVenceras para entradas de tamao n, g(n) es el tiempo que tarda la funcin ResolverDirectamente en resolver problemas de pequeo tamao (normalmente una constante) y f(n) es el tiempo necesario para partir el problema y combinar las subsoluciones. La eficiencia final del algoritmo depende de la funcin f(n) concreta que aparezca durante el anlisis. Ntese que, es general, para que esta tcnica resulte eficiente todos los subproblemas deben ser de tamao parecido. Elaboracin de un Calendario Deportivo: Sea un campeonato deportivo; para nuestros propsitos resulta indiferente el deporteobjeto de la competicin, as que hablaremos de participantes en vez de deportistas o equipos. El problema consiste en elaborar un calendario de competicin de forma que cada participante compita exactamente una vez con cada uno de los dems participantes. Por concrecin, y sin perdida de generalidad, puede suponerse que las competiciones se celebran en das sucesivos y

que cada participante compite una vez por da. Para simplificar el problema, se supone que el numero de participantes es una potencia de dos; es decir, hay n = 2k participantes para algn entero positivo k. Se supone tambin que cada participante tiene asignado un nmero comprendido entre 1 y N. Se necesitan elaborar n-1 competiciones por participantes. Por tanto, la solucin del problema puede representarse en una tabla de dimensin nx(n-1). El elemento (i,j)esimo de la tabla, 1<= i<=n, 1<=j<n, contiene el numero del participante contra el que el participante i-esimo compite el da j-esimo. Obsrvese que los nmeros de participantes incluidos en la fila i de la tabla son distintos porque el participante i-esimo solo debe competir una vez con cada participante restante. A su vez, la columna j tambin contiene nmeros distintos, porque el da j-esimo cada participante solo puede competir con otro participante. Se dispone de una solucin inmediata aplicando fuerza bruta. Primero se obtiene para cada participante i, 1<=i<=n, el conjunto P(i) de todas las permutaciones posibles del resto de los participantes con los que debe competir, es decir, el conjunto de permutaciones de los nmeros {1..n}-{i} ahora se completan las filas de la tabla de todas las formas posibles, incluyendo en cada fila i algn ejemplo de P(i). Solo sirve como solucin aquellas combinaciones de fila que cumplan las restricciones enunciadas en el prrafoanterior sobre las columnas de la tabla (las restricciones sobre las filas estn garantizadas por el modo de generar los conjuntos P(i)). Si hay varios calendarios validos, se elige uno cualquiera. El mtodo de fuerza bruta resulta sencillo, pero es terriblemente ineficiente. Cada conjunto P(i) consta de (n-1)! Elementos. Dado que el numero de participantes de n, resultan nx(n-1)!=n! formas de rellenar la tabla. Sin embargo la aplicacin de la tcnica de divide y vencers produce una solucin mas sencillas aun pero muy eficientes. La siguiente figura describe visualmente parte de la elaboracin de la tabla.

das 1 participantes 1 2 2 1 1 2 3 1 2 3 4 2 1 4 3 3 4 1 2 4 3 2 1 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 2 1 4 3 8 5 6 7 3 4 1 2 7 8 5 6 4 3 2 1 6 7 8 5 5 6 7 8 1 2 3 4 6 5 8 7 4 1 2 3 7 8 5 6 3 4 1 2

8 7 6 5 2 3 4 1

Se distinguen dos casos. El caso bsico se da cuando solo hay dos participantes. La solucin es directa porque se celebra una sola competicin entre ambos. El caso recursivo, cuando hay ms de dos participantes, es ms complejo. Si el numero de participantes es 2k , para k>1, puede decirse que el "tamao" del problema es 2k (sabemos que el calendario tendr un tamao de 2k x(2k-1 -1) posiciones). El problema puede reducirse a dos sub problemas de tamao 2k-1 si se elaboran independientemente dos subcalendarios de tamao 2k x(2k-1 -1): uno para los participantes, de numeracin comprendida entre 1 y 2k-1 y otro para los participantes comprendidos entre 2k-1 +1 y 2k . Sin embargo, la unin de estos subcalendarios no forma un calendario completo para el campeonato de 2k participantes, ya que a unin de los dos calendarios tiene un tamao 2k x(2k-1 -1), faltando 2k x2k-1 celdas para completar el calendario total. En efecto, faltan por elaborar las competiciones cruzadas entre los participantes de numeracin inferior y los de numeracin superior. Por fortuna, el resto del calendario se puede construir fcilmente. Completemos primero la parte de los participantes de numeracin inferior. El subcalendario del primer participante es sencillo porque basta con que compita en das sucesivos con los participantes de numeracin, superior en orden creciente de numeracin; es decir, sucesivamente con los participantes 2k-1 +1, .,2n . El siguiente participante toma esta secuencia y realiza una fcil permutacin de la misma que le garantiza el respeto de las restricciones de la solucin; por ejemplo, rotando dicha secuencia a la derecha. Este proceso se repite para el resto de los participantes de numeracin inferior. El calendario de los participantes de numeracin superior se completa de forma similar con los nmeros de los participantes de numeracin inferior. El algoritmo descrito se expresa a continuacin. PROCEDURE Calendario ( INOUT tabla : (1..N)1..N,1..N-1) -> PROCEDURE FormaTabla (IN inf : 1..N, IN sup :1..N, OUT tabla : (1..N) 1..N,1..N-1) -> VAR medio : 1..N IF inf = sup-1 THEN tablainf.1 : = sup; tablasup.1 := inf ELSE medio := (inf + sup) Div 2; FormarTabla (inf, medio, tabla); FormarTabla (medio+1, sup, tabla); CompletarTabla (inf, medio, medio,sup-1, medio+1, tabla); CompletarTabla (medio+1, sup, medio, sup-1, inf, tabla) Este sistema de ecuacionesdefina una funcin de tiempo del orden de O(n2), que es mucho mas eficiente que la solucin de fuerza bruta. Veamos otra estrategia, tambin de orden de complejidad cuadrtica, donde se aplica divide y vencers para resolver el problema y que se aprovecha de la simetra de la solucin. La idea consiste en aadir inicialmente a la tabla una columna "ficticia" de ndice j=0, que almacena los ndices de las filas. Despus se genera, mediante divide y vencers, la mitad izquierda de la tabla. Finalmente se completa la mitad derecha de la tabla (correspondiente al cruce de los dos

grupos de equipos cuyos subcalendarios se han generado por divide y vencers). En esta ltima etapa, los valores de las casillas (k,l), siendo 1<=k<=n y 0<=l<=(n/2)-1, de acuerdo con las siguientes expresiones de los ndices: i = (k + n/2) Mod (n+1) j = (1 + n/2) Mod n De esta forma se rellenan las casillas aun vacas, es decir, los componentes tablai,j a partir de las casillas tablak,l ya completadas. Ordenacin de un Vector por Mezcla: La ordenacin de un vector es un problema que se presta fcilmente a la aplicacin de la tcnica de divide y vencers. El caso bsico corresponde a un subvector de un solo elemento, que obviamente ya esta ordenado. Para el caso general, sea vi..s un vector de ndice inferior i e ndice superior s. La particin puede hacerse por la mitad si se toma un ndice m=[(i+s)/2] y dos subvectores vi..m y vm+1..s . la combinacin de los dos subvectores ya ordenados es fcil. basta con mezclar los dos subvectores, mediante comparaciones de sus elementos sucesivos, para obtener un nico vector ordenado. Este proceso de mezcla es realizado por un procedimiento auxiliar. El algoritmo resultante es: PROCEDURE Ordenar (INOUT v : INTEGER1..N) -> (* ordenacin por mezcla *) PROCEDURE OrdenarAux (INOUT Vector : INTEGER1..N,1..N, IN inf, sup : 1..N) -> VAR Medio : 1..N IF inf < sup THEN medio := (inf+sup) Div 2; OrdenarAux (vector, inf, medio); OrdenarAux (vector, medio+1, sup); Mezclar (vector, inf, medio, sup) OrdenarAux (v, 1, N) El procedimiento para realizar la mezcla de los subvectores ordenados es: PROCEDURE Mezclar ( IN inf : INTEGER, IN medio: INTEGER, IN sup : INTEGER, INOUT vector : INTEGER1..N) -> VAR vectorAux : INTEGER1..N, i1, i2, j : INTEGER, ndice : INTEGER i1 := inf; i2 := medio + 1; j := inf; WHILE (i1<=medio) ^ (i2<=sup) DO IF vectori1 << vectori2 THEN vectorAuxj :=vectori1; i1 :=i1 + 1 ELSE vectorAuxj ;= vectori2; i2 := i2 + 1

j := j + FOR ndice IN i1..medio DO vectorAuxj := vectorindice; J := j + 1 FOR ndice IN i2..sup DO vectorAuxj := vectorindice ; J := j + 1 FOR ndice In inf..sup DO vectorindice := vectorAuxindice El algoritmo resultante es sencillo conceptualmente. Es fcil analizar la complejidad del algoritmo para un vector de longitud n. La operacin de mezcla es proporcional a n, de forma que las ecuaciones de recurrencia de la funcin de tiempo son: T(n) = a, n=1, a=cte 2T(n/2) + bn, n>1, b=cte Si n es una potencia de 2; es decir, n =2k para algn k, las ecuaciones anteriores se resuelven por sustituciones sucesivas, resultando: T(n) = 2T(n/2) + bn= =2K T(n/2K) + kbn = an + bn log2 n El algoritmo de ordenacin por mezcla es ptimo en tiempo de ejecucin. Los nicos inconvenientes que presenta es que el procedimiento de mezcla necesita gran capacidad de almacenamiento (para dos copias del vector) y que, adems de mezclar, necesita copiar el vector auxiliar completo en el principal. Puede disearse un algoritmo de mezcla ms complejo que mejore ambos aspectos, pero mantenga la complejidad asinttica calculada. Multiplicacin de Matrices: Sean dos matrices, A y B, de dimensin nxn. La matriz productoC=AxB tambin es una matriz de nxn cuyo elemento (i,j)-esimo se forma multiplicando cada elemento de la final i-esima de A por el elemento correspondiente de la columna j-esima de B y sumando los productos parciales. El clculo de cada elemento Cij requiere n multiplicaciones. La matriz C tiene n2 elementos, as que el tiempo total del algoritmo de multiplicacin es de orden O(n3). El algoritmo anterior, que podemos llamar algoritmo convencional de multiplicacin de matrices, proviene directamente de la definicin matemtica del producto de matrices. Sin embargo, la tcnica de divide y vencers sugiere un algoritmo distinto. Supongamos, por sencillez, que n es una potencia de dos; es decir, que existe un entero no negativo k tal que n=2k. (Si n no es un potencia de dos, pueden aadirse las filas y columnas de ceros necesarias para formar una dimensin que sea potencia de dos.) las submatrices A y B pueden partirse en cuatro submatrices de dimensin (n/2)x(n/2). Si el producto AxB tiene la forma: A11 A12 B11 B12 C11 C12 A21 A22 B21 B22 C21 C22 Entonces: C11 = A11*B11 + A12*B21 C12 = A11*B12 + A12*B22 C21 = A21*B11 + A22*B21 C22 = A21*B12 + A22*B22

Para n=2, los elementos Cij se calculan mediante algunas multiplicaciones y sumas de nmeros, pero para n>2 las submatrices Cij se calculan mediante multiplicaciones (recursivas) y sumas de submatrices de dimensin (n/2)x(n/2). Dos submatrices de (n/2)x(n/2) pueden sumarse en un tiempo bn2, siendo b alguna constante. La resolucin de este sistema de ecuaciones nos dice que O(T(n))=OT(n3), de forma que no se ha conseguido ningn ahorro sustancial de tiempo. Sin embargo, interesa encontrar algoritmos mas eficientes, porque la multiplicacin esta relacionada con otras operaciones sobre matrices mas usuales, como inversin de una matriz o hallar su determinante. La existencia de un algoritmo eficiente para la multiplicacin (en realidad, para cualquier operacin de las anteriores) significara la existencia de un algoritmo similar para las dems. Podra conseguirse mas eficiencia si logrramos realizar menos multiplicaciones de matrices, aunque fuera a costa de un mayor numero de sumas de matrices, dado que la complejidad respectiva de estas operaciones es O(n3)n y o(n2). El algoritmo de Strassen calcula las cuatro submatrices Cij empleando 7 multiplicaciones y 18 sumas o restas de matrices. Programacin Dinmica Principios de programacin dinmica Se ha visto que la tcnica voraz se aplica a problemas cuya solucin puede formularse como el resultado de una secuencia de decisiones. El mtodo es eficiente porque una vez que se toma una decisin en un paso, no se reconsidera en el futuro, conduciendo de forma directa a la solucin. Sin embargo, no todos los problemas pueden resolverse de esta manera, asegurando que la secuencia de decisiones es la mejor de las posibles. La programacin dinmica (tambin llamada planificacin dinmica) es una tcnica de programacin que tambin permite resolver problemas mediante una secuencia de decisiones, pero de una manera menos directa que en el caso voraz. Esta vez se necesita producir varias secuencias de decisiones. Solamente al final se sabe cul es la mejor de todas. No es fcil establecer una definicin de la programacin dinmica; una caracterstica es que el programa "aprende "dinmicamente de las decisiones que toma. Adems, todo problema resoluble con esta tcnica debe de satisfacer el principio de optimalidad. Este principio establece que "una secuencia ptima de decisiones que resuelve un problema debe cumplir la propiedad de que cualquier subsecuencia de decisiones tambin debe ser ptima respecto al subproblema que resuelva ". Usando una tcnica de fuerza bruta, el nmero de secuencias de decisin es exponencial sobre el nmero de decisiones, porque si hay d opciones para cada una de las n decisiones, resultar un total de d secuencias posibles de decisin. En la programacin dinmica todos los subproblemas se resuelven de acuerdo con criterio de tamao creciente y los resultados de subproblemas ms pequeos se almacenan en algn tipo de estructura de datos (normalmente tablas) para facilitar la solucin de los problemas ms grandes. De esta forma se reduce al nmero total de subsecuencias generadas, evitndose una explosin combinatoria en la produccin de las secuencias y consiguindose soluciones ms eficientes en cuanto a tiempo de ejecucin. Podemos formalizar algo ms la idea bsica. Supongamos que tenemos un problema que satisface el principio de optimalidad, tal que Eo es el estado inicial del problema y deben tomarse n decisiones d, 1<i<n. Sea D = { v1 ..vn} el conjunto de valores de decisin posibles para la decisin d1. sea, asimismo, Eli el estado del problema tras la eleccin del valor vli 1<i<n1 y Sli una secuencia ptima de decisiones respecto al estao Eli. Entonces, una secuencia ptima de decisiones respecto a E0 es la mejor secuencias de decisin { Vli Sli }, 1<i<N1.

El razonamiento anterior se refiere a la primera decisin d1 tomada desde el estado inicial E0 sin embargo, puede generalizarse la formulacin del problema a cualquier subsecuencia de decisiones dk ..,dl, 1<k<n, partiendo como estado inicial de Ek-1. si este subproblema de simboliza como problema (k,l), entonces el problema completo es problema ( l,n ). Tiene sentido centrarse en un subproblema del problema inicial porque ste satisface el principio de optimalidad pero, adems, tiene la ventaja ( quizs paradjica al tratar de un problema ms pequeo ) de que proporciona una visin ms general del problema en cuestin. ( Obsrvese que vamos a usar la tcnica de resolucin de problemas por generalizacin para despus poder realizar una particularizacin de la solucin obtenida.) Una solucin dinmica para problema ( k,1 ) debe expresarse en trminos de los valores de decisin existente para decisiones d1 y el subproblema problema ( k+1,1 ) resultante de aplicar cada valor de decisin. La expresin inicial de la ecuacin de recurrencia, hay un caso en que la decisin d1 no va seguida por ninguna secuencia de decisiones, que es problema ( n,n ). En resumen, la aplicacin de la tcnica de programacin dinmica a un problema significa comprobar primero el principio de optimalidad y desarrollar despus unas ecuaciones recurrentes del estilo de (1) y (2). La ecuacin general relaciona la secuencia ptima en una etapa i con la decisin tomada en la etapa i y la subsecuencia ptima en la etapa posterior i+1. la ecuacin de base establece el valor para la etapa n+1 en que no queda ninguna decisin Xi, 1<i<n, a tomar. La ecuacin de recurrencia puede formularse de dos formas: delantera o trasera. Sea X1 ..Xn la secuencia de decisiones necesaria para resolver el problema. La formulacin delantera expresa la decisin de Xl , 1<i<n, a partir de la secuencia de decisiones Xi+1 Xn ( es la clase de formulacin adoptada hasta ahora ). La formulacin trasera expresa la decisin de Xi, 1<i<n , a partir de la recurrentes con formulacin trasera es igual que e la formulacin delantera, slo que en orden contrario. La eleccin de una formulacin delantera o trasera depende del problema considerado o, sencillamente, del gusto del programador. Algoritmos De Vuelta Atrs Existen un alto nmero de problemas que pueden formularse como la bsqueda de la mejor solucin o del conjunto de todas las soluciones que satisfacen ciertas condiciones. Adems, cada solucin es el resultado de una secuencia de decisiones. Por supuesto, debe existir una funcin de criterios que debe ser satisfecha por cada secuencia solucin u optimizada por dichas secuencias solucin si solo queremos la mejor. En algunos problemas de optimizacin se conoce un criterio ptimo de seleccin que puede usarse de forma voraz. Otros problemas satisfacen el principio de optimalidad, pudindose aplicar la tcnica de programacin dinmica. Sin embargo, todava hay otros problemas peores que no queda mas remedio que realizar una bsqueda de la solucin. Esquema de Algoritmos de Vuelta Atrs: Sea (x1,...,xi) el camino desde la raz hasta un nodo de un rbol del espacio de estado. Sea G(x1...xi) el conjunto de todos los valores posibles de xi+1 tales que (x1,...,xi+1) es un camino hasta el estado del problema. Supongamos que existe algn predicado acotador A tal que A(x1,...,xi+1) es falso si el camino (xi,...,xi+1) no puede extenderse para alcanzar un nodo de respuesta. Por lo tanto, los candidatos para la posicin i+1 del vector desolucion x1..n son aquellos valores generados por G que satisfacen A. Supongamos que tambin existe algn predicado R que determina si un camino (x1,...,xi+1) termina en un nodo de respuesta. El Algoritmo de Vuelta Atrs se especifica de la forma siguiente: PROCEDURE Retroceso (IN k : INTEGER, INOUT solucion : elemento1...n) ->

VAR nodo : elemento FOR noso IN G(solucion, 1, k-1) DO Solucion k := nodo; IF R(solucion, 1, k) THEN IF R(solucion, 1,k) THEN << guardar solucion >>; Retroceso (k+1, solucion) La llamada inicial del algoritmo es Retroceso(1, solucion). El procedimiento no hace ninguna llamada recursiva cuando k = N+1 o cuando ningn nodo generado por G satisface el elemento posible que satisfacen A se aade una solucin particular, se comprueba si se ha encontrado una solucion. Despus simplemente se llama recursivamente al algoritmo para generar los estados descendientes. Se sale del bucle FOR cuando no quedan mas valores para solucin terminando la llamada actual al algoritmo. Ramificacin (Bifurcacion) Y Acotacin Los mtodos de Ramificacin y Acotacin constituyen un a variante de las tcnicas de retroceso para problemas donde se trata de encontrar el valor mximo o mnimo de cierta funcin objeto (esto suele suceder en los problemas de programacin lineal entera). La tcnica de ramificacin y acotacotacion aplica de la siguiente manera: Supngase que al recorrer un rbol y alcanza una hoja se tiene una solucion con k colores, y que al seguir avanzando en el rbol (mediante la aplicacin de varios pasos de retrocesos) se alcanza un nodo que requiere k+1 colores. En este punto podemos retroceder (y no seguir avanzando por mas ramas), pues tenemos ya una solucion mayor. As, k sirve de cota inferior al retroceso. Este mismo proceso se repite en el resto de nodos del rbol, evitando as la exploracin de gran parte de al estructura. Algoritmos Heuristicos Existen muchos problemas para los cuales no se conocen algoritmos que puedan encontrar la solucin de forma eficiente: problemas NP-completos. La solucin exacta puede requerir un orden factorial o exponencial: el problema de la explosin combinatoria. Se hace necesario utilizar algoritmos heursticos: Un algoritmo heurstico (o simplemente heurstica) puede producir una buena solucin (puede que la ptima) pero tambin puede que no produzca ninguna solucin o dar una solucin no muy buena. Normalmente, se basa en un conocimiento intuitivo del programador sobre un determinado problema. La estructura de algoritmo voraz se puede utilizar para construir procedimientos heursticos: hablamos de heursticas voraces. Objetivo: obtener buenas soluciones en un tiempo de ejecucin corto. El problema del viajante Problema: Dado un grafo no dirigido, completo y ponderado G = (V, A), encontrar un ciclo simple de costo mnimo que pase por todos los nodos. Es un problema NP, pero necesitamos una solucin eficiente. Problema de optimizacin, donde la solucin est formada por un grupo de elementos en cierto orden: podemos aplicar el esquema voraz. Posibilidades:

1.

Los nodos son los candidatos. Empezar en un nodo cualquiera. En cada paso moverse al nodo no visitado ms prximo al ltimo nodo seleccionado. 2. Las aristas son los candidatos. Hacer igual que en el algoritmo de Kruskal, pero garantizando que se forme un ciclo. Heurstica voraz 1 Una solucin ser un cierto orden en el conjunto de nodos (c1, c2, ..., cn), el orden de visita de los nodos. Inicializacin: seleccionar un nodo cualquiera. Funcin de seleccin: de los nodos candidatos seleccionar el ms prximo al ltimo (o al primero) de la secuencia actual (c1, c2, ..., ca). Acabamos cuando tengamos n nodos. Ejemplo. Empezando en el nodo 1. Solucin: (1, 4, 5, 3, 2) Coste: 30+15+25+10+45=125 Empezando en el nodo 3. Solucin: (5, 4, 3, 2, 1) Coste: 15+20+10+45+50=140 Heurstica voraz 2 Una solucin ser un conjunto de aristas (a1, a2, ..., an-1) que formen un ciclo hamiltoniano, sin importar el orden. Empezar con un grafo sin aristas. Seleccin: seleccionar la arista candidata de menor coste. Factible: una arista se puede aadir a la solucin actual si no se forma un ciclo (excepto para la ltima arista aadida) y si los nodos unidos no tienen grado mayor que 2. Ejemplo. Solucin: ((2, 3), (4, 5), (3, 4), (1, 2), (1, 5)) Coste = 10+15+20+45+50 = 140 Conclusiones: Ninguno de los dos algoritmos garantiza una solucin ptima. Sin embargo, normalmente ambos dan soluciones buenas, prximas a la ptima. Posibles mejoras: buscar heursticas mejores; repetir la heurstica 1 con varios orgenes; bien, a partir de la solucin del algoritmo intentar hacer modificaciones locales para mejorar esa solucin. Algoritmos De Aproximacin Dado un problema NP completo, es probable que no sepamos resolverlo de manera precisa y completa utilizando un algoritmo polimico en tiempo. Para este tipo de problemas, los algoritmos que no conducen a una solucin ptima se llaman algoritmos de aproximacin. Sin embargo, resulta parcialmente interesante que estos garanticen una cota en el margen de imprecisin. A continuacin se ilustra este tipo de tratamiento de problemas al problema de recubrimiento de un grafico: Dado un grafo G=(V,A), se trata de encontrar un conjunto con el menor numero de vrtices tal que toda arista sea incidente por lo menos de un vrtice de V. Este problema se puede resolver a travs de otro aproximado, como es calcular el ajuste maximizal del grafo G. Se trata de calcular un subconjunto A de aristas tal que dos aristas

cualquiera de A no tengan ningn vrtice comn y toda arista de A-A comparta algn vrtice comn con una arista de A. Este nuevo problema garantiza conseguir un recubrimiento que contiene no ms de dos vrtices del recubrimiento mnimo. El procedimiento para construir un ajuste maximizal de un grafo G consistira en ir tomando aristas de G, de una en una y en cualquier orden e ir eliminando las incidentes al conjunto que se esta construyendo hasta recubrir todo en grafo. Para poder aplicar el nuevo problema aproximado, seria necesario demostrar que el conjunto de todos los vrtices inciden a las aristas de un ajuste maximal M para un grafo G es un recubrimiento con no mas de dos veces el numero de veces el recubrimiento de tamao mnimo. Esto es evidente, ya que por la definicin de ajuste maximal, los vrtices incidentes a las aristas de M son un recubrimiento de G. tambin por la propia definicin, ningn vrtice perteneciente a M puede recubrir a mas de una arista en M. En consecuencia, por lo menos la mitad de los vrtices de M deben pertenecer a un recubrimiento. En el siguiente trabajopretendemos presentar una serie de conceptoy definiciones propios del estudio de los Algoritmos, su anlisis y diseo. En el mismo podremos encontrar los conceptos de algoritmo y algunos de sus componentes,anlisis y diseo. Tambin veremos los diferentes tipos de formas y tamaos o medidas en que se pueden almacenar y representar los datos y estructuras en un algoritmo o programa. En ese mismo orden encontraremos las diferentes tcnicaspara disearlos como son el mtodo de la fuerza bruta, el voraz, divide y vencers, programacin dinmica, de vuelta atrs, entre otros. De igual forma podremos ver las definiciones y algunas caractersticas, reglas, normas, tipos de algoritmos de bsqueda y ordenacin as como sus aplicaciones. Finalmente veremos los que es la verificacin y derivacin de programas, donde daremos los conceptos bsicos de semnticay sus tipos haciendo mayor nfasis en la semntica axiomtica, la recursividad e iteracin, los diseos de estos ltimos, as como los tpicos ciclos utilizados en algoritmos y programas y los paso a tener en cuenta al momento de desarrollar un algoritmo iterativo o recursivo. Justificacion Es importante el estudio y conocimiento de lo que hoy conocemos como Algoritmos Computacionales, que desde su aparicin hasta nuestros das es, y seguir siendo; vital para el desarrollo de aplicaciones para computadorasy el manejo y dominio de la lgica de programacin para resolver problemas. Motivacin Como estudiantes de la Facultad de Ciencias y Tecnologa " Escuela de Informtica y Computacin " de la Universidad Dominicana Organizacin y Mtodos O&M con aspiraciones de iniciarnos como Ingeniero en Sistemas y Computacin. Con el objetivoinmediato de aprobar con los mejores meritos la asignatura de Algoritmos Computacionales. Objetivos General : Posibilitar la estudiante alcanzar una visin sistemtica de lo que conocemos sobre Los Algoritmos Computacionales. Especficos : Introducir los conceptos propios sobre Algoritmo, su importancia en el mundo de las aplicaciones para computadoras y el manejo de lgica de programacin.

y y y y y y

Proporcionar una idea de su uso. Visualizar sus ventajas e importancia. Definir sus tipos y variantes. Proporcionar conceptos sobre su anlisis y diseo. Proporcionar concepto sobre las tcnicas de diseo. Desglosar sus variantes (ordenacin, bsqueda, etc. ).

2. Marco Historico Un algoritmo es un conjunto de operaciones y procedimientosque deben seguirse para resolver un problema. La palabra algoritmo se deriva del nombre latinizado del gran Matemtico rabe Mohamed Ibn Al Kow Rizmi, el cual escribi sobre los aos 800 y 825 su obra Quitad Al Mugabala, donde se recoga el sistema de numeracin hind y el concepto del cero. Fue Fibinacci, el que tradujo la obra al latn y el inicio con la palabra: Algoritmi Dicit. El lenguajealgortmico es aquel por medio al cual se realiza un anlisis previo del problema a resolver y encontrar un mtodo que permita resolverlo. El conjunto de todas las operaciones a realizar y e orden en que se deben efectuarse, se le denomina algoritmo. Es un mtodo para resolver un problema mediante una serie de datos precisos, definidos y finitos. 3. Generalidades El programador de computadoras es ante que nada una personaque resuelve problemas, por lo que para llegar a ser un programador eficaz se necesita aprender a resolver problemas de un modo riguroso y sistemtico. A la metodologa necesaria para resolver problemas mediante programas se denomina Metodologa de la Programacin. El eje central de esta metodologa es el concepto, ya tratado, de algoritmo. Un algoritmo es un mtodo para resolver un problema. Aunque la popularizacin del trmino ha llegado con el advenimiento de la era informtica, algoritmo proviene de Mohammed alKhowarizmi, matemtico persa que vivi durante el siglo IX y alcanzo gran reputacin por el enunciado de las reglas para sumar, restar, multiplicar y dividir nmeros decimales; la traduccinal latn del apellido de la palabra algorismus derivo posteriormente en algoritmo. Euclides, el gran matemtico griego (del siglo IV antes de Cristo) que invento un mtodo para encontrar el mximo comn divisor de dos nmeros, se considera con Al-Khowarizmi el otro gran padre de la algoritmia ( ciencia que trata de los algoritmos). El profesor Niklaus Wirth, inventor de Pascal, Modula-2 y Oberon, titulo uno de sus mas famosos libros, Algoritmos + Estructuras de Datos = Programas, significndonos que solo se puede llegar a realizar un buen programa con el diseo de un algoritmo y una correcta estructura de datos. Esta ecuacin ser de una de las hiptesis fundamentales consideradas en esta obra. La resolucin de un problema exige el diseo de un algoritmo que resuelva el problema propuesto. Los pasos para la resolucin de un problema son: 1. Diseo de algoritmo, que describe la secuencia ordenada de pasos que conducen a la solucin de un problema dado. (Anlisis del problema y desarrollo del algoritmo). 2. Expresar el algoritmo como un programa de lenguaje de programacin adecuado. (Fase de codificacin.) 3. Ejecucin y validacin del programa por la computadora.

Para llegar a la realizacin de un programa es necesario el diseo previo de algoritmo, de modo que sin algoritmo no puede existir un programa. Los algoritmos son independientes tanto del lenguaje de programacin en que se expresan como de la computadoraque lo ejecuta. En cada problema el algoritmo se puede expresar en un lenguaje diferente de programacin y ejecutarse en una computadora distinta; sin embargo, el algoritmo ser siempre el mismo. As, por ejemplo, en una analoga con la vida diaria, una receta de un plato de cocina se puede expresar en espaol, ingles o francs, pero cualquiera que sea el lenguaje, los pasos para la elaboracin del plato se realizaran sin importar el idioma del cocinero. En la cienciade la computacin y en la programacin, los algoritmos son ms importantes que los lenguajes de programacin o las computadoras. Un lenguaje de programacin es tan solo un medio para expresar un algoritmo y una computadora es solo un procesador para ejecutarlo. Tanto el lenguaje de programacin como la computadora son los mediospara obtener un fin: conseguir que el algoritmo se ejecute y se efecte el proceso correspondiente. Dada la importancia del algoritmo en la ciencia de la computacin, un aspecto muy importante ser el diseo de algoritmos. El diseo de la mayora de los algoritmos requiere creatividady conocimientos profundos de la tcnica de la programacin. En esencia, la solucin de un problema se puede expresar mediante un algoritmo. Caractersticas de los Algoritmos: Las caractersticas fundamentales que debe cumplir todo algoritmo son:
y y y

Un algoritmo debe ser preciso e indicar el orden de realizacin de cada paso. Un algoritmo debe estar definido. Si se sigue un algoritmo dos veces, se debe obtener el mismo resultado cada vez. Un algoritmo debe ser finito. Si se sigue un algoritmo se debe terminar en algn momento; o sea, debe tener un numero finito de pasos.

La definicin de un algoritmo debe definir tres partes: Entrada, Proceso y Salida. En el algoritmo de receta de cocina citado anteriormente se tendr: Entrada: ingrediente y utensilios empleados. Proceso: elaboracin de la receta en la cocina. Salida: terminacin del plato (por ejemplo, cordero). Ejemplo de Algoritmo: Un cliente ejecuta un pedido a una fbrica. Esta examina en su banco de datos la ficha del cliente; si el cliente es solvente entonces la empresa acepta el pedido; en caso contrario rechazara el pedido. Redactar el algoritmo correspondiente. Los pasos del algoritmo son: 1. 2. 3. 4. 5. inicio leer el pedido examinar la ficha del cliente si el cliente es solvente aceptar pedido; en caso contrario, rechazar pedido fin

Diseo del Algoritmo: En la etapa de anlisis del proceso de programacin se determina que hace el programa. En la etapa de diseo se determina como hace el programa la tarea solicitada. Los mtodos mas eficaces para el proceso de diseo se basan en el conocido por Divide y Vencers, es decir, la

resolucin de un problema complejo se realiza dividiendo el problema en sub problemas y a continuacin dividir estos sub problemas en otros de nivel mas bajo, hasta que pueda ser implementada una solucin en la computadora. Este mtodo se conoce tcnicamente como diseo descendente (Top Down) o modular. El proceso de romper el problema en cada etapa y expresar cada paso en forma ms detallada se denomina refinamiento sucesivo. Cada sub programa es resuelto mediante un modulo (sub programa) que tiene un solo punto de entrada y un solo punto de salida. Cualquier programa bien diseado consta de un programa principal (el modulo de nivel mas alto) que llama a sub programas (mdulos de nivel mas bajo) que a su vez pueden llamar a otros sub programas. Los programas estructurados de esta forma se dice que tienen un diseo modular y el mtodo de romper el programa en mdulos ms pequeo se llama Programacin Modular. Los mdulos pueden ser planeados, codificados, comprobados y depurados independientemente (incluso por diferentes programadores) y a continuacin combinarlos entre si. El proceso implica la ejecucin de los siguientes pasos hasta que el programa se termina:
y y y y

programar modulo. Comprobar el modulo. Si es necesario, depurar el modulo. Combinar el modulo con los mdulos anteriores.

El proceso que convierte los resultados del anlisis del problema en un diseo modular con refinamiento sucesivo que permitan una posterior traduccin al lenguaje se denomina diseo de algoritmo. El diseo del algoritmo es independiente del lenguaje de programacin en el que se vaya a codificar posteriormente. 4. Anlisis De Algoritmos Recursos De Computadores Y Complejidad Algoritmo: Conjunto de reglas para resolver un problema. Su ejecucin requiere unos recursos. Un algoritmo es mejor cuantos menos recursos consuma, su facilidad de programarlo, corto, fcil de entender, robusto, etc. Criterio empresarial: Maximizar la eficiencia. Eficiencia: Relacin entre los recursos consumidos y los productos conseguidos. Recursos consumidos: Tiempo de ejecucin. Memoria principal: Entradas/salidas a disco. Comunicaciones, procesadores, etc. Lo que se consigue: Resolver un problema de forma exacta, forma aproximada o algunos casos. Recursos consumidos: Ejemplo. Cuntos recursos de tiempo y memoria consume el siguiente algoritmo sencillo? i:= 0 a[n+1]:= x repetir i:= i + 1

hasta a[i] = x Respuesta: Depende. De qu depende? De lo que valga n y x, de lo que haya en a, de los tipos de datos, de la mquina... En general los recursos dependen de: Factores externos. El ordenador donde lo ejecutemos: 286, Pentium III, Cray,... El lenguaje de programacin y el compilador usado. La implementacin que haga el programador del algoritmo. En particular, de las estructuras de datos utilizadas. Tamao de los datos de entrada. Ejemplo. Calcular la media de una matriz de NxM. Contenido de los datos de entrada. Mejor caso. El contenido favorece una rpida ejecucin. Peor caso. La ejecucin ms lenta posible. Caso promedio. Media de todos los posibles contenidos. Los factores externos no aportan informacin sobre el algoritmo. Conclusin: Estudiar la variacin del tiempo y la memoria necesitada por un algoritmo respecto al tamao de la entrada y a los posibles casos, de forma aproximada (y parametrizada). externos no aportan informacin sobre el algoritmo. Normalmente usaremos la notacin T(N)=..., pero qu significa T(N)? Tiempo de ejecucin en segundos. T(N) = bN + c. Suponiendo que b y c son constantes, con los segundos que tardan las operaciones bsicas correspondientes. Instrucciones ejecutadas por el algoritmo. T(N) = 2N + 4. Tardarn todas lo mismo? Ejecuciones del bucle principal. T(N) = N+1. Cunto tiempo, cuntas instrucciones,...? Sabemos que cada ejecucin lleva un tiempo constante, luego se diferencia en una constante con los anteriores. Asignacin de tiempos, para el conteo de instrucciones. Algunas reglas bsicas. Operaciones bsicas (+, -, *, :=,...): Una unidad de tiempo, o alguna constante. Operaciones de entrada salida: Otra unidad de tiempo, o una constante diferente. Bucles FOR: Se pueden expresar como una sumatoria, con los lmites del FOR. IF y CASE: Estudiar lo que puede ocurrir. Mejor caso y peor caso segn la condicin. Se puede predecir cundo se cumplirn las condiciones? Llamadas a procedimientos: Calcular primero los procedimientos que no llaman a otros. Bucles WHILE y REPEAT: Estudiar lo que puede ocurrir. Existe una cota inferior y superior del nmero de ejecuciones? Se puede convertir en un FOR? El anlisis de algoritmos tambin puede ser a posteriori: implementar el algoritmo y contar lo que tarda para distintas entradas. Ejemplo. Programa "cifras.exe": N= 4, T(4)= 0.1 ms N= 5, T(5)= 5 ms N= 6, T(6)= 0.2 s

N= 7, T(7)= 10 s N= 8, T(8)= 3.5 min Qu conclusiones podemos extraer? Anlisis a priori: Evitamos la implementacin, si el algoritmo es poco eficiente. Podemos hacer previsiones. Podemos comparar con otros algoritmos. Medidas Asintoticas Notacin asinttica: El tiempo de ejecucin T(n) est dado en base a unas constantes que dependen de factores externos. Nos interesa un anlisis que sea independiente de esos factores. Notaciones asintticas: Indican como crece T, para valores suficientemente grandes (asintticamente) sin considerar constantes. O(T): Orden de complejidad de T. W (T): Orden inferior de T, u omega de T. Q (T): Orden exacto de T. Orden de complejidad de f(n): O(f) Dada una funcin f: N R+, llamamos orden de f al conjunto de todas las funciones de N en R+ acotadas superiormente por un mltiplo real positivo de f, para valores de n suficientemente grandes. O(f)= { t: N R+ / $ c R+, $ n0 N, " n n0: t(n) cf(n) } Nota: O(f) es un conjunto de funciones, no una funcin. "Valores de n sufic. Grandes...": no nos importa lo que pase para valores pequeos. "Funciones acotadas superiormente por un mltiplo de f...": nos quitamos las constantes. La definicin es aplicable a cualquier funcin de N en R, no slo tiempos de ejec. Propiedades P1. Si f O(g) y g O(h) entonces f O(h). Si f W (g) y g W (h) entonces f W (h) Ej. 2n+1 O(n), n O(n2) 2n+1 O(n2) P2. Si f O(g) entonces O(f) O(g). Cmo es la relacin para los W ? P3. Dadas f y g de N en R+, se cumple: i) O(f) = O(g) f O(g) y g O(f) ii) O(f) O(g) f O(g) La relacin de orden entre O(..) es completa? Dadas f y g, se cumple O(f) O(g) O(g) O(f)? P4. Dadas f y g, de N en R+, O(f+g) = O(max(f, g)). W (f+g) = W (max(f+g)) Y para los Q (f+g)? Es cierto que O(f - g) = O(max(f, -g))? P5. Dadas f y g de N en R+, se cumple: i) limn f(n) R+ O(f)=O(g), W (f)=W (g), Q (f)=Q (g) g(n) ii) limn f(n) = 0 O(f) O(g), W (g) W (f) g(n)

P5. Ej. Qu relacin hay entre O(log2 n) y O(log10 n)? P6. Dadas f y g de N en R+, O(f)=O(g) Q (f)=Q (g) f Q (g) W (f)=W (g) P7. Dadas f y g de N en R+, se cumple: i) limn f(n) R+ O(f) = O(g) g(n) ii) limn f(n) = 0 O(f) O(g) g(n) iii) limn f(n) = + O(f) O(g) g(n) Notacin con varios parmetros: En general, el tiempo y la memoria consumidos pueden depender de muchos parmetros. f: Nm R+ (f: Nx...m..xN R+) Ej. Memoria en una tabla hash. M(B,n, l, k) = kB+l+n+2kn Orden de complejidad de f(n1, n2, ..., nm): O(f) Dada una funcin f: Nm R+, llamamos orden de f al conjunto de todas las funciones de Nm en R+ acotadas superiormente por un mltiplo real positivo de f, para valores de (n1, ..., nm) suficientemente grandes. O(f)= { t: Nm R+ / $ c R+, $ n1, n2, .., nm N, " k1 n1 , k2 n2 ,..," km nm : t(k1, k2, ..., km) cf(k1, k2, ..., km) } De la misma forma, podemos extender los conceptos de W (f) y Q (f), para funciones con varios parmetros. Las propiedades se siguen cumpliendo Demostrarlo. Ejemplo. T(N) = T(N, a, b) = aN + b El tiempo depende del tamao del problema N, y del tiempo de inicializacin b y de ejecucin de un paso a. Podemos suponerlos constantes T(N), o variables T(N,a,b). Qu relacin hay entre los siguientes rdenes? O(n+m), O(nm) O(n2), O(n+2m) Notaciones condicionales: En algunos casos interesa estudiar el tiempo slo para ciertos tamaos de entrada. Ejemplo. Algoritmo de bsqueda binaria: Si N es potencia de 2 el estudio se simplifica. Orden condicionado de f(n): O(f | P) Dada una funcin f: N R+, y P: N B, llamamos orden de f segn P (o condicionado a P) al conjunto: O(f | P)= { t: N R+ / $ c R+, $ n0 N, " n n0: P(n) t(n) cf(n) } De igual forma, tenemos W (f | P) y Q (f | P). O(f) = O(f | true). Para cualquier f y g, f O(g | false). O(f) O(f | P)? Ordenes De Complejidad Uso de los rdenes de complejidad: Dado un tiempo t(n), encontrar la funcin f ms simple tal que t O(f), y que ms se aproxime asintticamente. Ejemplo. t(n) = 2n2/5 + 3p /2; t(n) O(n2). Relacin de orden entre O(..) = Relacin de inclusin entre conjuntos.

O(f) O(g) O(f) O(g) Para toda t O(f), t O(g) Se cumple que: O(c) = O(d), siendo c y d constantes positivas. O(c) O(n) O(cn + b) = O(dn + e) O(p) = O(q), si p y q son polinomios del mismo grado. O(p) O(q), si p es un polinomio de menor grado que q. Orden inferior u omega de f(n): W (f): Dada una funcin f: N R+, llamamos omega de f al conjunto de todas las funciones de N en R+ acotadas inferiormente por un mltiplo real positivo de f, para valores de n suficientemente grandes. W (f)= { t: N R+ / $ c R+, $ n0 N, " n n0: t(n) cf(n) } La notacin omega se usa para establecer cotas inferiores del tiempo de ejecucin. Relacin de orden: igual que antes. Orden exacto de f(n): Q (f): Dada una funcin f: N R+, llamamos orden exacto de f al conjunto de todas las funciones de N en R+ que crecen igual que f, asintticamente y salvo constantes. Q (f) = O(f) W (f) = { t: N R+ / $ c, d R+, $ n0 N, " n n0: cf(n) t(n) df(n) } Notacin o pequea de f(n): o(f): Dada una funcin f: N R+, llamamos o pequea de f al conjunto de todas las funciones de N en R+ que crecen igual que f asintticamente: o(f)= { t: N R+ / lim t(n)/f(n) = 1}n Esta notacin conserva las constantes multiplicativas para el trmino de mayor orden. Ejemplo. t(n) = amnm + am-1nm-1 + ... +a1n + a0 t(n) o(amnm) o(nm) o(amnm) O(amnm)? o(t) O(t)? Costa de complejidad con frecuencia Algunas relaciones entre rdenes frecuentes: O(1) O(log n) O(n) O(nlog n) O(n(log n)2) O(n1.001...) O(n2) O(n3) ... O(2n) O(n!) O(nn) Qu pasa con las omegas? Y con los rdenes exactos? El orden de un polinomio anxn+...+a1x+a0 es O(xn). nnn 1 = n O(n); i = n(n+1)/2 O(n2); im O(nm+1) i=1 i=1 i=1 Si hacemos una operacin para n, otra para n/2, n/4, ..., aparecer un orden logartmico O(log2 n). Los logaritmos son del mismo orden, independientemente de la base. 5. Tcnica de diseo de algoritmos Diseo de Algoritmos: Hasta ahora se han realizado algunos comentarios respecto a la necesidad de disear algoritmos correctos y eficientes utilizando los elementos de un lenguaje de programacin .Es necesario en este momento mencionar algo sobre como hacerlo. El acto de disear un algoritmo puede considerarse como una tarea que difcilmente podr ser del todo

automatizada. Todo problema algortmico es un reto para su diseador, algunos resultan inmediatos de resolver, otros son bastante complejos. La investigacinen esta rea ha permitido descubrir un conjunto de mtodos o esquemas de diseo hacia los cuales puede orientarse la realizacin de muchos algoritmos. No obstante, y a pesar de que resulta mas adecuado en bastantes casos utilizar alguno de estos esquemas que realizar un diseo desde cero, idear un algoritmo continua siendo una labor bastante creativa donde los conocimientos y la experiencia del propio diseador tiene un papel fundamental. El diseo de un algoritmo que resuelva un problema es, en general, una tarea difcil. Una forma de facilitar esta labor consiste en recurrir a tcnicas conocidas de diseo de algoritmos, se decir, a esquemas muy generales que pueden adaptarse a un problema particular al detallar las partes generales del esquema. Muchos problemas pueden resolverse buscando una solucin fcil y directa pero, a la vez bastante ineficiente. Este mtodo, llamado de fuerza bruta, puede ser muy directo, pero con un poco de anlisis puede encontrarse algoritmos ms eficientes. El esquema mas sencillo quizs sea el llamado divide y vencers, basado en la descomposicin de un problema en subproblemas. Otros esquemas requieren un anlisis minucioso del problema de forma que la solucin se vaya construyendo en etapas. Si puede preverse que decisin conviene en cada etapa para producir cierto tipo de mejor resultado, tenemos una solucin voraz, si la decisin en una etapa, solo puede tomarse tras considerar varias solucionesde otras etapas mas simples, la solucin es dinmica. Aun as, hay problemas cuya solucin no puede hallarse sino mediante un proceso de bsqueda, a pesar de lo complejas que son las operaciones de bsqueda, su uso adecuado mediante el esquema de bsqueda con retroceso (o backtracking) permite ganar gran eficiencia respecto a soluciones de fuerza bruta. Por ultimo, conviene conocer otros mtodos de diseo de algoritmos que tambin resultan de utilidad prctica. Nos estamos refiriendo a mtodos basados en la mejora de la eficiencia (por ejemplo, el uso de parmetros de acumulacin al resolver problemas utilizando divide y vencers, y el empleode tablas como estructura auxiliar para la resolucin eficiente de problemas donde se aplica programacin dinmica), y a mtodos basados en transformaciones del dominio para encontrar una solucin mas fcilmente a un problema en un dominio transformado, siendo dicha solucin finalmente adaptada al dominio original. Consideraciones generales Si el hbil programador dispone de un recetario de algoritmos de donde poder seleccionar el ms adecuado para cada problema, su tarea se simplifica. Supongamos que disponemos de una especificacin precisa, completa y consistente del problema a resolver y queremos obtener un algoritmo en el que, dados uno datos de entrada valido, se produzca cierto resultado. Si no nos importa la eficiencia del algoritmo, podramos utilizar un algoritmo general llamado algoritmo del museo britnico. Se programa un computador de manera que parta de un conjunto de axioma matemticos y los que use para reducir aleatoriamente teoremas validos. Aprender los principiosbsicos del diseo de algoritmos podemos preguntarnos por un mtodo aceptable. El mas entendido, y quizs el mejor, es organizar el diseo sobre un esquema de algoritmo o una tcnica de diseo que haya demostrado su utilidad para otros problemas. Este mtodo de trabajo es practicable, puesto que existe un nmero reducido de esquema y tcnicas de diseo. El conocimiento de tcnicas de diseo es solo un primer paso para el diseador, que debe

completarse con otros conocimientos y, sobre todo, con la experiencia. Mtodo de fuerza bruta Comenzamos el estudio de esquemas algortmicos con un mtodo sencillo, pero que debe evitarse siempre que se pueda, dad su ineficacia; la fuerza bruta. En realidad, no es un esquema algortmico, si no mas bien calificativo Para una forma de disear algoritmos: tomar una solucin directa, poco reflexionada. En principio, esto no es malo, pero dado que no se ha analizado apenas el problema, es muy probable que no se hayan aprovechado propiedades deducibles del problema y que la solucin sea terriblemente ineficiente. Una solucin por fuerza bruta tambin puede resultar adecuada como primera aproximacin a la solucin final, porque su desarrollo puede permitir profundizar ms sobre el problema y conocer propiedades que sean utilizadas para obtener otra versin ms eficiente. Por ejemplos: Algunos algoritmos de bsqueda de un elemento en un vector. Uno de ellos realizaba una bsqueda secuencial con complejidad lineal sobre el tamao del vector y poda usarse con cualquier vector. Otro algoritmo realizaba un bsqueda dicotomica o binaria, con complejidad logartmica, y solo se poda usar cuando el vector estuviese ordenado. El algoritmo primero responde a un razonamiento ms sencillo, por lo que uno puede sentirse tentado a usar siempre. Esta es la solucin de fuerza bruta: una solucin directa, pero poco reflexionada. Lo ms razonable es comprobar si el vector esta ordenado y, en caso positivo, aprovechar esta circunstancia para usar el algoritmo ms eficiente: el de bsqueda binaria. Tcnicas de los Parmetros Acumuladores y de Tabulacion La recurcion es un mecanismo que permite obtener, en combinacin con otras contrucciones, una solucin funcional a muchos problemas. Muchos algoritmos recursivos resultan eficientes, pero no todos: hay algunos fcilmente formulables, pero muy ineficientes. En estos casos, dichos algoritmos pueden servir como una primera aproximacin al algoritmo definitivo, pero debe mejorar su rendimiento para que sea prctico. Veremos dos parmetros para la mejora de eficiencia de algoritmos recursivos: el uso de parmetros acumuladores y el uso de tablas. Cada una se ilustra con un ejemplo distinto. Parmetros Acumuladores Veamos primero una solucin ineficiente que intentaremos mejorar. Ejemplo: Nmeros de Fibonacci Los nmeros de fibonacci suele especificarse como: Fib(0)=1 Fib(1)1 Fib(n+2)=fib(n)+fib(n+1) Esta especificacin de los nmeros de fibonacci tienen una formulacin recursiva inmediata en estilo funcional. Un modo de evitar problema lo proporciona la tcnica de los parmetros acumuladores, cuya idea bsica se expone a continuacin. La funcin principal usa una funcin auxiliar que tiene los parmetros de aquellas ms algunos adicionales. La funcin principal simplemente realiza una llamada a esta funcin auxiliar en los que los parmetros de aquellas se modifican y los parmetros nuevos toman un valor inicial adecuado . Los parmetros adicionales tienen como misin ir acumulando resultados principales durante el proceso recursivo.

Tabulacion No todos los algoritmos recursivos ineficientes pueden optimizarse con la tcnica de los parmetros acumuladores. Otra tcnica til es el uso de tablas. La intencin es que la primera vez que se realiza un clculo, se almacena en una tabla, donde puede consultarse otras veces que se necesite. Esta tcnica tambin se suele emplear con la programacin dinmica. Ejemplo: Sea el problema de la competicin. Hay dos participantes (deportistas o equipos, no importa que), A,B, que juegan una competicin que es ganada por el primero que venza en n partidos, siendo ( n ) mayor que( 0 ). Por sencillez , se supone que ambos participantes tienen cualidades y preparacin similar . De forma que cada uno tiene un 50% de posibilidades de ganar cada partido. De todas formas, la modificacin para incorporar probabilidades diferentes es evidente y no complica el problema. Divide y vencers: Consiste en descomponer un problema en un subproblema, resolver independientemente los subproblemas para luego combinar sus soluciones y obtener la solucin del problema original. Esta tcnica se puede aplicar con xito a problemas como la multiplicacin de matrices, la ordenacin de vectores, la bsqueda en estructuras ordenadas,etc. Ejemplo. Bsqueda de una palabra en un diccionario Como ejemplo sencillo de aplicacin de esta estrategia puede considerarse la bsqueda de una palabra en un diccionariode acuerdo con el siguiente criterio. Se abre el diccionario por la pagina centrar(quedando dividido en dos mitades) y se comprueba si la palabra aparece all o si es lxico grficamente anterior o posterior. Si no ha encontrado y es anterior se procede a buscarla en la primera mitad., si es posterior, se buscara en la segunda mitad. El procedimiento se repite sucesivamente hasta encontrar la palabra o decidir que no aparece. Mtodo voraz: Este mtodo trata de producir tipo de mejor resultado a partir de conjunto de opciones candidatas .Para ello, se va procedimiento paso a paso realizndose la mejor eleccin (usando una funcin objetivo que respeta un conjunto de restricciones ) de entre las posibles. Puede emplearse en problemas de optimizacin, como el conocido de la mochila, en la bsqueda de caminos mnimos sobre grafos, la planificacin en el orden de la ejecucin de unos programas en un computador,etc. Ejemplo. Dar un cambioutilizando el menor nmero de monedas Considrese ahora el problema de la devolucin del cambio al realizar una compra (por ejemplo, en una maquina expendedora de tabaco). Suponiendo que se disponga de cantidad suficiente de ciertos tipos diferentes de monedas de curso legal, se trata de dar como cambio la menor cantidad posible usando estos tipos de monedas. La estrategia voraz aplicada comienza devolviendo, cuando se pueda, la moneda de mayor valor ( es decir, mientras el valor de dicha moneda sea mayor o igual al cambio que resta por dar), continua aplicndose el mismo criterio para la segunda moneda mas valiosa, y as sucesivamente. El proceso finaliza cuando se ha devuelto todo el cambio. Consideraciones y Criterios para Disear Algoritmos Algunas consideraciones estilsticas pueden contribuir a mejor la calidadde los algoritmos (y programas ) mediante la reduccin del numero de errores que aparecen al desarrollar los.

Tambin influyen haciendo que nuestro algoritmo resulten ms fciles de leer y entender para otras personas. Los criterios de estilo pueden reflejarse en un conjunto de normas de estilo de codificacin. Ello asegura que tanto algoritmos como programa resulten legibles y puedan modificarse fcilmente en caso de necesidad. Generalmente, estas normas de estilo se dirigen hacia aspectos como la forma de construir los nombres de variables o tipo de datos que aparezcan., la tipografa seguida ala hora de escribir nombres de variables, subprogramas, palabras claves, etc. El modo de encolumnar las distintas partes de un algoritmo para facilitar su lectura y comprensin, y la normas sobre como y donde deben de introducirse los comentarios. Estilo y calidad de los programas van fuertemente unidos. Ante la pregunta Cules son las caracterstica de un buen algoritmo?, las siguientes respuestas reflejan, cierta medida, los factores que identifican la calidad en ellos . 1. Correccin, el algoritmo debe funcionar. 2. Nunca se debe olvidar que la caracterstica ms simple e importante de un algoritmo es que funcione. Pude aparecer obvio, pero resulta difcil de asegurar en algoritmos complejos. 3. Eficiencia, el algoritmo no debe desaprovechar recursos. La eficiencia de un algoritmo se mide por los recursos que este consume. En particular, se habla de la memoria y del tiempo de ejecucin . A pesar de que con la reduccin de los costes del hardware es posible disear computadores ms rpidos y con ms memoria, no hay que desperdiciar estos recursos y tratar de desarrollar algoritmos ms eficientes. 4. Claridad, el algoritmo debe estar bien documentacin. La documentacin ayuda a comprender el funcionamiento de los algoritmos. Ciertos detalles o algunas partes especiales de los mismos pueden olvidarse fcilmente o quedar oscura si no estn adecuadamente comentadas. En realidad, y de acuerdo con los puntos de vista anteriores, la calidad de un algoritmo tiene muchas facetas y todas ellas importantes. Resumiendo, lo ideal es que nuestro algoritmo resulte correcto, eficiente, claro, fiable y fcil de mantener. Algoritmos voraces Esquema voraz Hay muchos problemas en los que se pretende obtener un subconjunto de n elementos que satisfaga ciertas restricciones y que optimice alguna medida. Se supone que un problema de esta clasetiene al menos una solucin. Puede haber varias soluciones optimas, en cuyo caso no importa cual se elija. Por ejemplo, sea el problema de encontrar un subconjunto de los arcos de un grafo. Otro ejemplo se da cuando, dados unos ficheros almacenados en una cinta de que el tiempo de recuperacin de un fichero cualquiera sea el mnimo en promedio. A menudo, el problema incluye restricciones adicionales que limitan el nmero posible de soluciones. Normalmente, estos problemas no se intentan resolver "de golpe ", encontrando de una sola vez la solucin completa y ptima. Es ms frecuente que el subconjunto de la solucin se vaya formando paso a paso, analizando durante cada etapa que elemento conviene aadir a la solucin parcial ya existente. La dificultad principal para resolver esta clase de problemas estriba en el anlisis necesario para poder formular un algoritmo que halle la solucin en varios pasos. Un algoritmo voraz sigue el esquema anterior, pero con la fortuna de que cada vez que aade un elemento a la solucin se tiene la certeza de haber realizado la mejor eleccin posible. Esta caracterstica hace que aunque el anlisis del problema sea arduo, la solucin voraz siempre

resulte sencilla. La nica complicacin es comprobar que se siguen satisfaciendo las restricciones del problema. Por lo que se ha descrito del esquema voraz, ste es un proceso repetitivo sencillo que trata sucesivamente los diferentes elementos del problema. Para facilitar la descripcin de este proceso, puede llamarse candidato al elemento tratado en cada paso. Inicialmente, el conjunto de candidatos que forman la solucin est vaco. En cada paso se intenta aadir el mejor de los candidatos restantes a dicha solucin parcial. Si este conjunto ampliado sigue siendo vlido, es decir, si satisface las restricciones del problema y, por tanto, permite formar una solucin del problema, el candidato se incorpora definitivamente. Al contrario, si dicho conjunto no es vlido, se desecha el candidato. Si el algoritmo voraz se ha diseado correctamente, la primera solucin encontrada es ptima. Por tanto, la dificultad principal al disear un algoritmo voraz reside en encontrar un criterio en encontrar un criterio de seleccin que garantice la optimalidad de la solucin. Segn esta descripcin, el problema parte de:
y y

Una funcin objetivo que da el valor de una solucin. Obviamente, sta es la funcin por optimizar. Un conjunto de restricciones sobre el valor de los datos de entrada y sobre la solucin final del problema.

A su vez, la solucin consta de:


y y y

Un conjunto de candidatos Una funcin de seleccin que en cada momento determine que candidato de los an no usados parece ser el mejor. Una funcin que determine si cierto conjunto de candidatos es vlido; es decir, si permite formar alguna solucin del problema.

Obsrvese que las funciones de validez y completitud no se preocupan de la optimalidad del la solucin, pero si la funcin de seleccin es la adecuada, cada solucin vlida y completa es optima. Podemos representar el esquema voraz de la siguiente forma funcional: FUNCTION Voraz ( candidatos: ( 1..n ) : ( 1..n) -> FUNCTION VorazAcumulador ( candidatos : (1..n), Solucin : (1..n) : (1..n) -> Cadidatos = ( ) v EsSolucin ( solucin)-> Value siguiente -> seleccionar ( candidatos ) IN EsVlida (solucin v ( siguiente)) => VorazAcumulador (candidatos (solucin), solucin v (siguiente)) VorazAcumulador (candidatos (siguiente), solucin) VorazAcumulador (candidatos, ( ) ) Puede verse por qu estos algoritmos se llaman " voraces " : en cada paso toman el mejor trozo de la solucin; es decir, el mejor candidato. Adems, nunca cambian de opinin: una vez que un candidato es aceptado o rechazado en la solucin, la decisin, es definitiva. La funcin objetivo no suele aparecer en el algoritmo final, sino que se utiliza durante el anlisis del problema y es determinante en la eleccin de la funcin de seleccin. De todas formas, debe recordarse que puede haber varios criterios alternativos de seleccin y que de su

correcta eleccin depende que la solucin calculada por el algoritmo sea optima. Como ejercicio, el lector puede intentar encontrar una solucin voraz del problema del calendario. Es fcil encontrar una solucin si en cada etapa se genera el subcalendario correspondiente a un equipo; es decir, la tabla de competicin se va completando por filas. Como fila primera se toma la secuencia de los ndices de los participantes en cualquier orden. Cada fila resultante puede tener una complejidad de o (n2). Adems, este algoritmo tiene la ventaja de valer para las situaciones en que el nmero de participantes no es una potencia de dos. Desglose en monedas Como primer ejemplo introductorio sencillo al que puede aplicarse la tcnica voraz, se considera el problema de un cambio o desglose en monedas. Hay que desglosar una cantidad en un conjunto de monedas tratando de cumplir alguna condicin; en este caso, utilizar el menor nmero de monedas. Para ello, se parte de un conjunto de tipos de monedas vlidas, de las que se supone que hay cantidad suficiente para realizar el desglose, y de un importe. Se trata de indicar la cantidad (menor) de monedas de los tipos considerados, tales que sumados sus valores equivalgan al importe. Para simplificar, suponemos que manejamos dineroespaol y, en particular, podemos utilizar slo monedas de 500, 100, 50, 25, 5 y 1 pesetas para el desglose. Estos valores se definen por medio de un tipo enumerado MONEDAS. Asimismo, se declaran los tipos VALORES y CANTIDADES para representar el valor asignado a cada unidad monetaria y la cantidad de cada tipo de moneda que se devolver en el desglose. Su declaracin es la siguiente: TYPE Monedas -> M500 I M100 I M50 I M25 I M5 I M1, Valores -> Integer M500 M1 Cantidades -> Integer M500 .M1 Se supone inicialmente asignados los valores a cada uno de los tipos de monedas. Los elementos de la tcnica voraz estn presentes en este problema de la siguiente forma:
y y y y y

El conjunto de candidatos est constituido por cada una de las monedas de los diferentes tipos que se pueden usar para realizar el desglose del importe dado. Una solucin viene dad por un conjunto de monedas devuelto tras el desglose, y cuyo valor total es igual al importe a desglosar. La condicin de factibilidad de la solucin siendo construida establece en el desglose debe ser menor o igual que el importe a desglosar. La funcin de seleccin establece que hay que elegir, mientras sea posible, la moneda de mayor valor de entre las candidatas. La funcin objetivo cosiste en minimizar la cantidad total de monedas utilizadas en el desglose.

Con esta informacin se puede comprobar que en este problema estn presentes los distintos elementos de la tcnica voraz. Adems, cuando un candidato (moneda) se incorpora al conjunto solucin, ste no ser nunca excluido de l. Divide Y Vencers La tcnica divide y vencers consiste en descomponer el problema en un conjunto de subproblemas ms pequeos. Despus se resuelven estos subproblemas y se combinan las soluciones para obtener la solucin para el problema original.

Esquema de Divide y vencers. La tcnica de divide y vencers es quizs una de las utilizadas debido a su sencillez: si un problema es demasiado grande para resolverlo de una vez, se descompone en varias partes ms fciles de resolver. Mas formalmente, dado un problema al resolver planteando en trminos de una entrada de tamao n, la tcnica de divide y vencers parte la entrada en k subproblemas, 1<k<=n. Estos subproblemas se resuelven independientemente y despus se combinan sus soluciones parciales para obtener la solucin del problema original. Este esquema de particin de problemas se denomina esquema de divide y vencers solo en el caso en que los problemas sean de la misma clase del problema original. Esta restriccin permite una formulacin y resolucin recursiva de los subproblemas. Por supuesto, deben existir algunos pasos sencillos cuya solucin pueda calcularse fcil y directamente; en caso contrario, el proceso recursivo nunca terminara. El caso ms frecuente es cuando el nmero de subproblemas es dos. Veamos el esquema de divide y vencers para dos subproblemas; es fcil su generalizacin a k subproblemas 2<k<=n. Su formacin funcional es como sigue, considerado el problema como de tipo dato y la solucin, de tipo resultado: TYPEVAR Dato, resultado FUNCTION DivideYVenceras (problema : dato) : resultado -> EsPequeo (problema) }=> ResolverDirectamente (problema) | VALUE subproblemas -> Partir (problema) IN subproblemas == (subproblema1, subproblema2) => Combinar (DivideYVenceras (subproblema1) , DivideYVenceras (subproblema2)) Se puede hacer una formulacin imperativa similar. Sin embargo, escribiremos una formulacin ms restrictiva pero bastante usual, en la que se utiliza un vector de tamao N. TYPEVAR dato, resultado PROCEDURE DivideYVenceras (IN problema : dato1..n, OUT solucin : resultado) -> PROCEDURE DyVAux (IN problema : dato1..n, IN inferior, superior : 1..N, OUT solucin : resultado) -> VAR medio: 1..N subsolucion1, subsolucion2 : resultado IF EsPequeo (inferior, superior) THEN ResolverDirectamente (problema, inferior, superior, olucin) ELSE Medio := Partir (inferior, superior); DyVAux (problema, inferior, medio, subsolucion1); DyVAux (problema, medio+1, superior, subsolucion2); Combinar (subsolucion1, subsolucion2, solucin) DyVAux (problema, 1, N, solucin)

El esquema general se adapta a un problema concreto al sustituir los metasimbolos EsPequeo, ResolverDirectamente, Partir y Combinar por funciones o procedimientos concretos. Si el tamao de los dos subproblemas es el mismo (o casi), el tiempo de cmputo de la funcin DivideYVecneras se describe con la siguiente relacin de recurrencia: g(n),si n es pequeo T(n) = 2 T(n/2) + f(n), en caso contrario donde T(n) es la funcin de tiempo de DivideYVenceras para entradas de tamao n, g(n) es el tiempo que tarda la funcin ResolverDirectamente en resolver problemas de pequeo tamao (normalmente una constante) y f(n) es el tiempo necesario para partir el problema y combinar las subsoluciones. La eficiencia final del algoritmo depende de la funcin f(n) concreta que aparezca durante el anlisis. Ntese que, es general, para que esta tcnica resulte eficiente todos los subproblemas deben ser de tamao parecido. Elaboracin de un Calendario Deportivo: Sea un campeonato deportivo; para nuestros propsitos resulta indiferente el deporteobjeto de la competicin, as que hablaremos de participantes en vez de deportistas o equipos. El problema consiste en elaborar un calendario de competicin de forma que cada participante compita exactamente una vez con cada uno de los dems participantes. Por concrecin, y sin perdida de generalidad, puede suponerse que las competiciones se celebran en das sucesivos y que cada participante compite una vez por da. Para simplificar el problema, se supone que el numero de participantes es una potencia de dos; es decir, hay n = 2k participantes para algn entero positivo k. Se supone tambin que cada participante tiene asignado un nmero comprendido entre 1 y N. Se necesitan elaborar n-1 competiciones por participantes. Por tanto, la solucin del problema puede representarse en una tabla de dimensin nx(n-1). El elemento (i,j)esimo de la tabla, 1<= i<=n, 1<=j<n, contiene el numero del participante contra el que el participante i-esimo compite el da j-esimo. Obsrvese que los nmeros de participantes incluidos en la fila i de la tabla son distintos porque el participante i-esimo solo debe competir una vez con cada participante restante. A su vez, la columna j tambin contiene nmeros distintos, porque el da j-esimo cada participante solo puede competir con otro participante. Se dispone de una solucin inmediata aplicando fuerza bruta. Primero se obtiene para cada participante i, 1<=i<=n, el conjunto P(i) de todas las permutaciones posibles del resto de los participantes con los que debe competir, es decir, el conjunto de permutaciones de los nmeros {1..n}-{i} ahora se completan las filas de la tabla de todas las formas posibles, incluyendo en cada fila i algn ejemplo de P(i). Solo sirve como solucin aquellas combinaciones de fila que cumplan las restricciones enunciadas en el prrafoanterior sobre las columnas de la tabla (las restricciones sobre las filas estn garantizadas por el modo de generar los conjuntos P(i)). Si hay varios calendarios validos, se elige uno cualquiera. El mtodo de fuerza bruta resulta sencillo, pero es terriblemente ineficiente. Cada conjunto P(i) consta de (n-1)! Elementos. Dado que el numero de participantes de n, resultan nx(n-1)!=n! formas de rellenar la tabla. Sin embargo la aplicacin de la tcnica de divide y vencers produce una solucin mas sencillas aun pero muy eficientes. La siguiente figura describe visualmente parte de la elaboracin de la tabla.

das

1 participantes 1 2 2 1

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

1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 2 1 4 3 8 5 6 7 3 4 1 2 7 8 5 6 4 3 2 1 6 7 8 5 5 6 7 8 1 2 3 4 6 5 8 7 4 1 2 3 7 8 5 6 3 4 1 2 8 7 6 5 2 3 4 1

Se distinguen dos casos. El caso bsico se da cuando solo hay dos participantes. La solucin es directa porque se celebra una sola competicin entre ambos. El caso recursivo, cuando hay ms de dos participantes, es ms complejo. Si el numero de participantes es 2k , para k>1, puede decirse que el "tamao" del problema es 2k (sabemos que el calendario tendr un tamao de 2k x(2k-1 -1) posiciones). El problema puede reducirse a dos sub problemas de tamao 2k-1 si se elaboran independientemente dos subcalendarios de tamao 2k x(2k-1 -1): uno para los participantes, de numeracin comprendida entre 1 y 2k-1 y otro para los participantes comprendidos entre 2k-1 +1 y 2k . Sin embargo, la unin de estos subcalendarios no forma un calendario completo para el campeonato de 2k participantes, ya que a unin de los dos calendarios tiene un tamao 2k x(2k-1 -1), faltando 2k x2k-1 celdas para completar el calendario total. En efecto, faltan por elaborar las competiciones cruzadas entre los participantes de numeracin inferior y los de numeracin superior. Por fortuna, el resto del calendario se puede construir fcilmente. Completemos primero la parte de los participantes de numeracin inferior. El subcalendario del primer participante es sencillo porque basta con que compita en das sucesivos con los participantes de numeracin, superior en orden creciente de numeracin; es decir, sucesivamente con los participantes 2k-1 +1, .,2n . El siguiente participante toma esta secuencia y realiza una fcil permutacin de la misma que le garantiza el respeto de las restricciones de la solucin; por ejemplo, rotando dicha secuencia a la derecha. Este proceso se repite para el resto de los participantes de numeracin inferior. El calendario de los participantes de numeracin superior se completa de forma similar con los nmeros de los participantes de numeracin inferior. El algoritmo descrito se expresa a continuacin. PROCEDURE Calendario ( INOUT tabla : (1..N)1..N,1..N-1) -> PROCEDURE FormaTabla (IN inf : 1..N, IN sup :1..N, OUT tabla : (1..N) 1..N,1..N-1) -> VAR

medio : 1..N IF inf = sup-1 THEN tablainf.1 : = sup; tablasup.1 := inf ELSE medio := (inf + sup) Div 2; FormarTabla (inf, medio, tabla); FormarTabla (medio+1, sup, tabla); CompletarTabla (inf, medio, medio,sup-1, medio+1, tabla); CompletarTabla (medio+1, sup, medio, sup-1, inf, tabla) Este sistema de ecuacionesdefina una funcin de tiempo del orden de O(n2), que es mucho mas eficiente que la solucin de fuerza bruta. Veamos otra estrategia, tambin de orden de complejidad cuadrtica, donde se aplica divide y vencers para resolver el problema y que se aprovecha de la simetra de la solucin. La idea consiste en aadir inicialmente a la tabla una columna "ficticia" de ndice j=0, que almacena los ndices de las filas. Despus se genera, mediante divide y vencers, la mitad izquierda de la tabla. Finalmente se completa la mitad derecha de la tabla (correspondiente al cruce de los dos grupos de equipos cuyos subcalendarios se han generado por divide y vencers). En esta ltima etapa, los valores de las casillas (k,l), siendo 1<=k<=n y 0<=l<=(n/2)-1, de acuerdo con las siguientes expresiones de los ndices: i = (k + n/2) Mod (n+1) j = (1 + n/2) Mod n De esta forma se rellenan las casillas aun vacas, es decir, los componentes tablai,j a partir de las casillas tablak,l ya completadas. Ordenacin de un Vector por Mezcla: La ordenacin de un vector es un problema que se presta fcilmente a la aplicacin de la tcnica de divide y vencers. El caso bsico corresponde a un subvector de un solo elemento, que obviamente ya esta ordenado. Para el caso general, sea vi..s un vector de ndice inferior i e ndice superior s. La particin puede hacerse por la mitad si se toma un ndice m=[(i+s)/2] y dos subvectores vi..m y vm+1..s . la combinacin de los dos subvectores ya ordenados es fcil. basta con mezclar los dos subvectores, mediante comparaciones de sus elementos sucesivos, para obtener un nico vector ordenado. Este proceso de mezcla es realizado por un procedimiento auxiliar. El algoritmo resultante es: PROCEDURE Ordenar (INOUT v : INTEGER1..N) -> (* ordenacin por mezcla *) PROCEDURE OrdenarAux (INOUT Vector : INTEGER1..N,1..N, IN inf, sup : 1..N) -> VAR Medio : 1..N IF inf < sup THEN medio := (inf+sup) Div 2; OrdenarAux (vector, inf, medio); OrdenarAux (vector, medio+1, sup); Mezclar (vector, inf, medio, sup) OrdenarAux (v, 1, N)

El procedimiento para realizar la mezcla de los subvectores ordenados es: PROCEDURE Mezclar ( IN inf : INTEGER, IN medio: INTEGER, IN sup : INTEGER, INOUT vector : INTEGER1..N) -> VAR vectorAux : INTEGER1..N, i1, i2, j : INTEGER, ndice : INTEGER i1 := inf; i2 := medio + 1; j := inf; WHILE (i1<=medio) ^ (i2<=sup) DO IF vectori1 << vectori2 THEN vectorAuxj :=vectori1; i1 :=i1 + 1 ELSE vectorAuxj ;= vectori2; i2 := i2 + 1 j := j + FOR ndice IN i1..medio DO vectorAuxj := vectorindice; J := j + 1 FOR ndice IN i2..sup DO vectorAuxj := vectorindice ; J := j + 1 FOR ndice In inf..sup DO vectorindice := vectorAuxindice El algoritmo resultante es sencillo conceptualmente. Es fcil analizar la complejidad del algoritmo para un vector de longitud n. La operacin de mezcla es proporcional a n, de forma que las ecuaciones de recurrencia de la funcin de tiempo son: T(n) = a, n=1, a=cte 2T(n/2) + bn, n>1, b=cte Si n es una potencia de 2; es decir, n =2k para algn k, las ecuaciones anteriores se resuelven por sustituciones sucesivas, resultando: T(n) = 2T(n/2) + bn= =2K T(n/2K) + kbn = an + bn log2 n El algoritmo de ordenacin por mezcla es ptimo en tiempo de ejecucin. Los nicos inconvenientes que presenta es que el procedimiento de mezcla necesita gran capacidad de almacenamiento (para dos copias del vector) y que, adems de mezclar, necesita copiar el vector auxiliar completo en el principal. Puede disearse un algoritmo de mezcla ms complejo que mejore ambos aspectos, pero mantenga la complejidad asinttica calculada. Multiplicacin de Matrices: Sean dos matrices, A y B, de dimensin nxn. La matriz productoC=AxB tambin es una matriz de nxn cuyo elemento (i,j)-esimo se forma multiplicando cada elemento de la final i-esima de A por el elemento correspondiente de la columna j-esima de B y sumando los productos

parciales. El clculo de cada elemento Cij requiere n multiplicaciones. La matriz C tiene n2 elementos, as que el tiempo total del algoritmo de multiplicacin es de orden O(n3). El algoritmo anterior, que podemos llamar algoritmo convencional de multiplicacin de matrices, proviene directamente de la definicin matemtica del producto de matrices. Sin embargo, la tcnica de divide y vencers sugiere un algoritmo distinto. Supongamos, por sencillez, que n es una potencia de dos; es decir, que existe un entero no negativo k tal que n=2k. (Si n no es un potencia de dos, pueden aadirse las filas y columnas de ceros necesarias para formar una dimensin que sea potencia de dos.) las submatrices A y B pueden partirse en cuatro submatrices de dimensin (n/2)x(n/2). Si el producto AxB tiene la forma: A11 A12 B11 B12 C11 C12 A21 A22 B21 B22 C21 C22 Entonces: C11 = A11*B11 + A12*B21 C12 = A11*B12 + A12*B22 C21 = A21*B11 + A22*B21 C22 = A21*B12 + A22*B22 Para n=2, los elementos Cij se calculan mediante algunas multiplicaciones y sumas de nmeros, pero para n>2 las submatrices Cij se calculan mediante multiplicaciones (recursivas) y sumas de submatrices de dimensin (n/2)x(n/2). Dos submatrices de (n/2)x(n/2) pueden sumarse en un tiempo bn2, siendo b alguna constante. La resolucin de este sistema de ecuaciones nos dice que O(T(n))=OT(n3), de forma que no se ha conseguido ningn ahorro sustancial de tiempo. Sin embargo, interesa encontrar algoritmos mas eficientes, porque la multiplicacin esta relacionada con otras operaciones sobre matrices mas usuales, como inversin de una matriz o hallar su determinante. La existencia de un algoritmo eficiente para la multiplicacin (en realidad, para cualquier operacin de las anteriores) significara la existencia de un algoritmo similar para las dems. Podra conseguirse mas eficiencia si logrramos realizar menos multiplicaciones de matrices, aunque fuera a costa de un mayor numero de sumas de matrices, dado que la complejidad respectiva de estas operaciones es O(n3)n y o(n2). El algoritmo de Strassen calcula las cuatro submatrices Cij empleando 7 multiplicaciones y 18 sumas o restas de matrices. Programacin Dinmica Principios de programacin dinmica Se ha visto que la tcnica voraz se aplica a problemas cuya solucin puede formularse como el resultado de una secuencia de decisiones. El mtodo es eficiente porque una vez que se toma una decisin en un paso, no se reconsidera en el futuro, conduciendo de forma directa a la solucin. Sin embargo, no todos los problemas pueden resolverse de esta manera, asegurando que la secuencia de decisiones es la mejor de las posibles. La programacin dinmica (tambin llamada planificacin dinmica) es una tcnica de programacin que tambin permite resolver problemas mediante una secuencia de decisiones, pero de una manera menos directa que en el caso voraz. Esta vez se necesita producir varias secuencias de decisiones. Solamente al final se sabe cul es la mejor de todas. No es fcil establecer una definicin de la programacin dinmica; una caracterstica es que el programa "aprende "dinmicamente de las decisiones que toma. Adems, todo problema resoluble con esta tcnica debe de satisfacer el principio de optimalidad. Este principio establece que "una secuencia ptima de decisiones que resuelve un problema debe cumplir la

propiedad de que cualquier subsecuencia de decisiones tambin debe ser ptima respecto al subproblema que resuelva ". Usando una tcnica de fuerza bruta, el nmero de secuencias de decisin es exponencial sobre el nmero de decisiones, porque si hay d opciones para cada una de las n decisiones, resultar un total de d secuencias posibles de decisin. En la programacin dinmica todos los subproblemas se resuelven de acuerdo con criterio de tamao creciente y los resultados de subproblemas ms pequeos se almacenan en algn tipo de estructura de datos (normalmente tablas) para facilitar la solucin de los problemas ms grandes. De esta forma se reduce al nmero total de subsecuencias generadas, evitndose una explosin combinatoria en la produccin de las secuencias y consiguindose soluciones ms eficientes en cuanto a tiempo de ejecucin. Podemos formalizar algo ms la idea bsica. Supongamos que tenemos un problema que satisface el principio de optimalidad, tal que Eo es el estado inicial del problema y deben tomarse n decisiones d, 1<i<n. Sea D = { v1 ..vn} el conjunto de valores de decisin posibles para la decisin d1. sea, asimismo, Eli el estado del problema tras la eleccin del valor vli 1<i<n1 y Sli una secuencia ptima de decisiones respecto al estao Eli. Entonces, una secuencia ptima de decisiones respecto a E0 es la mejor secuencias de decisin { Vli Sli }, 1<i<N1. El razonamiento anterior se refiere a la primera decisin d1 tomada desde el estado inicial E0 sin embargo, puede generalizarse la formulacin del problema a cualquier subsecuencia de decisiones dk ..,dl, 1<k<n, partiendo como estado inicial de Ek-1. si este subproblema de simboliza como problema (k,l), entonces el problema completo es problema ( l,n ). Tiene sentido centrarse en un subproblema del problema inicial porque ste satisface el principio de optimalidad pero, adems, tiene la ventaja ( quizs paradjica al tratar de un problema ms pequeo ) de que proporciona una visin ms general del problema en cuestin. ( Obsrvese que vamos a usar la tcnica de resolucin de problemas por generalizacin para despus poder realizar una particularizacin de la solucin obtenida.) Una solucin dinmica para problema ( k,1 ) debe expresarse en trminos de los valores de decisin existente para decisiones d1 y el subproblema problema ( k+1,1 ) resultante de aplicar cada valor de decisin. La expresin inicial de la ecuacin de recurrencia, hay un caso en que la decisin d1 no va seguida por ninguna secuencia de decisiones, que es problema ( n,n ). En resumen, la aplicacin de la tcnica de programacin dinmica a un problema significa comprobar primero el principio de optimalidad y desarrollar despus unas ecuaciones recurrentes del estilo de (1) y (2). La ecuacin general relaciona la secuencia ptima en una etapa i con la decisin tomada en la etapa i y la subsecuencia ptima en la etapa posterior i+1. la ecuacin de base establece el valor para la etapa n+1 en que no queda ninguna decisin Xi, 1<i<n, a tomar. La ecuacin de recurrencia puede formularse de dos formas: delantera o trasera. Sea X1 ..Xn la secuencia de decisiones necesaria para resolver el problema. La formulacin delantera expresa la decisin de Xl , 1<i<n, a partir de la secuencia de decisiones Xi+1 Xn ( es la clase de formulacin adoptada hasta ahora ). La formulacin trasera expresa la decisin de Xi, 1<i<n , a partir de la recurrentes con formulacin trasera es igual que e la formulacin delantera, slo que en orden contrario. La eleccin de una formulacin delantera o trasera depende del problema considerado o, sencillamente, del gusto del programador. Algoritmos De Vuelta Atrs Existen un alto nmero de problemas que pueden formularse como la bsqueda de la mejor solucin o del conjunto de todas las soluciones que satisfacen ciertas condiciones. Adems,

cada solucin es el resultado de una secuencia de decisiones. Por supuesto, debe existir una funcin de criterios que debe ser satisfecha por cada secuencia solucin u optimizada por dichas secuencias solucin si solo queremos la mejor. En algunos problemas de optimizacin se conoce un criterio ptimo de seleccin que puede usarse de forma voraz. Otros problemas satisfacen el principio de optimalidad, pudindose aplicar la tcnica de programacin dinmica. Sin embargo, todava hay otros problemas peores que no queda mas remedio que realizar una bsqueda de la solucin. Esquema de Algoritmos de Vuelta Atrs: Sea (x1,...,xi) el camino desde la raz hasta un nodo de un rbol del espacio de estado. Sea G(x1...xi) el conjunto de todos los valores posibles de xi+1 tales que (x1,...,xi+1) es un camino hasta el estado del problema. Supongamos que existe algn predicado acotador A tal que A(x1,...,xi+1) es falso si el camino (xi,...,xi+1) no puede extenderse para alcanzar un nodo de respuesta. Por lo tanto, los candidatos para la posicin i+1 del vector desolucion x1..n son aquellos valores generados por G que satisfacen A. Supongamos que tambin existe algn predicado R que determina si un camino (x1,...,xi+1) termina en un nodo de respuesta. El Algoritmo de Vuelta Atrs se especifica de la forma siguiente: PROCEDURE Retroceso (IN k : INTEGER, INOUT solucion : elemento1...n) -> VAR nodo : elemento FOR noso IN G(solucion, 1, k-1) DO Solucion k := nodo; IF R(solucion, 1, k) THEN IF R(solucion, 1,k) THEN << guardar solucion >>; Retroceso (k+1, solucion) La llamada inicial del algoritmo es Retroceso(1, solucion). El procedimiento no hace ninguna llamada recursiva cuando k = N+1 o cuando ningn nodo generado por G satisface el elemento posible que satisfacen A se aade una solucin particular, se comprueba si se ha encontrado una solucion. Despus simplemente se llama recursivamente al algoritmo para generar los estados descendientes. Se sale del bucle FOR cuando no quedan mas valores para solucin terminando la llamada actual al algoritmo. Ramificacin (Bifurcacion) Y Acotacin Los mtodos de Ramificacin y Acotacin constituyen un a variante de las tcnicas de retroceso para problemas donde se trata de encontrar el valor mximo o mnimo de cierta funcin objeto (esto suele suceder en los problemas de programacin lineal entera). La tcnica de ramificacin y acotacotacion aplica de la siguiente manera: Supngase que al recorrer un rbol y alcanza una hoja se tiene una solucion con k colores, y que al seguir avanzando en el rbol (mediante la aplicacin de varios pasos de retrocesos) se alcanza un nodo que requiere k+1 colores. En este punto podemos retroceder (y no seguir avanzando por mas ramas), pues tenemos ya una solucion mayor. As, k sirve de cota inferior al retroceso. Este mismo proceso se repite en el resto de nodos del rbol, evitando as la exploracin de gran parte de al estructura. Algoritmos Heuristicos Existen muchos problemas para los cuales no se conocen algoritmos que puedan encontrar la solucin de forma eficiente: problemas NP-completos.

La solucin exacta puede requerir un orden factorial o exponencial: el problema de la explosin combinatoria. Se hace necesario utilizar algoritmos heursticos: Un algoritmo heurstico (o simplemente heurstica) puede producir una buena solucin (puede que la ptima) pero tambin puede que no produzca ninguna solucin o dar una solucin no muy buena. Normalmente, se basa en un conocimiento intuitivo del programador sobre un determinado problema. La estructura de algoritmo voraz se puede utilizar para construir procedimientos heursticos: hablamos de heursticas voraces. Objetivo: obtener buenas soluciones en un tiempo de ejecucin corto. El problema del viajante Problema: Dado un grafo no dirigido, completo y ponderado G = (V, A), encontrar un ciclo simple de costo mnimo que pase por todos los nodos. Es un problema NP, pero necesitamos una solucin eficiente. Problema de optimizacin, donde la solucin est formada por un grupo de elementos en cierto orden: podemos aplicar el esquema voraz. Posibilidades: 1. Los nodos son los candidatos. Empezar en un nodo cualquiera. En cada paso moverse al nodo no visitado ms prximo al ltimo nodo seleccionado. 2. Las aristas son los candidatos. Hacer igual que en el algoritmo de Kruskal, pero garantizando que se forme un ciclo. Heurstica voraz 1 Una solucin ser un cierto orden en el conjunto de nodos (c1, c2, ..., cn), el orden de visita de los nodos. Inicializacin: seleccionar un nodo cualquiera. Funcin de seleccin: de los nodos candidatos seleccionar el ms prximo al ltimo (o al primero) de la secuencia actual (c1, c2, ..., ca). Acabamos cuando tengamos n nodos. Ejemplo. Empezando en el nodo 1. Solucin: (1, 4, 5, 3, 2) Coste: 30+15+25+10+45=125 Empezando en el nodo 3. Solucin: (5, 4, 3, 2, 1) Coste: 15+20+10+45+50=140 Heurstica voraz 2 Una solucin ser un conjunto de aristas (a1, a2, ..., an-1) que formen un ciclo hamiltoniano, sin importar el orden. Empezar con un grafo sin aristas. Seleccin: seleccionar la arista candidata de menor coste. Factible: una arista se puede aadir a la solucin actual si no se forma un ciclo (excepto para la ltima arista aadida) y si los nodos unidos no tienen grado mayor que 2. Ejemplo. Solucin: ((2, 3), (4, 5), (3, 4), (1, 2), (1, 5)) Coste = 10+15+20+45+50 = 140

Conclusiones: Ninguno de los dos algoritmos garantiza una solucin ptima. Sin embargo, normalmente ambos dan soluciones buenas, prximas a la ptima. Posibles mejoras: buscar heursticas mejores; repetir la heurstica 1 con varios orgenes; bien, a partir de la solucin del algoritmo intentar hacer modificaciones locales para mejorar esa solucin. Algoritmos De Aproximacin Dado un problema NP completo, es probable que no sepamos resolverlo de manera precisa y completa utilizando un algoritmo polimico en tiempo. Para este tipo de problemas, los algoritmos que no conducen a una solucin ptima se llaman algoritmos de aproximacin. Sin embargo, resulta parcialmente interesante que estos garanticen una cota en el margen de imprecisin. A continuacin se ilustra este tipo de tratamiento de problemas al problema de recubrimiento de un grafico: Dado un grafo G=(V,A), se trata de encontrar un conjunto con el menor numero de vrtices tal que toda arista sea incidente por lo menos de un vrtice de V. Este problema se puede resolver a travs de otro aproximado, como es calcular el ajuste maximizal del grafo G. Se trata de calcular un subconjunto A de aristas tal que dos aristas cualquiera de A no tengan ningn vrtice comn y toda arista de A-A comparta algn vrtice comn con una arista de A. Este nuevo problema garantiza conseguir un recubrimiento que contiene no ms de dos vrtices del recubrimiento mnimo. El procedimiento para construir un ajuste maximizal de un grafo G consistira en ir tomando aristas de G, de una en una y en cualquier orden e ir eliminando las incidentes al conjunto que se esta construyendo hasta recubrir todo en grafo. Para poder aplicar el nuevo problema aproximado, seria necesario demostrar que el conjunto de todos los vrtices inciden a las aristas de un ajuste maximal M para un grafo G es un recubrimiento con no mas de dos veces el numero de veces el recubrimiento de tamao mnimo. Esto es evidente, ya que por la definicin de ajuste maximal, los vrtices incidentes a las aristas de M son un recubrimiento de G. tambin por la propia definicin, ningn vrtice perteneciente a M puede recubrir a mas de una arista en M. En consecuencia, por lo menos la mitad de los vrtices de M deben pertenecer a un recubrimiento.