2. Probleme beim Ansatz Matching Tree

Werbung
Ausarbeitung
zum Seminar
„Active Data Managment“
an der Freien Universität Berlin,
Fachbereich Mathematik und Informatik
Sommersemester 2001
THEMA:
Prädikat-Matching Algorithmen in
Benachrichtigungssystemen
Betreuung:
Prof. Dr. H. Schweppe
Annika Hinze
Torsten Schlieder
vorgelegt von:
Sven Bittner
A. Einführung
Benachrichtigungssysteme basieren auf folgender Idee: Auf der einen Seite stehen die Anbieter. Sie
verfügen über eine große Anzahl von Informationen, die einem breiten Publikum zugänglich gemacht
werden sollen. Dazu schicken die Anbieter ihre Informationen an verschiedene Kanäle, welche durch
Themengebiete gekennzeichnet sind. Die Abonnenten auf der anderen Seite, können sich bei einem
oder mehreren dieser Kanäle anmelden. Sie erhalten dann alle Informationen, die über diesen Kanal
eintreffen.
Eine Erweiterung dieses klassischen Ansatzes sind inhaltsbasierte Benachrichtigungssysteme. Die
Abonnenten können hier Einfluss nehmen, welche Artikel an sie weitergeleitet werden. Eine einfache
Art der Einflussnahme ist durch Angabe von Stichworten möglich. Die eintreffenden Informationen
werden auf diese getestet und nur bei Übereinstimmung weitergeleitet. Als besserer Ansatz ist der
folgende vorstellbar: Zur Beschreibung der Art und des Inhalts werden die Artikel von den Anbietern
durch verschiedene Attribute gekennzeichnet. Ein Abonnent kann nun anhand seiner Interessen, für
ihn in Frage kommende Attribute bestimmen und so festlegen, welche Informationen an ihn
weitergeleitet werden sollen. Diese Inhaltsbestimmung nennt man auch Profil. Vorteil eines solchen
Systems ist es, dass sowohl die Anbieter den Inhalt ihrer Informationen genau spezifizieren können,
als auch die Abonnenten in der Lage sind, ihre Interessen genau anzugeben. Eine Stichwortsuche auf
den Artikeln ist nicht mehr notwendig. Damit entfallen auch die dadurch entstehenden Fehler, da
bekanntlich das Vorhandensein oder die Abwesenheit von Schlüsselwörtern nicht auf einen Inhalt der
Artikel schließen lassen. Somit wird die Qualität des Filterns von relevanten Artikeln extrem erhöht,
vorausgesetzt die Attribute entsprechen auch den Tatsachen. Ebenfalls ist es möglich Nicht-TextArtikel an interessierte Abonnenten zu verteilen.
Bei der Umsetzung dieses Ansatzes kommt es grundlegend darauf an, wie schnell es möglich ist,
einen eintreffenden Artikel, im folgenden auch Event/Ereignis genannt, an alle interessierten
Abonnenten weiterzureichen. Charakteristisch für ein solches Benachrichtigungssystem sind eine
große Zahl von Abonnenten und viele zu unbekannten Zeitpunkten eintreffende Events.
Im folgenden werden verschiedene Ideen zur Implementierung solcher Systeme betrachtet. Zuerst
wird ein allgemeiner Algorithmus analysiert. Danach die Ansätze der Arbeiten „Matching Events in a
Content-based Subscription System“ [1] und „Efficient Recognition of Events in a Distributed System“
[2] aufgezeigt und verglichen. Schließlich folgt in Abschnitten E ff eine Einordnung der genannten
Ideen, Kritikpunkte und die Betrachtung weitergehender Fragestellungen, welche in beiden Arbeiten
offen bleiben.
B. Naive Lösung/einfacher Algorithmus
Bei einer ersten Betrachtung des Problems des Zuordnen der Artikel zu den Abonnenten gelangt man
zu folgender Lösung: Teste für alle Abonnenten, ob ein eintreffendes Ereignis relevant ist.
Als Vorteil dieser Lösung ist die einfache Implementierung zu sehen. Man geht die gesamte
Abonnentenmenge durch und testet, ob die Attribute den spezifizierten Anforderungen genügen.
Nachteilig hingegen stellt sich die Laufzeit dar. Bei einer Gesamtzahl von n Abonnenten und einer
Testzeit von f für ein Ereignis, liegt die Laufzeit bei O(n*f). Angesichts der großen Zahl zu erwartender
Abonnenten und in hohen Frequenzen eintreffender Artikel wären andere Algorithmen, deren
Laufzeiten nicht im linearen Verhältnis zur Abonnentenzahl liegen, als besser geeignet anzusehen.
Zwei solche Ideen werden im folgenden betrachtet. Einer der Hauptunterschiede ist, dass nicht mehr
die einzelnen Abonnenten überprüfen, ob ein Ereignis relevant ist, sondern die Ereignisse sich die
passenden Abonnenten suchen.
C. Lösung durch Aufbau eines Matching Tree
Im folgenden wird eine Zusammenfassung des Artikels „Matching Events in a Content-based
Subscription System“ [1] gegeben. Eine Wertung des Ansatzes folgt im späteren Verlauf in den
Abschnitten E ff.
1. Problemverfeinerung/weitere Annahmen
Zur Nutzung der vorgestellten Ideen in einem Benachrichtigungssystem sind einige besondere
Annahmen zur Einschränkung des Problembereichs zu machen. Ein jeder Abonnent sub wird als
Konjunktion von Prädikaten angesehen. Dabei soll jedes Prädikat einen einfachen Test auf genau
einem Attribut eines Events darstellen. Solch ein einfacher Test kann z.B. auf Gleichheit, Ungleichheit
oder Enthaltensein in einem Bereich überprüfen. Ein jedes Prädikat liefert einen booleschen Wert,
welcher dem Zutreffen des Test entspricht. Durch Konjunktion dieser einzelnen Werte erhält man
dann ein Gesamtergebnis. Dieses steht entweder für Interesse oder Nichtinteresse des Abonnenten
am getesteten Event.
Eine formale Definition eines Abonnenten könnte so aussehen:
sub := pr1 AND pr2 AND ... AND prk
pri := testi( event )  resi (der Test testi soll als Ergebnis resi liefern)
Suchen wir z.B. Personen, welche durch Wohnort und Geburtstag gekennzeichnet sind, wären
folgende Prädikate denkbar:
pr1 = test1( event )  „Berlin“
pr2 = test2( event )  „<“
test1 = werte Attribut Wohnort aus
test2 = vergleiche Attribut Geburtstag mit dem Datum 01.01.1979
Weiterhin wird eine vorgegebene Reihenfolge der möglichen Attribute vorausgesetzt. Nicht alle
Attribute müssen von den Abonnenten spezifiziert werden, da ihnen die Möglichkeit gelassen werden
soll, vom Wert eines oder mehrerer Attribute unabhängig zu sein. Dieser Fall wird als don’t care
bezeichnet.
Der vorgeschlagene Algorithmus zerlegt die Lösung des Problems in zwei Phasen. In der ersten wird
eine interne Datenstruktur, der Matching Tree, aufgebaut und in der anderen, die Auswertung der
eintreffenden Events auf Grundlage dieses Matching Tree durchgeführt.
2. Aufbau/Abarbeitung des Matching Tree
Der Matching Tree stellt in seiner Struktur einen Baum dar. Die Blätter des Baumes enthalten die
Abonnenten (Subscribers). Ein jeder innerer Knoten stellt einen Test dar. Die Kanten sind als
Ergebnisse dieser Tests zu sehen. Ein don’t care Fall wird durch eine *-Kante symbolisiert. Testet
man beispielsweise das Attribut auf Gleichheit (test1 im obigen Beispiel), so stellen die Kanten die
Vergleichswerte dar. Ein Beispiel eines Baumes mit Gleichheitstests ist in Bild1 zu sehen (die
eingezeichneten Pfeile sind erst einmal zu ignorieren).
a) Algorithmus zum Baumaufbau
In den Matching Tree werden alle Abonnenten mit ihren Prädikaten eingetragen. Dazu werden diese
und deren Prädikate nacheinander betrachtet. Dabei wird der Baum durchlaufen und bei Bedarf
ergänzt.
Jeder Abonnent startet seine Betrachtungen in der Baumwurzel. Entweder ist der Test im betrachteten
Knoten mit dem Attributtest des aktuellen Abonnenten identisch. Dann wird eine Kante mit dem
Ergebnis des Abonnenten gesucht. Ist sie vorhanden, wird ihr gefolgt. Sonst wird eine derartige Kante
erzeugt (sie zeigt auf einen neuen leeren Knoten) und dieser gefolgt. Danach bearbeitet man das
nächste Attribut. Schwieriger wird es, wenn der Knotentest und der aktuelle Abonnententest nicht
übereinstimmen. Hat der Knoten keine *-Kante, so fügt man eine solche dazu und trägt den
Abonnententest in deren Folgeknoten ein. Danach wird das nächste Attribut bearbeitet. Ist schon eine
*-Kante vorhanden, so folgt man dieser und versucht, den Test im nächsten Knoten einzutragen. Sind
alle Prädikate in den Baum übertragen, wird der Abonnent dem Knoten hinzugefügt (der Knoten ist
dann entweder leer oder er ist schon ein Blatt mit Abonnenten).
b) Algorithmus zum Finden der relevanten Abonnenten
Das Finden der Abonnenten besteht in einer Abarbeitung der erzeugten Baumstruktur. Dabei kann
sowohl Tiefen- als auch Breitensuche verwendet werden. Für einen Event gestaltet sich dies
folgendermaßen (es wird Tiefensuche durchgeführt).
Beginne in der Wurzel. Führe den Test des aktuellen Knotens auf dem Event aus. Folge der Kante mit
dem richtigen Testergebnis und arbeite den nächsten Knoten ab. Gibt es eine don’t care Kante, so
folge auch dieser. Die erreichten Blätter stellen die am Artikel interessierten Abonnenten dar. Erreicht
man keine Blätter, so gibt es keine relevanten Abonnenten.
Der folgende Pseudocode soll diese Idee noch einmal verdeutlichen.
procedure match( tree, event )
visit( tree, root, event )
procedure visit( tree, v, event )
IF v ist Blatt THEN Abonnenten in v sind relevant
ELSE
führe den Test in v auf event aus
IF v hat Kante e mit Testergebnis
THEN visit( tree, Zielknoten von e, event )
IF v hat *-Kante e
THEN visit( tree, Zielknoten von e, event )
3. Analyse der Algorithmen
Im folgenden werden Speicher- und Zeitbedarf der beiden Algorithmen aufgezeigt. Dabei wird die
Analyse auf den Fall beschränkt, dass alle Tests die Gleichheit eines Attributes überprüfen.
Im genannten Spezialfall erhält man immer einen Baum der Höhe k, wobei k, hier wie im folgenden,
die Zahl der Attribute/Prädikate darstellen soll. Das beruht auf der Tatsache, dass jeder Abonnent
beim Eintragen in den Baum entweder eine passende Kante findet, oder die benötigte zum Knoten
hinzufügt. Ein Übergehen eines Knotens, wegen einer anderen Art des Tests, bleibt aus. In jeder
Ebene i des Baumes befinden sich Knoten, welche genau das i. Attribut eines Events testen. Die
ausgehenden Kanten sind mögliche Werte des Attributes.
a) Zeitverhalten für den Baumaufbau
Um einen Abonnenten in den Baum einzutragen, müssen alle seine Attribute abgearbeitet werden.
Dabei ist entweder Kanten zu folgen oder eine Kante und ein neuer Knoten in den Baum einzutragen.
Bei k Attributen ergibt sich ein Aufwand von O(k+1), wenn man die Zahl Knotenbesuche als
ausschlaggebende Operation ansieht. Sind insgesamt n Abonnenten vorhanden, ergibt sich eine
Gesamtlaufzeit von O(n*k).
b) Speicherplatz für den Baum
Für jeden der n Abonnenten werden im schlimmsten Fall k+1 Knoten zum Baum hinzugefügt. k
Knoten enthalten dabei einen Test und einer stellt ein Blatt, mit dem Abonnenten als Inhalt, dar.
Zusätzlich wird der Baum um maximal k Kanten erweitert. Also ergibt sich ein Speicheraufwand von
O(n*k). Somit ist sowohl bei Aufbauzeit als auch bei Speicher für den Baum Linearität zur Anzahl der
Abonnenten gegeben.
c) Zeitverhalten zum Finden der relevanten Abonnenten
Als Zeitmaß soll wieder die Anzahl der besuchten Knoten angenommen werden. Die Auswertung des
Gleichheitstests und das Finden des Folgeknotens ist in konstanter Zeit möglich und das Folgen der
Kanten ebenfalls. Praktisch umsetzbar wäre das z.B. mit Hashtabellen, welche die Werte der Attribute
als Schlüssel und die Kanten des Baumes als Einträge enthalten. Eintragen und Suchen in
Hashtabellen ist durchschnittlich in konstanter Zeit möglich [3].
Die Zahl der besuchten Knoten ist von mehreren Faktoren abhängig. Je mehr Attribute vorhanden
sind, desto höher ist der Baum und somit auch der Weg zu einem möglichen Blatt. Haben viele
Abonnenten don’t care Tests, müssen häufig zwei Pfade verfolgt werden. Auch der Event selbst ist für
den zu wählenden Pfad entscheidend, also für die Zahl der Knotenbesuche.
Eine einfache obere Schranke der Knotenbesuche ergibt sich wie folgt. Man stelle sich einen Baum
vor, dessen Knoten jeweils genau zwei Kanten enthalten. Zum einen eine don’t care Kante und zum
anderen eine Kante mit dem beliebigen Wert v. Um einen Event zu testen, dessen Attribute alle aus
dem Wert v bestehen, müssen nun sämtliche Knoten des Baumes besucht werden. Die Anzahl der
Knoten liegt zwischen n und k*n, wenn n Abonnenten in den Baum eingetragen sind. Somit ist die
Suchzeit im schlimmsten Fall proportional zur Anzahl der Abonnenten und Attribute.
Eine andere obere Schranke ist wie folgt zu erhalten. In jeder Ebene des Baumes verfolgt man
maximal 2 Kanten (einer mit einem Wert und einer don’t care Kante). Also werden insgesamt maximal
2^0 + 2^1 +2^2 + ... + 2^k = 2^(k+1)-1 Knoten besucht. Diese Zahl ist zwar unabhängig von der
Abonnentenzahl, jedoch exponentiell in der Anzahl der Attribute. Ein ebenfalls unbefriedigendes
Resultat.
Im besten Fall enthält der Baum oder der zu nehmende Weg keine don’t care Kanten. Dann wird pro
Ebene genau einer Kante gefolgt. Insgesamt werden k Knoten besucht, die Abarbeitung ist also in
konstanter Zeit möglich (es gibt eine feste Zahl von Attributen).
Aufgrund dieser Ergebnisse analysieren die Autoren nun die zu erwartende Zeit zum Finden der
Abonnenten für einen zufälligen Event in einem zufälligen Baum. Dabei erhalten sie eine Laufzeit,
welche sublinear von der Zahl der Abonnenten abhängt. Die Größe des zu erwartenden Exponenten
ist dabei von Art und Anzahl der Attribute des Systems anhängig. In einigen Fällen liegt er bei 0,5. Der
Beweis ist in der Originalarbeit in Abschnitt 4 nachzulesen.
4. Optimierungen
Durch Änderungen beim Aufbau des Baumes kann eine Verbesserung der Laufzeit des
Suchalgorithmus erreicht werden. Da die Minimierung dieser Zeit die Effektivität des Algorithmus
widerspiegelt, kann eine Vergrößerung des Speicherbedarfs als kalkulierbar hingenommen werden.
Eine Möglichkeit der Optimierung gestaltet
sich wie folgt. Enthält ein Knoten v des
Baumes nur eine don’t care Kante (v,w), so
kann dessen Elternknoten direkt auf w
zeigen. Knoten v kann aus dem Baum
entfernt werden. In Bild1 könnte also Knoten
A direkt durch Knoten B ersetzt werden
(zweifache
Anwendung
der
Regel).
Praktische Tests ergaben bei dieser Art der
Optimierung Verbesserungen der Suchzeit
um bis zu 60%.
Eine weitere Optimierung kann durch
Minimierung der Zahl der Auswertungen ein
und desselben Attributes erzielt werden. Es
wird versucht zu verhindern, dass mehrere
Pfade im Baum aufgrund von don’t care
Kanten besucht werden. *-Kanten wird nun
per Definition nur bei Knoten ohne andere
Kanten gefolgt. Nach dem Baumaufbau
werden in jedem Knoten zusätzlich Kanten
zu den Knoten gespeichert, welche durch
Ersetzen von Attributen im bisherigen Weg
durch einen don’t care Fall, erreichbar sind.
Bild1. Matching Tree
Beim Auswerten werden alle diese
Folgeknoten betrachtet und als mögliche
Wege bearbeitet. Das Folgen von *-Kanten ist somit hinfällig, außer ein Knoten enthält nur diese eine
Kante, was bei der ersten Optimierung auch entfällt. In Bild1 werden in Knoten C (Weg 123) die
Knoten D (Weg ***), E (Weg **3), F (Weg *2*), G (Weg 1*3), H (Weg 12*) und K (Weg 1**) als
Folgeknoten gespeichert. Nicht hingegen Knoten A (Weg 1*1), da das 3. Attribut nicht mit dem 3.
Attribut von Knoten C übereinstimmt. Die Werte aller dieser Folgeknoten werden nun beim Auswerten
von C betrachtet. Jedoch erhöht sich bei dieser Optimierung der notwendige Speicherplatz. Praktisch
ergaben sich dadurch Verbesserungen von bis zu 20%.
Das Erzeugen von mehreren Bäumen kann ebenfalls zur Effizienzsteigerung genutzt werden.
Attribute, welche von kaum einem Abonnenten als don’t care gekennzeichnet sind, werden als
Einstieg in die verschiedenen Bäume genutzt. Eine Anwendung ist sogar auf mehreren Ebenen
vorstellbar. Diese Bäume enthalten dann keine Test für diese speziellen Indexattribute. Allerdings ist
zu beachten, dass Abonnenten, welche doch don’t care Fälle eines Indexattributes enthalten, in
mehrere der Bäume eingetragen werden müssen. Insgesamt gibt es V^m solche Doppeleintragungen,
wenn es V Werte pro Attribut gibt und don’t care Fälle bei m Indexattributen eines Abonnenten
auftreten. Deshalb muss eine Abwägung zwischen zusätzlichen Speicherbedarf und Zeitgewinn
getroffenen werden.
Auch möglich wäre es, die Attribute so zu ordnen, dass die Anzahl ihrer möglichen Werte von der
Baumwurzel her zunimmt. Dadurch sind bei Knoten in höheren Ebenen weniger Ausgangskanten
nötig, der Baum wird insgesamt kleiner. Die beiden letzten Optimierungen setzen jedoch eine Analyse
der Abonnentenmenge vor dem Baumaufbau voraus.
D. Lösung durch endliche Automaten
Im folgenden wird eine Zusammenfassung des Artikels „Efficient Recognition of Events in a
Distributed System“ [2] wiedergegeben.
1. Lösungsansatz/weitere Annahmen
Auch dieser Ansatz benötigt einige einschränkende Annahmen. Ein jeder Abonnent wird wieder als
Konjunktion von Prädikaten angesehen. Prädikate sind ebenfalls Tests auf genau einem Attribut des
Artikels. Für die Attribute wird eine feste Reihenfolge vorausgesetzt. Jede Konjunktion soll genau k
Prädikate beinhalten. Don’t care Fälle werden somit wieder benötigt. Die möglichen Werte eines
Attributes werden als beliebige, nicht notwendigerweise beschränkte Menge angenommen.
Jeder Abonnent kann als Grundlage für einen NFA gesehen werden. Dieser NFA besteht aus genau k
Zustandsübergängen, wobei der i. Übergang genau vom i. Attribut abhängig ist. Ein jeder
Nichtendzustand enthält einen Test, wie im anderen Ansatz ein jeder innerer Knoten. Ein Übergang
stellt das Resultat eines Tests dar. Don’t Care Fälle sind direkt in -Übergänge übertragbar. Der NFA
hat genau k+1 Zustände, wobei die ersten k die Tests enthalten und der Endzustand den Abonnenten
beinhaltet. Hat die Abonnentenmenge Kardinalität n, gibt es n solche NFA’s. Diese können zu einem
großen Automaten zusammengefasst werden. Er besteht aus n parallelen Pfaden, dessen sämtliche i.
Übergänge Resultate eines Tests auf dem i. Attribut eines Artikels darstellen. Dieser NFA kann in
einen DFA gewandelt werden. Mit diesem kann man einen Event testen, um die interessierten
Abonnenten zu finden. Dabei müssen maximal k+1 Zustände besucht werden. Die Laufzeit wird somit
eher von der Attributzahl als von der Abonnentenzahl abhängig sein.
2. Größe des Eingabealphabets für den Automaten
Wie unter 1. erwähnt, kann die Kardinalität der Attributräume durchaus unbeschränkt sein. Es stellt
sich also die Frage, ob die Theorie von endlichen Automaten, welche bekanntlich auf endlichen
Alphabeten beruht, als Grundlage genommen werden kann.
Aufgrund einer endlichen Abonnentenmenge, kann die Wertemenge eines jeden Attributes nur in eine
endliche Zahl von Untermengen zerlegt werden. Denn ein jedes Prädikat kann die bisherige Anzahl
von Teilmengen verdoppeln. Das tritt ein, falls jede Untermenge sowohl Elemente enthält für die der
Attributtest stimmt, als auch welche, für die er nicht zutrifft. n Abonnenten können somit jede der
Attributmengen in höchstens 2^n Teilmengen zerlegen. Bei k Attributen entstehen also maximal k*2^n
Teilmengen. Das ist nur die theoretische Obergrenze. Gleichheitstests zerlegen eine jede
Attributmenge in maximal n+1 disjunkte Teilmengen. Bei Bereichstests gibt es im schlimmsten Fall
k*2*n Untermengen. Eine Ordnung auf der Menge wird hier vorausgesetzt. Für jede eindeutige
Untermenge wird ein Symbol benötigt. Somit ist das Alphabet für unseren Automaten, trotz der
beliebigen Attributmengen, ein endliches. Schlimmstenfalls hat es eine Dimension von k*2^n.
3. Transformation von NFA zu DFA
Ein klassischer Automat hat für alle seine Zustände ein gemeinsames großes Eingabealphabet.
Dieses setzt sich aus der Vereinigung der Alphabete jedes Zustands zusammen, wobei eventuell
Umbenennungen vorgenommen werden
1
{1,2,3}
x
müssen. Für unser Problem stellt es einen
a
e
i
m
Vorteil dar, die Alphabete eines jeden
Zustands einzeln zu betrachteten. Dadurch

