IA_TP_LAWSON-LARTEGO/TPIA/jeu_nim/exo8.py

73 lines
3.1 KiB
Python
Raw Normal View History

2024-10-23 21:37:10 +02:00
import heapq
def algorithme_a_star(etat_initial):
# File de priorité (tas) pour les nœuds à explorer
file_priorite = []
# Ajouter l'état initial dans la file de priorité (f(n), g(n), état)
heapq.heappush(file_priorite, (0 + heuristique(etat_initial), 0, etat_initial))
# Dictionnaire pour stocker le coût minimal pour atteindre chaque état
cout_minimal = {tuple(etat_initial): 0}
# Dictionnaire pour stocker le parent de chaque état (reconstruction du chemin)
predecesseurs = {tuple(etat_initial): None}
# Ensemble pour stocker les états déjà visités
etats_visites = set()
while file_priorite:
# Extraire l'état avec le plus faible coût estimé f(n)
_, cout_actuel, etat_actuel = heapq.heappop(file_priorite)
# Convertir l'état en tuple pour le stockage dans les ensembles
etat_tuple = tuple(etat_actuel)
# Si l'état a déjà été visité, on l'ignore
if etat_tuple in etats_visites:
continue
# Marquer l'état comme visité
etats_visites.add(etat_tuple)
# Vérifier si l'état actuel est l'état final
if est_etat_final(etat_actuel):
# Reconstruire le chemin optimal
chemin = []
while etat_actuel is not None:
chemin.append(etat_actuel)
etat_actuel = predecesseurs[tuple(etat_actuel)]
chemin.reverse() # On inverse le chemin pour l'avoir dans l'ordre
return chemin
# Générer tous les mouvements possibles à partir de l'état actuel
mouvements_possibles = generer_mouvements(etat_actuel)
for nouvel_etat in mouvements_possibles:
# Calculer le coût du mouvement (toujours 1 dans notre cas)
cout_mouvement_actuel = cout_actuel + cout_mouvement(etat_actuel, nouvel_etat)
# Si le nouvel état est rencontré avec un coût inférieur à celui déjà connu
etat_tuple_nouveau = tuple(nouvel_etat)
# Vérifier si l'état a déjà été visité ou si le coût est inférieur
if etat_tuple_nouveau not in etats_visites or cout_mouvement_actuel < cout_minimal.get(etat_tuple_nouveau, float('inf')):
cout_minimal[etat_tuple_nouveau] = cout_mouvement_actuel
predecesseurs[etat_tuple_nouveau] = etat_actuel # Stocker le parent
# Calculer f(n) = g(n) + h(n)
f_n = cout_mouvement_actuel + heuristique(nouvel_etat)
# Ajouter le nouvel état dans la file de priorité
heapq.heappush(file_priorite, (f_n, cout_mouvement_actuel, nouvel_etat))
# Si aucun chemin n'a été trouvé (ce qui ne devrait pas arriver dans le jeu de Nim)
return None
etat_initial = [3, 4, 5] # Exemple d'état initial
# Appel de l'algorithme A* pour trouver le chemin optimal
chemin_optimal = algorithme_a_star(etat_initial)
# Affichage du chemin
for etat in chemin_optimal:
print(etat)