19.05.2013 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!