kann ein anderer als der klassische
{1,2,3}
x
1
b
f
j
Algorithmus
zur
Umwandlung
des

n
nichtdeterministischen
in
den
s
deterministischen Automaten angewendet

werden. Dessen Unterschied liegt zum
0
{1,2,3}
y
c
g
k
o
einen
darin,
dass
nicht
alle

Alphabetsymbole von jedem Zustand aus
betrachtet werden müssen. Lediglich die
des jeweiligen Teilalphabets sind möglich.
0
{1,2,3}
y
d
h
l
p
Andere führen per Definition in die leeren
Zustandsmenge. Ein weiterer Unterschied
Bild2. NFA
liegt
in
der
Erzeugung
von
{a,b,c,d}
{e,f}
{g,h}
{i}
{j}
{k}
{l}
{ i, j}
1a
{e, f}
{}
{}
{}
{}
{}
{}
{}
0
{g, h}
{}
{}
{}
{}
{}
{}
{}
1
{}
{i}
{}
{}
{}
{}
{}
{}
2
{}
{i, j}
{k}
{}
{}
{}
{}
{}
3
{}
{i}
{l}
{}
{}
{}
{}
{}
4
{}
{j}
{k}
{}
{}
{}
{}
{}
5
{}
{j}
{l}
{}
{}
{}
{}
{}
x
{}
{}
{}
{m}
{n}
{}
{}
{m, n}
y
{}
{}
{}
{}
{}
{o}
{p}
{}
Bild3. Klassische Konstruktionsmethode
{a,b,c,d}
{1}
{ e, f }
{e,f}
{1,3}
{i}
{2}
{ i, j }
{g,h}
{2,4}
{k}
{3,5}
{l}
{i}
{ i, j}
{0}
{ g, h }
{4,5}
{j}
{x}
{m}
{x}
{ m, n }
{x}
{n}
{y}
{k} {o}
{y}
{l} {p}
Bild4. Optimierte Methode
{j}
-
Folgezuständen. In der klassischen Version wird jedes Symbol
des Alphabets einzeln betrachtet und jeweils die Menge der
Folgezustände erzeugt. In der optimierten Version wird durch
effizientes Einsetzen eines Algorithmus gleich die
Symbolmenge, die in die selbe Zustandsmenge abbildet,
gefunden. Dann muss nicht für jedes Alphabetsymbol einzeln
die Folgezustandsmenge gesucht werden, sondern nur für ein
Element der gefundenen disjunkten Teilmengen von
Symbolen. Die Bilder3 und 4 zeigen die beiden Algorithmen
am Beispiel des nichtdeterministischen Automaten aus Bild2.
Das Hauptproblem bei der Umsetzung des Verfahrens liegt
darin, die Teilmengen von Symbolen, welche in die gleiche
Zustandsmenge abbilden, zu finden. Diese Mengen müssen
bei Vereinigung die verwendeten Alphabetsymbole in der
betrachteten Zustandsmenge des NFA ergeben. Dazu wird
folgender effiziente Algorithmus von den Autoren [2]
vorgeschlagen. Das Verfahren ist jedoch nur für Mengen- und
Gleichheitstests anwendbar.
Der Algorithmus besteht aus 2 Schritten. Der erste funktioniert
folgendermaßen:
- Markiere jede Originalalphabetmenge eines Übergangs
der Zustandsmenge mit einem eindeutigen Einheitsvektor. (Dieser muss mindestens die
Dimension m haben, wenn es m Übergänge in dieser Zustandsmenge im NFA gibt.)
Trage jedes Symbol jeder Originalalphabetmenge in eine Hashtabelle ein. Nutze dabei die
Elemente als Schlüssel und die Vektoren als Werte. Tritt ein Konflikt bei gleichen Schlüsseln auf,
so verknüpfe deren beiden Vektoren mit einem logischen ODER und ersetze den bisherigen
Vektor des Schlüssels. Löse Konflikte bei verschiedenen Schlüsseln z.B. mit einer verketteten
Liste.
In der erzeugten Hashtabelle ist nun für jedes Element verzeichnet, in welcher Originalalphabetmenge
es vorhanden war. Für einen jeden entstandenen Vektor muss ein Übergang im DFA bereitgestellt
werden. Bei Abarbeitung des Automaten kann in dieser Tabelle nachgeschaut werden, welchem
Übergang bei einem Eingabesymbol zu folgen ist. Dies ist in konstanter Zeit möglich [3].
Der zweite Schritt tut nun folgendes:
-
Trage jedes Element der erzeugten Hashtabelle in eine weitere Hashtabelle ein. Nutze den
assoziierten Vektor als Schlüssel und das Element als Wert.
Tritt ein Konflikt bei gleichen Schlüsseln auf, vereinige das vorhandene Element (Menge) mit dem
neuen und speichere diese Menge als Wert des Schlüssels. Anderenfalls löse den Konflikt durch
eine verkettete Liste.
In dieser zweiten Hashtabelle sind jetzt die gesuchten disjunkten Teilmengen, die einen
Zustandsübergang im DFA bilden, enthalten. Das Erzeugen beider Hashtabellen ist in linearer Zeit zur
Summe der Mächtigkeiten der Originalalphabetmengen möglich. Dies basiert auf Hashtabellen mit
Durchschnittszeiten zum Einfügen und Auslesen in konstanter Zeit [3].
Eine weitere Besonderheit weist der Transformationsalgorithmus auf. Da in jedem Zustand ein Test
auf genau einem Attribut ausgeführt werden soll, dürfen keine Zustände mit Tests aus
unterschiedlichen Attributen zusammengefasst werden. Dieses Zusammenfassen tritt bei Übergängen in der Standardmethode auf. Deshalb müssen diese Fälle hier anders behandelt werden.
Anstatt einen Zustand mit dem einer anderen
b
b
Ebene zu vereinigen, wird diese spätere Ebene
in alle Nichtepsilon-Übergänge
dieses
c
c
a
a
Zustands integriert. Zusätzlich wird ein
d
Übergang (durch  gekennzeichnet), welcher
bei Zutreffen keiner der anderen Kanten verfolgt
e


