def coste_uniforme(problema): """Búsqueda en grafos de coste uniforme (uniform-cost search).""" raiz = crea_nodo_raiz(problema) frontera = [ raiz, ] explorados = set() while True: if not frontera: return None nodo = frontera.pop(0) if problema.es_objetivo(nodo.estado): return nodo explorados.add(nodo.estado) if not nodo.acciones: continue for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] if (hijo.estado not in explorados and hijo.estado not in estados_frontera): frontera.append(hijo) else: buscar = [ nodo for nodo in frontera if nodo.estado == hijo.estado ] if buscar: if hijo.coste < buscar[0].coste: indice = frontera.index(buscar[0]) frontera[indice] = hijo frontera.sort(key=lambda nodo: nodo.coste)
def profundidad(problema): """Búsqueda en grafos primero en profundidad (depth-first search).""" raiz = crea_nodo_raiz(problema) if problema.es_objetivo(raiz.estado): return raiz frontera = [ raiz, ] explorados = set() while True: if not frontera: return None nodo = frontera.pop() explorados.add(nodo.estado) if not nodo.acciones: continue for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] if (hijo.estado not in explorados and hijo.estado not in estados_frontera): es_objetivo = problema.es_objetivo(hijo.estado) if es_objetivo: return hijo frontera.append(hijo)
def a_estrella_iterativa(problema, nodo=None, limite=0, explorados=None): """Búsqueda A* iterativa que buscará hasta un límite máximo.""" if not nodo: nodo = crea_nodo_raiz(problema) if explorados is None: explorados = set() else: explorados.add(nodo.estado) if limite <= 0: limite = problema.infinito valor_nodo = min([ nodo.valores[objetivo.nombre] for objetivo in problema.estados_objetivos ]) if valor_nodo > limite: return None, valor_nodo if problema.es_objetivo(nodo.estado): return nodo, limite if not nodo.acciones: return None, limite minimo = problema.infinito for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) if hijo.estado not in explorados: nod_hijo, lim_hijo = a_estrella_iterativa(problema, hijo, limite, explorados) if nod_hijo: return nod_hijo, lim_hijo if lim_hijo < minimo: minimo = lim_hijo return None, minimo
def amplia_frontera(problema, nodo, objetivo, frontera, explorados): for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] estados_explorados = [nodo.estado for nodo in explorados] if (hijo.estado not in estados_explorados and hijo.estado not in estados_frontera): if objetivo == hijo.estado: return hijo frontera.append(hijo) return None
def sma_estrella(problema, maximo_nodos=10): """Búsqueda A* para memoria limitada (Simplified Memory-Bounded A*).""" raiz = crea_nodo_raiz(problema) frontera = [ raiz, ] explorados = set() while True: if not frontera: return None nodo = sacar_siguiente(frontera, 'valor', objetivos=problema.estados_objetivos) if problema.es_objetivo(nodo.estado): return nodo explorados.add(nodo.estado) if not nodo.acciones: continue for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] if hijo.estado in explorados or hijo.estado in estados_frontera: buscar = [ nodo for nodo in frontera if nodo.estado == hijo.estado ] if buscar: valores_hijo = [ hijo.valores[objetivo.nombre] for objetivo in problema.estados_objetivos ] valores_buscar = [ buscar[0].valores[objetivo.nombre] for objetivo in problema.estados_objetivos ] minimo_hijo = min(valores_hijo) minimo_buscar = min(valores_buscar) if minimo_hijo < minimo_buscar: indice = frontera.index(buscar[0]) frontera[indice] = hijo else: if len(frontera) > maximo_nodos: ordenador = lambda x: [ x.valores[objetivo.nombre] for objetivo in problema.estados_objetivos ] frontera = sorted(frontera, key=ordenador) frontera.pop() frontera.append(hijo)
def __coste_recursivo(nodo, problema, limite, explorados, soluciones): """Función recursiva de la busqueda en profundidad iterativa con costes.""" if limite <= 0: return None if problema.es_objetivo(nodo.estado): soluciones.append(nodo) return nodo explorados.add(nodo.estado) if not nodo.acciones: return None for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) if hijo.estado not in explorados: coste = problema.coste_accion(nodo.estado, accion) __coste_recursivo(hijo, problema, limite - coste, explorados.copy(), soluciones) return None
def __bpp_recursiva(nodo, problema, limite, explorados): """Función recursiva para realizar la búsqueda primero en profundidad.""" if problema.es_objetivo(nodo.estado): return nodo if limite == 0: return None explorados.add(nodo.estado) if not nodo.acciones: return None for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) if hijo.estado not in explorados: resultado = __bpp_recursiva(hijo, problema, limite - 1, explorados.copy()) if resultado: return resultado return None
def a_estrella(problema): """Búsqueda A* (que se lee 'A estrella').""" raiz = crea_nodo_raiz(problema) frontera = [ raiz, ] explorados = set() while True: if not frontera: return None nodo = sacar_siguiente(frontera, 'valor', objetivos=problema.estados_objetivos) if problema.es_objetivo(nodo.estado): return nodo explorados.add(nodo.estado) if not nodo.acciones: continue for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] if hijo.estado in explorados or hijo.estado in estados_frontera: buscar = [ nodo for nodo in frontera if nodo.estado == hijo.estado ] if buscar: valores_hijo = [ hijo.valores[objetivo.nombre] for objetivo in problema.estados_objetivos ] valores_buscar = [ buscar[0].valores[objetivo.nombre] for objetivo in problema.estados_objetivos ] minimo_hijo = min(valores_hijo) minimo_buscar = min(valores_buscar) if minimo_hijo < minimo_buscar: indice = frontera.index(buscar[0]) frontera[indice] = hijo else: frontera.append(hijo)
def voraz(problema): """Búsqueda en grafos voraz (greedy search).""" raiz = crea_nodo_raiz(problema) frontera = [ raiz, ] explorados = set() while True: if not frontera: return None nodo = sacar_siguiente(frontera, 'heuristica', objetivos=problema.estados_objetivos) if problema.es_objetivo(nodo.estado): return nodo explorados.add(nodo.estado) if not nodo.acciones: continue for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion) estados_frontera = [nodo.estado for nodo in frontera] if hijo.estado in explorados or hijo.estado in estados_frontera: buscar = [ nodo for nodo in frontera if nodo.estado == hijo.estado ] if buscar: heuristic_hijo = [ hijo.heuristicas[objetivo.nombre] for objetivo in problema.estados_objetivos ] heuristic_buscar = [ buscar[0].heuristicas[objetivo.nombre] for objetivo in problema.estados_objetivos ] minimo_hijo = min(heuristic_hijo) minimo_buscar = min(heuristic_buscar) if minimo_hijo < minimo_buscar: indice = frontera.index(buscar[0]) frontera[indice] = hijo else: frontera.append(hijo)
def _brpm_recursiva(problema, nodo, limite, explorados): """Función recursiva para búsqueda recursiva primero el mejor.""" explorados.add(nodo.estado) if limite <= 0: limite = problema.infinito if problema.es_objetivo(nodo.estado): return nodo, limite if not nodo.acciones: return None, limite for nombre_accion in nodo.acciones.keys(): accion = Accion(nombre_accion) hijo = crea_nodo_hijo(problema, nodo, accion, False) if hijo.estado not in explorados: hijo.padre = nodo nodo.hijos.append(hijo) maximo = max([ hijo.valores[objetivo.nombre] for objetivo in problema.estados_objetivos ]) hijo.alfa = max(maximo, nodo.alfa) if not nodo.hijos: return None, problema.infinito while True: objetivos = problema.estados_objetivos mejor = nodo.hijo_mejor(problema, metrica='alfa') if mejor.alfa > limite: return None, mejor.alfa hijos = nodo.hijos.copy() nodo.hijos.remove(mejor) alfa = limite if nodo.hijos: alternativa = nodo.hijo_mejor(problema, metrica='alfa') alfa = min(limite, alternativa.alfa) nodo.hijos = hijos resultado, mejor.alfa = _brpm_recursiva(problema, mejor, alfa, explorados) if resultado: return resultado, mejor.alfa
estado = nodo.estado.nombre coste_total = nodo.coste print(msg.format(estado, coste_total)) if nodo.accion: accion = nodo.accion.nombre padre = nodo.padre.estado coste = problema_resolver.coste_accion(padre, nodo.accion) if accion: msg = "<--- {0} [{1}] ---" print(msg.format(accion, coste)) nodo = nodo.padre # %% if __name__ == '__main__': accN = Accion('N') accS = Accion('S') accE = Accion('E') accO = Accion('O') accNE = Accion('NE') accNO = Accion('NO') accSE = Accion('SE') accSO = Accion('SO') lanoi = Estado('Lanoi', [accNE]) nohoi = Estado('Nohoi', [accSO, accNO, accNE]) ruun = Estado('Ruun', [accNO, accNE, accE, accSE]) milos = Estado('Milos', [accO, accSO, accN]) ghiido = Estado('Ghiido', [accN, accE, accSE]) kuart = Estado('Kuart', [accO, accSO, accNE]) boomon = Estado('Boomon', [accN, accSO])