From 49671d1fea5b2cde73d95a7fd2c8832afd1a4bfc Mon Sep 17 00:00:00 2001 From: Nathan BOUZON Date: Wed, 23 Oct 2024 11:57:12 +0200 Subject: [PATCH] =?UTF-8?q?T=C3=A9l=C3=A9verser=20les=20fichiers=20vers=20?= =?UTF-8?q?"/"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- heur.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 heur.py diff --git a/heur.py b/heur.py new file mode 100644 index 0000000..eca8013 --- /dev/null +++ b/heur.py @@ -0,0 +1,76 @@ +import heapq + +# Fonction heuristique: Somme des objets restants (admissible) +def heuristique(etat_jeu): + return sum(etat_jeu) + +# Fonction qui vérifie si l'état est final (tous les tas sont vides) +def est_etat_final(etat_jeu): + return all(tas == 0 for tas in etat_jeu) + +# Fonction qui génère tous les mouvements possibles depuis un état donné +def generer_mouvements(etat_jeu): + mouvements_possibles = [] + for i in range(len(etat_jeu)): + if etat_jeu[i] > 0: + for retirer in range(1, etat_jeu[i] + 1): + nouvel_etat = etat_jeu.copy() + nouvel_etat[i] -= retirer + mouvements_possibles.append(nouvel_etat) + return mouvements_possibles + +# Classe Noeud utilisée pour l'algorithme A* +class Noeud: + def __init__(self, etat, parent=None, g=0, h=0): + self.etat = etat + self.parent = parent + self.g = g # Coût du chemin (g(n)) + self.h = h # Heuristique (h(n)) + + # Priorité des nœuds basée sur la somme g + h + def __lt__(self, other): + return (self.g + self.h) < (other.g + other.h) + +# Algorithme A* pour trouver le chemin optimal vers la victoire +def algorithme_a_star(etat_initial): + # Initialisation de la file de priorité + open_list = [] + heapq.heappush(open_list, Noeud(etat_initial, g=0, h=heuristique(etat_initial))) + closed_list = set() + + while open_list: + # Récupérer le nœud avec le plus faible f(n) = g(n) + h(n) + noeud_courant = heapq.heappop(open_list) + + # Vérifier si c'est l'état final + if est_etat_final(noeud_courant.etat): + return reconstruire_chemin(noeud_courant) + + # Ajouter l'état courant aux états visités + closed_list.add(tuple(noeud_courant.etat)) + + # Générer les mouvements légaux + for mouvement in generer_mouvements(noeud_courant.etat): + if tuple(mouvement) in closed_list: + continue + + g_nouveau = noeud_courant.g + 1 + h_nouveau = heuristique(mouvement) + nouveau_noeud = Noeud(mouvement, parent=noeud_courant, g=g_nouveau, h=h_nouveau) + heapq.heappush(open_list, nouveau_noeud) + + return None # Si aucun chemin n'est trouvé + +# Fonction pour reconstruire le chemin optimal +def reconstruire_chemin(noeud_final): + chemin = [] + noeud_courant = noeud_final + while noeud_courant is not None: + chemin.append(noeud_courant.etat) + noeud_courant = noeud_courant.parent + return chemin[::-1] # Retourner le chemin dans l'ordre correct + +# Test de l'algorithme A* avec l'état initial [3, 4, 5] +etat_initial = [3, 4, 5] +chemin_optimal = algorithme_a_star(etat_initial) +print("Chemin optimal:", chemin_optimal)