

def cerca_amplada(estat_inicial):
"""Búsqueda en anchura en un problema."""
frontera = collections.deque([estat_inicial])
visitats = set()
while frontera:
estat = frontera.popleft()
if estat in visitats:
continue
visitats.add(estat)
if es_solucio(estat):
return estat
for succesor in succesors(estat):
if succesor not in visitats:
frontera.append(succesor)
(0, 0) · Estado objetivo: (2, *) o (*, 2).[(0,0)].(0,0): [(3,0), (0,4)].(3,0): [(0,4), (3,4), (0,3)].(0,4): [(3,4), (0,3), (3,4), (3,1)].(3,4) se descartará si ya se ha visitado.| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | Sí | Si el espacio de búsqueda es finito, se encontrará una solución. |
| Optimalidad | Sí | Si todas las acciones tienen el mismo coste, la primera solución es óptima. |
| Complejidad temporal | ||
| Complejidad espacial |

def cerca_profunditat(estat_inicial):
frontera = [(estat_inicial, (estat_inicial,))]
while frontera:
estat, cami = frontera.pop()
if es_solucio(estat):
return estat
for succesor in succesors(estat):
if succesor not in cami:
frontera.append((succesor, cami + (succesor,)))
return None
(0, 0) · Estado objetivo: (2, *) o (*, 2).[(0,0)].(3,0) y (0,4), se extrae (0,4) porque la pila es LIFO.| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | No | Puede no encontrar una solución si hay ramas infinitas. |
| Optimalidad | No | La primera solución encontrada no tiene por qué ser óptima. |
| Complejidad temporal | ||
| Complejidad espacial | Es mucho menor que en anchura si no hay ciclos; con ciclos, depende de cómo se controlen. |
def cerca_profunditat_limitada(estat_inicial, limit):
frontera = [(estat_inicial, (estat_inicial,))]
tall = False
while frontera:
estat, cami = frontera.pop()
if es_solucio(estat):
return estat, tall
for succesor in succesors(estat):
if succesor not in cami:
if len(cami) - 1 < limit:
frontera.append((succesor, cami + (succesor,)))
else:
tall = True
return None, tall




def cerca_profunditat_iterativa(estat_inicial):
limit = 0
while True:
solucio, tall = cerca_profunditat_limitada(
estat_inicial, limit)
if solucio is not None or not tall:
return solucio
limit += 1
| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | Sí | Si el espacio de búsqueda es finito, encontrará una solución. |
| Optimalidad | Sí | La primera solución encontrada será óptima si todas las acciones tienen el mismo coste. |
| Complejidad temporal y espacial | Como la búsqueda en profundidad, con repetición de estados | El límite aumenta progresivamente. |
En los ejemplos con costes, succesors(estat) devuelve pares (sucesor, coste).
Es una variante de la búsqueda en anchura.
La frontera se ordena según el coste del camino hasta cada estado: se utiliza una cola de prioridad.
Se visitan los estados por orden creciente de coste acumulado.
Si todas las acciones tienen el mismo coste, equivale a la búsqueda en anchura.
import heapq
def cerca_cost_uniforme(estat_inicial):
"""Búsqueda de coste uniforme en un problema."""
frontera = [(0, estat_inicial)]
visitats = set()
while frontera:
cost_actual, estat = heapq.heappop(frontera)
# La frontera puede contener el mismo estado más de una vez.
if estat in visitats:
continue
visitats.add(estat)
if es_solucio(estat):
return estat
for succesor, cost_accio in succesors(estat):
if succesor not in visitats:
heapq.heappush(frontera, (cost_actual + cost_accio, succesor))
| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | Sí | Si todos los costes son positivos y se cumplen las condiciones del algoritmo. |
| Optimalidad | Sí | La primera solución extraída es óptima. |
| Complejidad temporal y espacial |
import heapq
def cerca_voraç(estat_inicial):
"""Búsqueda voraz en un problema."""
frontera = [(0, estat_inicial)]
visitats = set()
while frontera:
cost_actual, estat = heapq.heappop(frontera)
visitats.add(estat)
if es_solucio(estat):
return estat
for succesor, cost in succesors(estat):
if succesor not in visitats:
heapq.heappush(frontera, (heuristica(succesor), succesor))
| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | Sí | Si el espacio de búsqueda es finito y se evitan ciclos. |
| Optimalidad | No | La primera solución puede no ser óptima. |
| Complejidad temporal y espacial |
Con heurística consistente y costes no negativos, esta implementación encuentra una solución óptima.
import heapq
def cerca_a_estrella(estat_inicial):
"""Búsqueda A* en un problema."""
frontera = [(h(estat_inicial), 0, estat_inicial)]
visitats = set()
while frontera:
_, cost_actual, estat = heapq.heappop(frontera)
if estat in visitats:
continue
visitats.add(estat)
if es_solucio(estat):
return estat, cost_actual
for succesor, cost_accio in succesors(estat):
if succesor not in visitats:
nou_cost = cost_actual + cost_accio
prioritat = nou_cost + h(succesor)
heapq.heappush(frontera, (prioritat, nou_cost, succesor))
| Propiedad | Valor | Comentarios |
|---|---|---|
| Completitud | Sí | Bajo las condiciones habituales de costes positivos y ramificación finita. |
| Optimalidad | Sí | Si la heurística es admisible; para búsqueda en grafos, se requiere consistencia o reabrir estados. |
| Complejidad temporal y espacial |
Estas propiedades se cumplen si la heurística es consistente, como la distancia en línea recta en el mapa de Rumanía.
def cerca_a_limitada(estat, g, limit, cami):
f = g + h(estat)
if f > limit:
return None, f
if es_solucio(estat):
return cami[:], f
proxim_limit = float("inf")
for succesor, cost in succesors(estat):
if succesor in cami:
continue
cami.append(succesor)
solucio, valor = cerca_a_limitada(
succesor, g + cost, limit, cami)
cami.pop()
if solucio is not None:
return solucio, valor
proxim_limit = min(proxim_limit, valor)
return None, proxim_limit
def cerca_a_iterativa(estat_inicial):
limit = h(estat_inicial)
while limit < float("inf"):
solucio, seguent = cerca_a_limitada(
estat_inicial, 0, limit, [estat_inicial])
if solucio is not None:
return solucio
limit = seguent
return None
import heapq
def cerca_a_ponderat(estat_inicial, epsilon):
frontera = [(epsilon * h(estat_inicial), 0, estat_inicial)]
costos = {estat_inicial: 0}
while frontera:
_, cost_actual, estat = heapq.heappop(frontera)
if cost_actual != costos[estat]:
continue
if es_solucio(estat):
return estat, cost_actual
for succesor, cost in succesors(estat):
nou_cost = cost_actual + cost
if nou_cost < costos.get(succesor, float("inf")):
costos[succesor] = nou_cost
prioritat = nou_cost + epsilon * h(succesor)
heapq.heappush(frontera, (prioritat, nou_cost, succesor))
return None
def cerca_anytime_a(estat_inicial):
millor_cost = float("inf")
for epsilon in (8, 4, 2, 1):
solucio = cerca_a_ponderat(estat_inicial, epsilon)
if solucio is not None and solucio[1] < millor_cost:
millor_cost = solucio[1]
yield solucio