d
d
wird, eingefügt. Bild5 soll dies verdeutlichen.
e
e
4. Aufwandsanalyse:
Bild5. Wandelung DFA in NFA
Als Maß für die Laufzeit wird die Zahl der Tests
im DFA angenommen. Es werden Analysen für
verschiedene Arten von Tests betrachtet. Diese sind zu den bisher betrachteten als jeweilig zusätzlich
anzusehen. n soll im folgenden die Anzahl der Abonnenten und k die Zahl der Prädikate sein.
a) nur Gleichheitstests
Im besten Fall liegt auf dem Weg durch den
DFA nur ein Zustand, welcher zwei
Übergänge besitzt. Alle anderen haben
genau einen Übergang (und den Übergang
in die leeren Zustandsmenge). Es müssen
hier k+1 Ergebnisse betrachtet werden.
Dieser Fall tritt ein, wenn alle anderen
Abonnenten, aufgrund eines Unterschieds
Bild6. worst case Pfad
in einem Attribut, nicht möglich sind. Bild7
zeigt dieses.
Im schlechtesten Fall liegen die Abzweigungen zu den
anderen Zuständen (Abonnenten) alle auf dem Weg durch
den Automaten. Dann müssen (n-1)+k mögliche Ergebnisse
getestet werden. Das Ergebnis ist nicht zufriedenstellend, da
es linear mit der Abonnentenzahl steigt. Eine einfache
Verbesserung spiegelt sich jedoch extrem in der Laufzeit
Bild7. best case Pfad
wieder. Durch Sortieren der möglichen Symbole in den
Zuständen und Nutzung von binärer Suche kann der
Aufwand auf O(k * log n) verkleinert werden. (Durch den Einsatz von Hashtabellen wäre sogar
Linearität zur Attributanzahl gegeben.) In Bild6 sind 2 Möglichkeiten dieses Falls zu sehen.
b) don’t care Fälle
Die mögliche Unabhängigkeit von einem Attribut verschlechtert die Laufzeit des Algorithmus nicht. Ein
don’t care Fall stellt bei NFA einen -Übergang dar. Bei der Transformation zum DFA werden diese
Übergänge eliminiert. Es bleibt lediglich eine zusätzliche Möglichkeit bei jedem Zustand erhalten. Es
existiert ein Übergang (), welcher benutzt werden muss, falls kein anderer in Frage kommt. Dadurch
entfällt wiederum der Übergang in die leere Zustandsmenge. Somit müssen im schlechtesten Fall die
gleiche Anzahl von Vergleichen durchgeführt werden. Die Laufzeit bleibt also gleich.
c) Mengentests
Im schlimmsten Fall können 2^n-1 Übergänge je Zustand entstehen. Diese Zahl ist die maximal
mögliche Anzahl von Kombinationen aus den n Zuständen je Ebene. Tritt dieser pathologische Fall in
allen Ebenen des Automaten auf, ergibt sich ein Gesamtaufwand von O(k * 2^n). Der oben unter 3.
erklärte Algorithmus mit Nutzung von Hashtabellen kann den Aufwand auf O( k ) verringern.
d) Bereichstests
Bei Nutzen von Bereichen können 2*n-1 Übergange je Zustand entstehen. Diese Zahl ergibt sich,
wenn der Bereich eines jeden Abonnenten den bisherigen Bereichen genau 2 hinzufügt. Also einen
bereits vorhandenen in 3 Bereiche zerlegt. Summiert ergibt sich im schlechtesten Fall eine
Komplexität von O(n * k). Durch Einsetzen von binärer Suche kann wieder eine Verbesserung der
Laufzeit auf O(k * log n) erreicht werden.
e) Speicherplatz
Der benötigte Platz für einen Automaten hängt von seiner Zustandszahl und der Anzahl der
Übergänge ab. Wie unter c) analysiert gibt es maximal 2^n-1 Zustände pro Ebene. Da es k+1 Ebenen
im DFA gibt, liegt der maximale Speicherbedarf bei O( k * 2^n ).
f)
Zeit zum Aufbau
Die Aufbauzeit ist auch direkt von der Zustandszahl des erzeugten DFA’s abhängig. Es ergibt sich
analog zu e) ein Maximalaufwand von O( k * 2^n ).
5. Optimierungen
Die schlechtesten Fälle beim Abarbeiten des DFA ergeben sich nur dann, wenn die Hauptzahl der
Abonnenten ein gemeinsames Präfix besitzt. Ziel ist es, ein solches gemeinsames Präfix so klein wie
möglich zu halten. Eine Umsortierung der Prädikate hat keinen Einfluss auf das Endergebnis, da laut
Definition ein Abonnent eine Konjunktion von Prädikaten darstellt. Deren Reihenfolge ändert das
Resultat nicht. Eine Betrachtung der Abonnenten vor Erzeugen des NFA’s könnte diese Minimierung
der gemeinsamen Präfixe durch Umsortieren durchführen. Im DFA würden dann viele Abonnenten in
frühen Zuständen in unterschiedliche Pfade eingetragen werden. Dadurch entfallen die Betrachtungen
ihrer Prädikatergebnisse dann auf einem Weg durch den Automaten. Ob diese Art der Sortierung
jedoch in allen Fällen zum gewünschten Erfolg führt, möchte ich bezweifeln. Eine Sortierung nach
Anzahl der möglichen Attributwerte steht einer Problemlösung wohl näher. Dadurch wird erreicht, dass
durch eine minimale Anzahl von Vergleichen viele Abonnenten in andere Pfade eingetragen werden,
wodurch Vergleiche mit ihren anderen Attributen entfallen.
Eine andere Verbesserung kann durch Verlagerung der zeitintensiven Bereichstests an das Ende des
Automaten gelingen. Diese Tests würden dann auf einem kleineren Alphabet ausgeführt werden und
somit weniger Laufzeit benötigen. Führt man sie schon früh im Automaten aus, müssen viele mögliche
Ergebnisse betrachtet werden, da sämtliche durch diesen Knoten erreichbaren Abonnenten zu
beachten sind.
E. Wertung der Ansätze
1. Einschränkung des Profils
Die Einschränkung des Profils auf Konjunktionen stellt eine Beschneidung der Möglichkeiten dar. Zwar
ist {,} funktional vollständig, jedoch ist man durch eine weitere Festlegung beschränkt. Dadurch,
dass jedes Prädikat von genau einem Attribut abhängig sein muss, können nicht alle Anfragen mit der
Sprache definiert werden.
a) Integration von ODER
Um die Profilsprache nicht der von beiden Ansätzen vorausgesetzten Einschränkung der bloßen
Verwendung von Konjunktionen zu unterwerfen, könnte man die Ansätze wie folgt erweitern. Zur
Nutzung eines logischen ODER, ist es nötig einen Abonnenten vielfach in die interne Struktur
einzutragen. Dabei muss so verfahren werden, dass jeweils alle bis auf eine der Disjunktionen anstatt
einen bestimmten Wert zu fordern, als don’t care Fall betrachtet werden. Der Abonnent mit den Tests (
a=1  b=2 )  c=3 müsste z.B. als a=*  b=2  c=3, als auch als a=1  b=*  c=3 eingetragen werden.
Da bei komplizierten Ausdrücken eine große Zahl dieser verschiedenen Möglichkeiten existiert,
müssten eventuell kleinere Einschränkungen dieser Komplexität gemacht werden, zwingend
notwendig ist es jedoch nicht. Durch die Mehrfacheintragung steigt die Größe der internen Struktur zur
Darstellung der Abonnenten, welche sich für das System wie eine Erhöhung der absoluten
Abonnentenzahl auswirkt. Dementsprechend würde sowohl Zeit als auch Speicherverbrauch
ansteigen.
Die Möglichkeit einer Verknüpfung durch ODER auf ein und demselben Attribut ist in beiden Fällen
durch die Anwendung eines Tests auf Vorhandensein in einer Menge schon integriert.
b) Integration von NOT
Durch die Möglichkeit der Integration einer Verknüpfung der Attribute in den Profilen durch ein
logischer ODER, sollte es nun möglich sein, den Einsatz eines NOT zu erzeugen. Durch Umformung
einer beliebigen booleschen Formel, ist es möglich diese mit den 3 Operatoren ,, darzustellen.
Diese Darstellung kann man in DNF wandeln und nun alle entstandenen Konjunktionen als einzelne
Abonnenten eintragen. Jede dieser eingetragenen Konjunktionen ist von allen Attributen abhängig und
zwar durch genau einen Test oder kann durch don’t care Fälle aufgefüllt werden. Die Negationen
stehen nun jeweils vor einem Test. Diese entgegengesetzte Testart könnte dann in das System
übernommen werden, falls sie noch nicht vorhanden ist.
Also sind nun alle Formen von booleschen Anfragen möglich.
c) Reihenfolge der Attribute
Beide Ansätze gehen von einer vorgegebenen Reihenfolge und der Abhängigkeit jedes Abonnenten
von allen Attributen aus. Diese Einschränkungen sind jedoch unkritisch, da sie für den Abonnenten als
Nutzer des Systems gar nicht sichtbar sein müssen. Er kann frei sein Profil erstellen. Nach dem
Abgeben der Spezifikationen kann das System die Reihenfolge seiner Prädikate verändern, natürlich
unter Beachtung der Äquivalenz der Umwandlung. Vom Nutzer nicht eingeschränkte Attribute können
durch einen don’t care Fall ersetzt werden. Somit sind alle engen Anforderungen des Systems auch
bei einer weiter gefassten Profilsprache gegeben. Auf der anderen Seite sind die eintreffenden
Dokumente zu sehen. Ihre Attribute müssen ebenfalls in der vorgegebenen Reihefolge vorhanden
sein. Praktisch dürfte das schwer von der Vielzahl der Anbieter zu erwarten sein. Eine Sortierung
müsste durchgeführt werden. Diese ist in O( k * log k) bei k Attributen möglich. Der praktisch damit
verbundene Aufwand sollte jedoch nicht zu groß eingeschätzt werden, da eventuell sowieso
Anpassungen der Attribute der verschiedenen Anbieter von Informationen vorgenommen werden
müssen. Die Sortierung also „nebenbei“ passieren könnte.
2. Probleme beim Ansatz Matching Tree
a) verschiedene Arten von Tests
Der Algorithmus zum Baumaufbau verfolgt bei Vorhandensein unterschiedlicher Arten von Tests eine
einfache und für den Suchaufwand ineffiziente Strategie. Soll ein anderer Test, als der im aktuellen
Knoten vorhandene, ausgeführt werden, wird einfach *-Kanten gefolgt. Und zwar so lange, bis man
den richtigen Test oder einen Knoten ohne *-Kante findet. Diesem Knoten fügt man dann eine solche
Kante hinzu und trägt den Test in einen neuen Knoten ein. Aufgrund dieser Strategie sind sehr große
Baumhöhen möglich, was zu höheren Suchzeiten führt.
Eine andere Möglichkeit verschiedene Tests zu integrieren ist es, diese als gleichartige darzustellen.
Bei Gleichheits- und Mengentests ist das ohne weiteren möglich. Bereichstests wiederum, könnte man
als Mengentests betrachten. Bei kleinen Bereichen kann das angebracht sein. Liegen jedoch große
Unterschiede zwischen dem Minimum und dem Maximum, so hätte man extrem große Mengen zu
verwalten. Ein Mehrverbrauch an Speicher und größere Suchzeiten wären die Folge.
Auch die andere Richtung gestaltet sich problematisch. Grosse Mengen würden im Extremfall pro
Element genau einen Bereich erzeugen. Die Folgen für Speicher und Laufzeit wären die gleichen.
Im Artikel [2] wird vorgeschlagen, Bereichstests pro unterschiedlichem Testbereich als andere Art von
Test anzusehen. Damit hätte jeder dieser Tests genau 2 Kanten. Eine, der gefolgt wird wenn das
Attribut des Events im Bereich liegt und eine *-Kante. Damit ergibt sich erstens eine sehr große
Baumhöhe und zweitens die daraus resultierende größere Suchzeit, da stets beiden Kanten zu folgen
ist. Andererseits könnte man die Bereiche als Kanten der Knoten eintragen. Dann müsste man aber
eventuell mehreren dieser Kanten folgen. Auch so würde die Suchzeit extrem verlängert. Schließlich
wäre es bei überlappenden Bereichen auch möglich, eine vorhandene Überschneidung durch
Aufsplitten dieser, aufzuheben. Dann müssen Abonnenten jedoch in mehrere Blätter eingetragen
werden. Die Knotenzahl läge dann im schlimmsten Fall exponentiell zur Abonnentenzahl.
b) Laufzeitbeweis
Als Laufzeit für das Finden der an einem Artikel interessierten Abonnenten, wurde als
durchschnittlicher Wert O(k‘ * (ln k‘ + ln V) * [ |S| ^ (1-)] ) gezeigt. V ist die Zahl der möglichen Werte
pro Attribut, S die Menge der Abonnenten, k‘ die Attributanzahl + 1 und  eine von V und k
beeinflusste Konstante. Der Beweis ist in der zugrundeliegenden Arbeit [1] in Abschnitt 4 zu finden. Zu
diesem muss noch einmal erwähnt werden, dass nur Gleichheitstests der Attribute vorausgesetzt
wurden.
Das gefundene Ergebnis ist logarithmisch von der Anzahl der möglichen Werte V für ein Attribut
abhängig. Diese Anzahl stellt nicht die Menge der möglichen Werte, bei den in den Baum
eingetragenen Abonnenten dar, sondern die tatsächliche Mächtigkeit des zugrundeliegenden
Alphabets je Attribut. Die Alphabete können also nicht als unbeschränkte Mengen angesehen werden.
Beim Ansatz mit endlichen Automaten gibt es diese Einschränkung nicht. Praktisch ist diese
Beschränkung jedoch im System gegeben, wenn auch in einer entsprechenden Größenordung.
Ebenfalls wurde beim Beweis eine Gleichverteilung der möglichen Werte angenommen. In der Praxis
ist das nicht anzunehmen.
Ein Beispiel soll die daraus resultierenden Folgen aufzeigen. Nehme man für V eine große Zahl an.
Bei simplen Tests auf Zeichenketten ist das ohne weiteres möglich. Theoretisch geht der -Wert
dadurch nahe an 1. Der zu erwartende Exponent ist dann nahe 0. Erklärbar ist dieses Ergebnis
dadurch, dass bei Gleichverteilung sehr viele Abonnenten, auf einem bestimmten Weg durch den
Baum, vom Pfad abzweigen. In der Praxis hingegen ist es nicht unüblich, dass viele Abonnenten bei
einem Attribut die gleichen Werte verlangen. Tritt dann auch nur bei einem von diesen Abonnenten im
nächsten Attribut ein don’t care Fall auf, müssen alle diesem Pfad folgenden Events, mehrere Kanten
parallel betrachten und somit Tests ausführen. Erstens ist also keine Gleichverteilung gegeben und
zweitens hat ein häufig auftretender Fall schlechtere Laufzeiten als die selteneren.
Die im Beweis getroffenen theoretischen Annahmen unterscheiden sich somit von der Praxis
gravierend, und es ist fraglich, ob die gefundenen Werte in realen Systemen haltbar sind.
F. Vergleich der Algorithmen
1. Effizienz
Im folgenden wird versucht ein Vergleich zwischen den beiden Ansätzen hinsichtlich
Speicherverbrauch und Laufzeit anzustellen. Die Lösung mit Aufbau eines Matching Tree wird im
folgenden als Ansatz a und die Idee über endliche Automaten als Ansatz b bezeichnet.
Beide Algorithmen zerlegen das Problem in 2 Teile. Dabei wird im ersten eine innere Datenstruktur
aufgebaut, anhand derer die späteren Betrachtungen stattfinden. Ansatz b hat beim Aufbau dieser
Struktur ein klares Defizit. Sowohl benötigter Speicher als auch Aufbauzeit liegen hier im
exponentiellen Bereich zur Abonnenten- und Attributzahl. Bei Ansatz a hingegen ist der Aufwand
proportional zum Produkt dieser beiden Werte. Wie unter E analysiert ist dieses Ergebnis jedoch nur
bei Gleichheitstests zu erwarten. Der Automat hat in diesem Fall eine maximale Zustandszahl im
Bereich Abonnentenanzahl ^ Attributanzahl, was immer noch ein vielfaches mehr ist. Es wäre jedoch
vorstellbar, dass der Automat nur in großen Zeitintervallen neu aufgebaut wird. Eine tägliche
Aktualisierung der Struktur wäre, aufgrund der vorhandenen Problemstellung, wahrscheinlich
ausreichend. Das Problem des Speicherbedarfs könnte entweder durch große Hauptspeicher, oder
durch ein Auslagern von Teilen der Struktur in den Hintergrund, gelöst werden. Da auf jedem Weg
durch den DFA, die Zahl der besuchten Zustände der Anzahl der Attribute entspricht, könnte man bei
jedem Event mit maximal dieser Zahl von Plattenzugriffen auskommen.
Der andere wichtige Vergleichswert für die Effizienz ist die benötigte Zeit, um zu einem Artikel alle
interessierten Abonnenten zu finden. Ansatz a braucht hierzu Zeit proportional zur Attributanzahl und
sublinear zur Anzahl der Abonnenten. Der Exponent ist von Art und Menge der Attribute abhängig.
Wie unter E. aufgezeigt, ist dieser Wert, wenn überhaupt, lediglich für Gleichheitstests annehmbar.
Ansatz b hat hier einen großen Vorteil. Bei dieser Einschränkung ist das Finden der Abonnenten
sogar von deren Gesamtzahl unabhängig. Lediglich die Zahl der Attribute geht als linearer Faktor ein.
Auch bei anderen Testarten kommt bloß ein zusätzlicher Faktor logarithmisch zur Abonnentenzahl
hinzu.
Durch verschiedene Möglichkeiten der Optimierung sind bei beiden Ansätzen Verbesserungen der
Laufzeit und Änderungen des benötigten Speichers zu erreichen. Eine theoretische Analyse des dabei
zu erwartenden Aufwands ist nur schwer möglich. Praktische Vergleiche der Suchzeiten sind dann
wohl besser geeignet, um Aussagen über das Verhalten bei tatsächlich vorhandenen
Problemstellungen zu geben.
2. Lösungsansatz
Beide Verfahren sehen es als geeignet an, eine interne Repräsentation des vorhandenen Problems zu
erstellen. Auf deren Grundlage sollte es dann effizienter möglich sein, die Abonnenten zu finden, als
beim unter B. genannten „einfachen“ Algorithmus. Ebenso gehen beide Ansätze in der Definition der
zu verwendenden Profilsprache in die gleiche Richtung. Ihnen ist jeweils gemeinsam, dass sämtliche
Abonnenten ihre Auswahlkriterien als Konjunktion von Einschränkungen der Attribute angeben
müssen.
Die Struktur der zur Suche erstellten internen Darstellung des Problem ist bei beiden Ansätzen eine
ähnliche. Sowohl der Automat, als auch der Matching Tree, stellen eine Art Suchbaum dar. Lediglich
in dessen Optimierung liegen die Unterschiede. Ansatz b versucht die Struktur soweit als möglich
dahingehend zu optimieren, dass beim Suchen die minimal nötige Anzahl von Baumknoten besucht
werden muss. Diese liegt in der Anzahl der Attribute. Die don’t care Fälle werden während des
Erzeugens betrachtet und nicht erst beim späteren Arbeiten auf dem Automaten. Die Struktur erhält
dadurch mehr Knoten, was auf Kosten von Speicherplatz und Erzeugungszeit geht. Ansatz a versucht
die Baumstruktur in eine andere Richtung zu optimieren. Das Hauptziel liegt darin, einen geeigneten
Mittelwert zwischen Suchzeit und Aufbauzeit zu finden. Der Speicherbedarf soll linear zur
Abonnentenzahl sein. Dafür wird eine Verschlechterung der Suchzeit in Kauf genommen, wobei diese
unter der des „einfachen“ Algorithmus liegen soll.
Der Hauptunterschied der beiden Ansätze liegt somit nur auf der Optimierungsrichtung der jeweils
erstellten internen Datenstruktur. Ansatz b baut dabei auf die Automatentheorie auf. Das vorhandene
Ausgangsproblem ist leicht durch einen nichtdeterministischen Automaten darzustellen. Dessen,
aufgrund der Problemstellung entstehende Struktur führt dazu, dass beim äquivalenten DFA auf
jedem Pfad maximal so viele Zustände liegen, wie es Attribute gibt. Also ist durch dessen Erzeugen
eine nur von der Attributzahl abhängige Lösung gefunden. Diese Umwandlung des Automaten ist die
Hauptarbeit des Algorithmus. Die dafür benötigte Zeit ist direkt in die Erstellungszeit übertragbar.
Aufgrund der Vielzahl von Zustandskombinationen, welche bei der Umwandlung entstehen können,
leiten sich die im schlechtesten Fall entstehenden Zahlen für Speicher und Aufwand her. Diese
Vielzahl von Kombinationen ist besonders wegen der nötigen Eliminierung von *-Kanten zu erreichen.
Ansatz a löst diese nicht auf, sondern nimmt es in Kauf, jeweils mehreren Kanten folgen zu müssen.
Würde man den Matching Tree als Automaten betrachten, wären zwar alle Übergänge mit eindeutigen
Werten gekennzeichnet, jedoch gibt es noch -Übergänge. Er stellt quasi einen NFA dar, der teilweise
in einen DFA umgewandelt wurde.
G. Möglichkeiten der Aktualisierung der Datenstrukturen
Beide hier vorgestellten Algorithmen verfolgen hinsichtlich der Veränderung der erzeugten
Datenstrukturen den gleichen Ansatz. Es wird davon ausgegangen, dass sich die Profile der
Abonnenten nur selten verändern bzw. neue hinzukommen oder verschwinden. In diesem Fall wird
der gesamte Baum/DFA neu erzeugt (jedenfalls werden in beiden Arbeiten keine anderen Ansätze
kundgetan). Deshalb soll im folgenden versucht werden solche Möglichkeiten zu analysieren.
1. Grundlage Matching Tree
Bei den folgenden Betrachtungen wird jeweils von einer unoptimierten Version des Matching Tree
ausgegangen.
Am einfachsten ist das Hinzufügen eines neuen Abonnenten zu realisieren. Dieses wird beim Aufbau
des Baumes ohnehin mit jedem Abonnenten getan. Somit kann sogar der Standardalgorithmus
verwendet werden können. Über die sich daraus ergebende Ineffizienz bei verschiedenen Tests bzw.
Ergebnisüberlappungen wird auf Abschnitt E verwiesen. Die Laufzeit ist proportional zur Baumhöhe.
Das Entfernen eines Abonnenten kann wie folgt geschehen. Am einfachsten ist es, wenn er nicht der
einzige Eintrag in einem Blatt ist. Dann kann man den Abonnenten einfach aus der Menge streichen.
Sonst geht man im Baum schrittweise Richtung Wurzel, bis ein Knoten mit mindestens zwei Kindern
gefunden wird. Aus diesem entfernt man dann die Kante, welche auf dem Weg zu ihm passiert wurde.
Problematisch ist es, wenn dieser Knoten nur noch eine *-Kante enthält. Dann kann er aus dem Baum
entfernt werden und sein Kind wird an seine Stelle gesetzt. Eventuell tritt nun der gleiche Fall erneut
auf, die Lösung bleibt die selbe. Der entstehende Aufwand ergibt sich proportional zur Baumhöhe.
Änderungen sind nun zum einen durch Kombination der beiden genannten Operationen möglich.
Sinnvoll ist das nur, wenn die Änderung auch auf dem ersten Attribut der gegebenen Reihenfolge
stattfand. Anderenfalls sollte man beim Entfernen darauf achten, dass nur solche Knoten gelöscht
werden, die Tests auf „größeren“ als dem „kleinsten“ geänderten Attribut beinhalten. Ab dieser
„kleinsten“ Änderung kann dann das Einfügen erfolgen. So erspart man sich ein Löschen und
Hinzufügen von Knoten mit letztendlich gleichem Inhalt.
Eine Änderung (Löschen, Einfügen, Update) des Baumes jeglicher Art kann somit in Zeit proportional
zur Baumhöhe geschehen. Die Datenstruktur könnte einmal erzeugt werden und danach nur noch
durch Änderungen in ihrer Struktur erneuert werden.
2. Grundlage endliche Automaten
Beim Ansatz mit endlichen Automaten gestalten sich die
Operationen zur Änderung schwieriger. Wir wollen zuerst das
Entfernen eines Abonnenten betrachten. Gibt es mehrere
1..3
Abonnenten der gleichen Art, so kann er einfach aus der Menge
A1,A3
4..6
im Endzustand entfernt werden. Anderenfalls geht man so lange
in Richtung Startzustand, bis ein Zustand mit mindestens 2
A4,A5
7..9
Übergängen erreicht wird. Der überwundene Pfad kann dann
entfernt werden. Allerdings ist der Abonnent jetzt
möglicherweise noch nicht vollständig aus dem Automaten
Bild8. Entfernen eines Abonnenten
entfernt. Es ist möglich, dass Zustände, welche auf dem Weg zu
dem entfernten Abonnenten liegen, noch Tests enthalten,
welche aufgrund des entfernten Zustandes bestehen. Folgendes Beispiel anhand von Bild8 soll das
zeigen. Der Test überprüft Bereiche. Wird Abonnent A3 entfernt, so ist dessen ehemaliger Zweig
überflüssig. Er könnte entfernt und mit dem oberen vereint werden. Dieser würde dann den Bereich
1..6 abdecken. Solche Probleme könnten bei allen Zuständen auftreten. Diese zu analysieren würde
zeitlich nicht möglich sein, da mindestens alle Endzustände betrachtet werden müssen. Deren Zahl
liegt schlimmstenfalls im exponentiellen Bereich zur Abonnentenzahl. Eine andere Möglichkeit wäre
es, in jedem Zustand bei jedem Testergebnis zu speichern, aufgrund welcher Abonnenten es
entstanden ist. Die Analyse würde dann zwar beschleunigt, jedoch der Speicheraufwand noch weiter
steigen. Die einfachste Lösung ist jedoch, diesen Fakt zu ignorieren und den Baum erst nach dem
Entfernen von einer größeren Zahl von Abonnenten neu zu erzeugen, um die unnötigen
Vergrößerungen zu eliminieren.
Auch das Einfügen bringt erwartungsgemäß Probleme mit sich. Ist bereits ein Abonnent mit gleichen
Prädikaten in den Automaten eingetragen, so trifft man beim Durchlaufen auf einen Endzustand. Zu
diesem fügt man den neuen Abonnenten hinzu. Trifft man auf dem Weg durch den Automaten auf ein
noch nicht behandeltes Testergebnis, gibt es zwei Möglichkeiten. Bestenfalls gibt es keinen
Übergang, dem bei allen nichtverzeichneten Fällen zu folgen ist. Dann kann man einfach das
Testergebnis zum Zustand hinzufügen und die restlichen Tests ebenso. Gibt es diesen Übergang,
muss der gesamte von ihm ausgehende Pfad kopiert werden und dann in diesen weiter eingetragen
werden. Das gleiche Problem ergibt sich beim Aufsplitten eines Testergebnisses in verschiedene
Fälle. Da schlechterdings exponentiell zur Abonnentenzahl viele Zustände zu kopieren sind, erhält das
Problem eine entsprechende exponentielle Größe.
Insgesamt gestaltet sich das Problem der Aktualisierung beim DFA also schwieriger, da der Aufwand
ins exponentielle gehen kann. Der Matching Tree mit linearer Zeit zur Baumhöhe hat dabei klare
Vorteile. Eine Aktualisierung der Struktur einmal am Tag stellt jedoch eine mögliche Alternative dar,
welche auch praktisch keine Hindernisse schaffen sollte.
A1
Quellen/Material:
[1]
M.K. Aguilera, R.E. Strom, Dw.C. Sturman, M. Astley and T.D. Chandra: Matching events in a
content-based subscription system. Proceedings of the 18th ACM symposium on Principles of
distributed computing May 1999.
[2]
K.J. Gough, G. Smith: Efficient Recognition of Events in a Distributed System. Proceedings of
the ACSC-18, 1995
[3]
Thomas H. Cormen, Charles E. Leiserson and Ronald L. Rivest Introduction to Algorithms.
The MIT Electrical Engineering and Computer Science Series, The MIT Press, 1990
Herunterladen