Ein Expertensystem ist im Prinzip eine Datenbank, die Fragen stellt und nach passenden Antworten weitere Fragen. Zum Schluss wird ein Datensatz ausgegeben, der zu der Antwortkette gehört. Wird auf eine Frage mit einer unbekannten Antwort reagiert, erfragt das System eine Anschlussfrage, alternativ den auszugebenden Datensatz. Die neue Frage bzw. der Datensatz werden gespeichert und in die nächste Fragenrunde integriert. Frage, Antwort und Nachfolgefrage werden wir zu einem Prädikat zusammen fassen.
Expertensysteme werden in der Medizin eingesetzt, um aus Symptomen eine Diagnose abzuleiten, oder auch in Werkstätten, um Fehler zu finden und die Möglichkeit, sie zu beheben. Die Anzahl der Antworten pro Frage ist nicht begrenzt!
Alternativ muss nach der Beantwortung einer Frage eine Nachfolgefrage oder ein (Diagnose-)Text ausgegeben werden. Im Programm lassen sich
Frage, Antwort und Nachfolgefrage/Diagnose durch eine Klausel dat mit drei Parametern darstellen. Soll statt einer neuen Nachfolgefrage eine
Diagnose erstellt werden, so antworte man anschließend nach Ausgabe der Diagnose als Frage mit #. Der Programmablauf ist dann:
Das Programm soll entsprechend aus drei Klauseln exp(F) bestehen, die als Parameter die Frage bzw. Diagnose übergeben. Nützlich ist eine vierte Klausel, über die das Programm gestartet wird und die die erste Frage stellt. Die Fragen müssen sich unterscheiden, damit das Programm sauber arbeitet.
Zum Einlesen von Texten verwenden wir das Prädikat readln(T). readln ewartet eine Texteingabe und teilt dann den Text in einzelne Atome auf, die die Variable T in Form einer Liste ersetzen.
Es muss geklärt werden, ob eine Klausel mit einer vorgegebenen Frage und Antwort existiert. Dazu kann man das Prädikat clause(A,B) verwenden.
In clause(K,R) ist K der Kopf eines Prädikats und R der Rumpf. clause(K,R) ist dann wahr, wenn es diese Kombination
von Kopf und Rumpf gibt. Alternativ kann K ein Fakt und R der Wert true sein. In diesem Fall testet das Programm, ob es einen Fakt
der vorgegebenen Form gibt. Sind in dem Fakt Atome durch Variablen ersetzt, so sucht clause passende Atome zu den Variablen, so dass ein
vorhandener Fakt entsteht:
|
clause(paar(berta,peter),true)
add(X,X+1).
clause(add(2,A),true) |
testet, ob es den Fakt paar(berta,peter) gibt
X wird ersetzt durch X+1 |
assert(kind(berta,paul,frieda)
Hinweis: Benutzt man assert usw. zur Definition einer Klausel, so müssen alle Klauseln des zugehörigen Prädikats über assert usw. definiert werden!
|
exp(F):-clause(dat(F,[#],_),true), write("Diagnose:"),write(F),nl. exp(F):-write(F),readln(A),clause(dat(F,A,Fn),true),exp(Fn). exp(F):-write("Antwort wiederholen oder #:"),readln(A), write("Neue Frage:"),readln(Fn),asserta(dat(F,A,Fn)),exp(Fn). anf:-exp([krank]). |
dat(F,[#]) suchen mit der Frage F und der Antwort #, bei Erfolg F als Diagnose
sonst Frage F, nach Antwort A dat(F,A,Fn) suchen, exp(Fn) aufrufen |
Es ist schon beeindruckend, dass man mit vier Klauseln ein Expertensystem programmieren kann. Allerdings ist die Ausgabe nicht sehr schön. Um das zu verbessern,
kann man ein neues Prädikat ausl definieren, das die Liste als Text ausgibt, wobei jeweils das Komma zwischen zwei Listenelementen durch ein Leerzeichen ersetzt wird:
|
ausl([]). ausl([A|R]):-write(A),write(' '),ausl(R). |
keine Aktion bei leerer Liste Liste in erstes Element A und Restliste R aufteilen, A ausgeben, Restliste mit ausl(R) ausgeben |
Ein Expertensystem führt nicht nur über Abfragen zur Diagnose, sondern kann bei vorgegebener Diagnose passende Fragen und Antworten suchen, also in der Medizin zu einer Diagnose zugehörige Symptome, die erfragt werden. Dies soll in einer Aufgabe geklärt werden.
Aufgabe: Zu einer Diagnose passende Fragen und Antworten finden und ausgeben.