TP_IA/tp1/aetoile.pl
2021-03-21 01:31:33 +01:00

107 lines
3.2 KiB
Prolog

:- include('avl.pl'). % predicats pour gerer des arbres bin. de recherche
:- include('taquin.pl'). % predicats definissant le systeme a etudier
main :-
% Calcul de H pour la situation de départ
initial_state(U0),
heuristique(U0, H0),
% initialisations Pf, Pu et Q
insert([ [H0, H0, 0], U0 ], nil, Pf),
insert([U0, [H0, H0, 0], nil, nil], nil, Pu),
empty(Q),
!,
% lancement de Aetoile
aetoile(Pf, Pu, Q).
%*******************************************************************************
afficher_solution(_, nil).
afficher_solution(Q, S) :-
belongs([S, [_,_,G], Pere, Action], Q),
!,
write_state(S),
print(Action),
print(' ('),
print(G),
print(')'),
nl, nl,
afficher_solution(Q, Pere).
%*******************************************************************************
% Cas arbres vides -> plus d'état à développer -> pas de solution
aetoile(Pf, _, _) :-
empty(Pf),
!,
print('Pas de solution : l\'état final n\'est pas atteignable !\n').
% Cas état final -> solution trouvée
aetoile(Pf, Pu, Q) :-
suppress_min([[F, H, G], Sf], Pf, _),
final_state(Sf),
!,
suppress([Sf, [F, H, G], Pere, A], Pu, _),
insert([Sf, [F, H, G], Pere, A], Q, Q1),
print('Solution trouvée :\n'),
afficher_solution(Q1, Sf).
aetoile(Pf, Pu, Q) :-
suppress_min([[F, H, G], S], Pf, Pf1),
suppress([S, [F, H, G], Pere, A], Pu, Pu1),
expand(S, G, Successors),
loop_successors(Successors, S, Pf1, Pu1, Q, Pf2, Pu2),
insert([S, [F, H, G], Pere, A], Q, Q1),
aetoile(Pf2, Pu2, Q1).
%*******************************************************************************
expand(S, Gs, Successors) :-
findall([Successor, [F, H, G], Action], (
rule(Action, Cost, S, Successor),
G is Gs + Cost,
heuristique(Successor, H),
F is G + H
), Successors).
%*******************************************************************************
% Cas pas de successseurs
loop_successors([], _,Pf, Pu, _, Pf, Pu) :- !.
% Cas successeur déjà traité : on ignore
loop_successors([[S,_,_] | Rest], Pere, Pf, Pu, Q, Pf_new, Pu_new) :-
belongs([S,_,_,_], Q),
%!,
loop_successors(Rest, Pere, Pf, Pu, Q, Pf_new, Pu_new),
!.
% Cas successeur déjà connu : on met à jour le coût
loop_successors([[S, [F, H, G], Action] | Rest], Pere, Pf, Pu, Q, Pf_new, Pu_new) :-
belongs([S, [F_old,_,_], _, _], Pu),
%!,
update_trees(S, H, [F, G, Pere, Action], F_old, Pf, Pf1, Pu, Pu1),
loop_successors(Rest, Pere, Pf1, Pu1, Q, Pf_new, Pu_new),
!.
% Cas successeur inconnu : on l'ajoute à P
loop_successors([[S, [F, H, G], Action] | Rest], Pere, Pf, Pu, Q, Pf_new, Pu_new) :-
insert([S, [F, H, G], Pere, Action], Pu, Pu1),
insert([[F, H, G], S], Pf, Pf1),
loop_successors(Rest, Pere, Pf1, Pu1, Q, Pf_new, Pu_new).
%*******************************************************************************
% Mise à jour des coûts et des parents seulement si plus faible
update_trees(S, H, [F, G, Pere, Action], F_old, Pf, Pf2, Pu, Pu2) :-
(F_old is min(F, F_old) ->
Pf = Pf2,
Pu = Pu2
;
suppress([S,_,_,_], Pu, Pu1),
insert([S, [F, H, G], Pere, Action], Pu1, Pu2),
suppress([[F_old,_,_], S], Pf, Pf1),
insert([[F, H, G], S], Pf1, Pf2)
).