Академический Документы
Профессиональный Документы
Культура Документы
SESIN
5
Tcnicas de Diseo de Algoritmos. Parte I
I. OBJETIVOS
Definir las tcnicas de diseo de algoritmos
Valorar los mtodos de fuerza bruta, recursividad, divide y vencers.
Por ejemplo, un algoritmo de fuerza bruta para encontrar el divisor de un numero natural
n consistira en enumerar todos los enteros desde 1 hasta n, chequeando si cada uno de
ellos divide n sin generar resto. Otro ejemplo de bsqueda por fuerza bruta, en este caso
para solucionar el problema de las ocho reinas (posicionar ocho reinas en el tablero de
ajedrez de forma que ninguna de ellas ataque al resto), consistira en examinar todas las
combinaciones de posicin para las 8 reinas (en total 64! /56! = 178.462.987.637.760
posiciones diferentes), comprobando en cada una de ellas si las reinas se atacan
mutuamente.
La bsqueda por fuerza bruta es sencilla de implementar y, siempre que exista, encuentra
una solucin. Sin embargo, su coste de ejecucin es proporcional al nmero de
soluciones candidatas, el cual es exponencialmente proporcional al tamao del problema.
Por el contrario, la bsqueda por fuerza bruta se usa habitualmente cuando el nmero de
soluciones candidatas no es elevado, o bien cuando este puede reducirse previamente
usando algn otro mtodo heurstico.
1
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
La bsqueda por fuerza bruta no se debe confundir con backtracking, mtodo que
descarta un gran nmero de conjuntos de soluciones, sin enumerar explcitamente cada
una de las mismas.
Implementacin de la bsqueda por fuerza bruta
Algoritmo bsico
Para poder utilizar la bsqueda por fuerza bruta a un tipo especifico de problema, se
deben implementar las funciones primero, siguiente, valido, y mostrar. Todas recogern
el parmetro indicando una instancia en particular del problema:
Por ejemplo, para buscar los divisores de un entero n, la instancia del problema P es el
propio numero n. la llamada primero (n) devolver 1 siempre y cuando n1, y "nulo" en
otro caso; la funcin siguiente (n,c) debe devolver c + 1 si c<n , y "nulo" caso contrario;
vlido (n,c) devolver verdadero si y solo si c es un divisor de n.
Explosin combinacional
La principal desventaja del mtodo de fuerza bruta es que, para la mayora de problemas
reales, el nmero de soluciones candidatas es prohibitivamente elevado.
Por ejemplo, para buscar los divisores de un numero n tal y como se describe
anteriormente, el numero de soluciones candidatas a probar ser de n. Por tanto, si n
consta de, digamos, 16 dgitos, la bsqueda requerir de al menos 1015 comparaciones
computacionales, tarea que puede tardar varios das en un ordenador personal tipo. Si n
es un bit de 64 dgitos, que aproximadamente puede tener hasta 19 dgitos decimales, la
bsqueda puede tardar del orden de 10 anos.
2
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
2. Recursividad
Un problema que pueda ser definido en funcin de su tamao, sea este N, pueda ser
dividido en instancias ms pequeas (< N) del mismo problema y se conozca la solucin
explicita a las instancias ms simples, lo que se conoce como casos base, se puede aplicar
induccin sobre las llamadas ms pequeas y suponer que estas quedan resueltas.
Para que se entienda mejor a continuacin se exponen algunos ejemplos:
Factorial(x: Entero): Sea N := x el tamao del problema, podemos definir el
problema de forma recurrente como x*Factorial(x - 1); como el tamao de
Factorial(x - 1) es menor que N podemos aplicar induccin por lo que
disponemos del resultado. El caso base es el Factorial(0) que es 1.
Ordenacin por fusin(v: vector): Sea N := tamao(v), podemos separar el vector
en dos mitades. Estas dos mitades tienen tamao N/2 por lo que por induccin
podemos aplicar la ordenacin en estos dos subproblemas. Una vez que tenemos
ambas mitades ordenadas simplemente debemos fusionarlas. El caso base es
ordenar un vector de 0 elementos, que esta trivialmente ordenado y no hay que
hacer nada.
3
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
Con esta definicin veamos cmo funciona esta funcin para el valor del factorial de 3:
3! = 3 (3-1)!
= 3 2!
= 3 2 (2-1)!
= 3 2 1!
= 3 2 1 (1-1)!
= 3 2 1 0!
=3211
=6
Algoritmo recursivo
Un mtodo usual de simplificacin de un problema complejo es la divisin de este en
subproblemas del mismo tipo. Esta tcnica de programacin se conoce como divide y
vencers y es el ncleo en el diseo de numerosos algoritmos de gran importancia, as
como tambin es parte fundamental de la programacin dinmica.
int factorial(int x)
{
if (x > -1 && x < 2) return 1; // Cuando -1 < x < 2 devolvemos 1
// puesto que 0! = 1 y 1! = 1
else if (x < 0) return 0; // Error no existe factorial de
// nmeros negativos
return x * factorial(x - 1); // Si x >= 2 devolvemos el producto
// de x por el factorial de x - 1
}
4
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
Ejemplos de recurrencias
Factoria l -- n! = n (n-1)!
Sucesion de Fibonacc i -- f(n) = f(n-1) + f(n-2)
Numeros de Catalan -- C(2n, n)/(n+1)
Las Torres de Hanoi
Funcion de Ackermann
3. Divide y Vencers
En la cultura popular, divide y vencers hace referencia a un refrn que implica resolver
un problema difcil, dividindolo en partes mas simples tantas veces como sea necesario,
hasta que la resolucin de las partes se torna obvia. La solucin del problema principal se
construye con las soluciones encontradas.
Esta tcnica es la base de los algoritmos eficientes para casi cualquier tipo de problema
como, por ejemplo, algoritmos de ordenamiento (quicksort, mergesort, entre muchos
otros),multiplicar nmeros grandes (Karatsuba), anlisis sintcticos (anlisis sintctico
top-down) y la transformada discreta de Fourier.
Por otra parte, analizar y disear algoritmos de DyV son tareas que lleva tiempo dominar.
Al igual que en la induccin, a veces es necesario sustituir el problema original por uno
ms complejo para conseguir realizar la recursin, y no hay un mtodo sistemtico de
generalizacin.
El nombre divide y vencers tambin se aplica a veces a algoritmos que reducen cada
problema a un nico subproblema, como la bsqueda binaria para encontrar un elemento
en una lista ordenada (o su equivalente en computacin numrica, el algoritmo de
biseccin para bsqueda de races). Estos algoritmos pueden ser implementados mas
eficientemente que los algoritmos generales de divide y vencers; en particular, si es
usando una serie de recursiones que lo convierten en simples bucles. Bajo esta amplia
definicin, sin embargo, cada algoritmo que usa recursin o bucles puede ser tomado
como un algoritmo de divide y vencers. El nombre decrementa y vencers ha sido
propuesta para la subclase simple de problemas.
Diseo e implementacin
La resolucin de un problema mediante esta tcnica consta fundamentalmente de los
siguientes pasos:
5
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
3. Por ltimo, combinar las soluciones obtenidas en el paso anterior para construir la
solucin del problema original. Los algoritmos divide y vencers (o divide and conquer,
en ingls), se disean como procedimientos generalmente recursivos.
Por el hecho de usar un diseo recursivo, los algoritmos diseados mediante la tcnica de
Divide y Vencers van a heredar las ventajas e inconvenientes que la recursin plantea:
Por un lado el diseo que se obtiene suele ser simple, claro, robusto y elegante, lo
que da lugar a una mayor legibilidad y facilidad de depuracin y mantenimiento
del cdigo obtenido.
Por contra, los diseos recursivos conllevan normalmente un mayor tiempo de
ejecucin que los iterativos, adems de la complejidad espacial que puede
representar el uso de la pila de recursin.
Sin embargo, este tipo de algoritmos tambin se pueden implementar como un algoritmo
no recursivo que almacene las soluciones parciales en una estructura de datos explicita,
como puede ser una pila, cola, o cola de prioridad. Esta aproximacin da mayor libertad
al diseador, de forma que se pueda escoger que subproblema es el que se va a resolver a
continuacin, lo que puede ser importante en el caso de usar tcnicas como Ramificacion
y acotacin o de optimizacin.
Recursin
Los algoritmos de divide y vencers estn naturalmente implementados, como
procesos recursivos. En ese caso, los subproblemas parciales encabezados por aquel que
ya ha sido resuelto se almacenan en la pila de llamadas de procedimientos.
6
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
Pila explcita
Los algoritmos de divide y vencers tambin pueden ser implementados por un programa
no recursivo que almacena los subproblemas parciales en alguna estructura de datos
explicita, tales como una pila, una cola, o una cola de prioridad. Este enfoque permite
mas libertad a la hora de elegir los subproblemas a resolver despus, una caracterstica
que es importante en algunas aplicaciones, por ejemplo en la bsqueda en anchura y en el
mtodo de ramificacin y poda para optimizacin de subproblemas. Este enfoque es
tambin la solucin estndar en lenguajes de programacin que no permiten
procedimientos recursivos.
Tamao de la pila
En implementaciones recursivas de algoritmos de DyV, debe asegurarse que hay
suficiente memoria libre para la pila de recursin, sino la ejecucin puede .fallar por
desbordamiento de la pila. Afortunadamente, los algoritmos DyV que son eficientes
temporalmente tienen una profundidad recursiva relativamente pequea. Por ejemplo, el
algoritmo quicksort puede ser implementado de forma que nunca requiere ms de log2n
llamadas recursivas para ordenar n elementos.
7
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
Notemos que, si la lista vaca fuese el nico caso base, ordenar una lista con n entradas
dara lugar a n+1 llamadas al quicksort que no hara nada salvo volver inmediatamente.
El incrementar los casos bases a listas de tamao 2 o menos eliminaran la mayora de
estas llamadas que no haran nada, y ms generalmente un caso base ms grande que 2 es
tpicamente usado para reducir la fraccin de tiempo gastado en la sobrecarga de la
llamada de funciones o manipulacin de la pila.
Ventajas
Paralelismo
Este tipo de algoritmos se adapta de forma natural a la ejecucin en entornos
multiprocesador, especialmente en sistemas de memoria compartida donde la
comunicacin de datos entre los procesadores no necesita ser planeada por adelantado,
por lo que subproblemas distintos se pueden ejecutar en procesadores distintos.
Acceso a memoria
Los algoritmos que siguen el paradigma Divide y vencers, tienden naturalmente a hacer
un uso eficiente de las memorias caches. La razn es que una vez que un subproblema es
lo suficientemente pequeo, el y todos sus subproblemas se pueden, en principio,
solucionar dentro de esa cache, sin tener acceso a la memoria principal, que es del orden
de decenas de veces ms lenta. Un algoritmo diseado para aprovechar la memoria cache
8
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
Desventajas
La principal desventaja de este mtodo es su lentitud en la repeticin del proceso
recursivo: los gastos indirectos de las llamadas recursivas a la resolucin de los
subproblemas, junto con el hecho de tener que almacenar la pila de llamadas (el estado
en cada punto en la repeticin), pueden empeorar cualquier mejora hasta entonces
lograda. Esta tarea, sin embargo, depende del estilo de la implementacin: con casos base
lo suficientemente grandes, se reducen los gastos indirectos de la repeticin de las
llamadas.
9
Sesin 5 ANLISIS Y DISEO DE ALGORITMOS
IV
ACTIVIDADES
a) Factorial n! = n (n-1)!
b) Sucesin de Fibonacci f(n) = f(n-1) + f(n-2)
c) Nmeros de Catalan C(2n, n)/(n+1)
d) Las Torres de Hanoi
e) Funcin de Ackermann
V
CUESTIONARIO
10