Ejercicio de evaluación (ITIS). Ramificación y poda
Ejercicio de evaluación (ITIS). Ramificación y poda
Ejercicio de evaluación (ITIS). Ramificación y poda
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Ejercicio</strong> <strong>de</strong> <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong><br />
Recubrimiento <strong>de</strong> los vértices <strong>de</strong> un grafo<br />
Un recubrimiento <strong>de</strong> los vértices <strong>de</strong> un grafo no dirigido G = 〈V , A〉 es un<br />
subconjunto <strong>de</strong> vértices R ⊆ V cuyos elementos son adyacentes a todos<br />
los <strong>de</strong>más vértices <strong>de</strong>l grafo: Por cada vértice v <strong>de</strong>l grafo, existe una arista<br />
en A que lo une con algún vértice <strong>de</strong> R, o bien v ∈ R.<br />
Diseña un algoritmo <strong>de</strong> ramificación y <strong>poda</strong> que obtenga un recubrimiento<br />
<strong>de</strong> vértices <strong>de</strong> tamaño mínimo <strong>de</strong> un grafo. Detalla lo siguiente:<br />
1. El árbol <strong>de</strong> búsqueda: significado <strong>de</strong> las aristas, los niveles y el<br />
contenido <strong>de</strong> cada nodo.<br />
2. El pseudocódigo <strong>de</strong>l algoritmo.<br />
3. La función o funciones <strong>de</strong> cálculo <strong>de</strong> cotas.<br />
Yolanda García, Jesús Correas (DSIC - UCM) 1 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong><br />
Como <strong>de</strong>bemos proporcionar un subconjunto <strong>de</strong> los vértices, po<strong>de</strong>mos<br />
utilizar una tupla <strong>de</strong> valores booleanos 〈x1, . . . , xn〉, don<strong>de</strong> xi tiene<br />
valor cierto si el vértice i pertenece al conjunto, o falso en caso<br />
contrario.<br />
El grafo pue<strong>de</strong> venir representado mediante su matriz <strong>de</strong> adyacencia,<br />
ya que <strong>de</strong>bemos recorrer los vértices uno por uno.<br />
Cada nivel <strong>de</strong>l árbol correspon<strong>de</strong> a un vértice <strong>de</strong>l grafo.<br />
Cada nodo <strong>de</strong>l árbol tiene dos <strong>de</strong>scendientes.<br />
Las soluciones están en el nivel N, número <strong>de</strong> vértices <strong>de</strong>l grafo<br />
(podrían estar antes <strong>de</strong>l nivel N si <strong>de</strong>terminamos que todos los<br />
vértices ya están recubiertos).<br />
Restricciones explícitas: xi ∈ {0, 1}<br />
Restricciones implícitas: no tiene<br />
La solución <strong>de</strong>be cumplir que todos los vértices <strong>de</strong>l grafo son<br />
seleccionados o adyacentes a alguno <strong>de</strong> los vértices seleccionados.<br />
Yolanda García, Jesús Correas (DSIC - UCM) 2 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong><br />
Cada nodo <strong>de</strong>l árbol tiene la siguiente estructura:<br />
Solución parcial (sol[1..N])<br />
etapa<br />
número <strong>de</strong> vértices <strong>de</strong> la solución (num)<br />
número <strong>de</strong> vértices pendientes <strong>de</strong> recubrir (vPendientes)<br />
vértices recubiertos (vRecubiertos[1..N])<br />
cota inferior (cinf)<br />
cota superior (csup)<br />
Con la forma <strong>de</strong>l árbol <strong>de</strong>scrita, pue<strong>de</strong>n existir nodos intermedios <strong>de</strong>l<br />
árbol <strong>de</strong>s<strong>de</strong> los que no se pueda obtener ninguna solución.<br />
Yolanda García, Jesús Correas (DSIC - UCM) 3 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong><br />
Sin embargo, si po<strong>de</strong>mos <strong>de</strong>terminar que <strong>de</strong>s<strong>de</strong> un nodo <strong>de</strong>l árbol <strong>de</strong><br />
expansión no se llega a ninguna solución, podríamos evitar la<br />
generación <strong>de</strong> estos nodos.<br />
Si tenemos una solución parcial factible (que permite llegar a un<br />
recubrimiento <strong>de</strong> los vértices <strong>de</strong>l grafo) hasta la etapa k, se pue<strong>de</strong>n<br />
tomar dos <strong>de</strong>cisiones posibles sobre el vértice k+1:<br />
a) Si <strong>de</strong>cidimos incluir el vértice k+1 en el conjunto, la solución parcial<br />
seguirá siendo factible;<br />
b) Si <strong>de</strong>cidimos no incluirlo, la solución pue<strong>de</strong> <strong>de</strong>jar <strong>de</strong> ser factible, si<br />
algún vértice queda no recubierto por ningún otro vértice que se pueda<br />
seleccionar en alguna etapa posterior a k+1<br />
La comprobación <strong>de</strong> factibilidad se pue<strong>de</strong> realizar con un algoritmo<br />
con coste cuadrático en el caso peor. En caso <strong>de</strong> resultar no factible,<br />
no se genera el nodo correspondiente en el árbol: se pue<strong>de</strong> utilizar<br />
un esquema <strong>de</strong> <strong>poda</strong> basado en dos cotas.<br />
Si no se hace esta comprobación <strong>de</strong> factibilidad, entonces<br />
<strong>de</strong>berá utilizarse un esquema <strong>de</strong> <strong>poda</strong> basado en una sola cota.<br />
Yolanda García, Jesús Correas (DSIC - UCM) 4 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc recub-vertices(D[1..n,1..n],mejorSol[1..n], Cota)<br />
Cota ← ∞ ; nodoRaiz(raiz,D) ; introducir(Lnv, raiz)<br />
mientras not(vacia(Lnv)) hacer<br />
sacar(Lnv,x)<br />
si x.cinf ≤ Cota entonces<br />
generarHijos(x, hijos, numhijos, calles)<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta numhijos hacer<br />
si (hijos[i].cinf ≤ Cota) entonces<br />
si hijos[i].vPendientes = 0 entonces<br />
mejorSol ← hijos[i].sol ; Cota ← hijos[i].num<br />
si no si hijos[i].etapa < N entonces<br />
Cota ← min(Cota,hijos[i].csup) ; introducir(Lnv,hijos[i])<br />
fin si<br />
fin si<br />
fin <strong>de</strong>s<strong>de</strong><br />
fin si<br />
fin mientras<br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 5 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc generarHijos(nodo, hijos[1..2], numhijos, D[1..N,1..N])<br />
newEtapa ← nodo.etapa +1<br />
// primer caso: se elige el vértice newEtapa<br />
crear hijos[1] ; hijos[1].etapa ← newEtapa ; hijos[1].sol ← nodo.sol<br />
hijos[1].sol[newEtapa] ← cierto ; hijos[1].num ← nodo.num + 1<br />
hijos[1].vPendientes ← nodo.vPendientes ; hijos[1].vRecubiertos ← nodo.vRecubiertos<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta N hacer<br />
si D[newEtapa,i] ∨ i = newEtapa entonces<br />
si ¬hijos[1].vRecubiertos[i] entonces hijos[1].vPendientes ← hijos[1].vPendientes-1<br />
hijos[1].vRecubiertos[i] ← cierto<br />
fin si<br />
fin <strong>de</strong>s<strong>de</strong><br />
hijos[1].cinf ← calcCinf(hijos[1],D) ; hijos[1].csup ← calcCsup(hijos[1],D)<br />
// segundo caso: no se elige el vértice newEtapa<br />
si factible(nodo,D,newEtapa) entonces<br />
crear hijos[2] ; numHijos ← 2 ; hijos[2].etapa ← newEtapa ; hijos[2].sol ← nodo.sol<br />
hijos[2].num ← nodo.num ; hijos[2].vPendientes ← nodo.vPendientes<br />
hijos[2].cinf ← calcCinf(hijos[2],D) ; hijos[2].csup ← calcCsup(hijos[2],D)<br />
si no<br />
numHijos ← 1<br />
fin si<br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 6 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
fun factible(padre, D[1..N,1..N], newEtapa)<br />
// Comprueba si no eligiendo el vértice newEtapa la solución<br />
// es factible (se pue<strong>de</strong> llegar al recubrimiento <strong>de</strong> todos los vértices)<br />
esFactible ← cierto ; i ← 1<br />
mientras i ≤ newEtapa ∧ esFactible hacer<br />
// en el bucle externo se buscan los vértices conectados con newEtapa<br />
// (incluyendo el propio vértice newEtapa) que no se han seleccionado<br />
si (D[newEtapa,i] ∧¬padre.sol[i]) ∨ newEtapa = i entonces<br />
j ← 1<br />
// Se comprueba si el vértice i está cubierto por algún otro vértice seleccionado<br />
mientras j ≤ newEtapa-1 ∧¬(D[i,j] ∧ padre.sol[j]) hacer j ← j+1<br />
// Si el vértice i no está cubierto por ningún vértice seleccionado,<br />
// se comprueba si se podría cubrir por algún otro vértice no consi<strong>de</strong>rado todavía<br />
si j = newEtapa entonces<br />
mientras j ≤ N ∧¬D[i,j] hacer j ← j+1<br />
// Si no se pue<strong>de</strong> cubrir por ningún otro vértice, entonces no es factible<br />
si j > N entonces esFactible ← falso<br />
fin si<br />
fin si<br />
i ← i + 1<br />
fin mientras<br />
<strong>de</strong>volver esFactible<br />
fin fun<br />
Yolanda García, Jesús Correas (DSIC - UCM) 7 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc NodoRaiz(raiz,D[1..n,1..n])<br />
crearNodo(raiz)<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta n hacer<br />
raiz.sol[i] ← falso ; raiz.vRecubiertos[i] ← falso<br />
fin <strong>de</strong>s<strong>de</strong><br />
raiz.etapa ← 0<br />
raiz.num ← 0<br />
raiz.cinf ← calcCinf(raiz, D)<br />
raiz.csup ← calcCsup(raiz, D)<br />
raiz.vPendientes ← n // Inicialmente ningún vértice está recubierto<br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 8 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
Como cota inferior, se va a consi<strong>de</strong>rar la suma <strong>de</strong>:<br />
◮ los vértices seleccionados hasta el momento<br />
◮ más el número <strong>de</strong> vértices no cubiertos dividido por el grado máximo<br />
<strong>de</strong> los vértices no consi<strong>de</strong>rados todavía: La suposición optimista es que,<br />
<strong>de</strong> los nodos pendientes, no van a existir dos nodos que recubran los<br />
mismos vértices, y todos los nodos tienen el mismo grado máximo.<br />
Como cota superior, se pue<strong>de</strong> consi<strong>de</strong>rar la suma <strong>de</strong>:<br />
◮ los vértices seleccionados hasta el momento<br />
◮ más el número <strong>de</strong> vértices pendientes (suponemos que todos los<br />
vértices que quedan son elegidos)<br />
Yolanda García, Jesús Correas (DSIC - UCM) 9 / 18
Solución ej. <strong>evaluación</strong> (<strong>ITIS</strong>). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
fun calcCinf(nodo, D[1..N,1..N])<br />
gradoMax ← 0<br />
<strong>de</strong>s<strong>de</strong> i ← nodo.etapa+1 hasta N hacer<br />
grado ← 0<br />
<strong>de</strong>s<strong>de</strong> j ← 1 hasta N hacer<br />
si ¬nodo.vRecubiertos[j] ∧ D[i,j] entonces grado ← grado + 1<br />
fin <strong>de</strong>s<strong>de</strong><br />
si grado > gradoMax entonces gradoMax ← grado<br />
fin <strong>de</strong>s<strong>de</strong><br />
<strong>de</strong>volver nodo.num + nodo.numPendientes / (gradoMax + 1)<br />
// Se consi<strong>de</strong>ran los vértices que pue<strong>de</strong>n recubrir tantos vértices distintos<br />
// como indica el grado máximo<br />
fin fun<br />
fun calcCsup(nodo, D[1..N,1..N])<br />
<strong>de</strong>volver nodo.num + (N - nodo.etapa)<br />
fin fun<br />
Yolanda García, Jesús Correas (DSIC - UCM) 10 / 18
<strong>Ejercicio</strong> <strong>de</strong> <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y Poda<br />
VERTEX-COVER<br />
En un grafo no dirigido G = 〈V , A〉, un recubrimiento <strong>de</strong> vértices<br />
(vertex-cover) es un subconjunto <strong>de</strong> vértices V ′ ⊆ V tal que, para todas<br />
las aristas (u, v) ∈ A, entonces u ∈ V ′ o bien v ∈ V ′ (o ambos).<br />
Diseña un algoritmo <strong>de</strong> ramificación y <strong>poda</strong> que proporcione el<br />
recubrimiento <strong>de</strong> vértices (vertex-cover) <strong>de</strong> tamaño mínimo. Detalla lo<br />
siguiente:<br />
1. El árbol <strong>de</strong> búsqueda: significado <strong>de</strong> las aristas, los niveles y el<br />
contenido <strong>de</strong> cada nodo.<br />
2. El pseudocódigo <strong>de</strong>l algoritmo.<br />
3. La función o funciones <strong>de</strong> cálculo <strong>de</strong> cotas.<br />
Yolanda García, Jesús Correas (DSIC - UCM) 11 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong><br />
El grafo <strong>de</strong> entrada se pue<strong>de</strong> representar mediante una matriz <strong>de</strong><br />
adyacencia booleana.<br />
Como el resultado <strong>de</strong>l algoritmo consiste en un subconjunto <strong>de</strong> los<br />
vértices <strong>de</strong>l grafo, la solución pue<strong>de</strong> estar formada por un vector<br />
booleano <strong>de</strong> n elementos que contiene cierto si el vértice pertenece al<br />
conjunto.<br />
El árbol tiene grado 2, y cada una <strong>de</strong> las aristas correspon<strong>de</strong> a si se<br />
elige o no el vértice correspondiente a ese nivel.<br />
El nodo <strong>de</strong>l árbol <strong>de</strong> búsqueda tiene los siguientes atributos:<br />
Solución actual (sol[1..n])<br />
Núm. vértices seleccionados en la solución actual (num)<br />
Núm. aristas pendientes <strong>de</strong> cubrir (numPendientes)<br />
etapa<br />
cota inferior (cinf)<br />
cota superior (csup)<br />
Yolanda García, Jesús Correas (DSIC - UCM) 12 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc vertex-cover(D[1..n,1..n],mejorSol[1..n], Cota)<br />
Cota ← ∞ ; nodoRaiz(raiz,D) ; introducir(Lnv, raiz)<br />
mientras not(vacia(Lnv)) hacer<br />
sacar(Lnv,x)<br />
si x.cinf ≤ Cota entonces<br />
generarHijos(x, hijos, numhijos, D)<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta numhijos hacer<br />
si (hijos[i].cinf ≤ Cota) entonces<br />
si hijos[i].numPendientes = 0 entonces<br />
mejorSol ← hijos[i].sol ; Cota ← hijos[i].num<br />
si no si hijos[i].etapa < N entonces<br />
Cota ← min(Cota,hijos[i].csup) ; introducir(Lnv,hijos[i])<br />
fin si<br />
fin si<br />
fin <strong>de</strong>s<strong>de</strong><br />
fin si<br />
fin mientras<br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 13 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc generarHijos(nodo, hijos[1..2], numhijos, D[1..n,1..n])<br />
newEtapa ← nodo.etapa +1<br />
// primer caso: se elige el vértice newEtapa<br />
crear hijos[1]<br />
hijos[1].etapa ← newEtapa ; hijos[1].sol ← nodo.sol<br />
hijos[1].sol[newEtapa] ← cierto<br />
hijos[1].num ← nodo.num + 1<br />
hijos[1].numPendientes ← numAristasPtes(hijos[1],D)<br />
hijos[1].cinf ← calcCinf(hijos[1],D)<br />
hijos[1].csup ← calcCsup(hijos[1],D)<br />
// primer caso: no se elige el vértice<br />
si factible(nodo,D) entonces<br />
crear hijos[2]<br />
numHijos ← 2<br />
hijos[2].etapa ← newEtapa ; hijos[2].sol ← nodo.sol<br />
hijos[2].num ← nodo.num<br />
hijos[2].numPendientes ← nodo.numPendientes<br />
hijos[2].cinf ← calcCinf(hijos[2],D)<br />
hijos[2].csup ← calcCsup(hijos[2],D)<br />
si no<br />
numHijos ← 1<br />
fin si<br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 14 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
fun numAristasPtes(nodo,D[1..n,1..n])<br />
// calcula el número <strong>de</strong> aristas pendientes <strong>de</strong> cubrir<br />
numAristas ← 0<br />
<strong>de</strong>s<strong>de</strong> j ← 1 hasta n hacer<br />
si ¬nodo.sol[j] ∧ D[j,nodo.etapa] entonces<br />
numAristas ← numAristas + 1<br />
fin si<br />
fin <strong>de</strong>s<strong>de</strong><br />
<strong>de</strong>volver nodo.numPendientes - numAristas<br />
fin fun<br />
fun factible(nodo, D[1..n,1..n])<br />
// Comprueba si no eligiendo el vértice nodo.etapa+1 la solución<br />
// es factible (se pue<strong>de</strong> llegar al recubrimiento <strong>de</strong> todas las aristas)<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta nodo.etapa hacer<br />
si ¬nodo.sol[i] ∧ D[i,nodo.etapa+1] entonces <strong>de</strong>volver falso<br />
fin <strong>de</strong>s<strong>de</strong><br />
<strong>de</strong>volver cierto<br />
fin fun<br />
Yolanda García, Jesús Correas (DSIC - UCM) 15 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
proc NodoRaiz(raiz,D[1..n,1..n])<br />
crearNodo(raiz)<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta n hacer<br />
raiz.sol[i] ← falso<br />
fin <strong>de</strong>s<strong>de</strong><br />
raiz.etapa ← 0<br />
raiz.num ← 0<br />
raiz.cinf ← calcCinf(raiz, D)<br />
raiz.csup ← calcCsup(raiz, D)<br />
raiz.numPendientes ← 0<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta n hacer<br />
<strong>de</strong>s<strong>de</strong> j ← i+1 hasta n hacer<br />
si D[i,j] entonces raiz.numPendientes ← raiz.numPendientes + 1<br />
fin <strong>de</strong>s<strong>de</strong><br />
fin <strong>de</strong>s<strong>de</strong><br />
fin proc<br />
Yolanda García, Jesús Correas (DSIC - UCM) 16 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
Se pue<strong>de</strong>n utilizar el esquema <strong>de</strong> <strong>poda</strong> basado en dos cotas porque,<br />
según está <strong>de</strong>finido el algoritmo, no pue<strong>de</strong>n existir hojas que no sean<br />
solución:<br />
◮ La función factible garantiza que si no se selecciona un nodo, no<br />
quedan aristas que ya no se podrán recubrir con ningún otro nodo;<br />
◮ Por otra parte, si una solución parcial es factible, existe al menos una<br />
solución posible (por ejemplo, seleccionando todos los vértices<br />
pendientes <strong>de</strong> consi<strong>de</strong>rar).<br />
Como cota inferior, se va a consi<strong>de</strong>rar la suma <strong>de</strong>:<br />
◮ los vértices seleccionados hasta el momento<br />
◮ más el número <strong>de</strong> aristas no cubiertas dividido por el grado máximo <strong>de</strong><br />
los vértices pendientes: La suposición optimista es que, <strong>de</strong> los vértices<br />
pendientes, no van a existir dos vértices que recubran la misma arista.<br />
Como cota superior, se pue<strong>de</strong> consi<strong>de</strong>rar la suma <strong>de</strong>:<br />
◮ los vértices seleccionados hasta el momento<br />
◮ más el número <strong>de</strong> vértices pendientes (suponemos que todos los<br />
vértices que quedan son elegidos)<br />
Yolanda García, Jesús Correas (DSIC - UCM) 17 / 18
Solución ej. <strong>evaluación</strong> (ITIG). <strong>Ramificación</strong> y <strong>poda</strong> (cont.)<br />
fun calcCinf(nodo, D[1..n,1..n])<br />
maxGrado ← 0<br />
<strong>de</strong>s<strong>de</strong> i ← 1 hasta n hacer<br />
si ¬nodo.sol[i] entonces<br />
grado ← 0<br />
<strong>de</strong>s<strong>de</strong> j ← i+1 hasta n hacer<br />
si ¬nodo.sol[j] ∧ D[i,j] entonces grado ← grado + 1<br />
fin <strong>de</strong>s<strong>de</strong><br />
si grado > maxGrado entonces maxGrado ← grado<br />
fin si<br />
fin <strong>de</strong>s<strong>de</strong><br />
<strong>de</strong>volver nodo.num + ⌊ nodo.numPendientes / maxGrado ⌋<br />
fin fun<br />
fun calcCsup(nodo, D[1..n,1..n])<br />
<strong>de</strong>volver nodo.num + (n - nodo.etapa)<br />
fin fun<br />
Yolanda García, Jesús Correas (DSIC - UCM) 18 / 18