Musterlösung Blatt 2, Aufgaben 2.1 a und 2.2 a

Aufgabe 2.1 a


% D aus ziffernliste ziehen falls D noch nicht gebunden, 
% (ggf.) verminderte Ziffernliste zurueckgeben 

% D schon gebunden: cut

bind(D, Avail, Avail) :- nonvar(D), !.

% D kann erste ziffer sein...

bind(D, [D|T], T), !.

% ...oder im rest

bind(D, [H|T1], [H|T2]) :- bind(D, T1, T2).


% sum/5: Eingabe Ziffernliste Summand 1, 
%   Eingabe Ziffernliste Summand 2, 
%   Rueckgabe Uebertrag, Rueckgabe Ziffernliste Summe,  
%   Rueckgabe noch verfuegbare Ziffern

% Rekursionsende: keine Ziffern uebrig. Uebertrag ist 0, 
% Summenliste is [], alle Ziffern verfuegbar 

sum([],[],0,[],[0,1,2,3,4,5,6,7,8,9]).

% Rekursion und dann fuehrende Ziffer unter beruecksichtigung
% der verfuegbaren Ziffern und des Uebertrages summieren

sum([H1|T1], [H2|T2], C, [H3|T3], Avail3) :-
  sum(T1, T2, CA, T3, Avail0), 
  bind(H1, Avail0, Avail1),
  bind(H2, Avail1, Avail2),
  bind(H3, Avail2, Avail3),
  H3 is (H1+H2+CA) mod 10,
  C is (H1+H2+CA) // 10.

% convenience-praedikat sum/3 auf sum/5 abbilden 

sum([H1|T1], [H2|T2], [H3|T3]) :- sum([H1|T1], [H2|T2], H3, T3, _),
 H1 =\= 0, H2 =\= 0, H3 =\= 0.

% sum([S,E,N,D],[M,O,R,E],M,[O,N,E,Y], AVAIL), M =\= 0, S =\=0.

Aufgabe 2.2 a

%%  Bibliotheken fuer Listenfunktionen und Negation:

:- ensure_loaded(library(basics)).
:- ensure_loaded(library(not)).

%%  Praedikat zum Starten des Suchprozesses, das den Start-Spielzustand
%%  auf den zugehoerigen Suchraumknoten abbildet, die Suche startet und
%%  die Anzahl der zum Erreichen des Ziels benoetigten Expansionen sowie
%%  den Suchraumknoten mit der Loesung liefert, der unter anderen den 
%%  Pfad der Spielzustaende zum Ziel sowie die Kosten dieses Pfades umfasst:
%%	start( Startzustand+, Expansionen-, Loesung- )

start(Startzustand,Expansionen,Loesung) :-
    suche([pfad(0,0,0,Startzustand,[])],[],0,Expansionen,Loesung).

%%  A*-Suche (und Bergsteigen durch Aendern einer Zeile in 'sortiere'):
%%	suche( Offen+, Geschlossen+, AnzahlBisherigerExpansionen+,
%%	       AnzahlExpansionenDerLoesung-, Loesung- )

suche([Aktuell|_],_Geschl,Expansionen,Expansionen,Aktuell) :- ziel(Aktuell).
    %%  Ende der Suche:  Ziel erreicht (aktueller gleich Ziel-Suchraumknoten)

suche([],_Geschl,Expansionen,Expansionen,[]).
    %%  Ende der Suche:  keine Loesung gefunden ('Offen' ist leer und Ziel
    %%			 nicht erreicht).

    %%  Expandierung des aktuell besten, noch offenen (Suchraum)Zustands
    %%  (= erstes Element in der 'Offen'-Liste):

suche([Aktuell|Offen],Geschl,Expansionen,ExpansionenErg,Loesung) :-
     write(Aktuell),nl,
    nachfolger(Aktuell,Geschl,Nachf),  %% Ermitteln aller noch zu 
				       %%   betrachtenden Nachfolger
    sortiere(Offen,Nachf,OffenNeu),  %% Aktualisiere sortiere die Vereinigung
				     %%   der Menge offener Knoten und der
				     %%   Menge der aktuellen Nachfolger
    ExpansionenNeu is Expansionen+1,
    suche(OffenNeu,[Aktuell|Geschl],ExpansionenNeu,ExpansionenErg,Loesung).

    %% Bestimme alle noch zu betrachtenden Nachfolger-Suchraum-Zustaende des
    %% Suchraum-Zustands mit dem Spielzustand K:

