Está en la página 1de 11

Búsqueda exhaustiva

Programación - Algoritmos y Estructuras de Datos

Sistemas Bioinformáticos - Máster Universitario en Bioinformática - Curso 2019/20


Búsqueda exhaustiva
La búsqueda exhaustiva es una técnica general de resolución de problemas que evalúa todas
las soluciones candidatas a un problema.

Aunque encuentra soluciones correctas, el hecho de realizar una búsqueda sistemática


conlleva que suela ser ine ciente.

Existen técnicas que mejoran el rendimiento de la búsqueda exhaustiva como Backtracking y


Rami cación y poda.

Caso de estudio: sea un conjunto de números, obtener un subconjunto cuya suma sea
exactamente un valor. Por ejemplo, sea (13, 11, 7) y el valor a obtener 20, la solución es el
subconjunto que suma ese valor es (13, 7).

2/11
Generación de las soluciones candidatas
El módulo itertools ofrece funciones para generar permutaciones y combinaciones de
elementos:

· combinations(elementos, r): combinaciones sin repetición de tamaño r. No importa el


orden.
· combinations_with_replacement: combinaciones con repetición. No importa el orden.

· product(elementos, r): variaciones con repetición de tamaño r.

· permutations(elementos): todas las formas de ordenar elementos

combinations([0, 1, 2, 3], 3) # (0, 1, 2) (0, 1, 3) (0, 2, 3) (1, 2, 3)


product(['A', 'B'], 2) # (A, A) (A, B) (B, A) (B, B)
permutations([0, 1, 2]) # (0, 1, 2) (0, 2, 1) (1, 0, 2) (1, 2, 0) (2, 0, 1) (2, 1, 0)

3/11
Generación de las soluciones candidatas
Cálculo del conjunto potencia (todos los subconjuntos):

def powerset(elementos):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(elementos)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

Ejercicio: generar todas las combinaciones de los números del 0 al 9, puestos de 2 en 2.

Ejercicio: Calcula todas las secuencias de ADN de tamaño 4.

4/11
Resolución del problema
Analizamos cómo aplicar la búsqueda exhaustiva al problema de la suma de los números
haciendo uso de de las funciones que proporciona el módulo itertools y la función powerset.

def suma_numeros(numeros, suma_objetivo):


solucion = []

for candidata in powerset(numeros):


suma = 0
for numero in candidata: # calcula la suma de la solución candidata
suma = suma + numero
if suma == suma_objetivo:
solucion = candidata
break

return solucion

5/11
Resolución del problema
Probamos la función suma_numeros con los datos del caso de estudio:

solucion1 = suma_numeros(numeros = [13, 11, 7], suma_objetivo = 20)


print(solucion1)

Ejercicio: adapta la función que resuelve el problema anterior para que retorne todas las
soluciones que cumplan la condición.

Para probar el ejercicio utilizaremos los siguientes datos:

numeros = [13, 11, 7, 18]


suma_objetivo = 18

El problema tiene dos soluciones: (11, 7) y (18).

6/11
Suma números - optimización
La técnica de búsqueda exhaustiva también se aplica a la resolución de problemas de
optimización: maximizar un bene cio o reducir un coste.

En estos problemas se evalúan todas las soluciones candidatas y se retorna la mejor, de


acuerdo al criterio establecido en el problema.

Volvemos a plantear el problema suma de números como un problema de optimización del


siguiente modo:

· Sea un conjunto de números, obtener un subconjunto cuya suma sea exactamente un valor
y tenga el menor tamaño (criterio).
· Por ejemplo, sea el conjunto de números (13, 11, 7, 18) y la suma a obtener 18, los
subconjuntos que suman ese valor son (11, 7) y (18).
· La solución al problema sería (18), puesto que tiene menor tamaño.

7/11
Resolución del problema de optimización
A continuación analizamos cómo aplicar la búsqueda exhaustiva a un problema de
optimización.

La función necesita dos variables:

· soa: solución óptima actual. Representa la mejor solución encontrada.

- Inicialmente toma el valor de la lista vacía (todavía no hay solución).


- Esta variable reemplaza a solucion.

· voa: valor de la solución óptima actual. Representa el valor de soa de acuerdo al criterio
jado en el problema. En este problema es el tamaño del conjunto de números de soa.

- Inicialmente toma como valor una cota, superior (problemas de minimización) o inferior
(problemas de maximización).
- El valor inicial de voa es inicialmente peor que la valoración de cualquier solución
candidata.

8/11
Resolución del problema de optimización
def suma_numeros_optimizacion(numeros, suma_objetivo):
soa = []
voa = 1 + len(numeros) # Todas las soluciones candidatas tendrán un tamaño menor
for candidata in powerset(numeros):
suma = 0
for numero in candidata:
suma = suma + numero
if suma == suma_objetivo and len(candidata) < voa: # ¿es solución y es mejor que soa?
soa = candidata
voa = len(candidata)

return soa

Prueba:

solucion = suma_numeros_optimizacion([13, 11, 7, 18], 18)

9/11
Resolución del problema de optimización
¿Qué sucede si llamamos a la función buscando la suma objetivo de 19?

Ejercicio: cambia el criterio de optimización con el n de que se maximice el tamaño de la


solución, esto es, una solución es mejor que otra si incluye más números.

10/11
Conclusiones
El esquema algorítmico búsqueda exhaustiva está basado en analizar todas las soluciones
candidatas a un problema.

Utilizando esta técnica podemos encontrar:

· Una solución al problema (primera aproximación a la suma de números).


· Todas las soluciones al problema (ejercicio de clase).

· Mejor solución (optimización).

El principal inconveniente de la búsqueda exhaustiva es que resulta ine ciente cuando el


tamaño del problema es grande.

Existen variaciones más inteligentes del esquema, como, por ejemplo, backtracking, capaces de
eliminar conjuntos de soluciones candidatas que no van a ser soluciones al problema.

El esquema algorítmico avance rápido utiliza un enfoque opuesto. Se sacri ca el análisis


exhaustivo de todas las posibles soluciones con el n de encontrar una solución rápida.

11/11

También podría gustarte