Está en la página 1de 573

Algoritmia básica

Grado en Ingeniería Informática


Universidad de Zaragoza

Este documento está sujeto a una licencia de uso Creative


Javier Campos, Simona Bernardi (Universidad de Zaragoza) Commons. No se permite un uso comercial de la obra
original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Introducción a la algoritmia

Este documento está sujeto a una licencia de uso Creative


Algoritmia básica - Javier Campos (Universidad de Zaragoza) Commons. No se permite un uso comercial de la obra
original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Introducción a la algoritmia

AB Algoritmia =
Algoritmia = tratamiento sistemático de
técnicas fundamentales para
el diseño y análisis de
algoritmos eficientes

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 2


Introducción a la algoritmia
• Computadores cada vez más rápidos
y a más bajo precio:
– Se resuelven problemas
de cálculo antes impensables.
– Inconscientemente se tiende a restar
importancia al concepto de eficiencia.
• Existen problemas que seguirán siendo intratables si se
aplican ciertos algoritmos por mucho que se aceleren
los computadores
⇒ importancia de
nuevas soluciones eficientes

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 3


Introducción a la algoritmia
• Ejemplo:
“En Agosto de 1977, Scientific American proponía a sus lectores el reto
consistente en descifrar un mensaje secreto, para así ganar cien dólares.
Parecía algo seguro: se estimaba en aquel momento que el ordenador más
rápido existente, empleando el algoritmo más eficiente de los conocidos,
no podría ganar la apuesta salvo funcionando sin interrupción durante un
tiempo equivalente a millones de veces la edad del Universo. Sin
embargo, ocho meses de cálculo que comenzaron dieciséis años después
bastaron para la tarea. ¿Qué había pasado?…”

G. Brassard y P. Bratley
Fundamentos de Algoritmia (Prólogo)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 4


Introducción a la algoritmia
• Un curso de algoritmia
NO ES
– ni un curso de programación
(ya deberíais saber programar)
– ni un curso de estructuras de datos
(ya deberíais conocer las fundamentales)
TAMPOCO ES
– una colección de “recetas” Si tu problema es
o algoritmos listos para ordenar un fichero
secuencial de
ser introducidos en el enteros
computador para resolver entonces ejecuta
el algoritmo A026.
problemas específicos

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 5


Introducción a la algoritmia
• Un curso de algoritmia tiene como objetivo principal:

– dar más herramientas


fundamentales para
facilitar el desarrollo
de programas

¿qué herramientas?:

técnicas o “esquemas” de diseño de


algoritmos eficientes

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 6


Introducción a la algoritmia
• Un medio para alcanzar ese objetivo es:

– presentar cada esquema de forma


genérica, incidiendo en los
principios que conducen a él, e

– ilustrar el esquema mediante ejemplos concretos de


algoritmos tomados de varios dominios de aplicación

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 7


Introducción a la algoritmia
• Un problema muy sencillo:

Multiplicación de dos enteros positivos con lápiz y


papel.
– En España: – En Inglaterra:
981
1234
981
1234

3924 981
2943 1962
1962 2943
981 3924
1210554 1210554

– Ambos métodos son muy similares, los llamaremos algoritmo


“clásico” de multiplicación.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 8
Introducción a la algoritmia
– Algoritmo de multiplicación “a la rusa”:

 981 1234 1234


490 2468
 245 4936 4936
122 9872
 61 19744 19744
30 39488
 15 78976 78976
 7 157952 157952
 3 315904 315904
 1 631808 631808
1210554

• Ventaja: no hay que almacenar los productos parciales.


• Sólo hay que saber sumar y dividir por 2.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 9


Introducción a la algoritmia
– Todavía otro algoritmo:
• De momento, exigimos que ambos números tengan igual nº de cifras y
que éste sea potencia de 2.
Por ejemplo: 0981 y 1234.
• En primer lugar, partimos ambos números por la mitad y hacemos
cuatro productos:
multiplicar desplazar resultado
1) 09 12 4 108····
2) 09 34 2 306··
3) 81 12 2 972··
4) 81 34 0 2754
1210554

doble del nº de cifras nº de cifras

Es decir, hemos reducido un producto de nos de 4 cifras en cuatro


productos de nos de 2 cifras, varios desplazamientos y una suma.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 10
Introducción a la algoritmia
• Los productos de números de 2 cifras pueden hacerse con la misma técnica.
Por ejemplo, 09 y 12:
multiplicar desplazar resultado
1) 0 1 2 0··
2) 0 2 1 0·
3) 9 1 1 9·
4) 9 2 0 18
108
– Es un ejemplo de algoritmo que utiliza la técnica de “divide y vencerás”.
– Tal y como lo hemos presentado…
NO mejora en eficiencia al algoritmo clásico.
– Pero, puede mejorarse:
Es posible reducir un producto de dos números de muchas cifras a 3 (en
vez de 4) productos de números de la mitad de cifras, y éste SÍ que mejora
al algoritmo clásico.
– Y aún se conocen métodos más rápidos para multiplicar números muy
grandes.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 11


Introducción a la algoritmia
• Ideas clave:
– Incluso para un problema tan básico pueden construirse MUCHAS
soluciones.
– El método clásico lo usamos con lápiz y papel porque nos resulta muy
familiar (lo que se aprende en la infancia…).
– El método “a la rusa” se implementa en hardware en los computadores
por la naturaleza elemental de los cálculos intermedios.
– El método de divide y vencerás es más rápido si se quiere multiplicar
números grandes.
La algoritmia estudia las propiedades de los algoritmos y nos ayuda a
elegir la solución más adecuada en cada situación.

En muchos casos, una buena elección ahorra tiempo y dinero.


En algunos casos, una buena elección marca la diferencia entre poder
resolver un problema y no poder hacerlo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 12


Introducción a la algoritmia
• ¿A quién puede interesar este curso?

A todo aquél a quien:


– le guste diseñar algoritmos para resolver nuevos problemas o
algoritmos mejores a los triviales para resolver viejos
problemas, y

O(n2) ¿O(nlog n)?

– tenga curiosidad por conocer, por ejemplo, cómo se resuelven


los siguientes problemas:

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 13


Introducción a la algoritmia

– ¿Cómo multiplicar dos números enteros de forma más


eficiente que con el algoritmo clásico?

– ¿Cómo se compactan ficheros mediante el algoritmo de


Huffman?

– ¿Cómo se consiguen implementaciones muy eficientes de la


multiplicación y potenciación de enteros muy grandes para el
algoritmo RSA?

– ¿Por qué funcionan algoritmos vistos en Matemática Discreta


como el de Dijkstra, Prim o Kruskal?
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 14
Introducción a la algoritmia

– ¿Existen árboles binarios de búsqueda óptimos suponiendo


que se conocen las probabilidades de búsqueda de cada
clave?

– ¿Alguna forma de resolver el problema del viajante de


comercio?

– ¿Cómo se compara el ADN de un Homo sapiens y de un


Homo neanderthalensis?

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 15


Algoritmia básica: Contenidos de la asignatura
• Introducción a la algoritmia
• Algoritmos voraces
• Divide y vencerás
• Programación dinámica
• Búsqueda con retroceso
• Ramificación y poda
• Programación lineal y reducciones

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 16


Algoritmia básica: Bibliografía básica

[CLRS09] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein. Introduction to


Algorithms (3rd edition), The MIT Press, 2009.

[DPV08] S. Dasgupta, C. Papadimitriou, U. Vazirani. Algorithms, McGraw-


Hill, 2008.

[BB97] G. Brassard, P. Bratley. Fundamentos de Algoritmia, Prentice Hall,


1997.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 17


Algoritmia básica: Bibliografía complementaria

[HSR08] E. Horowitz, S. Sahni, and S. Rajasekaran. Computer algorithms,


2nd ed., Silicon Press, 2008.

[KT05] J. Kleinberg, E. Tardos. Algorithm Design, Addison-Wesley,


2005.

[PG02] I. Parberry and W. Gasarch. Problems on Algorithms (2nd


edition), free book, 2002.

Además: transparencias y otro material adicional disponibles en la


web de la asignatura, hojas de ejercicios, enlaces de Internet
(ejemplo: http://jeffe.cs.illinois.edu/teaching/algorithms/), etc.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 18


Chuleta
• Coste de algoritmos recursivos:
El coste T(n) de una función para datos de tamaño n se define
en función del coste T(m) de las llamadas recursivas para
otros tamaños m (menores que n)

Teorema (Master Theorem):


Θ( n k ) si a < 1
 f ( n) si 0 ≤ n < c   k +1
T1 ( n) =   ⇒ T1 ( n ) ∈ Θ( n ) si a = 1
 1
a ⋅ T ( n − c ) + b ⋅ n k
si c ≤ n  Θ(a n / c ) si a > 1

Θ(n k ) si a < c k
 g ( n) si 0 ≤ n < c  
T2 (n) =   ⇒ T2 (n) ∈ Θ(n k ⋅ log n) si a = c k
a ⋅ T2 (n / c) + b ⋅ n si c ≤ n
k
 Θ(n log c a ) si a > c k

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 19


Algoritmos voraces

Este documento está sujeto a una licencia de uso Creative


Algoritmia básica - Javier Campos (Universidad de Zaragoza) Commons. No se permite un uso comercial de la obra
original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Algoritmos voraces

• Introducción y primer ejemplo 3


• El problema de la mochila 9
• Caminos mínimos en grafos 17
• Árboles de recubrimiento de coste mínimo 39
• Consideraciones sobre la corrección del esquema voraz 55
• Códigos de Huffman 58
• El problema de la selección de actividades 66
• El problema de la minimización del tiempo de espera 71
• Fundamentos teóricos del esquema voraz 75
• Un problema de planificación de tareas a plazo fijo 85
• Heurísticas voraces 91
– Coloreado de grafos 91
– El problema del viajante de comercio 94

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 2


El esquema voraz: Introducción y primer ejemplo
• Es uno de los esquemas más simples y al mismo tiempo de los
más utilizados.
• Típicamente se emplea para resolver problemas de
optimización:
– existe una entrada de tamaño n que son los candidatos a formar parte de
la solución;
– existe un subconjunto de esos n candidatos que satisface ciertas
restricciones: se llama solución factible;
– hay que obtener la solución factible que maximice o minimice una cierta
función objetivo: se llama solución óptima.
• Ejemplos:
– encontrar la secuencia óptima para procesar un conjunto de tareas por un
computador,
– hallar un camino mínimo en un grafo,
– problema de la mochila,…
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 3
El esquema voraz: Introducción y primer ejemplo
• El esquema voraz procede por pasos:
– inicialmente el conjunto de candidatos escogidos es vacío;
– en cada paso, se intenta añadir al conjunto de los escogidos “el mejor” de
los no escogidos (sin pensar en el futuro), utilizando una función de
selección basada en algún criterio de optimización (puede ser o no ser la
función objetivo);
– tras cada paso, hay que ver si el conjunto seleccionado es completable
(i.e., si añadiendo más candidatos se puede llegar a una solución);
• si el conjunto no es completable, se rechaza el último candidato elegido y no
se vuelve a considerar en el futuro;
• si es completable, se incorpora al conjunto de escogidos y permanece
siempre en él;
– tras cada incorporación se comprueba si el conjunto resultante es una
solución;
– el algoritmo termina cuando se obtiene una solución;
– el algoritmo es correcto si la solución encontrada es siempre óptima;
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 4
El esquema voraz: Introducción y primer ejemplo
• Esquema genérico:
función voraz(C:conjunto) devuelve conjunto
{C es el conjunto de todos los candidatos}
principio
S:=Ø; {S es el conjunto en el que se construye la solución}
mq ¬solución(S) ∧ C≠Ø hacer
x:=elemento de C que maximiza seleccionar(x);
C:=C-{x};
si completable(S∪{x})
entonces S:=S∪{x}
fsi
fmq;
si solución(S)
entonces devuelve S
sino devuelve no hay solución
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 5


El esquema voraz: Introducción y primer ejemplo
• Problema del cambio en monedas.
– Se trata de devolver una cantidad de euros con el
menor número posible de monedas.
– Se parte de:
• un conjunto de tipos de monedas válidas, de las que se supone que hay cantidad
suficiente para realizar el desglose, y de
• un importe a devolver.
• Elementos fundamentales del esquema:
– Conjunto de candidatos: cada una de las monedas de los diferentes tipos que se
pueden usar para realizar el desglose del importe dado.
– Solución factible: un conjunto de monedas devuelto tras el desglose y cuyo valor
total es igual al importe a desglosar.
– Completable: la suma de los valores de las monedas escogidas en un momento
dado no supera el importe a desglosar.
– Función de selección: elegir si es posible la moneda de mayor valor de entre las
candidatas.
– Función objetivo: número total de monedas utilizadas en la solución (debe
minimizarse).
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 6
El esquema voraz: Introducción y primer ejemplo
• Solución:
tipo moneda=(M25,M10,M5,M1) {por ejemplo}

función cambia(importe:nat; valor:vector[moneda] de nat)


devuelve vector[moneda] de nat
variables mon:moneda; cambio:vector[moneda] de nat
principio
para todo mon en moneda hacer
cambio[mon]:=0
fpara;
para mon:=M25 hasta M1 hacer
mq valor[mon]≤importe hacer
cambio[mon]:=cambio[mon]+1;
importe:=importe-valor[mon]
fmq
fpara;
devuelve cambio
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 7


El esquema voraz: Introducción y primer ejemplo
• Problemas sobre el problema del cambio en monedas:
– Demostrar la corrección del algoritmo.
– Demostrar, buscando contraejemplos, que el algoritmo no es
óptimo si se añade un nuevo tipo de moneda de 12 euros o si
se elimina alguno de los tipos existentes.
Demostrar que, en esas condiciones, el algoritmo puede
incluso no encontrar solución alguna aunque ésta exista.
• Otro problema:
– ¿Es el método de ordenación por selección directa un
algoritmo voraz?
Si es así, ¿cuáles son las funciones utilizadas (“selección”,
“completable”, “solución”)?

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 8


El problema de la mochila
• Se tienen n objetos fraccionables y una mochila.
• El objeto i tiene peso pi, 1≤i ≤ n.
• La mochila tiene capacidad C.
• Si se mete una fracción xi, 0 ≤ xi ≤ 1, del objeto i en la
mochila, entonces se consigue un beneficio bixi.
• El objetivo es llenar la mochila de manera que se
maximice el beneficio total.
• Pero como la mochila tiene capacidad C, el peso total
de todos los objetos metidos en ella no puede superar
esa cantidad.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 9


El problema de la mochila
• Formalmente: maximizar Σ
1≤i≤n
bixi (1)

sujeto a Σ pixi ≤ C (2)


1≤i≤n

con 0≤xi≤1, bi>0, pi>0, 1≤i≤n (3)

• Una solución factible es cualquier n-tupla (x1,…,xn) que


satisfaga (2) y (3).
• Una solución óptima es cualquier solución factible para la que
(1) sea máximo.
• Si p1+⋅⋅⋅+pn≤C, entonces obviamente xi=1, 1≤i≤n, es una
solución óptima.
• Por tanto, supongamos que p1+⋅⋅⋅+pn>C.
• Nótese además que todas las soluciones óptimas llenarán la
mochila por completo (podemos poner ‘=‘ en (2)).
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 10
El problema de la mochila
• Ejemplo:
n=3 C=17
(b1,b2,b3)=(40,36,22)
(p1,p2,p3)=(15,12,8)

• Tres soluciones factibles (entre otras muchas):

Σ bixi
(x1,x2,x3) 1≤i≤3
(i) (1,1/6,0) 46
(ii) (0,3/4,1) 49
(iii) (0,1,5/8) 49’75
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 11
El problema de la mochila
• Solución voraz:
– El conjunto de candidatos son los objetos, tomándose de ellos
cierta fracción.
– Un conjunto de candidatos es completable si la suma de sus
pesos no supera la capacidad de la mochila, y es una solución
si iguala dicha capacidad.
Σ bixi.
– La función objetivo a maximizar es 1≤i≤n

– La función de selección es la más difícil de determinar.


• Si procedemos vorazmente, en cada paso debemos considerar un
objeto y tomar cierta fracción suya.
• La cuestión de qué fracción se toma es más fácil de resolver: si hemos
elegido el mejor candidato, tomamos todo lo que podamos de él.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 12


El problema de la mochila
– ¿Cuál es el mejor candidato (es decir, la mejor función de
selección)?
– Volvamos al ejemplo:
• Primera estrategia: elegir el objeto con mayor beneficio total (el
primero). Sin embargo, la mochila se llena muy rápidamente con poco
beneficio total.
• Segunda estrategia: elegir el objeto que llene menos la mochila, para
acumular beneficios de un número mayor de objetos. Sin embargo, es
posible que se elija un objeto con poco beneficio simplemente porque
pesa poco.
• La tercera estrategia, que es la óptima, es tomar siempre el objeto que
proporcione mayor beneficio por unidad de peso.
– Los algoritmos resultantes de aplicar cualquiera de las dos
primeras estrategias también son voraces, pero no calculan la
solución óptima.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 13
El problema de la mochila
constante n=... {número de objetos}
tipo vectReal=vector[1..n] de real

{Pre:∀i∈1..n:peso[i]>0 ∧
∀i∈1..n-1:benef[i]/peso[i]≥benef[i+1]/peso[i+1]}
función mochila(benef,peso:vectReal; cap:real) devuelve vectReal
variables resto:real; i:entero; sol:vectReal
principio
para todo i en 1..n hacer
sol[i]:=0.0 {inicializar solución}
fpara;
resto:=cap; {capacidad restante}
i:=1;
mq (i≤n) and (peso[i]≤resto) hacer
sol[i]:=1; resto:=resto-peso[i]; i:=i+1
fmq;
si i≤n entonces sol[i]:=resto/peso[i] fsi;
devuelve sol
fin
{Post: sol es solución óptima del problema de la mochila}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 14


El problema de la mochila
• Coste temporal: Θ(n)
Θ(nlog n) si se tiene en cuenta que hay que ordenar primero los vectores.
• Demostración de la corrección:
Sea X=(x1,…,xn) la solución generada por el algoritmo voraz.
Si todos los xi son iguales a 1, la solución es claramente óptima.
Luego, sea j el menor índice tal que xj≠1.
Por tanto xi=1 para 1≤i<j, xi=0 para j<i≤n, y 0≤xj<1.
Si X no es óptima ent. existe otra solución factible Y=(y1,…,yn) tal que
Σ biyi > Σ bixi.
Sin perdida de generalidad, asumimos que Σ piyi =C.
Sea k el menor índice tal que yk≠xk (claramente, existe ese k).
Se verifica: yk<xk . En efecto:
• Si k<j entonces xk=1. Pero yk≠xk luego yk<xk .
• Si k=j ent., puesto que Σ piyi =C y yi=xi para 1≤i<j, se sigue que yk<xk ó Σ piyi >C.
• Si k>j entonces Σ piyi > C, y eso no es posible.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 15


El problema de la mochila
Ahora, supongamos que aumentamos yk hasta xk y disminuímos tantos
(yk+1,…,yn) como sea necesario para que la capacidad utilizada siga siendo C.
Se obtiene así una nueva solución Z=(z1,…,zn)
con zi=xi, para 1≤i≤k y Σk<i≤n pi(yi -zi)=pk(zk-yk).
Entonces:
Σ1≤i≤n bizi = Σ1≤i≤n biyi + (zk-yk)pkbk/pk -
- Σk<i≤n (yi -zi)pibi/pi
≥ Σ1≤i≤n biyi +
+ [(zk-yk)pk - Σk<i≤n (yi -zi)pi]bk/pk
= Σ1≤i≤n biyi
Si Σ1≤i≤n bizi > Σ1≤i≤n biyi entonces Y no puede ser óptima.
Si esas sumas son iguales entonces bien Z=X y X es óptima, o bien Z≠X.
En este último caso, se usa de nuevo el mismo argumento hasta demostrar
que bien Y no es óptima o bien Y se transforma en X, demostrando que X
también es óptima. 
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 16
Caminos mínimos en grafos
• Grafos etiquetados con pesos no negativos

12 3 3 12
3 3
5 5
1 2 5 1 2 5
21 4 21 4
4 4
• Búsqueda de caminos de longitud mínima
– longitud o coste de un camino: suma de los pesos de las aristas que lo componen
– cálculo de la longitud mínima de los caminos existentes entre dos vértices dados
• Características del tipo de dato de las etiquetas (o pesos):
– dominio ordenado (<, =, ≤)
– operación suma (+):
• conmutativa
• con elemento neutro (0), que es además el peso más pequeño posible
• con elemento idempotente (∞), que es además el peso más grande posible

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 17


Caminos mínimos en grafos
• Representaciones de grafos: Matriz de adyacencia
– Grafo dirigido G=(V,A) con V={1,2,…,n}.
– La matriz de adyacencia para G es una matriz A de dimensiones n × n de
elementos booleanos en la que A[i,j] es verdad si y sólo si existe una arista
en G que va del vértice i al vértice j.
constante n = ... {cardinal de V}
tipo grafo = vector[1..n,1..n]de booleano

1
falso verdad falso

2 A = verdad falso verdad


Grafo
dirigido falso falso falso
3
Matriz de adyacencia
– En el caso de un grafo no dirigido, la matriz de adyacencia tiene la
particularidad de ser simétrica.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 18


Caminos mínimos en grafos
– La representación de la matriz de adyacencia es útil para aquellos algoritmos
que precisan saber si existe o no una arista entre dos vértices dados.
– En el caso de grafos etiquetados con pesos, los elementos de la matriz
pueden ser enteros o reales (en lugar de booleanos) y representar el peso de la
arista. Si no existe una arista de i a j, debe emplearse un valor que no pueda
ser una etiqueta válida para almacenarse en A[i,j].
– Un inconveniente de la representación de la matriz de adyacencia es que
requiere un espacio en Θ(n2) aunque el grafo tenga muy pocas aristas.
– Dado un grafo G=(V,A) representado mediante su matriz de adyacencia, la
pregunta ¿(u,v)∈A? se puede contestar en un tiempo en Θ(1).
– Sin embargo, la operación sucesores(g,v) necesita un tiempo en Θ(n) (pues
hay que recorrer una fila completa de la matriz).
– Más aún, para saber, por ejemplo, si un grafo no dirigido representado
mediante su matriz de adyacencia es conexo, o simplemente para conocer el
número de aristas, los algoritmos requieren un tiempo en Θ(n2), lo cual es
más de lo que cabría esperar.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 19


Caminos mínimos en grafos
• Listas de adyacencia
– Esta representación sirve para mejorar la eficiencia de los algoritmos
sobre grafos que necesitan acceder a los vértices sucesores a uno dado.
– Consiste en almacenar n listas enlazadas mediante punteros de forma que
la lista i-ésima contiene los vértices sucesores del vértice i.
1
constante n = ... {cardinal de V}
tipos ptNodo = ↑nodo;
nodo = registro Grafo 2
dirigido
vértice:1..n;
3
sig:ptNodo
freg
grafo = vector[1..n] de ptNodo 2 nil
1
2 1 3 nil
3 nil

Vector de listas de adyacencia

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 20


Caminos mínimos en grafos
– La representación de un grafo con listas de adyacencia requiere un espacio
del orden del máximo entre n (el número de vértices) y a (el nº de aristas).
– En el caso de un grafo no dirigido, si (u,v)∈A entonces el vértice v estará
en la lista correspondiente al vértice u, y el vértice u lo estará a su vez en
la lista de adyacencia del vértice v.
– Para representar un grafo etiquetado con pesos basta con añadir otro
campo al tipo nodo que almacene el peso correspondiente.
– Acceder a la lista de los vértices sucesores de uno dado lleva un tiempo
constante.
– Sin embargo, consultar si una determinada arista (u,v) está en el grafo
precisa recorrer la lista asociada al vértice u, lo que en el caso peor se
realiza en Θ(n).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 21


Caminos mínimos en grafos
– En el caso de un grafo dirigido, si se necesita saber los
predecesores de un vértice dado, la representación con listas
de adyacencia no es adecuada.

Ese problema puede superarse si se almacena otro vector de n


listas de forma que la lista i-ésima contenga los vértices
predecesores del vértice i.

Estas listas se llaman listas de adyacencia inversa.


1

2 nil
2 1
2 1 nil
3
2 nil
3

Grafo Vector de listas de adyacencia inversa


dirigido
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 22
Caminos mínimos en grafos
• Listas múltiples de adyacencia
– En el caso de grafos dirigidos, las listas de adyacencia directa e inversa
pueden representarse de forma más compacta…
– Una lista múltiple es una estructura dinámica de datos enlazados mediante
punteros en la que cada dato puede pertenecer a dos o más listas.
– Hay un nodo por cada una de las aristas del grafo.
– Cada nodo guarda la clave de dos vértices (origen y destino de la arista) y
dos punteros: el primero al nodo que guarda la siguiente arista que tiene el
mismo vértice destino y el segundo al nodo que guarda la siguiente arista
que tiene el mismo vértice origen.
Listas de adyacencia inversa
1
1 2 3

3 1 2 nil nil
1
Grafo dirigido 2 2 1 nil 2 3 nil nil
3 nil
Listas de adyacencia

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 23


Caminos mínimos en grafos

constante n = ... {cardinal de V}


tipos ptNodo = ↑nodo;
nodo = registro
origen,destino: 1..n;
sigInvAdy,sigAdy: ptNodo
freg
grafoDirigido =
= registro
adyacentes,invAdyacentes: vector[1..n] de ptNodo
freg

Nótese que se emplea la palabra “adyacente” con el


significado de “sucesor”, mientras que “adyacente inverso” se
refiere a “predecesor”.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 24


Caminos mínimos en grafos
– Las listas múltiples pueden utilizarse también para representar grafos no
dirigidos.
– De esta forma, en lugar de
2 3 4 nil
que a cada arista le correspondan 1
1
1 3 4 nil
dos nodos en la estructura 2 3
2
3
1
dinámica (como ocurre con la 4
4
2 4 nil

1 2 3 nil
representación basada en listas
Grafo no dirigido Listas de adyacencia
“ simples” de adyacencia), puede
representarse cada arista con un 1 2

solo nodo y hacer que éste


pertenezca a dos listas de 1
2 1 3 2 3
adyacencia diferentes. 3
4

1 4 2 4 3 4

nil nil nil nil

Listas múltiples de adyacencia

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 25


Caminos mínimos en grafos
– La definición de la estructura de datos es la siguiente:

constante n = ... {cardinal de V}


tipos ptNodo = ↑nodo;
nodo = registro
v1,v2:1..n;
sig1,sig2:ptNodo
freg
grafoNoDirigido = vector[1..n] de ptNodo

– Una ventaja de esta representación es que es útil para


implementar aquellos algoritmos que necesitan recorrer un
grafo y al mismo tiempo “marcar” las aristas por las que se
pasa (bastaría con añadir un campo booleano al tipo nodo).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 26


Caminos mínimos en grafos
• Cálculo del coste del camino mínimo desde un vértice
dado al resto, en un grafo etiquetado con pesos no
negativos

• Utilidad:
el grafo representa una distribución geográfica, donde las
aristas dan el coste (precio, distancia...) de la conexión entre
dos lugares y se desea averiguar el camino más corto
(barato...) para llegar a un punto partiendo de otro

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 27


Caminos mínimos en grafos

E.W. Dijkstra:
“A note on two problems in connexion with
graphs”,
Numerical Mathematica, 1, pp. 269-271, 1959.

• Solución voraz: Algoritmo de Dijkstra


– para grafos dirigidos (la extensión a no dirigidos es inmediata)
– genera uno a uno los caminos de un nodo v al resto por orden creciente de
longitud
– usa un conjunto de vértices donde, a cada paso, se guardan los nodos para los que
ya se sabe el camino mínimo
– devuelve un vector indexado por vértices: en cada posición w se guarda el coste
del camino mínimo que conecta v con w
– cada vez que se incorpora un nodo a la solución se comprueba si los caminos
todavía no definitivos se pueden acortar pasando por él
– se supone que el camino mínimo de un nodo a sí mismo tiene coste nulo
– valor ∞ en la posición w del vector indica que no hay ningún camino desde v a w

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 28


Caminos mínimos en grafos

{Pre: g es un grafo dirigido etiquetado no neg.}


función Dijkstra(g:grafo; v:vért) devuelve vector[vért] de etiq
variables S:cjtVért; D:vector[vért] de etiq
principio
∀w∈vért:D[w]:=etiqueta(g,v,w);
D[v]:=0; S:={v};
mq S no contenga todos los vértices hacer
{D contiene caminos mínimos formados íntegramente por nodos de S
(excepto el último), y los nodos de S corresponden a los caminos
mínimos más cortos calculados hasta el momento}
elegir w∉S t.q. D[w] es mínimo;
S:=S∪{w};
∀u∉ S:actualizar dist.mín. comprobando si por w hay un atajo
fmq;
devuelve D
fin
{Post: D=caminosMínimos(g,v)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 29


Caminos mínimos en grafos
• Corrección:
ver material adicional en la web.

• Se presenta a continuación una implementación más


detallada
– Se utiliza en lugar de S su complementario T
– Se supone que n es el número de vértices

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 30


Caminos mínimos en grafos

{Pre: g es un grafo dirigido etiquetado no neg.}


función Dijkstra(g:grafo; v:vért) devuelve vector[vért] de etiq
variables T:cjtVért;
D:vector[vért] de etiq;
u,w:vért; val:etiq
principio
T:=∅;
para todo w en vért hacer
D[w]:=etiqueta(g,v,w); T:=T∪{w}
fpara;
D[v]:=0; T:=T-{v};
repetir n-2 veces {quedan n-1 caminos por determinar}
{selección del w tal que D[w] es mín.: w∈T ∧ ∀u∈ T:D[w]≤D[u]}
val:=∞;
para todo u en T hacer
si D[u]≤val ent w:=u; val:=D[u] fsi
{siempre hay un nodo que cumple la condición}
fpara;
...

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 31


Caminos mínimos en grafos

...
{se marca w como vértice tratado}
T:=T-{w};
{se recalculan las nuevas dist. mínimas}
para todo u en T hacer
si D[w]+etiqueta(g,w,u)<D[u]
ent D[u]:=D[w]+etiqueta(g,w,u)
fsi
fpara
frepetir;
devuelve D
fin
{Post: D=caminosMínimos(g,v)

Nota: el bucle principal se ejecuta n-2 veces porque el último camino queda
calculado después del último paso (no quedan vértices para hallar atajos)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 32


Caminos mínimos en grafos
• Tiempo de ejecución:
– se supone que las operaciones sobre cjtos. están implementadas en tiempo
constante, excepto la creación (p.ej., mediante un vector de booleanos)
– fase de inicialización:
• creación del cjto. y ejecución n veces de diversas operaciones constantes: Θ(n)
– fase de selección:
• las instrucciones del interior del bucle son Θ(1)
• nº de ejecuciones del bucle:
1ª vuelta: se consultan n-1 vértices,
2ª vuelta: n-2, etc.
(el cardinal de T decrece en 1 en cada paso)
nº de ejecuciones: n(n-1)/2-1 ⇒ Θ(n2)
– fase de “marcaje”:
• n supresiones a lo largo del algoritmo: Θ(n)
– fase de recálculo de las distancias mínimas:
• queda Θ(n2) por igual razón que la selección
Coste total: Θ(n2)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 33


Caminos mínimos en grafos
• Mejoras en el tiempo de ejecución
– Si la representación es por listas de adyacencia, la fase de recálculo se
ejecuta sólo a (a<n2) veces (sustituyendo el bucle sobre los vért. de T por
otro bucle sobre los vért. sucesores de w).
– Si el conjunto T se sustituye con una cola con prioridades, se rebaja
también el coste de la fase de selección (puesto que se selecciona el
mínimo).

Problema: la fase de recálculo puede exigir cambiar la prioridad de un


elemento cualquiera de la cola.

Solución: nuevo tipo de cola con prioridades que permita el acceso directo
a cualquier elemento.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 34


Caminos mínimos en grafos
género cpa {colaPriAristas}
operaciones
creaVacía: → cpa Θ(1)
inserta: cpa vért etiq → cpa Θ(log n)
primero: cpa → (vért,etiq) Θ(1)
borra: cpa → cpa Θ(log n)
sustit: cpa vért etiq → cpa Θ(log n)
valor: cpa vért → etiq Θ(1)
está?: cpa vért → bool Θ(1)
vacía?: cpa → bool Θ(1)

– Implementación: montículo junto con un vector indexado por vértices


<4,20>
1
2 el valor ∞ de la etiqueta
3 <3,75> <5,60>
significa que el vértice
no está en la cola
4
5 <2,∞>

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 35


Caminos mínimos en grafos
{Pre: g es un grafo dirigido etiquetado no neg.}
función Dijkstra(g:grafo; v:vért) devuelve vector[vért] de etiq
variables A:cpa; {cola de aristas con prior.}
D:vector[vért] de etiq; u,w:vért; et,val:etiq
principio
{crear la cola con todas las aristas <v,w>}
creaVacía(A);
para todo w en vért hacer
inserta(A,w,etiqueta(g,v,w))
fpara;
mq not esVacía(A) hacer
<w,val>:=primero(A); {selecc. arista mín.}
D[w]:=val; borra(A); {marca w como tratado}
{se recalculan las nuevas dist. mínimas}
para todo <u,et> en suc(g,w) hacer
si está(A,u) and_then val+et<valor(A,u) entonces
sustituye(A,u,val+et) fsi
fpara
fmq;
D[v]:=0; devuelve D
fin {Post: D=caminosMínimos(g,v)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 36


Caminos mínimos en grafos
• Eficiencia temporal:
– inicialización: Θ(nlog n)
– selección y supresión: Θ(nlog n)
– bucle interno: examina todas las aristas del grafo y en el caso
peor efectúa una sustitución por arista, por tanto: Θ(alog n)
• El coste total es: Θ((a+n)log n), luego es mejor que la versión
anterior si el grafo es disperso.
• Si el grafo es denso, el algoritmo original es mejor.

• Puede conseguirse un coste en Θ(n2) para grafos densos y en


Θ(alog n) para no densos, representando el montículo en un
árbol k-ario en lugar de binario [BB97, pp. 243].

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 37


Caminos mínimos en grafos
• Ejercicio: cálculo de la secuencia de nodos que componen el
camino mínimo
– si el camino mínimo entre v y w pasa por u, el camino mínimo entre v y u
es un prefijo del camino mínimo entre v y w
– basta con devolver un vector pred tal que pred[w] contenga el nodo
predecesor de w en el camino mínimo de v a w (que será v si está
directamente unido al nodo de partida o si no hay camino entre v y w)
– el vector debe actualizarse al encontrarse un atajo en el camino
– es necesario también diseñar un nuevo algoritmo para recuperar el camino
a un nodo dado, que tendría como parámetro pred

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 38


Árboles de recubrimiento de coste mínimo
• Objetivo: dado un grafo, obtener un nuevo grafo que sólo contenga las aristas
imprescindibles para una optimización global de las conexiones entre todos
los nodos

“optimización global”: algunos pares de nodos pueden no quedar conectados entre


ellos con el mínimo coste posible en el grafo original

• Aplicación: problemas que tienen que ver con distribuciones geográficas

conjunto de computadores distribuidos geográficamente en diversas ciudades de


diferentes países a los que se quiere conectar para intercambiar datos, compartir
recursos, etc.;

se pide a las compañías telefónicas respectivas los precios de alquiler de líneas


entre ciudades

asegurar que todos los computadores pueden comunicar entre sí, minimizando el
precio total de la red

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 39


Árboles de recubrimiento de coste mínimo
• Terminología:
– árbol libre:
es un grafo no dirigido conexo acíclico
• todo árbol libre con n vértices tiene n – 1 aristas
• si se añade una arista se introduce un ciclo
• si se borra una arista quedan vértices no conectados
• cualquier par de vértices está unido por un único camino simple
• un árbol libre con un vértice distinguido es un árbol con raíz
– árbol de recubrimiento de un grafo no dirigido y etiquetado no
negativamente: es cualquier subgrafo que contenga todos los vértices y
que sea un árbol libre
– árbol de recubrimiento de coste mínimo:
es un árbol de recubrimiento y no hay ningún otro árbol de recubrimiento
cuya suma de aristas sea menor
– notación: arm(g)={árboles de recubrimiento de coste mínimo de g}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 40


Árboles de recubrimiento de coste mínimo
• Propiedad fundamental de los árboles de recubrimiento
de coste mínimo:
“Sea g un grafo no dirigido conexo y etiquetado no
negativamente, g∈{f:V×V→E},
sea U un conjunto de vértices, U⊂V, U≠∅,
si <u,v> es la arista más pequeña de g tal que u∈U y v∈V–U,
entonces existe algún árbol de recubrimiento de coste mínimo
de g que la contiene.”

Dem: Por reducción al absurdo (por ejemplo, en


[AHU88] A.V. Aho, J.E. Hopcroft y J.D Ullman. Estructuras de datos y
algoritmos. Addison-Wesley Iberoamericana, S.A., 1988.).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 41


Árboles de recubrimiento de coste mínimo
V. Jarník: “O jistém problému minimálním”,
Práca Moravské Prírodovedecké Spolecnosti, 6,
pp. 57-63, 1930.

R.C. Prim:
“Shortest connection networks and some generalizations”,
Bell System Technical Journal, 36, pp. 1389-1401, 1957.

• Algoritmo de Prim (debido a Jarník)


– Aplica reiteradamente la propiedad de los árboles de
recubrimiento de coste mínimo incorporando a cada paso una
arista
– Se usa un conjunto U de vértices tratados y se selecciona en
cada paso la arista mínima que une un vértice de U con otro
de su complementario

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 42


Árboles de recubrimiento de coste mínimo

{Pre: g es un grafo no dirigido conexo etiquetado no negativamente}


función Prim(g:grafo) devuelve grafo
variables U:cjtVért; gsol:grafo;
u,v:vért; x:etiq
principio
creaVacío(gsol); U:={cualquier vértice};
mq U no contenga todos los vért. hacer
seleccionar <u,v,x> mínima t.q. u∈U; v∉U
añade(gsol,u,v,x); U:=U∪{v}
fmq;
devuelve gsol
fin
{Post: gsol∈arm(g)}

Coste: Θ(na)
(es decir, Θ(n3) si el grafo es denso)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 43


Árboles de recubrimiento de coste mínimo
• La versión previa puede refinarse hasta obtener un
algoritmo en Θ(n2), es decir, mejor que el anterior
(a≥n-1).

Se usa un vector arisMín, indexado por vértices, que


contiene:

si v∉U: arisMín[v]=<w,g(v,w)> t.q. <v,w> es la arista más


pequeña que conecta v con un vértice w∈U

si v∈U: arisMín[v]=<v,∞>

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 44


Árboles de recubrimiento de coste mínimo
{Pre: g es un grafo no dirigido conexo etiquetado no negativamente}
función Prim(g:grafo) devuelve grafo
variables
arisMín:vector[vért] de <vért,etiq>;
gsol:grafo; prim,mín,v,w:vért; x:etiq
principio
{inicialización del resultado}
prim:=unVérticeCualquiera;
para todo v en vért hacer
arisMín[v]:=<prim,etiqueta(g,prim,v)>
fpara;
arisMín[prim]:=<prim,∞>;
{a continuación se aplica el método}
creaVacío(gsol);
repetir n-1 veces
mín:=prim; {centinela: arisMín[mín].et=∞}
para todo v en vért hacer
<w,x>:=arisMín[v];
si x<arisMín[mín].et ent mín:=v {como mínimo habrá uno} fsi
fpara;
...

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 45


Árboles de recubrimiento de coste mínimo

...
{a continuación se añade a la solución}
añade(gsol,mín,arisMín[mín].v,arisMín[mín].et);
{se añade mín al conjunto de vértices tratados}
arisMín[mín]:=<mín,∞>;
{se reorganiza el vector comprobando si la arista mínima de los
vértices todavía no tratados los conecta a mín}
para todo <v,x> en adyacentes(g,mín) hacer
si (arisMín[v].v≠v)and(x<arisMín[v].et)
entonces arisMín[v]:=<mín,x>
fsi
fpara
frepetir;
devuelve gsol
fin
{Post: gsol∈arm(g)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 46


Árboles de recubrimiento de coste mínimo
• Eficiencia temporal:
– inicialización: lineal en caso de matriz de adyacencia y
cuadrática en caso de listas
– bucle principal:
• el bucle de selección: Θ(n)
• el añadido de una arista al grafo: constante usando matriz, lineal
usando listas
• el bucle de reorganización:
– con matriz de adyacencia: el cálculo de los adyacentes es Θ(n) y
el coste total queda Θ(n2)
– con listas: el coste total es Θ(a+n)
Coste total: Θ(n2), independientemente de la
representación.
Coste espacial: Θ(n) de espacio adicional.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 47


Árboles de recubrimiento de coste mínimo

J.B. Kruskal: “On the shortest spanning subtree of a graph


and the traveling salesman problem”, Proceedings of the
American Mathematical Society, 7, pp. 48-50, 1956.

• Algoritmo de Kruskal:
– Se basa también en la propiedad de los árboles de
recubrimiento de coste mínimo:

Partiendo del árbol vacío, se selecciona en cada paso la arista


de menor etiqueta que no provoque ciclo sin requerir ninguna
otra condición sobre sus extremos.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 48


Árboles de recubrimiento de coste mínimo

{Pre: g es un grafo no dirigido conexo etiquetado no negativamente}


función Kruskal(g:grafo) devuelve grafo
variables gsol:grafo; u,v:vért; x:etiq
principio
creaVacío(gsol);
mq gsol no contenga todos los vértices hacer
seleccionar <u,v,x> mínima(∗) no examinada;
si no provoca ciclo
entonces añade(gsol,u,v,x)
fsi
fmq;
devuelve gsol
fin
{Post: gsol∈arm(g)}

(∗) Utilizar una cola con prioridades.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 49


Árboles de recubrimiento de coste mínimo
• Implementación eficiente:
– En cada momento, los vértices que están dentro de una componente
conexa en la solución forman una clase de equivalencia, y el algoritmo se
puede considerar como la fusión continuada de clases hasta obtener una
única componente con todos los vértices del grafo.

30 3
A B A B
40 40 4

50 C 60 C
10 20 1 2
D 50
E D E

Evolución de las clases de equivalencia:

{[A],[B],[C],[D],[E]} → {[A],[B],[C,D],[E]} → {[A],[B],[C,D,E]} →

→ {[A,B],[C,D,E]} → {[A,B,C,D,E]}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 50


Árboles de recubrimiento de coste mínimo

• Se utiliza el TAD “relación de equivalencia” sobre los vértices


género rev {relac. de equiv. sobre vért.}
operaciones
creaREV: → rev {cada vért. una clase}
clase: rev vért → nat
fusiona: rev nat nat → rev
numClases: rev → nat

Implementación asintóticamente óptima:


• basada en una representación del tipo rev usando árboles y una técnica de
compresión de caminos [AHU88, pp. 182-191]
(o ver aquí: http://webdiis.unizar.es/asignaturas/TAP/material/3.5.disjuntos.pdf )
• el coste de creaREV es lineal
• el coste de numClases es constante
• el coste de k ejecuciones combinadas de fusiona y clase es
Θ(kα(k,n)), lo cual es prácticamente constante, porque
α es una función inversa de la función de Ackerman que crece MUY
despacio (α(k,n)≤4, para todos los valores de k y n “imaginables”)
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 51
Árboles de recubrimiento de coste mínimo

{Pre: g es un grafo no dirigido conexo etiquetado no negativamente}


función Kruskal(g:grafo) devuelve grafo
variables T:cpa; gsol:grafo;
u,v:vért; x:etiq;
C:rev; ucomp,vcomp:nat
principio
creaREV(C); {cada vért. forma una clase}
creaVacío(gsol);
creaVacía(T);
{se colocan todas las aristas en la cola}
para todo v en vért hacer
para todo <u,x> en adyacentes(g,v) hacer
inserta(T,v,u,x)
fpara
fpara;
...

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 52


Árboles de recubrimiento de coste mínimo

...
mq numClases(C)>1 hacer
{obtener y elim. la arista mín.de la cola}
<u,v,x>:=primero(T); borra(T);
{si la arista no provoca ciclo se añade a la
solución y se fusionan las clases corresp.}
ucomp:=clase(C,u); vcomp:=clase(C,v);
si ucomp≠vcomp entonces
fusiona(C,ucomp,vcomp);
añade(gsol,u,v,x)
fsi
fmq;
devuelve gsol
fin
{Post: gsol∈arm(g)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 53


Árboles de recubrimiento de coste mínimo
• Coste del algoritmo:
– las a inserciones consecutivas de aristas en la cola con prioridades dan Θ(alog a);
como a≤n2: Θ(alog a)⊆Θ(alog n2)=Θ(2alog n)=Θ(alog n)
– como mucho hay a consultas y supresiones de la arista mínima, el coste de la
consulta es constante y el de la supresión es Θ(log a); por ello, este paso queda en
Θ(alog n)
– averiguar cuántas clases hay en la relación de equivalencia es constante
– en el caso peor, la operación de fusión de clases se ejecuta n-1 veces y la
operación de localizar la clase 2a veces; por tanto, el coste total es en la práctica
Θ(a)
– las n-1 inserciones de aristas quedan en Θ(n) con matriz de adyacencia y Θ(n2)
con listas, aunque en el caso de las listas puede reducirse también a Θ(n) si se
elimina en la operación de añade la comprobación de existencia de la arista (el
algoritmo de Kruskal garantiza que no habrá inserciones repetidas de aristas)

Coste total: Θ(alog n)


(menos que el algoritmo de Prim, aunque con mayor espacio adicional)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 54


Consideraciones sobre la corrección del esquema voraz
• La selección de una candidata óptima en cada paso es una
estrategia heurística que no siempre conduce a la solución
óptima.
• En ocasiones, se utilizan heurísticas voraces para obtener
soluciones subóptimas cuando el cálculo de las óptimas es
demasiado costoso.
• ¿Puede saberse que familias de problemas (de optimización u
otros) pueden resolverse con una estrategia voraz?
La respuesta es: NO exactamente (aunque hay resultados).
• Sin embargo, existen ciertos indicios… más bien, técnicas de
demostración:
la propiedad de la selección voraz y la existencia de una
subestructura óptima.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 55


Consideraciones sobre la corrección del esquema voraz
• La propiedad de la selección voraz:

– Se verifica esta propiedad cuando una solución globalmente


óptima puede ser alcanzada mediante selecciones localmente
óptimas que son tomadas en cada paso sin depender de las
selecciones futuras;

– en otras palabras, una estrategia voraz progresa de arriba


hacia abajo, tomando una decisión voraz tras otra, reduciendo
iterativamente el problema a otro más pequeño.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 56


Consideraciones sobre la corrección del esquema voraz
• ¿Cómo se comprueba si se verifica la propiedad de la selección
voraz?
– Normalmente, se examina una solución globalmente óptima,
– se trata de demostrar que esa solución puede ser manipulada de forma que
se obtiene tras una primera selección voraz (localmente óptima),
– y esa selección reduce el problema a otro similar pero más pequeño;
– se aplica inducción para demostrar que se puede usar una selección voraz
en cada paso
hay que demostrar que una solución óptima
posee una “subestructura óptima”

• Subestructura óptima:
– Un problema posee una subestructura óptima si una solución óptima de
ese problema incluye soluciones óptimas de subproblemas.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 57


Códigos de Huffman
D.A. Huffman: “A method for the construction of
minimum-redundancy codes”,
Proceedings of the IRE, 40(9), pp. 1098-1101, 1952.
• Los códigos de Huffman son una técnica muy útil para comprimir ficheros.
• El algoritmo voraz de Huffman utiliza una tabla de frecuencias de aparición de cada
carácter para construir una forma óptima de representar los caracteres con códigos
binarios.
• Ejemplo:
– Se tiene un fichero con 100.000 caracteres que se desea comprimir. Las frecuencias de
aparición de caracteres en el fichero son las siguientes:

a b c d e f
aparic. (en miles) 45 13 12 16 9 5

– Puede usarse un código de longitud fija (de 3 bits). El fichero requeriría 300.000 bits.

a b c d e f
cód.long.fija 000 001 010 011 100 101

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 58


Códigos de Huffman
– Puede hacerse mejor con un código de longitud variable, dando codificaciones
cortas a los caracteres más frecuentes y más largas a los
menos frecuentes.

a b c d e f
cód.long.var. 0 101 100 111 1101 1100

Este código ahorra algo más del 25% (requiere 224.000 bits en lugar de 300.000).
• Se precisa un código libre de prefijos:
– Ninguna codificación puede ser prefijo de otra.
– De esta forma, la decodificación es inmediata pues no hay ambigüedades.
– Por ejemplo: ‘001011101’ sólo puede ser ‘aabe’.
• El código se representa mediante un trie (árbol lexicográfico):
– árbol binario cuyas hojas son los caracteres codificados;
– el código de cada carácter es el camino desde la raíz hasta la hoja, donde ir al hijo
izquierdo significa ‘0’ e ir hacia el derecho significa ‘1’.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 59


Códigos de Huffman
• Ejemplo: árboles de los dos códigos anteriores.
100 100
0 1 0 1

86 14 a:45 55
0 1 0 0 1
58 28 14 25 30
0 1 0 1 0 1 0 1 0 1
a:45 b:13 c:12 d:16 e:9 f:5 c:12 b:13 14 d:16
0 1
f:5 e:9
– Cada hoja está etiquetada con un carácter y su frecuencia.
– Cada nodo interno está etiquetado con la suma de los pesos de las hojas de
su subárbol.
– Un código óptimo siempre está representado por un árbol lleno: cada
nodo interno tiene dos hijos.
• Si el alfabeto que se quiere codificar es C, entonces el árbol del código
óptimo tiene |C| hojas y |C| – 1 nodos internos.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 60
Códigos de Huffman
• El algoritmo voraz de Huffman construye el árbol A de
un código óptimo de abajo hacia arriba.
• Utiliza una cola Q de árboles con prioridades (las
frecuencias hacen de prioridades).
• Empieza con un conjunto de |C| hojas en Q y realiza
una secuencia de |C| – 1 “mezclas” hasta crear el árbol
final.
• En cada paso, se “mezclan” los dos objetos (árboles) de
Q que tienen menos frecuencia y el resultado es un
nuevo objeto (árbol) cuya frecuencia es la suma de las
frecuencias de los dos objetos mezclados.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 61


Códigos de Huffman
{Pre: C es un conjunto de caracteres y f es el
vector de frecuencias de esos caracteres}
función Huffman(C:conjunto;f:vectFrec) devuelve árbol
variables Q:colaPri; i,fx,fy,fz:entero; z,x,y:árbol
principio
creaVacía(Q);
para todo x en C hacer
inserta(Q,<x,f[x]>)
fpara;
para i:=1 hasta |C|-1 hacer
<x,fx>:=primero(Q); borra(Q);
<y,fy>:=primero(Q); borra(Q);
fz:=fx+fy;
z:=creaÁrbol(raíz=>fz, hijoIzq=>x, hijoDer=>y);
inserta(Q,<z,fz>)
fpara;
<z,fz>:=primero(Q); borra(Q)
devuelve z
fin
{Post: z es el árbol de un código libre de prefijos óptimo para
(C,f)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 62


Códigos de Huffman
• Para el ejemplo anterior:

f:5 e:9 c:12 b:13 d:16 a:45 c:12 b:13 14 d:16 a:45 (3º) 14 d:16 25 a:45
0 1 0 1 0 1
(1º) (2º) f:5 e:9 f:5 e:9 c:12 b:13

25 30 a:45 a:45 55 100


0 1 0 1 0 1 0 1
c:12 b:13 d:16 (5º)
14 25 30 a:45 55
0 1 0 1 0 1 0 1
(4º) f:5 e:9 (6º)
c:12 b:13 14 d:16 25 30
0 1 0 1 0 1
f:5 e:9 c:12 b:13 14 d:16
0 1
f:5 e:9
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 63
Códigos de Huffman
• Coste temporal:
– inicialización de Q: Θ(|C|) (ejercicio)
– el interior del bucle: Θ(log |C|)
Coste total: Θ(|C|log |C|)
• Corrección: ver que se verifican las propiedades de la selección voraz y
de la subestructura óptima.
• Propiedad de la selección voraz:
– Sea C un alfabeto en el que cada carácter c tiene frecuencia f[c]. Sean x e y
dos caracteres de C con frecuencias mínimas. Entonces existe un código
libre de prefijos óptimo para C en el que las codificaciones de x e y tienen
igual longitud y se diferencian sólo en el último bit.
La idea de la demostración consiste en tomar un árbol que represente un
código libre de prefijos óptimo arbitrario y modificarlo hasta convertirlo en
otro árbol que represente otro código libre de prefijos óptimo y tal que los
caracteres x e y aparezcan como hojas hermanas de máxima profundidad.
Detalles en [CLRS09, pp. 433-434].

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 64


Códigos de Huffman
– Por tanto, el proceso de construir un árbol óptimo mediante mezclas
puede empezar, sin pérdida de generalidad, con la elección voraz de
mezclar los dos caracteres de menor frecuencia.
• Propiedad de la subestructura óptima:
– Sea T un árbol binario lleno que representa un código libre de prefijos
sobre un alfabeto C, con frecuencia f[c] para cada carácter c∈C.
Sean x e y dos caracteres de mínima frecuencia que aparecen como hojas
hermanas en T, y sea z su padre.
Considerando z como un carácter con frecuencia f[z]=f[x]+f[y], el árbol
T’=T–{x,y} representa un código libre de prefijos para el alfabeto
C’=C–{x,y}∪{z}.
Si T’ es óptimo para C’, entonces T es óptimo para C.
La demostración, en [CLRS09, p. 435].
• La corrección del algoritmo se sigue de los dos resultados
anteriores, aplicando inducción.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 65


El problema de la selección de actividades
• Es un problema de planificación de tareas (en inglés,
scheduling).
• Se tiene un conjunto S={1,2,…,n} de actividades (por ej., clases)
que deben usar un recurso (por ej., un aula) que sólo puede ser
usado por una actividad en cada instante.
• Cada actividad i tiene asociado un instante de comienzo ci y un
instante de finalización fi, tales que ci≤fi, de forma que la
actividad i, si se realiza, debe hacerse durante [ci,fi).
• Dos actividades i, j se dicen compatibles si los intervalos [ci,fi) y
[cj,fj) no se superponen (i.e., (ci≥fj)∨(cj≥fi)).
• El problema de selección de actividades consiste en seleccionar
un conjunto de actividades mutuamente compatibles que tenga
cardinal máximo.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 66
El problema de la selección de actividades
• Ejemplos de estrategias voraces (funciones de selección
voraz) para resolver el problema:
– Seleccionar primero la tarea que empieza primero.
– Seleccionar primero la tarea que termina primero.
– Seleccionar primero la tarea más corta.
– Seleccionar primero la tarea menos conflictiva.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 67


El problema de la selección de actividades

constante n=... {número de actividades}


tipo vectReal=vector[1..n] de real

{Pre: ∀i∈1..n:c[i]≤f[i] ∧ ∀i∈1..n-1:f[i]≤f[i+1]}


función selec(c,f:vectReal)devuelve conjunto
variables i,j:entero; A:conjunto
principio
A:={1};
j:=1; {j es la última actividad seleccionada}
para i:=2 hasta n hacer
si c[i]≥f[j]
entonces A:=A∪{i}; j:=i
fsi
fpara;
devuelve A
fin
{Post: A es soluc. óptima del problema de la selección de
actividades.}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 68


El problema de la selección de actividades
• Coste temporal: Θ(n)
Θ(nlog n) si se tiene en cuenta que hay que ordenar primero los vectores.
• Demostración de la corrección:
La actividad 1 tiene el primer instante de finalización. Veamos que existe
una solución óptima que comienza con una selección voraz, es decir, con
la actividad 1.
Supongamos que A⊆S es una solución óptima y que las actividades de A
están ordenadas por tiempos de finalización. Supongamos que la primera
actividad de A es la actividad k.
Si k=1, entonces A empieza con una selección voraz.
Si k≠1, veamos que existe otra solución óptima B que comienza con 1.
Sea B=A–{k}∪{1}. Como f1≤fk, las actividades en B son disjuntas y como
tiene el mismo número de actividades que A entonces B es también óptima.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 69


El problema de la selección de actividades
Después de la selección voraz de la actividad 1, el problema se reduce a
encontrar una solución óptima del problema de selección actividades
sobre las actividades de S que son compatibles con la actividad 1.
Si A’=A–{1} es una solución óptima para el problema S’={i∈S | ci≥f1},
entonces A es una solución óptima para el problema original S.
Trivial, si existiese alguna solución mejor que A para S, las actividades de esa
solución eliminando la tarea 1 serían una solución mejor para S’ que A’.
Por tanto, después de cada selección voraz, nos encontramos con otro
problema de optimización con igual forma que el problema original.
Por inducción sobre el número de selecciones, y realizando una selección
voraz en cada paso, se obtiene una solución óptima. 

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 70


El problema de la minimización del tiempo de espera
• Es otro problema de planificación de tareas.
• Un servidor (por ej., un procesador, un cajero
automático, un surtidor de gasolina, etc.) tiene que
atender n clientes que llegan todos juntos al sistema.
• El tiempo de servicio para cada cliente es ti, i=1,2,…,n.
• Se quiere minimizar:
n
T = Σ tiempo total que el cliente i está en el sistema
i=1

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 71


El problema de la minimización del tiempo de espera
• Ejemplo:

3 clientes con t1=5, t2=10, t3=3.

orden T
1 2 3: 5+ (5+10) + (5+10+3) = 38
1 3 2: 5+ (5+3) + (5+3+10) = 31
2 1 3: 10 + (10+5) + (10+5+3) = 43
2 3 1: 10 + (10+3) + (10+3+5) = 41
3 1 2: 3+ (3+5) + (3+5+10) = 29 óptimo
3 2 1: 3+ (3+10) + (3+10+5) = 34

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 72


El problema de la minimización del tiempo de espera
• Estrategia voraz: Atender en cada paso al cliente no atendido con
menor tiempo de servicio.
• Demostración de la corrección:
Sea I=(i1,i2,…,in) una permutación cualquiera de los naturales {1,2,…,n}.
Si se atiende a los clientes según la secuencia I, el tiempo total que los
clientes están en el sistema es:
T(I) = ti1 + (ti1+ti2) + ((ti1+ti2)+ti3) + ···
= nti1 + (n-1)ti2 + (n-2)ti3 + ···
n
= Σ
k=1
(n-k+1)t ik

Supongamos que I es tal que es posible encontrar dos naturales a y b con


a<b y tia>tib, es decir, que el cliente a-ésimo es atendido antes que el
b-ésimo aunque su tiempo de servicio es mayor.
Si se invierten sus posiciones en I se obtiene una nueva secuencia I’.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 73
El problema de la minimización del tiempo de espera
Entonces: n
T(I’) = (n-a+1)tib + (n-b+1)tia + Σ
k=1
(n-k+1)t ik

k≠a,b

T(I) - T(I’) = (n-a+1)(tia-tib) + (n-b+1)(tib-tia)


= (b-a)(tia-tib)
>0
Es decir, se puede mejorar cualquier secuencia en la que un cliente que
necesita más tiempo sea atendido antes que otro que necesita menos.
Las únicas secuencias que no pueden mejorarse, y por tanto son óptimas,
son aquéllas en las que los clientes están ordenados por tiempos de
servicio decrecientes (todas ellas dan igual tiempo total). 
• Puede generalizarse a s procesadores.
– Se numeran los clientes de forma que t1≤t2≤⋅⋅⋅≤tn.
– El procesador i, 1≤i≤s, atenderá a los clientes i, i+s, i+2s, …

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 74


Fundamentos teóricos del esquema voraz
• Existe una teoría matemática que sirve de base a los algoritmos
voraces:
Teoría de matroides

• Un matroide es un par M=(S,I) tal que:


– S es un conjunto finito no vacío.
– I es una familia no vacía de subconjuntos de S, llamados subconjuntos
independientes, tal que si B∈I y A⊆B, entonces A∈I.
Por cumplir esta propiedad, I se dice hereditaria
(nótese que el conjunto vacío es necesariamente un miembro de I).
– Si A∈I, B∈I y |A|<|B|, entonces existe algún x∈B–A tal que A∪{x}∈I.
Se dice que M satisface la propiedad de intercambio.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 75


Fundamentos teóricos del esquema voraz
• Ejemplos de matroides:
– Dada una matriz de números reales, sea S el conjunto de sus vectores fila,
y considerese que un subconjunto de S es independiente si los vectores
que lo componen son linealmente independientes (en el sentido habitual).

Se llama “matroide matricial” y es el primero que se estudió (H. Whitney,


1935).

– Sea un grafo no dirigido G=(V,A).


Sea MG=(SG,IG), donde:
• SG=A (el conjunto de aristas).
• Si B⊆A, entonces B∈IG si y sólo si B es acíclico.
Se llama “matroide gráfico” y está muy relacionado con el cálculo de
árboles de recubrimiento de coste mínimo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 76


Fundamentos teóricos del esquema voraz
• Sea M=(S,I) y B∈I.
Un elemento x∉B se dice extensión de B si B∪{x}∈I.
– Ejemplo: en un matroide gráfico MG, si B es un conjunto independiente de
aristas, entonces la arista a es una extensión de B si y sólo si a no está en
B y la incorporación de a a B no crea un ciclo.
• Si A es un subconjunto independiente de un matroide M, se dice
que A es maximal si no tiene extensiones.
• Teorema. Todos los subconjuntos independientes maximales de
un matroide tienen el mismo cardinal.
(Dem.: muy fácil [CLRS09, p. 439].)
– Ejemplo: Dado un grafo no dirigido y conexo G, todo subconjunto
independiente maximal de MG es un árbol libre con |V|–1 aristas que
conecta todos los vértices de G.
Ese árbol se llama árbol de recubrimiento de G.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 77


Fundamentos teóricos del esquema voraz
• Un matroide M=(S,I) al que se le asocia una función que asigna
un “peso” estrictamente positivo w(x) a cada x∈S se llama
matroide ponderado.

La función de peso w se extiende a los subconjuntos de S


mediante la suma:

w(A) = ∑ w(x), para todo A⊆S.


x∈A

– Ejemplo: si w(a) denota la longitud de la arista a en un matroide gráfico


MG, entonces w(B) es la longitud total de todas las aristas del subconjunto
de aristas B.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 78


Fundamentos teóricos del esquema voraz
• Voracidad y matroides.

Muchos de los problemas para


los que un algoritmo voraz
calcula la solución óptima
pueden formularse en términos
de “encontrar un subconjunto
independiente de máximo peso
en un matroide ponderado.”

– Es decir, dado un matroide ponderado M=(S,I), se quiere encontrar un


subconjunto A independiente (i.e., A∈I) tal que w(A) sea máximo.
– Un subconjunto independiente y de máximo peso en un matroide
ponderado se llama subconjunto óptimo del matroide.
– Como la función de peso w es positiva, un subconjunto óptimo siempre es
maximal (i.e., no tiene extensiones, ya que aumentar un conjunto siempre
incrementa su peso).
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 79
Fundamentos teóricos del esquema voraz
• Ejemplo: el problema del árbol de recubrimiento de coste mínimo (*).
– Sea un grafo no dirigido y conexo G=(V,A) y una función de longitud w tal que
w(a) es la longitud positiva de la arista a (llamamos longitudes a las etiquetas del
grafo en lugar de pesos por reservar esta palabra para la función definida sobre un
matroide).
– El problema(*) consiste en encontrar un subconjunto de aristas que conecte todos
los vértices del grafo y tenga longitud mínima.
– Considerar MG y la función de peso w’ definida como: w’(a) = w0 – w(a), donde
w0 es un valor mayor que la longitud de todas las aristas.
– En este matroide ponderado, todos los pesos son positivos y un subconjunto
óptimo es precisamente un árbol de recubrimiento del grafo original con longitud
total mínima.
– Más específicamente, cada subconjunto independiente maximal B corresponde a
un árbol de recubrimiento, y puesto que
w’(B) = (|V| – 1)w0 – w(B)
para todo subconjunto independiente maximal B, el subconjunto independiente
que maximiza w’(B) debe minimizar w(B).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 80


Fundamentos teóricos del esquema voraz
• Algoritmo voraz de cálculo de un subconjunto óptimo
en un matroide arbitrario:
{Pre: S y la función indep definen un matroide;
w es una función de peso positiva sobre S}
función voraz(S:conjunto) devuelve conjunto
variable A:conjunto
principio
A:=Ø;
ordenar S por valores decrecientes del peso w;
para todo x en S tomado en orden decreciente de w(x) hacer
si indep(A∪{x}) entonces
A:=A∪{x}
fsi
fpara;
devuelve A
fin
{Post: A es subconjunto óptimo de (S,indep,w)}

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 81


Fundamentos teóricos del esquema voraz
• Eficiencia temporal:
Denotando |S| como n,
• fase de ordenación: Θ(nlog n)
• bucle: Θ(n f(n)), suponiendo que el coste de evaluar la función
indep es Θ(f(n))

Total: Θ(nlog n + n f(n))

• Corrección:
Teorema 16.11 en [CLRS09, pp. 441-442]
(un par de páginas; sin gran dificultad).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 82


Fundamentos teóricos del esquema voraz
• Utilidad fundamental:

Dados un problema y una solución voraz,

para demostrar la corrección de esa solución basta con

identificar una estructura


de matroide subyacente al
problema

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 83


Fundamentos teóricos del esquema voraz
• Resumen:
– La teoría de matroides no cubre todos los problemas en los
que el esquema voraz calcula la solución óptima.
– Sin embargo cubre muchos casos interesantes (por ej., árboles
de recubrimiento de coste mínimo).
– Más aún, se ha demostrado que una estructura es un matroide
si y sólo si el esquema voraz calcula para ella una solución
óptima sea cual sea la función de peso escogida
(la demostración puede verse en pp. 13-18 de
[Koz92] D.C. Kozen. The Design and Analysis of Algorithms. Springer-
Verlag, 1992.)
– La investigación continúa…

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 84


Un problema de planificación de tareas a plazo fijo
• Se tiene un conjunto S={1,2,…,n} de tareas de duración
unidad.
• En cada instante, sólo se puede realizar una tarea.
• La tarea i, 1≤i≤n, debe terminarse antes del instante (o
plazo) di, con 1≤di≤n.
• Hay una penalización wi, 1≤i≤n, si la tarea i no termina
antes de su plazo.
• Se trata de encontrar una secuencia de realización de las
tareas que minimice la penalización total.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 85


Un problema de planificación de tareas a plazo fijo
• Una tarea en una secuencia se dice puntual si termina antes de
su plazo, y tardía si lo hace después de su plazo.
• Una secuencia está en forma “puntuales primero” si todas las
tareas puntuales están antes de las tardías.
• Cualquier secuencia puede transformarse en forma puntuales
primero (manteniendo la penalización).
En efecto, si una tarea puntual x va detrás de una tarea tardía y, pueden
intercambiarse sus posiciones de forma que x sigue siendo puntual e y
tardía.
• Una secuencia está en forma canónica si está en forma
puntuales primero y las tareas puntuales están ordenadas por
valores crecientes de sus plazos.
• Cualquier secuencia puede transformarse en forma canónica
(manteniendo la penalización).
Argumentación similar a la anterior.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 86
Un problema de planificación de tareas a plazo fijo
• Encontrar una secuencia óptima es encontrar un subconjunto A
de tareas que sean puntuales en la secuencia óptima.
• Una vez encontrado A, la secuencia se crea ordenando los
elementos de A por plazos crecientes y a continuación las tareas
tardías (en S – A) en cualquier orden.
• Decimos que un subconjunto A de tareas es independiente si
existe una ordenación de las mismas en la que ninguna es tardía.
Por ejemplo, el conjunto de tareas puntuales de una secuencia es un
conjunto independiente.
• Denotamos con I el conjunto de todos los subconjuntos
independientes de tareas.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 87


Un problema de planificación de tareas a plazo fijo
• Sea Nt(A), t=1,…,n, el nº de tareas de A cuyo plazo es menor o igual que t.
• Lema. Sea A un conjunto de tareas. Son equivalentes:
1. A es independiente.
2. Nt(A)≤t, para t=1,…,n.
3. Si las tareas de A se ordenan por plazos crecientes, entonces ninguna tarea es
tardía.
Dem.: (1)⇒(2) Si Nt(A)>t para algún t, entonces no hay forma de construir una
secuencia con las tareas de A de forma que ninguna sea tardía.
(2)⇒(3) El i-ésimo plazo mayor es como mucho i. Por tanto, ordenando las tareas
por plazos crecientes, no hay forma de que alguna tarea sea tardía.
(3)⇒(1) Trivial. 
• Corolario. La propiedad (2) del lema anterior sirve para decidir en tiempo
O(|A|) si un conjunto de tareas es independiente.
Dem.: Ejercicio
(suponer las tareas sin ordenar previamente; puede usarse espacio adicional O(|A|)).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 88


Un problema de planificación de tareas a plazo fijo
• El problema de minimizar la suma de penalizaciones de las
tareas tardías de una secuencia es el mismo que el de maximizar
la suma de penalizaciones de sus tareas puntuales.
• Teorema. Si S es un conjunto de tareas de duración unidad con
penalizaciones e I es el conjunto de todos los conjuntos
independientes de tareas, entonces (S,I) es un matroide.
Dem.: Es claro que todo subconjunto de un conjunto independiente de tareas
es también independiente.
Para demostrar la propiedad del intercambio, supongamos que B y A son
conjuntos independientes de tareas con |B|>|A|.
Sea k el mayor t tal que Nt(B)≤Nt(A).
Como Nn(B)=|B| y Nn(A)=|A|, se sigue que k<n y que Nj(B)>Nj(A) para
todo j tal que k+1≤j≤n.
Por tanto, B tiene más tareas con plazo k+1 que A.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 89


Un problema de planificación de tareas a plazo fijo
Sea x una tarea de B\A con plazo k+1.
Sea A’=A∪{x}.
Demostramos ahora que A’ es independiente usando la propiedad (2) del
Lema anterior.
Como A es independiente, Nt(A’)=Nt(A)≤t, para 1≤t≤k.
Como B es independiente, Nt(A’)≤Nt(B)≤t, para k<t≤n.
Por tanto, A’ es independiente. 
• Corolario. Se puede utilizar un algoritmo voraz para encontrar
un conjunto independiente de tareas A con penalización máxima.
• A continuación, se puede crear una secuencia óptima que tiene
como tareas puntuales las de A.
• Tiempo de ejecución: O(n2)
¿Por qué?

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 90


Heurísticas voraces: Coloreado de grafos
• A veces se utilizan algoritmos voraces a pesar de que no calculan
soluciones óptimas:
– bien porque el cálculo de una solución óptima es demasiado costoso,
– bien porque el algoritmo voraz calcula un solución “subóptima” que
resulta suficiente.
• Problema del coloreado de un grafo.
– Sea G=(V,A) un grafo no dirigido cuyos vértices se desea colorear.
– Se exige que todo par de vértices unidos por una arista tengan asignados
colores diferentes.
– Se pretende emplear el menor número posible de colores.
3

1 2 5

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 91


Heurísticas voraces: Coloreado de grafos
– Algoritmo voraz de coloreado de un grafo:
• escoger inicialmente un color y un vértice arbitrario como punto de
partida;
• tratar de asignarle ese color al mayor número posible de vértices,
respetando la restricción impuesta (vértices adyacentes deben tener
distinto color);
• escoger otro vértice aún no coloreado y un color distinto y repetir el
proceso hasta haber coloreado todos los vértices.

– Aplicado al ejemplo anterior, se obtiene la solución óptima:


dos colores.
3

1 2 5

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 92


Heurísticas voraces: Coloreado de grafos
– Sin embargo, tomando el mismo grafo pero ordenando los
vértices de otra forma, 1,5,2,3,4, el algoritmo voraz colorearía
1 y 5 de un color, 2 en otro, y necesitaría un tercer color para
3 y 4.
3

1 2 5

– Por tanto es un algoritmo heurístico que tiene la


posibilidad, pero no la certeza, de encontrar la solución
óptima.
– Todos los algoritmos exactos conocidos para el problema del
coloreado de un grafo emplean un tiempo exponencial, de ahí
la utilidad de la heurística voraz.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 93
Heurísticas voraces: El problema del viajante de comercio
• El problema del viajante de comercio
consiste en encontrar un recorrido de
longitud mínima para un viajante que
tiene que visitar varias ciudades y
volver al punto de partida, conocida
la distancia existente entre cada dos
ciudades.

• En términos matemáticos es el
problema del cálculo del hamiltoniano
de longitud mínima.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 94


Heurísticas voraces: El problema del viajante de comercio
• Ejemplo:
Cinco cabinas de teléfonos, b, c, d, e, f, para las que se conocen sus
coordenadas relativas a la central telefónica, a, desde la que parten los
recolectores y a donde deben regresar al terminar, y se supone que la
distancia entre cada dos viene dada por la línea recta.

c (1,7) d (15,7)
e (15,4)
b (4,3)
a (0,0) f (18,0)

a
b 5
c 7,07 5
d 16,55 11,70 14
e 15,52 11,05 14,32 3
f 18 14,32 18,38 7,6 5
distan. a b c d e f
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 95
Heurísticas voraces: El problema del viajante de comercio

• El algoritmo de fuerza bruta para resolver el problema


consiste en intentar todas las posibilidades, es decir,
calcular las longitudes de todos los recorridos posibles, y
seleccionar la de longitud mínima (veremos una solución
algo mejor mediante programación dinámica).
• Obviamente, el coste de tal algoritmo crece
exponencialmente con el número de puntos a visitar.
• En el ejemplo anterior, la solución viene dada por el
siguiente recorrido (en realidad dos recorridos, pues ambos
sentidos de marcha son posibles) de longitud 48,39:
c d
b e
a f

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 96


Heurísticas voraces: El problema del viajante de comercio
• Heurística voraz:
Ir seleccionando parejas de puntos que serán visitados de forma consecutiva:
– se seleccionará primero aquella pareja de puntos entre los que la distancia
sea mínima;
– a continuación, se selecciona la siguiente pareja separada con una
distancia mínima siempre que esta nueva elección no haga que:
• se visite un punto dos veces o más (es decir, que el punto aparezca tres o más
veces en las parejas de puntos seleccionadas), o
• se cierre un recorrido antes de haber visitado todos los puntos.

De esta forma, si hay que visitar n puntos (incluido el origen), se


selecciona un conjunto de n parejas de puntos (que serán visitados de
forma consecutiva) y la solución consiste en reordenar todas esas parejas
de forma que constituyan un recorrido.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 97


Heurísticas voraces: El problema del viajante de comercio
• En el ejemplo anterior:
– Las parejas ordenadas por distancia entre sus puntos son: (d,e), (a,b),
(b,c), (e,f), (a,c), (d,f), (b,e), (b,d), (c,d), (b,f), (c,e), (a,e), (a,d), (a,f) y
(c,f).
– Se selecciona primero la pareja (d,e) pues la distancia entre ambos puntos
es mínima (3 unidades).
(d,e)
– Después se seleccionan las parejas (a,b), (b,c) y (e,f). La distancia es para
todas ellas igual (5 unidades).
(d,e), (a,b), (b,c), (e,f)
– La siguiente pareja de distancia mínima es (a,c), con longitud 7,07.
Sin embargo, esta pareja cierra un recorrido junto con otras dos ya
seleccionadas, (b,c) y (a,b), por lo que se descarta.
– La siguiente pareja es (d,f) y se descarta también por motivos similares.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 98


Heurísticas voraces: El problema del viajante de comercio
(d,e), (a,b), (b,c), (e,f)
– La siguiente es la pareja (b,e), pero debe rechazarse también porque su
inclusión haría visitar más de una vez los puntos b y e.
– La pareja (b,d) se rechaza por motivos similares (el punto b habría que
visitarlo dos veces).
– La siguiente pareja es (c,d), y se selecciona.
(d,e), (a,b), (b,c), (e,f), (c,d)
– Las parejas (b,f), (c,e), (a,e) y (a,d) no son aceptables.
– Finalmente, la pareja (a,f) cierra el recorrido:
c d
b e
f
a
– Este recorrido no es el óptimo pues su longitud es de 50 unidades.
No obstante, es el 4º mejor recorrido de entre los sesenta (esencialmente
distintos) posibles y es más costoso que el óptimo en sólo un 3,3%.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 99
Divide y vencerás

Este documento está sujeto a una licencia de uso Creative


Algoritmia básica - Javier Campos (Universidad de Zaragoza) Commons. No se permite un uso comercial de la obra
original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Divide y vencerás
• Introducción 3
• La búsqueda dicotómica 9
• La ordenación por fusión 14
• El algoritmo de ordenación de Hoare 16
• Algoritmos de selección y de búsqueda de la mediana 19
• Multiplicación de enteros grandes 23
• Potenciación de enteros 30
• Introducción a la criptografía 37
• Multiplicación de matrices 48
• Calendario de un campeonato 53

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 2


El esquema divide y vencerás: Introducción
• Técnica de diseño de algoritmos “divide y vencerás”:

– descomponer el ejemplar a resolver en un cierto número de


subejemplares más pequeños del mismo problema;
– resolver independientemente cada subejemplar;
– combinar los resultados obtenidos para construir la solución
del ejemplar original.

aplicar esta técnica recursivamente

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 3


El esquema divide y vencerás: Introducción
• Esquema genérico:
función divide_y_vencerás(x:tx) devuelve ty
variables x1,…,xk:tx; y1,…,yk:ty
principio
si x es suficientemente simple entonces
devuelve solución_simple(x)
sino
descomponer x en x1,…,xk;
para i:=1 hasta k hacer
yi:=divide_y_vencerás(xi)
fpara;
devuelve combinar(y1,…,yk)
fsi
fin

• Si k=1, el esquema anterior se llama técnica de


reducción.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 4


El esquema divide y vencerás: Introducción
• Sobre el coste computacional:
– Sea un algoritmo A que emplea un tiempo cuadrático.
– Sea c una constante tal que una implementación particular de
A emplea un tiempo

tA(n)≤cn2

para un ejemplar de tamaño n.


– Supongamos que A se puede descomponer en tres
subejemplares de tamaño n/2, resolverlos y combinar su
resultados para resolver A.
– Sea d una constante tal que el tiempo empleado en la
descomposición y combinación es t(n)≤dn.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 5


El esquema divide y vencerás: Introducción
– La utilización de esta partición da lugar a un nuevo algoritmo B con un
tiempo: tB (n) = 3tA (n / 2)+ t(n)
2
 n + 1
≤ 3c  + dn
 2 
3 3  3
= cn2 +  c+ d n + c
4 2  4

– Luego B es un 25% más rápido que A.


– Si se aplica a B la misma técnica de descomposición se obtiene un
algoritmo C con tiempo:
 tA (n) si n ≤ n0
tC (n) = 
 3tC (n / 2)+ t(n) en otro caso

– Donde tA(n) es el tiempo del algoritmo simple, n0 es el umbral por


encima del cual el algoritmo se usa recursivamente y t(n) el tiempo de la
descomposición y combinación.
– La solución de la ecuación en recurrencias da un tiempo para el algoritmo
C de nlog 3 ≈ n1,59.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 6


El esquema divide y vencerás: Introducción
• Recordar…

una de las ecuaciones en recurrencias especialmente útil para el


análisis de algoritmos de divide y vencerás:

– La solución de la ecuación

T(n) = aT(n/b) + Θ(nklogpn)

con a≥1, b>1, p≥0 es

O (nlogb a), si a > bk



T (n) ∈ O (nk logp + 1n), si a = bk
O (nk logp n), si a < bk

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 7


El esquema divide y vencerás: Introducción
• Sobre el cálculo del umbral óptimo:
– Es un problema complejo.
– Para un mismo problema, varía con la implementación
concreta y varía con el valor de n.
– Puede estimarse empíricamente (tablas,…)...
– ... o teóricamente: calculando el n para el que la solución
recursiva y la solución simple tienen igual coste; por ejemplo,
si tA(n)=n2 y t(n)=16n:

t A (n) = 3tA (n / 2) + t(n)

da un valor de n0≈64 (ignorando los redondeos).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 8


La búsqueda dicotómica
• Problema:
– Dado T[1..n] vector ordenado crecientemente y dado x, encontrar x en T, si es que
está.
– Formalmente: encontrar un natural i tal que
0≤i≤n y T[i]≤x<T[i+1], con el convenio de que
T[0]= – ∞ y T[n+1]= ∞ (centinelas).
– Solución secuencial evidente:
función secuencial(T:vector[1..n]de dato; x:dato) devuelve 0..n
variables i:0..n+1; parar:booleano
principio
i:=1; parar:=falso;
mq (i≤n) and not parar hacer
si T[i]>x entonces parar:=verdad sino i:=i+1 fsi
fmq;
devuelve i-1
fin Coste caso promedio y caso peor: Θ(n)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 9


La búsqueda dicotómica
• Búsqueda dicotómica (alg. de reducción, puesto que k=1):
función dicotómica(T:vector[1..n]de dato; x:dato) devuelve 0..n
principio
si (n=0) or (x<T[1]) entonces devuelve 0
sino devuelve dicotRec(T,1,n,x)
fsi
fin

función dicotRec(T:vector[1..n]de dato; i,d:1..n; x:dato) dev. 1..n


{búsqueda dicotómica de x en T[i..d]; Pre: T[i]≤x<T[d+1], i≤d}
variable k:1..n
principio
si i=d entonces devuelve i
sino
k:=(i+d+1) div 2;
si x<T[k] ent devuelve dicotRec(T,i,k-1,x)
sino devuelve dicotRec(T,k,d,x)
fsi
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 10


La búsqueda dicotómica
• Versión iterativa:
función dicotIter(T:vector[1..n]de dato; x:dato) devuelve 0..n
variables i,d,k:1..n
principio
si (n=0) or (x<T[1]) entonces devuelve 0
sino
i:=1; d:=n;
mq i<d hacer {T[i]≤x<T[d+1]}
k:=(i+d+1) div 2;
si x<T[k]
entonces d:=k-1
sino i:=k
fsi
fmq;
devuelve i
Coste: Θ(log n), en todos los casos.
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 11


La búsqueda dicotómica
• Mejora aparente:
función dicotIter2(T:vector[1..n]de dato; x:dato) devuelve 0..n
variable i,d,k:1..n
principio
si (n=0) or (x<T[1]) entonces devuelve 0
sino
i:=1; d:=n;
mq i<d hacer {T[i]≤x<T[d+1]}
k:=(i+d) div 2;
si x<T[k] entonces d:=k-1
sino
si x≥T[k+1] entonces i:=k+1
sino i:=k; d:=k
fsi
fsi
fmq;
devuelve i
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 12


La búsqueda dicotómica
• La mejora es sólo aparente:
– el primer algoritmo realiza siempre Θ(log n) iteraciones mientras que el
segundo puede parar antes;
– cálculo del número medio de iteraciones suponiendo que:
• todos los elementos de T son distintos,
• x está en T,
• cada posición tiene igual probabilidad de contener a x
[BB90] G. Brassard y P. Bratley. Algorítmica. Concepción y análisis. Masson,
S.A., 1990. pp. 116-119. 3
Iter 1 (n) ≅ Iter2 (n) +
2
– Es decir, el 1er algoritmo realiza, en media, 1’5 iteraciones más que el 2º.
– Pero, cada iteración del 2º es ligeramente más costosa que la del 1º.
Son difícilmente comparables.
Si n es suficientemente grande, el 1er algoritmo es mejor que el 2º.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 13


La ordenación por fusión
• Dado un vector T[1..n] de n elementos dotados de una relación de orden total,
se trata de ordenar de forma creciente esos elementos.
• Técnica de divide y vencerás más sencilla: Ojo: usamos notación de
vectores pero el algoritmo es
– dividir el vector en dos mitades; especialmente adecuado para
– ordenar esas dos mitades recursivamente; listas y para ficheros.

– fusionarlas (o mezclarlas) en un solo vector ordenado.


algoritmo ordFusión(e/s T:vect[1..n]de dato)
variables U:vect[1..(n div 2)]de dato;
V:vect[1..((n+1) div 2)]de dato
principio
si n es pequeño entonces ordInserción(T)
sino
U:=T[1..(n div 2)];
V:=T[(n div 2 + 1)..n];
ordFusión(U);
ordFusión(V);
fusión(T,U,V)
fsi
fin {método denominado “mergesort”}
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 14
La ordenación por fusión
• Coste de ejecución:
– la descomposición de T en U y V precisa un tiempo lineal;
– la fusión de U y V también necesita un tiempo lineal;
– por tanto, si t(n) es el tiempo de ejecución del algoritmo para ordenar n
elementos,
( ) (
t (n) ∈t n / 2 + t n / 2 + Θ (n) )
es decir, t(n)∈Θ(nlog n)

• Además:
La fusión de T[1..k] y T[k+1..n] (ya ordenados) en el mismo T[1..n] puede
hacerse en tiempo lineal utilizando sólo una cantidad fija de variables
auxiliares (independiente de n).
(Ejercicio 18 de la sección 5.2.4 de [Knu87] D.E. Knuth. El arte de programar
ordenadores. Volumen III: Clasificación y búsqueda. Editorial Reverté, 1987,
“nivel [40]” => “realmente difícil o largo”… ver artículo en “material adicional”.)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 15


El algoritmo de ordenación de Hoare

C.A.R. Hoare: “Quicksort”,


Computer Journal, 5(1), pp. 10-15, 1962.

algoritmo ordRápida(e/s T:vect[1..n]de dato; ent iz,de:1..n)


{Ordenación de las componentes iz..de de T.}
variable me:1..n
principio
si de-iz es pequeño
entonces ordInserción(T,iz,de)
sino
divide(T,iz,de,me);
{iz≤k<me ⇒ T[k]≤T[me] ∧ me<k≤de ⇒ T[k]>T[me]}
ordRápida(T,iz,me-1);
ordRápida(T,me+1,de)
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 16


El algoritmo de ordenación de Hoare
algoritmo divide(e/s T:vect[1..n]de dato; ent iz,de:1..n; sal me:1..n)
{Permuta los elementos iz..de de T de forma que:
iz≤me≤de,
∀k t.q. iz≤k<me: T[k]≤p,
T[me]=p,
∀k t.q. me<k≤de: T[k]>p,
p se llama pivote y es, por ejemplo, el valor inicial de T[iz]. }
variables p:dato; k:1..n
principio
p:=T[iz];
k:=iz; me:=de+1;
repetir k:=k+1 hasta que (T[k]>p)or(k≥de);
repetir me:=me-1 hasta que (T[me]≤p);
mq k<me hacer
intercambiar(T[k],T[me]);
repetir k:=k+1 hasta que T[k]>p;
repetir me:=me-1 hasta que T[me]≤p
fmq;
intercambiar(T[iz],T[me])
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 17


El algoritmo de ordenación de Hoare
• Coste en el peor caso: cuadrático
(si la elección del pivote no es adecuada, los subejemplares
no tienen tamaño parecido…)

• Coste promedio: O(n log n)


Dem.: [BB97, pp. 264-266]

(la constante multiplicativa es menor que en los otros


algoritmos de ordenación que hemos visto cuyo coste en el
caso peor es O(n log n): mergesort y heapsort)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 18


Algoritmos de selección y de búsqueda de la mediana
• Dado un vector T[1..n] de enteros, la mediana de T es un
elemento m de T que tiene tantos elementos menores como
mayores que él en T:

{i ∈[1..n]| T [i ]< m} < n / 2, y

{i ∈[1..n]| T [i ]> m}≤ n / 2

(nótese que la definición formal es más general: n puede ser par y además
puede haber elementos repetidos, incluida la mediana)

Primera solución:
– Ordenar T y extraer el elemento n/2-ésimo.
– Tiempo Θ(n log n).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 19


Algoritmos de selección y de búsqueda de la mediana
• Problema más general: la selección (o cálculo de los estadísticos de orden).
Dado un vector T de n elementos y 1≤k≤n, el k-ésimo menor elemento de T
es aquel elemento m de T que satisface:

{i ∈[1..n]| }
T[i ]< m < k , y

{i ∈[1..n]| T[i ]≤ m ≥ k }
Es decir, el elemento en posición k si T estuviese ordenado crecientemente.

• Por tanto, la mediana de T es el n/2-ésimo menor elemento de T.

• Solución del problema: inspirada en el algoritmo de ordenación de Hoare


(pero ahora sólo se resuelve uno de los subejemplares).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 20


Algoritmos de selección y de búsqueda de la mediana
función seleccionar(T:vector[1..n]de dato; k:1..n) devuelve dato
principio
devuelve selRec(T,1,n,k)
fin

función selRec(T:vector[1..n]de dato; i,d,k:1..n) devuelve dato


principio
si d-i es pequeño entonces ordInserción(T,i,d); devuelve T[k]
sino
divide(T,i,d,m);
si m-i+1≥k entonces selRec(T,i,m,k)
sino selRec(T,m+1,d,k-(m-i+1))
fsi
fsi
fin

algoritmo divide(e/s T:vect[1..n]de dato; ent i,d:1..n; sal m:1..n)


{Permuta los elementos i..d de T de forma que:
i≤m≤d; ∀k t.q. i≤k<m: T[k]≤p; T[m]=p; ∀k t.q. m<k≤d: T[k]>p;
p es, por ejemplo, el valor inicial de T[i]. }

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 21


Algoritmos de selección y de búsqueda de la mediana
• Como en el método de ordenación de Hoare, una elección
desafortunada del pivote conduce en el caso peor a un tiempo
cuadrático.

• No obstante, el coste promedio es lineal.

• Existe una mejora que permite un coste lineal también en el peor


caso [CLRS09], aunque en la práctica, en muchos casos, se
comporta mejor el algoritmo anterior.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 22


Multiplicación de enteros grandes
• Coste de realizar las operaciones elementales de suma y
multiplicación:
– Es razonable considerarlo constante si los operandos son directamente
manipulables por el hardware, es decir, no son muy grandes.
– Si se necesitan enteros muy grandes, hay que implementar por software
las operaciones.

• Enteros muy grandes:


– Representación de un entero de n cifras: puede hacerse en un vector con
un espacio en O(n) bits.
– Operaciones de suma, resta: pueden hacerse en tiempo lineal.
– Operaciones de multiplicación y división entera por potencias positivas
de 10: pueden hacerse en tiempo lineal (desplazamientos de las cifras).
– Operación de multiplicación con el algoritmo clásico (o con el de
multiplicación rusa): tiempo cuadrático.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 23
Multiplicación de enteros grandes
A. Karatsuba e Y. Ofman:
“Multiplication of multidigit numbers on automata”,
Dokl. Akad. Nauk SSSR, 145, pp. 293-294, 1962.

• Algoritmo de Karatsuba: Técnica de divide y vencerás para la


multiplicación de enteros muy grandes.
– Sean u y v dos enteros de n cifras.
– Se descomponen en mitades de igual tamaño:
u = 10s w + x s s
s  con 0≤ x < 10 , 0≤ z < 10 , y
v = 10 y + z 
s = n 2

– Por tanto, w e y tienen n/2 cifras n


u w x
v y z
n/2 n/2

– El producto es:
uv = 102s wy + 10s (wz+ xy) + xz

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 24


Multiplicación de enteros grandes

función mult(u,v:granEnt) devuelve granEnt


variables n,s:entero; w,x,y,z:granEnt
principio
n:=máx(tamaño(u),tamaño(v));
si n es pequeño
entonces devuelve multClásica(u,v)
sino
s:=n div 2;
w:=u div 10s; x:=u mod 10s;
y:=v div 10s; z:=v mod 10s;
devuelve mult(w,y)*102s + (mult(w,z)+mult(x.y))*10s + mult(x,z)
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 25


Multiplicación de enteros grandes
• Coste temporal:
– Las sumas, multiplicaciones por potencias de 10 y divisiones por
potencias de 10: tiempo lineal.
– Operación módulo una potencia de 10: tiempo lineal (puede hacerse con
una división, una multiplicación y una resta).
– Por tanto, si t(n) es el tiempo del algoritmo:

( ) ( )
t (n) = 3t n 2 + t n 2 + Θ (n)

Si n se supone potencia de 2,

( )
t (n) = 4t n 2 + Θ(n)

La solución de esta recurrencia es:

t (n) ∈O (n 2)

¿¡Y no hemos ganado nada!?


Algoritmia básica - Javier Campos (Universidad de Zaragoza) 26
Multiplicación de enteros grandes
– Truco: calcular wy, wz+xy, y xz haciendo menos de cuatro
multiplicaciones.
Teniendo en cuenta que:
r = (w + x)(y + z) = wy + (wz + xy)+ xz

función mult2(u,v:granEnt) devuelve granEnt


variables n,s:entero; w,x,y,z,r,p,q:granEnt
principio
n:=máx(tamaño(u),tamaño(v));
si n es pequeño entonces devuelve multClásica(u,v)
sino
s:=n div 2;
w:=u div 10s; x:=u mod 10s;
y:=v div 10s; z:=v mod 10s;
r:=mult2(w+x,y+z);
p:=mult2(w,y); q:=mult2(x,z);
devuelve p*102s+(r-p-q)*10s+q
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 27


Multiplicación de enteros grandes
• Eficiencia temporal de la versión 2:
– Teniendo en cuenta que w+x e y+z pueden necesitar 1+n/2 cifras,

( ) ( ) ( )
t 2 (n) ∈t2 n 2 + t2 n 2 + t2 1+ n 2 + Θ(n)

Y por tanto,

( ) (
t 2 (n) ∈Θ nlog 3 ∈O n 1,59 )
– Debido a la constante multiplicativa, el algoritmo sólo es interesante en la
práctica para n grande.
– Una buena implementación no debe usar la base 10 sino la base más
grande posible que permita multiplicar dos “cifras” (de esa base)
directamente en hardware.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 28


Multiplicación de enteros grandes
– La diferencia entre los órdenes n2 y n1,59 es menos espectacular que la existente
entre n2 y nlog n.
– Ejemplo realizado en un computador en base 220:
(que permite multiplicar directamente números de 20 dígitos binarios)
• Multiplicación de números de unas 602 cifras (base decimal):
algoritmo clásico: 400 milisegundos
algoritmo mult2: 300 milisegundos
• Multiplicaciones de números de unas 6000 cifras (base decimal):
algoritmo clásico: 40 segundos
algoritmo mult2: 15 segundos
– Descomponiendo los operandos en más de dos partes se puede lograr la
multiplicación de dos enteros en un tiempo del orden de nα, para
cualquier α>1.
– Descomponiendo los operandos en n1/2 partes y usando la transformada de
Fourier, se pueden multiplicar dos enteros de n cifras en un tiempo
O(n log n loglog n) (algoritmo Schönhage–Strassen, 1971) o incluso en
n log n 2O(log* n) (algoritmo de Martin Fürer, 2007).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 29


Potenciación de enteros
• Problema: Dados los enteros positivos a y n,
se trata de calcular an.
• Solución ingenua:
función pot0(a,n:entero) devuelve entero
{Devuelve an}
variables r,i:entero
principio
r:=1;
para i:=1 hasta n hacer
r:=r*a
fpara;
devuelve r
fin

– Si se añade al final la operación mod z, sirve para calcular an mod z (útil


por ejemplo para implementar el algoritmo RSA de criptografía).
– Si “r:=r*a” se considera “operación elemental”, el coste está en Θ(n).
Pero NO es así (p.e., 1517 no cabe en 8 bytes).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 30


Potenciación de enteros
• Inconvenientes de esta solución:
– Su coste (el bucle se ejecuta n veces).
Si se quiere aplicar a un entero a grande (de m cifras), el coste es
prohibitivo.
Θ(m2n2), si se usa el algoritmo clásico de multiplicar.
nº cifras(r1)=m (r1 denota r tras el 1er paso)
nº cifras(ri+1)=m+mi ⇒ nº cifras(ri+1)=i m
n− 1
coste = ∑ M (m ,i m)
i =1

Método clásico de multiplicar


n− 1 n− 1
⇒ coste = ∑cmim = cm2 ∑i = cm2n2
i =1 i =1

Θ(mlog 3n2), si se usa el algoritmo de divide y vencerás para multiplicar.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 31


Potenciación de enteros
• Existe un algoritmo más eficiente para la potenciación de
enteros.
Por ejemplo, con dos multiplicaciones y elevar al cuadrado cuatro veces
se obtiene:
2
 2
2
( )
x 25 =   x 2x   x
  
Nótese que reemplazando en
2
 
2 
( )
2
x =   x × x × 1 × 1 × x
25 2
  
cada x por un 1 y cada 1 por un 0, se obtiene la secuencia de bits 11001
(expresión binaria de 25).

( );
2
En otras palabras, x 25 = x24x ; x24 = x12 etc

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 32


Potenciación de enteros
• Un algoritmo de eficiencia aceptable:

función pot(a,n:entero) devuelve entero


{Devuelve an}
variable r:entero
principio
si n=0 entonces devuelve 1
sino
si n es impar entonces
r:=pot(a,n-1); Es un algoritmo de reducción.
devuelve a*r
sino
r:=pot(a,n/2);
Igual que antes, se puede añadir
devuelve r*r al final la operación mod z
fsi si interesa calcular an mod z.
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 33


Potenciación de enteros
• Sobre la eficiencia de este algoritmo:

– Tiempo O(h(n) × M(z))


• h(n) = nº de multiplicaciones
• M(z) = cota del tiempo para multiplicar dos enteros menores que z (y
calcular el módulo, si se precisa para implementar el RSA, por
ejemplo).
– Es claro que:
0 si n = 0

h(n) = 1+ h(n − 1) si n es impar

1+ h(n / 2) en otro caso

Y, por tanto, h(n) es logarítmico en n.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 34


Potenciación de enteros
• Una versión iterativa:

función potIter(a,n:entero) devuelve entero


{Devuelve an}
variable i,x,r:entero
principio
i:=n; x:=a; r:=1;
mq i>0 hacer
si i es impar entonces r:=r*x fsi;
x:=x*x;
i:=i div 2
fmq;
devuelve r
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 35


Potenciación de enteros
• Comentarios finales:
– Ni la versión recursiva ni la iterativa del algoritmo de potenciación
presentadas aquí son las óptimas, pero ambas son razonablemente
buenas.
– Añadiendo en ambos algoritmos los cálculos “mod z”, se obtienen
algoritmos para elevar un entero a a otro n módulo z.
Su eficiencia depende, obviamente, del algoritmo que se utilice para
multiplicar enteros grandes.
– Si a, n y z son números de 200 cifras:
• el algoritmo potIter puede calcular an mod z en menos de 1 segundo,
• el algoritmo ingenuo pot0 requeriría del orden de 10179 veces la edad del
Universo.

Suponiendo que dos enteros de 200 cifras se multiplican en 1 milisegundo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 36


Introducción a la criptografía
• El problema:
Eva fue un día al teatro con su vecina Alicia y allí
le presentó a ésta a su amigo Roberto.

Por razones que no vienen al caso, Alicia decide


enviar a Roberto un mensaje secreto.
Desea hacerlo en una conversación telefónica, pero ésta puede ser
escuchada por Eva.
Eva puede escuchar la información que circula por la línea pero no puede
introducir mensajes ni modificar los que circulan.

Por supuesto, Alicia no desea que Eva


tenga acceso a sus secretos.
Se trata de encontrar un método que
permita a Alicia conseguir su objetivo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 37


Introducción a la criptografía
• La solución clásica (¡usada durante siglos!):
– Alicia y Roberto, previamente y en secreto, se han puesto de acuerdo en
una clave k.
– Usando la clave k, Alicia puede cifrar su mensaje m, obteniendo el
mensaje cifrado c.
– Roberto, al recibir el mensaje c, utiliza la clave k para descifrarlo y
obtener el mensaje original m.
– Si Eva intercepta c, como no conoce la clave k, no podrá reconstruir el
mensaje m.

• Problema actual: telecomunicaciones


– Dos ciudadanos necesitan enviarse un mensaje cifrado mediante correo
electrónico por internet pero no pueden verse previamente en secreto para
acordar una clave k.
¡Este problema no se resolvió hasta los años 70!
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 38
Introducción a la criptografía
• Solución:
– Un sistema criptográfico de clave pública.
– El más conocido: el sistema RSA.
R.L. Rivest, A. Shamir y L.M. Adleman:
“A method for obtaining digital signatures and
public-key cryptosystems”,
Communications of the ACM, 21(2), pp. 120-126, 1978.

– Publicado previamente en:


M. Gardner: “Mathematical games: A new kind of cipher
that would take millions of years to break”,
Scientific American, 237(2), pp. 120-124, 1977.

• Planteó un problema cuya solución estimó que necesitaría 2 millones de veces


la edad del Universo de cálculo ininterrumpido del mejor computador de
aquel momento.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 39
Introducción a la criptografía

 p, q: nos primos de 300 cifras


 z=pq
(∗) ¿Cómo?
 φ=(p-1)(q-1)


n: 1≤n≤z-1, mcd(n,φ)=1
s: 1≤s≤z-1: ns mod φ=1 (∗)}
(s es único, ¡me lo guardo!)
 m: mensaje en texto
 z, n  a: codificado (ASCII)
(0≤a≤z-1)
 c: c=an mod z

c

(∗∗)  z, n, c…
 a: a=cs
mod z
 m: mensaje (ASCII)
 Yo también…
(∗∗) ¿Por qué?
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 40
Introducción a la criptografía
• Cálculo de n:

– Se genera un valor de n aleatoriamente en (1, z–1).

– Después se intenta calcular s tal que 1≤s≤z–1 y ns mod φ=1;

• la teoría de números asegura que si existe es único y si no existe es


porque n no verifica mcd(n,φ)=1.

– Si no se encuentra tal s es que n no es adecuado


(mcd(n,φ)≠1), se vuelve a generar otro n; etc.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 41


Introducción a la criptografía
• Cálculo de s (algoritmo de Euclides extendido):
– Lema. Sean u≥v>0 y d=mcd(u,v). Entonces existen a y b tales que
au+bv=d. (a y b pueden ser positivos, negativos o nulos)
Euclides
Dem.: Si u=v entonces d=v, a=0 y b=1.
Si u>v, sea w=u mod v. En particular w<v. Se tiene que d=mcd(v,w).
Por inducción, algoritmo egcd(ent u,v:entero; sal d,a,b:entero)
{Pre: u,v>0} {Post: d=mcd(u,v) ∧ d=au+bv}
existen a’ y b’ variables w,aa,bb:entero
tales que principio
selección
a’v+b’w=d. u=v: d:=v; a:=0; b:=1;
Haciendo: u<v: egcd(v,u,d,b,a);
u>v: w:=u mod v; {w<v}
a=b’ si w=0 ent d:=v; a:=0; b:=1
y sino {d=mcd(v,w)}
egcd(v,w,d,aa,bb);
b=a’–(u div v)b’ a:=bb; b:=aa-(u div v)*bb fsi
se sigue. fselección
fin
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 42
Introducción a la criptografía
– Por tanto, para calcular s tal que n s mod φ = 1 :
• n, φ > 0
• mcd(n,φ) = 1

Calcular s y t tales que n s + t φ = 1.

egcd(n,φ,d,s,t);
si d=1
entonces s es el buscado
sino n no es ‘bueno’
fsi

ns+tφ=1⇒ns=1–tφ
n s mod φ = (1 – t φ) mod φ = 1 – 0 = 1

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 43


Introducción a la criptografía
• Falta comprobar la corrección del mensaje obtenido por Roberto.

– Teorema. Sean p,q dos números primos,


z = pq, φ = (p–1)(q–1) y a tal que 0 ≤ a < z.
Si x mod φ = 1 entonces ax mod z = a.

– Alicia construye su mensaje a, 0 ≤ a < z, y a partir de él, calcula


c = an mod z.

– Roberto calcula
cs mod z = (an mod z)s mod z = ans mod z = a
(porque ns mod φ = 1).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 44


Introducción a la criptografía
• ¿Qué puede hacer Eva?

– Conoce z, n y c.

– Tiene que encontrar a, que es el único nº entre 0 y z–1 tal que


c = an mod z.

– Es decir, tiene que calcular la raíz n-ésima de c módulo z.

– No se conoce ningún algoritmo eficiente para hacerlo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 45


Introducción a la criptografía
• La mejor solución conocida es factorizar z en p y q.
– Después, calcular φ=(p-1)(q-1), calcular s, y calcular a igual que Roberto.

• Problema: factorizar un número de unas 300 cifras (i.e., unos


1024 bits) parece imposible (o mejor: es difícil) con la tecnología
actual y el estado actual de la teoría de números.
– El problema propuesto por Gardner exigía factorizar un número de 129
cifras (Gardner estimó en 2 millones de veces la edad del Universo el
tiempo necesario para resolverlo).
– En 1989, se estimaba que ese mismo problema podría ser resuelto “ya” en
unos 250 años–CRAY.
Si se trataba de un número de 200 cifras, la estimación subía a 1 millón de
años–CRAY.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 46


Introducción a la criptografía
• Sin embargo:

– En abril de 1994, Atkins, Graff, Lenstra y Leyland


resolvieron el problema propuesto por Gardner en 1977
(que exigía factorizar un nº de 129 cifras):
• 6 meses de cálculo, mediante
• unos 1600 computadores de todo el mundo trabajando como una
máquina paralela virtual.

 

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 47


Introducción a la criptografía
• Extraído de Wikipedia:
– Las claves RSA tienen normalmente entre 1024 a 2048 bits de longitud.
– Algunos expertos creen que las claves de 1024 bits podrían comenzar a
ser débiles en poco tiempo y las de 4096 en un futuro.
– Si n es suficientemente grande el algoritmo RSA es seguro, de momento.
– Si n tiene 256 bits o menos puede ser factorizado en pocas horas con un
computador personal usando software libre.
– Si n tiene 512 bits o menos puede ser factorizado por varios cientos de
computadoras como en 1994.
– Un dispositivo hardware teórico llamado TWIRL descrito por Shamir y
Tromer en el 2003 cuestionó la seguridad de claves de 1024 bits.
– Actualmente se recomienda que n tenga como mínimo 2048 bits.

– ¿Computador cuántico?  Calma: criptografía cuántica.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 48


Multiplicación de matrices
V. Strassen: “Gaussian elimination is not optimal”,
Numerische Mathematik, 13, pp. 354-356, 1969.

• Sean A y B dos matrices n×n y C su producto.


– El algoritmo clásico calcula:

Es decir, precisa un tiempo Θ(n3).

• La idea de Strassen es reducir el número de


multiplicaciones a costa de aumentar el número de
sumas y restas e introducir variables auxiliares
(como en la multiplicación de enteros grandes).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 49


Multiplicación de matrices
• Veamos el caso 2×2:

– Algoritmo clásico: 8 multiplicaciones y 4 sumas


– Reducción:

Es decir, 7 multiplicaciones y 24 sumas y restas.


Notar que el número de sumas y restas puede reducirse a 15 utilizando
más variables auxiliares para evitar cálculos repetidos, como el de

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 50


Multiplicación de matrices
• Caso 2n×2n:
– Si cada elemento de A y B del caso 2×2 lo sustituimos por una matriz n×n,
se pueden multiplicar dos matrices 2n×2n realizando:
• 7 multiplicaciones de matrices de n×n, y
• 15 sumas y restas de matrices de n×n.

• Coste:
– Una suma de matrices n×n está en Θ(n2).
– Suponer que n es potencia de 2; se obtiene la recurrencia:

( )
T (n) = 7T n 2 + Θ(n2)

Es decir, se pueden multiplicar matrices en tiempo Θ(nlog 7)∈O(n2,81).

• Si n no es potencia de 2: añadir filas y columnas nulas hasta que


lo sea (como mucho se duplica el tamaño)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 51


Multiplicación de matrices
• Comentarios finales sobre el algoritmo de Strassen:
– Según algunos estudios empíricos y debido a la constante multiplicativa,
para que se noten mejoras con respecto al algoritmo clásico, n debe ser
superior a 100, y la matriz densa.
– Es menos estable que el algoritmo clásico (i.e., para errores similares en
los datos produce mayores errores en el resultado).
– Es más difícil de implementar que el algoritmo clásico.
– Es difícilmente paralelizable, mientras que el clásico puede ser fácilmente
paralelizado.
– El algoritmo clásico precisa un espacio adicional de tamaño constante,
mientras que el algoritmo de Strassen precisa un espacio adicional mayor.
– El algoritmo de Strassen ha tenido una repercusión fundamentalmente
teórica (dio también ideas para otras operaciones basadas en él: inversión
de matrices, determinantes,…).
– Se conocen algoritmos teóricamente mejores: la actual cota superior está
en O(n2,3728639).
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 52
Calendario de un campeonato
• El problema:

En una competición deportiva se enfrentan n participantes.

Debe confeccionarse un calendario para que cada participante


juegue exactamente una vez con cada adversario.

Además, cada participante debe jugar exactamente un partido


diario.

Supongamos, por simplificar, que n = 2k.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 53


Calendario de un campeonato
• La representación de los datos y de la solución:
Participantes: 1, 2, …, n.
Cada participante debe saber el orden en el que se enfrenta a los n – 1
restantes.
Por tanto, la solución puede
representarse en una matriz n×(n – 1).

El elemento (i,j), 1≤i≤n, 1≤j≤n-1, contiene el número del participante


contra el que el participante i-ésimo compite el día j-ésimo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 54


Calendario de un campeonato
• Solución de fuerza bruta:
1. Se obtiene para cada participante i, 1≤i≤n, el conjunto P(i) de todas las
permutaciones posibles del resto de los participantes {1..n}\{i}.
2. Se completan las filas de la matriz de todas las formas posibles,
incluyendo en cada fila i algún elemento de P(i).
3. Se elige cualquiera de las matrices resultantes en la que toda columna j,
1≤j≤n-1, contiene números distintos (nadie puede competir el mismo día
contra dos participantes).

– Cada conjunto P(i) consta de (n-1)! elementos.


– La matriz tiene n filas.

Hay n! formas distintas de rellenar la matriz.

¡Es demasiado costoso!


Algoritmia básica - Javier Campos (Universidad de Zaragoza) 55
Calendario de un campeonato
• Una solución mediante la técnica de divide y vencerás (caso
n=2k, k>0):
– Caso básico: n=2, basta con una competición.
– Caso a dividir: n=2k, con k>1.
• Se elaboran independientemente dos sub-calendarios de 2k-1 participantes:
• Uno para los participantes 1..2k-1, y otro para los participantes 2k-1+1..2k.
• Falta elaborar las competiciones cruzadas entre los participantes de
numeración inferior y los de numeración superior.
– Se completa primero la parte de los participantes de numeración inferior:
1er participante: compite en días sucesivos con los participantes de
numeración superior en orden creciente.
2º participante: toma la misma secuencia y realiza una permutación
cíclica de un participante.
Se repite el proceso para todos los participantes de numeración inferior.
– Para los de numeración superior se hace lo análogo con los de inferior.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 56


Calendario de un campeonato

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 57


Calendario de un campeonato
tipo tabla=vector[1..n,1..n-1] de 1..n

algoritmo calendario(sal t:tabla)


{Devuelve en t el calendario de competición de n participantes, con n=2k, k>0.}
principio
formarTabla(t,1,n)
fin

algoritmo formarTabla(sal t:tabla; ent inf,sup:1..n)


{Forma la parte de tabla correspondiente a los enfrentamientos de los
participantes inf..sup}
variable medio:1..n
principio
si inf=sup-1 entonces t[inf,1]:=sup; t[sup,1]:=inf
sino
medio:=(inf+sup) div 2;
formarTabla(t,inf,medio);
formarTabla(t,medio+1,sup);
completarTabla(t,inf,medio,medio,sup-1,medio+1);
completarTabla(t,medio+1,sup,medio,sup-1,inf)
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 58


Calendario de un campeonato

algoritmo completarTabla(e/s t:tabla;


ent eqInf,eqSup,díaInf,díaSup,eqInic:1,,n)
{Rellena t[eqInf..eqSup,díaInf..díaSup] con permutaciones cíclicas
empezando en eqInic}
principio
para j:=díaInf hasta díaSup hacer
t[eqInf,j]:=eqInic+j-díaInf
fpara;
para i:=eqInf+1 hasta eqSup hacer
t[i,díaInf]:=t[i-1,díaSup];
para j:=díaInf+1 hasta díaSup hacer
t[i,j]:=t[i-1,j-1]
fpara
fpara
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 59


Calendario de un campeonato
• Coste temporal:
– Recurrencia: T (n) = 2T (n 2)+ n2 4
– Por tanto, O(n2).

• ¿Y si n no es potencia de 2?
– Supongamos que está resuelto para n par.
– Si n es impar (mayor que 1), no bastan con n-1 días para la competición,
sino que se necesitan n.
Basta con resolver el problema resultante de añadir un participante
(ficticio) más: el n+1.
Como n+1 es par, podemos calcular el calendario, que consta de n días.
Una vez resuelto, si al participante i-ésimo le toca jugar el día j-ésimo
contra el participante n+1 (ficticio), eso significa que j es el día de
descanso para el participante i.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 60


Calendario de un campeonato
• ¿Y si n es par?
– Si n div 2 es par, se puede aplicar el algoritmo “formarTabla” (visto para
el caso n=2k).
– Si n div 2 es impar:
Paso 1:
• Se calcula la 1ª parte de la competición para los n div 2 participantes de
numeración inferior, añadiendo un participante ficticio.
• Se calcula la primera parte de la competición para los otros n div 2
participantes, añadiendo otro participante ficticio.
Paso 2:
• El día j-ésimo, 1≤j≤n div 2, se hace jugar entre sí a los dos participantes, uno
de numeración inferior y otro superior, a los que les había tocado el j como
día de descanso en el Paso anterior.
Paso 3:
• Se completa el resto de la tabla con competiciones cruzadas, de forma
parecida a como se hizo en el algoritmo “completarTabla”.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 61


Calendario de un campeonato

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 62


Programación dinámica

Este documento está sujeto a una licencia de uso Creative


Algoritmia básica - Javier Campos (Universidad de Zaragoza) Commons. No se permite un uso comercial de la obra
original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Programación dinámica
• Introducción 3
• El problema de la mochila 0-1 8
• Camino de coste mínimo en un grafo multietapa 18
• Multiplicación de una secuencia de matrices 31
• Pasos en una solución de Programación Dinámica 41
• Comparaciones de secuencias 43
• Caminos mínimos entre todos los pares de nodos de un grafo 50
• Árboles binarios de búsqueda óptimos 56
• Un problema de fiabilidad de sistemas 67
• El problema del viajante de comercio 72
• Planificación de trabajos 82
• Una competición internacional 95
• Triangulación de polígonos 101

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 2


Programación dinámica: Introducción
• Recordemos el problema de la mochila (fraccionaria):
– Se tienen n objetos fraccionables y una mochila.
– El objeto i tiene peso pi y una fracción xi (0≤xi≤1) del objeto i produce un
beneficio bixi.
– El objetivo es llenar la mochila,
de capacidad C, maximizar ∑ bi xi
de manera que se 1≤i ≤n
maximice el beneficio.
sujeto a ∑ pi xi ≤ C
1≤i ≤n

con 0≤ xi ≤ 1, bi > 0, pi > 0, 1≤ i ≤ n

• Una variante: la “mochila 0-1” (el “auténtico” problema de la mochila)


– xi sólo toma valores 0 ó 1, indicando que el objeto se deja fuera o se mete en
la mochila.
– Los pesos, pi, y la capacidad son números naturales.
Los beneficios, bi, son reales no negativos.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 3


Programación dinámica: Introducción
• Ejemplo:
n=3 C=15
(b1,b2,b3)=(38,40,24)
(p1,p2,p3)=(9,6,5)

• Recordar la estrategia voraz:


– Tomar siempre el objeto que proporcione mayor beneficio por unidad de
peso.
– Se obtiene esta solución: (x1,x2,x3)=(0,1,1), con beneficio 64
– Sin embargo, la solución óptima es: (x1,x2,x3)=(1,1,0), con beneficio 78

• Por tanto, la estrategia voraz no calcula la solución óptima del


problema de la mochila 0-1.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 4


Programación dinámica: Introducción
R. Bellman: Dynamic Programming,
Princeton University Press, 1957.
• Técnica de programación dinámica
– Se emplea típicamente para resolver problemas de optimización.
– Permite resolver problemas mediante secuencias de decisiones.
Como el esquema voraz
– A diferencia del esquema voraz, se producen varias secuencias de decisiones y
sólamente al final se sabe cuál es la mejor de ellas.

– Descompone un problema en subproblemas del mismo tipo.


Como en divide y vencerás
– A diferencia de divide y vencerás, los subproblemas están superpuestos entre sí,
comparten subproblemas entre ellos  se almacenan y reutilizan sus soluciones
(memoization)

– Está basada en el principio de optimalidad de Bellman (= propiedad de la


subestructura óptima):
“Cualquier subsecuencia de decisiones de una secuencia óptima de decisiones que
resuelve un problema también debe ser óptima respecto al subproblema que resuelve.”

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 5


Programación dinámica: Introducción
– Supongamos que un problema se resuelve tras tomar una
secuencia d1, d2, …, dn de decisiones.

– Si hay d opciones posibles para cada una de las decisiones,


una técnica de fuerza bruta exploraría un total de dn
secuencias posibles de decisiones (explosión combinatoria).

– La técnica de programación dinámica evita explorar todas las


secuencias posibles por medio de la resolución de
subproblemas de tamaño creciente y almacenamiento en una
tabla de las soluciones óptimas de esos subproblemas para
facilitar la solución de los problemas más grandes.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 6


Programación dinámica: Introducción
• Más formalmente:
– Sea E0 el estado inicial del problema.
– Sea el conjunto de valores de decisión
posibles para la decisión d1.
– Sea E1i el estado del problema tras la elección del valor v1i, 1≤i≤n1.
– Sea S1i una secuencia óptima de decisiones respecto al estado E1i.
• Principio de optimalidad de Bellman:
Una secuencia óptima de decisiones respecto a E0 es la mejor de las
secuencias de decisión {v1i,S1i}, 1≤i≤n1.
El mismo razonamiento puede aplicarse a cualquier subsecuencia de
decisiones dk, …, dl, 1≤k≤l≤n, partiendo como estado inicial de Ek-1.
Una solución dinámica para este problema, simbolizado como (k,l),
debe expresarse en términos de los valores de decisión existentes para
la decisión dk y el subproblema (k+1,l), resultante de aplicar cada valor
de decisión.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 7


El problema de la mochila 0-1
l
• Sea mochila(k,l,P) el problema: maximizar ∑ bi xi
i=k
l
sujeto a ∑ pi xi ≤ P
i=k

con xi ∈{0,1}, k ≤ i ≤ l

– El problema de la mochila 0-1 es mochila(1,n,C).


• Principio de optimalidad:
Sea y1,…,yn una secuencia óptima de valores 0-1 para x1,…,xn.
– Si y1=0, entonces y2,…,yn forman una secuencia óptima para el problema
mochila(2,n,C).
– Si y1=1, entonces y2,…,yn forman una secuencia óptima para el problema
mochila(2,n,C-p1).
Demostración: Si existe una solución mejor y˜2 ,, y˜n para el problema
correspondiente, entonces y1 , y˜2 ,, y˜n es mejor que para el
problema mochila(1,n,C), en contra de la hipótesis.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 8


El problema de la mochila 0-1
• Lo mismo se cumple en cualquier etapa de decisión:
– Si y1,…,yn es una solución óptima del problema
mochila(1,n,C), entonces para todo j, 1≤j≤n:

• y1,…,yj es solución óptima de

 j 
mochila  1, j , ∑ pi xi 
 i =1 

• yj+1,…,yn es solución óptima de

 j 
mochila  j + 1,n,C − ∑ pi xi 
 i=1 

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 9


El problema de la mochila 0-1
• Ecuación de recurrencia hacia adelante:
– Si gj(c ) es el beneficio (o ganancia total) de una solución óptima
de mochila(j,n,c), entonces

{
gj (c) = max gj + 1(c), g j+ 1(c − pj ) + bj }
dependiendo de que el objeto j-ésimo entre o no en la solución
(nótese que sólo puede entrar si c-pj≥0).
– Además,
gn+ 1 (c) = 0, para cualquier capacidad c

Ambas ecuaciones permiten calcular g (C ) , que


1
es el valor de una solución óptima de
mochila(1,n,C).

(Nótese que la ecuación de recurrencia es hacia adelante


pero el cálculo se realiza hacia atrás.)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 10


El problema de la mochila 0-1
• Ecuación de recurrencia hacia atrás:
– Si gj (c) es el beneficio (o ganancia total) de una solución óptima de
mochila(1,j,c), entonces

{
gj (c) = max gj − 1(c) , gj − 1(c − pj ) + bj }
dependiendo de que el objeto j-ésimo entre o no en la solución
(nótese que sólo puede entrar si c-pj≥0).
– Además,
g0(c ) = 0, para cualquier capacidad c

Ambas ecuaciones permiten calcular gn(C) , que es el


valor de una solución óptima de mochila(1,n,C).

(Ahora la recurrencia es hacia atrás pero el cálculo se realiza


hacia adelante.)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 11


El problema de la mochila 0-1
• Tanto la recurrencia hacia adelante como hacia atrás permiten escribir
un algoritmo recursivo de forma inmediata.
función mochila1(p,b:vector[1..n] de nat; C:nat) devuelve nat
principio
devuelve g(n,C)
fin

función g(j,c:nat) devuelve nat


principio
si j=0 entonces devuelve 0
sino
si c<p[j] entonces devuelve g(j-1,c)
sino
si g(j-1,c)≥g(j-1,c-p[j])+b[j] entonces devuelve g(j-1,c)
sino
devuelve g(j-1,c-p[j])+b[j]
fsi
fsi
fsi
fin
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 12
El problema de la mochila 0-1
• Problema: ineficiencia
– Un problema de tamaño n se reduce a dos subproblemas de tamaño (n-1).
– Cada uno de los dos subproblemas se reduce a otros dos…
Por tanto, se obtiene un algoritmo exponencial.

• Sin embargo, el número total de subproblemas a resolver no es


tan grande:
La función gj (c) tiene dos parámetros:
• el primero puede tomar n valores distintos y
• el segundo, C valores.
¡Luego sólo hay nC problemas diferentes!
• Por tanto, la solución recursiva está generando y resolviendo el
mismo problema muchas veces.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 13


El problema de la mochila 0-1
• Memoization: las soluciones de los subproblemas se almacenan
en una tabla para evitar hacer más de una vez la misma llamada
recursiva  se obtiene un algoritmo iterativo.
– Matriz n×C cuyo elemento (j,c) almacena g j ( c )
– Para el ejemplo anterior:
En castellano…
n=3 C=15 “memoización”
(b1,b2,b3)=(38,40,24) “memorialización”
(p1,p2,p3)=(9,6,5) ...

c=…

j=0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j=1
j=2
j=3
{
g j (c ) = max g j − 1(c) , g j − 1(c − p j ) + b j }
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 14
El problema de la mochila 0-1
algoritmo mochila(ent p,b:vect[1..n]de nat; ent Cap:nat;
sal g:vect[0..n,0..Cap]de nat)
variables c,j:nat
principio
para c:=0 hasta Cap hacer g[0,c]:=0 fpara;
para j:=1 hasta n hacer g[j,0]:=0 fpara;
para j:=1 hasta n hacer
para c:=1 hasta Cap hacer
si c<p[j] entonces
g[j,c]:=g[j-1,c]
sino
si g[j-1,c]≥g[j-1,c-p[j]]+b[j] entonces
g[j,c]:=g[j-1,c]
sino
g[j,c]:=g[j-1,c-p[j]]+b[j]
fsi
fsi
fpara
fpara
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 15


El problema de la mochila 0-1
• Cálculos posibles a partir de la tabla g:
– beneficio total: g[n,Cap]
– los objetos metidos en la mochila:
algoritmo objetos(ent p,b:vect[1..n]de nat; ent Cap:nat;
ent g:vect[0..n,0..Cap]de nat)
principio
test(n,Cap)
fin

algoritmo test(ent j,c:nat)


principio
si j>0 entonces
si c<p[j] entonces test(j-1,c)
sino
si g[j-1,c-p[j]]+b[j]>g[j-1,c] entonces
test(j-1,c-p[j]); escribir('meter ',j)
sino test(j-1,c)
fsi fsi fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 16


El problema de la mochila 0-1
• Consideraciones finales

– Cada componente de la tabla g se calcula en tiempo


constante, luego el coste de construcción de la tabla es O(nC).

– El algoritmo test se ejecuta una vez por cada valor de j,


desde n descendiendo hasta 0, luego su coste es O(n).

– Si C es muy grande, entonces esta solución no es buena.

– Si los pesos pi o la capacidad C son reales, esta solución no


sirve.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 17
Camino de coste mínimo en un grafo multietapa
• Grafo multietapa:
– Un grafo multietapa G=(V,A) es un grafo dirigido en el que se puede hacer
una partición del conjunto V de vértices en k (k≥2) conjuntos distintos
Vi, 1≤i≤k, tal que todo arco del grafo (u,v) es tal que u∈Vi y v∈Vi+1 para
algún i, 1≤i<k.
– Los conjuntos V1 y Vk tienen un solo vértice que se llama vértice origen, o,
y vértice destino, d, respectivamente.
V1 V2 V3 V4 V5
2 3 7
8 5
5 1 5 1
7 1 9
o 1 3 4 6 8 10 d

2 5 6 4
12
4 9 9

– Consideraremos grafos etiquetados.


Denotamos por c(u,v) el coste del arco (u,v).
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 18
Camino de coste mínimo en un grafo multietapa
• El problema: Encontrar un camino de coste mínimo que
vaya de o a d.

– Todo camino de o a d tiene exactamente un vértice en cada


Vi, por eso se dice que cada Vi define una etapa del grafo.

V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
2 5 6 4
12
4 9 9

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 19


Camino de coste mínimo en un grafo multietapa
• Ejemplo de aplicación:
– Se tienen n unidades de un recurso que deben asignarse a r
proyectos.
– Si se asignan j, 0≤j≤n, unidades al proyecto i se obtiene un
beneficio Ni,j.
– El problema es asignar
el recurso a los r proyectos
maximizando
el beneficio total.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 20


Camino de coste mínimo en un grafo multietapa
– Formulación como grafo multietapa:
• Número de etapas: r+1
• La etapa i, 1≤i≤r, representa el proyecto i.
• Hay n+1 vértices vi,j, 0≤j≤n, en cada etapa i, 2≤i≤r.
• Las etapas 1 y r+1 tienen un vértice, o=v1,0 y d=vr+1,n,
respectivamente.
• El vértice vi,j, 2≤i≤r, representa el estado en el que se asignan un total
de j unidades del recurso a los proyectos 1, 2, …, i-1.
• Los arcos son de la forma (vi,j,vi+1,l) para todo j≤l y 1≤i<r.
• El arco (vi,j,vi+1,l), j≤l, tiene asignado un coste Ni,l-j que corresponde a
asignar l-j unidades del recurso al proyecto i, 1≤i<r.
• Además hay arcos de la forma (vr,j,vr+1,n), que tienen asignado un coste
max {Nr , p}.
0≤ p ≤n − j

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 21


Camino de coste mínimo en un grafo multietapa
– Grafo resultante para r=3 y n=4.
• La asignación óptima está
definida por un camino de N 2,0
v2,0 v3,0
coste máximo de o a d. N 1,0
max {N 3,i }
i= 0,1,2,3,4
• Para convertirlo en un N 2,1

problema de camino de v2,1 N 2,0


v3,1
N 1,1
coste mínimo basta N 2,2 max {N 3,i }
N 2,3 i= 0,1,2,3
cambiar los signos de
N 2,1 max {N 3,i }
las etiquetas. N 1,2 N 2,0 i= 0,1,2
o = v1,0 v2,2 v3,2 d = v4,4

N max {N 3,i }
N 2,1 N 2,2 2,3 i= 0,1
N 1,3 N 2,2
v2,3 v3,3
N 2,0
N 2,1 N 3,0
N 1,4 N 2,4

v2,4 v3,4
N 2,0
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 22
Camino de coste mínimo en un grafo multietapa
• Solución de programación dinámica:
V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
2 5 6 4
12
4 9 9

– Cada camino de o a d es el resultado de una secuencia de k-2 decisiones.


– Decisión i-ésima: determinar, a partir de un vértice vi de Vi, un arco que
tenga a vi como origen y algún nodo de Vi+1 como destino.
– Principio de optimalidad:
El camino de coste mínimo debe contener subcaminos de coste mínimo
entre otros nodos.
Dem.: En otro caso, podrían sustituirse dichos subcaminos por otros mejores,
resultando un camino total de coste menor.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 23
Camino de coste mínimo en un grafo multietapa
– Ecuación de recurrencia hacia adelante:
• Sea s(i,j) un camino de coste mínimo C*(i,j) desde el vértice j del
conjunto Vi hasta el vértice destino d.
• Entonces:

C∗ (i , j ) = min
l ∈V i+ 1
{c( j ,l )+ C∗ (i + 1,l )}, para 1≤ i ≤ k − 2
( j ,l )∈A

V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
2 5 6 4
12
4 9 9

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 24


Camino de coste mínimo en un grafo multietapa

C∗ (i , j ) = min
l ∈V i+ 1
{c( j ,l )+ C∗ (i + 1,l )}, para 1≤ i ≤ k − 2
( j ,l )∈A
V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
2 5 6 4
12
4 9 9
C∗ (3,5)= min {8+ C ∗(4,7),11+ C ∗ (4,8),6+ C ∗(4,9)}= 13
C ∗ (3,6)= 4+ C ∗(4,8) = 13
C ∗ (2,2)= min {3+ C ∗(3,5),1+ C ∗ (3,6)}= 14
C ∗ (2,3)= 4+ C ∗(3,5) = 17
C ∗ (2,4)= min {5+ C ∗(3,5),9+ C ∗ (3,6)}= 18
C ∗ (1,1)= min {5+ C ∗(2,2),7+ C ∗ (2,3),2+ C ∗(2,4)}= 19

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 25


Camino de coste mínimo en un grafo multietapa
– Falta almacenar las decisiones hechas en cada etapa que
minimizan el coste:
• Sea D(i,j) el valor de l que minimiza c( j,l) + C∗ (i + 1,l).
• Entonces el camino de coste mínimo es:
v1=1; v2=D(1,1); v3=D(2,D(1,1)); etc.
V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
D(3, 5) = 7; D (3,6) = 8 2 5 6 4
12
4 9 9
D (2,2)= 6; D (2,3) = 5; D (2,4) = 5
D (1,1)= 2
v1 = 1
v2 = D (1,1) = 2
v3 = D (2,D (1,1))= 6
v4 = D (3,D (2,D (1,1)))= 8
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 26
Camino de coste mínimo en un grafo multietapa
algoritmo multietapa(ent G=(V,A,c):grafo; ent k,n:nat;
sal P:vect[1..k]de 1..n)
{Los vértices están numerados de forma que los índices de los
vértices de una etapa son mayores que los índices de los de la
etapa anterior.
El primer índice de C* y D, que sólo identificaba la etapa, se ha
suprimido.}
variables C:vect[1..n]de real; D:vect[1..n]de 1..n; j,r:1..n
principio
C[n]:=0.0; {Cálculo de C* y D}
para j:=n-1 descendiendo hasta 1 hacer
r:=vértice t.q. (j,r)∈A ∧ c(j,r)+C[r] es mínimo;
C[j]:=c(j,r)+C[r];
D[j]:=r
fpara;
P[1]:=1; P[k]:=n; {Construcción del camino}
para j:=2 hasta k-1 hacer
P[j]:=D[P[j-1]]
fpara
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 27


Camino de coste mínimo en un grafo multietapa
• Coste del algoritmo:

– Si G está representado mediante listas de adyacencia,


entonces el cálculo de r en el interior del primer bucle lleva
un tiempo proporcional al grado del vértice j.

– Por tanto, si a es el número de arcos del grafo, el coste total


del algoritmo es Θ(a).

(El segundo bucle lleva un tiempo Θ(k).)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 28


Camino de coste mínimo en un grafo multietapa
• Análogamente, se desarrolla la recurrencia hacia atrás.
– Ecuación de recurrencia hacia atrás:
• Sea s(i,j) un camino de coste mínimo C*(i,j) desde el vértice origen o
hasta el vértice j del conjunto Vi.
• Entonces:

C∗ (i , j ) = min
l ∈V i− 1
{c(l , j )+ C∗ (i − 1,l )}, para 3≤ i ≤ k
(l , j )∈A

V1 V2 V3 V4 V5
2 3
8
7 5
5 1 5 11
7 9
o 1 3 4 6 8 10 d
2 5 6 4
12
4 9 9

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 29


Camino de coste mínimo en un grafo multietapa
algoritmo multietapaB(ent G=(V,A,c):grafo; ent k,n:nat;
sal P:vect[1..k]de 1..n)
{Los vértices están numerados de forma que los índices de los
vértices de una etapa son mayores que los índices de los de la etapa
anterior. El primer índice de C* y D, que sólo identificaba la
etapa, se ha suprimido.}
variables C:vect[1..n]de real; D:vect[1..n]de 1..n; j,r:1..n
principio
C[1]:=0.0; {Cálculo de C* y D}
para j:=2 hasta n hacer
r:=vértice t.q. (r,j)∈ A ∧ c(r,j)+C[r] es mínimo;
C[j]:=c(r,j)+C[r];
D[j]:=r
fpara;
P[1]:=1; P[k]:=n; {Construcción del camino}
para j:=k-1 descendiendo hasta 2 hacer
P[j]:=D[P[j+1]]
fpara
fin

Nota: La eficiencia es la misma si G está representado mediante listas de adyacencia inversa.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 30


Multiplicación de una secuencia de matrices
• Se desea calcular el producto matricial:
Como es asociativo, existen varias formas…
(Recordar que el algoritmo resultante de la definición del producto de dos
matrices p×q y q×r necesita pqr multiplicaciones de escalares.)

– Ejemplo: se quiere calcular el producto ABCD, de las matrices A(13×5),


B(5×89), C(89×3) y D(3×34).
nº multip.
((AB)C)D) 10582
(AB)(CD) 54201
(A(BC))D 2856
A((BC)D) 4055
A(B(CD)) 26418

¡El caso más eficiente es casi 19 veces más rápido que el más lento!

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 31


Multiplicación de una secuencia de matrices
• ¿Cómo hallar el mejor método?
1. Insertar los paréntesis de todas las formas posibles (significativamente
diferentes).
2. Calcular para cada una el número de multiplicaciones escalares
requeridas.
• ¿Cuántas formas posibles T(n) de insertar paréntesis existen en
un producto de n matrices?
– Si cortamos entre la i y la (i+1)-ésima:
Entonces tenemos T(i)T(n-i) formas distintas.
– Como i puede tomar valores entre 1 y n-1:

n −1
T (n) = ∑ T (i )T (n − i ), para n > 1
i =1
T (1) = 1 Números de Catalan

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 32


Multiplicación de una secuencia de matrices
• Los números de Catalan crecen exponencialmente.
– De hecho puede demostrarse que:

1 2n − 2
T (n) =
n n− 1 

Por ejemplo:
n 1 2 3 4 5 10 15
T (n) 1 1 2 5 14 4862 2674440

• Luego el método directo “no sirve” (por costoso).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 33


Multiplicación de una secuencia de matrices

S. Godbole: “On efficient computation of matrix chain products”,


IEEE Transactions on Computers, 22(9), pp. 864-866, 1973.

• Aplicación del principio de optimalidad:


Si el mejor modo de realizar el producto exige dividir inicialmente entre
las matrices i e (i+1)-ésima, los productos

deberán ser realizados de forma óptima para que el total también sea
óptimo.
• Método:
– Construir la matriz [mij], 1≤i≤j≤n, donde mij da el óptimo (i.e., el número
de multiplicaciones escalares requeridas) para la parte
del producto total.
– La solución final vendrá dada por m1n.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 34
Multiplicación de una secuencia de matrices
– Construcción de [mij], 1≤i≤j≤n:
• Guardar las dimensiones de las Mi, 1≤i≤n, en un vector d, de
0..n componentes, de forma que Mi tiene dimensiones di-1×di.
• La diagonal s de [mij] contiene los mij tales que j-i=s:

• El tercer caso representa que para calcular se


intentan todas las posibilidades
y se escoge la mejor.
• De forma más compacta:
0, si i = j
mij =  min {mik + mk + 1, j + di − 1dkdj }, si i < j
i ≤ k< j
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 35
Multiplicación de una secuencia de matrices
• Para el ejemplo anterior:
– A(13×5), B(5×89), C(89×3) y D(3×34). Se tiene d=(13,5,89,3,34).
– Para s=1: m12=5785, m23=1335, m34=9078.
– Para s=2:

– Para s=3:

– La matriz es:

(s = j – i,
es decir,
j = i + s)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 36


Multiplicación de una secuencia de matrices
• Solución recursiva inmediata:
– Aplicación de la ecuación recurrente.
– Problema: complejidad exponencial.

• Almacenamiento de las soluciones de los subproblemas


en una tabla:
– Número de subproblemas: Θ(n2).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 37


Multiplicación de una secuencia de matrices
algoritmo parentOpt(ent d:vect[0..n]de nat;
sal m:vect[1..n,1..n]de nat; sal km:vect[1..n,1..n]de 1..n)
{m es la matriz [mij] definida antes; km[i,j] guarda el índice k para
el que se alcanza el mínimo al calcular m[i,j].}
variables i,s,j,k,q:nat
principio
para i:=1 hasta n hacer m[i,i]:=0 fpara;
para s:=1 hasta n-1 hacer
para i:=1 hasta n-s hacer
j:=i+s;
m[i,j]:=∞;
para k:=i hasta j-1 hacer
q:=m[i,k]+m[k+1,j]+d[i-1]*d[k]*d[j];
si q<m[i,j] entonces
m[i,j]:=q; km[i,j]:=k
fsi
fpara
fpara
fpara
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 38


Multiplicación de una secuencia de matrices
• Coste en tiempo:

– Θ(n3)

• Coste en memoria:

– Θ(n2)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 39


Multiplicación de una secuencia de matrices
• ¡Falta hacer el producto!
– El elemento km[i,j] guarda el valor de k tal que la división
óptima de parte el producto entre Mk y Mk+1.
– Por tanto:
función multSec(M:vect[1..n]de matriz;
km:vect[1..n,1..n]de 1..n;
i,j:1..n) devuelve matriz
variables X,Y:matriz
principio
si j>i entonces
X:=multSec(M,km,i,km[i,j]);
Y:=multSec(M,km,km[i,j]+1,j];
devuelve mult(X,Y)
sino
devuelve M[i]
fsi
Fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 40


Pasos en una solución de Programación Dinámica
Para plantear una solución de programación dinámica deben seguirse los pasos
siguientes:
1. Definir de manera precisa una función parametrizada tal que, para algunos
valores de sus parámetros, nos aporte la solución del problema propuesto.
2. Escribir una ecuación recurrente (o relación de recurrencia) para esa función
parametrizada, detallando para qué valores de sus parámetros es válida la
ecuación, y escribir los casos base de la función (casos particulares de sus
parámetros para los que se puede expresar el valor de la función sin necesidad
de recurrencias).
3. Detallar qué tabla es necesaria para almacenar los valores de la función
parametrizada, y qué orden puede seguirse para calcularla. Detallar si se
precisa alguna otra tabla auxiliar para reconstruir la solución para la que la
función alcanza el óptimo.
4. Escribir en pseudocódigo el algoritmo para rellenar la tabla de los valores
óptimos de la función parametrizada y, si se solicita, escribir el algoritmo
para construir la solución del problema original.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 41


Pasos en una solución de Programación Dinámica
Ejemplo para el problema de multiplicación de una secuencia de matrices:
1. Función m(i,j) = número mínimo de multiplicaciones de escalares necesarias
para multiplicar la subsecuencia de matrices Mi, …, Mj.
El problema originalmente propuesto es calcular m(1,n).
2. m(i,i) = 0, para i = 1..n (casos base).
m(i,j) = mini≤k<j {m(i,k) + m(k+1,j) + di-1dkdj}, para los i, j tales que 1≤i<j≤n.
3. Matriz triangular superior para almacenar los m(i,j), con 1≤i≤j≤n.
Puede calcularse por diagonales, empezando por la diagonal principal y,
desde ahí, hacia arriba.
Matriz auxiliar de iguales dimensiones para almacenar los índices k para los
que se consigue el mínimo de la ecuación recurrente para cada uno de
los m(i,j). Es la matriz km[i,j] en el algoritmo de la transparencia nº 38.
4. Algoritmos de la página 38 y de la página 40.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 42


Comparaciones de secuencias

D. Gusfield: Algorithms on Strings, Trees, and Sequences.


Computer Science and Computational Biology,
Cambridge University Press, 1997.

• Problemas relacionados con biología molecular.


• Problema de la distancia de edición:
“Mínimo número de pasos de edición para transformar una cadena en otra.”

– Sean A=a1a2…an y B=b1b2…bm dos cadenas de caracteres.


– Se quiere modificar A, carácter a carácter, hasta convertirlo en B.
– Se permiten tres tipos de cambios (pasos de edición) y cada uno tiene
coste unidad:
1. Insertar un carácter en la cadena.
2. Borrar un carácter de la cadena.
3. Sustituir un carácter por otro diferente.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 43


Comparaciones de secuencias

– Ejemplo: ¿nº de pasos?


abbc babb

Una solución: Otra solución (mejor):


abbc babb abbc babb

1: borrar a 3: sustituir c por b


1: insertar b 2: borrar c

bbc babc babbc


2: insertar a

• Aplicaciones en comparación y mantenimiento de versiones de


ficheros:
– Si se tienen varias versiones parecidas de un fichero es más eficiente
almacenar sólo la 1ª versión y para el resto de versiones almacenar los
pasos de edición (normalmente inserciones y borrados) desde la 1ª.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 44


Comparaciones de secuencias

R.A. Wagner y M.J. Fischer:


“The string-to-string correction problem”,
Journal of the ACM, 21, pp. 168-173, 1974.

• Solución de programación dinámica:


– Sean A(i) y B(j) las subcadenas prefijo de A y B
(i.e., A(i)=a1a2…ai, B(j)=b1b2…bj).
– C(i,j) el coste mínimo de transformar A(i) en B(j).
– El problema original es: A(n) → B(m)
– Fijémonos en los posibles tratamientos de ai en el problema A(i) → B(j):
• bien es borrado, y el problema se reduce a transformar A(i-1) en B(j) y luego borrarlo;
• bien se le hace coincidir con algún carácter de B anterior a bj, en cuyo caso el problema
se reduce a transformar A(i) en B(j-1) y luego insertar un carácter igual a bj;
• bien se le sustituye por un carácter igual a bj, y el problema se reduce a transformar
A(i-1) en B(j-1) y luego sustituir ai;
• o bien ai coincide con bj, y entonces basta con transformar A(i-1) en B(j-1).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 45


Comparaciones de secuencias
– Si denotamos:
0, si ai = bj
c (i , j) = 
1, si ai ≠ bj
– Se tiene: C (i  1, j )  1
 (borrando ai )
C (i, j )  min C (i, j  1)  1 (insertando bj )

C (i  1, j  1)  c(i, j ) (otros casos)

- No hacer nada
C (i ,0) = i , for all i , 0≤ i ≤ n - Cambiar ai por bj
C (0, j) = j , for all j , 0≤ j ≤ m
– Solución recursiva obvia: ¡coste exponencial!
– Sin embargo, sólo existen nm subproblemas diferentes
(C(i,j), 1≤i≤n,1≤j≤m).
– Orden de cálculo (a partir de la ecuación): j

i ?
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 46
Comparaciones de secuencias
algoritmo compSec(ent A:cad[n]; ent B:cad[m];
sal C:vect[0..n,0..m]de nat; sal T:vect[1..n,1..m]de Transf)
{Transf=(borrar,insert,sustit,nada); i.e. posibles transformaciones}
variables i,j,x,y,z:nat
principio
para i:=0 hasta n hacer C[i,0]:=i fpara;
para j:=0 hasta m hacer C[0,j]:=j fpara;
para i:=1 hasta n hacer
para j:=1 hasta m hacer
x:=C[i-1,j]+1; y:=C[i,j-1]+1;
si A[i]=B[j] entonces z:=C[i-1,j-1]
sino z:=C[i-1,j-1]+1
fsi;
C[i,j]:=min(x,y,z);
T[i,j]:= (min=x) => borrar; {último cambio de A[i] a B[j]}
(min=y) => insert;
(min=z) & A[i]=B[j]) => nada;
(min=z) & A[i]≠B[j]) => sustit;
fpara
fpara
Fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 47


Comparaciones de secuencias
algoritmo res(ent i,j:nat)
{Para resolver el problema, ejecutar res(n,m).}
variable k:nat
principio
selección
i=0: para k:=1 hasta j hacer
escribir('Añadir',B[k],'en el lugar',k) fpara
j=0: para k:=1 hasta i hacer
escribir('Borrar car.nº',k) fpara
otros:
selección
T[i,j]=borrar: res(i-1,j); escribir('Borrar car.nº',i)
T[i,j]=insert: res(i,j-1); escribir('Insertar car.nº',j,
'de B tras la posición',i)
T[i,j]=sustit: res(i-1,j-1); escribir('Sustit. car.nº',i,
'de A por nº',j,'de B')
T[i,j]=nada: res(i-1,j-1)
fselección
fselección
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 48


Comparaciones de secuencias
• Coste:

– En tiempo: Θ(nm)

– En espacio: Θ(nm)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 49


Caminos mínimos entre todos los pares de nodos de un grafo
R.W. Floyd:
“Algorithm 97: Shortest path”, Bernard Roy (1959)
Communications of the ACM, 5(6), p. 345, 1962. Robert Floyd (1962)
Stephen Warshall (1962)
• Problema:
Cálculo de los caminos de coste mínimo entre todos los pares de vértices de un
grafo dirigido sin ciclos de peso negativo.
• Principio de optimalidad:
Si i1, i2, …, ik, ik+1, …, in es un camino de coste mínimo de i1 a in, entonces:
• i1, i2, …, ik es un camino de coste mínimo de i1 a ik, y
• ik, ik+1, …, in es un camino de coste mínimo de ik a in.
• Aplicación del principio:
– Si k es el vértice intermedio de mayor índice en el camino óptimo de i a j,
entonces el subcamino de i a k es un camino óptimo de i a k que, además, sólo
pasa por vértices de índice menor que k.
– Lo análogo ocurre con el subcamino de k a j.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 50


Caminos mínimos entre todos los pares de nodos de un grafo
– Sea C(i,j) el peso de la arista (i,j) o infinito si esa arista no existe.
Sea C(i,i)=0.
– Sea Dk(i,j) la longitud (o distancia) del camino de coste mínimo de i a j
que no pasa por ningún vértice de índice mayor que k.
– Sea D(i,j) la longitud del camino de coste mínimo de i a j.
– Entonces:
D(i,j) = Dn(i,j), 1≤ i ≤ n, 1≤ j ≤ n

– Ahora, un camino óptimo de i a j que no pase por ningún vértice de índice


mayor que k, o bien pasa por el vértice k o no pasa.
• Si pasa por k entonces: Dk (i , j) = Dk−1(i ,k) + Dk−1(k , j )
• Si no pasa por k entonces
ningún vértice intermedio
tiene índice superior a k-1: Dk (i , j) = Dk−1(i , j )

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 51


Caminos mínimos entre todos los pares de nodos de un grafo

• En resumen:
– Se tiene la siguiente ecuación recurrente que define el método
de programación dinámica.

{ }
Dk (i , j) = min Dk − 1(i , j ), Dk − 1(i , k) + Dk − 1(k , j ) ,
k ≥1
D0 (i , j) = C (i , j ), 1≤ i ≤ n, 1≤ j ≤ n

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 52


Caminos mínimos entre todos los pares de nodos de un grafo

{Pre: g es un grafo dirigido etiquetado sin ciclos negativos}


función Floyd(g:grafo) devuelve vector[vért,vért] de etiq
variables D:vector[vért,vért] de etiq;
i,j,k:vért
principio
{inicialmente la distancia entre dos vértices tiene el valor de la
arista que los une; las diagonales se ponen a cero}
para todo i en vért hacer
para todo j en vért hacer
D[i,j]:=etiqueta(g,i,j) {∞ si no hay arco}
fpara;
D[i,i]:=0
fpara;
...

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 53


Caminos mínimos entre todos los pares de nodos de un grafo

...
para todo k en vért hacer
para todo i en vért hacer
para todo j en vért hacer
si D[i,k]+D[k,j]<D[i,j] entonces
D[i,j]:=D[i,k]+D[k,j]
fsi
fpara
fpara
fpara;
devuelve D
fin
{Post: D=caminosMínimos(g)}

Ver en la web (material adicional) por qué se puede eliminar el subíndice k de la


ecuación en recurrencias y por tanto evitar el uso de otra matriz.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 54


Caminos mínimos entre todos los pares de nodos de un grafo
• Eficiencia temporal: Θ(n3)
– representación con matriz de adyacencia:
igual que reiterar Dijkstra (Algoritmos voraces, pág. 28), aunque el
interior del bucle en Floyd es más simple
– representación con listas de adyacencia:
reiterando Dijkstra + colas con prioridad está en Θ(anlog n)
• Espacio:
– Floyd exige Θ(n2) mientras que Dijkstra precisa Θ(n)
• Ejercicio: cálculo de las secuencias de nodos que componen los
caminos mínimos
– si el camino mínimo de m a n pasa primero por p y después por q, la
secuencia de vértices que forman el camino mínimo de p a q forma parte
de la secuencia de vértices que forman el camino mínimo de m a n
– usar un vector bidimensional C indexado por vértices: C[v,w] contiene un
nodo u que forma parte del camino mínimo entre v y w
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 55
Árboles binarios de búsqueda óptimos
• Recordar árbol binario de búsqueda:
– La clave de todo nodo es mayor o igual que las de sus descendientes
izquierdos y menor que las de sus descendientes derechos.
• El problema:
– Se tiene un conjunto de claves distintas:
(ordenadas alfab) que deben almacenarse en un árbol binario de búsqueda.
– Se conoce la probabilidad pi, 1≤i≤n, con la que se pide buscar la clave wi
y su información asociada.
– Se conoce también la probabilidad qi, 0≤i≤n, de búsqueda de una clave
inexistente situada entre wi y wi+1 (con el significado obvio para q0 y qn).
– Se tiene que

– Se quiere construir un árbol binario de búsqueda para guardar las claves


que minimice el número medio de comparaciones para encontrar una
clave o para garantizar que no está.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 56
Árboles binarios de búsqueda óptimos
– Recordar que la profundidad de la raíz es 0, la de sus hijos es 1, etc.
– Si construimos un árbol en el que la clave wi está en un nodo de
profundidad di, 1≤i≤n, entonces se necesitan di+1 comparaciones para
encontrarla.
– Si con probabilidad qi, 0≤i≤n, buscamos una clave que no está en el
árbol pero que, en caso de estar, ocuparía un nodo de profundidad di
entonces se necesitan di comparaciones para garantizar que no está.
– Por tanto, el número medio de comparaciones para encontrar una clave
o para garantizar que no está (función que queremos minimizar) es:

Palabra Probabilidad
• Ejemplo: a 0, 22
qi = 0, 0≤ i ≤ 7 al 0,18
ama 0, 20
eso 0,05
si 0, 25
sin 0,02
Algoritmia básica - Javier Campos (Universidad de Zaragoza) su 0,08 57
Árboles binarios de búsqueda óptimos

si
• Solución 1:
eso • Solución 2:
a su
Creada con
estrategia voraz. Árbol perfectamente
ama sin al sin equilibrado.
C=2,43
al eso a ama si su C=2,70

ama
• Solución 3:
a si
Es óptima.

C=2,15 al eso su

sin
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 58
Árboles binarios de búsqueda óptimos
E.N. Gilbert y E.F. Moore: “Variable length encodings”,
Bell System Technical Journal, 38(4), pp. 933-968, 1959.

• Solución de programación dinámica:


Principio de optimalidad:
“Todos los subárboles de un árbol óptimo son
óptimos con respecto a las claves que contienen.”
– Consideremos un subárbol óptimo que contenga las claves wi+1, wi+2, …, wj.
– La probabilidad de que una clave buscada esté o debiera estar en ese subárbol es:
j j
mij = ∑ pk + ∑ qk
k= i + 1 k= i
– Denotemos por Cij el número medio de comparaciones efectuadas en un subárbol
óptimo que contiene las claves wi+1, wi+2, …, wj durante la búsqueda de una clave
en el árbol principal (y convenimos en que Cii=0).
– Supongamos ahora que wk ocupa la raíz de ese subárbol.
– Sea CijK el número medio de comparaciones efectuadas en ese subárbol durante la
búsqueda de una clave en el árbol principal.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 59


Árboles binarios de búsqueda óptimos
– Entonces:

• Ci,k-1 es el nº medio de comparaciones en el subárbol izquierdo.


• Ckj es el nº medio de comparaciones en el subárbol derecho.
• mij es el el nº medio de comparaciones con la raíz.

– Ahora se trata de escoger la raíz de forma que se minimice Cij:

{ }
Cij = mij + min Ci , k − 1 + Ckj , si 0≤ i < j ≤ n
i < k≤ j

Cii = 0, si 0≤ i ≤ n

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 60


Árboles binarios de búsqueda óptimos
• El ejemplo: qi = 0, 0≤ i ≤ 7

Palabra Probabilidad
a 0, 22
al 0,18
ama
eso
0, 20
0,05 { }
Cij = mij + min Ci , k− 1 + Ckj , si 0≤ i < j ≤ n
i < k≤ j
si 0, 25
sin 0,02 Cii = 0, si 0≤ i ≤ n
su 0,08
0 1 2 3 4 5 6 7
0 0 0,22 0,58 1,02 1,17 1,83 1,89 2,15

1 0 0,18 0,56 0,66 1,21 1,27 1,53

2 0 0,20 0,30 0,80 0,84 1,02

3 0 0,05 0,35 0,39 0,57
C= 4º
4 0 0,25 0,29 0,47

5 0 0,02 0,12

6 0 0,08

7 0

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 61


Árboles binarios de búsqueda óptimos
tipos probP=vector[1..n] de real;
probQ=vector[0..n] de real;
matC=vector[0..n,0..n] de real;
matSol=vector[0..n,0..n] de entero

algoritmo abbÓpt(ent p:probP; ent q:probQ; sal C:matC; sal r:matSol)


{C es la matriz definida previamente. En cada componente i,j de r se
guarda el k para el que C[i,j] resulta mínimo.}
variables i,j,k,d:entero; min,aux:real; m:matC
principio
para i:=0 hasta n hacer
C[i,i]:=0; m[i,i]:=q[i];
para j:=i+1 hasta n hacer
m[i,j]:=m[i,j-1]+p[j]+q[j]
fpara
fpara;
para j:=1 hasta n hacer
C[j-1,j]:=m[j-1,j]; r[j-1,j]:=j
fpara;
{Ya están determinados los árboles de 1 nodo.} ...

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 62


Árboles binarios de búsqueda óptimos

...
para d:=2 hasta n hacer
para j:=d hasta n hacer
i:=j-d;
min:=maxEntero;
para k:=i+1 hasta j hacer
aux:=C[i,k-1]+C[k,j];
si aux<min entonces
min:=aux;
r[i,j]:=k
fsi
fpara;
C[i,j]:=m[i,j]+min
fpara
fpara
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 63


Árboles binarios de búsqueda óptimos
tipos vectClaves=vector[1..n] de cadena;
árbol=↑nodo;
nodo=registro
dato:cadena;
iz,de:árbol
freg

algoritmo creaABB(ent w:vectClaves; ent r:matSol; sal a:árbol)


algoritmo creaRec(sal a:árbol; ent i,j:entero)
principio
si i=j entonces a:=nil
sino
nuevoDato(a);
a↑.dato:=w[r[i,j]];
creaRec(a↑.iz,i,r[i,j]-1);
creaRec(a↑.de,r[i,j],j)
fsi
fin
principio
creaRec(a,0,n)
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 64


Árboles binarios de búsqueda óptimos
• Complejidad:

Θ(n3), usando Θ(n2) posiciones de memoria.

• Es posible transformar automáticamente ciertos algoritmos


cúbicos de programación dinámica, como este, en algoritmos
cuadráticos…

F.F. Yao: “Efficient dynamic programming using


quadrangle inequalities”,
Proceedings of the 12th Annual ACM Symposium on the
Theory of Computing, pp. 429-435, 1980.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 65


Árboles binarios de búsqueda óptimos
D.E. Knuth: “Optimum binary search trees”,
Acta Informatica, 1, pp. 14-25, 1971.

• En este caso concreto basta con demostrar que:


r[i,j-1] ≤ r[i,j] ≤ r[i+1,j], si j-i≥2

(por inducción en j-i [Knu87, p. 492] D.E. Knuth. El arte de programar


ordenadores. Volumen III: Clasificación y búsqueda. Editorial Reverté, 1987)

Ahora, el coste de los dos bucles internos de abbÓpt es:

∑ (r[i + 1, j ]− r [i , j − 1]+ 1)
d ≤ j ≤n
i = j−d
= r [n − d + 1, n ]− r [0, d − 1]+ n − d + 1< 2n

Por tanto, el coste es Θ(n2).


Algoritmia básica - Javier Campos (Universidad de Zaragoza) 66
Un problema de fiabilidad de sistemas
• El problema:
– Diseñar un sistema compuesto de varios dispositivos conectados en serie.

D1 D2 D3 ••• Dn

– Sea ri la fiabilidad de Di, i.e., la probabilidad de que funcione


correctamente.

– Entonces, la fiabilidad del sistema sistema entero es:


n
∏i = 1ri

– Por ejemplo, si n=10 y ri=0,99, 1≤i≤10, la fiabilidad de cada dispositivo


es muy alta y sin embargo

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 67


Un problema de fiabilidad de sistemas
– Una forma de aumentar la D1 D2 D3 Dn
fiabilidad es replicar los D1 D2 D3 ••• Dn
dispositivos (en paralelo). D1 D3 Dn
D3
Fase 1 Fase 2 Fase 3 Fase n

– Si la fase i contiene mi copias de Di, la


probabilidad de que toda la fase falle es (1 − ri )mi
– Luego la fiabilidad de la fase i es 1 − (1− r i )mi
– Por tanto, si ri=0,99 y mi=2, la fiabilidad de la fase i es 0,9999.
– En realidad, la fiabilidad de la fase i es algo menor que 1 − (1− r i )mi
(las copias de un mismo dispositivo no son completamente
independientes pues su diseño es común, por ejemplo);
si denotamos la fiabilidad de la fase i por φi (mi )
– entonces la fiabilidad del sistema es:
∏1≤i ≤n φi (mi )
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 68
Un problema de fiabilidad de sistemas
– El problema: maximizar la fiabilidad replicando los
dispositivos y con alguna limitación en el coste.

Donde ci es el coste de cada unidad de dispositivo i.


– Como ci>0 y mj≥1, entonces 1≤mi≤ui con

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 69


Un problema de fiabilidad de sistemas
– Una solución óptima m1, m2, …, mn es el resultado de una
secuencia de decisiones, una por cada mi.

– Denotemos:
fi (x) = máximo ∏ φ j (mj )
1≤ j ≤i
sujeto a ∑ cj m j ≤ x
1≤ j ≤i
1≤ mj ≤ u j , 1≤ j ≤ i

Entonces el valor de una solución óptima es fn(c).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 70


Un problema de fiabilidad de sistemas
– La última decisión requiere elegir mn de entre {1,2,3,…,un}.
– Una vez tomada la última decisión, las restantes decisiones deben utilizar
el resto de fondos c – cnmn de forma óptima.
– Se cumple el principio de optimalidad y

f n (c) = max
1 ≤mn ≤u
{
n
φn ( mn ) f n − 1 (c − cn m n ) }

– En general, para fi(x), i≥1, se tiene:

f i (x ) = max
1 ≤ m i ≤ ui
{φ i ( m i ) f i − 1 (x − ci m i ) }
f 0 (x) = 1, para todox , 0≤ x ≤ c

(ver, además, http://webdiis.unizar.es/asignaturas/AB/?p=1292 )


– Se resuelve de forma similar al problema de la mochila 0-1 (ejercicio).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 71


El problema del viajante de comercio
• Recordar:

– Encontrar un recorrido de longitud mínima para un viajante que tiene que


visitar varias ciudades y volver al punto de partida, conocida la distancia
existente entre cada dos ciudades.

– Es decir, dado un grafo dirigido con arcos de ¡Más


vueltas!
longitud no negativa, se trata de encontrar
un circuito de longitud mínima que comience
y termine en el mismo vértice y pase
exactamente una vez por cada uno de los
vértices restantes (circuito hamiltoniano).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 72


El problema del viajante de comercio
– Sean G=(V,A) un grafo orientado,
V={1,2,…,n},
Lij la longitud de (i,j)∈A,
Lij=∞ si no existe el arco (i,j).
– El circuito buscado empieza en el vértice 1.
Se compone de (1,j), con j≠1, seguido de un camino de j a 1 que pasa
exactamente una vez por cada vértice de V \ {1,j}.
– Principio de optimalidad: si el circuito es óptimo, el camino de j a 1 debe
serlo también.
– Sea S⊆V \ {1} un subconjunto de vértices e i∈V \ S un vértice;
llamamos g(i,S) a la longitud del camino mínimo desde i hasta 1 que pase
exactamente una vez por cada vértice de S.
Entonces:
longitud del circuito óptimo = g(1,V \ {1}) =

{ }
= min L1j + g( j ,V \ {1, j })
2≤ j ≤n
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 73
El problema del viajante de comercio
– Más en general, si i≠1, S≠Ø e i∉S:

{ }
g (i ,S) = min Lij + g( j ,S \ { j })
j ∈S
(*)

Además:
g (i ,∅) = Li 1, i = 2,3,…, n

– Método de resolución:
• Usar (*) y calcular g para todos los conjunto S con un solo vértice (distinto
del 1).
• Volver a usar (*) y calcular g para todos los conjuntos S de dos vértices
(distintos del 1) y así sucesivamente.
• Cuando se conoce el valor de g para todos los conjuntos S a los que sólo les
falta un vértice (distinto del 1) basta calcular g(1,V \ {1}).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 74


El problema del viajante de comercio
• Ejemplo. Sea G el grafo completo
de cuatro vértices con longitudes: 0 10 15 20
L = 5 0 9 10
6 13 0 12
8 8 9 0 

– Inicialización:
g(2,Ø) = 5; g(3,Ø) = 6; g(4,Ø) = 8.

Usar
j ∈S
{
g (i ,S) = min Lij + g( j ,S \ { j }) } para obtener:

g(2,{3}) = L23 + g(3,Ø) = 15;


g(2,{4}) = L24 + g(4,Ø) = 18;

g(3,{2}) = 18; g(3,{4}) = 20;


g(4,{2}) = 13; g(4,{3}) = 15.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 75


El problema del viajante de comercio
– Ahora, utilizando de nuevo (*) para conjuntos de dos elementos:
{
g (2,{ 3, 4}) = min L23+ g(3,{4}), L24+ g(4,{3}) = }
= min{29,25} = 25;

{
g (3,{ 2, 4}) = min L32+ g(2,{4}), L24+ g(4,{2}) = }
= min{31,25} = 25;

{
g (4 ,{ 2, 3}) = min L42+ g(2,{3}), L43+ g(3,{2}) =}
= min{23,27} = 23.

– Finalmente:
g (1,{ 2, 3, 4}) = min{ L12+ g(2,{3,4}),
L13+ g(3,{2,4}),
L14 + g(4,{2,3}) } =
= min{ 35,40,43 } = 35.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 76
El problema del viajante de comercio
• Si además se quiere saber cómo se construye el circuito óptimo:
Utilizar una función adicional
J(i,S) es el valor de j que minimiza g(i,S) al aplicar la fórmula (*).
• En el ejemplo:
J(2,{3,4}) = 4; J(3,{2,4}) = 4;
J(4,{2,3}) = 2; J(1,{2,3,4}) = 2.

Y el circuito óptimo será:


1 →J(1,{2,3,4}) = 2
→J(2,{3,4}) = 4
→J(4,{3}) = 3
→1

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 77


El problema del viajante de comercio
• Implementación recursiva ineficiente:
función g(i,S) devuelve nat
variables másCorto,distancia,j:nat
principio
si S=Ø entonces devuelve L[i,1]
sino
másCorto:=∞;
para todo j en S hacer
distancia:=L[i,j]+g(j,S\{j});
si distancia<másCorto entonces
másCorto:=distancia
fsi
fpara;
devuelve másCorto
fsi
fin

Se calcula repetidas veces el mismo valor de g: Ω((n-1)!)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 78


El problema del viajante de comercio
• Utilización de una “función con memoria”:
{se usa una tabla gtab cuyos elementos se inicializan con -1}
función g(i,S) devuelve nat
variables másCorto,distancia,j:nat
principio
si S=Ø entonces devuelve L[i,1]
sino
si gtab[i,S]≥0 entonces devuelve gtab[i,S]
sino
másCorto:=∞;
para todo j en S hacer
distancia:=L[i,j]+g(j,S\{j});
si distancia<másCorto entonces másCorto:=distancia fsi
fpara;
gtab[i,S]:=másCorto;
devuelve másCorto
fsi
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 79


El problema del viajante de comercio
• Coste del algoritmo:
– cálculo de g(j,Ø): n-1 consultas a una tabla,
– cálculo de los g(j,S) tales que 1≤card(S)=k≤n-2:

– cálculo de g(1,V\{1}): n-1 sumas.

 n− 2 
Tiempo de cálculo:
 k= 1

 k  (
Θ  2(n − 1) + ∑ (n − 1)k n − 2  = Θ n22n )
r  
puesto que ∑ k  rk  = r 2r − 1
k= 1

(Este tiempo es mejor que Ω(n!) que resultaría de la estrategia de fuerza


bruta, pero…)
– Coste en espacio (para conservar g y J): Ω(n2n)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 80


El problema del viajante de comercio
• Para hacernos una idea del coste…

número de tiempo tiempo espacio


vértices fuerza bruta prog . dinámica prog . dinámica
n n! n2 2n n2n

5 120 800 160


10 3.628.800 102.400 10.240
Si las unidades
son microsegundos:

menos de 7 minutos 15 1, 31 × 10 12 7.372.800 491.520

20 2, 43 × 10 18 419.430.400 20.971.520
más de 77.000 años
25 1, 55 × 10 25 20.971.520.000 838.860.800

30 2, 65 × 10 32 966.367.641.600 32.212.254.720

50 3, 04 × 10 64 2, 81 × 10 18 5, 62 × 10 16

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 81


Planificación de trabajos
• El problema:
Sea un sistema en el que la realización de un conjunto de trabajos requiere
la ejecución por parte de un conjunto de agentes (o procesadores) de una
serie de tareas diferentes para cada trabajo.
• n trabajos requiriendo cada uno m tareas:
T1i, T2i, …, Tmi, 1≤i≤n
• la tarea Tji la realiza el procesador Pj, 1≤j≤m, y requiere un tiempo tji
• Planificación para los n trabajos:
Es una asignación de tareas a intervalos de tiempo en los procesadores.
• la tarea Tji debe asignarse a Pj
• un procesador no puede tener más de una tarea asignada en cada instante de
tiempo
• para todo trabajo i, el procesamiento de Tji, j>1, no puede empezar hasta que
Tj-1,i haya terminado

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 82


Planificación de trabajos
• Ejemplo:
Se tiene que planificar la ejecución de dos trabajos en tres procesa- 2 0
dores, de forma que los tiempos de cada tarea vienen dados por: T = 3 3
Dos planificaciones posibles: 5 2

(a)

(b)

La planificación (b) se dice no-interruptiva (non-preemptive) porque el


procesamiento de una tarea no se interrumpe hasta que ésta ha terminado.
La planificación (a) se dice interruptiva (preemptive) porque el trabajo 1 se
apropia del procesador 2 antes de que éste termine con el trabajo 2.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 83


Planificación de trabajos
– El tiempo de terminación del trabajo i en la planificación S es el instante,
fi(S), en que todas las tareas del trabajo i han terminado.

En el ejemplo (a), f1(Sa)=10 y f2(Sa)=12.


En el ejemplo (b), f1(Sb)=11 y f2(Sb)=5.

– El tiempo de terminación, f(S), de la planificación S es:

{
F (S) = max fi (S)
1≤i ≤n
}
– El tiempo medio de terminación, MFT(S), se define como:

1
MFT(S) = ∑ fi (S)
n 1≤i ≤n

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 84


Planificación de trabajos
– Planificación con tiempo de terminación óptimo (OFT) para un conjunto
de trabajos:
es una planificación no-interruptiva, S, para la que F(S) es mínimo entre
todas las planificaciones no-interruptivas.
– Planificación interruptiva y con tiempo de terminación óptimo (POFT):
es una planificación interruptiva, S, para la que F(S) es mínimo entre
todas las planificaciones interruptivas.
– Planificación con tiempo medio de terminación óptimo (OMFT):
es una planificación no-interruptiva, S, para la que MFT(S) es mínimo
entre todas las planificaciones no-interruptivas.
– Planificación interruptiva y con tiempo medio de terminación óptimo
(POMFT):
es una planificación interruptiva, S, para la que MFT(S) es mínimo entre
todas las planificaciones interruptivas.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 85


Planificación de trabajos
– El cálculo de OFT y POFT para m>2 y el cálculo de OMFT es
computacionalmente difícil (es NP-duro).
– El cálculo de OFT para m=2 puede hacerse mediante programación
dinámica.
• Caso m=2:
– Denotemos T1i como ai y T2i como bi.
– Una planificación está completamente especificada fijando una
permutación de los trabajos en uno de los procesadores (coincidirá con el
otro procesador).
Cada tarea empezará tan pronto como sea posible.
Ejemplo con 5 trabajos:

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 86


Planificación de trabajos
– Supongamos, para simplificar, que ai≠0, 1≤i≤n
(si hay trabajos con ai=0, se construye primero la planificación óptima
para los trabajos con ai≠0 y después se añaden delante los trabajos con
ai=0).

– Principio de optimalidad:

Una permutación (planificación) óptima es tal que, fijado el primer trabajo


de la permutación, el resto de la permutación es óptimo con respecto al
estado en que quedan los dos procesadores después de terminar el primer
trabajo.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 87


Planificación de trabajos
– Sea g(S,t) la longitud (duración) de una planificación óptima para el
subconjunto de trabajos S suponiendo que el procesador 2 no estará
disponible hasta el instante t.
Entonces:
{ (
g (S, t) = min ai + g S \ {i }, bi + max{t − ai ,0}
i ∈S
)}
con g(Ø,t) = max{t,0} y ai≠0, 1≤i≤n.
caso t≥ai: 0 ai t t+bi
ai aj, j∈S\{i}
bi bj, j∈S\{i}

0 t+bi-ai

caso t<ai: 0 t ai ai+bi

ai aj, j∈S\{i}
bi bj, j∈S\{i}

0 bi
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 88
Planificación de trabajos
– La ecuación recursiva resultante podría resolverse de forma análoga a la
del problema del viajante de comercio, pero existe una solución mejor…
– Supongamos que i y j son los dos primeros trabajos (y en ese orden) en la
planificación óptima del subconjunto S; entonces:

Pero: tij = bj + max{bi + max{t − ai ,0}− aj ,0} =

= bj + bi − aj + max{max{t − ai ,0}, aj − bi } =

= bj + bi − aj + max{t − ai , aj − bi ,0} =

= bj + bi − aj − ai + max{t, ai + aj − bi , ai }

Si los dos primeros trabajos fueran j e i:


g′ (S, t) = aj + ai + g′ (S \ { j , i }, bi + bj − ai − aj + max{t, aj + ai − bj , aj })

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 89


Planificación de trabajos
– Entonces: g (S, t) ≤ g′ (S, t) ⇔
⇔ max{t, ai + aj − bi , ai } ≤ max{t, aj + ai − bj , aj }

Para que esto sea cierto para todo valor de t, se precisa:


max{ai + aj − bi , ai } ≤ max{aj + ai − bj , aj }

Es decir:
ai + aj + max{− bi ,− aj } ≤ aj + ai + max{− bj ,−ai }

O sea:
min{bi ,a j } ≥ min{bj , ai } (*)

– Luego existe una planificación óptima en la que cada par (i,j) de trabajos
adyacentes verifica (*).
– Puede demostrarse que todas las planificaciones que verifican (*) tienen la
misma longitud.
Por tanto, basta generar una permutación para la que se cumpla (*) para
todo par de trabajos adyacentes.
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 90
Planificación de trabajos
– Ahora, si

Entonces el trabajo i debería ser el primero en una planificación óptima.


– En cambio, si

Entonces el trabajo j debería ser el último en una planificación óptima.

– Luego podemos decidir la posición de uno de los trabajos (el primero o el


último).
Repitiendo el proceso, se puede construir la planificación óptima.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 91


Planificación de trabajos
• Por tanto la solución es:

i) ordenar los ai y bi en orden no decreciente;

ii) si el siguiente número de la secuencia es ai y el trabajo i no ha sido


planificado todavía, planificar el trabajo i en la posición más a la
izquierda de entre los que restan;
si el siguiente número es bj y el trabajo j no ha sido planificado
todavía, planificar el trabajo j en la posición más a la derecha de entre
los que restan;

(nótese que el algoritmo sirve también si hay trabajos con ai=0)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 92


Planificación de trabajos
• Ejemplo:
– Sean n=4, (a1,a2,a3,a4) = (3,4,8,10) y (b1,b2,b3,b4) = (6,2,9,15).
– La secuencia ordenada de los ai y los bi es:
(b2,a1,a2,b1,a3,b3,a4,b4) = (2,3,4,6,8,9,10,15).

– Sea σ1,σ2,σ3,σ4 la secuencia óptima.


• Como el número menor es b2, entonces σ4=2.
• El siguiente número es a1 luego σ1=1.
• El siguiente es a2 pero el trabajo 2 ya ha sido planificado.
• El siguiente es b1 pero 1 ya ha sido planificado.
• El siguiente es a3 luego hacemos σ2=3.
• Por tanto, σ3=4.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 93


Planificación de trabajos
• Coste: O(n log n)

• Nótese que la solución directa de


{ (
g (S, t) = min ai + g S \ {i }, bi + max{t − ai ,0}
i ∈S
)}

hubiera llevado al menos O(2n), que es el número de


subconjuntos S diferentes para los que habría que calcular g(S,t).

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 94


Una competición internacional
• El problema:
Dos equipos A y B se enfrentan un máximo de 2n – 1 veces, ganando el
primer equipo que acumule n victorias.
Supongamos que no es posible un partido nulo, que los resultados de cada
partido son independientes y que hay una probabilidad constante p de que
A gane un partido y q = 1 – p de que lo gane B.
¿Cuál es la probabilidad, a priori, de que gane A?
• El planteamiento:
– Sea P(i,j) la probabilidad de que A gane la competición sabiendo que le
faltan todavía i victorias y a B le faltan j.
– Entonces, antes del primer partido, la probabilidad de que A gane la
competición es P(n,n).
– Si A ya ha acumulado todas las victorias necesarias entonces es el ganador
de la competición, es decir: P(0,j) = 1, 1≤j≤n.
– Igualmente, P(i,0) = 0, para 1≤i≤n.
– La ecuación recurrente es:
P(i,j) = pP(i – 1,j) + qP(i,j – 1), para i,j≥1.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 95


Una competición internacional
• La solución directa:

función P(i,j) devuelve real


{pp (pq) es la probabilidad de que gane A (B)}
principio
si i=0 entonces
devuelve 1
sino
si j=0 entonces
devuelve 0
sino
devuelve pp*P(i-1,j)+pq*P(i,j-1)
fsi
fsi
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 96


Una competición internacional
• Coste de la solución directa:
– Sea T(k) el tiempo necesario en el caso peor para calcular P(i,j) con i+j=k.
T (1) = c
T (k) ≤ 2T (k − 1) + d, k > 1

donde c y d son dos constantes.


– Luego, T(k) es O(2k) y por tanto T(2n) es O(22n).
 i + j
– Exactamente el número de llamadas recursivas es 2 −2
 j 

 n
– Por tanto, el tiempo para calcular P(n,n) es Ω( 2 )
 n
y puede demostrarse que  2n 2n
≥2 (2n + 1)
 n

– En definitiva, el tiempo de la solución directa para calcular P(n,n) es


O(4n) y Ω(4n/n).
Puede demostrarse que el tiempo es Θ 4n n ( )
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 97
Una competición internacional
• El problema de la solución directa:
– Como siempre en programación dinámica, se calcula muchas veces el
valor de cada P(i,j).
– Solución mejor: usar una tabla para almacenar los P(i,j).
– Ejemplo (para p = q = 1/2):

1 2 21 32 13 16 15 16 1 4
11 32 1 2 11 16 7 8 1 3 P(i,j) = pP(i-1,j) + qP(i,j-1)
3 16 5 16 1 2 3 4 1 2
j
1 16 1 8 1 4 1 2 1 1
0 0 0 0 0
4 3 2 1 0
i
la matriz se completa, por ejemplo,
por filas (de abajo a arriba, j=0, 1, …, n)
y en cada fila por columnas (de dch. a izq., i=0, 1, …, n)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 98


Una competición internacional
• La solución:

función apuestas(n:natural; p:real) devuelve real


variables tabP:vector[0..n,0..n]de real;
q:real; i,j:natural
principio
q:=1-p;
para j:=1 hasta n hacer
tabP[0,j]:=1; tabP[j,0]:=0;
para i:=1 hasta n hacer
tabP[i,j]:=p*tabP[i-1,j] + q*tabP[i,j-1]
fpara
fpara;
devuelve tabP[n,n]
fin

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 99


Una competición internacional
• Coste:

– En tiempo: Θ(n2)

– En espacio: Θ(n2), aunque se puede reducir fácilmente a Θ(n)

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 100


Triangulación de polígonos
• Problema:
(8,26) (15,26)
Dados los vértices de un polígono, v2 v3
se trata de seleccionar un conjunto de
cuerdas (líneas entre vértices no (0,20) v1 v4 (27,21)
adyacentes) de modo que ningún par
de cuerdas se cruce entre sí y que todo v5 (22,12)
(0,10) v0
el polígono quede dividido en
triángulos.
v6 (10,0)

Además, la longitud total de las cuerdas debe ser mínima (triangulación


minimal).
– Utilidad: se puede emplear para sombrear objetos tridimensionales en una
imagen virtual (bidimensional).
– Otra: interpolación numérica de funciones de dos variables.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 101


Triangulación de polígonos
• Resolución de programación dinámica:
– Consideremos un polígono definido por sus vértices v0, v1, …, vn-1.
– Sea Sis el subproblema de tamaño s partiendo del vértice vi, es decir, el
problema de la triangulación minimal del polígono formado por los s
vértices que comienzan en vi y siguen en el sentido de las agujas del reloj
(vi, vi+1, …, vi+s-1), contando con la cuerda (vi,vi+s-1).

v2 v3

v1 v4
S65

v5
v0

v6

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 102


Triangulación de polígonos
– Ahora, para triangular el polígono Sis, hay s – 2 posibilidades:

1. Tomar el vértice vi+1 v2 v3 2. Tomar el vértice vi+s-2


para formar un para formar un triángulo v2 v3
triángulo con S04 con las cuerdas
las cuerdas v1
(vi,vi+s-1) y v1
(vi,vi+s-1) y (vi,vi+s-2) y con el
(vi+1,vi+s-1) y
S65
tercer lado S64 S65
con el tercer v0 (vi+s-2,vi+s-1),
lado (vi,vi+1), y después resolver el v0
y después resolver el subproblema Si,s-1.
subproblema Si+1,s-1. v6
v6

v2 v3
3. Para algún k entre 2 y s-3, S13
tomar el vértice vi+k y formar v1
un triángulo con lados
(vi,vi+k), (vi+k,vi+s-1) y (vi,vi+s-1), S65
S63
y después resolver los
subproblemas Si,k+1 y Si+k,s-k. v0

v6
Algoritmia básica - Javier Campos (Universidad de Zaragoza) 103
Triangulación de polígonos
– Por tanto, si denotamos por Cis el coste de la triangulación Sis,
se obtiene la siguiente relación recursiva:
Cis = min
1≤k ≤s −2
{
Ci , k + 1 + Ci + k , s − k + D(vi ,vi + k ) +
+ D(vi + k ,vi + s − 1 ) }
para 0≤i≤n-1, 4≤s≤n;

donde:
D(vp,vq) es la longitud de la cuerda entre los vértices vp y vq si
vp y vq no son vértices adyacentes en el polígono;
y D(vp,vq) es 0 si vp y vq son adyacentes.

Además, Cis = 0 para 0≤i≤n-1, 2≤s<4.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 104


Triangulación de polígonos
• Solución recursiva inmediata:

– Aplicando la ecuación recurrente anterior


– Problema: el número de llamadas crece exponencialmente con el número
de vértices
– Sin embargo, sin contar el problema original, sólo hay n(n-4)
subproblemas diferentes que hay que resolver
– Por tanto, la solución recursiva resuelve muchas veces un mismo
subproblema

• Solución eficiente:

– Utilización de una tabla para almacenar los costes de las soluciones de los
subproblemas

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 105


Triangulación de polígonos
(1) (8,26) (15,26)
C65 = min{ C62 + C04 + D(v6 ,v0) + D(v0 ,v3), v2 v3
(2)
C63 + C13 + D(v6 ,v1) + D(v1 ,v3),
(3) (0,20) v1 v4 (27,21)
C64 + C23 + D(v6 ,v2) + D(v2 ,v3) } =
= min {38,09 ; 38,52 ; 43,97 } = 38,09
v5 (22,12)
(0,10) v0
C07 =
7
75,43 v6 (10,0)
C06 = C16 = C26 = C36 = C46 = C56= C66 =
6
53,54 55,22 57,58 64,69 59,78 59,78 63,62
C05 = C15 = C25 = C35 = C45 = C55= C65=
5
37,54 31,81 35,49 37,74 45,50 39,98 38,09
(1) C04 = C14 = C24 = C34 = C44 = C54 = C64 = (3)
4
16,16 16,16 15,65 15,65 22,69 22,69 17,89
C03 = C13 = C23= C33= C43= C53 = C63 =
3
0 0 (2) 0 (3) 0 0 0 0 (2)
C02 = C12 = C22= C32= C42= C52 = C62 =
2
0 0 0 0 0 0 0 (1)
s i=0 1 2 3 4 5 6

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 106


Triangulación de polígonos
• Hemos calculado el coste de la triangulación mínima pero,
¿cuál es esa triangulación?

– Para cada posición (i,s) de la tabla se necesita almacenar, además del


coste, el valor del índice k que produjo el mínimo.

– Entonces la solución consta de las cuerdas (vi,vi+k) y (vi+k,vi+s-1)


(a menos que una de ellas no sea cuerda, porque k=1 o k=s-2),
más las cuerdas que estén implicadas por las soluciones de Si,k+1 y Si+k,s-k.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 107


Triangulación de polígonos
• En el ejemplo: v2 v3
– El valor de C07 procede de k=5. Es decir, el problema
S07 se divide en S06 y S53. v1 v4
2 3
2
S53 es un problema trivial, de coste 0.
Así, se introduce la cuerda (v0,v5), de coste 22’09,
v5
y se debe resolver S06. v0
1

v6

– El valor de C06 procede de k=2. Por tanto, el problema se divide en S03 y S24.
S03 es un triángulo con vértices v0, v1 y v2, luego no precisa ser resuelto, mientras
que S24 es un cuadrilátero, definido por v2, v3, v4 y v5, y debe ser resuelto.
Además, hay que incluir los costes de las cuerdas (v0,v2) y (v2,v5), que son 17’89 y
19’80.
– El valor de C24 se obtiene con k=1, dando los subproblemas S22 y S33, que tienen
tamaño menor o igual que tres y, por tanto, coste 0.
Se introduce la cuerda (v3,v5), con coste 15’65.

Algoritmia básica - Javier Campos (Universidad de Zaragoza) 108


Búsqueda con retroceso
(backtracking)

Simona Bernardi
Universidad de Zaragoza

Presentación reducida y adaptada de la original de J. Campos

Este documento está sujeto a una licencia de uso Creative Commons. No se permite
un uso comercial de la obra original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Búsqueda con retroceso

Resumen

Método general
Aplicación
Problema de las reinas
Ciclos hamiltonianos
Atravesar un laberinto
El problema de la mochila 0-1

Simona Bernardi Búsqueda con retroceso 2 / 44


Búsqueda con retroceso
Método general

Problema de búsqueda
Búsqueda de la mejor solución o todas las soluciones
que satisfacen a ciertas condiciones

Simona Bernardi Búsqueda con retroceso 3 / 44


Búsqueda con retroceso
Método general

Problema de búsqueda
Búsqueda de la mejor solución o todas las soluciones
que satisfacen a ciertas condiciones

Cada solución es el resultado de una secuencia de decisiones


Existe una función objetivo que debe ser satisfecha por cada selección
u optimizada

Simona Bernardi Búsqueda con retroceso 3 / 44


Búsqueda con retroceso
Método general

Problema de búsqueda
Búsqueda de la mejor solución o todas las soluciones
que satisfacen a ciertas condiciones

Cada solución es el resultado de una secuencia de decisiones


Existe una función objetivo que debe ser satisfecha por cada selección
u optimizada

Tipos de problemas
Se conoce un criterio óptimo de selección en cada decisión
⇒ Técnica voraz
Se cumple el principio de optimalidad de Bellman
⇒ Técnica de la programación dinámica
Otros en lo que no hay más remedio que buscar

Simona Bernardi Búsqueda con retroceso 3 / 44


Búsqueda con retroceso
Método general

Planteamiento del problema


Buscar todas las soluciones que satisfagan a un predicado P
Solución: una n-tupla (x1 , . . . , xn ) donde cada xi ∈ Ci
Si |CQ
i | = ti entonces el tamaño del espacio de soluciones posibles es
t = ni=1 ti

Simona Bernardi Búsqueda con retroceso 4 / 44


Búsqueda con retroceso
Método general

Planteamiento del problema


Buscar todas las soluciones que satisfagan a un predicado P
Solución: una n-tupla (x1 , . . . , xn ) donde cada xi ∈ Ci
Si |CQ
i | = ti entonces el tamaño del espacio de soluciones posibles es
t = ni=1 ti

Métodos de búsqueda
Fuerza bruta: examinar todas las t tuplas y seleccionar las que
safisfacen P
Retroceso (backtracking, en inglés): formar cada tupla de manera
progresiva, elemento a elemento, comprobando para cada elemento xi
añadido a la tupla que (x1 , . . . , xi ) puede conducir a una tupla
completa satisfactoria

Simona Bernardi Búsqueda con retroceso 4 / 44


Búsqueda con retroceso
Método general

Planteamiento del problema II

Deben existir unos predicados acotadores Pi (x1 , . . . , xi )


Los Pi dicen si (x1 , . . . , xi ) puede conducir a una solución

Simona Bernardi Búsqueda con retroceso 5 / 44


Búsqueda con retroceso
Método general

Planteamiento del problema II

Deben existir unos predicados acotadores Pi (x1 , . . . , xi )


Los Pi dicen si (x1 , . . . , xi ) puede conducir a una solución

Diferencia entre fuerza bruta y búsqueda con retroceso


Si se comprueba que Pi (x1 , . . . , xi ) = false, se evita formar las
ti+1 × · · · × tn tuplas que comienzan por (x1 , . . . , xi )

Simona Bernardi Búsqueda con retroceso 5 / 44


Búsqueda con retroceso
Método general

Planteamiento del problema II

Deben existir unos predicados acotadores Pi (x1 , . . . , xi )


Los Pi dicen si (x1 , . . . , xi ) puede conducir a una solución

Diferencia entre fuerza bruta y búsqueda con retroceso


Si se comprueba que Pi (x1 , . . . , xi ) = false, se evita formar las
ti+1 × · · · × tn tuplas que comienzan por (x1 , . . . , xi )

Tipos de restricciones que tienen que cumplir las n-tuplas solución


Explı́citas: describen el conjunto Ci de valores que puede tomar xi
(espacio de soluciones posibles C1 × · · · × Cn )
Implı́cita: describen las relaciones que deben cumplirse entre los xi
(qué soluciones posibles satisfacen el predicado objetivo P)

Simona Bernardi Búsqueda con retroceso 5 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema de las ocho reinas


Colocar ocho reinas en un tablero de ajedrez sin que se den jaque
Dos reinas se dan jaque si comparten fila, columna o diagonal

Simona Bernardi Búsqueda con retroceso 6 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema de las ocho reinas


Colocar ocho reinas en un tablero de ajedrez sin que se den jaque
Dos reinas se dan jaque si comparten fila, columna o diagonal

64

Fuerza bruta: 8 = 4.426.165.368

Simona Bernardi Búsqueda con retroceso 6 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema de las ocho reinas


Colocar ocho reinas en un tablero de ajedrez sin que se den jaque
Dos reinas se dan jaque si comparten fila, columna o diagonal

64

Fuerza bruta: 8 = 4.426.165.368

Replanteamiento del problema: “colocar una reina en cada fila del


tablero de forma que no se den jaque”
Para ver si dos reinas se dan jaque basta con ver si comparten
columna o diagonal

Simona Bernardi Búsqueda con retroceso 6 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema de las ocho reinas


Colocar ocho reinas en un tablero de ajedrez sin que se den jaque
Dos reinas se dan jaque si comparten fila, columna o diagonal

64

Fuerza bruta: 8 = 4.426.165.368

Replanteamiento del problema: “colocar una reina en cada fila del


tablero de forma que no se den jaque”
Para ver si dos reinas se dan jaque basta con ver si comparten
columna o diagonal

Representación de una solución


Toda solución del problema puede representarse con una 8-tupla
(x1 , . . . , x8 ) en la que xi es la columna en la que se coloca la reina que
está en la fila i del tablero
Simona Bernardi Búsqueda con retroceso 6 / 44
Búsqueda con retroceso
Aplicación (problema de las reinas)

Restricciones
Explı́citas: Ci = {1, 2, 3, 4, 5, 6, 7, 8}, 1 ≤ i ≤ 8
El espacio de soluciones consta de 88 (16.777.216) 8-tuplas

Simona Bernardi Búsqueda con retroceso 7 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Restricciones
Explı́citas: Ci = {1, 2, 3, 4, 5, 6, 7, 8}, 1 ≤ i ≤ 8
El espacio de soluciones consta de 88 (16.777.216) 8-tuplas
Implı́citas: No puede haber dos reinas en la misma columna o en la
misma diagonal
Se deduce que todas las soluciones son permutaciones de la 8-tupla
(1, 2, 3, 4, 5, 6, 7, 8)
El espacio de soluciones se reduce de 88 a 8! (40.320) 8-tuplas

Simona Bernardi Búsqueda con retroceso 7 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Restricciones
Explı́citas: Ci = {1, 2, 3, 4, 5, 6, 7, 8}, 1 ≤ i ≤ 8
El espacio de soluciones consta de 88 (16.777.216) 8-tuplas
Implı́citas: No puede haber dos reinas en la misma columna o en la
misma diagonal
Se deduce que todas las soluciones son permutaciones de la 8-tupla
(1, 2, 3, 4, 5, 6, 7, 8)
El espacio de soluciones se reduce de 88 a 8! (40.320) 8-tuplas

Una solución: (4, 6, 8, 2, 7, 1, 3, 5)

Simona Bernardi Búsqueda con retroceso 7 / 44


Búsqueda con retroceso
Método general

Representación del espacio de soluciones


Para facilitar la búsqueda, se adopta una organización en árbol del
espacio de soluciones

Simona Bernardi Búsqueda con retroceso 8 / 44


Búsqueda con retroceso
Método general

Representación del espacio de soluciones


Para facilitar la búsqueda, se adopta una organización en árbol del
espacio de soluciones
Ejemplo para el problema de las cuatro reinas (tablero 4 × 4):

Árbol de
permutaciones
El espacio de
soluciones está
definido por todos los
caminos desde la raı́z
a cada hoja (hay 4!
hojas)

Simona Bernardi Búsqueda con retroceso 8 / 44


Búsqueda con retroceso
Método general

Esquema algorı́tmico

Sean
(x1 , . . . , xi ) un camino de la raı́z hasta un nodo del árbol del espacio de
estados
G (x1 , . . . , xi ) el conjunto de los valores posibles de xi+1 tales que
(x1 , . . . , xi+1 ) es un camino hasta un nodo del árbol

Simona Bernardi Búsqueda con retroceso 9 / 44


Búsqueda con retroceso
Método general

Esquema algorı́tmico

Sean
(x1 , . . . , xi ) un camino de la raı́z hasta un nodo del árbol del espacio de
estados
G (x1 , . . . , xi ) el conjunto de los valores posibles de xi+1 tales que
(x1 , . . . , xi+1 ) es un camino hasta un nodo del árbol
Suponemos que existe algún predicado acotador A tal que
A(x1 , . . . , xi+1 ) = falso ⇒ el camino (x1 , . . . , xi+1 ) no puede extenderse
para alcanzar una solución
Por tanto, los candidatos xi+1 son los valores de G (x1 , . . . , xi ) tales
que A(x1 , . . . , xi+1 ) = verdadero

Simona Bernardi Búsqueda con retroceso 9 / 44


Búsqueda con retroceso
Método general

Esquema algorı́tmico

Sean
(x1 , . . . , xi ) un camino de la raı́z hasta un nodo del árbol del espacio de
estados
G (x1 , . . . , xi ) el conjunto de los valores posibles de xi+1 tales que
(x1 , . . . , xi+1 ) es un camino hasta un nodo del árbol
Suponemos que existe algún predicado acotador A tal que
A(x1 , . . . , xi+1 ) = falso ⇒ el camino (x1 , . . . , xi+1 ) no puede extenderse
para alcanzar una solución
Por tanto, los candidatos xi+1 son los valores de G (x1 , . . . , xi ) tales
que A(x1 , . . . , xi+1 ) = verdadero
Supongamos finalmente, que existe un predicado R que determina si
un camino (x1 , . . . , xi+1 ) es una solución.

Simona Bernardi Búsqueda con retroceso 9 / 44


Búsqueda con retroceso
Método general

Esquema algorı́tmico

algoritmo buscarSol(ent k:entero; entsal sol:vector[1..n] de elmto)


{Pre: sol[1..k-1] es prometedora}
variable nodo:elmto
principio
para todo nodo en G(sol,1,k-1) hacer {G(sol,1,n) = \emptyset}
sol[k]:=nodo;
si A(sol,1,k) entonces
si R(sol,1,k) entonces
guardar(sol,1,k) {se guardan todas las soluciones}
fsi;
buscarSol(k+1,sol)
fsi
fpara
fin

La llamada inicial: buscarSol(1,solución);

Simona Bernardi Búsqueda con retroceso 10 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema de las cuatro reinas

16 nodos frente a los 65 del árbol completo

Simona Bernardi Búsqueda con retroceso 11 / 44


Búsqueda con retroceso
Método general

Observaciones

El árbol no se construye explı́citamente sino implicı́tamente mediante


las llamadas recursivas del algoritmo de búsqueda
El algoritmo no hace llamada recursivas cuando
k = n + 1 (G(sol,1,n)= ∅) o
ningún nodo generado por G satisface el predicado A
Backtracking: búsqueda de primero en profundidad y con predicados
acotadores
El algoritmo halla todas las soluciones y además éstas pueden ser de
longitud variable

Simona Bernardi Búsqueda con retroceso 12 / 44


Búsqueda con retroceso
Método general

Variantes a la solución propuesta


Limitar el número de soluciones a una sola añadiendo un parámetro
booleano de salida que indique si se ha encontrado la solución

Simona Bernardi Búsqueda con retroceso 13 / 44


Búsqueda con retroceso
Método general

Variantes a la solución propuesta


Limitar el número de soluciones a una sola añadiendo un parámetro
booleano de salida que indique si se ha encontrado la solución
Forzar a que sólo los nodos hoja puedan significar una solución
(realizando la recursión sólo si no se ha encontrado un nodo solución
si R(sol,1,k) entonces
guardar(sol,1,k)
sino
buscarSol(k+1,sol)
fsi

Simona Bernardi Búsqueda con retroceso 13 / 44


Búsqueda con retroceso
Método general

Variantes a la solución propuesta


Limitar el número de soluciones a una sola añadiendo un parámetro
booleano de salida que indique si se ha encontrado la solución
Forzar a que sólo los nodos hoja puedan significar una solución
(realizando la recursión sólo si no se ha encontrado un nodo solución
si R(sol,1,k) entonces
guardar(sol,1,k)
sino
buscarSol(k+1,sol)
fsi

Resolver problemas de optimización


Hay que guardar la mejor solución encontrada hasta el momento
Se mejora la eficiencia de la búsqueda si los predicados acotadores
permiten eliminar los nodos de los que se sabe que no pueden llevar a
una solución mejor que la ahora disponible (métodos de ramificación
y poda).
Simona Bernardi Búsqueda con retroceso 13 / 44
Búsqueda con retroceso
Método general

Eficiencia del algoritmo de búsqueda


Factores
1 El tiempo necesario para generar sol[k]
2 El número de elementos solución que satisfacen G
3 El tiempo de ejecución de los predicados acotadores A
4 El número de elementos sol[k] que satisfacen los predicados A

Simona Bernardi Búsqueda con retroceso 14 / 44


Búsqueda con retroceso
Método general

Eficiencia del algoritmo de búsqueda


Factores
1 El tiempo necesario para generar sol[k]
2 El número de elementos solución que satisfacen G
3 El tiempo de ejecución de los predicados acotadores A
4 El número de elementos sol[k] que satisfacen los predicados A

Buenos predicados A reducen mucho el número de nodos generados


A menudo buenos predicados precisan mucho tiempo de evaluación
Si lo reducen a un solo nodo generado (solución voraz): O(n) nodos a
generar en total
Caso peor: O(p(n) × 2n ) o O(p(n)n!), con p(n) polinomio
Reestructuración de las selecciones de forma que
|C1 | < |C2 | < · · · < |Cn |, y ası́ cabe esperar que se explorarán menos
caminos
Simona Bernardi Búsqueda con retroceso 14 / 44
Búsqueda con retroceso
Método general

Estimación a priori del número de nodos generados


Idea: generar un camino aleatorio X en el árbol del espacio de estados

Simona Bernardi Búsqueda con retroceso 15 / 44


Búsqueda con retroceso
Método general

Estimación a priori del número de nodos generados


Idea: generar un camino aleatorio X en el árbol del espacio de estados
Sea xi ∈ X el nodo en el nivel i y sea mi el número de hijos de xi que
satisfacen el predicado acotador A

Simona Bernardi Búsqueda con retroceso 15 / 44


Búsqueda con retroceso
Método general

Estimación a priori del número de nodos generados


Idea: generar un camino aleatorio X en el árbol del espacio de estados
Sea xi ∈ X el nodo en el nivel i y sea mi el número de hijos de xi que
satisfacen el predicado acotador A
El siguiente nodo de X se obtiene aleatoriamente de entre esos mi

Simona Bernardi Búsqueda con retroceso 15 / 44


Búsqueda con retroceso
Método general

Estimación a priori del número de nodos generados


Idea: generar un camino aleatorio X en el árbol del espacio de estados
Sea xi ∈ X el nodo en el nivel i y sea mi el número de hijos de xi que
satisfacen el predicado acotador A
El siguiente nodo de X se obtiene aleatoriamente de entre esos mi
La generación termina en un nodo solución o en un nodo por el que
no se puede seguir (ninguno de sus hijos satisfacen el predicado
acotador)

Simona Bernardi Búsqueda con retroceso 15 / 44


Búsqueda con retroceso
Método general

Estimación a priori del número de nodos generados


Idea: generar un camino aleatorio X en el árbol del espacio de estados
Sea xi ∈ X el nodo en el nivel i y sea mi el número de hijos de xi que
satisfacen el predicado acotador A
El siguiente nodo de X se obtiene aleatoriamente de entre esos mi
La generación termina en un nodo solución o en un nodo por el que
no se puede seguir (ninguno de sus hijos satisfacen el predicado
acotador)
Si los predicados acotadores son estáticos y si los nodos de un mismo
nivel tiene todos igual grado
El número estimado de nodos que se generará con el algoritmo de
búsqueda con retroceso es:

m = 1 + m1 + m1 m2 + m1 m2 m3 + . . .

Simona Bernardi Búsqueda con retroceso 15 / 44


Búsqueda con retroceso
Método general

Algoritmo de estimación
funcion estimación devuelve entero
variables k,m,r,card: entero; nodo: elmto; sol: vector[1..n] de elmto
principio
k:=1; m:=1; r:=1;
repetir
card:=0;
para todo nodo en G(sol,1,k-1) hacer
sol[k]:= nodo;
si A(sol,1,k) entonces card:=card+1 fsi
fpara
si card <> 0 entonces
r=r*card;
m:=m+r;
sol[k] := elegirAleatorio(G(sol,1,k-1));
k:=k+1;
fsi
hastaQue R(sol,1,k) or (card=0);
devuelve m
fin

Simona Bernardi Búsqueda con retroceso 16 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Problema general de las n reinas

Colocar n reinas en un tablero de dimensiones n × n, sin que se den


jaque

Cada solución se representa por una n-pla (x1 , . . . , xn ), en la que xi es


la columna de la i-ésima fila en la que se coloca la i-ésima reina
El espacio de soluciones se reduce a n! elementos teniendo en cuenta
que todas ellas han de ser permutaciones de (1, 2, . . . , n)
Además no deben compartir diagonal

Simona Bernardi Búsqueda con retroceso 17 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Definición del predicado acotador

La función buenSitio devuelve el valor verdadero si la k-ésima reina


se puede colocar en x[k], es decir, si está en distinta columna y
diagonal que las k − 1 reinas anteriores
Dos reinas están:
en la misma diagonal % si tienen el mismo valor de fila+columna
en la misma diagonal - si tienen el mismo valor de fila-columna

Condición de jaque en diagonal


(f1 + c1 = f2 + c2 ) ∨ (f1 − c1 = f2 − c2 ) ⇔
(c1 − c2 = f1 − f2 ) ∨ (c1 − c2 = f2 − f1 ) ⇔
|c1 − c2 | = |f1 − f2 |

Simona Bernardi Búsqueda con retroceso 18 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Algoritmo del predicado acotador

funcion buenSitio(k: entero; x: vector[1..n] de entero) devuelve bool


{Devuelve verdadero si y sólo si se puede colocar la k-ésima reina en x[k],
habiendo sido colocadas ya las k-1 reinas anteriores}
variables i: entero; esBueno: bool
principio
i:=1; esBueno:=verdadero;
mientrasQue (i<k) and esBueno hacer
si x[i]=x[k] or abs(x[i]-x[k]) = abs(i-k) entonces
esBueno = falso
sino
i:=i+1
fsi
fmientrasQue
devuelve esBueno
fin

¿Coste de la función?

Simona Bernardi Búsqueda con retroceso 19 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Algoritmo del predicado acotador

funcion buenSitio(k: entero; x: vector[1..n] de entero) devuelve bool


{Devuelve verdadero si y sólo si se puede colocar la k-ésima reina en x[k],
habiendo sido colocadas ya las k-1 reinas anteriores}
variables i: entero; esBueno: bool
principio
i:=1; esBueno:=verdadero;
mientrasQue (i<k) and esBueno hacer
si x[i]=x[k] or abs(x[i]-x[k]) = abs(i-k) entonces
esBueno = falso
sino
i:=i+1
fsi
fmientrasQue
devuelve esBueno
fin

¿Coste de la función? O(k − 1)

Simona Bernardi Búsqueda con retroceso 19 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Algoritmo de búsqueda
Versión recursiva

algoritmo colocarReinas(ent k: entero; entsal sol: vector[1..n] de entero)


{sol[1..k-1] están bien colocadas}
variables i: entero
principio
para i:=1 hasta n hacer
sol[k]:=i;
si buenSitio(k,sol) entonces
si k=n entonces escribir(sol)
sino colocarReinas(k+1,sol)
fsi
fsi
fpara
fin

La llamada inicial: colocarReinas(1,solución);

Simona Bernardi Búsqueda con retroceso 20 / 44


Búsqueda con retroceso
Aplicación (problema de las reinas)

Estimación del coste


Comparación con el enfoque fuerza bruta

Caso 8 reinas, 5 evaluaciones de la función estimación

Con cada elección, se guarda el número de columnas en que es


posible colocar la reina y a partir de él se calcula el valor que devuelve
la función
Recordar m = 1 + m1 + m1 m2 + m1 m2 m3 + . . .
Simona Bernardi Búsqueda con retroceso 21 / 44
Búsqueda con retroceso
Aplicación (problema de las reinas)

Estimación del coste II


Comparación con el enfoque fuerza bruta
P5
mi
m= = 1645 (media evaluaciones)
i=1
5
P h Qj i
Tamaño espacio de estados: 1 + 7j=0 i=0 (8 − i) = 69.281
Porcentaje de nodos explorados por el algoritmo (si la estimación es
acertada): 2, 34 %
Estimación optimista: el número de nodos explorados es 2057
(porcentaje de nodos explorados 2, 97 %)
Número de soluciones para 8 reinas: 92
Mejora adicional
Observar que algunas soluciones son simplemente rotaciones o
reflexiones de otras
Para encontrar soluciones no equivalentes, el algoritmo sólo debe
probar con x1 = 2, 3, . . . , dn/2e

Simona Bernardi Búsqueda con retroceso 22 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Ciclos hamiltonianos

Encontrar todos los ciclos hamiltonianos de un grafo

Definición
Sea G = (V , A) un grafo conexo con n vértices
Un ciclo hamiltoniano es un camino que visita una vez cada vértice
y vuelve al vértice inicial
Es decir, (v1 v2 . . . vn+1 ) tal que:
vi ∈ V , i = 1, . . . n + 1
(vi , vi+1 ) ∈ A, i = 1, . . . n
v1 = vn+1
vi 6= vj , ∀i, j = 1, . . . , n : i 6= j

Simona Bernardi Búsqueda con retroceso 23 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Ejemplos

Grafo a la izda
Hamiltoniano: 1-2-8-7-6-5-4-3-1
Grafo a la dcha
No contiene ningún hamiltoniano

Simona Bernardi Búsqueda con retroceso 24 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Observaciones

No se conoce algoritmo eficiente para resolver el problema


Hay una relación entre este problema y el problema del viajante de
comercio para el caso de un grafo con todas las distancias entre
vértices iguales
Hay una heurı́stica voraz muy eficiente pero subóptima para el
problema del viajante de comercio
Hay una solución de programación dinámica

Simona Bernardi Búsqueda con retroceso 25 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Análisis del problema y restricciones

En el vector solución (x1 , . . . , xn ), xi representa el i-ésimo vértice


visitado
Si ya x1 , . . . , xk−1 ya tienen valores asignados, calculamos los posibles
valores para xk
k = 1: fijamos como x1 un cualquier vértice, por ejemplo x1 = 1
1 < k < n: xk puede ser cualquier vértice distinto de x1 , . . . , xk−1 y
conectado por un arco con xk−1
k = n: xn sólo puede ser el vértice que queda sin visitar y debe estar
conectado por sendos arcos con x1 y xn−1

Simona Bernardi Búsqueda con retroceso 26 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Estructura de datos

Sólo se necesita saber si un arco existe o no

El grafo
tipo grafo = vector[1..n,1..n] de bool

La solución
tipo sol = vector[1..n] de 1..n

Simona Bernardi Búsqueda con retroceso 27 / 44


Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Algoritmo (restricciones)
algoritmo siguienteValor(entsal x:sol; ent k:entero; ent g: grafo)
variables encontrado:bool; j:entero
principio
repetir
x[k]:=(x[k]+1) mod (n+1); {vértice prometedor}
si x[k]<>0 entonces {no se ha asignado ningún vértice todavı́a}
encontrado:=falso;
si g[x[k-1],x[k]] entonces {el vértice está conectado con el previo}
j:=1; encontrado:=verdadero; {tiene que ser distinto de los previos}
mientrasQue (j<=k-1) and encontrado hacer
si x[j]=x[k] entonces encontrado:=falso sino j:=j+1 fsi
fmientrasQue;
si encontrado entonces
{caso último vértice: tiene que estar conectado con el primero}
si (k=n) and not g[x[n],1] entonces encontrado:=falso fsi
fsi
fsi
fsi
hastaQue (x[k]=0) or encontrado
fin
Simona Bernardi Búsqueda con retroceso 28 / 44
Búsqueda con retroceso
Aplicación (ciclos hamiltonianos)

Algoritmo de búsqueda
algoritmo hamiltoniano(ent k:entero; entsal x:sol; ent g: grafo)
{En x se tiene la parte de la solución ya calculada, es decir hasta x[k-1]}
principio
repetir
siguienteValor(x,k,g);
si x[k]<>0 entonces
si k=n entonces escribir(x)
sino hamiltoniano(k+1,x,g) fsi
fsi
hastaQue x[k]=0
fin

Llamada inicial
{g contiene la matriz de adyacencia del grafo y el vector solución está
inicializado a x=[1,0,...,0]}
hamiltoniano(2,x,g);

Simona Bernardi Búsqueda con retroceso 29 / 44


Búsqueda con retroceso
Aplicación (atravesar un laberinto)

Atravesar un laberinto

Hay una entrada y una salida en


el laberinto y hay que intentar
atravesarlo
El mapa del laberinto: una
matriz N × M de casillas
marcadas como libre u ocupadas
por una pared
Entrada: casilla (2, 2)
Salida: casilla (N − 1, M − 1)
Es posible pasar de una casilla a
otra moviéndose sólamente en
vertical u horizontal

Simona Bernardi Búsqueda con retroceso 30 / 44


Búsqueda con retroceso
Aplicación (atravesar un laberinto)

Diseño de un algoritmo de backtracking


Se marcará en la misma matriz un camino solución (si existe)
Si se llega a una casilla desde la que es imposible encontrar una
solución, hay que volver atrás y buscar otro camino
Hay que marcar las casillas por donde ya se ha pasado para evitar
meterse varias veces en el mismo callejón sin salida, dar vueltas
alrededor de columnas . . .

(a) Camino encontrado (b) Caso retroceso (c) Búsqueda otro camino
Simona Bernardi Búsqueda con retroceso 31 / 44
Búsqueda con retroceso
Aplicación (atravesar un laberinto)

Estructura de datos y funciones auxiliares

{Estructura de datos}
tipos
casilla = (libre,pared,camino,imposible)
laberinto = vector[1..N,1..M] de casilla

{Funciones auxiliares}
funcion fueraLaberinto(fila,columna: entero) devuelve bool
principio
devuelve (fila < 2) or (fila > N-1) or (columna < 2) or (columna > M-1)
fin
funcion esLibre(lab: laberinto; fila,columna: entero) devuelve bool
principio
devuelve lab[fila][columna] = libre
fin
funcion esSalida(fila,columna: entero) devuelve bool
principio
devuelve (fila = N-1) and (columna = M-1)
fin

Simona Bernardi Búsqueda con retroceso 32 / 44


Búsqueda con retroceso
Aplicación (atravesar un laberinto)

Solución de búsqueda con retroceso

algoritmo buscarCamino(entsal lab:laberinto; ent fila, columna: entero;


sal encontrado:booleano)
principio
si fueraLaberinto(fila,columna) or not esLibre(lab,fila,columna) entonces
encontrado:=falso
sino
lab[fila,columna]:=camino;
si esSalida(fila,columna) entonces {se ha encontrado una solución}
encontrado:=verdadero
sino
buscarCamino(fila,columna+1,lab,encontrado);
si not encontrado entonces buscarCamino(fila-1,columna,lab,encontrado) fsi;
si not encontrado entonces buscarCamino(fila,columna-1,lab,encontrado) fsi;
si not encontrado entonces buscarCamino(fila+1,columna,lab,encontrado) fsi;
si not encontrado entonces lab[fila,columna]:=imposible fsi
fsi
fsi
fin

Simona Bernardi Búsqueda con retroceso 33 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Problema de la mochila 0-1


Hay n objetos y una mochila
n
El objeto i tiene peso pi y su X
max bi xi
inclusión en la mochila produce
i=1
un beneficio bi Xn
Objetivo: llenar la mochila de t.q. pi xi ≤ C
capacidad C , de manera que se i=1
maximice el beneficio xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n

Simona Bernardi Búsqueda con retroceso 34 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Problema de la mochila 0-1


Hay n objetos y una mochila
n
El objeto i tiene peso pi y su X
max bi xi
inclusión en la mochila produce
i=1
un beneficio bi Xn
Objetivo: llenar la mochila de t.q. pi xi ≤ C
capacidad C , de manera que se i=1
maximice el beneficio xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n

Soluciones a problemas parecidos


Objetos fraccionables (0 ≤ xi ≤ 1, 1 ≤ i ≤ n): solución voraz
Mochila 0-1 con pesos, beneficios y capacidad de la mochila números
naturales (solución de programación dinámica)
En el caso general, ninguna de las dos soluciones funciona
Simona Bernardi Búsqueda con retroceso 34 / 44
Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Espacio de soluciones
2n modos de asignar los valores 0 ó 1 a las xi
Dos formas de representar la solución

Tuplas de tamaño variable:


xi = objeto introducido en el
i-ésimo lugar

Simona Bernardi Búsqueda con retroceso 35 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Espacio de soluciones
Tuplas de tamaño fijo

xi = 1 si el objeto i-ésimo se introduce


xi = 0 si el objeto i-ésimo no se introduce
Elegimos ésta última representación
Simona Bernardi Búsqueda con retroceso 36 / 44
Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Elección de funciones acotadoras


Intentar podar ramas que no puedan producir soluciones mejores que la
disponible actualmente

Se llama poda basada en el coste de la mejor solución en curso


Calcular una cota superior del valor de la mejor solución posible al
expandir un nodo y sus descendientes
Si la cota es menor o igual que el valor de la mejor solución disponible
hasta el momento, no expandir ese nodo
¿Cómo calcular esa cota superior?
Suponer que en el nodo actual ya se han determinado xi , 1 ≤ i ≤ k
Relajar el requisito de integridad:
xi ∈ {0, 1}, k + 1 ≤ i ≤ n =⇒ 0 ≤ xi ≤ 1, k + 1 ≤ i ≤ n
Aplicar el algoritmo voraz

Simona Bernardi Búsqueda con retroceso 37 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Algoritmo para el cálculo de la cota


const N=... {número de objetos}
tipo vectReal=vector[1..N] de real

{Pre: forall i = 1..n: peso[i]>0 and


forall i=1..n-1: benef[i]/peso[i] >= benef[i+1]/peso[i+1]}
funcion cota(benef,peso:vectReal; cap,ben:real; obj:entero) devuelve real
{cap=capacidad aún libre de la mochila; ben=beneficio actual;
obj=ı́ndice del primer objeto a considerar}
principio
si obj>N or cap=0.0 entonces devuelve ben
sino
si peso[obj]>cap entonces devuelve ben+cap/peso[obj]*benef[obj]
sino
devuelve cota(benef,peso,cap-peso[obj],ben+benef[obj],obj+1)
fsi
fsi
fin

Simona Bernardi Búsqueda con retroceso 38 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Algoritmo de búsqueda con retroceso


tipo solución=vector[1..N] de 0..1
{Variables globales: benef,peso:vectReal; cap:real}

algoritmo búsqueda(ent solAct:solución; ent benAct,pesAct:real;


ent obj:entero; entsal sol:solución, entsal ben:real)
variable decisión: 0..1
principio
para decisión:=1 descendiendo hasta 0 hacer
solAct[obj]:=decisión;
benAct:=benAct+decisión*benef[obj];
pesAct:=pesAct+decisión*peso[obj];
si pesAct<=cap and ben<cota(benef,peso,cap-pesAct,benAct,obj+1) entonces
si obj=N entonces
si benAct>ben entonces sol:=solAct; ben:=benAct fsi
sino búqueda(solAct,benAct,pesAct,obj+1,sol,ben)
fsi
fsi
fpara
fin

Simona Bernardi Búsqueda con retroceso 39 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Algoritmo solución

algoritmo mochila0-1(ent benef,peso:vectReal; ent cap:real;


sal sol:solución; sal ben: real)
variables solAct:solución
principio
{inicialización vectores solAct=[0,..0] y sol[0,..,0]}
ben:=0.0;
búsqueda(solAct,0.0,0.0,1,sol,ben)
fin

Simona Bernardi Búsqueda con retroceso 40 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Ejemplo
benef=(11,21,31,33,43,53,55,65)
peso =(1,11,21,23,33,43,45,55)
cap=110
N=8

Simona Bernardi Búsqueda con retroceso 41 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Problema de la mochila 0-1

Tamaño del espacio de estados: 29 − 1(= 511) nodos


Aplicando el algoritmo de backtracking, sólo se generan 33
Se podı́a haber reducido a 26 simplemente sustituyendo la condición
ben < cota(...)
en el algoritmo de búsqueda por:
ben < parteEntera(cota(...))

Simona Bernardi Búsqueda con retroceso 42 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Observaciones

Hasta ahora hemos visto algoritmos de búsqueda con retroceso


basados en árbol de espacio de estados estático
Es decir, la estructura del árbol es independiente de la instancia del
problema
Se pueden diseñar algoritmos basados en árboles de espacio de
estados dinámicos

Simona Bernardi Búsqueda con retroceso 43 / 44


Búsqueda con retroceso
Aplicación (problema de la mochila 0-1)

Solución del problema basada en un árbol dinámico


Resolver el problema sin la
restricción de integridad, con n
algoritmo voraz X
max bi xi (1)
Si la solución es entera,
i=1
también es óptima para el n
X
problema 0-1 s.t. pi xi ≤ C
Si no es entera, existe
i=1
exactamente un xi tal que 0 ≤ xi ≤ 1, bi , pi > 0, 1 ≤ i ≤ n
0 < xi < 1
Se parte el espacio de soluciones en dos: en uno (subárbol izquierdo)
xi = 0 y en otro (subárbol derecho) xi = 1
En general, en cada nodo, se usa el algoritmo voraz para resolver el
problema (1) con las restricciones añadidas a las asignaciones ya
realizadas a lo largo del camino desde la raı́z al nodo

Simona Bernardi Búsqueda con retroceso 44 / 44


Ramificación y poda
(branch & bound)

Simona Bernardi
Universidad de Zaragoza

Presentación adaptada de la original de J. Campos

Este documento está sujeto a una licencia de uso Creative Commons. No se permite
un uso comercial de la obra original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Ramificación y poda

Resumen

Método general
Aplicación
El juego del 15
Problemas de optimización
Un problema de planificación de tareas a plazo fijo
El problema de la mochila 0-1
El problema del viajante de comercio

Simona Bernardi Ramificación y poda 2 / 73


Ramificación y poda
Método general

Ramificación
Al igual que los métodos de búsqueda con retroceso:
Se aplica a problemas de optimización con restricciones
Se genera el espacio de soluciones, organizandólo en un árbol (en
general en un grafo)
No se genera el espacio de soluciones completo, sino que se podan
bastantes estados

Simona Bernardi Ramificación y poda 3 / 73


Ramificación y poda
Método general

Ramificación
Al igual que los métodos de búsqueda con retroceso:
Se aplica a problemas de optimización con restricciones
Se genera el espacio de soluciones, organizandólo en un árbol (en
general en un grafo)
No se genera el espacio de soluciones completo, sino que se podan
bastantes estados

Terminologı́a
Nodo vivo: nodo del espacio de soluciones del que no se han
generado aún todos sus hijos
Nodo muerto: nodo del que no se van a generar más hijos porque
no hay más
no es completable, es decir viola las restricciones
no producirá una solución mejor que la solución actual
Nodo en expansión: nodo del que se están generando hijos
Simona Bernardi Ramificación y poda 3 / 73
Ramificación y poda
Método general

Diferencia con el método de búsqueda con retroceso

Búsqueda con retroceso: tan pronto como se genera un nuevo hijo del
nodo en expansión, este hijo pasa a ser el nodo en curso
Ramificación y poda: se generan todos los hijos del nodo en expansión
antes de que cualquier otro nodo vivo pase a ser el nuevo nodo en
expansión

Simona Bernardi Ramificación y poda 4 / 73


Ramificación y poda
Método general

Diferencia con el método de búsqueda con retroceso

Búsqueda con retroceso: tan pronto como se genera un nuevo hijo del
nodo en expansión, este hijo pasa a ser el nodo en curso
Ramificación y poda: se generan todos los hijos del nodo en expansión
antes de que cualquier otro nodo vivo pase a ser el nuevo nodo en
expansión

Consecuencia
Búsqueda con retroceso: los únicos nodos vivos son los que están en
el camino de la raı́z al nodo en expansión
Ramificación y poda: puede haber más nodos vivos. Se necesita una
estructura de datos auxiliar para almacenar la lista de nodos vivos

Simona Bernardi Ramificación y poda 4 / 73


Ramificación y poda
Método general

Recorrido del árbol de soluciones


Diferentes estrategias de elegir el siguiente nodo de la lista de nodos vivos

Distintos órdenes de recorrido del árbol de soluciones

Simona Bernardi Ramificación y poda 5 / 73


Ramificación y poda
Método general

Recorrido del árbol de soluciones


Diferentes estrategias de elegir el siguiente nodo de la lista de nodos vivos

Distintos órdenes de recorrido del árbol de soluciones

FIFO: la lista de nodos vivos es una cola ⇒ recorrido por niveles (en
anchura)
LIFO: la lista de nodos vivos es una pila ⇒ ≈ recorrido en
profundidad (depth first)

Simona Bernardi Ramificación y poda 5 / 73


Ramificación y poda
Método general

Recorrido del árbol de soluciones


Diferentes estrategias de elegir el siguiente nodo de la lista de nodos vivos

Distintos órdenes de recorrido del árbol de soluciones

FIFO: la lista de nodos vivos es una cola ⇒ recorrido por niveles (en
anchura)
LIFO: la lista de nodos vivos es una pila ⇒ ≈ recorrido en
profundidad (depth first)

Mı́nimo coste: la lista de nodos vivos es una cola con prioridades ⇒


recorrido extraño
La prioridad de un nodo se calcula con una función de estimación
que mide cuánto de prometedor es un nodo

Simona Bernardi Ramificación y poda 5 / 73


Ramificación y poda
Método general

Punto clave: función de estimación

Encontrar un buen orden de recorrido (o ramificación) de los nodos


w
w


Definir una buena función de prioridad de los nodos vivos, para que las
soluciones buenas se encuentren rápidamente

Simona Bernardi Ramificación y poda 6 / 73


Ramificación y poda
Método general

Esquema algorı́tmico

repetir
elegir el nodo más prometedor como nodo_E;
generar todos sus hijos;
matar el nodo_E;
para cada hijo hacer
si coste(hijo) > coste(mejor_solución_en_curso) entonces se mata
sino
si no es solución entonces se pasa a la lista_de_nodos_vivos
sino {es solución: el coste no es estimado sino real}
es la mejor_solución_en_curso y se revisa la lista_de_nodos_vivos,
eliminando los que prometen algo peor
fsi
fsi
fpara
hasta que la lista está vacı́a

Simona Bernardi Ramificación y poda 7 / 73


Ramificación y poda
Aplicación (juego del 15)

El juego del 15
El problema original

Samuel Loyd and the 15 puzzle


http://mathematicalmysterytour.blogspot.com/2014/10/sam-loyd-and-15-puzzle.html

Simona Bernardi Ramificación y poda 8 / 73


Ramificación y poda
Aplicación (juego del 15)

El juego del 15
El problema original

Samuel Loyd and the 15 puzzle


http://mathematicalmysterytour.blogspot.com/2014/10/sam-loyd-and-15-puzzle.html

La solución de fuerza bruta:


Buscar en el espacio de estados (todas las configuraciones alcanzables
dede la configuración inicial) hasta encontrar el objetivo
Hay 16! ≈ 20, 9 × 1012 configuraciones, aunque sólo (?) la midad
pueden alcanzarse desde la configuración inicial propuesta por Loyd

Simona Bernardi Ramificación y poda 8 / 73


Ramificación y poda
Aplicación (juego del 15)

Configuraciones alcanzables
Numeremos las casillas de 1 a 16

Simona Bernardi Ramificación y poda 9 / 73


Ramificación y poda
Aplicación (juego del 15)

Configuraciones alcanzables
Numeremos las casillas de 1 a 16
Dada una configuración:
Sea pos(i) la posición (entre 1 y 15) de la ficha con número i, y sea
pos(16) la posición de la casilla vacı́a
Para cada ficha i, sea m(i) el número de fichas j < i tales que
pos(j) > pos(i)

Simona Bernardi Ramificación y poda 9 / 73


Ramificación y poda
Aplicación (juego del 15)

Configuraciones alcanzables
Numeremos las casillas de 1 a 16
Dada una configuración:
Sea pos(i) la posición (entre 1 y 15) de la ficha con número i, y sea
pos(16) la posición de la casilla vacı́a
Para cada ficha i, sea m(i) el número de fichas j < i tales que
pos(j) > pos(i)

Sea x = 1 si la casilla vacı́a está en alguna de las posiciones verdes y


x = 0 en caso contrario

Simona Bernardi Ramificación y poda 9 / 73


Ramificación y poda
Aplicación (juego del 15)

Configuraciones alcanzables

Teorema
La configuración objetivo es alcanzable desde una cierta configuración
inicial si para esta configuración:
16
X
m(i) + x es par .
i=1

Simona Bernardi Ramificación y poda 10 / 73


Ramificación y poda
Aplicación (juego del 15)

Configuraciones alcanzables

Teorema
La configuración objetivo es alcanzable desde una cierta configuración
inicial si para esta configuración:
16
X
m(i) + x es par .
i=1

Para el ejemplo anterior, dicha suma vale 16: la configuración objetivo


es alcanzable
En el problema original de Loyd, la configuración objetivo no es
alcanzable

Simona Bernardi Ramificación y poda 10 / 73


Ramificación y poda
Aplicación (juego del 15)

Búsqueda en anchura
Hijos de cada nodo = movimientos de la casilla vacı́a
(arriba,dcha,abajo,izda)

Simona Bernardi Ramificación y poda 11 / 73


Ramificación y poda
Aplicación (juego del 15)

Búsqueda en profundidad

Orden de los movimientos (arriba,dcha,abajo,izda)

Sigue la rama izquierda del árbol

Simona Bernardi Ramificación y poda 12 / 73


Ramificación y poda
Método general

Estrategias de búsqueda

Estrategias a ciegas:
FIFO: recorrido en anchura o por niveles
Relativamente útil si el nodo solución está cerca de la raı́z
LIFO: ≈ recorrido en profundidad (también llamado D-search en el
libro de Horowitz et al.)
Puede no encontrar la solución (problemas con los ciclos)

Simona Bernardi Ramificación y poda 13 / 73


Ramificación y poda
Método general

Estrategias de búsqueda

Estrategias a ciegas:
FIFO: recorrido en anchura o por niveles
Relativamente útil si el nodo solución está cerca de la raı́z
LIFO: ≈ recorrido en profundidad (también llamado D-search en el
libro de Horowitz et al.)
Puede no encontrar la solución (problemas con los ciclos)
Estrategias no ciegas (informadas, en inteligencia artificial)
Buscan la solución adaptando el camino de búsqueda en el árbol de
soluciones a la instancia del problema a solucionar
Se necesita definir una función de coste para los nodos del árbol

Simona Bernardi Ramificación y poda 13 / 73


Ramificación y poda
Aplicación (juego del 15)

Ejemplo de función de coste


c(x) = longitud desde la raı́z hasta el nodo objetivo más cercano que es descendiente de x

Simona Bernardi Ramificación y poda 14 / 73


Ramificación y poda
Método general

Función de estimación
Problema: el cálculo de la función c
Un ejemplo de problemas en los que es posible: aquéllos en los que hay
soluciones voraces

Simona Bernardi Ramificación y poda 15 / 73


Ramificación y poda
Método general

Función de estimación
Problema: el cálculo de la función c
Un ejemplo de problemas en los que es posible: aquéllos en los que hay
soluciones voraces

Función de estimación (heurı́stica)


ĉ(x) = f (x) + ĝ (x)
f (x) = longitud del camino de la raı́z a x
ĝ (x) = estimación de la longitud del camino de x hasta la solución más
cercana

Simona Bernardi Ramificación y poda 15 / 73


Ramificación y poda
Método general

Función de estimación
Problema: el cálculo de la función c
Un ejemplo de problemas en los que es posible: aquéllos en los que hay
soluciones voraces

Función de estimación (heurı́stica)


ĉ(x) = f (x) + ĝ (x)
f (x) = longitud del camino de la raı́z a x
ĝ (x) = estimación de la longitud del camino de x hasta la solución más
cercana
Propiedades de ĉ:
Fácil de calcular
Si x es una hoja o solución: c(x) = ĉ(x)

Simona Bernardi Ramificación y poda 15 / 73


Ramificación y poda
Aplicación (juego del 15)

Estrategia de mı́nimo coste

ĝ (x) = número de casillas no vacı́as que no están en su sitio objetivo (ĉ(x) ≤ c(x), ∀x)

La lista de nodos vivos es una cola de nodos x con prioridades ĉ(x)

Simona Bernardi Ramificación y poda 16 / 73


Ramificación y poda
Aplicación (juego del 15)

Estrategia de mı́nimo coste

ĝ (x) = número de casillas no vacı́as que no están en su sitio objetivo (ĉ(x) ≤ c(x), ∀x)

La lista de nodos vivos es una cola de nodos x con prioridades ĉ(x)

Nodo inicial

Simona Bernardi Ramificación y poda 16 / 73


Ramificación y poda
Aplicación (juego del 15)

Estrategia de mı́nimo coste

ĝ (x) = número de casillas no vacı́as que no están en su sitio objetivo (ĉ(x) ≤ c(x), ∀x)

La lista de nodos vivos es una cola de nodos x con prioridades ĉ(x)

Nodo inicial

Se generan sus
hijos y se añaden
a la cola

Simona Bernardi Ramificación y poda 16 / 73


Ramificación y poda
Aplicación (juego del 15)

Estrategia de mı́nimo coste

Se elige el
mı́nimo (4), se
elimina de la cola
y se generan sus
hijos

Simona Bernardi Ramificación y poda 17 / 73


Ramificación y poda
Aplicación (juego del 15)

Estrategia de mı́nimo coste

Se elige el
mı́nimo (4), se
elimina de la cola
y se generan sus
hijos

Se elige el
mı́nimo (10), se
elimina de la cola
y se generan sus
hijos

Simona Bernardi Ramificación y poda 17 / 73


Ramificación y poda
Aplicación (juego del 15)

Algoritmo de búsqueda
algoritmo mı́nimoCoste(ent x0: nodo)
variables c:cola; {cola con prioridades <x,coste(x)>}
éxito: bool; xcurso,x:nodo
principio
si esSolución(x0) entonces escribir(x0)
sino
crearColaVacı́a(c); {cola de nodos vivos}
a~
nadir(c,<x0,coste(x0)>); éxito:=falso;
mientrasQue not éxito and not esVacı́a(c) hacer
xcurso:=min(c); {nodo en expansión}
eliminar(c,xcurso);
mientrasQue not éxito and hay_otro_hijo_x_de_xcurso hacer
si esSolución(x) entonces escribir(x); éxito:=verdadero
sino a~nadir(c,<x,coste(x)>) fsi
fmientrasQue
fmientrasQue
si not éxito entonces escribir("No hay solución") fsi
fsi
fin

Simona Bernardi Ramificación y poda 18 / 73


Ramificación y poda
Aplicación (juego del 15)

Observaciones

Si se desea escribir todo el camino desde la raı́z hasta la solución,


cada vez que se añade un nodo a la cola, hay que guardar en una
tabla auxiliar de padres de nodos ese nodo junto a su padre

Simona Bernardi Ramificación y poda 19 / 73


Ramificación y poda
Aplicación (juego del 15)

Observaciones

Si se desea escribir todo el camino desde la raı́z hasta la solución,


cada vez que se añade un nodo a la cola, hay que guardar en una
tabla auxiliar de padres de nodos ese nodo junto a su padre
La terminación del algoritmo sólo está garantizada si el espacio de
estados es finito

Simona Bernardi Ramificación y poda 19 / 73


Ramificación y poda
Aplicación (juego del 15)

Observaciones

Si se desea escribir todo el camino desde la raı́z hasta la solución,


cada vez que se añade un nodo a la cola, hay que guardar en una
tabla auxiliar de padres de nodos ese nodo junto a su padre
La terminación del algoritmo sólo está garantizada si el espacio de
estados es finito
Si el espacio de estados es infinito y existe al menos una solución, se
puede garantizar la terminación con una elección adecuada de la
función de estimación

Simona Bernardi Ramificación y poda 19 / 73


Ramificación y poda
Aplicación (juego del 15)

Observaciones

Si se desea escribir todo el camino desde la raı́z hasta la solución,


cada vez que se añade un nodo a la cola, hay que guardar en una
tabla auxiliar de padres de nodos ese nodo junto a su padre
La terminación del algoritmo sólo está garantizada si el espacio de
estados es finito
Si el espacio de estados es infinito y existe al menos una solución, se
puede garantizar la terminación con una elección adecuada de la
función de estimación
Si el espacio de estados es infinito y no hay solución, el algoritmo no
termina. . .
Se suele restringir la búsqueda a nodos con coste estimado menor que
C (cota)

Simona Bernardi Ramificación y poda 19 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Problemas de optimización
La función o coste a minimizar ya no es la distancia de la raı́z a la
solución, sino una función objetivo dada
¿Qué ocurre si interesa buscar una solución óptima (es decir de coste
mı́nimo)?
¿Encuentra el algoritmo minimoCoste esa solución?

Simona Bernardi Ramificación y poda 20 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Problemas de optimización
La función o coste a minimizar ya no es la distancia de la raı́z a la
solución, sino una función objetivo dada
¿Qué ocurre si interesa buscar una solución óptima (es decir de coste
mı́nimo)?
¿Encuentra el algoritmo minimoCoste esa solución? No

Se expande la raı́z, sus hijos se añaden


a la cola de nodos vivos
Se elige el hijo izquierdo, se expande y
se obtiene una solución factible de coste
20
La solución óptima tiene coste 10.
¿Porqué?

Simona Bernardi Ramificación y poda 20 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Problemas de optimización
La función o coste a minimizar ya no es la distancia de la raı́z a la
solución, sino una función objetivo dada
¿Qué ocurre si interesa buscar una solución óptima (es decir de coste
mı́nimo)?
¿Encuentra el algoritmo minimoCoste esa solución? No

Se expande la raı́z, sus hijos se añaden


a la cola de nodos vivos
Se elige el hijo izquierdo, se expande y
se obtiene una solución factible de coste
20
La solución óptima tiene coste 10.
¿Porqué?
∃x, y : ĉ(x) < ĉ(y ) ∧ c(x) > c(y )
Simona Bernardi Ramificación y poda 20 / 73
Ramificación y poda
Aplicación (problemas de optimización)

Problemas de optimización
Teorema
Si para cada nodo x del árbol del espacio de estados ĉ(x) es una
estimación de c(x) tal que para todo par de nodos y , z:

ĉ(y ) < ĉ(z) ⇔ c(y ) < c(z)

entonces el algoritmo mı́nimoCoste termina y encuentra siempre una


solución óptima.

Simona Bernardi Ramificación y poda 21 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Problemas de optimización
Teorema
Si para cada nodo x del árbol del espacio de estados ĉ(x) es una
estimación de c(x) tal que para todo par de nodos y , z:

ĉ(y ) < ĉ(z) ⇔ c(y ) < c(z)

entonces el algoritmo mı́nimoCoste termina y encuentra siempre una


solución óptima.

Problema: no es fácil encontrar una función de estimación con tales


caracterı́sticas y fácil de calcular
Conformarse con: una función ĉ(x) fácil de calcular y tal que para
todo nodo x: ĉ(x) ≤ c(x) y para cada solución: ĉ(x) = c(x). En este
caso, mı́nimoCoste no siempre encuentra una solución óptima, pero
se puede modificar ligeramente. . .
Simona Bernardi Ramificación y poda 21 / 73
Ramificación y poda
Aplicación (problemas de optimización)

Algoritmo de búsqueda modificado

algoritmo mı́nimoCoste2(ent x0: nodo)


variables c:cola; {cola con prioridades <x,coste(x)>}
éxito: bool; xcurso,x:nodo
principio
crearColaVacı́a(c); {cola de nodos vivos}
a~
nadir(c,<x0,coste(x0)>); éxito:=falso;
mientrasQue not éxito and not esVacı́a(c) hacer
xcurso:=min(c); {nodo en expansión}
eliminar(c,xcurso);
si esSolución(xcurso) entonces escribir(x); éxito:=verdadero
sino
para todo x_hijo_de_xcurso hacer
a~
nadir(c,<x,coste(x)>)
fpara
fsi
fmientrasQue
si not éxito entonces escribir("No hay solución") fsi
fin

Simona Bernardi Ramificación y poda 22 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Diferencia entre los dos algoritmo de coste mı́nimo


mı́nimoCoste si encuentra un hijo que sı́ es solución factible ya no
incluye el resto de los hijos en la cola de nodos vivos con prioridades;
mı́nimoCoste2 incluye en la cola de nodos vivos con prioridades
todos los hijos, sin mirar si son solución factible o no. (⇐ algoritmo
más prudente)

Simona Bernardi Ramificación y poda 23 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Diferencia entre los dos algoritmo de coste mı́nimo


mı́nimoCoste si encuentra un hijo que sı́ es solución factible ya no
incluye el resto de los hijos en la cola de nodos vivos con prioridades;
mı́nimoCoste2 incluye en la cola de nodos vivos con prioridades
todos los hijos, sin mirar si son solución factible o no. (⇐ algoritmo
más prudente)

Teorema
Si para cada nodo x del árbol del espacio de estados ĉ(x) es una función
de estimación tal que:
ĉ(x) ≤ c(x)
y para cada nodo solución x se verifica: ĉ(x) = c(x), entonces si el
algoritmo mı́nimoCoste2 encuentra una solución, ésta es óptima.

Simona Bernardi Ramificación y poda 23 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Demostración teorema

Si se encuentra la solución xcurso, se tiene que: ĉ(xcurso) ≤ ĉ(x)


para todo nodo x de la cola de nodos vivos
Además: ĉ(xcurso) = c(xcurso) y ĉ(x) ≤ c(x) para todo nodo x de
la cola de nodos vivos y
También c(x) ≤ c(y ) para cada nodo x del árbol, donde y es un
hijo de x
Luego c(xcurso) ≤ c(x) y xcurso es de mı́nimo coste.

Simona Bernardi Ramificación y poda 24 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda
Dado el problema de minimización de una función objetivo c(x)
Se utiliza una función de estimación ĉ(x) tal que ĉ(x) ≤ c(x)
Suponer que se conoce una cota superior del valor mı́nimo de c:

c(x ∗ ) = min c(x) ≤ U


x

(cota pesimista de la solución del problema)

Simona Bernardi Ramificación y poda 25 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda
Dado el problema de minimización de una función objetivo c(x)
Se utiliza una función de estimación ĉ(x) tal que ĉ(x) ≤ c(x)
Suponer que se conoce una cota superior del valor mı́nimo de c:

c(x ∗ ) = min c(x) ≤ U


x

(cota pesimista de la solución del problema)

Regla de poda

Si ĉ(x) > U, entonces x puede ser podado


porque ∀y solución descendiente de x:

c(y ) ≥ c(x) ≥ ĉ(x) > U

Simona Bernardi Ramificación y poda 25 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda

Valor inicial de U:
Utilizar alguna heurı́stica (basada en información extra sobre el
problema)

Simona Bernardi Ramificación y poda 26 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda

Valor inicial de U:
Utilizar alguna heurı́stica (basada en información extra sobre el
problema)

Si al alcanzar solución factible x: c(x) < U, se actualiza el valor de U

Simona Bernardi Ramificación y poda 26 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda

Valor inicial de U:
Utilizar alguna heurı́stica (basada en información extra sobre el
problema)

Si al alcanzar solución factible x: c(x) < U, se actualiza el valor de U
Todos los nodos vivos de coste estimado mayor que U también se
pueden podar

Simona Bernardi Ramificación y poda 26 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Poda

Valor inicial de U:
Utilizar alguna heurı́stica (basada en información extra sobre el
problema)

Si al alcanzar solución factible x: c(x) < U, se actualiza el valor de U
Todos los nodos vivos de coste estimado mayor que U también se
pueden podar
Si el valor inicial de U es mayor o igual que el coste de una solución
de mı́nimo coste, la regla de poda no elimina ningún nodo ascendente
de una solución de coste mı́nimo

Simona Bernardi Ramificación y poda 26 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Simona Bernardi Ramificación y poda 27 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Si x es solución factible del problema: c(x) = Fobjectivo (x)

Simona Bernardi Ramificación y poda 27 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Si x es solución factible del problema: c(x) = Fobjectivo (x)


Si x no es factible: c(x) = ∞

Simona Bernardi Ramificación y poda 27 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Si x es solución factible del problema: c(x) = Fobjectivo (x)


Si x no es factible: c(x) = ∞
Si x es solución parcial (x puede ser completada a factible):

c(x) = min c(y ) | y es descendiente de x

Simona Bernardi Ramificación y poda 27 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Si x es solución factible del problema: c(x) = Fobjectivo (x)


Si x no es factible: c(x) = ∞
Si x es solución parcial (x puede ser completada a factible):

c(x) = min c(y ) | y es descendiente de x

Tan difı́cil de calcular como resolver el problema original!

Simona Bernardi Ramificación y poda 27 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Construcción del algoritmo


Definición de la función de coste c(x) de forma que c(x) sea mı́nimo para
todos los nodos que representan una solución óptima. ¿Cómo?

Si x es solución factible del problema: c(x) = Fobjectivo (x)


Si x no es factible: c(x) = ∞
Si x es solución parcial (x puede ser completada a factible):

c(x) = min c(y ) | y es descendiente de x

Tan difı́cil de calcular como resolver el problema original!


Se utiliza ĉ(x) tal que ĉ(x) ≤ c(x) para todo x
La función de estimación estima el valor de la función objetivo y
no el coste computacional de alcanzar la solución
Simona Bernardi Ramificación y poda 27 / 73
Ramificación y poda
Aplicación (problemas de optimización)

Puntos clave de método

1 Encontrar un buen orden de recorrido (o ramificación) de los nodos,


es decir, definir una buena función de prioridad ĉ de los nodos vivos,
para que las soluciones buenas se encuentren rápidamente.
2 Encontrar una buena función de poda, U para que se produzca
el retroceso lo antes posible.

Simona Bernardi Ramificación y poda 28 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Algoritmo de búsqueda modificado


algoritmo RamPodaMinCoste(ent x0: nodo)
{Busca en el árbol cuya raı́z es x0 una solución de mı́nimo coste.
Se asume que existe al menos un nodo de mı́nimo coste y que se
dispone de una función c_est y de un valor inicial U: c_est(x)<=c(x)<=U.}
variables q:cola; {cola con prioridades de <x,c_est(x)>} xcurso,x: nodo
principio
creaColaVacı́a(q); {cola con prioridades de nodos vivos}
a~
nadir(q,<x0,c_est(x0)>);
mientrasQue not esVacı́a(q) hacer
xcurso:= min(q); {nodo en expansión} eliminar(q,xcurso);
para todo x hijo_de xcurso hacer
si c_est(x) <= U entonces
a~
nadir(q,<x,c_est(x)>);
si esSoluciónFactible(x) and c(x) < U entonces U:=c(x) fsi
fsi
fpara;
si esVacı́a(q) or c_est(min(q))>=U entonces escribir(U); crearVacı́a(q) fsi
fmientrasQue
fin

Simona Bernardi Ramificación y poda 29 / 73


Ramificación y poda
Aplicación (problemas de optimización)

Observaciones

Si se desea escribir la solución óptima además del valor óptimo U de


la función objetivo:
Cada vez que se añade un nodo a la cola, hay que guardar en una tabla
auxiliar de nodos padre el nodo añadido junto a su padre o bien
guardar con cada nodo una identificación de su padre, y
Hay que mantener una variable auxiliar con el valor del último nodo
solución que ha permitido actualizar U

Simona Bernardi Ramificación y poda 30 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Un problema de planificación de tareas a plazo fijo

Se tiene un conjunto C = {1, 2, . . . , n} de tareas y en cada instante


sólo se puede realizar una tarea
Cada tarea, 1 ≤ i ≤ n, tiene asociada una terna (ti , di , wi )
ti es la duración de la tarea i
la tarea i debe terminarse antes del plazo di
hay una penalización wi si la tarea i no termina antes de su plazo
Se quiere encontrar un subconjunto S ⊆ C tal que todas las tareas de
S puedan ser ejecutadas antes de sus plazos y la penalización total
sea mı́nima.

Simona Bernardi Ramificación y poda 31 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Ejemplo

n=4
(t1 , d1 , w1 ) = (1, 1, 5)
(t2 , d2 , w2 ) = (2, 3, 10)
(t3 , d3 , w3 ) = (1, 2, 6)
(t4 , d4 , w4 ) = (1, 1, 3)

Espacio de estados: todos los subconjuntos de {1, 2, 3, 4}


Dos representaciones posibles:
Tuplas de tamaño variable
Tuplas de tamaño fijo

Simona Bernardi Ramificación y poda 32 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Representación con tuplas de tamaño variable

Nodos cuadrados: estados no factibles


Nodos circulares: soluciones factibles
Nodo 9: solución óptima (es la única):
S = {2, 3}; penalización total =8
Simona Bernardi Ramificación y poda 33 / 73
Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Representación con tuplas de tamaño fijo

Nodos cuadrados: estados no factibles


Hojas circulares: soluciones factibles
Nodo 25 solución óptima: S = {2, 3}; penalización total =8
Simona Bernardi Ramificación y poda 34 / 73
Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de coste c(x)


Para todo nodo circular x con algún hijo circular c(x) es la mı́nima
penalización correspondiente a todos los nodos descendientes de x. Para
todo nodo cuadrado x: c(x) = ∞.

Simona Bernardi Ramificación y poda 35 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de coste c(x)


Para todo nodo circular x con algún hijo circular c(x) es la mı́nima
penalización correspondiente a todos los nodos descendientes de x. Para
todo nodo cuadrado x: c(x) = ∞.

Simona Bernardi Ramificación y poda 36 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de estimación ĉ(x) ≤ c(x)


Sean:
Sx = {tareas seleccionadas para S hasta el nodo x}
mx = max{i | i ∈ Sx }
Entonces:
Para los nodos circulares:
X
ĉ(x) = wi
i<m,i6∈Sx

Penalización debida a las tareas que ya han quedado excluidas de x.


Para los nodos cuadrados:
ĉ(x) = ∞

Simona Bernardi Ramificación y poda 37 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de estimación ĉ(x) ≤ c(x)

Simona Bernardi Ramificación y poda 38 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de estimación ĉ(x) ≤ c(x)

Simona Bernardi Ramificación y poda 39 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Definición de la función de poda U

(Recordar) U debe ser cota superior del coste de una solución de


mı́nimo coste
Para cada nodo x, se puede calcular un valor de U:
X
U= wi
i6∈S

Simona Bernardi Ramificación y poda 40 / 73


Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Algoritmo de ramificación y poda


Estrategia de mı́nimo coste con representación de tamaño variable

Empieza con U = 24 y 1 como nodo en expansión (único nodo vivo)


Se expande 1 generando: 2 3 4 5
U se actualiza a 14 al generar 3
4 5 se matan porque ĉ(4) = 15 > U, ĉ(5) = 21 > U
Simona Bernardi Ramificación y poda 41 / 73
Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Algoritmo de ramificación y poda


Estrategia de mı́nimo coste con representación de tamaño variable

El siguiente nodo en expansión: 2 (ĉ(2) < ĉ(3))


Se expande 2 generando: 6 7 8 ; U se actualiza a 9 al generar 6
7 8 se matan porque ĉ(7) = 10 > U = 9, ĉ(8) = ∞
Los nodos vivos son: 3 6
Simona Bernardi Ramificación y poda 42 / 73
Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Algoritmo de ramificación y poda


Estrategia de mı́nimo coste con representación de tamaño variable

El siguiente nodo en expansión: 6 (ĉ(6) < ĉ(3))


Se expande 6 generando: 12 13 no factibles
El siguiente nodo en expansión: 3
Se expande 3 generando: 9 10 ; U se actualiza a 8 al generar 9
10 se mata porque ĉ(10) = 11 > U = 8
Simona Bernardi Ramificación y poda 43 / 73
Ramificación y poda
Aplicación (problema de planificación de tareas a plazo fijo)

Algoritmo de ramificación y poda


Estrategia de mı́nimo coste con representación de tamaño variable

El único nodo vivo es 9 : se convierte en el nodo en expansión


Su único hijo es no factible, por tanto se acaba la búsqueda
La solución es el nodo 9
Simona Bernardi Ramificación y poda 44 / 73
Ramificación y poda
Aplicación (problema de la mochila 0-1)

Problema de la mochila 0-1


Repaso

Hay n objetos y una mochila


n
El objeto i tiene peso pi y su X
max bi xi
inclusión en la mochila produce
i=1
un beneficio bi Xn
Objetivo: llenar la mochila de s.t. pi xi ≤ C
capacidad C , de manera que se i=1
maximice el beneficio xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n

Simona Bernardi Ramificación y poda 45 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Problema de la mochila 0-1


Repaso

Hay n objetos y una mochila


n
El objeto i tiene peso pi y su X
max bi xi
inclusión en la mochila produce
i=1
un beneficio bi Xn
Objetivo: llenar la mochila de s.t. pi xi ≤ C
capacidad C , de manera que se i=1
maximice el beneficio xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n

Soluciones a problemas parecidos


Objetos fraccionables (0 ≤ xi ≤ 1, 1 ≤ i ≤ n): solución voraz
Mochila 0-1 con pesos, beneficios y capacidad de la mochila números
naturales (solución de programación dinámica)
En el caso general, ninguna de las dos soluciones funciona
Simona Bernardi Ramificación y poda 45 / 73
Ramificación y poda
Aplicación (problema de la mochila 0-1)

Solución con técnica de ramificación y poda


Transformación del problema en un problema de minimización

n
X
min − bi xi
i=1
n
X
s.t. pi xi ≤ C
i=1
xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n

Espacio de soluciones: 2n modos de asignar 0 ó 1 a las xi


Dos formas de representar la solución (tuplas de tamaño fijo o
variable)
Elegimos la representación con tuplas de tamaño fijo

Simona Bernardi Ramificación y poda 46 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Definición de la función de coste

Las hojas x tales que:


n
X
pi xi ≤ C
i=1

representan soluciones factibles


El resto de las hojas representan
soluciones no factibles

 P
n
− i=1 bi xi , si x nodo solución factible


c(x) = ∞   si x nodo solución no factible

min c(xizdo ), c(xdcho )

si x nodo no hoja
Simona Bernardi Ramificación y poda 47 / 73
Ramificación y poda
Aplicación (problema de la mochila 0-1)

Definición de las funciones de estimación y de poda


Funciones ĉ(x) y U tales que:

ĉ(x) ≤ c(x) ≤ U

Definición sencilla de U
Si x es un nodo de nivel j, con 1 ≤ j ≤ n, se han asignado ya valores
a xi , 1 ≤ i ≤ j, por tanto:
j
X
c(x) ≤ − bi xi = U
i=1

Beneficio actual cambiado de signo

Simona Bernardi Ramificación y poda 48 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Algoritmo de la función de poda mejorada

const N=... {número de objetos}


tipo vectReal=vector[1..N] de real
variables C:real; benef,peso:vectReal
{Pre: forall i = 1..n: peso[i]>0 and
forall i=1..n-1: benef[i]/peso[i] >= benef[i+1]/peso[i+1]}

funcion U_mejor(cap,Ufácil:real; obj:entero) devuelve real


{cap=capacidad ya ocupada de la mochila; Ufácil=valor de U
calculado de forma fácil; obj=ı́ndice del primer objeto a considerar}
variables: ca,U:real
principio
U:=Ufácil; ca:=cap;
para i:=obj hasta N hacer
si ca+peso[i] <= C entonces ca:=ca+peso[i]; U:=U-benef[i] fsi
fpara;
devuelve U
fin

Simona Bernardi Ramificación y poda 49 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Algoritmo de la función de poda mejorada

const N=... {número de objetos}


tipo vectReal=vector[1..N] de real
variables C:real; benef,peso:vectReal
{Pre: forall i = 1..n: peso[i]>0 and
forall i=1..n-1: benef[i]/peso[i] >= benef[i+1]/peso[i+1]}

funcion U_mejor(cap,Ufácil:real; obj:entero) devuelve real


{cap=capacidad ya ocupada de la mochila; Ufácil=valor de U
calculado de forma fácil; obj=ı́ndice del primer objeto a considerar}
variables: ca,U:real
principio
U:=Ufácil; ca:=cap;
para i:=obj hasta N hacer
si ca+peso[i] <= C entonces ca:=ca+peso[i]; U:=U-benef[i] fsi
fpara;
devuelve U P
j Pj 
fin U = U mejor i=1 pi xi , − i=1 bi xi , j +1

Simona Bernardi Ramificación y poda 49 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Definición de la función de estimación

Utilizar la función de poda que se definió para el método de búsqueda


con retroceso
Era una cota superior del valor de la mejor solución posible al expandir
el nodo y sus descendientes
Ahora hemos cambiado de signo la función objetivo
Luego, cambiada de signo, es una cota inferior de c(x)
¿Cómo se calculó esa cota?
En el nodo x de nivel j ya se han determinado xi , 1 ≤ i ≤ j
Relajar el requisito de integridad:
xi ∈ {0, 1}, j + i ≤ i ≤ n se sustituye por 0 ≤ xi ≤ 1, j + i ≤ i ≤ n
Aplicar el algoritmo voraz

Simona Bernardi Ramificación y poda 50 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Algoritmo de la función de estimación


const N=... {número de objetos}
tipo vectReal=vector[1..N] de real
variables C:real; benef,peso:vectReal
{Pre: forall i = 1..n: peso[i]>0 and
forall i=1..n-1: benef[i]/peso[i] >= benef[i+1]/peso[i+1]}

funcion cota(cap,ben:real; obj:entero) devuelve real


{cap=capacidad aún libre de la mochila; ben=beneficio actual;
obj=ı́ndice del primer objeto a considerar}
principio
si obj>N or cap=0.0 entonces devuelve ben
sino
si peso[obj]>cap entonces devuelve ben+cap/peso[obj]*benef[obj]
sino
devuelve cota(cap-peso[obj],ben+benef[obj],obj+1)
fsi
fsi
fin

Simona Bernardi Ramificación y poda 51 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Algoritmo de la función de estimación


const N=... {número de objetos}
tipo vectReal=vector[1..N] de real
variables C:real; benef,peso:vectReal
{Pre: forall i = 1..n: peso[i]>0 and
forall i=1..n-1: benef[i]/peso[i] >= benef[i+1]/peso[i+1]}

funcion cota(cap,ben:real; obj:entero) devuelve real


{cap=capacidad aún libre de la mochila; ben=beneficio actual;
obj=ı́ndice del primer objeto a considerar}
principio
si obj>N or cap=0.0 entonces devuelve ben
sino
si peso[obj]>cap entonces devuelve ben+cap/peso[obj]*benef[obj]
sino
devuelve cota(cap-peso[obj],ben+benef[obj],obj+1)
fsi
fsi  
ĉ(x) = −cota C − ji=1 pi xi , ji=1 bi xi , j
P P
fin +1

Simona Bernardi Ramificación y poda 51 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Ejemplo ../..
n=4
(b1 , b2 , b3 , b4 ) = (10, 10, 12, 18)
(p1 , p2 , p3 , p4 ) = (2, 4, 6, 9)
C = 15
Nodo en expansión: 1 (raı́z, nivel 0, ninguna xi asignada)

ĉ(1)=−cota(15, 0, 1)
=−cota(13, 10, 2)
=−cota(9, 20, 3)
== −cota(3, 32, 4)
=−(32 + 3/9 ∗ 18) = −38
U =−32
Simona Bernardi Ramificación y poda 52 / 73
Ramificación y poda
Aplicación (problema de la mochila 0-1)

Ejemplo ../..

n=4
(b1 , b2 , b3 , b4 ) = (10, 10, 12, 18)
(p1 , p2 , p3 , p4 ) = (2, 4, 6, 9)
C = 15

2 siguiente nodo en expansión

4 siguiente nodo en expansión


¿Siguiente nodo en expansión?
Hay 6 y 7 con igual prioridad
...

Simona Bernardi Ramificación y poda 53 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Ejemplo
Si se elige 6 : el hijo izquierdo n=4
se elimina por no ser factible, el
(b1 , b2 , b3 , b4 ) = (10, 10, 12, 18)
derecho se añade a la cola de
nodos vivos, con coste -32, (p1 , p2 , p3 , p4 ) = (2, 4, 6, 9)
mayor que el nodo 7 C = 15

7 siguiente nodo en expansión


Nuevo valor de U = −38
Los nodos 3 5 y 9 se matan
(no alcanzan el valor U)

El nodo 8 es el único de la cola y es hoja: el valor óptimo es 38

Simona Bernardi Ramificación y poda 54 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Observaciones
Para poder imprimir la solución (además del valor óptimo) hay que:
Guardar con cada nodo una identificación de su padre (identificador,
puntero, curso,. . . )
Mantener una variable auxiliar con el valor del último nodo solución
que ha permitido actualizar U
Asociar con cada nodo un booleano que diga si es un hijo izquierdo o
derecho (es decir, si se mete en la mochila el objeto correspondiente o
no)

Simona Bernardi Ramificación y poda 55 / 73


Ramificación y poda
Aplicación (problema de la mochila 0-1)

Observaciones
Para poder imprimir la solución (además del valor óptimo) hay que:
Guardar con cada nodo una identificación de su padre (identificador,
puntero, curso,. . . )
Mantener una variable auxiliar con el valor del último nodo solución
que ha permitido actualizar U
Asociar con cada nodo un booleano que diga si es un hijo izquierdo o
derecho (es decir, si se mete en la mochila el objeto correspondiente o
no)
Cabe pensar en una versión con estrategia ciega de ramificación (FIFO,
por ejemplo):
Por un lado la intuición nos dice que la estrategia de mı́nimo coste se
acerca más de prisa a la solución óptima
Por otra parte, la inserción y borrado en la cola con prioridades de
nodos vivos tiene coste logarı́timico, mientras que con una cola FIFO,
el coste es constante . . .
Simona Bernardi Ramificación y poda 55 / 73
Ramificación y poda
Aplicación (problema del viajante de comercio)

El problema del viajante de comercio

Encontrar un recorrido de longitud mı́nima para un viajante que tiene que


visitar varias ciudades y volver al punto de partida, conocida la distancia
existente entre cada dos ciudades.

Es decir, dado un grafo dirigido con arcos de longitud no negativa, se


trata de encontrar un circuito de longitud mı́nima que comience y
termine en el mismo vértice y pase exactamente una vez por cada uno
de los vértices restantes (circuito hamiltoniano).

Simona Bernardi Ramificación y poda 56 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Soluciones propuestas
El problema del viajante de comercio es probablemente el problema
NP-completo más estudiado en términos de soluciones propuestasa
a
U. Manber: Introduction to Algorithms. A Creative Approach. Addison Wesley, 1989.

Solución heurı́stica voraz


Calcula una solución subóptima
Programación dinámica:
Coste en tiempo: Θ(n2 2n )
Coste en espacio: Ω(n2n )

Simona Bernardi Ramificación y poda 57 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Soluciones propuestas
El problema del viajante de comercio es probablemente el problema
NP-completo más estudiado en términos de soluciones propuestasa
a
U. Manber: Introduction to Algorithms. A Creative Approach. Addison Wesley, 1989.

Solución heurı́stica voraz


Calcula una solución subóptima
Programación dinámica:
Coste en tiempo: Θ(n2 2n )
Coste en espacio: Ω(n2n )
El coste del caso peor de la solución que vamos a ver seguirá estando
en Θ(n2 2n )
Sin embargo, el uso de buenas funciones de acotación mejora la
eficiencia en muchos casos con respecto a la solución de programación
dinámica
Simona Bernardi Ramificación y poda 57 / 73
Ramificación y poda
Aplicación (problema del viajante de comercio)

Formalización del problema

Sean G = (V , A) un grafo orientado:


n vértices V = {1, 2, . . . , n}
Lij la longitud de (i, j) ∈ A. Si el arco (i, j) no existe: Lij = ∞
El circuito buscado empieza en el vértice 1

Espacio de soluciones: E = {1, π, 1 | π es una permutación de


(2, 3, . . . , n)}
Tamaño: |E | = (n − 1)!

Reducción del espacio de soluciones


E = {1, π, 1 | π = i1 , i2 , . . . , in−1 , es una permutación de (2, 3, . . . , n) tal
que (ij , ij+1 ) ∈ A, 0 ≤ j ≤ n − 1 y i0 = in = 1}.

Simona Bernardi Ramificación y poda 58 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Representación del espacio de estados


Caso de un grafo completo |V | = 4

Cada hoja es una solución y representa el viaje definido por el camino


desde la raı́z hasta la hoja.

Simona Bernardi Ramificación y poda 59 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de coste

La función c debe ser tal que el nodo solución x con valor mı́nimo de
c(x) corresponda a un recorrido de longitud mı́nima
Por ejemplo:
Si x es una hoja, entonces c(x) es la longitud del hamiltoniano definido
por el camino desde la raı́z hasta x
Si x no es una hoja, entonces c(x) es el coste de una hoja de coste
mı́nimo del subárbol con raı́z x

Simona Bernardi Ramificación y poda 60 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


La función ĉ debe ser tal que ĉ(x) ≤ c(x), para cada x
Una función muy fácil:
ĉ(x) es la distancia total del recorrido definido por el camino desde la
raı́z hasta x

Si es una hoja, es obvio que ĉ(x) = c(x)

Simona Bernardi Ramificación y poda 61 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


Mejora de ĉ(x)

Matriz de distancias reducidas


Una fila (columna) de la matriz de distancias se dice reducida si sus
elementos son no negativos y contiene al menos un 0 (cero)
Una matriz de distancias se dice reducida si cada fila y columna es
reducida

Simona Bernardi Ramificación y poda 62 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


Mejora de ĉ(x)

Matriz de distancias reducidas


Una fila (columna) de la matriz de distancias se dice reducida si sus
elementos son no negativos y contiene al menos un 0 (cero)
Una matriz de distancias se dice reducida si cada fila y columna es
reducida

Para cada k, 1 ≤ k ≤ n, todo circuito hamiltoniano incluye


exactamente un arco de la forma (k, ·) y exactamente un arco de la
forma (·, k)
Si se resta una constante t de cada elemento de una fila (columna)
de la matriz de distancia, la longitud de todo hamiltoniano se reduce
exactamente en t y un hamiltoniano de distancia mı́nima lo sigue
siendo
Simona Bernardi Ramificación y poda 62 / 73
Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


Ejemplo de reducción    
∞ 20 30 10 11 ∞ 10 20 0 1
15
 ∞ 16 4 2
15
 ∞ 16 4 2 
Reducción fila 1, t = 10  3
 5 ∞ 2 4
3
 5 ∞ 2 4 
19 6 18 ∞ 3 19 6 18 ∞ 3
16 4 7 16 ∞ 16 4 7 16 ∞
   
∞ 20 30 10 11 ∞ 10 17 0 1
Se repite el proceso 15 ∞ 16 4 2 12 ∞ 11 2 0
hasta obtener la matriz  3
   
5 ∞ 2 4 0 3 ∞ 0 2
de distancia reducida
   
19 6 18 ∞ 3 15 3 12 ∞ 0
Reducción: L = 25 16 4 7 16 ∞ 11 0 0 12 ∞

La cantidad L total restada es una cota inferior de la longitud de un


hamiltoniano de longitud mı́nima, luego sirve como estimación de ĉ(x)
para el nodo x raı́z.
Simona Bernardi Ramificación y poda 63 / 73
Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


Cálculo de ĉ(x) para los nodos x intermedios (no raı́z y no hoja)
Sea A la matriz de distancia reducida para el nodo y
Sea x un hijo de y que corresponda a incluir el arco (i, j) en el
recorrido y que no sea hoja
La matriz B reducida para x se calcula de la siguiente forma:

Simona Bernardi Ramificación y poda 64 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de estimación


Cálculo de ĉ(x) para los nodos x intermedios (no raı́z y no hoja)
Sea A la matriz de distancia reducida para el nodo y
Sea x un hijo de y que corresponda a incluir el arco (i, j) en el
recorrido y que no sea hoja
La matriz B reducida para x se calcula de la siguiente forma:

1 Cambiar todos los elementos de la fila i y de la columna j de A por ∞


2 Cambiar el elemento A(j, 1) por ∞ para evitar considerar el arco (j, 1)
3 B es la matriz que se obtiene al reducir todas las filas y columnas de
la matriz resultante (excepto aquéllas formadas sólo por ∞).
Si r es el valor total restado:
ĉ(x) = ĉ(y ) + A(i, j) + r

Simona Bernardi Ramificación y poda 64 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Definición de la función de poda

Una función de poda trivial:


Inicialmente, U = ∞
Se modifica U sólo cuando se llega a un nodo x que es hoja (solución
factible), entonces: 
U = min U, c(x)
Se puede pensar en mejores funciones de poda

Simona Bernardi Ramificación y poda 65 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Ejemplo

∞ 20 30 10 11 ∞ 10 17 0 1
   
15 ∞ 16 4 2 12 ∞ 11 2 0
3 5 ∞ 2 4  Grafo original 0 3 ∞ 0 2  Reducción: L = 25
   
19 6 18 ∞ 3 15 3 12 ∞ 0
16 4 7 16 ∞ 11 0 0 12 ∞

Simona Bernardi Ramificación y poda 66 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Ejemplo

El siguiente nodo a expander


serı́a 5 pero ĉ(5) > U luego el
algoritmo termina
El hamiltoniano mı́nimo es
1,4,2,5,3,1

Simona Bernardi Ramificación y poda 67 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Otras soluciones

Un hamiltoniano es un conjunto de n arcos


Además, para cada vértice i, 1 ≤ i ≤ n, debe haber en ese conjunto
exactamente un arco de la forma (i, ·) y uno de la forma (·, i)
Representación del espacio de estados como un árbol binario
Un hijo izquierdo representa la inclusión de un determinado arco en el
hamiltoniano
Un hijo derecho representa la exclusión de ese arco

Simona Bernardi Ramificación y poda 68 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Representaciones con árboles binarios


Hay distinto árboles dependiendo de qué arco se elige para
incluir/excluir en cada paso

¿Cómo elegir el arco por el que empezar?


Depende de los datos del problema
Árbol de estados dinámico: el método de construcción depende de
los datos del problema
Simona Bernardi Ramificación y poda 69 / 73
Ramificación y poda
Aplicación (problema del viajante de comercio)

Representaciones con árboles binarios


Si se elige, para empezar, el arco (i, j)
El subárbol izquierdo representa todos los recorridos que incluyen (i, j)
El subárbol derecho representa todos los recorridos que no lo incluyen
Si hay un recorrido óptimo incluido en el subárbol izquierdo, entonces
sólo faltan por seleccionar n − 1 arcos para encontrarlo
Mientras que si todos los recorridos óptimos están en el derecho, hay
que seleccionar todavı́a n arcos
Hay que intentar seleccionar un arco que tenga la máxima
probabilidad de estar en el recorrido óptimo
Varias heurı́sticas posibles:
Elegir un arco que produzca un subárbol derecho cuya raı́z tenga ĉ(x)
máxima
Elegir un arco tal que la diferencia entre ĉ(xizquierdo ) y ĉ(xderecho ) sea
máxima

Simona Bernardi Ramificación y poda 70 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Representaciones con árboles binarios


Heurı́stica del máximo coste estimado

∞ 20 30 10 11
 
15 ∞ 16 4 2
3 5 ∞ 2 4
 
19 6 18 ∞ 3
16 4 7 16 ∞
Grafo original

Al nodo 6 se han elegido ya tres arcos: (3, 1), (5, 3) y (1, 4)


Para los restantes, sólo queda ya una opción: (4, 2) y (2, 5)
Hamiltoniano: 5,3,1,4,2,5 con distancia total: 28 (ası́, U = 28)
El siguiente nodo a expander es 3 con ĉ(3) > U. El algoritmo acaba.

Simona Bernardi Ramificación y poda 71 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Observaciones

En el último ejemplo, el método de ramificación y poda se usa sólo


para subárboles grandes
Una vez que se llega a subárboles pequeños (4 ó 6 nodos) es más
eficientes construirlos enteros y calcular el valor exacto de la función
de coste

No hay forma de calcular analı́ticamente cuál de las soluciones del


problema del viajante de comercio es más eficiente.

Simona Bernardi Ramificación y poda 72 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Consideraciones finales sobre eficiencia


¿Es posible disminuir el algún caso el número de nodos generados
mediante la expansión de nodos x con ĉ(x) > U?

Nunca porque el valor de U no será modificado si se expande tal nodo x,


y es el valor de U que determina qué nodos se expanden en el futuro.

Simona Bernardi Ramificación y poda 73 / 73


Ramificación y poda
Aplicación (problema del viajante de comercio)

Consideraciones finales sobre eficiencia


¿Es posible disminuir el algún caso el número de nodos generados
mediante la expansión de nodos x con ĉ(x) > U?

Nunca porque el valor de U no será modificado si se expande tal nodo x,


y es el valor de U que determina qué nodos se expanden en el futuro.

Si hay dos funciones de poda U1 , U2 diferentes y U1 < U2 entonces


siempre es mejor usar U1 (nunca dará lugar a más nodos)
¿Si se usa una función de estimación mejor, decrece el número de
nodos a expandir? (ĉ2 es mejor que ĉ1 si ĉ1 ≤ ĉ2 ≤ c)

No necesariamente. Si se usa una función de estimación mejor con la


estrategia de ramificación de mı́nimo coste, el número de nodos
generados puede crecer.

Simona Bernardi Ramificación y poda 73 / 73


Programación lineal

Simona Bernardi
Universidad de Zaragoza

Curso 2018/19
Grado en Ingenierı́a Informática
Aula A.12
Presentación adaptada de la original de J. Julvez

Este documento está sujeto a una licencia de uso Creative Commons. No se permite
un uso comercial de la obra original ni de las posibles obras derivadas, la distribución
de las cuales se debe hacer con una licencia igual a la que regula la obra original.
Programación lineal

Resumen

Introducción
Método general
Formulación del problema general
Interpretación geométrica
Algoritmo sı́mplex
Dualidad
Reducciones
Aplicación
El problema de la fábrica de cerveza
El problema de flujo máximo/mı́nimo corte
El problema de emparejamiento bipartido

Simona Bernardi Programación lineal 2 / 67


Programación lineal
Introducción

Introducción
Técnica para la resolución de problemas de asignación óptima de un
número limitado de recursos entre un conjunto de tareas que
compiten entre sı́.

max 12A + 20B


t.q. 4A + 12B ≤ 384
0,1A + 0,1B ≤ 4
14A + 8B ≤ 476
A, B ≥ 0

Se puede aplicar a muchos problemas diferentes


Problemas de caminos mı́nimos, máximo flujo, asignación, . . .
Existen muchas herramientas de soporte (comerciales y libres)
Simona Bernardi Programación lineal 3 / 67
Programación lineal
Introducción

Aplicaciones

Simona Bernardi Programación lineal 4 / 67


Programación lineal
Aplicación: el problema de la fábrica de cerveza

El problema de la fábrica de cerveza


Dos nuevos tipos diferentes de
cerveza: Ale y Lambic
Hay una cantidad limitada de
materia prima
Trigo: 384Kg
Lúpulo: 4Kg
Cebada: 476Kg
Cada tipo requiere diferentes 1 barril trigo lúpulo cebada
proporciones de materia prima (50 litros) (Kg.) (Kg.) (Kg.)
Hay un beneficio diferente en la Ale 4 0.1 14
Lambic 12 0.1 8
venta de cada tipo
1 barril
¿Cuántos barriles hay que Ale 12e
producir para maximizar el Lambic 20e
beneficio?
Simona Bernardi Programación lineal 5 / 67
Programación lineal
Aplicación: el problema de la fábrica de cerveza

Formalización en un problema de programación lineal

Sean
A número de barriles del tipo Ale
B número de barriles del tipo Lambic

max 12A + 20B (beneficio)


t.q. 4A + 12B ≤ 384 (trigo)
0,1A + 0,1B ≤ 4 (l úpulo)
14A + 8B ≤ 476 (cebada)
A, B ≥ 0

Simona Bernardi Programación lineal 6 / 67


Programación lineal
Aplicación: el problema de la fábrica de cerveza

Resolución en el plano cartesiano


Región factible
Las desigualdades definen semiplanos
La región factible es un polı́gono convexo
lúpulo
0.1A+0.1B=4

cebada
(0;32) 14A+8B=476

(12;28)

Lambic
trigo
(26;14) 4A+12B=384

(0;0)
Ale (34;0)

Simona Bernardi Programación lineal 7 / 67


Programación lineal
Aplicación: el problema de la fábrica de cerveza

Resolución en el plano cartesiano


Función objetivo
Gradiente en el origen de la función ∇ = (12, 20)
La solución óptima se encuentra en un vértice
Intersección de dos rectas en R2

mayor beneficio?
(0;32)

(12;28)
12A+20B=1200euro

Lambic

(26;14)

12A+20B=704euro
(0;0)
Ale (34;0)
12A+20B=408euro

Simona Bernardi Programación lineal 8 / 67


Programación lineal
Formulación del problema general

Formulación del problema LP


Objetivo
Maximizar (o minimizar) una función lineal de n variables, sujeta a m
desigualdades o igualdades (≤, ≥, =) lineales.

max c1 x1 + c2 x2 + · · · + cn xn Datos en entrada:


A = (aij ) ∈ Rm×n
t.q. a11 x1 + a12 x2 + · · · + a1n xn T b1
b = (bj ) ∈ Rm
a12 x1 + a22 x2 + · · · + a2n xn T b2 c = (ci ) ∈ Rn
.. .. Variables:
. .
x = (xi ) ∈ Rn
am1 x1 + am2 x2 + · · · + amn xn Tbm
x1 , x2 , . . . , xn ∈ R max cT x s.t. Ax T b

Simona Bernardi Programación lineal 9 / 67


Programación lineal
Formulación del problema general

Formas estándar
Se añaden las restricciones de signo
Algunos autores llaman estándar a la canónica otros a la slack

Forma canónica Forma(s) slack


max c1 x1 + c2 x2 + · · · + cn xn max c1 x1 + c2 x2 + · · · + cn xn
t.q. a11 x1 + a12 x2 + · · · + a1n xn ≤b1 t.q. a11 x1 + a12 x2 + · · · + a1n xn =b1
a12 x1 + a22 x2 + · · · + a2n xn ≤b2 a12 x1 + a22 x2 + · · · + a2n xn =b2
.. .. .. ..
. . . .
am1 x1 + am2 x2 + · · · + amn xn ≤bm am1 x1 + am2 x2 + · · · + amn xn =bm
x1 , x2 , . . . , xn ≥ 0 x1 , x2 , . . . , xn ≥ 0

max cT x t.q. Ax ≤ b, x ≥ 0 max cT x t.q. Ax = b, x ≥ 0

Simona Bernardi Programación lineal 10 / 67


Programación lineal
Aplicación: el problema de la fábrica de cerveza

Transformación del problema en forma slack


Forma slack
Problema original max Z
12A +20B −Z = 0
max 12A + 20B
t.q. 4A + 12B ≤ 384 t.q. 4A +12B+Sc = 384
0,1A + 0,1B ≤ 4 0,1A+0,1B +Sd = 4
14A + 8B ≤ 476 14A +8B +Se = 476
A, B ≥ 0 A, B, Sc , Sd , Se , Z ≥ 0

Se añade
Una variable Z y la ecuación correspondiente a la función objetivo
Una variable slack para transformar una desigualdad en igualdad
Restricciones de signo
Problema en R6
Simona Bernardi Programación lineal 11 / 67
Programación lineal
Interpretación geométrica

Resolución en el espacio Rn
Dado un problema LP:
Un punto x ∈ Rn es factible si satisface a todas restricciones lineales
El conjunto de los puntos factibles se llama región factible
Las restricciones de igualdad definen hiperplanos en Rn
Las restricciones de desigualdad definen semiespacios Rn
La región factible es la intersección de los hiperplanos y semiespacios
⇒ poliedro convexo

punto extremo (vértice)

No convexo Convexo

Ejemplo en R2
Simona Bernardi Programación lineal 12 / 67
Programación lineal
Interpretación geométrica

Propiedad de los vértices


Si existe una solución óptima al problema LP, entonces existe una
solución óptima que es un vértice
El número de vértices a considerar es finito ,
El número de vértices puede ser exponencial /

Los óptimos locales son óptimos


globales porque la función
objetivo es lineal y la región
factible es convexa
Propiedad voraz: un vértice es
óptimo si y sólo si no hay mejor
vértice adyacente

Simona Bernardi Programación lineal 13 / 67


Programación lineal
Algoritmo sı́mplex

Algoritmo sı́mplex [George Dantzig, 1947]


Desarrollado después de la II guerra Mundial para resolver problemas
de lógistica
Clasificado como uno de los 10 mejores algoritmos del siglo XX

Idea básica

1 Empieza en un vértice de la región factible


2 Se mueve a un vértice adyacente que genera un
mejor valor para la función objetivo
3 Repite el paso 2 hasta que no exista mejor
vértice
vértice inicial
4 El último vértice visitado es un óptimo global
Ejemplo en R2

Simona Bernardi Programación lineal 14 / 67


Programación lineal
Algoritmo sı́mplex

Solución factible básica


Una base es un subconjunto de p < n variables
Solución factible básica (SFB)
Inicializa a cero las n − p variables que no están en la base
Resolve p ecuaciones en p variables
Si existe una solución única y factible, entonces es una SFB
SFB ⇔ vértice
max Z
12A +20B −Z = 0 solución factible básica

{B,Sd,Se} solución no factible básica


(0;32) {A,B,Se}
(12;28)
t.q. 4A +12B+Sc = 384
{A,B,Sd}
0,1A+0,1B +Sd = 4 (16,92;22,25)
Lambic
14A +8B +Se = 476 {A,B,Sc}
(26;14)
A, B, Sc , Sd , Se , Z ≥ 0
{A,Sc,Sd}
{Sc,Sd,Se}
(34;0)
(0;0)
Ale

Simona Bernardi Programación lineal 15 / 67


Programación lineal
Algoritmo sı́mplex

Inicialización
max Z
12A +20B −Z = 0
Base={Sc,Sd,Se}
A=B=0 (0;0)
Z=0
t.q. 4A +12B+Sc = 384 Sc=384
0,1A+0,1B +Sd = 4 Sd=4
Lambic Se=476
14A +8B +Se = 476
A, B, Sc , Sd , Se , Z ≥ 0
(0;0)
Ale

Solución factible inicial:


Variables slack en la base {SC , SD , SE }
Variables A, B inicializadas a cero
Solución 4 ecuaciones, 4 variables

Simona Bernardi Programación lineal 16 / 67


Programación lineal
Algoritmo sı́mplex

Pivote – primera iteración


max Z
max Z 16 5
A − Sc −Z = −640 (1)
12A +20B −Z = 0 3 3
1 1
t.q. A+B + Sc = 32 (2)
t.q. 4A +12B+Sc = 384 3 12
1 1 1 1 4
A+ B +Sd = 4 A − Sc +Sd = (3)
10 10 15 120 5
14A +8B +Se = 476 34 2
A − Sc +Se = 220 (4)
A, B, Sc , Sd , Se , Z ≥ 0 3 3
A, B, Sc , Sd , Se , Z ≥ 0

1
Sustituir B = 12 (384 − 4A − Sc ) Base={B,Sd,Se}
(0;32) A=Sc=0 (0;32)
Z=640
Añadir B a la base B=32
Sd=8/10
Volver a escribir la ecuación (2) Lambic Se=220

Eliminar B en las ecuaciones


(1,3,4) (0;0)
Ale

Simona Bernardi Programación lineal 17 / 67


Programación lineal
Algoritmo sı́mplex

Selección del pivote


max Z ↓
12A +20B −Z = 0 (1)

t.q. → 4A +12B+Sc = 384 (2)


1 1
A+ B +Sd = 4 (3)
10 10
14A +8B +Se = 476 (4)
A, B, Sc , Sd , Se , Z ≥ 0

¿Porqué elegimos el pivote en la columna de la variable B?

Simona Bernardi Programación lineal 18 / 67


Programación lineal
Algoritmo sı́mplex

Selección del pivote


max Z ↓
12A +20B −Z = 0 (1)

t.q. → 4A +12B+Sc = 384 (2)


1 1
A+ B +Sd = 4 (3)
10 10
14A +8B +Se = 476 (4)
A, B, Sc , Sd , Se , Z ≥ 0

¿Porqué elegimos el pivote en la columna de la variable B?


Tiene un coeficiente positivo en la función objetivo (cada incremento
de una unidad en B incrementa la función objetivo de 20e)
La columna de la variable A también vale

Simona Bernardi Programación lineal 18 / 67


Programación lineal
Algoritmo sı́mplex

Selección del pivote


max Z ↓
12A +20B −Z = 0 (1)

t.q. → 4A +12B+Sc = 384 (2)


1 1
A+ B +Sd = 4 (3)
10 10
14A +8B +Se = 476 (4)
A, B, Sc , Sd , Se , Z ≥ 0

¿Porqué elegimos el pivote en la columna de la variable B?


Tiene un coeficiente positivo en la función objetivo (cada incremento
de una unidad en B incrementa la función objetivo de 20e)
La columna de la variable A también vale
¿Porqué elegimos el pivote en la fila (2)?

Simona Bernardi Programación lineal 18 / 67


Programación lineal
Algoritmo sı́mplex

Selección del pivote


max Z ↓
12A +20B −Z = 0 (1)

t.q. → 4A +12B+Sc = 384 (2)


1 1
A+ B +Sd = 4 (3)
10 10
14A +8B +Se = 476 (4)
A, B, Sc , Sd , Se , Z ≥ 0

¿Porqué elegimos el pivote en la columna de la variable B?


Tiene un coeficiente positivo en la función objetivo (cada incremento
de una unidad en B incrementa la función objetivo de 20e)
La columna de la variable A también vale
¿Porqué elegimos el pivote en la fila (2)?
Preserva la factibilidad asegurando que b ≥ 0
Regla mı́nimo ratio: min{ 384 476
12 , 40, 8 }
Simona Bernardi Programación lineal 18 / 67
Programación lineal
Algoritmo sı́mplex

Pivote – segunda iteración


max Z max Z
16 5
A − Sc −Z = −640 (1) −Sc −80Sd −Z = −704
3 3
1 1 1
t.q. A+B + Sc = 32 (2) t.q. +B+ Sc −5Sd = 28
3 12 8
1 1 4 1
A − Sc +Sd = (3) A − Sc +15Sd = 12
15 120 5 8
34 2 3
A − Sc +Se = 220 (4) + Sc −170Sd +Se = 84
3 3 4
A, B, Sc , Sd , Se , Z ≥ 0 A, B, Sc , Sd , Se , Z ≥ 0

Base={A,B,Se}
Sustituir A = 15( 54 + 1
120 Sc − Sd ) (0;32) (12;28)
Sc=Sd=0 (12;28)
Z=704
A=12
Añadir A a la base B=28
Lambic Se=84
Volver a escribir la ecuación (3)
Eliminar A en las ecuaciones (1,2,4)
(0;0)
Ale

Simona Bernardi Programación lineal 19 / 67


Programación lineal
Algoritmo sı́mplex

Optimalidad
max Z
−Sc −80Sd −Z = −704 (1)
Base={A,B,Se}
1 (0;32) (12;28)
Sc=Sd=0 (12;28)
t.q. +B+ Sc −5Sd = 28 (2) Z=704
8 A=12
1 B=28
A − Sc +15Sd = 12 (3) Lambic Se=84
8
1
+ Sc −170Sd +Se = 84 (4)
3
A, B, Sc , Sd , Se , Z ≥ 0 (0;0)
Ale

¿Cuándo se termina?

Simona Bernardi Programación lineal 20 / 67


Programación lineal
Algoritmo sı́mplex

Optimalidad
max Z
−Sc −80Sd −Z = −704 (1)
Base={A,B,Se}
1 (0;32) (12;28)
Sc=Sd=0 (12;28)
t.q. +B+ Sc −5Sd = 28 (2) Z=704
8 A=12
1 B=28
A − Sc +15Sd = 12 (3) Lambic Se=84
8
1
+ Sc −170Sd +Se = 84 (4)
3
A, B, Sc , Sd , Se , Z ≥ 0 (0;0)
Ale

¿Cuándo se termina?
Cuando no hay coeficientes positivos en la función objetivo

Simona Bernardi Programación lineal 20 / 67


Programación lineal
Algoritmo sı́mplex

Optimalidad
max Z
−Sc −80Sd −Z = −704 (1)
Base={A,B,Se}
1 (0;32) (12;28)
Sc=Sd=0 (12;28)
t.q. +B+ Sc −5Sd = 28 (2) Z=704
8 A=12
1 B=28
A − Sc +15Sd = 12 (3) Lambic Se=84
8
1
+ Sc −170Sd +Se = 84 (4)
3
A, B, Sc , Sd , Se , Z ≥ 0 (0;0)
Ale

¿Cuándo se termina?
Cuando no hay coeficientes positivos en la función objetivo
¿Porqué la última SFB es óptima?

Simona Bernardi Programación lineal 20 / 67


Programación lineal
Algoritmo sı́mplex

Optimalidad
max Z
−Sc −80Sd −Z = −704 (1)
Base={A,B,Se}
1 (0;32) (12;28)
Sc=Sd=0 (12;28)
t.q. +B+ Sc −5Sd = 28 (2) Z=704
8 A=12
1 B=28
A − Sc +15Sd = 12 (3) Lambic Se=84
8
1
+ Sc −170Sd +Se = 84 (4)
3
A, B, Sc , Sd , Se , Z ≥ 0 (0;0)
Ale

¿Cuándo se termina?
Cuando no hay coeficientes positivos en la función objetivo
¿Porqué la última SFB es óptima?
Cualquier SFB satisface el sistema de ecuaciones en curso
En particular la (1): Z = 704 − Sc − 80Sd
El valor óptimo z ∗ ≤ 704 porque Sc , Sd ≥ 0
La SFB en curso tiene valor 704 ⇒ es óptima
Simona Bernardi Programación lineal 20 / 67
Programación lineal
Algoritmo sı́mplex

Excepciones
El problema LP no es factible
No es posible satisfacer todas las restricciones (región factible = ∅)
El problema LP no es acotado
max x max x+y
t.q. x <=1; t.q. x >=1;
x >=2 y >=2
x=1 x=2 x=1
y

x+y=k
y=2

x x
Ejemplos en R2
Simona Bernardi Programación lineal 21 / 67
Programación lineal
Algoritmo sı́mplex

Sı́mplex: construcción del cuadro inicial


Problema inicial (forma canónica ⇒ forma slack)
n
X max z
max ci xi X
i=1
t.q. aij xj + xi = bi ,i ∈ B
n j∈N
X
aij xj ≤ bi ,i = 1, . . . , m
X
t.q. cj xj − z = −v
j=1 j∈N
xi ≥ 0 i = 1, . . . , n xi ≥ 0, v = 0 i ∈N ∪B

N = {i | xi fuera de la base}
(|N| = n)
B = {i | xi en base} (|B| = m)
v término constante en la
función objetivo
Simona Bernardi Programación lineal 22 / 67
Programación lineal
Algoritmo sı́mplex

Sı́mplex: esquema algorı́tmico


1 algoritmo sı́mplex(entsal A: matriz, entsal b,c: vector)
2 variables ... {no se especifican por razones de espacio}
3 principio
4 factible := inicializaciónSı́mplex(A,b,c,N,B,v);
5 si not factible entonces escribir("Problema no factible")
6 sino
7 óptimo := falso; noAcotado := falso;
8 mientrasQue not óptimo and not noAcotado hacer
9 si not hayPositivosFO(c,N) entonces óptimo := verdadero
10 sino
11 colP := eligePositivo(c,N) {variable que entra en la base}
12 si not hayPositivos(A,B,colP) entonces noAcotado := verdadero
13 sino {b[filaP]/a[filaP][colP]=min(b[i]/a[i][colP]: i\in B,a[i][colP]>0)}
14 filaP := filaPivote(A,b,B,colP); {variable que sale de la base}
15 pivote(N,B,A,b,c,v,colP,filaP); {cambio de base}
16 fsi fsi
17 fmientrasQue
18 si óptimo entonces escribirSolución(b,c,B,v)
19 sino escribir("Problema no acotado")
20 fin

Simona Bernardi Programación lineal 23 / 67


Programación lineal
Algoritmo sı́mplex

Cuestiones

1 ¿Cómo determinar si un problema es factible?


2 ¿Qué hacemos si un problema es factible, pero la solución básica
inicial no lo es?

⇒ inicializaciónSı́mplex
3 ¿Cómo sabemos si un problema no está acotado?

⇒ hayPositivos
4 ¿Cómo elegimos las variables que entran en la base y las que salen?

⇒ eligePositivo y filaPivote

Simona Bernardi Programación lineal 24 / 67


Programación lineal
Algoritmo sı́mplex

Factibilidad del problema y solución factible básica


Cuestiones 1 & 2

La función inicializaciónSimplex determina si el problema es


factible o no. Si lo es, devuelve la forma slack con la solución factible
básica.

Enfoque inicializaciónSimplex (Fase 1 del sı́mplex)


Si b ≥ 0
La solución que corresponde al vertex origen es factible
Devuelve la forma slack del problema P (cuadro inicial)
Sino crea un problema auxiliar P 0
Soluciona P 0 con el algoritmo sı́mplex (lı́neas 7–17)
Dependiendo del valor de la solución de P 0 decide si el problema
inicial P es factible . . .

Simona Bernardi Programación lineal 25 / 67


Programación lineal
Algoritmo sı́mplex

Factibilidad del problema y solución factible básica


Problema inicial P y problema auxiliar P 0

n
P 0 : max − x0
X
P : max c i xi
i=1
n n
X
X
t.q. aij xj ≤ bi ,i = 1, . . . , m t.q. aij xj − x0 ≤ bi ,i = 1, . . . , m
j=1 j=1

xi ≥ 0 i = 1, . . . , n xi ≥ 0 i = 0, . . . , n

Lemma
P es factible si y solo si el valor óptimo de P 0 es 0 (cero).

Simona Bernardi Programación lineal 26 / 67


Programación lineal
Algoritmo sı́mplex

Factibilidad del problema y solución factible básica


Cuestiones 1 & 2

Enfoque inicializaciónSimplex
Si b ≥ 0
La solución que corresponde al vertex origen es factible
Devuelve la forma slack del problema P (cuadro inicial)
Sino crea un problema auxiliar P 0
Soluciona P 0 con el algoritmo sı́mplex (lı́neas 7–17)
Dependiendo del valor de la solución de P 0 decide si el problema
inicial P es factible . . .
Si x0 = 0 entonces P es factible y devuelve la forma slack final de P 0
borrando x0 y recuperando la función objetivo original de P
Sino el problema P no es factible

Simona Bernardi Programación lineal 27 / 67


Programación lineal
Algoritmo sı́mplex

Caso no acotado
Cuestión 3
La función hayPositivos(A,B,colP) determina si hay elementos
A[i][colP], i ∈ B positivos: si no hay entonces el problema no está
acotado
Ninguna restricción del problema limita la cantidad a incrementar
para la variable que entra en la base (colP ∈ N)
Ejemplo
x1 x2 x3 x4 b
P 0 : max x1 + x2 c1: -1 0 1 0 1
t.q. x1 ≥ −1 c2: 0 -1 0 1 2
x2 ≥ −2 z: 1 1 0 0 0
x1 , x2 ≥ 0
B = {3, 4}, N = {1, 2}

Simona Bernardi Programación lineal 28 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable entrante

Función eligePositivo(c,N)

La función elige la variable que


entra en la base B
¿Cuál?

Simona Bernardi Programación lineal 29 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable entrante

Función eligePositivo(c,N)

La función elige la variable que


entra en la base B
¿Cuál?
La variable con ı́ndice q ∈ N
que tiene un coeficiente
positivo en la función objetivo

Simona Bernardi Programación lineal 29 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable entrante

Función eligePositivo(c,N)

La función elige la variable que


entra en la base B
¿Cuál?
La variable con ı́ndice q ∈ N
que tiene un coeficiente
positivo en la función objetivo

¿Si hay varias posibilidades?

Simona Bernardi Programación lineal 29 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable entrante

Función eligePositivo(c,N)

La función elige la variable que


entra en la base B
¿Cuál?
La variable con ı́ndice q ∈ N
que tiene un coeficiente
positivo en la función objetivo

¿Si hay varias posibilidades?. . . hay diferentes criterios


Regla de Bland: la variable con el ı́ndice menor

Simona Bernardi Programación lineal 29 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable saliente

Función filaPivote(A,b,B,q)

La función elige la variable que


sale de la base B
¿Cuál?

Simona Bernardi Programación lineal 30 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable saliente

Función filaPivote(A,b,B,q)

La función elige la variable que


sale de la base B
¿Cuál?
Regla mı́nimo ratio: la variable
con ı́ndice p ∈ N tal que:

b[p]  b[i]
= min : i ∈ B, A[i][q] > 0
A[p][q] A[i][q]

Simona Bernardi Programación lineal 30 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable saliente

Función filaPivote(A,b,B,q)

La función elige la variable que


sale de la base B
¿Cuál?
Regla mı́nimo ratio: la variable
con ı́ndice p ∈ N tal que:

b[p]  b[i]
= min : i ∈ B, A[i][q] > 0
A[p][q] A[i][q]

¿Si hay varias posibilidades?

Simona Bernardi Programación lineal 30 / 67


Programación lineal
Algoritmo sı́mplex

Elección del pivote


Cuestión 4: variable saliente

Función filaPivote(A,b,B,q)

La función elige la variable que


sale de la base B
¿Cuál?
Regla mı́nimo ratio: la variable
con ı́ndice p ∈ N tal que:

b[p]  b[i]
= min : i ∈ B, A[i][q] > 0
A[p][q] A[i][q]

¿Si hay varias posibilidades?. . . hay diferentes criterios


Regla de Bland: la variable con el ı́ndice menor
Simona Bernardi Programación lineal 30 / 67
Programación lineal
Algoritmo sı́mplex

Caso de degeneración
El vértice B es degenerado
Es la intersección de más de n = 3 caras del
poliedro: 2 3 4 5
Si se elige uno de los siguientes conjuntos de
desigualdades
2 3 4 – 2 3 5 – 2 4 5 – 3 4 5
y se soluciona el sistema de 3 ecuaciones en 3
variables de obtiene la misma solución en todo
los casos
Fuente: S. Dasgupta et al. Algorithms

Simona Bernardi Programación lineal 31 / 67


Programación lineal
Algoritmo sı́mplex

Caso de degeneración
El vértice B es degenerado
Es la intersección de más de n = 3 caras del
poliedro: 2 3 4 5
Si se elige uno de los siguientes conjuntos de
desigualdades
2 3 4 – 2 3 5 – 2 4 5 – 3 4 5
y se soluciona el sistema de 3 ecuaciones en 3
variables de obtiene la misma solución en todo
los casos
Fuente: S. Dasgupta et al. Algorithms
Problema! El sı́mplex puede pasar en ciclo por la diferentes bases
que corresponden al mismo vértex
Es importante el criterio de elección del pivote
P.ej. la regla de Bland asegura la selección de un número finito de
pivotes
Simona Bernardi Programación lineal 31 / 67
Programación lineal
Algoritmo sı́mplex

Tiempo de ejecución del sı́mplex


Problema general Un vértice v es la intersección de n
hiperplanos
max cT x Cada vértice vecino u comparte con v
t.q. Ax ≤ b n − 1 hiperplanos
x≥0 v tiene como máximo n · m vecinos
(elegir un hiperplano a quitar y otro a
n variables, m desigualdades añadir)

Simona Bernardi Programación lineal 32 / 67


Programación lineal
Algoritmo sı́mplex

Tiempo de ejecución del sı́mplex


Problema general Un vértice v es la intersección de n
hiperplanos
max cT x Cada vértice vecino u comparte con v
t.q. Ax ≤ b n − 1 hiperplanos
x≥0 v tiene como máximo n · m vecinos
(elegir un hiperplano a quitar y otro a
n variables, m desigualdades añadir)
Tiempo de ejecución en cada iteración: O(nm)
¿Cuántas iteraciones puede haber?
n+m

Cota superior del número de vértices: n
Exponencial en n!
Sin embargo en la mayorı́a de las aplicaciones prácticas es
polinomial
Simona Bernardi Programación lineal 32 / 67
Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida
Mantener la dispersión

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida
Mantener la dispersión ⇒ estructuras de datos ad hoc

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida
Mantener la dispersión ⇒ estructuras de datos ad hoc
Caso de degeneración

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida
Mantener la dispersión ⇒ estructuras de datos ad hoc
Caso de degeneración
Estabilidad numérica

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Algoritmo sı́mplex

Observaciones
Problemas de implementación
No factibilidad ⇒ fase 1 del sı́mplex
Caso no acotados ⇒ regla bien definida
Mantener la dispersión ⇒ estructuras de datos ad hoc
Caso de degeneración
Estabilidad numérica

Buena práctica: no implementarlo!


Implementaciones disponibles en muchos entornos de programación
Hay muchas herramientas disponibles que pueden resolver problemas
con millones de variables
Hay lenguajes de modelado para la especificación de problemas LP

Simona Bernardi Programación lineal 33 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

La red de oleoductos de Arabia Saudita

Problema1 ¿Cuál es la máxima


velocidad a la que se puede
enviar el crudo desde los campos
petroleros a las terminales de los
puertos marı́timos?
⇒ Máximo flujo
Problema2 ¿Cuál es la forma
más barata de sabotear la red?
⇒ Mı́nimo corte

Fuente: https://www.eia.gov/beta/international/analysis.php?iso=SAU

Simona Bernardi Programación lineal 34 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Definición de flujo
La red es un grafo dirigido G = (V , E ) con dos nodos especiales
s, t ∈ V (fuente y destino)
Un flujo-(s, t) es una función f : E → R que satisface a la siguiente
restricción de conservación en cada nodo v ∈ V (excepto
posiblemente s y t):
X X
f (u → v ) = f (v → w )
u w

Simona Bernardi Programación lineal 35 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Definición de flujo
La red es un grafo dirigido G = (V , E ) con dos nodos especiales
s, t ∈ V (fuente y destino)
Un flujo-(s, t) es una función f : E → R que satisface a la siguiente
restricción de conservación en cada nodo v ∈ V (excepto
posiblemente s y t):
X X
f (u → v ) = f (v → w )
u w

El valor del flujo f es el flujo total de la red que sale de la fuente


s ∈ V: X X
|f | = f (s → w ) − f (u → s)
w u
Se puede demostrar que |f | es también igual al flujo total de la red
que entra en el nodo destino t
Simona Bernardi Programación lineal 35 / 67
Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Problema de flujo máximo


Sea c : E → R≥0 una función
que asigna capacidades no
negativas a cada arco e ∈ E
Un flujo f es factible si
0 ≤ f (e) ≤ c(e) para cada arco
e∈E
f satura e ⇔ f (e) = c(e) Flujo-(s, t) factible con valor |f | = 10
f evita e ⇔ f (e) = 0 Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

Simona Bernardi Programación lineal 36 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Problema de flujo máximo


Sea c : E → R≥0 una función
que asigna capacidades no
negativas a cada arco e ∈ E
Un flujo f es factible si
0 ≤ f (e) ≤ c(e) para cada arco
e∈E
f satura e ⇔ f (e) = c(e) Flujo-(s, t) factible con valor |f | = 10
f evita e ⇔ f (e) = 0 Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

Problema LP
max |f |
X X
t.q. f (u → v ) = f (v → w ), ∀v ∈ V \ {s, t}
u w
0 ≤ f (e) ≤ c(e), ∀e ∈ E

Simona Bernardi Programación lineal 36 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Definición de corte
Un corte-(s, t) es una partición de los nodos del grafo G en dos
subconjuntos S, T (S ∪ T = V , S ∩ T = ∅) tales que s ∈ S y t ∈ T
Sea c la función de capacidad de los arcos, la capacidad del corte, se
define como: XX
||S, T || = c(v → w )
v ∈S w ∈T

Simona Bernardi Programación lineal 37 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Definición de corte
Un corte-(s, t) es una partición de los nodos del grafo G en dos
subconjuntos S, T (S ∪ T = V , S ∩ T = ∅) tales que s ∈ S y t ∈ T
Sea c la función de capacidad de los arcos, la capacidad del corte, se
define como: XX
||S, T || = c(v → w )
v ∈S w ∈T

Intuitivamente, el corte mı́nimo


es la forma más barata de
interrumpir todo el flujo de s a t
Corte-(s, t) con capacidad ||S, T || = 15
Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/
Simona Bernardi Programación lineal 37 / 67
Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Relación entre flujos y cortes


Lemma
Sea f un flujo-(s, t) factible y (S, T ) un corte-(s, t), entonces el valor de f
es menor o igual a la capacidad de (S, T ). Además |f | = ||S, T || si y solo
si f satura cada arco de S a T y evita cada arco de T a S.

Simona Bernardi Programación lineal 38 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Relación entre flujos y cortes


Lemma
Sea f un flujo-(s, t) factible y (S, T ) un corte-(s, t), entonces el valor de f
es menor o igual a la capacidad de (S, T ). Además |f | = ||S, T || si y solo
si f satura cada arco de S a T y evita cada arco de T a S.

Teorema máximo flujo-mı́nimo corte [Ford-Fulkerson 1954]


En cada red de flujo G = (V , E ) con fuente s y destino t, el valor del
máximo flujo-(s, t) es igual a la capacidad del mı́nimo corte-(s, t).

Simona Bernardi Programación lineal 38 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Relación entre flujos y cortes


Lemma
Sea f un flujo-(s, t) factible y (S, T ) un corte-(s, t), entonces el valor de f
es menor o igual a la capacidad de (S, T ). Además |f | = ||S, T || si y solo
si f satura cada arco de S a T y evita cada arco de T a S.

Teorema máximo flujo-mı́nimo corte [Ford-Fulkerson 1954]


En cada red de flujo G = (V , E ) con fuente s y destino t, el valor del
máximo flujo-(s, t) es igual a la capacidad del mı́nimo corte-(s, t).

El algoritmo de Ford-Fulkerson se basa en:


1 Considerar el flujo-(s, t) factible f ≡ 0
2 Elegir cualquier camino apropiado de s a t e incrementar el flujo en los
arcos del camino cuanto más posible
3 Repetir el paso 2 hasta que no hay caminos apropiados
Simona Bernardi Programación lineal 38 / 67
Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Capacidad residual

Dada una red de flujo G = (V , E ) con capacidad c y un flujo-(s, t)


factible, la capacidad residual es una función cf : E → R≥0 ası́
definida:

c(u → v ) − f (u → v ) si u → v ∈ E

cf (u → v ) = f (v → u) si v → u ∈ E

0 de otra manera

La capacidad residual de un arco indica cuanto más flujo se puede


introducir en el arco
Es posible tener una capacidad residual cf (u → v ) > 0 aunque
u → v 6∈ E

Simona Bernardi Programación lineal 39 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Grafo residual

El grafo residual Gf = (V , Ef ) es el grafo asociado a la red de flujo


G = (V , E ) con capacidad c y flujo-(s, t) factible, donde Ef es el
conjunto de arcos cuya capacidad residual cf es positiva.

Flujo f en la red de flujo G (izda.) y su grafo residual Gf (dcha.)


Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

Simona Bernardi Programación lineal 40 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Incremento del flujo en un camino de s a t

Sea P un camino de s a t en el grafo residual Gf , la máxima


cantidad de flujo que se puede introducir en P es:

F = minu→v ∈P cf (u → v )

Se define un nuevo flujo f 0 : E → R en el grafo original G :



f (u → v ) + F
 si u → v ∈ P
0
f (u → v ) = f (u → v ) − F si v → u ∈ P

0 de otra manera

Simona Bernardi Programación lineal 41 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Incremento del flujo en un camino de s a t

Camino P con F = 5 en Gf (izda.) y el nuevo flujo f 0 en G (dcha.)


Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

El nuevo flujo f 0 es factible con respecto a las capacidades originales


c de G
|f 0 | = |f | + F ≥ |f | ⇒ f no es flujo máximo

Simona Bernardi Programación lineal 42 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Terminación del algoritmo

¿Qué pasa si el grafo residual Gf no incluye un camino P de s a t?


Sea S el conjunto de nodos de Gf que se pueden alcanzar de s y
T =V \S
Se puede demostrar que el flujo f satura cada arco de S a T y evita
cada arco de T a S
Por el lemma (transpa. 27): |f | = ||S, T ||

Simona Bernardi Programación lineal 43 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Eficiencia
En cada iteración se puede utilizar una búsqueda en profundidad o
amplitud para encontrar un camino de s a t
Complejidad en tiempo: O(|E |)

Simona Bernardi Programación lineal 44 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Eficiencia
En cada iteración se puede utilizar una búsqueda en profundidad o
amplitud para encontrar un camino de s a t
Complejidad en tiempo: O(|E |)
¿Cuántas iteraciones hay?
Asumimos todos los arcos con capacidad entera N
El algoritmo de Ford-Fulkerson termina después como mucho |f ∗ |
iteraciones, donde |f ∗ | es el flujo máximo
Complejidad en tiempo (caso peor): O(|E ||f ∗ |)

Simona Bernardi Programación lineal 44 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Eficiencia
En cada iteración se puede utilizar una búsqueda en profundidad o
amplitud para encontrar un camino de s a t
Complejidad en tiempo: O(|E |)
¿Cuántas iteraciones hay?
Asumimos todos los arcos con capacidad entera N
El algoritmo de Ford-Fulkerson termina después como mucho |f ∗ |
iteraciones, donde |f ∗ | es el flujo máximo
Complejidad en tiempo (caso peor): O(|E ||f ∗ |)

Exponencial en el tamaño del input


(número de bits necesario para describir
las capacidades en entrada)

Fuente: jeffe.cs.illinois.edu/teaching/

algorithms/book/

Simona Bernardi Programación lineal 44 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Eficiencia
En cada iteración se puede utilizar una búsqueda en profundidad o
amplitud para encontrar un camino de s a t
Complejidad en tiempo: O(|E |)
¿Cuántas iteraciones hay?
Asumimos todos los arcos con capacidad entera N
El algoritmo de Ford-Fulkerson termina después como mucho |f ∗ |
iteraciones, donde |f ∗ | es el flujo máximo
Complejidad en tiempo (caso peor): O(|E ||f ∗ |)

Exponencial en el tamaño del input


(número de bits necesario para describir
las capacidades en entrada)
¿Qué compleijdad tiene el algoritmo en
Fuente: jeffe.cs.illinois.edu/teaching/
el caso de capacidades racionales Q?
algorithms/book/
Igual que en el caso entero
Simona Bernardi Programación lineal 44 / 67
Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Sobre la terminación y convergencia al valor max

¿Qué pasa en el caso de


capacidades irracionales R \ Q?

Simona Bernardi Programación lineal 45 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Sobre la terminación y convergencia al valor max

¿Qué pasa en el caso de


capacidades irracionales R \ Q?
¡No está garantizada ni la
terminación ni la convergencia
al flujo máximo!
Ejemplo de Uri Zwick
Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

¿Es un problema únicamente teórico?

Simona Bernardi Programación lineal 45 / 67


Programación lineal
Aplicación: el problema de flujo máximo/mı́nimo corte

Sobre la terminación y convergencia al valor max

¿Qué pasa en el caso de


capacidades irracionales R \ Q?
¡No está garantizada ni la
terminación ni la convergencia
al flujo máximo!
Ejemplo de Uri Zwick
Fuente:jeffe.cs.illinois.edu/teaching/algorithms/book/

¿Es un problema únicamente teórico?


¡No! En práctica: una mala implementación del algoritmo puede
provocar los mismos problemas con capacidades no enteras debido a
errores de redondeo

Simona Bernardi Programación lineal 45 / 67


Programación lineal
El problema de emparejamiento bipartido

El problema de emparejamiento bipartido

Fuente: S. Dasgupta, et al. Algorithms

Objetivo del emparejamiento perfecto


¿Es posible elegir las parejas para que todos estén contentos?

El problema se puede reducir en un problema de máximo flujo . . .


Simona Bernardi Programación lineal 46 / 67
Programación lineal
El problema de emparejamiento bipartido

Reducción en un problema de máximo flujo

1 Crear un nuevo nodo fuente s y


conectarlo a todos los chicos
2 Crear un nuevo nodo destino t y
conectar todas las chicas a t
3 Asociar capacidad 1 a cada arco Fuente: S. Dasgupta, et al. Algorithms

Simona Bernardi Programación lineal 47 / 67


Programación lineal
El problema de emparejamiento bipartido

Reducción en un problema de máximo flujo

1 Crear un nuevo nodo fuente s y


conectarlo a todos los chicos
2 Crear un nuevo nodo destino t y
conectar todas las chicas a t
3 Asociar capacidad 1 a cada arco Fuente: S. Dasgupta, et al. Algorithms

Hay un emparejamiento perfecto ⇔ la red de flujo tiene un flujo con valor


igual al número de parejas

Simona Bernardi Programación lineal 47 / 67


Programación lineal
Dualidad

Dualidad

Problema de la fábrica de cerveza

max 12A + 20B


t.q. 4A + 12B ≤ 384 Solución óptima:
0,1A + 0,1B ≤ 4 (A = 12, B = 28)
14A + 8B ≤ 476 Valor max: 704
A, B ≥ 0

Multiplicamos la primera, segunda y tercera restricción por 1, 80 y 0


respectivamente . . .

Simona Bernardi Programación lineal 48 / 67


Programación lineal
Dualidad

Dualidad

Problema de la fábrica de cerveza

max 12A + 20B


t.q. 4A + 12B ≤ 384 Solución óptima:
0,1A + 0,1B ≤ 4 (A = 12, B = 28)
14A + 8B ≤ 476 Valor max: 704
A, B ≥ 0

Multiplicamos la primera, segunda y tercera restricción por 1, 80 y 0


respectivamente . . .
Obtenemos: 12A + 20B ≤ 704 ,

Simona Bernardi Programación lineal 48 / 67


Programación lineal
Dualidad

Dualidad
¿De dónde vienen los multiplicadores (1, 80, 0)?

Mult. Desigualdades
y1 4A + 12B ≤ 384 Sean yi ≥ 0 (preservamos las desigualdades ≤)
y2 0,1A + 0,1B ≤ 4 Después haber multiplicado y sumado . . .
y3 14A + 8B ≤ 476

(4y1 + 0,1y2 + 14y3 )A + (12y1 + 0,1y 2 + 8y3 )B ≤ 384y1 + 4y2 + 476y3

Queremos que la parte izquierda de la desigualdad sea parecida a la


función objetivo del problema inicial . . . 12A + 20B
Es decir: (4y1 + 0,1y2 + 14y3 ) ≥ 12 y (12y1 + 0,1y2 + 8y3 ) ≥ 20

Simona Bernardi Programación lineal 49 / 67


Programación lineal
Dualidad

Dualidad

Cota superior de la función objetivo:


12A + 20B ≤ 384y1 + 4y2 + 476y3
Si:

y1 , y2 , y3 ≥ 0
4y1 + 0,1y2 + 14y3 ≥ 12
12y1 + 0,1y2 + 8y3 ≥ 20

Para obtener una buena cota, tenemos que minimizarla


Se obtiene un nuevo problema!

Simona Bernardi Programación lineal 50 / 67


Programación lineal
Dualidad

Dualidad
Relación entre soluciones primal-dual
Problema dual

Cualquier solución factible del dual es


min 384y1 + 4y2 + 476y3 una cota superior del problema primal
Si encontramos una pareja de
t.q. 4y1 + 0,1y2 + 14y3 ≥ 12 soluciones factibles iguales, entonces
12y1 + 0,1y2 + 8y3 ≥ 20 son soluciones óptimas
y1 , y2 , y3 ≥0 Primal: (A, B) = (12, 28), sol.: 704
Dual: (y1 , y2 , y3 ) = (1, 80, 0), sol.: 704

Fuente: S. Dasgupta, et al. Algorithms


Simona Bernardi Programación lineal 51 / 67
Programación lineal
Dualidad

Dualidad
Primal en forma canónica

Para cada problema de programación lineal, existe un problema dual


que se obtiene aplicando un conjunto de reglas.
Si el primal se encuentra en forma canónica, la transformación es más
simple . . .

Problema primal Problema dual

max cT x min yT b
t.q. Ax ≤ b ⇐⇒ t.q. AT y ≥ c
x≥0 y≥0

Simona Bernardi Programación lineal 52 / 67


Programación lineal
Dualidad

Dualidad
Primal y dual en forma canónica

Podemos escribir el problema dual también en forma canónica como


el primal
La dualidad es una involución: el dual del dual es el problema primal!

Problema primal Problema dual

max cT x max −bT y


t.q. Ax ≤ b ⇐⇒ t.q. −AT y ≤ −c
x≥0 y≥0

Simona Bernardi Programación lineal 53 / 67


Programación lineal
Dualidad

Dualidad
Teorema de dualidad

Problema primal Problema dual

max cT x min yT b
t.q. Ax ≤ b ⇐⇒ t.q. AT y ≥ c
x≥0 y≥0

El problema primal tiene una solución óptima x ∗ si y solo si el problema


dual tiene una solución óptima y ∗ tal que:

c · x ∗ = y ∗T Ax ∗ = y ∗T · b.

Simona Bernardi Programación lineal 54 / 67


Programación lineal
Dualidad

Dualidad
Visualización del dual

Problema primal: problema del camino mı́nimo entre dos nodos S y T


Problema dual: es un problema de máximo
¿Cómo se interpreta?

Simona Bernardi Programación lineal 55 / 67


Programación lineal
Dualidad

Dualidad
Visualización del dual

Problema primal: problema del camino mı́nimo entre dos nodos S y T


Problema dual: es un problema de máximo
¿Cómo se interpreta?

Fuente: S. Dasgupta, et al. Algorithms

Simona Bernardi Programación lineal 55 / 67


Programación lineal
Dualidad

Dualidad
Visualización del dual

Problema primal: problema del camino mı́nimo entre dos nodos S y T


Problema dual: es un problema de máximo
¿Cómo se interpreta?

Las cuerdas que unen parejas de


nodos tiene una longitud dada

Fuente: S. Dasgupta, et al. Algorithms

Simona Bernardi Programación lineal 55 / 67


Programación lineal
Dualidad

Dualidad
Visualización del dual

Problema primal: problema del camino mı́nimo entre dos nodos S y T


Problema dual: es un problema de máximo
¿Cómo se interpreta?

Las cuerdas que unen parejas de


nodos tiene una longitud dada
Problema dual: estirar los nodos
S y T cuanto más posible, sin
romper las cuerdas que unen las
parejas de nodos
Fuente: S. Dasgupta, et al. Algorithms

Simona Bernardi Programación lineal 55 / 67


Programación lineal
Reducciones

Transformación de un problema en otro


P es reducible a Q si se puede utilizar un algoritmo eficiente para
resolver Q como sub-rutina de un algoritmo eficiente para resolver P

Fuente: S. Dasgupta et al. Algorithms, 2008

1 {P: encontrar el camino más largo en un DAG;


2 Q: encontrar el camino más corto en el DAG}
3 funcion caminoMasLargo(G: grafo) devuelve camino
4 principio
5 {Pre-procesado: negar todos los pesos de los arcos en G}
6 devuelve caminoMasCorto(G)
7 fin

Simona Bernardi Programación lineal 56 / 67


Programación lineal
Reducciones

Reducciones en problemas de optimización

Las reducciones se aplican a menudo a problemas de optimización


Un problema LP general tiene muchos grados de libertad:
Puede ser un problema de max o de min
Puede tener restricciones de igualdad o de desigualdad
Las variables a menudo tienen que ser no negativas

Todas las variantes pueden reducirse entre sı́

Simona Bernardi Programación lineal 57 / 67


Programación lineal
Reducciones

Variantes de problemas LP

Reducción de un problema max a un problema min (o viceversa)


Multiplicar la función objetivo por “−1”

Ejemplo: problema de la mochila 0-1


n
X n
X
max bi xi min − bi xi
i=1 i=1
Xn n
X
s.t. pi xi ≤ C s.t. pi xi ≤ C
i=1 i=1
xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n xi ∈ {0, 1}, bi , pi > 0, 1 ≤ i ≤ n
Aplicación de la técnica de ramificación y poda al problema min

Simona Bernardi Programación lineal 58 / 67


Programación lineal
Reducciones

Variantes de problemas LP
Reducción de una restricción de desigualdad a una de igualdad
Añadir una nueva variable slack s
n
X n
X
ai xi ≤bi ⇒ ai xi + s =bi
i=1 i=1
s≥0

Reducción de una restricción de igualdad a una de desigualdad


n
X n
X
ai xi =bi ⇒ ai xi + ≤bi
i=1 i=1
Xn
ai xi + ≥bi
i=1

Simona Bernardi Programación lineal 59 / 67


Programación lineal
Reducciones

Variantes de problemas LP
Reducción de una variable x sin restricciones de signo a dos variables
x + , x − no negativas
Añadir las dos variables x1 , x2 ≥ 0
Sustituir x por x1 − x2 (en las restricciones y función objetivo)
Reducción de un problema primal a un problema dual

Primal Dual Primal Dual


T min yT b
Pmax c x P
a x ≤ bi yi ≥ 0 xj ≥ 0 a y ≥ cj
Pj ij j Pi ij i
aij xj ≥ bi yi ≤ 0 xj ≤ 0 aij yi ≤ cj
Pj Pi
j aij xj = bi yi T 0 xj T 0 i aij yi = cj

Ejemplo
Problema de máximo flujo (primal) / problema de mı́nimo corte (dual)
Simona Bernardi Programación lineal 60 / 67
Programación lineal
Reducciones

Reducciones en problemas de optimización

P: problema de programación lineal entera (ILP)


Q: problema de programación lineal relajado

Fuente: S. Dasgupta et al. Algorithms, 2008

Algoritmo para P: técnica de ramificación y poda


Algoritmo para Q: algoritmo sı́mplex

Simona Bernardi Programación lineal 61 / 67


Programación lineal
Reducciones

Problemas ILP

Ejemplo
Máquina Espacio Precio Beneficio (por unidad y dı́a)
prensa 15m2 8.000e 100e
torno 30m 2 4.000e 150e
Espacio disponible: 200m2 , Presupuesto: 40.000e

Simona Bernardi Programación lineal 62 / 67


Programación lineal
Reducciones

Problemas ILP

Ejemplo
Máquina Espacio Precio Beneficio (por unidad y dı́a)
prensa 15m2 8.000e 100e
torno 30m 2 4.000e 150e
Espacio disponible: 200m2 , Presupuesto: 40.000e

P : max 100x1 + 150x2


t.q. 15x1 + 30x2 ≤ 200 x1 : número de prensas
8000x1 + 4000x2 ≤ 40000 x2 : número de tornos
x1 , x2 ≥ 0 enteros

Simona Bernardi Programación lineal 62 / 67


Programación lineal
Reducciones

Reducción del problema a un problema LP

P : max 100x1 + 150x2


t.q. 15x1 + 30x2 ≤ 200 x1 : número de prensas
8000x1 + 4000x2 ≤ 40000 x2 : número de tornos
x1 , x2 ≥ 0 enteros

Q: problema LP obtenido de P quitando las restricciones de


integridad, (i.e., x1 , x2 ∈ R+
0)

Simona Bernardi Programación lineal 63 / 67


Programación lineal
Reducciones

Reducción del problema a un problema LP

P : max 100x1 + 150x2


t.q. 15x1 + 30x2 ≤ 200 x1 : número de prensas
8000x1 + 4000x2 ≤ 40000 x2 : número de tornos
x1 , x2 ≥ 0 enteros

Q: problema LP obtenido de P quitando las restricciones de


integridad, (i.e., x1 , x2 ∈ R+
0)

Cota superior: valor de la solución


óptima del problema Q
Cota inferior: valor de la solución
óptima redondeada por defecto (es
solución factible de P)
Simona Bernardi Programación lineal 63 / 67
Programación lineal
Reducciones

Técnica de ramificación y poda

Criterio de ramificación
Dado el nodo X del árbol y la solución óptima asociada al problema
QX , elegir la variable con la mayor parte decimal
x1 = 2, 22 y x2 = 5, 56
Crear dos nuevas restricciones que definen una partición en el
conjunto de soluciones de Q
Problema P2 : P+ la restricción x2 ≤ 5 asociado al hijo izquierdo de X
Problema P3 : P+ la restricción x2 ≥ 6 asociado al hijo derecho de X
Resolver los problemas relajados correspondientes: Q2 , Q3

Simona Bernardi Programación lineal 64 / 67


Programación lineal
Reducciones

Técnica de ramificación y poda


Los valores de las soluciones óptimas de Q2 y Q3 son las cotas
superiores asociadas a los nodos 2 y 3

No hay soluciones enteras óptimas


¿Cuál es el siguiente nodo en expansión?

Simona Bernardi Programación lineal 65 / 67


Programación lineal
Reducciones

Técnica de ramificación y poda


Los valores de las soluciones óptimas de Q2 y Q3 son las cotas
superiores asociadas a los nodos 2 y 3

No hay soluciones enteras óptimas


¿Cuál es el siguiente nodo en expansión?
El nodo que tiene el valor más alto como cota superior
Simona Bernardi Programación lineal 65 / 67
Programación lineal
Reducciones

Técnica de ramificación y poda

Simona Bernardi Programación lineal 66 / 67


Programación lineal
Referencias

Referencias

T. H. Cormen et al. Introduction to Algorithms (3rd edition), the


MIT Press, 2009 – Capı́tulo 29
S. Dasgupta et al., Algorithms, McGraw-Hill, 2008 – Capı́tulo 7
J. Erickson, Algorithms, libro en lı́nea, 2019:
http://jeffe.cs.illinois.edu/teaching/algorithms/ – Capı́tulos 10, H
Transparencias de J. Julvez:
http://webdiis.unizar.es/asignaturas/AB/material/todo.pdf – pp. 476–582
Transparencias de R. Sedgewick, K. Wayne (Princeton University):
https://algs4.cs.princeton.edu/lectures/99LinearProgramming.pdf

Simona Bernardi Programación lineal 67 / 67

También podría gustarte