nachfolger(pfad(_,G,_,K,P),Geschl,Nachf) :-
    findall(pfad(F1,G1,H1,K1,[K|P]), %% Ermittle alle (Spielzustand-)Nachfolger
	(nachf(K,K1,Kosten),	     %%   K1 von K mit realen Kosten des 
				     %%   Wegs zu ihnen
	 bewerte(K1,H1),	     %% Schaetze Restkosten von K1 aus
				     %%   entsprechend aktueller Heuristik
	 G1 is G+Kosten,	     %% Berechne neue reale Kosten
	 F1 is G1+H1,		     %% Berechne geschaetzte Gesamtkosten
	 \+ (member(pfad(_,G2,_,K1,_),Geschl),  %% betrachte noch nicht
	     G1 >= G2)),			%%   geschlossene Nachfolger
	Nachf).					%%   sowie auch geschlossene, 
						%%   wenn sie jetzt mit
						%%   kuerzerem realen Weg
						%%   erreichbar sind

%%  Sortierte (Nachfolger)Liste:  eine Zeile fuer den A*-Algorithmus
%%  (Aufgabe 1.1) und eine Zeile fuer das Bergsteigen (Aufgabe 1.2), 
%%  d.h. die jeweils andere ist auszukommentieren;
%%  die dritte Klausel ist beiden gemein:
%%	sortiere( Offen+, Nachfolger+, OffenNeu- )
%%% A*-Algorithmus

 best(Offen,Best,Restoffen):-
      sort(Offen,[Best | Restoffen]).

%%% Bergsteigen
%%% (nur aktuell bestes Element behalten, den Rest verwerfen)
%best(Offen,Best,[]):-
%     sort(Offen,[Best|_]).


%%% Entferne alten Suchraumknoten mit groesseren realen Kosten fuer den
%%% aktuellen Spielraumknoten.
%%% sortiere(+Offen,+Nachfolger,-OffenNeu)

sortiere(Offen,[],[Best | Restoffen]) :- best(Offen,Best,Restoffen).


sortiere(Offen,[pfad(F,G,H,K,P)|Nachf],OffenNeu) :-   %% BEIDE Verfahren
    (  (member(pfad(FAlt,GAlt,HAlt,K,PAlt),Offen), 
        G < GAlt )=")" -="-"> %% IF
           (append(Vor,[pfad(FAlt,GAlt,HAlt,K,PAlt)|Nach],Offen), %% THEN
            append(Vor,Nach,Offen2)
           )
        ;     
        Offen2 = Offen  %% ELSE
    ),           
    sortiere([pfad(F,G,H,K,P)|Offen2],Nachf,OffenNeu).


%     %% Abbildung Problemraum-Zielzustand <-> Spiel-Zielzustand

ziel(pfad(_,_,_,K,_)) :- zielzustand(K).

:-ensure_loaded(library(math)).


%%%%%%%%%%%%%%%%% Modellierung %%%%%%%%%%

% Repraesentation: Liste aus Zeilenindex der
% Leerstelle und drei Unterlisten fuer die
% drei Zeilen, siehe Start-/Zielzustand

% Verschiebungen in einer Zeile

horiz([0, A, B], [A, 0, B]).
horiz([A, 0, B], [0, A, B]).
horiz([A, 0, B], [A, B, 0]).
horiz([A, B, 0], [A, 0, B]).

% Vertikale verschiebungen (2 Zeilen eingabe, 2 Zeilen ausgabe)

vert([0, B, C], [D, E, F], [D, B, C], [0, E, F]).
vert([A, 0, C], [D, E, F], [A, E, C], [D, 0, F]).
vert([A, B, 0], [D, E, F], [A, B, F], [D, E, 0]).

% nachfolgezustaende (horizontale versch.)

nachf([1, A, B, C], [1, X, B, C], 1) :- horiz(A, X).
nachf([2, A, B, C], [2, A, X, C], 1) :- horiz(B, X).
nachf([3, A, B, C], [3, A, B, X], 1) :- horiz(C, X).

% nachfolgezustaende (vertikale versch.)

nachf([1, A1, B1, C], [2, A2, B2, C], 1) :- vert(A1, B1, A2, B2).
nachf([2, A, B1, C1], [3, A, B2, C2], 1) :- vert(B1, C1, B2, C2).

nachf([3, A, B1, C1], [2, A, B2, C2], 1) :- vert(C1, B1, C2, B2). 
nachf([2, A1, B1, C], [1, A2, B2, C], 1) :- vert(B1, A1, B2, A2). 

% startzustand

startzustand([3, [2, 8, 3], [1, 6, 4], [7, 5, 0]]).
zielzustand([2, [1, 2, 3], [8, 0, 4], [7, 6, 5]]).

% h=0

bewerte(_,0).

% start(X, E, L), startzustand(X), zielzustand(L).