No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TP1.pl 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /*
  2. *
  3. *
  4. *
  5. *
  6. * TAQUIN
  7. *
  8. *
  9. *
  10. *
  11. *
  12. */
  13. /* Fichier du probleme.
  14. Doit contenir au moins 4 predicats qui seront utilises par A*
  15. etat_initial(I) % definit l'etat initial
  16. etat_final(F) % definit l'etat final
  17. rule(Rule_Name, Rule_Cost, Before_State, After_State) % règles applicables
  18. heuristique(Current_State, Hval) % calcul de l'heuristique
  19. Les autres prédicats sont spécifiques au Taquin.
  20. */
  21. %:- lib(listut). % Laisser cette directive en commentaire si vous utilisez Swi-Prolog
  22. % Sinon décommentez la ligne si vous utilisez ECLiPSe Prolog :
  23. % -> permet de disposer du predicat nth1(N, List, E)
  24. % -> permet de disposer du predicat sumlist(List, S)
  25. % (qui sont predefinis en Swi-Prolog)
  26. %***************************
  27. %DESCRIPTION DU JEU DU TAKIN
  28. %***************************
  29. %********************
  30. % ETAT INITIAL DU JEU
  31. %********************
  32. % format : initial_state(+State) ou State est une matrice (liste de listes)
  33. initial_state([ [b, h, c], % C'EST L'EXEMPLE PRIS EN COURS
  34. [a, f, d], %
  35. [g,vide,e] ]). % h1=4, h2=5, f*=5
  36. % AUTRES EXEMPLES POUR LES TESTS DE A*
  37. /*
  38. initial_state([ [ a, b, c],
  39. [ g, h, d],
  40. [vide,f, e] ]). % h2=2, f*=2
  41. initial_state([ [b, c, d],
  42. [a,vide,g],
  43. [f, h, e] ]). % h2=10 f*=10
  44. initial_state([ [f, g, a],
  45. [h,vide,b],
  46. [d, c, e] ]). % h2=16, f*=20
  47. initial_state([ [e, f, g],
  48. [d,vide,h],
  49. [c, b, a] ]). % h2=24, f*=30
  50. initial_state([ [a, b, c],
  51. [g,vide,d],
  52. [h, f, e]]). % etat non connexe avec l'etat final (PAS DE SOLUTION)
  53. */
  54. %******************
  55. % ETAT FINAL DU JEU
  56. %******************
  57. % format : final_state(+State) ou State est une matrice (liste de listes)
  58. final_state([[a, b, c],
  59. [h,vide, d],
  60. [g, f, e]]).
  61. %********************
  62. % AFFICHAGE D'UN ETAT
  63. %********************
  64. % format : write_state(?State) ou State est une liste de lignes a afficher
  65. write_state([]).
  66. write_state([Line|Rest]) :-
  67. writeln(Line),
  68. write_state(Rest).
  69. %**********************************************
  70. % REGLES DE DEPLACEMENT (up, down, left, right)
  71. %**********************************************
  72. % format : rule(+Rule_Name, ?Rule_Cost, +Current_State, ?Next_State)
  73. rule(up, 1, S1, S2) :-
  74. vertical_permutation(_X,vide,S1,S2).
  75. rule(down, 1, S1, S2) :-
  76. vertical_permutation(vide,_X,S1,S2).
  77. rule(left, 1, S1, S2) :-
  78. horizontal_permutation(_X,vide,S1,S2).
  79. rule(right,1, S1, S2) :-
  80. horizontal_permutation(vide,_X,S1,S2).
  81. bad_placed(U,P) :-
  82. final_state(Fin), nth1(L,Fin,Ligne), nth1(C,Ligne,P2), nth1(L,U ,Ligne2), nth1(C,Ligne2,P), P\=P2, P \= vide .
  83. well_placed(U,P) :-
  84. final_state(Fin), nth1(L,Fin,Ligne), nth1(C,Ligne,P), nth1(L,U ,Ligne2), nth1(C,Ligne2,P), P \= vide .
  85. %***********************
  86. % Deplacement horizontal
  87. %***********************
  88. % format : horizontal_permutation(?Piece1,?Piece2,+Current_State, ?Next_State)
  89. horizontal_permutation(X,Y,S1,S2) :-
  90. append(Above,[Line1|Rest], S1),
  91. exchange(X,Y,Line1,Line2),
  92. append(Above,[Line2|Rest], S2).
  93. %***********************************************
  94. % Echange de 2 objets consecutifs dans une liste
  95. %***********************************************
  96. exchange(X,Y,[X,Y|List], [Y,X|List]).
  97. exchange(X,Y,[Z|List1], [Z|List2] ):-
  98. exchange(X,Y,List1,List2).
  99. %*********************
  100. % Deplacement vertical
  101. %*********************
  102. vertical_permutation(X,Y,S1,S2) :-
  103. append(Above, [Line1,Line2|Below], S1), % decompose S1
  104. delete(N,X,Line1,Rest1), % enleve X en position N a Line1, donne Rest1
  105. delete(N,Y,Line2,Rest2), % enleve Y en position N a Line2, donne Rest2
  106. delete(N,Y,Line3,Rest1), % insere Y en position N dans Rest1 donne Line3
  107. delete(N,X,Line4,Rest2), % insere X en position N dans Rest2 donne Line4
  108. append(Above, [Line3,Line4|Below], S2). % recompose S2
  109. %***********************************************************************
  110. % Retrait d'une occurrence X en position N dans une liste L (resultat R)
  111. %***********************************************************************
  112. % use case 1 : delete(?N,?X,+L,?R)
  113. % use case 2 : delete(?N,?X,?L,+R)
  114. delete(1,X,[X|L], L).
  115. delete(N,X,[Y|L], [Y|R]) :-
  116. delete(N1,X,L,R),
  117. N is N1 + 1.
  118. %*******************
  119. % PARTIE A COMPLETER
  120. %*******************
  121. %*******************************************************************
  122. % Coordonnees X(colonne),Y(Ligne) d'une piece P dans une situation U
  123. %*******************************************************************
  124. % format : coordonnees(?Coord, +Matrice, ?Element)
  125. % Définit la relation entre des coordonnees [Ligne, Colonne] et un element de la matrice
  126. /*
  127. Exemples
  128. ?- coordonnees(Coord, [[a,b,c],[d,e,f]], e). % quelles sont les coordonnees de e ?
  129. Coord = [2,2]
  130. yes
  131. ?- coordonnees([2,3], [[a,b,c],[d,e,f]], P). % qui a les coordonnees [2,3] ?
  132. P=f
  133. yes
  134. */
  135. coordonnees([L,C], Mat, Elt) :-
  136. nth1(L,Mat ,Ligne), nth1(C,Ligne,Elt).
  137. %*************
  138. % HEURISTIQUES
  139. %*************
  140. heuristique(U,H) :-
  141. % heuristique1(U, H). % au debut on utilise l'heuristique 1
  142. heuristique2(U, H). % ensuite utilisez plutot l'heuristique 2
  143. %****************
  144. %HEURISTIQUE no 1
  145. %****************
  146. % Nombre de pieces mal placees dans l'etat courant U
  147. % par rapport a l'etat final F
  148. % Suggestions : définir d'abord le prédicat coordonnees(Piece,Etat,Lig,Col) qui associe à une pièce présente dans Etat
  149. % ses coordonnees (Lig= numero de ligne, Col= numero de Colonne)
  150. % Definir ensuite le predicat malplace(P,U,F) qui est vrai si les coordonnes de P dans U et dans F sont differentes.
  151. % On peut également comparer les pieces qui se trouvent aux mêmes coordonnees dans U et dans H et voir s'il sagit de la
  152. % même piece.
  153. % Definir enfin l'heuristique qui détermine toutes les pièces mal placées (voir prédicat findall)
  154. % et les compte (voir prédicat length)
  155. heuristique1(U, H) :- findall(P,bad_placed(U,P),Liste), length(Liste,H) .
  156. /*
  157. * manhattan(U,P, M) :-
  158. final_state(Fin), nth1(L,Fin,Ligne), nth1(C,Ligne,_P2), nth1(L,U ,Ligne2), nth1(C,Ligne2,P), coordonnees([L1,C1],U,P), coordonnees([L2,C2],Fin,P), M1 is abs(L1-L2), M2 is abs(C1-C2), M is (M1+M2), P \= vide.
  159. */
  160. manhattan(U,Element,Cout):-
  161. final_state(Fin),
  162. coordonnees([X,Y],Fin,Element),
  163. coordonnees([A,B],U,Element),
  164. Element \= vide ,
  165. Cout is (abs(X - A) + abs(B - Y)).
  166. %****************
  167. %HEURISTIQUE no 2
  168. %****************
  169. % Somme des distances de Manhattan à parcourir par chaque piece
  170. % entre sa position courante et sa positon dans l'etat final
  171. heuristique2(U, H) :- findall(M,manhattan(U,_,M),Liste), sumlist(Liste,H) .
  172. /*
  173. *
  174. *
  175. *
  176. *
  177. * AVL
  178. *
  179. *
  180. *
  181. *
  182. *
  183. */
  184. %***************************
  185. % Gestion d'un AVL en Prolog
  186. %***************************
  187. %***************************
  188. % INSA TOULOUSE - P.ESQUIROL
  189. % mars 2017
  190. %***************************
  191. %*************************
  192. % unit tests : OK
  193. % integration aetoile : OK
  194. %*************************
  195. % Les AVL sont des arbres BINAIRES DE RECHERCHE H-EQUILIBRES :
  196. % La hauteur de l'avl A est d�finie par :
  197. % -1, si A est vide (A=nil)
  198. % 1 + max( hauteur(ss_arbre_gauche(A)), hauteur(ss_arbre_droitee(A)) ) sinon
  199. % Tout noeud de l'arbre est soit :
  200. % - une feuille
  201. % - un noeud interne tel que la diff�rence de hauteur entre le sous-arbre droit
  202. % et le sous-arbre gauche appartient � [-1,0,+1]
  203. %***********************************************
  204. % PREDICATS EXPORTES ET COMPLEXITE ALGORITHMIQUE
  205. %***********************************************
  206. % soit N = nombre de noeuds de l'arbre % UTILITE POUR A*
  207. % % ----------------
  208. % empty(?Avl) O(1) %<<< initialisation de P et Q
  209. % height(+Avl, ?Height) O(1)
  210. % put_flat(+Avl) O(N)
  211. % put_90(+Avl) O(N)
  212. % belongs(+Elem, +Avl) O(log N) %<<< appartenance d'un noeud � Q
  213. % subtree(+Elem, +Avl, Ss_Avl) O(log N)
  214. % insert(+Elem, +Avant, ?Apres) O(log N) %<<< insertion d'un nouveau noeud dans P ou dans Q
  215. % suppress(+Elem,+Avant,?Apres) O(log N) %<<< mise � jour <=> suppression puis insertion
  216. % suppress_min(?Min,+Avant,?Apres) O(log N) %<<< supression du noeud minimal
  217. % suppress_max(?Max,+Avant,?Apres) O(log N)
  218. %****************************
  219. % Pr�dicats internes (prives)
  220. %****************************
  221. % left_rotate(+Avant, ?Apres) O(1)
  222. % right_rotate(+Avant, ?Apres) O(1)
  223. % left_balance(+Avant, ?Apres) O(1)
  224. % right_balance(+Avant, ?Apres) O(1)
  225. %------------------------------
  226. % Constructeur et test AVL vide
  227. %------------------------------
  228. empty(nil).
  229. %-----------------
  230. % Hauteur d'un AVL
  231. %-----------------
  232. % par convention, un avl vide a une hauteur de -1
  233. % sinon la hauteur est enregistree au meme niveau que la racine de l'avl
  234. % elle n'est pas calculee recursivement "from scratch"
  235. % elle est mise � jour de fa�on incr�mentale, apres chaque insertion ou suppression
  236. % d'ou sa complexit� en O(1) :-)
  237. height(nil, -1).
  238. height(avl(_G,_R,_D, H), H).
  239. %-------------------
  240. % Affichage d'un AVL
  241. %-------------------
  242. % dans l'ordre croissant (lexicographique)
  243. put_flat(nil).
  244. put_flat(avl(G,R,D,_H)) :-
  245. put_flat(G),
  246. nl, write(R),
  247. put_flat(D).
  248. %----------------------------
  249. % Affichage (couch�) d'un AVL
  250. %----------------------------
  251. put_90(Avl) :-
  252. nl, writeln('----------------------------------'),
  253. put_90(Avl,"").
  254. put_90(nil,Str) :-
  255. write(Str), write('.').
  256. put_90(avl(G,R,D,_H),Str) :-
  257. append_strings(Str, " ", Str2),
  258. put_90(D,Str2),
  259. nl, write(Str), write(R),nl,
  260. put_90(G,Str2).
  261. %-----------------------------------------
  262. % Appartenance d'un element donne a un AVL
  263. %-----------------------------------------
  264. belongs(Elem, avl(G,Racine,D,_Hauteur)) :-
  265. (Elem = Racine ->
  266. true
  267. ;
  268. (Elem @< Racine ->
  269. belongs(Elem, G)
  270. ;
  271. belongs(Elem, D) %Racine @< Elem
  272. )
  273. ).
  274. %------------------------------------------------------------
  275. % Recherche du sous-arbre qui a comme racine un element donne
  276. %------------------------------------------------------------
  277. subtree(Elem, avl(G,Racine,D,H), A) :-
  278. (Elem = Racine ->
  279. A = avl(G,Racine,D,H)
  280. ;
  281. (Elem @< Racine ->
  282. subtree(Elem,G,A)
  283. ;
  284. subtree(Elem,D,A) %Racine @< Elem
  285. )
  286. ).
  287. %----------------------
  288. % Rotations dans un avl
  289. %----------------------
  290. % Les rotations ci-dessous d�crivent uniquement les cas ou la rotation est possible.
  291. % Dans les autres cas, ces relations �chouent ; plus pr�cis�ment :
  292. % a/ si l'arbre est un avl vide, alors aucune rotation n'est possible ;
  293. % b/ si l'arbre est un avl non vide mais si son ss-arbre gauche est un avl vide
  294. % alors la rotation droite n'est pas possible ;
  295. % c/ si l'arbre est un avl non vide mais si son ss-arbre droite est un avl vide
  296. % alors la rotation gauche n'est pas possible.
  297. right_rotate(avl(G,R,D,_H), A_Apres) :-
  298. height(D,HD),
  299. G = avl(SG,RG,SD,_HG),
  300. height(SD,HSD),
  301. H_Inter is 1 + max(HSD, HD),
  302. Inter = avl(SD,R,D,H_Inter),
  303. height(SG,HSG),
  304. H_Apres is 1 + max(HSG,H_Inter),
  305. A_Apres = avl(SG,RG,Inter,H_Apres).
  306. left_rotate(avl(G,R,D,_), A_Apres) :-
  307. height(G,HG),
  308. D = avl(SG,RD,SD,_),
  309. height(SG,HSG),
  310. H_Inter is 1 + max(HSG, HG),
  311. Inter = avl(G,R,SG,H_Inter),
  312. height(SD,HSD),
  313. H_Apres is 1 + max(H_Inter,HSD),
  314. A_Apres = avl(Inter,RD,SD,H_Apres).
  315. %---------------------------------
  316. % Insertion equilibree dans un avl
  317. %---------------------------------
  318. % On suppose que l'arbre avant insertion est equilibr� (difference de hauteur
  319. % entre les ss-arbres gauche et droite de 1 au maximum)
  320. % L'insertion doit assurer qu'apres insertion l'arbre est toujours equilibre
  321. % sinon les rotations necessaires sont effectuees.
  322. % On suppose que les noeuds contiennent des informations que l'on peut comparer
  323. % a l'aide d'une relation d'ordre lexicographique (la cle c'est l'info elle-meme)
  324. % En prolog, c'est la relation '@<'
  325. % On peut comparer par exemple des integer, des string, des constantes,
  326. % des listes d'entiers, des listes de constantes, etc ... bref, des termes clos
  327. % T1 @< T2 est vrai si T1 est lexicographiquement inf�rieur a T2.
  328. insert(Elem, nil, avl(nil,Elem,nil,0)).
  329. insert(Elem, AVL, NEW_AVL) :-
  330. AVL = avl(Gauche,Racine,Droite,_Hauteur),
  331. (Elem = Racine ->
  332. % l'�l�ment est d�j� present, pas d'insertion possible
  333. fail
  334. ;
  335. (Elem @< Racine ->
  336. % insertion dans le ss-arbre gauche
  337. insert(Elem, Gauche, New_Gauche),
  338. height(New_Gauche, New_HG),
  339. height(Droite, HD),
  340. H_Int is 1+max(New_HG, HD),
  341. AVL_INT = avl(New_Gauche, Racine, Droite, H_Int),
  342. right_balance(AVL_INT, NEW_AVL)
  343. ;
  344. % Elem @> Racine
  345. % insertion dans le ss-arbre droite
  346. insert(Elem, Droite, New_Droite),
  347. height(New_Droite, New_HD),
  348. height(Gauche, HG),
  349. H_Int is 1+max(New_HD, HG),
  350. AVL_INT =avl(Gauche, Racine,New_Droite, H_Int),
  351. left_balance(AVL_INT, NEW_AVL)
  352. )
  353. ).
  354. %------------------------------------------------
  355. % Suppression d'un element quelconque dans un avl
  356. %------------------------------------------------
  357. % On suppose que l'�l�ment � supprimer appartient bien � l'AVL,
  358. % sinon le predicat �choue (en particulier si l'AVL est vide).
  359. suppress(Elem, AVL, NEW_AVL) :-
  360. AVL = avl(Gauche, Racine, Droite, _Hauteur),
  361. (Elem = Racine ->
  362. % cas de la suppression de la racine de l'avl
  363. (Gauche = nil -> % cas simple d'une feuille ou d'un avl sans fils gauche
  364. NEW_AVL = Droite
  365. ;
  366. (Droite = nil -> % cas simple d'un avl avec fils gauche mais sans fils droit
  367. NEW_AVL = Gauche
  368. ;
  369. % cas d'un avl avec fils gauche ET fils droit
  370. %Gauche \= nil
  371. %Droite \= nil
  372. suppress_max(Max, Gauche, New_Gauche),
  373. AVL_INT = avl(New_Gauche,Max,Droite,_),
  374. left_balance(AVL_INT, NEW_AVL)
  375. )
  376. )
  377. ;
  378. % cas des suppressions d'un element autre que la racine
  379. (Elem @< Racine ->
  380. % suppression dans le ss-arbre gauche
  381. suppress(Elem, Gauche, New_Gauche),
  382. AVL_INT = avl(New_Gauche, Racine, Droite,_),
  383. left_balance(AVL_INT, NEW_AVL)
  384. ;
  385. %Racine @< Droite
  386. % suppression dans le ss-arbre droite
  387. suppress(Elem, Droite, New_Droite),
  388. AVL_INT = avl(Gauche, Racine, New_Droite,_),
  389. right_balance(AVL_INT, NEW_AVL)
  390. )
  391. ).
  392. %-------------------------------------------------------
  393. % Suppression du plus petit element dans un avl non vide
  394. %-------------------------------------------------------
  395. % Si l'avl est vide, le predicat echoue
  396. suppress_min(Min, AVL, NEW_AVL) :-
  397. AVL = avl(Gauche,Racine,Droite, _Hauteur),
  398. (Gauche = nil ->
  399. Min = Racine,
  400. NEW_AVL = Droite
  401. ;
  402. % Gauche \= nil
  403. suppress_min(Min, Gauche, New_Gauche),
  404. AVL_INT = avl(New_Gauche, Racine, Droite,_),
  405. left_balance(AVL_INT, NEW_AVL)
  406. ).
  407. %-------------------------------------------------------
  408. % Suppression du plus grand element dans un avl non vide
  409. %-------------------------------------------------------
  410. % Si l'avl est vide, le pr�dicat �choue
  411. suppress_max(Max, AVL, NEW_AVL) :-
  412. AVL = avl(Gauche,Racine,Droite, _Hauteur),
  413. (Droite = nil ->
  414. Max = Racine,
  415. NEW_AVL = Gauche
  416. ;
  417. % Droite \= nil
  418. suppress_max(Max, Droite, New_Droite),
  419. AVL_INT = avl(Gauche, Racine, New_Droite,_),
  420. right_balance(AVL_INT, NEW_AVL)
  421. ).
  422. %----------------------------------------
  423. % Re-equilibrages d'un avl vers la gauche
  424. %----------------------------------------
  425. % - soit apres insertion d'un element dans le sous-arbre droite
  426. % - soit apres suppression d'un �l�ment dans le sous-arbre gauche
  427. %----------------------------------------------------------------
  428. left_balance(Avl, New_Avl) :-
  429. Avl = avl(Gauche, Racine, Droite, _Hauteur),
  430. height(Gauche, HG),
  431. height(Droite, HD),
  432. (HG is HD-2 ->
  433. % le sous-arbre droite est trop haut
  434. Droite = avl(G_Droite, _R_Droite, D_Droite, _HD),
  435. height(G_Droite, HGD),
  436. height(D_Droite, HDD),
  437. (HDD > HGD ->
  438. % une simple rotation gauche suffit
  439. left_rotate(Avl, New_Avl)
  440. ;
  441. % il faut faire une rotation droite_gauche
  442. right_rotate(Droite, New_Droite),
  443. height(New_Droite, New_HD),
  444. H_Int is 1+ max(HG, New_HD),
  445. Avl_Int = avl(Gauche, Racine, New_Droite, H_Int),
  446. left_rotate(Avl_Int, New_Avl)
  447. )
  448. ;
  449. % la suppression n'a pas desequilibre l'avl
  450. New_Hauteur is 1+max(HG,HD),
  451. New_Avl = avl(Gauche, Racine, Droite, New_Hauteur)
  452. ).
  453. %----------------------------------------
  454. % Re-equilibrages d'un avl vers la droite
  455. %----------------------------------------
  456. % - soit apres insertion d'un element dans le sous-arbre gauche
  457. % - soit apres suppression d'un �l�ment dans le sous-arbre droite
  458. %----------------------------------------------------------------
  459. right_balance(Avl, New_Avl) :-
  460. Avl = avl(Gauche, Racine, Droite, _Hauteur),
  461. height(Gauche, HG),
  462. height(Droite, HD),
  463. (HD is HG-2 ->
  464. % le sous-arbre gauche est trop haut
  465. Gauche = avl(G_Gauche, _R_Gauche, D_Gauche, _HG),
  466. height(G_Gauche, HGG),
  467. height(D_Gauche, HDG),
  468. (HGG > HDG ->
  469. % une simple rotation droite suffit
  470. right_rotate(Avl, New_Avl)
  471. ;
  472. % il faut faire une rotation gauche_droite
  473. left_rotate(Gauche, New_Gauche),
  474. height(New_Gauche, New_HG),
  475. H_Int is 1+ max(New_HG, HD),
  476. Avl_Int = avl(New_Gauche, Racine, Droite, H_Int),
  477. right_rotate(Avl_Int, New_Avl)
  478. )
  479. ;
  480. % la suppression n'a pas desequilibre l'avl
  481. New_Hauteur is 1+max(HG,HD),
  482. New_Avl = avl(Gauche, Racine, Droite, New_Hauteur)
  483. ).
  484. %-----------------------------------------
  485. % Arbres utilises pour les tests unitaires
  486. %-----------------------------------------
  487. avl_test(1, nil).
  488. avl_test(2, avl(nil, 1, nil, 0)).
  489. avl_test(3, avl(nil, 1, avl(nil,2,nil,0), 1)).
  490. avl_test(4, avl(avl(nil,1,nil,0),2, nil, 1)).
  491. avl_test(5, avl(avl(nil,1,nil,0), 2, avl(nil,3,nil,0),1) ).
  492. avl_test(6, avl(avl(nil,5,nil,0), 6, avl(nil,7,nil,0),1) ).
  493. avl_test(7, avl(G,4,D,2)) :-
  494. avl_test(5,G),
  495. avl_test(6,D).
  496. avl_test(8, avl(G,5,D,2)) :-
  497. D = avl(nil,6,nil,0),
  498. avl_test(3,G).
  499. avl_test(9, avl(G,3,D,2)) :-
  500. G = avl(nil,1,nil,0),
  501. avl_test(4,D).
  502. /* Test uniquement valable avec ECLiPSe
  503. avl_test(10, Final) :-
  504. empty(Init),
  505. (for(I,1,20), fromto(Init,In,Out,Final) do
  506. insert(I,In,Out)
  507. ).
  508. */
  509. /*
  510. *
  511. *
  512. *
  513. *
  514. * AETOILE
  515. *
  516. *
  517. *
  518. *
  519. *
  520. */
  521. %*******************************************************************************
  522. % AETOILE
  523. %*******************************************************************************
  524. /*
  525. Rappels sur l'algorithme
  526. - structures de donnees principales = 2 ensembles : P (etat pendants) et Q (etats clos)
  527. - P est dedouble en 2 arbres binaires de recherche equilibres (AVL) : Pf et Pu
  528. Pf est l'ensemble des etats pendants (pending states), ordonnes selon
  529. f croissante (h croissante en cas d'egalite de f). Il permet de trouver
  530. rapidement le prochain etat a developper (celui qui a f(U) minimum).
  531. Pu est le meme ensemble mais ordonne lexicographiquement (selon la donnee de
  532. l'etat). Il permet de retrouver facilement n'importe quel etat pendant
  533. On gere les 2 ensembles de fa�on synchronisee : chaque fois qu'on modifie
  534. (ajout ou retrait d'un etat dans Pf) on fait la meme chose dans Pu.
  535. Q est l'ensemble des etats deja developpes. Comme Pu, il permet de retrouver
  536. facilement un etat par la donnee de sa situation.
  537. Q est modelise par un seul arbre binaire de recherche equilibre.
  538. Predicat principal de l'algorithme :
  539. aetoile(Pf,Pu,Q)
  540. - reussit si Pf est vide ou bien contient un etat minimum terminal
  541. - sinon on prend un etat minimum U, on genere chaque successeur S et les valeurs g(S) et h(S)
  542. et pour chacun
  543. si S appartient a Q, on l'oublie
  544. si S appartient a Ps (etat deja rencontre), on compare
  545. g(S)+h(S) avec la valeur deja calculee pour f(S)
  546. si g(S)+h(S) < f(S) on reclasse S dans Pf avec les nouvelles valeurs
  547. g et f
  548. sinon on ne touche pas a Pf
  549. si S est entierement nouveau on l'insere dans Pf et dans Ps
  550. - appelle recursivement etoile avec les nouvelles valeurs NewPF, NewPs, NewQs
  551. */
  552. %*******************************************************************************
  553. %:- ['avl.pl']. % predicats pour gerer des arbres bin. de recherche
  554. %:- ['taquin.pl']. % predicats definissant le systeme a etudier
  555. %*******************************************************************************
  556. main :-
  557. % initialisations Pf, Pu et Q
  558. initial_state(S0),
  559. heuristique2(S0, H),
  560. empty(Pf0),
  561. empty(Pu0),
  562. empty(Q),
  563. insert([[H,H,0],S0],Pf0,Pf),
  564. insert([S0,[H,H,0],nil,nil],Pu0,Pu),
  565. % lancement de Aetoile
  566. aetoile(Pf,Pu,Q), !.
  567. %*******************************************************************************
  568. aetoile(Pf, _, _) :-
  569. empty(Pf),
  570. writeln("PAS de SOLUTION : L’ETAT FINAL N’EST PAS ATTEIGNABLE !").
  571. aetoile(Pf, Pu, Qs) :-
  572. suppress_min([[_,_,_],Fin],Pf,_Pf_new),
  573. final_state(Fin),
  574. writeln("Solution trouvée !"),
  575. suppress([Fin,[F,H,G],Pere,Action],Pu,_Pu_new),
  576. affiche_solution([Fin,[F,H,G],Pere,Action], Qs).
  577. aetoile(Pf, Pu, Qs) :-
  578. suppress_min([[_,_,_],U],Pf,Pf_new), % le nœud de Pf correspondant à l’état U à développer
  579. suppress([U,[F,H,G],Pere,Action],Pu,Pu_new), %le nœud frère associé dans Pu
  580. expand(U,G,Liste),
  581. loop_successors(Liste, Pf_new,Pu_new,Qs,Pf_last,Pu_last),
  582. insert([U,[F,H,G],Pere,Action],Qs,Qs_new),
  583. aetoile(Pf_last,Pu_last,Qs_new).
  584. expand(U,G,L):- findall(U3,(rule(Action,1,U,U2),heuristique(U2,H), F is H+G+1, G2 is G+1, U3 = [U2,[F,H,G2],U,Action]),L).
  585. affiche_solution([Debut,_,nil,nil],_) :-
  586. initial_state(Debut),
  587. writeln("Etat initial : "),
  588. writeln(Debut).
  589. affiche_solution(State,Qs):-
  590. State = [U,[_,_,G],Pere,Action],
  591. suppress([Pere,Cout,Pere1,Action1],Qs, Qs_new),
  592. affiche_solution([Pere,Cout,Pere1,Action1],Qs_new),
  593. write("Cout = "), writeln(G),
  594. write("Action = "), writeln(Action),
  595. writeln(U).
  596. loop_successors([], Pf,Pu,_Qs,Pf,Pu).
  597. loop_successors([D|F], Pf,Pu,Qs,Pf_last,Pu_last) :-
  598. D = [U,_,_Pere,_Action],
  599. belongs([U,_,_,_],Qs), %S est connu dans Q alors oublier cet état
  600. loop_successors(F,Pf,Pu,Qs,Pf_last,Pu_last).
  601. loop_successors([D|F], Pf,Pu,Qs,Pf_last,Pu_last) :-
  602. D = [U,[Fu,_Gu,_Hu],_Pere,_Action],
  603. belongs([U,[FF,_GG,_HH],_Father,_A],Pu),
  604. FF =< Fu,
  605. loop_successors(F,Pf,Pu,Qs,Pf_last,Pu_last).
  606. loop_successors([D|F], Pf,Pu,Qs,Pf_last,Pu_last) :-
  607. D = [U,[Fu,Gu,Hu],Pere,Action],
  608. belongs([U,[FF,GG,HH],Father,A],Pu),
  609. FF > Fu,
  610. suppress([U,[FF,GG,HH],Father,A],Pu,Pu_new),
  611. suppress([_,U],Pf,Pf_new),
  612. insert([U,[Fu,Gu,Hu],Pere,Action],Pu_new,Pu_N),
  613. insert([[Fu,Gu,Hu],U],Pf_new,Pf_N),
  614. loop_successors(F,Pf_N,Pu_N,Qs,Pf_last,Pu_last).
  615. loop_successors([D|F], Pf,Pu,Qs,Pf_last,Pu_last) :-
  616. D = [U,[Fu,Gu,Hu],Pere,Action],
  617. insert([U,[Fu,Gu,Hu],Pere,Action],Pu,Pu_N),
  618. insert([[Fu,Gu,Hu],U],Pf,Pf_N),
  619. loop_successors(F,Pf_N,Pu_N,Qs,Pf_last,Pu_last).