Integration des JEFIS Projekts in die Drools - Lab4Inf

Transcrição

Integration des JEFIS Projekts in die Drools - Lab4Inf
Fuzzylogik und Regelbasierte Systeme
Ausarbeitung für das Masterprojekt:
Thomas Beermann
Dennis Huning
Dennis Löhr
Inhaltsverzeichnis
I.
Übersicht
2
Autor: Dennis Löhr, B.Sc.
1. Übersicht
1.1. Einleitung . . . . . . . . . . . . . . . . .
1.2. Fuzzy-Logik . . . . . . . . . . . . . . . .
1.2.1. Klassische Logik vs. Fuzzy-Logik
1.2.2. Fuzzysets . . . . . . . . . . . . .
1.2.3. Fuzzifizierung . . . . . . . . . . .
1.2.4. Defuzzifizierung . . . . . . . . . .
1.2.5. Fuzzy Operatoren . . . . . . . .
1.2.6. Fuzzy-Controlling . . . . . . . .
1.2.6.1. Einleitung . . . . . . .
1.2.6.2. Implikation . . . . . . .
1.2.6.3. Anwendungen . . . . .
1.3. Regelbasierte Systeme . . . . . . . . . .
1.3.1. Einleitung . . . . . . . . . . . . .
1.3.2. Die Regelbasis . . . . . . . . . .
1.3.3. Die Faktenbasis . . . . . . . . . .
1.3.4. Inferenzmaschine . . . . . . . . .
1.3.4.1. Vorwärtsverkettung . .
1.3.4.2. Rückwärtsverkettung .
1.3.5. Zusammenfassung . . . . . . . .
1.3.6. Herkunft . . . . . . . . . . . . .
1.4. Jefis . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
3
3
4
4
4
5
6
6
7
7
9
9
10
11
11
11
12
12
12
13
II. Jefis Drools Adapter
14
Autor: Dennis Huning, B.Sc.
2. Jefis Drools Adapter
2.1. Einleitung . . . . . . . . . . . . . . . . . . . . . .
2.2. Der Rete-OO Algorithmus . . . . . . . . . . . . .
2.2.1. Überblick . . . . . . . . . . . . . . . . . .
2.2.2. Erzeugen eines deterministischen Baumes
ii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
15
15
15
15
Inhaltsverzeichnis
2.2.3. Laufzeit Ausführung . . . . . .
2.2.4. Beispiel eines Baumes . . . . .
2.3. Erweiterung des Rete-OO Algorithmus
2.4. Drools Chance . . . . . . . . . . . . .
2.5. Adapter . . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
um Fuzzy
. . . . . .
. . . . . .
. . . .
. . . .
Logik
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
16
17
18
19
19
III. Jefis Ruleengine
22
Autor: Dennis Löhr, B.Sc.
3. Jefis Ruleengine
3.1. Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Beispiel in Lab4Jefis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3. Die Lab4Jefis Rule-Engine . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
23
23
24
IV. FCL und ANTLR
27
Autor: Thomas Beermann, B.Sc.
4. FCL und ANTLR
4.1. FCL . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1. Einleitung . . . . . . . . . . . . . . . . . .
4.1.2. Beispiel . . . . . . . . . . . . . . . . . . .
4.1.3. Beschreibung . . . . . . . . . . . . . . . .
4.1.3.1. VAR INPUT / VAR OUTPUT
4.1.3.2. FUZZIFY / DEFUZZIFY . . . .
4.1.3.3. RULEBLOCK . . . . . . . . . .
4.2. ANTLR . . . . . . . . . . . . . . . . . . . . . . .
4.2.1. Einleitung . . . . . . . . . . . . . . . . . .
4.2.2. Lexer/Parser . . . . . . . . . . . . . . . .
4.2.3. Beispiel . . . . . . . . . . . . . . . . . . .
4.2.4. Benutzung in Java . . . . . . . . . . . . .
4.2.5. Treewalker . . . . . . . . . . . . . . . . .
4.2.6. Beispiel . . . . . . . . . . . . . . . . . . .
V. Anhang
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
28
28
28
28
30
30
30
31
32
32
32
33
36
36
37
38
5. ANTLR
39
A. Fcl.g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
B. FCLTreeWalker.g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6. Jefis Ruleengine
45
Abbildungsverzeichnis
46
iii
Inhaltsverzeichnis
Literaturverzeichnis
47
iv
Einleitung
Diese Ausarbeitung dokumentiert das Masterprojekt 2009/2010 im Labor für Informatik
an der Fachhochschule Münster - Fachbereich Elektrotechnik und Informatik. Thema des
Masterprojektes war es Fuzzy-Logik und klassische Regelbasierte Systeme zu verbinden.
Das Kapitel 1 beschreibt dafür die Grundlagen im Bereich Fuzzy-Logik und Regelbasierte Systeme, die für das Verständnis der Ausarbeitung erforderlich sind.
Nachfolgend stellt das Kapitel 2 den ersten Teil bzw. das erste Semester des Masterprojektes dar. Hierbei geht es hauptsächlich um die Fuzzy-Erweiterung von drools:chance,
das ein Unterprojekt von Drools 1 ist.
Im Weiteren wird das zweite Semester geschildert. Nach dem Abschluss des drools:chance
Projektes wurde das Projekt Jefis um Ruleengine Funktionalitäten erweitert. Das Kapitel 3 beschreibt, wie die Ruleengine für Jefis implementiert wurde und gibt zum Schluss
noch ein ausführliches Beispiel für die Benutzung.
Ein wichtiger Bestandteil der Ruleengine ist es Regeln und Fuzzysets aus einer Datei
auslesen zu lassen. Dafür war es notwendig eine einheitliche Form zu bestimmen, die in
der Fuzzy Control Language (FCL) gefunden wurde, beschrieben in Kapitel 4.1. Zuletzt
bestand dann noch das Problem diese FCL-Dateien mit Java auszulesen und in JefisObjekte umzuwandeln. Aus verschiedenen Gründen, erläutert in Kapitel 4.2, wurde dafür
ANTLR genommen.
1
http://www.jboss.org/drools
1
Teil I.
Übersicht
Autor: Dennis Löhr, B.Sc.
2
1. Übersicht
1.1. Einleitung
Dieses Kapitel gibt eine Übersicht über die notwendigen Grundlagen um den weiteren Teil der Ausarbeitung nachzuvollziehen. Es werden grundlegende Aspekte von Fuzzy erklärt, wie beispielsweise Fuzzysets, Fuzzifizierung oder Fuzzy-Operatoren. Im Abschnitt Regelbasierte Systeme werden Themen wie Faktenbasis, Inferenzmaschinen und
Vorwärtsverkettung erläutert. Abschließend gibt der Abschnitt Jefis einen Überblick
über das im Labor für Informatik der FH-Münster entstandene gleichnamige Projekt.
1.2. Fuzzy-Logik
1.2.1. Klassische Logik vs. Fuzzy-Logik
In der klassischen Logik kann ein Element x ∈ X entweder einer bestimmten Menge
A zugeordnet werden oder nicht. Schnell ist ersichtlich, dass es in vielen Fällen einer
weicheren Betrachtung bedarf. Als Beispiel sei hier eine Regel zur Lüftersteuerung genannt, die Regel besagt, dass die Kühlung ab einer Temperatur größer 80◦ C angeschaltet
wird. Eine minimale Abweichung um -0,0001◦ von der kritischen Temperatur würde in
der klassischen Logik nicht zum Einschalten der Kühlung führen. Wodurch es in diesem
Beispiel zu einer unnötig langen thermischen Überstrapazierung der CPU und daraus
resultierend zu einer schnelleren Alterung kommt.
Ein anderes Systemverhalten ist in der klassischen Logik nicht möglich, da für die Indikatorfunktion oder Charakteristische Funktion χA der Menge A gilt:
χA : X → {0, 1}
1:x∈A
χA (x) =
0:x∈
/A
Um eine solche Einschränkung zu umgehen, erweitert die Fuzzy-Logik die zweielementige
Menge {0, 1} auf das abgeschlossene Intervall I:= [0, 1]. Die so entstehende Lösungsmenge
à wird als Fuzzy-Menge bezeichnet und besteht aus geordneten Paaren der Form:
à = {(x, µ (x)) ∧ x ∈ X}
Ã
Durch µ ist auf dieser Menge eine Funktion definiert, die den Grad angibt, zu dem ein Element x ∈ X in der Menge à enthalten ist. Die Funktion µ wird als Zugehörigkeitsfunktion
bezeichnet.
3
KAPITEL 1. ÜBERSICHT
Abbildung 1.1.: Beispiel Fuzzy Partition für einen Wertebereich von 0 bis 80
1.2.2. Fuzzysets
Damit die Zugehörigkeitsfunktion überhaupt den Wert der Zugehörigkeit ermitteln kann,
muss über der Menge à eine beliebige Funktion beschrieben werden. Eine solche Funktion wird als Fuzzyset bezeichnet. Mehrere Fuzzysets werden zu einer Fuzzy Partition
zusammengefasst.
In der Abbildung 1.1 wird eine Beispiel Partition mit drei Fuzzysets gezeigt. Wie das
Beispiel zeigt können beliebige Funktionen genutzt werden um ein Fuzzyset zu beschreiben. Zusätzlich sieht man, dass ein Wert mehrere Zugehörigkeitswerte haben kann, z.B.
für den Wert 45 liefert µ(45) = {0, 0.7, 0.5}. Das bedeutet, dass der Eingabewert von
45 zu 0% im ersten Fuzzyset, zu 70% im Fuzzyset zwei und zu 50% im dritten Fuzzyset
liegt.
1.2.3. Fuzzifizierung
Bei der Fuzzifizierung wird für einen scharfen Wert in einem dazugehörigen Fuzzyset
die Zugehörigkeit ermittelt, dafür wird aber erstmal ein Eingabe-Fuzzyset benötigt. In
diesem Fuzzyset wird der Zugehörigkeitsgrad wie in Abbildung 1.1 bestimmt. Hierbei
wird von der X-Achse bei dem scharfen Wert senkrecht bis zu dem Fuzzyset gegangen
und dann die Zugehörigkeit auf der Y-Achse abgelesen. Hierbei können verschiedene
Verfahren benutzt werden um dies dann in ein Eingabe-Fuzzyset umzuwandeln. Eines
dieser Verfahren funktioniert so: Das betreffende Eingabe Fuzzyset dadurch gebildet
wird, dass das zugehörige Fuzzyset bis zur Zugehörigkeit gefüllt wird. Bei einem weiterem
Verfahren wird das zugehörige Fuzzyset mit der Zugehörigkeit Multipliziert. Es gibt noch
andere Verfahren die hier allerdings nicht weiter beschrieben werden.
1.2.4. Defuzzifizierung
Für die Defuzzifizierung gibt es auch mehrere Methoden dies zu machen die wohl am
weitesten verbreitete Methode ist die Schwerpunktmethode (center of gravity). Die Defuzzifizierung eines Sets sehen wir in Abbildung 1.2. In diesem Beispiel wurde die Schwerpunktmethode verwendet, durch die Verteilung und den Füllstand der Sets ergibt sich
der Schwerpunkt bei 28,57%. Zusätzlich zu dieser gibt es auch noch die Maximum Methode, hierbei wird das Maximum innerhalb des Fuzzysets gesucht und als defuzzifizierter
Wert zurückgegeben. Dabei gibt es drei Methoden:
4
KAPITEL 1. ÜBERSICHT
Abbildung 1.2.: Beispiel Defuzzifizierung über die Schwerpunktmethode
x
0
0
1
1
y
0
1
0
1
x∧y
0
0
0
1
x∨y
0
1
1
1
1
¬x
1
1
0
0
Tabelle 1.1.: Wahrheitstabelle der klassischen Logik
1. Linkes Maximum - hier wird von links das Maximum gesucht.
2. Rechtes Maximum - hier wird von rechts das Maximum gesucht.
3. Mittleres Maximum - hier wird erst das linke und das rechte Maximum gesucht
und anschließend der Mittelwert gebildet.
1.2.5. Fuzzy Operatoren
In der klassischen Logik ist es möglich mehrere Elemente verschiedener Mengen über
die Operatoren ∨, ∧ und ¬“, zu verknüpfen (Tabelle 1.1). Da die Fuzzy-Logik nicht
”
aus einer endlichen Mengen von Möglichkeiten besteht wird schnell ersichtlich, dass man
die Operatoren nicht eins zu eins auf die Fuzzy-Logik überführen kann. Daher müssen
spezielle Operatoren eingeführt werden, die die gleichen Ergebnisse wie in Tabelle 1.1
liefern.
Eine Lösung dieses Problems ist es die Operatoren durch die in Tabelle 1.2 gezeigten
Funktionen zu ersetzen. Die sich dadurch ergebene Wahrheitstabelle wird in Tabelle 1.3
gezeigte. Wie man leicht erkennen kann, liefern die Funktionen für die Grenzwerte 0 und
1 die gleichen Ergebnisse. Diese Norm wird auch MINMAX-Norm genannt.
1
Quelle der Graphik ist das Labor für Prozessinformatik und Prozesslenkung, FH-Münster - Fachbereich
Elektrotechnik und Informatik
5
KAPITEL 1. ÜBERSICHT
x∧y
x∨y
¬x
min(x,y)
max(x,y)
1-x
t-Norm
s-Norm
c-Norm
Tabelle 1.2.: Abbilden der Operationen auf Funktionen
x
0
0
1
1
0.2
0.7
0.6
y
0
1
0
1
0.5
0.2
0.6
min(x,y)
0
0
0
1
0.2
0.2
0.6
max(x,y)
0
1
1
1
0.5
0.7
0.6
1-x
1
1
0
0
0.8
0.3
0.4
Tabelle 1.3.: Wahrheitstabelle der Fuzzy-Logik
1.2.6. Fuzzy-Controlling
1.2.6.1. Einleitung
Fuzzy-Controlling wird in der Elektrotechnik seit den 1970er Jahren eingesetzt. Zu Beginn aber fast ausschließlich im asiatischen Raum. In der Elektrotechnik werden FuzzyController als Regler eingesetzt, wobei diese genauso wie andere Regler auch mit scharfen
Eingabewerten versorgt werden.
Abbildung 1.3.: Beispiel Fuzzy-Regler in einem Schaltbild
Aber anders als bei anderen Reglern fuzzifiziert der Fuzzy-Regler die Eingabewerte
bevor er mit den Daten arbeitet. Wenn die Eingabedaten dann für den Fuzzy-Regler
aufbereitet wurden, verarbeitet der Regler die Eingaben mit seinen Regeln. Nachdem
die internen Regeln des Fuzzy-Reglers dann abgearbeitet sind, werden die Ausgabewerte defuzzifiziert. Das Defuzzifizieren wird gemacht um wieder scharfe Werte für z.B.
eine Motorsteuerung zu erhalten. Auch beim Fuzzy-Controlling ist es möglich FuzzyRegler zu verketten, um so eine Hintereinanderausführung von verschiedenen Regeln zu
ermöglichen. Das wird allerdings in der Praxis nicht gemacht da dies nur die Komplexität
des Systems unnötig steigern würde.
6
KAPITEL 1. ÜBERSICHT
1.2.6.2. Implikation
Die Implikation ist der Kernbestandteil des Systems, hier gibt es eine Vielzahl an verschiedenen Verfahren. Einige dieser Verfahren sind Goedel,Lucasiewicz oder Zadeh, in
technischen Systemen wird aber meist nur Larsen oder Mamdani eingesetzt. Wobei die
Mamdani Implikation die am meisten genutzte in der Elektrotechnik ist.
Allgemein beschrieben wird bei der Implikation bestimmt, zu welchem Anteil die einzelnen Werte innerhalb eines Fuzzysets erfüllt sind. Bei der Mamdani Implikation
µA⇒B (x, y) := min{µA (x), µB (x)}
wird beispielsweise ein Wert innerhalb eines Fuzzysets bis zum Maximum der Schnittmenge gefüllt.
1.2.6.3. Anwendungen
In der Elektrotechnik werden Fuzzy-Systeme mit den folgenden Vor- bzw. Nachteilen
beschrieben. Vorteile sind, dass Lösungen auch möglich sind, wenn
• Kein in sich geschlossenes mathematisches Modell des Prozesses, z.B. in Form
von Differentialgleichungen, existiert oder gefunden werden kann, oder wenn die
Komplexität des Problems für eine solche Modellierung zu groß ist.
• Unscharfe und vage Aussagen oder intuitive Einschätzungen zur Modellierung des
Sachverhalts herangezogen werden müssen.
• Viele Eingangsparameter und hohe Nichtlinearität vorliegen.
Nachteile sind:
• Die Beliebigkeit bzw. die Freiheit, die der Entwickler bei der Wahl und Implementierung des Fuzzy-Modells hat. Es existieren keine standardisierten Vorgehensweisen, um Erfahrungswissen in die Daten- und Regelbasis eines Fuzzy-Systems
umzusetzen.
• Die Beliebigkeit bzw. die Freiheit, die der Entwickler bei der Modifizierung eines
Fuzzy-Modells zur Feinabstimmung oder Ergebnisverbesserung hat. Hierzu existieren ebenfalls keine standardisierten Methoden. Die Anpassung eines Fuzzy-Modells
an veränderte Parameter kann daher schwierig und zeitaufwendig werden oder auch
scheitern.
• Fuzzy-Systeme besitzen keine Lernfähigkeit, die Regeln und Zugehörigkeitsfunktionen müssen vom Entwickler entworfen und optimiert werden.
[Nel05]
Auch bei Systemen bei denen man annehmen würde, dass dort besonders auf eine
mathematische Beweisbarkeit geachtet wird gibt es Gegenbeispiele. Eines dieser Gegenbeispiele ist ein Raketen Zielsystem. In der Diplomarbeit von Alfons Möllers2 wurde ein
2
Quelle für das Beispiel ist die Diplomarbeit von Alfons Möllers an der FH Münster aus dem Jahr 1995
7
KAPITEL 1. ÜBERSICHT
Abbildung 1.4.: Flugbahn und Geschwindigkeitskorrektur über Fuzzy
Abbildung 1.5.: Schaltplan der Flugbahn und Geschwindigkeitskorrektur
Problem beschrieben bei dem Es die Aufgabe war ein System zu entwerfen, dass die
Geschwindigkeit eines Flugobjekts so anpasst das dieses zum richtigen Zeitpunkt am
Ziel ankommt. Hierbei muss man jedoch erwähnen das durch einen Fuzzy-Regler nur
Korrekturwerte an die eigentliche Flugkontrolle geliefert werden und nicht das ganze
System auf Fuzzy-Controlling basiert.
Ein weiteres Beispiel ist das inverse Pendel3 . In einem Versuchsaufbau an der Fachhochschule Münster ist es sogar möglich, ein gefülltes Bierglas auf das inverse Pendel zu
stellen, wie in Abbildung 1.6 zu sehen ist.
Beim Versuchsaufbau wird an einem beweglichen Schlitten über ein Kugellager eine
Stange befestigt. Ziel des Systems ist es die Stange in eine aufrechte Position zu bekommen. Dies gilt als schönes Beispiel, denn über eine normale Regelung ist es nicht möglich
den gesamten Vorgang in einen Regler abzubilden. Da es sich bei Normalen Regler meist
um lineare Systeme handelt. Wenn dieses Problem versucht wird über normale Regler
3
Quelle für das Beispiel ist die Diplomarbeit von Stefan Tombrock an der FH Münster aus dem Jahr
1996
8
KAPITEL 1. ÜBERSICHT
zu lösen, ist hierfür notwendig das die zugehörigen Differentialgleichungen für viele Positionen linearisiert wird. Durch den Einsatz von einem Fuzzy-Regler ist es möglich, das
Ganze in einem Regler zu implementieren. Eine Lösung hierfür ist das Aufstellen der
Regeln die in Abbildung 1.7 zu sehen sind, zusammen mit den Fuzzysets aus Abbildung
1.6.
Abbildung 1.6.: Bierglas auf Inversen Pendel; Fuzzysets des Beispiels
Abbildung 1.7.: Regeln des Inversen Pendels
1.3. Regelbasierte Systeme
1.3.1. Einleitung
Ein Regelbasiertes System besteht aus einer Faktenbasis, einer Regelbasis und einer
Inferenzmaschine. Hierbei stellt die Inferenzmaschine den Kern des Systems dar, da
9
KAPITEL 1. ÜBERSICHT
die Inferenzmaschine aus den in der Regelbasis enthaltenen Regeln zusammen mit den
gegebenen Fakten Schlussfolgerungen bildet. Hierbei wird beispielsweise aus dem Fakt,
dass es gerade regnet gefolgert, dass die Straßen nass sind. Was im weiteren Verlauf noch
genauer erklärt wird.
Abbildung 1.8.: Komponenten eines Regelbasierten Systems [Bec]
1.3.2. Die Regelbasis
ist eine Sammlung von Wissen. Diese Regeln sind folgendermaßen aufgebaut:
WENN (Prämisse / Voraussetzung)
DANN (Konklusion durch eine Aktion).
Sollte das Wissen nicht in dieser Form vorliegen so muss es umgeformt werden, dies
wird beispielsweise aus dem Wissen Alle Vögel können fliegen“ =⇒ Wenn ein Tier ein
”
”
Vogel ist, dann kann es fliegen“. Diese Regeln werden aber nicht einfach fest integriert,
sondern dynamisch hinzugefügt. Dadurch ist es möglich das System auf viele spezielle
Anwendungsgebiete anzupassen oder das System an sich ändernde Anforderungen anzupassen. Dies ist auch notwendig, denn einer IDC-Studie zufolge ändern sich ca. 45%
aller Regeln in einem Release-Zyklus [DWM08].
Aktuelle Beispiele für Systeme bzw. Notationen, mit denen Regeln erstellt werden
können sind: JBOSS-Rules, Ross-Notation, AORML - Agent Object Relationship Modeling Language , ORM - Objekt Role Modeling Language und URML - UML-Based
Rule Modeling Language. [Dre].
10
KAPITEL 1. ÜBERSICHT
1.3.3. Die Faktenbasis
setzt sich aus allen bekannten Fakten zusammen. Hierbei kann es sich sowohl um Messwerte, Symptome oder auch um Ergebnisse aus vorherigen Berechnungen handeln. Zu
dem gibt es auch Regelsysteme die gezielt Fragen stellen, um beispielsweise medizinische
Diagnosen zu stellen. Ein Beispiel ist hierfür das medizinische Diagnosesystem MYCIN.
MYCIN ist in den 70er Jahren als ein Konsultationssystem zur Diagnose und Therapie
von Infektionskrankheiten durch Antibiotika entwickelt worden. [Bei06]
Durch die Trennung des Wissens, was in den Regeln definiert ist und dem Verarbeiten
des Wissens in der Inferenzmaschine werden einige Eigenschaften von Regelbasierten
Systemen begründet. Folgende Eigenschaften von Regelsystemen stammen von Torben
Pullmann [Pul00]
• Transparenz: Aufgrund der transparenten Wissensrepräsentation kann das Verhalten von wissensbasierten Systemen in einfacher Weise erklärt und vorhergesagt
werden.
• Flexibilität: Wissen kann in einfacher Weise hinzugefügt und entfernt werden.
• Benutzerfreundlichkeit: Der Umgang mit wissensbasierten Systemen erfordert kein
programmiertechnisches Vorwissen.
• Kompetenz: Wissensbasierte Systeme verfügen in ihrem Anwendungsbereich über
eine hohe Problemlösungsfähigkeit.
1.3.4. Inferenzmaschine
Für die Inferenzmaschine selbst gibt es zwei grundsätzliche Vorgehensweisen, die Vorwärtsverkettung und die Rückwärtsverkettung. Bei der Vorwärtsverkettung wird versucht aus den vorhandenen Informationen, durch die Auswertung neue Informationen
zu generieren. Das Verfahren wird auch in Abbildung 1.8 verwendet. Ein Beispiel für
dieses Verfahren ist. Aus den Regeln:
1. Wenn man viel Schokolade isst, dann nimmt man viele Kalorien auf.
2. Wenn man viele Kalorien aufnimmt, dann wird man dick.
Wenn jetzt bekannt ist, dass jemand viele Kalorien zu sich nimmt, folgern wir aus der
zweiten Regel, dass diese Person dick ist. Dies ist die einfache Inferenz, da hier noch
nicht das Ergebnis einer anderen Regel ausgewertet wird.
1.3.4.1. Vorwärtsverkettung
Wenn aber die Inferenzmaschine die Vorwärtsverkettung verwendet, brauch nur bekannt
sein, dass eine Person viel Schokolade isst. So können wir daraus folgern, dass diese Person viele Kalorien zu sich nimmt und daraus wieder das diese Person dick ist. Dieses
Verfahren hat aber einen Nachteil, um beispielsweise einen bestimmten angestrebten
Zustand zu erreichen, müssten bei der Vorwärtsverkettung alle Möglichkeiten der Faktenbasis durchgegangen werden.
11
KAPITEL 1. ÜBERSICHT
1.3.4.2. Rückwärtsverkettung
Dies wird von der Rückwärtsverkettung besser behandelt. Haben wir wieder die vorherige
Regel gegeben und der Zustand den wir anstreben ist es herauszufinden, warum eine
bestimmte Person übergewichtig ist, so können wir unsere Regeln auswerten, die das
gewünschte Ergebnis haben. In diesem Fall wäre das die zweite Regel, die besagt Wenn
”
eine Person viele Kalorien zu sich nimmt, dann wird sie dick“. Aber das ist nicht die
einzige Möglichkeit, sondern wir haben noch die Regeln, die die Prämisse der zweiten
Regel als Konklusion haben, was bei der ersten Regel gegeben ist. Daraus ergibt sich
das Ergebnis mit dieser Regelbasis, dass eine Person dick ist, wenn sie viele Kalorien zu
sich nimmt oder viel Schokolade isst.
1.3.5. Zusammenfassung
Zusammengefasst bezeichnet der Begriff der Inferenz das Gewinnen von neuen Fakten
aus alten Fakten. Um die Faktenbasis zu erweitern und noch mehr Fakten zu erzeugen.
Um eine Schleifenbildung zu verhindern, die im Normalfall auftreten würde, wird ein
Beispiel gegeben. Als Regeln gelten wieder die beiden bekannten:
1. Wenn man viel Schokolade isst, dann nimmt man viele Kalorien auf.
2. Wenn man viele Kalorien aufnimmt, dann wird man dick.
Wenn in diesem Fall die Faktenbasis den Input bekommt, dass jemand viel Schokolade
isst, generiert die erste Regel daraus, dass diese Person viele Kalorien zu sich nimmt.
Für die nächste Iteration haben wir also in der Faktenbasis das Wissen, dass eine Person
viel Schokolade isst und viele Kalorien zu sich nimmt, damit können wir jetzt beide
Regeln wieder ausführen. Damit würde also eine Endlosschleife laufen, da kein Wissen
aus der Faktenbasis entfernt wird. Aus diesem Grund wird bei einer Inferenzmaschine
noch eine Konfliktmenge gebildet. Die Konfliktmenge stellt die aktiven Regeln dar, an
dem Beispiel erklärt heißt das für die Faktenbasis und die Konfliktmenge, dass sie leer
sind. Geben wir nun zur Faktenbasis die Information hinzu, dass jemand viel Schokolade
isst, so werden der Konfliktmenge auch alle Regeln hinzugefügt, die von der aktuellen
Faktenbasis bedient werden können. Nachdem dann die Regeln aus der Konfliktmenge
gefeuert wurden, werden die neu gewonnenen Informationen der Faktenbasis hinzugefügt.
Dabei werden alle vorherigen aktiven Regeln aus der Konfliktmenge entfernt und im
Anschluss die Regeln hinzugefügt die durch die neuen Informationen gefeuert werden
können. Damit würde also nach der ersten Iteration bzw. dem Ausführen der ersten Regel
nur die zweite Regel in der Konfliktmenge enthalten sein, wodurch wir das Problem der
Endlosschleife für dieses einfache Beispiel gelöst haben.
1.3.6. Herkunft
Als Geburtsstunde der künstlichen Intelligenz wird ein Workshop in Dartmouth im Sommer des Jahres 1956 angesehen, der von John McCarthy, Marvin Minsky, Nathan Rochester und Claude Shannon organisiert wurde. Durch diesen Workshop hat sich auch
12
KAPITEL 1. ÜBERSICHT
der englische Name artificial intelligence” durchgesetzt. Vor diesem Workshop wurden
”
Computer nur als arithmetische Rechenmaschinen angesehen. Nach diesem Workshop
aber haben die Teilnehmer, an verschiedenen Einrichtungen, versucht dem Computer mit
Wissen über einzelne Fachgebiete zu versehen, woraus auch die Regelbasierten Systeme
entstanden. Das erste System, das erfolgreich intensiv Wissen in der Form einer großen
Anzahl von Regeln aus einem spezifischen Anwendungsbereich einsetze, war DENDRAL.
Das DENDRAL Projekt wurde in den 1960er Jahren gestartet und interpretiert Auswertungen von Massenspektrometern. [Bei06]
1.4. Jefis
Jefis (Java Expert Fuzzy Inference System) ist ein Projekt der FH-Münster 4 . Das
Projekt beschäftigt sich mit Fuzzylogic. Wie in Abbildung 1.9 zu sehen ist, ist das
Fuzzyset einer der zentralen Bestandteile des Systems. Es unterstützt eine Vielzahl von
verschiedenen Implikationen wie beispielsweise Goedel, Lucasiewicz, Larsen, Mamdani
und noch einige mehr. Diese Vielfalt setzt sich bei den Normen fort, hier gibt es die
Normen Algebraic, Bounded oder MinMax um nur einige zu nennen. Des Weiteren sind
Elemente zur Visualisierung enthalten mit denen sich Beispiel Applets in kurzer Zeit
erstellen lassen. Ein Beispiel für die Visualisierung lässt sich in Abbildung 3.1 finden.
Abbildung 1.9.: UML Diagramm der wichtigsten Jefis Klassen [NW09]
4
Jefis ist ein Projekt des Labor für Informatik das zu finden ist unter http://www.lab4inf.fh-muenster.de
13
Teil II.
Jefis Drools Adapter
Autor: Dennis Huning, B.Sc.
14
2. Jefis Drools Adapter
2.1. Einleitung
Das erste Kapitel hat einen Überblick über die grundlegenden Themen des folgendem
Kapitels gegeben. In diesem Kapitel wird kurz der Rete-OO Algorithmus angeschnitten,
da dieser in JBoss Drools verwendet wird und alle folgenden Abschnitte in diesem Kapitel
auf diesem Projekt basieren. Anschließend wird auf die Kombination von Regelbasierten
Systemen und Fuzzy eingegangen, im Speziellen auf die Arbeit von Davide Sottara 2.3
und den im Masterprojekt 2009/10 entstandenen Adapter des Jefis-Projektes 2.5.
2.2. Der Rete-OO Algorithmus
2.2.1. Überblick
Der Rete-OO ist eine für objektorientierte Systeme optimierte Version des Rete Pattern
Matching Algorithmus und wird in der Business-Rule-Engine JBoss Drools eingesetzt.
Erfunden wurde der Rete Algorithmus von Dr. Charles Forgy. Der eigentliche Algorithmus kann in zwei Aufgaben aufgeteilt werden:
• Erzeugen eines deterministischen Baumes
• Laufzeit Ausführung
2.2.2. Erzeugen eines deterministischen Baumes
Während der ersten Ausführungsphase wird aus den Bedingungen der LHS aller Regeln eine Baumstruktur erzeugt, dabei entspricht jeder Knoten einer Teilbedingung
(Prämisse). Die LHS einer speziellen Regel ergibt sich aus der Verknüpfung einzelner
Pfade. Zusätzlich werden gleiche Bedingungsteile von unterschiedlichen Knoten geteilt.
In der Literatur wird vom Nodesharing gesprochen. Rete-OO kennt insgesamt die acht
in der Abbildung 2.1 gezeigten Knoten.
In jedem Baum ist der erste Knoten der ReteNode. Dieser Knoten errechnet für jedes Objekt, das zum WorkingMemory hinzugefügt wird, den zugehörigen Hashwert und
speichert diesen. Durch diese Maßnahme wird sichergestellt, dass kein gleiches Faktum
zweimal den Baum durchläuft. In der zweiten Ebene befinden sich die ObjectTypeNodes
die eine instanceof -Prüfung durchführen. Somit kann jeder Pfad nur von dem Faktum
durchlaufen werden an dem eine objektspezifische Prüfung erfolgreich durchgeführt werden kann.
AlphaNodes führen eine atomare Überprüfung an einer Membervariable durch. Trifft
15
KAPITEL 2. JEFIS DROOLS ADAPTER
Abbildung 2.1.: Auflistung der unterschiedlichen Rete-OO Knoten
die abgefragte Bedingung zu, wird das Faktum im sogenannten AlphaMemory abgespeichert. Zusätzlich propagiert ein AlphaNode, falls das Faktum die Bedingung erfüllt hat,
dieses zu seinem Nachfolger.
BetaNodes (JoinNodes) stellen eine Verbindung zwischen Gruppen aus einem oder mehreren Tupeln und eindeutigen Fakten her. Tupel werden an dem linken und Fakten am
rechten Eingang angelegt. Auch BetaNodes verfügen über einen Speicher. Für die Daten
vom linken Eingang heißt dieser Speicher BetaMemory. Die Daten vom rechten Eingang
werden im AlphaMemory gespeichert. Daher enthält der BetaMemory alle eingehenden
Tupel und der AlphaMemory alle eingehenden Objekte.
LeftInputAdapterNodes bekommen ein Objekt übergeben und propagieren nur ein einzelnes Objekttupel weiter an den darunter liegenden Knoten.
Jeder Pfad endet mit dem TerminalNode. Dieser Knoten ist mit einer bestimmten Regel
verknüpft. Sobald der Knoten aktiviert wird, fügt der Algorithmus die mit der TerminalNode verknüpften Regel zur Konfliktmenge hinzu.
2.2.3. Laufzeit Ausführung
Während der Laufzeit Ausführung durchläuft der Rete-Algorithmus drei Phasen:
Match: Inhalt des WorkingMemories (WM) wird auf alle LHS angewendet. Als Resultat
wird eine Menge (Conflict-Set), bestehend aus den Regeln deren LHS Wahrheitswert gleich wahr“ ist, geliefert.
”
Conflict-Resolution: Es wird eine Regel aus der Konfliktmenge zum Ausführen ausgewählt.
Act: Es wird die ausgewählte Regel ausgeführt. Dies hat zur Folge, dass sich der Status
des WM ändert, wodurch ein Rematching getriggert wird.
Zu beachten ist hierbei, dass 90% der Rechenzeit für die Matching-Phase benötigt wird.
16
KAPITEL 2. JEFIS DROOLS ADAPTER
2.2.4. Beispiel eines Baumes
In der Software Drools [dro10] werden die Regeln in der Drools Rule Language (DRL)
verfasst. Dabei werden die Regeln standardmäßig im MVEL-Dialekt[mve10] angegeben.
Eine in MVEL verfasste Regel zeigt das nachfolgende Beispiel:
Listing 2.1: Beispiel Regel in MVEL
1
3
5
7
rule " rule1 "
when
$cpu : CPU ( temp > 80 && voltage > 1.55 )
$cpucooler : Cooler ( cpu == $cpu && fanspeed <= 120 )
then
$cpucooler . setFanspeed (200);
end
Die Regel hängt von den zwei Objekten CPU und Cooler ab. Der deterministische Baum,
der für diese Regel erzeugt wird, besteht aus zwei Pfaden (Abbildung 2.2).
Einer behandelt alle Abfragen am Objekt CPU und der Andere Abfragen am Objekt
Cooler. Die ersten Knoten jedes Zweiges sind vom Typ ObjektTypNode und überprüfen
die im WorkingMermory enthaltenden Fakten auf ihr Instanzart. Das bedeutet: Für unser
Beispiel werden alle Objekte kontrolliert, ob sie vom Typ CPU oder vom Typ Cooler
sind. Wenn die Fakten vom Typ des entsprechenden Zweiges sind, werden diese an den
darauf folgenden Knoten propagiert. Jeder Zweig enthält für jede atomare Abfrage, aus
einer Regel, einen Knoten vom Typ AlphaNode. Der Pfad für die Fakten vom Typ CPU
beinhaltet zwei AlphaNodes. Der erste Knoten überprüft ob die Temperatur größer als
80◦ C ist. Falls dies zutrifft, wird ein neuer Eintrag in dem AlphaMemory für das Objekt
erzeugt. Anschließend wird das Objekt an den nächsten Knoten propagiert. Der nächste
Knoten vom Typ AlphaNode überprüft, ob die Spannung der CPU größer als 1,55V ist.
Im Pfad des Coolers wird abgefragt, ob die Cooler-Instanz zu einer im AlphaMemory
Abbildung 2.2.: Baum für die im Listing gezeigte Regel
gespeicherten CPU-Instanz gehört. Daher propagiert der LeftInputAdapterNode, aus
17
KAPITEL 2. JEFIS DROOLS ADAPTER
dem Pfad der CPU das Tupel, bestehend aus Objekt Hashwert und Instanz-ID, an den
linken Eingang des BetaNodes. Wurden alle Bedingungen erfüllt, fügt der TerminalNode
die Regel zur Konfliktmenge hinzu.
2.3. Erweiterung des Rete-OO Algorithmus um Fuzzy Logik
Davide Sottara hat in [DS08] eine Möglichkeit vorgestellt den Rete-OO Algorithmus
um Fuzzy Logik zu erweitern. Seine Erweiterungen sind in dem Drools-Branch Drools
Chance [Sot10b] zu finden. In den nächsten Zeilen wird auf die grundlegende Idee seiner
Erweiterung eingegangen.
Bei der Implementierung von Fuzzy Logik gibt es mehrere gravierende Unterschiede. Bei
der von Davide Sottara vorgestellten Möglichkeit wird die Unschärfe als ungefähr aufgefasst. Bei dieser Implementierung kann man sich die Fuzzy-Sets, je nach Abfrage, als
ansteigende oder abfallende Flanke vorstellen, wobei der zu prüfende Wert als Schwellwert dient. Bei diesem Verfahren wird die Standard MVEL-Syntax um die Operatoren
˜“, is und seems ergänzt. Auf den beiden Operatoren is und seems wird in den nächsten
”
Abschnitten noch eingegangen. Eine Abfrage, die mit dem ˜“-Operator anfängt, wird
”
als unscharfer Wert aufgefasst. Dies bedeutet für die Temperatur-Regel aus 2.1:
Listing 2.2: Beispiel Regel mit ˜“-Operator
”
1
3
5
7
rule " rule1 "
degree r
when
cpu : CPU ( temp ~ > 80 && voltage ~ > 1.55 )
cpucooler : Cooler ( cpu == cpu && fanspeed ~ > 120 )
then
cpucooler . setFanspeed (200);
end
Wie durch die vorangegangenen Abschnitte zu erkennen ist, muss bei der Erweiterung des Rete-OO-Algorithmus bedacht werden, dass es keine scharfen Werte mehr gibt.
Hierdurch können Auswertungen der Knoten bei falsch“ nicht einfach verworfen wer”
den. Dies führt zu einem weiteren Problem: Was passiert mit nicht erfüllten Regeln?“.
”
Um dieses Problem zu lösen, gibt es mehrere Strategien:
Niemals verwerfen: Regeln deren Bedingungen nicht erfüllt sind, werden trotzdem gefeuert. Dieses Verhalten generiert allerdings ein Performance Problem.
Künstliche Schwellwerte: Über ein Regelargument (degree) kann man einen Schwellwert setzen, der den Zugehörigkeitswert angibt, der erfüllt sein muss, damit eine
Regel feuert.
Heuristiken und weiteres: Über Interfaces ist es möglich eigene Evaluatoren zu implementieren.
18
KAPITEL 2. JEFIS DROOLS ADAPTER
2.4. Drools Chance
Wie bereits erwähnt ist es möglich eigene Evaluatoren zu erstellen. Diese Evaluatoren
müssen sich von der abstrakten Klasse BaseImperfectEvaluator ableiten. Die abstrakte
Klasse enthält eine Vielzahl von unterschiedlichen eval()-Methoden. Das nächste Listing
zeigt eine solche Methode. Wie man erkennen kann, gibt diese Methode eine Variable
des Typs IDegree zurück.
Listing 2.3: Beispiel einer eval()-Methode der abstrakten Klasse BaseImperfectEvaluator
protected abstract IDegree eval ( Object left , Object right , IDegreeFactory factory );
Das Interface IDegree repräsentiert den Zugehörigkeitswert einer Variable, also einen
Wert im Intervall I:= [0, 1]. Zusätzlich zu der Repräsentation des Intervalls ist es laut
[Sot10a] eine Anforderung an IDegree, die Werte True und False annehmen zu können.
Daher bietet es eine Möglichkeit den Zugehörigkeitswert auf boolean zu casten.
Damit die Ruleengine bei der Auswertung einer Regel mit Fuzzylogik auch den angepassten Evaluator wählt, muss dieser registriert werden. Das Registrieren eines solchen
Evaluators geschieht in zwei Schritten. Zum einem muss eine Definition, die sich von
ImperfectEvaluatorDefinition ableitet, erstellt werden. Diese Definition enthält eine ID
(z.B. seems“), die angibt auf welche Regeln der Evaluatoroperator angewendet werden
”
soll. Außerdem enthält die Definition eine getEvaluator()-Methode, die den Evaluator
zurückgibt. Zusätzlich muss der Operator an der Klasse Operator registriert werden.
Im zweiten Schritt wird der Classname des Standards Operators durch den eigenen
Classname ersetzt. Dazu wird beim Erstellen der RuleEngine eine modifizierte PackageBuilderConfiguration übergeben.
Durch diesen Mechanismus war es uns möglich einen Adapter für das Jefis Projekt zu
schreiben. Dieser Adapter erlaubt es die Regeln mit Hilfe der FuzzySets und FuzzyNormen aus Jefis auszuwerten. Im nächsten Abschnitt wird die Implementierung des Adapters beschrieben, wodurch noch einmal verdeutlicht wird, wie man eigene Evaluatoren
erstellt und registriert.
2.5. Adapter
Die Abbildung 2.3 gibt einen Überblick über die Klassen die genutzt werden um Jefis zu
adaptieren. Das zentrale Objekt des Jefis Projektes ist das FuzzySet. FuzzySets verfügen
über das Wissen wie sie miteinander verknüpft werden sollen. Das heißt: Welche Operatoren beim And oder Or angewendet werden sollen. Außerdem liefern FuzzySets die
Zugehörigkeit zu einer Variable.
Hinter jeder linguistischen Variable aus einer Regel steht ein solches Set. Auf dieses
FuzzySet muss der Evaluator zugreifen können um die Zugehörigkeit zurückgeben. Für
das folgende Listing 2.4 bedeutet dies, dass der Evaluator auf die beiden FuzzySets mit
cold“ und low“ zugreifen muss. Über die toString()-Methode des right“-Objektes aus
”
”
”
der eval()-Methode bekommt man den Namen des Sets geliefert.
19
KAPITEL 2. JEFIS DROOLS ADAPTER
Abbildung 2.3.: Klassendiagramm des Jefis-Drools-Adapters
Listing 2.4: Beispiel Regel mit Fuzzy-Evaluatoren
1
3
5
rule " R11 "
when
$cooler : Cooler ( $t : temperature is " cold " && $c : fanCurrent is " low " )
then
$cooler . setStatus (" green " , drools . g e t C o n s e q u e n c e D e g r e e ());
end
Mit diesen Namen kann man sich an der Klasse FuzzySetRegistry das entsprechende FuzzySet geben lassen. Die Registry ist als Singelton realisiert worden. Registriert werden
die FuzzySets automatisch beim Erzeugen eines FuzzySetDecorators. Dieses Vorgehen
schließt ein, dass der Name cold“, da er zu Identifizierung genutzt wird, eindeutig sein
”
muss.
Damit die Ruleengine den FuzzyEvaluator auch benutzt, wird in der Klasse JefisDroolsBuilder der Property Eintrag des entsprechenden Evaluators in der Klasse PackageBuilderConfiguration angepasst, siehe nachfolgendes Listing 2.5.
Listing 2.5: Ersetzen der Standard Evaluatoren
2
protected void c o n f i g u r e P a c k a g e B u i l d e r () {
packageBuilder = new PackageBuilder ();
p ac k ag eB u il d er Co n f = packageBuilder . g e t P a c k a g e B u i l d e r C o n f i g u r a t i o n ();
4
// r e g i s t e r some EvaluatorDefinitions . . .
p ac k ag eB u il d er Co n f . setProperty ( " drools . evaluator . seems " ,
F u z z y S e e m s E v a l u a t o r D e f i n i t i o n . class . getName ());
p ac k ag eB u il d er Co n f . setProperty ( " drools . evaluator . is " ,
I s E v a l u a t o r D e f i n i t i o n . class . getName ());
6
8
10
}
Die Regel R11 aus dem vorausgegangenen Beispiel besteht aus zwei Prämissen, die durch
den &&-Operator verknüpft sind. Für die Berechnung ruft die Ruleengine ein Implemen-
20
KAPITEL 2. JEFIS DROOLS ADAPTER
tierung von IDegreeFactory auf. Welche Factory gewählt wird, kann beim Erzeugen einer
RuleBase angegeben werden, siehe nachfolgendes Listing:
Listing 2.6: Übergabe der DegreeFactory
2
4
ruleBaseConf = new R u l e B a s e C o n f i g u r a t i o n ();
ruleBaseConf . setProperty ( DEGREE_FACTORY_TAG , J e fi s De gr e eF a ct or y . class
. getName ());
...
RuleBase ruleBase = RuleBaseFactory . newRuleBase ( ruleBaseConf );
Welche Algorithmen die Factory JefisDegreeFactory für die Operatoren zurückgibt, wird
in einer Properties-Datei parametrisiert [NW09]. Durch einen Eintrag bestimmt man
welcher Operator mit welcher Klasse verknüpft ist. Im folgendem Beispiel 2.7 wird die
Factory so parametrisiert, dass diese als Standardnormoperator eine Instanz der Klasse
de.lab4inf.fuzzy.norms.FuzzyMinMax“ und als Standardimplikationsoperator eine In”
stanz der Klasse de.lab4inf.fuzzy.logic.Mamdani“ zurückgibt.
”
Listing 2.7: Beispiel der Properties-Datei
1
3
5
7
9
11
norm . operator . DEFAULT
norm . operator . MinMax
.
.
.
= de . lab4inf . fuzzy . norms . FuzzyMinMax
= de . lab4inf . fuzzy . norms . FuzzyMinMax
implication . operator . DEFAULT
implication . operator . Zadeh
implication . operator . Goedel
.
.
.
= de . lab4inf . fuzzy . logic . Mamdani
= de . lab4inf . fuzzy . logic . Zadeh
= de . lab4inf . fuzzy . logic . Goedel
21
Teil III.
Jefis Ruleengine
Autor: Dennis Löhr, B.Sc.
22
3. Jefis Ruleengine
3.1. Einleitung
Nach einem erfolgreichen Abschluss der ersten Hälfte des Masterprojektes, wurde entschieden das wir uns in der zweiten Hälfte des Masterprojektes das an der Fachhochschule Münster entwickelte Jefis erweitern. Damit es mit Jefis nicht nur möglich ist
Fuzzy-Controlling zu betreiben, sondern auch möglich ist Fuzzy-Logic abzubilden. Dabei sollte man berücksichtigen das Jefis von sich aus keine Ruleengine, sondern einen
Fuzzy-Controller abbildet. Dieser ist zwar so entwickelt, dass Jefis aus einer XML-Datei
die Regeln dynamisch neu einliest aber dadurch, dass der Controller nur scharfe Werte
verarbeiten kann, war er nicht geeignet für das eigentliche Ziel unseres Masterprojektes.
Eines der wichtigsten Eigenschaften einer Ruleengine ist, dass es die Ergebnisse aus einer
vorherigen Regel, als Eingabe für eine neue benutzen kann (siehe Vorwärtsverkettung
1.3.4.1 bzw. Rückwärtsverkettung 1.3.4.2).
Dies wurde bei Jefis darüber gelöst, das die Ergebnisse erst defuzzifiziert und anschließend wieder fuzzifiziert werden. Durch dieses Defuzzifizieren und anschließendem Fuzzifizieren entstehen Ungenauigkeiten die spätestens nach der Hintereinanderausführung
von mehreren Regeln ein erhebliches Ausmaß annehmen.
3.2. Beispiel in Lab4Jefis
Da Jefis eine gute Möglichkeit liefert die Fuzzysets zu visualisieren wurde eine Beispielanwendung im Applet FuzzyRuleEngineApplet demonstriert. Bei diesem Applet gibt es vier
Fuzzysets in der Regelbasis (Food, Service, Tip und Waiter), damit wir eine Hintereinanderausführung von mehreren Regeln haben gibt es dazu die Regeln:
1. IF service IS good AND food IS delicious THEN tip IS generous
2. IF tip IS generous THEN waiter IS happy
In Abbildung 3.1 ist unter den Fuzzysets Premise: food und Premise: service zu sehen,
mit welchen Eingabesets wir in die Regeln hineingegangen sind. Die Eingabe Sets sind
auch in den Fuzzysets Service und Food zu sehen, bei service ist dies das gelbe Dreieck
wobei die Schnittmenge mit dem Set service:good hier als weiße Fläche eingefärbt ist.
Beim set food ist das Eingabeset durch das lila Dreieck und die Schnittmenge durch eine
türkise Fläche gekennzeichnet. Aus diesen beiden Fuzzyset-Schnittmengen ergibt sich
jetzt das Fuzzyset Premise: tip das im Ausgabe Set Tip bis zum Minimum der beiden
23
KAPITEL 3. JEFIS RULEENGINE
Abbildung 3.1.: Applet zur Visualisierung der Implikation
Eingabe Sets gefüllt ist. Zum Schluss bildet sich aus dem neuen Eingabeset Premise:tip
das neue Ausgabeset Result:waiter.
In dem Applet 3.2 wurde die Regelbasis noch fest in den Javacode eingegeben. Für
eine produktive Umgebung kann man dies allerdings nur schwer durchsetzen da, wie
im Kapitel 1.3.2 schon beschrieben ist, sich viele Regeln ändern. Deshalb haben wir
vor der Auswahl einer geeigneten Repräsentation der Regeln gestanden, zur Auswahl
kamen dabei die XML-Basierte Sprache von Jefis, die standardisierte FCL 4.1 oder eine
vollkommen eigene Entwicklung. Aufgrund dessen, dass es sich im Gegensatz zu beiden
Alternativen bei FCL um eine standardisierte Sprache für Fuzzy handelt wurde diese
dann auch genommen. Genaueres kann aus dem Kapitel 4.1 entnommen werden.
3.3. Die Lab4Jefis Rule-Engine
Um das Beispiel des Applet 3.1 mit FCL Unterstützung zu benutzen, benötigen wir eine
FCL-Datei. Diese FCL-Datei muss wie im nachfolgenden Kapitel 4.1 beschrieben wird
aufgebaut sein. Für das Beispiel stellt die FCL-Dateien die Wissensbasis des Systems
dar. Damit die beiden Eingabesets aus dem obigen Beispiel also zur Verfügung stehen,
benötigen wir innerhalb des FUNCTION BLOCKs die Elemente aus dem Listing 3.1.
24
KAPITEL 3. JEFIS RULEENGINE
Listing 3.1: FCL beschreibung der Fuzzysets service und food
2
4
6
8
10
12
14
VAR_INPUT
service : REAL ;
food : REAL ;
END_VAR
FUZZIFY service
TERM poor := (0 , 1) (4 , 0);
TERM good := (1 , 0) (4 ,1) (6 ,1) (9 ,0);
TERM excellent := (6 , 0) (9 , 1);
END_FUZZIFY
FUZZIFY food
TERM rancid := (0 , 1) (1 , 1) (3 ,0);
TERM delicious := (7 ,0) (9 ,1);
END_FUZZIFY
Wobei es für die Rule-Engine nicht erheblich ist, ob ein Fuzzyify oder Defuzzify Block
benutzt wird, da wir in der Rule-Engine mit den Ausgabesets der vorherigen Regel weiter
arbeiten. Deshalb sollten wir auch für tip“ einen Fuzzyify Block, wie im folgenden
”
Listing 3.2 benutzen.
Listing 3.2: FCL beschreibung der Fuzzysets tip und waiter
1
3
VAR_OUTPUT
tip : REAL ;
waiter : REAL ;
END_VAR
5
7
9
FUZZIFY tip
TERM cheap := (0 ,0) (5 ,1) (10 ,0);
TERM average := (10 ,0) (15 ,1) (20 ,0);
TERM generous := (20 ,0) (25 ,1) (30 ,0);
END_FUZZIFY
11
13
15
DEFUZZIFY waiter
TERM sad := ( -1.1 ,0) ( -1 ,1) (0 ,1) (3 ,0);
TERM normal := (2 ,0) (4 ,1) (5 ,1) (7 ,0);
TERM happy := (6 ,0) (9 ,1) (9.5 ,1) (9.6 ,0);
END_DEFUZZIFY
Wie beim Fuzzyset waiter bzw. food zu sehen ist, können nicht nur Dreiecke benutzt
werden, sondern es ist auch möglich Senken, Trapeze oder Polygone zu benutzen. Dadurch ist der Freiheitsgrad beim Erstellen der Fuzzysets groß, was allerdings bei den
Polygonen, wenn sehr viele Regeln benutzt werden zu Performance Einbußen führt. Damit die Wissensbasis für das Beispiel aus dem Applet aber komplett ist, wird zusätzlich
zu den Fuzzysets auch der RULEBLOCK mit den Regeln benötigt. Die beiden Regeln aus
dem Beispiel können hierfür einfach wie in Listing 3.3 eingegeben werden oder zusätzlich
mit der Norm und der Implikation versehen werden wie in Listing 3.4.
Listing 3.3: FCL beschreibung der Regeln ohne Norm und Implikation
2
4
RULEBLOCK No1
RULE 1 : IF service IS good AND food IS delicious THEN tip IS generous ;
RULE 2 : IF tip IS generous THEN waiter IS happy ;
END_RULEBLOCK
Listing 3.4: FCL beschreibung der Regeln mit Norm und Implikation
2
4
6
RULEBLOCK No1
AND : MIN ;
ACCU : MAX ;
RULE 1 : IF service IS good AND food IS delicious THEN tip IS generous ;
RULE 2 : IF tip IS generous THEN waiter IS happy ;
END_RULEBLOCK
Damit sind alle Teile der FCL-Datei komplett. Diese kann auch im Anhang zusammengefasst unter Listing 6.1 betrachtet werden. Damit das Wissen, das in der FCL-Datei
25
KAPITEL 3. JEFIS RULEENGINE
enthalten ist, in der Rule-Engine benutzten werden kann, wird ein FCLRuleEngineBuilder benötigt. Über diesen kann mit der Methode buildRuleEngine dann die Rule-Engine
mit der FCL-Datei erzeugt werden. Damit die Rule-Engine jetzt aber auch eine Regel
ausführen kann, benötigt sie eine Faktenbasis. Als Input für die Faktenbasis hatte das
Beispiel aus dem Applet für beide Fuzzysets, service und food, ein normales Dreieck.
Dieses erzeugen wir über den Konstruktor des FuzzyTriangle und setzten den Namen
des Fuzzysets, auf den es angewendet werden soll. Danach werden die einzelnen Sets zu
der Premise hinzugefügt. Das Listing 3.5 enthält alle dafür notwendigen Elemente.
Listing 3.5: Java Code zum erstellen der Beispiel Premise
2
4
6
HashMap < String , FuzzySet > premises ;
FuzzySet set ;
premises = new HashMap < String , FuzzySet >();
// Service
set = new FuzzyTriangle (3 , 2);
set . setName ( " service " );
premises . put ( set . getName () , set );
8
10
12
// Food
set = new FuzzyTriangle (7 , 3);
set . setName ( " food " );
premises . put ( set . getName () , set );
Wenn in der FCL-Datei nicht die Implikation und die Norm gewählt wurden, müssen
diese jetzt gesetzt werden. Die dafür notwendigen Funktionen sind im Listing 3.6 enthalten. Für diese stellt Jefis eine Vielzahl von verschiedenen Normen und Implikationen
zur Verfügung.
Listing 3.6: Java Code zum setzen der Implikation und der Norm
2
ruleEngine . s e tI mp l ic a ti on T yp e ( " Mamdani " );
ruleEngine . setNorm (new FuzzyMinMax ());
Nachdem der Rule-Engine nun alle Details bekannt sind, die notwendig sind, um das
Beispiel aus dem Applet darzustellen, können die Faktenbasis und die Wissensbasis über
die Methode conclusion zusammengeführt werden. Dabei wird eine Liste mit Fuzzysets
zurückgegeben, bei der beachtet werden muss das diese keine bestimmte Reihenfolge
besitzen, sondern über ihren Namen identifiziert werden können.
26
Teil IV.
FCL und ANTLR
Autor: Thomas Beermann, B.Sc.
27
4. FCL und ANTLR
4.1. FCL
4.1.1. Einleitung
Die Fuzzy Control Language oder auch FCL ist eine von der International Electrotechnical Commission (IEC 61131-7) standardisierte, domänenspezifische Sprache. Es hat nur
Sprachelemente die direkt mit Fuzzy Logik zusammenhängen, wie die Deklaration von
Fuzzy Sets und Regeln, aber nicht einmal so grundlegende Konstrukte wie Schleifen. Aus
dem Grund ist es auch nicht möglich ganze Programme in FCL zu schreiben sondern
nur die Teile davon, die die Fuzzy Regelmaschine beschreiben. Der Standard ist nicht
frei und muss erworben werden. Allerdings gibt es einen Entwurf von 1997 der sich nicht
entscheidend von dem finalen Standard unterscheidet und frei verfügbar ist unter [iec10].
Dieser Entwurf wurde in diesem Projekt verwendet.
4.1.2. Beispiel
Im Folgenden wird die Syntax von FCL genauer erklärt. Am Besten kann man dies an
einem einfachen Beispiel erklären. Die in diesem FCL Codebeispiel beschriebene Regel
Maschine berechnet die Glücklichkeit eines Kellers anhand des Trinkgelds, welches er
wiederum bekommt abhängig von der Qualität des Essens und des Services.
FUNCTION_BLOCK tipper
// Anfang eines neuen Block . Es k ö nnen mehrere in einer Datei definiert sein .
2
4
6
VAR_INPUT
service : REAL ;
food : REAL ;
tip : REAL ;
END_VAR
// Definition der E ing angs var iab len
VAR_OUTPUT
waiter : REAL ;
END_VAR
// Definition der Au sga ngsv ari abl en
8
10
12
14
16
FUZZIFY service
// Festlegung der Sets f ü r den Eingang ’ service ’
TERM poor := (0 , 1) (4 , 0) ;
TERM good := (1 , 0) (4 ,1) (6 ,1) (9 ,0);
TERM excellent := (6 , 0) (9 , 1);
END_FUZZIFY
18
20
22
24
26
28
30
32
FUZZIFY food
// Festlegung der Sets f ü r den Eingang ’ food ’
TERM rancid := (0 , 1) (1 , 1) (3 ,0) ;
TERM delicious := (7 ,0) (9 ,1);
END_FUZZIFY
FUZZIFY tip
// Festlegung der Sets f ü r den Eingang / Ausgang ’tip ’
TERM cheap := (0 ,0) (5 ,1) (10 ,0);
TERM average := (10 ,0) (15 ,1) (20 ,0);
TERM generous := (20 ,0) (25 ,1) (30 ,0);
END_FUZZIFY
DEFUZZIFY waiter
// Festlegung der Sets f ü r den Ausgang waiter
TERM sad := (0 ,0) (5 ,1) (10 ,0)
TERM normal := (10 ,0) (15 ,1) (20 ,0)
TERM happy := (20 ,0) (25 ,1) (30 ,0)
28
KAPITEL 4. FCL UND ANTLR
34
END_DEFUZZIFY
36
RULEBLOCK service_food_tip
AND : MIN ;
ACCU : MAX ;
ACT : MIN ;
38
// Angabe der Norm . ’MIN ’ f ü r ’AND ’ impliziert auch ’MAX ’ f ü r ’OR ’
// Angabe der Norm f ü r die Zusammenfassung der Ergebnisse .
// Angabe der Norm f ü r die Aktivierung der Regeln .
40
42
RULE 1 : IF service IS poor OR food is rancid THEN tip IS cheap ;
RULE 2 : IF service IS good THEN tip IS average ;
RULE 3 : IF service IS excellent AND food IS delicious THEN tip is generous ;
44
46
48
50
52
RULEBLOCK tip_waiter
AND : BOUNDED ;
ACCU : MAX ;
ACT : PROD ;
RULE 4 : IF tip IS cheap THEN waiter IS sad ;
RULE 5 : IF tip IS average THEN waiter IS normal ;
RULE 6 : IF tip IS generous THEN waiter IS happy ;
END_RULEBLOCK
54
E ND _ FU NC T IO N_ B LO C K
FCL wurde als Sprache für Fuzzy Control entwickelt, was man auch direkt bemerkt.
Eine FCL-Datei kann aus mehreren FUNCTION BLOCKs aufgebaut sein. Diese haben wie
reale Bausteine einen oder mehrere Ein-und Ausgänge. Dieses Beispiel besteht nur aus
dem FUNCTION BLOCK tipper. Die Eingaben und Ausgaben werden am Anfang deklariert in den Blöcken beginnend mit VAR INPUT bzw. VAR OUTPUT. Bei einem normalen
Fuzzy Control Block werden die Eingänge immer fuzzifiziert und die Ausgänge immer
defuzzifiert, so dass man die Variablen immer als Input oder Output deklarieren muss.
Bei der Rule Engine aus diesem Projekt müssen die Eingänge und Ausgänge aber nicht
unbedingt fuzzifiert und defuzzifiziert werden. Zu einen kann man auch mit unscharfen
Werten als Eingang reingehen, zum anderen können auch unscharfe Werte als Ausgabe
herauskommen. Aus diesem Grund können Regeln auch verkettet werden ohne jeweils
die Eingänge oder Ausgänge fuzzifizieren bzw. defuzzifieren zu müssen. Daraus folgt,
dass man die Variablen nicht immer unbedingt als Input oder Output deklarieren kann.
Bei service und food ist es offensichtlich, da diese nur als Eingabe verwendet werden
im Regelblock service food tip benutzt werden. Ebenso verhält es sich mit waiter
nur eben als Ausgabe im zweiten Regelblock. Bei tip ist das nicht mehr so eindeutig.
tip wird sowohl im 1. als auch im 2. Regelblock verwendet sowohl als Eingabe als auch
als Ausgabe. Ist das der Fall wird eine Variable als Eingabe deklariert.
Als nächstes folgt die Angabe der Partitionen und Sets für die einzelnen Variablen.
Dies geschieht in dem FUZZIFY bzw. DEFUZZIFY Block. Für jede Variable wird ein eigener
Block angelegt und in diesen Blöcken die Sets definiert. Jedes Set wird durch TERM
gefolgt von dem Namen eingeleitet. Es gibt dann verschiedene Möglichkeiten ein Set zu
definieren. In diesem Beispiel werden einfach verschiedene Referenzpunkte gewählt, die
in den Klammern angegeben werden. Der erste Wert ist die Eingabe und der Zweite
die Zugehörigkeit zum Set. Zwei Punkte müssen mindestens angegeben werden. Alle
weiteren Werte werden dann daraus berechnet.
Nachdem die Eingabe-und Ausgabewerte angegeben und die dazugehörigen Sets definiert wurden gibt man im RULEBLOCK die Regeln an. Bevor die eigentlichen Regeln
beginnen, kann man die Rule Engine noch mit 3 verschiedenen Optionen parametrisieren. Zunächst ist da die Norm. Hier reicht es entweder die AND oder OR Norm anzugeben
da die jeweils andere implizit darauf folgt. Dann gibt es noch die Akkumulationsnorm,
29
KAPITEL 4. FCL UND ANTLR
die angibt, mit welcher Norm die Ergebnis verbunden werden. Als Drittes gibt es noch
die Aktivierungsnorm, die angibt, welche Norm genutzt wird um herauszufinden welche
Regeln gefeuert werden müssen. Alle drei Optionen sind optional und haben jeweils die
MIN bzw. MAX Norm als Voreinstellung. Danach folgen die Regeln. Dies können beliebig
viele sein eingeleitet jeweils durch RULE gefolgt von einer Nummer. Die Regel an sich
wird durch einfache IF/THEN Konstrukte definiert. Die einzelnen Bedingungen können
dabei beliebig mit AND oder OR verknüft werden.
Mit diesen einführenden Beispiel kann der grundlegende Aufbau von FCL schon recht
gut verstanden werden. Es folgt nun die genaue Beschreibung der einzelnen Blöcke.
4.1.3. Beschreibung
4.1.3.1. VAR INPUT / VAR OUTPUT
• Beide Blöcke können beliebig viele müssen aber mindestens eine Variablendeklaration enthalten getrennt durch ein Semikolon.
• Eine Variablendeklaration besteht dabei immer aus dem Namen und dem Datentypen getrennt durch einen Doppelpunkt abgeschlossen durch ein Semikolon.
• Als Datentyp kann nur REAL gewählt werden.
• Variablen die sowohl Eingabe als auch Ausgabe für unterschiedliche Regeln sind
werden als Eingabe deklariert.
4.1.3.2. FUZZIFY / DEFUZZIFY
• Für jede Eingabevariable wird ein FUZZIFY Block angegeben und für jede Ausgabevariable ein DEFUZZIFY Block.
• Es können beliebig viele Sets getrennt durch ein Semikolon angeben werden.
• Ein Set wird deklariert durch einen Namen gefolgt von := und der Angabe der
Membershipfunktion. Es gibt:
1. Polygon: Hier werden einzelne Punkte angegeben. Alle weiteren Punkte dazwischen werden berechnet.
2. Trapez: Angegeben durch TRAPE gefolgt von 4 x-Werten, die von links nach
rechts das linke Minimum, das linke Maximum, das rechte Maximum und das
linke Minimum angeben.
3. Dreieck: Angegeben durch TRIAN gefolgt von 3 x-Werten, die von links nach
rechts das linke Minimum, das Maximum und das rechte Minimum angeben.
4. Singleton: Angegeben durch einen einfachen x-Wert.
• Der DEFUZZIFY Block hat zusätzlich noch die Option für die Defuzzifizierungsmethode (METHOD). Hier gibt es:
30
KAPITEL 4. FCL UND ANTLR
1. COG: Centre of Gravity.
2. LM: Left Most Maximum.
3. RM: Right Most Maximum.
4.1.3.3. RULEBLOCK
• Ein FUNCTION BLOCK kann beliebig viele RULEBLOCKs haben.
• Ein RULEBLOCK besteht immer aus drei optionalen Parametern und den Regeln
selbst.
• Der erste Parameter ist die Operatordefinition (AND / OR). Hier wird entweder
die Norm für AND oder OR angegeben. Die jeweils dazugehörige andere Norm wird
dadurch implizit mit angegeben. Für AND gibt es:
1. MIN: M in(µ1 (x), µ2 (x))
2. PROD: µ1 (x) ∗ µ2 (x)
3. BDIF: M ax(0, µ1 (x) + µ2 (x) − 1)
Für OR sind es:
1. MAX: M ax(µ1 (x), µ2 (x))
2. ASUM: µ1 (x) + µ2 (x) − µ1 (x) ∗ µ2 (x)
3. BSUM: M in(1, µ1 (x) + µ2 (x))
Wenn keine Angabe für AND oder OR gemacht wird wird MIN bzw. MAX genommen.
• Der zweite Parameter ist Aktivationsmethode (ACT). Sie gibt an welche Norm
genommen wird um herauszufinden welche Regeln überhaupt gefeuert werden
müssen. Hier gibt es:
1. PROD: µ1 (x) ∗ µ2 (x)
2. MIN: M in(µ1 (x), µ2 (x))
Wenn keine Angabe gemacht wird, wird MIN verwendet.
• Der letzte Parameter ist der Akkumulationoperator (ACCU). Dieser gibt die Norm
an die zum Zusammenfügen der Ergebnisse genutzt wird. Es gibt:
1. MAX: M ax(µ1 (x), µ2 (x))
2. BSUM: M in(1, µ1 (x) + µ2 (x))
Wenn keine Angabe gemacht wird, wird MAX verwendet.
• Danach folgen die Regeln. Davon kann es beliebig viele geben. Eine Regel beginnt immer mit dem Schlüsselwort RULE und einer ID, die eine beliebige Zeichenkette beginnen mit einem Buchstaben sein kann, und endet mit einem Semikolon. Dazwischen kommt dann die eigentliche Regel. Diese besteht aus einem
IF...THEN...(WITH) Konstrukt. Dabei gibt es drei Abschnitte
31
KAPITEL 4. FCL UND ANTLR
– IF: Besteht aus einer oder mehreren Bedingungen verknüpft durch AND oder
OR. Eine Bedingung besteht dabei aus Input IS Set. Input ist der Name
einer vorher definierten Eingabevariablen und Set ist der Name eines im
FUZZIFY Teil für diese Variable definierten Sets.
– THEN: Besteht aus einer Folgerung bestehend aus Output IS Set.
– WITH: Der WITH Teil ist optional gibt einer Folgerung eine Gewichtung. Es
sind Werte zwischen 0.0 und 1.0 erlaubt. Diese beeinflussen das Ausgabeset
indem die Zugehörigkeit um den angegebenen Faktor verringert wird. Wenn
kein Wert angeben ist wird 1.0 verwendet.
4.2. ANTLR
4.2.1. Einleitung
Nachdem FCL als Sprache für die Angabe der Sets und Regeln bestimmt wurde musste
entschieden werden, wie man diese in Java einliest und in Jefis-Objekte umwandelt. Ein
Möglichkeit wäre es selbst die einzelnen Zeichen aus der Datei auszulesen und einen
Automaten zu entwickeln, der die Zeichenfolge auf Korrektheit überprüft und dann die
Objekte erstellt. Zum Einen ist dies aber sehr aufwendig zu machen zum Anderen wird
es dadurch schwer wartbar und auch erweiterbar. Dieser Umstand führt zu ANother
Tool for Language Recognition, kurz ANTLR. Ein großer Vorteil ist es, dass es schon
eine Grammatikdatei von ANTLR für FCL gibt 1 . Lexer und Parser werden aus dieser
Grammatikdatei automatisch erzeugt und Änderungen können einfach in der Grammatik
vorgenommen. Der durch den Parser erzeugte Syntaxbaum kann dann mit einem auch
von ANTLR erzeugten Tree Walker durchlaufen werden, so dass dann die Jefis-Objekte
daraus erstellt werden können. Im Folgenden wird erklärt, wie eine solche Grammatik
definiert wird und wie der Tree Walker den Syntaxbaum verarbeiten kann.
4.2.2. Lexer/Parser
Die Hauptaufgabe des Lexer und des Parsers ist es eine eingegebene Datei auf ihre
syntaktische Korrektheit zu überprüfen. Der Lexer zerlegt dabei den Strom an Zeichen in
für den Parser verständliche Tokens. Wenn diese Tokens an den Parser übergeben worden
sind überprüft der dieser, ob die Zeichenfolge einem gültigen Programm entspricht. Ist
das der Fall wird ein Baum erstellt mithilfe dessen man später den Code erzeugen kann.
Die Erstellung des Lexer und des Parsers wird komplett von ANTLR übernommen.
Das einzige was ANTLR dafür braucht ist eine .g Datei (Grammatik Datei). In dieser
Datei wird eine kontextfreie Grammatik in EBNF angegeben, die die gewünschte Sprache
beschreibt. An einem kleinen Beispiel soll diese Grammatik jetzt beschrieben werden.
Die komplette Grammatik für FCL kann im Anhang gefunden werden.
1
Entwickelt von Pablo Cingolani im Projekt JFuzzyLogic
32
KAPITEL 4. FCL UND ANTLR
4.2.3. Beispiel
In diesem Beispiel wird der Teil von FCL.g erklärt, der die VAR INPUT/VAR OUTPUT Block
bestimmt.
1
3
5
grammar FCL ;
......
FUNCTION_BLOCK :
( ’f ’| ’F ’)( ’ u ’| ’U ’)( ’ n ’| ’N ’)( ’ c ’| ’C ’)( ’ t ’| ’T ’)( ’ i ’| ’I ’)( ’ o ’| ’O ’)( ’ n ’| ’N ’) ’_ ’( ’b ’| ’B ’)
( ’l ’| ’L ’)( ’ o ’| ’O ’)( ’ c ’| ’C ’)( ’ k ’| ’K ’);
E ND _ FU NC T IO N_ B LO C K
:
( ’e ’| ’E ’)( ’ n ’| ’N ’)( ’ d ’| ’D ’) ’_ ’( ’f ’| ’F ’)( ’ u ’| ’U ’)( ’ n ’| ’N ’)( ’ c ’| ’C ’)( ’ t ’| ’T ’)
( ’i ’| ’I ’)( ’ o ’| ’O ’)( ’ n ’| ’N ’) ’_ ’( ’b ’| ’B ’)( ’ l ’| ’L ’)( ’ o ’| ’O ’)( ’ c ’| ’C ’)( ’ k ’| ’K ’);
7
9
11
TYPE_REAL
VAR_INPUT
VAR_OUTPUT
END_VAR :
:
( ’r ’| ’R ’)( ’ e ’| ’E ’)( ’ a ’| ’A ’)( ’ l ’| ’L ’);
:
( ’v ’| ’V ’)( ’ a ’| ’A ’)( ’ r ’| ’R ’) ’_ ’( ’i ’| ’I ’)( ’ n ’| ’N ’)( ’ p ’| ’P ’)( ’ u ’| ’U ’)( ’ t ’| ’T ’);
:
( ’v ’| ’V ’)( ’ a ’| ’A ’)( ’ r ’| ’R ’) ’_ ’( ’o ’| ’O ’)( ’ u ’| ’U ’)( ’ t ’| ’T ’)( ’ p ’| ’P ’)( ’ u ’| ’U ’)( ’ t ’| ’T ’);
( ’e ’| ’E ’)( ’ n ’| ’N ’)( ’ d ’| ’D ’) ’_ ’( ’v ’| ’V ’)( ’ a ’| ’A ’)( ’ r ’| ’R ’);
13
......
15
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Lexer
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ......
COLON : ’: ’;
SEMICOLON : ’; ’ ;
......
// A DIGIT
fragment DIGIT : ’0 ’.. ’9 ’ ;
17
19
21
23
25
27
// A letter
fragment LETTER : LOWER | UPPER ;
fragment LOWER : ’a ’.. ’ z ’;
fragment UPPER : ’A ’.. ’ Z ’;
29
31
33
35
37
39
41
// Letter or digit
fragment ALPHANUM
:
LETTER | DIGIT ;
......
// An identifier .
ID
:
LETTER ( ALPHANUM | ’_ ’)*;
......
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Parser
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - main :
fcl :
f = fcl -> ^( FCL $f );
( function_block )+;
43
45
// Function block
function_block : FUNCTION_BLOCK ^ ( ID )? ( declaration )* EN D_ F UN C TI ON _ BL OC K !;
declaration : var_input | var_output | fuzzify_block | defuzzify_block | rule_block ;
47
51
// Variables input and output
var_input : VAR_INPUT ^ ( var_def )+ END_VAR !;
var_output : VAR_OUTPUT ^ ( var_def )+ END_VAR !;
var_def : ID ^ COLON ! data_type SEMICOLON !;
53
......
55
data_type : TYPE_REAL ;
49
Zu Beginn einer .g Datei kommt die Deklaration der Schlüsselwörter. In diesem Ausschnitt ist es z.B. TYPE REAL, welches für die Zeichenkette REAL steht. Die Groß- und
Kleinschreibung der einzelnen Buchstaben ist dabei egal.
Weiter folgen dann die Angaben für den Lexer, d.h. wichtige Zeichen, wie z.B. der
Doppelpunkt oder das Semikolon.
Danach kommt dann der Teil für den Parser. Hier werden einfache Ersetzungsregeln
aufgestellt in denen auch der Baum erstellt wird. Der oberste Knoten eines FCL Baumes
ist immer die Zeichenfolge FCL. Die Kinder davon sind die Bäume für die einzelnen
Funktionsblöcke. Um dies zu realisieren gibt es die beiden Regeln main und fcl. main
wird einfach nur durch fcl ersetzt. Durch f=fcl wird eine Variable f erzeugt, die im
zweiten Teil der Regeln benutzt werden kann. Der zweite Teil erzeugt den eigentlichen
33
KAPITEL 4. FCL UND ANTLR
Baum. Durch das ^ gefolgt von den Klammern wird ein neuer Unterbaum erzeugt, wobei
das erste Token, hier FCL, der Knoten ist und die darauf folgenden Token die Blätter, hier
die vorher erzeugte Variable f. $f wird dann durch die von fcl erzeugten Unterbäume
ersetzt.
Die Regel fcl ist recht einfach. Durch das + gibt sie an, das es durch mehrere aber
mindestens einen function block ersetzt werden muss. Hier wird kein neuer Unterbaum
erzeugt.
Das folgt in function block. Ein Funktionsblock muss immer mit FUNCTION BLOCK
anfangen und mit END FUNCTION BLOCK enden. Dazwischen folgt eine optionale ID angegeben durch das ? und null oder mehrere declaration angegeben durch das *. Durch
das ^ wird wieder der neue Unterbaum eingeleitet mit dem Knoten FUNCTION BLOCK.
Das erste Blatt ist dann die ID. Die weitere Blätter sind die declaration, falls vorhanden. Das ! gibt an, dass END FUNCTION BLOCK verworfen und nicht mit in den Baum
übernommen wird.
Eine declaration wiederum wird durch eine der 5 Optionen ersetzt. Für das Beispiel
sind nur var input und var output interessant.
var input und var output sind recht ähnlich und unterscheiden sich nur durch die
Namen. Auch hier wird wieder ein neuer Unterbaum für jeden Block angelegt. Der
Knoten ist wieder VAR INPUT oder VAR OUTPUT und die Blätter sind eine oder mehrere
var def. END VAR wird wieder verworfen.
Eine der letzten Regeln für die Variablen Blöcke ist var def. Solch eine var def
besteht immer aus einer ID gefolgt von einem Doppelpunkt, dem data type und abgeschlossen mit einem Semikolon. Der Unterbaum der daraus erzeugt wird besteht einfach
nur aus der ID und dem Datentypen als Blatt.
Zuletzt kommt noch data type. Hier ist nur TYPE REAL zugelassen.
Zum verdeutlichen wird an dem folgenden kurzen Codebeispiel gezeigt, welcher Baum
daraus erzeugt wird.
1
FUNCTION_BLOCK tipper
3
VAR_INPUT
service : REAL ;
food : REAL ;
END_VAR
5
7
9
VAR_OUTPUT
tip : REAL ;
END_VAR
11
......
13
E ND _ FU NC T IO N_ B LO C K
Aus der ersten Regel main wird zu Beginn der Knoten FCL erzeugt an dem später der
restliche Baum hängt.
Die ersten gefunden Token sind FUNCTION BLOCK und tipper. Zuerst wird dadurch
die Regeln fcl behandelt, die dann wieder zu function block führt. In dieser Regeln
wird ein neuer Baum angelegt mit dem Knoten FUNCTION BLOCK und zunächst tipper
als einziges Kind. Dieser Baum wird als Kind an den Knoten FCL angehängt.
Weiter geht es mit declaration. Davon kann es beliebig viele geben. In diesem Beispiel
sind es genau zwei. Einmal ein var input und ein var output. Mit der Regel var input
34
KAPITEL 4. FCL UND ANTLR
wird aus aus dem ersten Block zunächst ein Knoten VAR INPUT erzeugt, der an dem
Knoten FUNCTION BLOCK dran gehangen wird. An den neuen Knoten werden wiederum
mit der Regel var def zwei neue Knoten dran gehangen. Jeweils einer für service und
einer für food. Jeder dieser Knoten bekommt noch den Datentypen, hier TYPE REAL angehängt. Das Gleiche passiert noch für var output. Hier wird der Knoten VAR OUTPUT erzeugt und der Knoten tip angehängt, der wiederum den Knoten TYPE REAL dranhängen
hat. Auch VAR OUTPUT kommt an FUNCTION BLOCK und er Baum ist damit vollständig.
Der gesamte Baum ist auch in Abbildung 4.1 abgebildet.
Abbildung 4.1.: Der erzeugte Beispielbaum.
35
KAPITEL 4. FCL UND ANTLR
4.2.4. Benutzung in Java
Wenn der Lexer und Parser in der .g Datei angegeben wurden muss dieser nur noch von
ANTLR erzeugt werden, was komplett automatisch geschieht. Danach können beide in
einem Java Programm benutzt werden.
Es gibt verschiedene Möglichkeiten um mit ANTLR den Lexer/Parser zu erzeugen.
Die erste wäre, das im ANTLR mitgelieferte Tool zu benutzen, dem man einfach die .g
Datei übergibt und das dann die beiden Klassen für den Lexer und den Parser erzeugt
und in .java Dateien ablegt.
Die andere in dem Projekt benutzte Möglichkeit ist es das Maven Plugin zu verwenden.
Man kann ein Goal erstellen, das automatisch die Klassen erzeugt. Dazu muss man nur
in der pom.xml das Quellverzeichnis und das Ausgabeverzeichnis angeben und dann das
Goal ausführen.
2
4
6
8
10
12
14
16
< plugin >
< groupId > org . antlr </ groupId >
< artifactId > antlr3 - maven - plugin </ artifactId >
< version > 3.1.1 </ version >
< configuration >
< sourceDirectory > src / main / resources </ sourceDirectory >
< outputDirectory > gen </ outputDirectory >
</ configuration >
< executions >
< execution >
< goals >
< goal > antlr </ goal >
</ goals >
</ execution >
</ executions >
</ plugin >
Die erzeugten Klassen kann man dann in dem Projekt folgendermaßen benutzen:
2
4
6
......
String sourcefile = ‘‘ test . fcl ’ ’
FclLexer lexer = new FclLexer ( new ANT LRR eade rSt rea m ( new FileReader ( sourceFile )));
FclParser parser = new FclParser ( new Co mmo nTo ken Stre am ( lexer ));
FclParser . main_return root = parser . main ();
Tree parsingTree = (( Tree ) root . getTree ());
......
Der Lexer bekommt einen ANTLRReaderStream der die Quelldatei geöffnet hat. Der
Parser bekommt dann einen CommonTokenStream vom Lexer. Am dem Parser können
dann die Regeln aufgerufen werden, die vorher in der .g Datei angelegt wurden. Da
man hier die ganze Datei parsen will fängt man mit der ersten Regel main an. Von der
Rückgabe des Aufrufs bekommt man den dann einen Tree geliefert den man weiter mit
dem Treewalker verwenden kann.
4.2.5. Treewalker
Mit dem erhaltenen Baum könnte man direkt in Java weiterarbeiten. Man kann jeweils
die Kinder als eigene Bäume bekommen und so den kompletten Baum durchlaufen und
auswerten. Allerdings gibt es bei ANTLR eine viel angenehmere Lösung, den Treewalker. Ein Treewalker wird wie der Lexer/Parser in einer .g Datei mit der selben Syntax
angegeben. Die einzelnen Regeln sind fast identisch. Nur wird hier nicht die FCL Datei
geparst sondern der Baum. In jeder Regel kann man Java Code angeben und die Werte
aus den Knoten im Java Code verwenden, so dass man direkt an den gewünschten Stellen
die passenden Aktionen vornehmen kann.
36
KAPITEL 4. FCL UND ANTLR
4.2.6. Beispiel
In diesem Beispiel wird ein Treewalker vorgestellt der den Baum aus dem Beispiel zuvor parst und die Eingabe und Ausgabe Variablen und deren Datentyp einfach über
System.out ausgibt. Der richtige Treewalker aus dem Projekt gibt die die einzelnen
Werte natürlich nicht nur einfach aus sondern erzeugt damit die RuleEngine. Der Quellcode dafür befindet sich im Anhang.
1
3
5
7
@members {
private String varType = null ;
private String varName = null ;
}
main :
fcl :
^( FCL fcl );
( function_block )+;
9
11
// Function block
function_block : ^( FUNCTION_BLOCK ( ID )? ( declaration )*);
declaration : var_input | var_output | fuzzify_block | defuzzify_block | rule_block ;
13
15
17
19
21
// Variables input and output
var_input : ^( VAR_INPUT ( var_def )*) { System . out . println ( ‘ ‘ Eingabevariablen : ’ ’);
System . out . println (" Name : " + varName + " , Type : " + varType );};
var_output : ^( VAR_OUTPUT ( var_def )){ System . out . println ( ‘ ‘ Ausgabevariablen : ’ ’);
System . out . println (" Name : " + varName + " , Type : " + var \ Ttype );};
var_def : ^( ID data_type ) { varName = $ID . text };
......
data_type : TYPE_REAL { varType = ‘‘ REAL ’ ’};
Aus der .g Datei wird später eine Java Klasse erzeugt. Deshalb ist es auch möglich statische Java-Blöcke darin zu definieren, die 1 zu 1 in die Java Klasse übernommen werden.
Zum einen gibt es den @header Block indem das Package und die Includes angegeben
werden können und zum anderen den @members indem man sowohl Klassenvariablen als
auch Funktionen deklarieren kann. In diesen Beispiel werden die beiden String varType
und varName deklariert die später noch Verwendung finden.
Danach fangen wieder die Regeln an. Um das Ganze übersichtlich zu gestalten werden
hier wieder die gleichen Namen wie bei dem Parser gewählt. Die Regeln vom Parser
können als Grundlage gewählt werden und müssen nur leicht angepasst werden um den
Baum zu parsen. Das Zeichen ^ gibt auch hier wieder an, dass ein neuer Unterbaum
beginnt. In den Klammern ist dann angegeben, wie dieser auszusehen hat um gematcht
zu werden. In diesem Beispiel heißt das, dass der Baum mit dem Knoten FCL beginnen muss. Die Kinder werden aus der Regel fcl abgeleitet und die besteht wiederum
aus einem oder mehreren function block. Das geht dann so weiter wie vorher. Ein
function block besteht wieder aus dem Knoten FUNCTION BLOCK und den Kindern ID
und declaration. Interessant wird es ab der Regel var input. Hier werden die Eingabevariablen mit Namen und Typ ausgegeben. Jetzt könnte man annehmen, dass die
beiden Variablen varName und varType noch null sind, wenn man das erste Mal dort
hinkommt und die Ausgabe würde nicht funktionieren. Das ist aber nicht der Fall. Der
Baum wird von unten nach oben durchlaufen. D.h. es wird mit data type begonnen,
wo die Variable varType gesetzt wird. Danach geht es in die Regel var def. Hier wird
varName gesetzt. Dafür wird der Wert von ID ausgelesen. Dies kann man in Java Code
einfach machen, indem man ein $ vor ID setzt und dann die Variable text ausliest. Erst
dann kommt man in die Regel var input. Hier greift man dann einfach auf die vorher
gesetzten Strings zu und gibt diese einfach über System.out aus.
37
Teil V.
Anhang
38
5. ANTLR
A. Fcl.g
1
grammar Fcl ;
3
options {
// We ’ re going to output an AST .
output = AST ;
}
5
7
9
11
// Tokens ( reserved words )
tokens {
POINT ;
FCL ;
}
13
15
@lexer :: header {
package de . lab4inf . fcl ;
}
17
19
@header {
package de . lab4inf . fcl ;
}
22
24
26
28
30
32
34
36
38
40
42
44
46
48
50
52
54
56
58
60
62
64
66
68
ABS
:
( ’a ’| ’A ’ )( ’b ’| ’B ’ )( ’s ’| ’S ’ );
ACCU
:
( ’a ’| ’A ’ )( ’c ’| ’C ’ )( ’c ’| ’C ’ )( ’u ’| ’U ’ );
ACT
:
( ’a ’| ’A ’ )( ’c ’| ’C ’ )( ’t ’| ’T ’ );
AND
:
( ’a ’| ’A ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’ );
ASUM
:
( ’a ’| ’A ’ )( ’s ’| ’S ’ )( ’u ’| ’U ’ )( ’m ’| ’M ’ );
BDIF
:
( ’b ’| ’B ’ )( ’d ’| ’D ’ )( ’i ’| ’I ’ )( ’f ’| ’F ’ );
BSUM
:
( ’b ’| ’B ’ )( ’s ’| ’S ’ )( ’u ’| ’U ’ )( ’m ’| ’M ’ );
COA
:
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’a ’| ’A ’ );
COSINE :
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’s ’| ’S ’ )( ’i ’| ’I ’ )( ’n ’| ’N ’ )( ’e ’| ’E ’ );
COG
:
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’g ’| ’G ’ );
COGS
:
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’g ’| ’G ’ )( ’s ’| ’S ’ );
COGF
:
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’g ’| ’G ’ )( ’f ’| ’F ’ );
COS
:
( ’c ’| ’C ’ )( ’o ’| ’O ’ )( ’s ’| ’S ’ );
DEFAULT :
( ’d ’| ’D ’ )( ’e ’| ’E ’ )( ’f ’| ’F ’ )( ’a ’| ’A ’ )( ’u ’| ’U ’ )( ’l ’| ’L ’ )( ’t ’| ’T ’ );
DEFUZZIFY
:
( ’d ’| ’D ’ )( ’e ’| ’E ’ )( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’z ’| ’Z ’ )( ’z ’| ’Z ’ )( ’i ’| ’I ’ )( ’f ’| ’F ’ )( ’y ’| ’Y ’ );
DSIGM
:
( ’d ’| ’D ’ )( ’s ’| ’S ’ )( ’i ’| ’I ’ )( ’g ’| ’G ’ )( ’m ’| ’M ’ );
END_DEFUZZIFY
:
( ’e ’| ’E ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’) ’_ ’( ’d ’| ’D ’ )( ’e ’| ’E ’ )( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’z ’| ’Z ’)
( ’z ’| ’Z ’ )( ’i ’| ’I ’ )( ’f ’| ’F ’ )( ’y ’| ’Y ’ );
E ND _ FU NC T IO N_ B LO C K
:
( ’e ’| ’E ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’) ’_ ’( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’n ’| ’N ’ )( ’c ’| ’C ’)
( ’t ’| ’T ’ )( ’i ’| ’I ’ )( ’o ’| ’O ’ )( ’n ’| ’N ’) ’_ ’( ’b ’| ’B ’ )( ’l ’| ’L ’ )( ’o ’| ’O ’ )( ’c ’| ’C ’ )( ’k ’| ’K ’ );
END_FUZZIFY
:
( ’e ’| ’E ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’) ’_ ’( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’z ’| ’Z ’ )( ’z ’| ’Z ’ )( ’i ’| ’I ’)
( ’f ’| ’F ’ )( ’y ’| ’Y ’ );
END_RULEBLOCK
:
( ’e ’| ’E ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’) ’_ ’( ’r ’| ’R ’ )( ’u ’| ’U ’ )( ’l ’| ’L ’ )( ’e ’| ’E ’ )( ’b ’| ’B ’)
( ’l ’| ’L ’ )( ’o ’| ’O ’ )( ’c ’| ’C ’ )( ’k ’| ’K ’ );
END_VAR :
( ’e ’| ’E ’ )( ’n ’| ’N ’ )( ’d ’| ’D ’) ’_ ’( ’v ’| ’V ’ )( ’a ’| ’A ’ )( ’r ’| ’R ’ );
EXP
:
( ’e ’| ’E ’ )( ’x ’| ’X ’ )( ’p ’| ’P ’ );
FUNCTION
:
( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’n ’| ’N ’ )( ’c ’| ’C ’ )( ’t ’| ’T ’ )( ’i ’| ’I ’ )( ’o ’| ’O ’ )( ’n ’| ’N ’ );
GAUSS
:
( ’g ’| ’G ’ )( ’a ’| ’A ’ )( ’u ’| ’U ’ )( ’s ’| ’S ’ )( ’s ’| ’S ’ );
GBELL
:
( ’g ’| ’G ’ )( ’b ’| ’B ’ )( ’e ’| ’E ’ )( ’l ’| ’L ’ )( ’l ’| ’L ’ );
FUNCTION_BLOCK :
( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’n ’| ’N ’ )( ’c ’| ’C ’ )( ’t ’| ’T ’ )( ’i ’| ’I ’ )( ’o ’| ’O ’ )( ’n ’| ’N ’)
’_ ’( ’b ’| ’B ’ )( ’l ’| ’L ’ )( ’o ’| ’O ’ )( ’c ’| ’C ’ )( ’k ’| ’K ’ );
FUZZIFY :
( ’f ’| ’F ’ )( ’u ’| ’U ’ )( ’z ’| ’Z ’ )( ’z ’| ’Z ’ )( ’i ’| ’I ’ )( ’f ’| ’F ’ )( ’y ’| ’Y ’ );
IF
:
( ’i ’| ’I ’ )( ’f ’| ’F ’ );
IS
:
( ’i ’| ’I ’ )( ’s ’| ’S ’ );
LM
:
( ’l ’| ’L ’ )( ’m ’| ’M ’ );
LN
:
( ’l ’| ’L ’ )( ’n ’| ’N ’ );
LOG
:
( ’l ’| ’L ’ )( ’o ’| ’O ’ )( ’g ’| ’G ’ );
MAX
:
( ’m ’| ’M ’ )( ’a ’| ’A ’ )( ’x ’| ’X ’ );
METHOD :
( ’m ’| ’M ’ )( ’e ’| ’E ’ )( ’t ’| ’T ’ )( ’h ’| ’H ’ )( ’o ’| ’O ’ )( ’d ’| ’D ’ );
MIN
:
( ’m ’| ’M ’ )( ’i ’| ’I ’ )( ’n ’| ’N ’ );
MM
:
( ’m ’| ’M ’ )( ’m ’| ’M ’ );
NC
:
( ’n ’| ’N ’ )( ’c ’| ’C ’ );
NOT
:
( ’n ’| ’N ’ )( ’o ’| ’O ’ )( ’t ’| ’T ’ );
NSUM
:
( ’n ’| ’N ’ )( ’s ’| ’S ’ )( ’u ’| ’U ’ )( ’m ’| ’M ’ );
OR
:
( ’o ’| ’O ’ )( ’r ’| ’R ’ );
PROBOR :
( ’p ’| ’P ’ )( ’r ’| ’R ’ )( ’o ’| ’O ’ )( ’b ’| ’B ’ )( ’o ’| ’O ’ )( ’r ’| ’R ’ );
39
KAPITEL 5. ANTLR
70
72
74
76
78
80
82
84
86
PROD
:
( ’p ’| ’P ’ )( ’r ’| ’R ’ )( ’o ’| ’O ’ )( ’d ’| ’D ’ );
RANGE
:
( ’r ’| ’R ’ )( ’a ’| ’A ’ )( ’n ’| ’N ’ )( ’g ’| ’G ’ )( ’e ’| ’E ’ );
RM
:
( ’r ’| ’R ’ )( ’m ’| ’M ’ );
RULE
:
( ’r ’| ’R ’ )( ’u ’| ’U ’ )( ’l ’| ’L ’ )( ’e ’| ’E ’ );
RULEBLOCK
:
( ’r ’| ’R ’ )( ’u ’| ’U ’ )( ’l ’| ’L ’ )( ’e ’| ’E ’ )( ’b ’| ’B ’ )( ’l ’| ’L ’ )( ’o ’| ’O ’ )( ’c ’| ’C ’ )( ’k ’| ’K ’ );
SIGM
:
( ’s ’| ’S ’ )( ’i ’| ’I ’ )( ’g ’| ’G ’ )( ’m ’| ’M ’ );
SIN
:
( ’s ’| ’S ’ )( ’i ’| ’I ’ )( ’n ’| ’N ’ );
SINGLETONS
:
( ’s ’| ’S ’ )( ’i ’| ’I ’ )( ’n ’| ’N ’ )( ’g ’| ’G ’ )( ’l ’| ’L ’ )( ’e ’| ’E ’ )( ’t ’| ’T ’ )( ’o ’| ’O ’)
( ’n ’| ’N ’ )( ’s ’| ’S ’ );
SUM
:
( ’s ’| ’S ’ )( ’u ’| ’U ’ )( ’m ’| ’M ’ );
TAN
:
( ’t ’| ’T ’ )( ’a ’| ’A ’ )( ’n ’| ’N ’ );
TERM
:
( ’t ’| ’T ’ )( ’e ’| ’E ’ )( ’r ’| ’R ’ )( ’m ’| ’M ’ );
THEN
:
( ’t ’| ’T ’ )( ’h ’| ’H ’ )( ’e ’| ’E ’ )( ’n ’| ’N ’ );
TRAPE
:
( ’t ’| ’T ’ )( ’r ’| ’R ’ )( ’a ’| ’A ’ )( ’p ’| ’P ’ )( ’e ’| ’E ’ );
TRIAN
:
( ’t ’| ’T ’ )( ’r ’| ’R ’ )( ’i ’| ’I ’ )( ’a ’| ’A ’ )( ’n ’| ’N ’ );
TYPE_REAL
:
( ’r ’| ’R ’ )( ’e ’| ’E ’ )( ’a ’| ’A ’ )( ’l ’| ’L ’ );
VAR_INPUT
:
( ’v ’| ’V ’ )( ’a ’| ’A ’ )( ’r ’| ’R ’) ’_ ’( ’i ’| ’I ’ )( ’n ’| ’N ’ )( ’p ’| ’P ’ )( ’u ’| ’U ’ )( ’t ’| ’T ’ );
VAR_OUTPUT
:
( ’v ’| ’V ’ )( ’a ’| ’A ’ )( ’r ’| ’R ’) ’_ ’( ’o ’| ’O ’ )( ’u ’| ’U ’ )( ’t ’| ’T ’ )( ’p ’| ’P ’ )( ’u ’| ’U ’ )( ’t ’| ’T ’ );
WITH
:
( ’w ’| ’W ’ )( ’i ’| ’I ’ )( ’t ’| ’T ’ )( ’h ’| ’H ’ );
88
90
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Lexer
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92
94
96
98
// Send runs of space and tab characters to the hidden channel .
WS : ( ’ ’ | ’\ t ’ )+ { $channel = HIDDEN ; };
// Treat runs of newline characters as a single NEWLINE token .
// On some platforms , newlines are represented by a \ n character .
// On others they are represented by a \ r and a \ n character .
NEWLINE : ( ’\ r ’? ’\ n ’ )+ { $channel = HIDDEN ; };
100
102
104
106
108
110
112
114
116
// Common symbols
ASSIGN_OPERATOR : ’: ’ ’= ’;
COLON : ’: ’;
COMMA : ’ , ’;
DOT :
’. ’;
DOTS : ’ .. ’;
HAT : ’^ ’ ;
LEFT_CURLY : ’{ ’;
LEFT_PARENTHESIS : ’( ’;
MINUS : ’ - ’ ;
PERCENT : ’% ’ ;
PLUS : ’+ ’ ;
RIGHT_CURLY : ’} ’;
RI GHT _PA RENT HES IS : ’) ’ ;
SEMICOLON : ’; ’ ;
SLASH : ’/ ’ ;
STAR : ’* ’ ;
118
120
122
// A number is a set of digits
fragment NUMBER : ( DIGIT )+;
// A DIGIT
fragment DIGIT : ’0 ’ .. ’9 ’ ;
124
126
128
130
// A letter
fragment LETTER : LOWER | UPPER ;
fragment LOWER : ’a ’ .. ’z ’;
fragment UPPER : ’A ’ .. ’Z ’;
// Letter or digit
fragment ALPHANUM
:
LETTER | DIGIT ;
132
134
136
138
140
142
144
// Real number ( float / double ) without any sign
REAL :
( PLUS | MINUS )? NUMBER ( ’. ’ NUMBER )? ( ’e ’ ( PLUS | MINUS )? NUMBER )? ;
// FCL style comments
COMMENT options { greedy = false ; }
: ’ (* ’ .* ’ *) ’ NEWLINE ? { $channel = HIDDEN ; };
// ’C ’ style comments
COMMENT_C options { greedy = false ; }
: ’ /* ’ .* ’ */ ’ NEWLINE ? { $channel = HIDDEN ; };
// ’C ’ style single line comments
COMMENT_SL : ’ // ’ ~( ’\ r ’ | ’\ n ’ )* NEWLINE
{ $channel = HIDDEN ; };
146
148
150
152
// An identifier .
ID
:
LETTER ( ALPHANUM | ’_ ’ )*;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Parser
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40
KAPITEL 5. ANTLR
154
156
158
160
162
164
// FCL file may contain several funcion blocks
main : f = fcl -> ^( FCL $f );
fcl :
( function_block )+;
// Function block
function_block : FUNCTION_BLOCK ^ ( ID )? ( declaration )* EN D_ F UN C TI ON _ BL OC K !;
declaration : var_input | var_output | fuzzify_block | defuzzify_block | rule_block ;
// Variables input and output
var_input : VAR_INPUT ^ ( var_def )* END_VAR !;
var_output : VAR_OUTPUT ^ ( var_def )+ END_VAR !;
var_def : ID ^ COLON ! data_type SEMICOLON ! ( range )? ;
166
168
170
172
174
176
178
180
182
// Fuzzify
fuzzify_block : FUZZIFY ^ ID ( linguistic_term )* END_FUZZIFY !;
linguistic_term : TERM ^ ID ASSIGN_OPERATOR ! m em b e r s h i p _ f un c t i o n SEMICOLON !;
m e m b er s h i p _ f u n ct i o n : function | singleton | singletons | pi ece _wi se_ lin ear | gauss | trian |
trape | sigm | gbell | cosine | dsigm ;
cosine : COSINE ^ atom atom ;
dsigm : DSIGM ^ atom atom atom atom ;
gauss : GAUSS ^ atom atom ;
gbell : GBELL ^ atom atom atom ;
pi ece _wi se_l ine ar : ( points )+;
sigm : SIGM ^ atom atom ;
singleton : atom ;
singletons : SINGLETONS ^ ( points )+ ;
trape : TRAPE ^ atom atom atom atom ;
trian : TRIAN ^ atom atom atom ;
points : LEFT_PARENTHESIS x = atom COMMA y = atom RIG HT_ PAR ENT HES IS -> ^( POINT $x $y );
atom : ID | REAL ;
184
186
188
190
192
194
196
// Functions ( for singletons )
function : FUNCTION ^ fun_pm ;
fun_pm : fun_md (( PLUS ^ | MINUS ^ ) fun_md )*;
fun_md : fun_mp (( STAR ^ | SLASH ^) fun_mp )*;
fun_mp : fun_atom (( HAT ^ | PERCENT ^) fun_atom )*;
fun_atom : atom | ( EXP ^| LN ^| LOG ^| SIN ^| COS ^| TAN ^| ABS ^)? LEFT_PARENTHESIS ! fun_pm RI GHT _PA RENT HES IS !;
// Defuzzify
defuzzify_block : DEFUZZIFY ^ ID ( defuzzify_item )* END_DEFUZZIFY !;
defuzzify_item : d e f u z z i f i c a t i o n _ m e t h o d | default_value | linguistic_term | range ;
range : RANGE ^ ASSIGN_OPERATOR ! LEFT_PARENTHESIS ! REAL DOTS ! REAL R IGHT _PA REN THE SIS ! SEMICOLON !;
d e f u z z i f i c a t i o n _ m e t h o d : METHOD ^ COLON ! ( COG | COGS | COGF | COA | LM | RM | MM ) SEMICOLON !;
default_value : DEFAULT ^ ASSIGN_OPERATOR ! ( REAL | NC ) SEMICOLON !;
198
200
202
204
206
208
210
212
214
216
// Ruleblock
rule_block : RULEBLOCK ^ ID ( rule_item )* END_RULEBLOCK !;
rule_item : o p e r a t o r _ d ef i n i t i o n | a ctiv ati on_ met hod | a cc u m u l a t i o n _m e t h o d | rule ;
o p e r at o r _ d e f i n it i o n : o p e r a t o r _ d e f i n i t i o n _ o r | o p e r a t o r _ d e f i n i t i o n _ a n d ;
o p e r a t o r _ d e f i n i t i o n _ o r : OR ^ COLON ! ( MAX | ASUM | BSUM ) SEMICOLON !;
o p e r a t o r _ d e f i n i t i o n _ a n d : AND ^ COLON ! ( MIN | PROD | BDIF ) SEMICOLON !;
ac tiv ati on_m eth od : ACT ^ COLON ! ( PROD | MIN ) SEMICOLON !;
a c c u mu l a t i o n _ m et h o d : ACCU ^ COLON ! ( MAX | BSUM | NSUM | PROBOR | SUM ) SEMICOLON !;
rule : RULE ^ rule_name COLON ! if_clause then_clause ( with )? SEMICOLON ! ;
rule_name : ID | REAL ;
if_clause : IF ^ condition ;
then_clause : THEN ^ conclusion ;
condition : subcondition (( AND ^| OR ^) subcondition )*;
subcondition : ( NOT ^)? ( s ubco ndi tio n_b are | s u bc o nd it i on _p a re n );
su bco ndi tion _ba re : ID ^ ( IS ! ( NOT )? ID )? ;
s ub c on di t io n_ p ar e n : LEFT_PARENTHESIS ! condition R IGH T_P ARE NTHE SIS !;
conclusion : sub_conclusion ( COMMA ! sub_conclusion )?;
sub_conclusion : ID ^ IS ! ID ;
with : WITH ^ REAL ;
218
220
// Data type
data_type : TYPE_REAL ;
B. FCLTreeWalker.g
1
3
5
7
9
tree grammar FCLTreeWalker ;
options {
tokenVocab = Fcl ;
ASTLabelType = CommonTree ;
output = AST ;
}
@header {
package de . lab4inf . fcl ;
41
KAPITEL 5. ANTLR
11
13
15
17
19
21
23
25
27
29
31
import org . apache . log4j . Logger ;
import java . util . Map ;
import java . util . ArrayList ;
import
import
import
import
}
de . lab4inf . fcl . F C L T r e e W a l k e r P a r t i t i o n B u i l d e r ;
de . lab4inf . fcl . F C L T r e e W a l k e r R u l e B u i l d e r ;
de . lab4inf . fuzzy . FuzzyPartition ;
de . lab4inf . fuzzy . controller . FuzzyRule ;
@members {
private F C L T r e e W a l k e r P a r t i t i o n B u i l d e r partitionBuilder = new F C L T r e e W a l k e r P a r t i t i o n B u i l d e r ();
private F C L T r e e W a l k e r R u l e B u i l d e r ruleBuilder = new F C L T r e e W a l k e r R u l e B u i l d e r ();
private String setType = null ;
private String norm = null ;
private String accu_method = null ;
private String a ctiv ati on_ met hod = null ;
private static Logger logger = Logger . getLogger ( " de . lab4inf . fuzzy " );
public Map < String , FuzzyPartition > getPartitions () {
return partitionBuilder . getPartitions ();
}
33
public ArrayList < FuzzyRule > getRules () {
return ruleBuilder . getRules ();
35
}
37
public String getNormName () {
return norm ;
39
}
41
public String get Acc uMe tho dNa me () {
return accu_method ;
43
}
45
public String g e t A c t i v a t i o n M e t h o d N a m e () {
return ac tiv ati on_ meth od ;
47
}
}
49
51
53
55
57
59
main :
fcl :
^( FCL fcl );
( function_block )+ { logger . info ( " Walker Start " );};
// Function block
function_block : ^( FUNCTION_BLOCK ( ID )? ( declaration )*);
declaration : var_input | var_output | fuzzify_block | defuzzify_block | rule_block ;
// Variables input and output
var_input : ^( VAR_INPUT ( var_def )*);
var_output : ^( VAR_OUTPUT ( var_def ));
var_def : ^( ID data_type ) ;
61
63
65
67
69
71
73
75
77
79
81
83
85
87
89
91
93
// Fuzzify
fuzzify_block : ^( FUZZIFY ID ( linguistic_term )*) { logger . info ( " Walker : fuzzify_block : " + $ID . text );
partitionBuilder . newPartition ( $ID . text );
};
linguistic_term : ^( TERM ID m e m b er s h i p _ f u n c ti o n ) { logger . info ( " Walker : Linguistic Term : " + $ID . text );
partitionBuilder . newSet ( $ID . text , setType );
};
m e m b er s h i p _ f u n ct i o n : function | singleton | singletons | pi ece _wi se_ lin ear | gauss | trian | trape
| sigm | gbell | cosine | dsigm ;
cosine : ^( COSINE atom atom ){
setType = " cosine " ;
logger . info ( " POLYGON " );
};
dsigm : ^( DSIGM atom atom atom atom ){
setType = " dsigm " ;
logger . info ( " POLYGON " );
};
gauss : ^( GAUSS center = atom delta = atom ){
double pCenter = Double . parseDouble ((( Tree )( center . getTree ())). toStringTree ());
double pDelta = Double . parseDouble ((( Tree )( delta . getTree ())). toStringTree ());
partitionBuilder . addPoint ( pCenter , 0);
partitionBuilder . addPoint ( pDelta , 0);
setType = " gauss " ;
logger . info ( " POLYGON " );
};
gbell : ^( GBELL atom atom atom ){
setType = " gbell " ;
logger . info ( " GBELL " );
};
pi ece _wi se_l ine ar : ( points )+ {
setType = " polygon " ;
logger . info ( " POLYGON " );
};
42
KAPITEL 5. ANTLR
95
97
99
101
103
105
107
109
111
113
115
117
119
121
123
125
127
129
131
133
135
sigm : ^( SIGM atom atom ){
setType = " sigm " ;
logger . info ( " SIGM " );
};
singleton : x0 = atom {
double pX0 = Double . parseDouble ((( Tree )( x0 . getTree ())). toStringTree ());
partitionBuilder . addPoint ( pX0 , 0);
setType = " singelton " ;
logger . info ( " SINGLETON " );
};
singletons : ^( SINGLETONS ( points )+) {
setType = " singeltons " ;
logger . info ( " SINGLETONS " );
};
trape : ^( TRAPE l = atom ml = atom mr = atom r = atom ) {
setType = " trapez " ;
logger . info ( " TRAPE " );
double lp = Double . parseDouble ((( Tree )( l . getTree ())). toStringTree ());
double mlp = Double . parseDouble ((( Tree )( ml . getTree ())). toStringTree ());
double mrp = Double . parseDouble ((( Tree )( mr . getTree ())). toStringTree ());
double rp = Double . parseDouble ((( Tree )( r . getTree ())). toStringTree ());
partitionBuilder . addPoint ( lp , 0);
partitionBuilder . addPoint ( mlp , 0);
partitionBuilder . addPoint ( mrp , 0);
partitionBuilder . addPoint ( rp , 0);
};
trian : ^( TRIAN left = atom mean = atom right = atom ) {
double leftp = Double . parseDouble ((( Tree )( left . getTree ())). toStringTree ());
double meanp = Double . parseDouble ((( Tree )( mean . getTree ())). toStringTree ());
double rightp = Double . parseDouble ((( Tree )( right . getTree ())). toStringTree ());
partitionBuilder . addPoint ( leftp , 0);
partitionBuilder . addPoint ( meanp , 0);
partitionBuilder . addPoint ( rightp , 0);
setType = " triangle " ;
logger . info ( " TRIAN " );
};
points : ^( POINT x = atom y = atom ) {
double xp = Double . parseDouble ((( Tree )( x . getTree ())). toStringTree ());
double yp = Double . parseDouble ((( Tree )( y . getTree ())). toStringTree ());
partitionBuilder . addPoint ( xp , yp );
logger . info ( " POINT : " + (( Tree )( x . getTree ())). toStringTree () + " " + (( Tree )( y . getTree ())). toStringTree ());};
atom : ID | REAL ;
137
139
141
143
145
147
149
151
153
155
157
159
// Functions ( for singletons )
function : FUNCTION ^ fun_pm ;
fun_pm : fun_md (( PLUS ^ | MINUS ^ ) fun_md )*;
fun_md : fun_mp (( STAR ^ | SLASH ^) fun_mp )*;
fun_mp : fun_atom (( HAT ^ | PERCENT ^) fun_atom )*;
fun_atom : atom | ( EXP ^| LN ^| LOG ^| SIN ^| COS ^| TAN ^| ABS ^)? LEFT_PARENTHESIS ! fun_pm RI GHT _PA RENT HES IS !;
// Defuzzify
defuzzify_block : ^( DEFUZZIFY ID ( defuzzify_item )*) {
logger . info ( " Walker : defuzzify_block : " + $ID . text );
partitionBuilder . newPartition ( $ID . text );};
defuzzify_item : d e f u z z i f i c a t i o n _ m e t h o d | default_value | linguistic_term | range ;
range : ^( RANGE REAL );
defuzzification_method :
^( METHOD ( COG )) { logger . info ( " Defuzzifaction Method = COG " );}
|^( METHOD ( COGS ))
|^( METHOD ( COGF ))
|^( METHOD ( COA ))
|^( METHOD ( LM ))
|^( METHOD ( RM ))
|^( METHOD ( MM ));
// d e f u z z i f i c a t i o n _ m e t h o d : ^( METHOD COG );
default_value : ^( DEFAULT ( REAL | NC ));
161
163
165
167
169
171
173
175
177
// Ruleblock
rule_block : ^( RULEBLOCK ID ( rule_item )*) { logger . info ( " Walker : rule_block : " + $ID . text );};
rule_item : o p e r a t o r _ d ef i n i t i o n | a ctiv ati on_ met hod | a cc u m u l a t i o n _m e t h o d | rule ;
o p e r at o r _ d e f i n it i o n : o p e r a t o r _ d e f i n i t i o n _ o r | o p e r a t o r _ d e f i n i t i o n _ a n d ;
o p e r a t o r _ d e f i n i t i o n _ o r : ^( OR ( MAX { norm = " FuzzyMinMax " ;}| ASUM { norm = " FuzzyAlgebraic " ;}|
BSUM { norm = " FuzzyBoundedNorm " ;}));
o p e r a t o r _ d e f i n i t i o n _ a n d : ^( AND ( MIN { norm = " FuzzyMinMax " ;}| PROD { norm = " FuzzyAlgebraic " ;}|
BDIF { norm = " FuzzyBoundedNorm " ;}));
ac tiv ati on_m eth od : ^( ACT ( PROD { act iva tio n_m etho d = " FuzzyAlgebraic " ;}|
MIN { ac tiv ati on_m eth od = " FuzzyMinMax " ;}));
a c c u mu l a t i o n _ m et h o d : ^( ACCU ( MAX { accu_method = " FuzzyMinMax " ;}| BSUM { accu_method = " FuzzyBoundedNorm " ;}));
rule : ^( RULE rule_name if_clause then_clause ( with )?);
rule_name : ID {
ruleBuilder . setPartitions ( partitionBuilder . getPartitions ());
ruleBuilder . setRuleName ( $ID . text );
logger . info ( " Walker : rule_name ( ID ): " + $ID . text );}
| REAL {
43
KAPITEL 5. ANTLR
179
181
183
185
187
189
191
193
195
197
199
ruleBuilder . setPartitions ( partitionBuilder . getPartitions ());
ruleBuilder . setRuleName ( $REAL . text );
logger . info ( " Walker : rule_name ( REAL ): " + $REAL . text );};
if_clause : ^( IF condition );
then_clause : ^( THEN conclusion ) { logger . info ( " Walker : then_clause " );};
condition : ^( OR condition condition ) { ruleBuilder . addOrRelation ();
logger . info ( " Walker : condition ( OR ) " );}
|
^( AND condition condition ) { ruleBuilder . addAndRelation ();
logger . info ( " Walker : condition ( AND ) " );}
|
subcondition { logger . info ( " Walker : condition " );};
// condition : subcondition (( AND ^| OR ^) subcondition )*;
subcondition : ( NOT ^)? ( s ubco ndi tio n_b are );
su bco ndi tion _ba re : ^( x = ID ( ( NOT )? y = ID )?) {
ruleBuilder . addVariable ( $x . text , $y . text );
logger . info ( " Walker : su bco ndi tion _ba re " + $x . text + " " + $y . text );};
// s ub c on d it io n _p a re n : condition ;
conclusion : sub_conclusion ( sub_conclusion )* { ruleBuilder . c l e a r C on d i t i o n S t ac k ();};
sub_conclusion : ^( x = ID y = ID ) { ruleBuilder . addConclusion ( $x . text , $y . text ); ruleBuilder . newRule ();} ;
with : ^( WITH REAL );
// Data type
data_type : TYPE_REAL ;
201
203
atom1
atom2
:
:
atom ;
atom ;
44
6. Jefis Ruleengine
Listing 6.1: FCL-Datei Applet Beispiel
FUNCTION_BLOCK applet
2
4
6
8
10
VAR_INPUT
service : REAL ;
food : REAL ;
END_VAR
VAR_OUTPUT
tip : REAL ;
waiter : REAL ;
END_VAR
12
14
16
FUZZIFY service
TERM poor := (0 , 1) (4 , 0);
TERM good := (1 , 0) (4 ,1) (6 ,1) (9 ,0);
TERM excellent := (6 , 0) (9 , 1);
END_FUZZIFY
18
20
22
24
26
28
30
32
34
36
38
FUZZIFY food
TERM rancid := (0 , 1) (1 , 1) (3 ,0);
TERM delicious := (7 ,0) (9 ,1);
END_FUZZIFY
DEFUZZIFY tip
TERM cheap := (0 ,0) (5 ,1) (10 ,0);
TERM average := (10 ,0) (15 ,1) (20 ,0);
TERM generous := (20 ,0) (25 ,1) (30 ,0);
END_DEFUZZIFY
DEFUZZIFY waiter
TERM sad := ( -1.1 ,0) ( -1 ,1) (0 ,1) (3 ,0);
TERM normal := (2 ,0) (4 ,1) (5 ,1) (7 ,0);
TERM happy := (6 ,0) (9 ,1) (9.5 ,1) (9.6 ,0);
END_DEFUZZIFY
RULEBLOCK No1
RULE 1 : IF service IS good AND food IS delicious THEN tip IS generous ;
RULE 2 : IF tip IS generous THEN waiter IS happy ;
END_RULEBLOCK
40
E ND _ FU NC T IO N_ B LO C K
45
Abbildungsverzeichnis
1.1.
1.2.
1.3.
1.4.
1.5.
1.6.
1.7.
1.8.
1.9.
Beispiel Fuzzy Partition für einen Wertebereich von 0 bis 80
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Beispiel Fuzzy-Regler in einem Schaltbild . . . . . . . . . .
Flugbahn und Geschwindigkeitskorrektur über Fuzzy . . . .
Schaltplan der Flugbahn und Geschwindigkeitskorrektur . .
Bierglas auf Inversen Pendel; Fuzzysets des Beispiels . . . .
Regeln des Inversen Pendels . . . . . . . . . . . . . . . . . .
Komponenten eines Regelbasierten Systems [Bec] . . . . . .
UML Diagramm der wichtigsten Jefis Klassen [NW09] . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. 4
. 5
. 6
. 8
. 8
. 9
. 9
. 10
. 13
2.1. Auflistung der unterschiedlichen Rete-OO Knoten . . . . . . . . . . . . . . 16
2.2. Baum für die im Listing gezeigte Regel . . . . . . . . . . . . . . . . . . . . 17
2.3. Klassendiagramm des Jefis-Drools-Adapters . . . . . . . . . . . . . . . . . 20
3.1. Applet zur Visualisierung der Implikation . . . . . . . . . . . . . . . . . . 24
4.1. Der erzeugte Beispielbaum. . . . . . . . . . . . . . . . . . . . . . . . . . . 35
46
Literaturverzeichnis
[Bec]
Becker, P.: Wissensbasierte Systeme II. Vorlesung an der FH Bonn Rhein
Sieg.
[Bei06]
Beierle, C. und Kern-Isberner, G.: Methoden wissensbasierter Systeme:
Grundlagen-Algorithmen-Anwendungen. Vieweg + Teubner Verlag, 2006.
[Dre]
Drexl, M.N. und Koch, M.: Modellierung von Gesch
äftsregeln. Modellbasierte Softwareentwicklung, Seite 103.
[dro10]
JBoss Drools Documentation Drools Expert“.
Website, Juni 2010.
”
Verfügbar online unter http://downloads.jboss.com/drools/docs/5.0.
1.26597.FINAL/drools-expert/html_single/index.html; besucht am 18.
Juni 2010.
[DS08]
Davide Sottara, Paola Mello und Mark Proctor: Rule Representation, Interchange and Reasoning on the Web, Kapitel Adding uncertainty to
a Rete-OO inference engine, Seiten 104–118. Springer, 2008.
[DWM08] Dr. Wolfgang Martin, Thomas Cotic und Lars Wunderlich: Das
Ende des Software-Release-Zyklus? - Business Rules Management. Jaxenter,
2008.
[iec10]
FCL Entwurf der IEC. Website, Juni 2010. Verfügbar online unter http:
//www.fuzzytech.com/binaries/ieccd1.pdf; besucht am 18. Juni 2010.
[mve10]
MVEL Codehaus Projektseite. Website, Juni 2010. Verfügbar online unter
http://mvel.codehaus.org/; besucht am 18. Juni 2010.
[Nel05]
Nellessen, P.: Vortriebssynchrone Prognose der Setzungen bei Fl
üssigkeitsschildvortrieben auf Basis der Auswertung der Betriebsdaten mit
Hilfe eines Neuro-Fuzzy-Systems. Cuvillier Verlag, 2005.
[NW09]
Nikolaus Wulff, Davide Sottara: Rule Interchange and Applications,
Kapitel Fuzzy Reasoning with a Rete-OO Rule Engine. Springer Berlin /
Heidelberg, 2009.
[Pul00]
Pullmann, T.: Implementierung eines wissensbasierten Softwaresystems
zum Entwurf und zur Bemessung von Stahlbeton-Tragwerken. TU Darmstadt,
Vertieferarbeit, 2000.
47
Literaturverzeichnis
[Sot10a]
Sottora, D.: Blog Drools Chance. Website, Juni 2010. Verfügbar online
unter http://blog.athico.com/search/label/Drools%20Chance; besucht
am 18. Juni 2010.
[Sot10b]
Sottora, D.: Drools Chance Repisitory. Website, Juni 2010. Verfügbar
online unter https://svn.jboss.org/repos/labs/labs/jbossrules/
branches/DroolsChance; besucht am 18. Juni 2010.
48

Documentos relacionados