Evaluation von ausgewählten Matching

Werbung
Fakultät für Elektrotechnik und Informatik
Institut für Praktische Informatik
Fachgebiet Datenbanken und Informationssysteme
Evaluation von ausgewählten
Matching-Algorithmen für attributierte
Graphen
Bachelorarbeit
im Studiengang Informatik
Simon Wingert
-
Prüfer: Prof. Dr. Udo Lipeck
Zweitprüfer: Dr. Hans Hermann Brüggemann
Betreuer: M.Sc. Oliver Pabst
9. Juli 2015
Inhaltsverzeichnis
1 Einleitung
5
1.1
Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.2
Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2 Grundlagen
8
2.1
Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2
Levenshtein-Distanz
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
2.3
Stochastik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
2.4
Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
2.4.1
Kernel für Strings . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
2.4.2
Gute Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
3 Algorithmen
3.1
8
15
VF2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.1.1
Komplexität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
Fehlerkorrigierende Subgraphisomorphismen . . . . . . . . . . . . . . . .
20
3.2.1
Edit-Graphen und Subgraphisomorphismen
. . . . . . . . . . . .
21
3.2.2
Die Dekomposition . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.2.3
Der Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
3.2.4
Komplexität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
3.3
Diskrete Relaxation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
3.4
SMKernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
3.4.1
36
3.2
Komplexität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4 Implementierung
4.1
37
Externe Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
4.1.1
Die JGraphT-Bibliothek . . . . . . . . . . . . . . . . . . . . . . .
37
4.1.2
Andere Hilfsfunktionen . . . . . . . . . . . . . . . . . . . . . . . .
39
Allgemeine Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
4.2.1
Knoten- und Kantenklassen . . . . . . . . . . . . . . . . . . . . .
39
4.2.2
Die GraphMatcher-Klasse . . . . . . . . . . . . . . . . . . . . . .
41
4.3
VF2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
4.4
Fehlerkorrigierende Subgraphisomorphismen . . . . . . . . . . . . . . . .
45
4.5
Diskrete Relaxation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
4.6
SMKernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
4.2
5 Evaluation
5.1
5.2
58
Synthetische Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
5.1.1
VF2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
5.1.2
Fehlerkorrigierende Subgraphisomorphismen . . . . . . . . . . . .
60
5.1.3
Diskrete Relaxation . . . . . . . . . . . . . . . . . . . . . . . . . .
63
5.1.4
SMKernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
Reale Daten einer Bibliotheksdatenbank . . . . . . . . . . . . . . . . . .
70
5.2.1
VF2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
5.2.2
Fehlerkorrigierende Subgraphisomorphismen . . . . . . . . . . . .
72
5.2.3
Diskrete Relaxation . . . . . . . . . . . . . . . . . . . . . . . . . .
74
5.2.4
SMKernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
6 Fazit & Ausblick
77
4
Kapitel 1
Einleitung
1.1
Motivation
Graphen sind eine vielseitig einsetzbare Datenstruktur. Mit ihnen lassen sich Aufgabenstellungen in vielen Anwendungsfeldern der Informatik modellieren.
In der Bioinformatik beispielsweise werden Proteine als Graphen dargestellt. Um die
Funktion von Proteinen im Organismus zu verstehen, gibt es den Ansatz, sie mit Proteinen zu vergleichen, deren Funktion bereits bekannt ist. Die Idee ist, dass Proteine,
die eine ähnliche Molekülstruktur besitzen, auch eine ähnliche Funktion besitzen. Mit
Graph-Algorithmen werden in Datenbanken deshalb die Graph-Repräsentationen von
Proteinen untersucht [BOS+ 05]. Graphen werden auch in der Bildverarbeitung eingesetzt. Straßenverläufe auf Satellitenbildern werden als Graph modelliert und anschließend mit den Straßenverläufen verglichen, die aus vorliegenden Kartendaten bekannt
sind. So kann zum Beispiel veraltetes oder ungenaues Kartenmaterial erkannt werden
[WH97].
Wie diese Beispiele zeigen, ist eine wiederkehrende Aufgabe in den Anwendungen der
Vergleich von zwei Objekten. Wenn die Informationen in geeigneter Weise als Graph
repräsentiert werden, so kann das Problem durch eine Form von Graph Matching bearbeitet werden. Graph Matching meint das Finden von Übereinstimmungen zwischen
den Knoten und Kanten zweier Graphen unter Berücksichtigung von bestimmten Bedingungen, so dass ähnliche Strukturen in einem auf den anderen Graphen abgebildet
werden [FPV14].
In dieser Arbeit werden Algorithmen zum Graph Matching auf attributierten Graphen
betrachtet. Die ersten Arbeiten zum Graph Matching können in zwei Klassen eingeteilt
werden: exaktes und inexaktes Graph Matching. Während Ersteres eine strenge Übereinstimmung der Strukturen der zu vergleichenden Graphen fordert, kann bei Letzterem ein
5
Matching der Graphen auch bei einer gewissen strukturellen Unterschiedlichkeit realisiert werden [CFSV04a]. Mit inexaktem Matching verbindet sich zum einen die Hoffnung
in einer schnelleren Laufzeit nicht unbedingt optimale, aber ausreichend gute Ergebnisse
zu erzielen. Zum anderen ist es dadurch motiviert, dass die Daten des Graphen durch
Messungenauigkeiten „verunreinigt“ sein könnten oder sich der Standard zum Erfassen
von Daten unterscheidet (z.B. das Ausschreiben oder Abkürzen des Vornamens), so dass
ein präzises Matching nie zum Ziel führen würde.
In der vorliegenden Arbeit beschäftigen wir uns aus diesen Gründen mit zwei bekannten
Verfahren aus beiden Bereichen: der VF2-Algorithmus [CFSV04b] ist ein Ansatz für das
exakte Matching und der Algorithmus aus [MB98] erlaubt inexaktes Matching. Beiden
Algorithmen ist gemein, dass sie die gesamte Information aus der Struktur des Graphen
und die Information der Knoten- bzw. Kantenattribute benutzen, um ein Matching zu
identifizieren. Um auch einen Algorithmus kennenzulernen, der dem oben formulierten
Ziel der schnelleren Laufzeit näherkommt, wollen wir zudem einen Ansatz [WH97] vorstellen, bei dem bewusst Information über die Gesamtstruktur des Graphen ungenutzt
bleibt, um ein inexaktes Matching zu finden. Wir wollen sowohl die Geschwindigkeit der
Algorithmen untersuchen als auch insbesondere für den letzten Algorithmus die Qualität
der gefundenen Matchings.
Formal präzise ausgedrückt untersuchen wir in der vorliegenden Arbeit Algorithmen, die
Subgraphisomorphismen zwischen Graphen finden. Da dieses Problem NP-vollständig
ist, wurden in den letzten zehn Jahren auch Algorithmen entwickelt, die kein Matching
in obigem Sinne erlauben, aber dennoch den Vergleich von Graphen ermöglichen. Sie
berechnen sogenannte Graph Kernel, d.h. eine Maßzahl der Ähnlichkeit von zwei Graphen. Vereinfacht gesagt bilden Graph Kernel die Ähnlichkeit zweier Graphen als reelle
Zahl ab[FPV14]. In dieser Arbeit wird deshalb auch ein Algorithmus [KM12] zum Berechnen eines Graph Kernels vorgestellt und die Aussagekraft der berechneten reellen
Zahl im Hinblick auf die Identifikation von Subgraphisomorphismen zwischen Graphen
überprüft.
1.2
Überblick
Wir wollen in dieser Arbeit einen exakten und zwei inexakte Graph Matching-Algorithmen vorstellen und vergleichen sowie einen Algorithmus, der einen Graph-Kernel berechnet. In Kapitel 2 werden wir die formalen Grundlagen vorstellen und grundlegende
Definitionen vorgeben, mit denen wir die Algorithmen beschreiben.
In Kapitel 3 stellen wir die vier Algorithmen vor. In Abschnitt 3.1 nehmen wir zunächst
einen exakten Algorithmus für das Graph Matching in den Blick: Der VF2-Algorithmus
[CFSV04b] durchsucht systematisch den Suchraum möglicher Graph Matchings. Im Anschluss werden zwei inexakte Algorithmen gezeigt. In Abschnitt 3.2 lernen wir einen
6
Algorithmus [MB98] kennen, der die Unterschiedlichkeit von Graphen in Änderungsoperationen misst, um einen Graphen in einen anderen zu transformieren, und anhand dieser
zwischen den ähnlichsten ein Matching konstruiert. Schließlich geht Abschnitt 3.3 auf
einen Relaxationsalgorithmus [WH97] ein. Relaxation ist die Optimierung einer globalen
Zielfunktion, die die Güte des Matchings beschreibt[WH96]. Der Algorithmus [KM12]
in Abschnitt 3.4 berechnet einen Graph Kernel.
Die Implementierung der Algorithmen erfolgt in der Programmiersprache Java und wird
in Kapitel 4 vorgestellt. Zuerst wird gezeigt, welche Klassen Graphen und beschriftete
Knoten und Kanten darstellen sowie welche externen Bibliotheken verwendet werden.
Im Anschluss daran geht es mit Rückgriff auf die theoretisch besprochenen Algorithmen
um deren Implementierung. Einige Details der Implementierungen sind erst mit dem
Wissen um die Anwendung der Algorithmen in der Evaluierung zu verstehen. Kapitel 5
hat die Evaluierung zum Thema. Wir evaluieren die Algorithmen an einem synthetischen
Datensatz und Daten aus einer Bibliotheksdatenbank.
In Kapitel 6 ziehen wir ein Fazit über die Eignung der Algorithmen für das Graph
Matching auf attributierten Graphen.
7
Kapitel 2
Grundlagen
2.1
Graphen
Die vorgestellten Algorithmen arbeiten auf attributierten ungerichteten und gerichteten
Graphen, deren Knoten und Kanten beschriftet sind. Die Knoten- und Kantenbeschriftungen seien in den Mengen LV und LE enthalten.
Ein attributierter gerichteter Graph ist ein 4-Tupel G = (V, E, α, β), wobei V die Menge
der Knoten, E ⊆ V × V die Menge der Kanten, α : V → LV eine Funktion, die jedem
Knoten ein Label aus der Menge LV zuweist, und β : E → LE eine Funktion, die jeder
Kante ein Label aus der Menge LE zuweist, ist. Auch wenn wir im Folgenden nur von
Graphen sprechen, sind in der Regel attributierte Graphen gemeint, sofern nicht explizit
anders angegeben.
Die Menge der Vorgängerknoten eines Knoten v im Graphen G1 bezeichnet
Pred(G, v) = {u ∈ V |(u, v) ∈ E},
analog die Menge der Nachfolgerknoten
Succ(G, v) = {u ∈ V |(v, u) ∈ E}.
Wir nennen die Menge eines Knoten j und seiner Nachfolger seine Super-Clique[WH97]:
Cj = {j} ∪ Succ(G, j) und schreiben Rj = (j, i1 , . . . , i|Cj |−1 ) für die n-stellige Relation,
die Knoten j mit seinen Nachfolgern bildet.
Seien G1 = (V1 , E1 , α1 , β1 ) und G2 = (V2 , E2 , α2 , β2 ) zwei Graphen, sodass V1 ∩ V2 = ∅,
und E 0 ⊆ (V1 × V2 ) ∪ (V2 × V1 ) eine Kantenmenge mit einer Beschriftungsfunktion
β 0 : E 0 → LE sind. Dann heißt G = (V, E, α, β) Vereinigung von G1 und G2 [MB98]
hinsichtlich der die beiden Teilgraphen verbindenden Kantenmenge E 0 , wenn
8
• V = V1 ∪ V2
• E = E1 
∪ E2 ∪ E 0
α (v) wenn v ∈ V
1
1
• α(v) =
α2 (v) wenn v ∈ V2



β1 (e)
wenn e ∈ E1
• β(e) = β2 (e) wenn e ∈ E2

 0
β (e) wenn e ∈ E 0
Wir schreiben vereinfachend G = G1 ∪E 0 G2 . Wenn G = G1 ∪E 0 G2 gilt, definieren wir zur
Schreibvereinfachung die Subtraktion auf Graphen als G1 = G − G2 bzw. G2 = G − G1 .
Zu einem gegebenen Graph G = (V, E, α, β) nennen wir einen Graph GS = (VS , ES ,
αS , β S ) Subgraph, wenn gilt VS ⊆ V und ES ⊆ E ∩ (VS × VS ) und αS sowie β S auf
VS bzw. ES beschränkte Funktionen α und β sind, d.h. für v ∈ VS : αS (v) = α(v)
bzw. für e ∈ ES : β S (e) = β(e). Wir bemerken also, dass der Subgraph nicht alle Kanten
besitzen muss, die im Graphen G zwischen den entsprechenden Knoten aus VS vorhanden
sind. Wenn hingegen ES = E ∩ (VS × VS ) gilt, heißt der Subgraph knoten-induziert.
Wir schreiben dann auch G[VS ] = GS ⊆ G. Damit können wir die oben eingeführte
Subtraktion G1 = G − G2 definieren als einen durch die Knotenmenge V \ V2 induzierten
Subgraph auf G: G1 = G − G2 = G[V \ V2 ].
Wir nennen eine Bijektion f : V1 → V2 einen Graphisomorphismus von Graph G1 =
(V1 , E1 , α1 , β 1 ) zu Graph G2 = (V2 , E2 , α2 , β 2 ), wenn sie
• die Nachbarschaftsbeziehung der Knoten beibehält, d.h. für alle u, v ∈ V1 : (u, v) ∈
E1 ⇔ (f (u), f (v)) ∈ E2 ,
• die Knotenbeschriftungen beibehält, d.h. für alle v ∈ V1 gilt α1 (v) = α2 (f (v)),
• die Kantenbeschriftungen beibehält: Sei ψf : V12 → V22 die von f implizierte Zuordnung der Kanten, sodass gilt ψf ( (u, v) ) = ( f (u), f (v) ). Dann meint Beibehaltung
der Kantenbeschriftung, dass für alle Kanten e1 ∈ E1 gilt β1 (e1 ) = β2 (ψf (e1 )).
Davon zu unterscheiden ist ein Subgraphisomorphismus, d.h. eine injektive Funktion
f : V1 → V2 von G1 zu G2 , zu der es einen Subgraph S ⊆ G2 gibt, sodass f ein Graphisomorphismus von G1 zu S ist. Weil wir fordern, dass ein Graphisomorphismus die Nachbarschaftsbeziehung der Knoten erhält, ist der entstehende Subgraph knoten-induziert.
Wir bezeichnen einen Isomorphismus zwischen zwei Graphen auch als Matching der Graphen. Mit (v1 , v2 ) ∈ f bezeichnen wir die Zuordnung von Knoten v1 ∈ G1 zu Knoten
v2 ∈ S im Matching f . Zur Schreibvereinfachung führen wir zusätzlich v1 ∈ f bzw.
v2 ∈ f ein und meinen damit, dass Knoten v1 ∈ G1 bzw. Knoten v2 ∈ G2 durch das
Matching f zu einem Knoten des anderen Graphen zugeordnet wurde.
Von der Komplexität des Problems, zwischen zwei Graphen einen Graphisomorphismus zu finden, ist unbekannt, ob es NP-vollständig ist. Einen Subgraphisomorphismus
zwischen zwei Graphen zu finden, ist die Verallgemeinerung des Graphisomorphismus-
9
problems, weil ein Isomorphismus als ein Subgraphisomorphismus zwischen Graphen
gleicher Knotenzahl interpretiert werden kann. Das Problem, einen Subgraphisomorphismus zu finden, ist NP-vollständig [GJ79].
2.2
Levenshtein-Distanz
Die Levenshtein-Distanz zweier Strings s1 , s2 gibt an, mit wievielen Einfüge-, Lösch- oder
Änderungsoperationen ein String in den anderen überführt werden kann. Wir berechnen
die Distanz gemäß Algorithmus 2.1 nach [MRS08]. Es wird davon ausgegangen, dass die
Strings als Arrays vorliegen. Schrittweise wird dann eine Matrix m konstruiert, deren
Eintrag (i, j) nach Beendigung des Algorithmus angibt, wie groß die Distanz von den
ersten i Buchstaben des Strings s1 zu den ersten j Buchstaben von s2 ist.
Algorithmus 2.1 Levenshtein-Distanz, lev(s1 , s2 )
Eingabe: Strings s1 , s2
Ausgabe: Edit-Distanz zwischen den Strings
1: Initialisiere Matrix m[i, j] = 0 für 0 ≤ i ≤ |s1 | und 0 ≤ j ≤ |s2 |
2: for (i = 0; i ≤ |s1 |; i + +) do
3:
m[i, 0] = i
4: for (j = 0; j ≤ |s2 |; j + +) do
5:
m[0, j] = j
6: for (i = 1; i ≤ |s1 |; i + +) do
7:
for (j = 1; j ≤ |sn2 |; j + +) do
o
8:
m[i, j] = min m[i − 1, j − 1] + 1s1 [i]6=s2 [j] , m[i − 1, j], m[i, j − 1]
9:
return m[i, j]
Dabei ist 1s1 [i]6=s2 [j] gleich 1, falls s1 [i] 6= s2 [j] und sonst 0.
Für die folgenden Algorithmen werden wir ein Maß für die Ähnlichkeit von Knoten- und
Kantenbeschriftungen benötigen. Dieses Maß levsim definieren wir über die LevenshteinDistanz und einen Schwellwert t ∈ [0, 1]. Zwei Strings s1 , s2 sind ähnlich, d.h. s1 ≈ s2 ,
falls
levsim (s1 , s2 ) = 1 −
lev(s1 , s2 )
max{|s1 | , |s2 | , 1}
10
und
s1 ≈ s2 ⇔ levsim (s1 , s2 ) ≥ t
2.3
Stochastik
Sei (Ω, F, P ) ein Wahrscheinlichkeitsraum, wobei Ω die nichtleere Ergebnismenge, F
eine Menge von Teilmengen von Ω, die wir Ereignisse nennen, und P : F → [0, 1] das
Wahrscheinlichkeitsmaß. Dann ist für zwei Ereignisse A, B ∈ F die bedingte Wahrscheinlichkeit
P (A ∩ B)
,
P (A | B) =
P (B)
falls P (B) > 0. Wir können dies als die Wahrscheinlichkeit für das Eintreten von Ereignis A interpretieren, wenn wir wissen, dass Ereignis B eingetreten ist. Wir nennen die
Wahrscheinlichkeit deshalb auch a-posteriori. Der Satz von Bayes drückt eine bedingte
Wahrscheinlichkeit mit Hilfe einer anderen aus:
P (B|A) P (A)
.
P (A|B) =
P (B)
Der Satz von der totalen Wahrscheinlichkeit hilft, die Wahrscheinlichkeit für ein Ereignis
B mithilfe von bedingten Wahrscheinlichkeiten disjunkter Ereignisse Ai auszudrücken:
P
P (B) = N
i=1 P (B | Ai )P (Ai ). Wir sprechen von einer gedächtnislosen Verteilung, wenn
die bisherigen Ereignisse Ai den Ausgang des nächsten Ereignisses Ai+1 nicht beeinflussen. Dann gilt P (Ai+1 | Ai , . . . , A0 ) = P (Ai+1 ).
Obige Definitionen sind die Basis für eine Methode unbekannte Parameter einer Verteilung zu schätzen, wenn wir lediglich einen Ausschnitt aus der Grundgesamtheit beobachten konnten. Wir schätzen einen unbekannten Parameter p einer bekannten Beobachtung
x mit der Maximum-a-posteriori-Methode(MAP)[KS99], indem wir den Wert für p wählen, der die Wahrscheinlichkeit P (p|x) maximiert. Mit dem Satz von Bayes können wir
schreiben:
P (x|p)P (p)
.
p = arg max P (p|x) = arg max
p
p
P (x)
Zum weiteren Verständnis der später erklärten Algorithmen benötigen wir noch den
Begriff der stochastischen Unabhängigkeit. Wir nennen zwei Ereignisse unabhängig, wenn
gilt: P (A ∩ B) = P (A)P (B). Wir verstehen darunter, dass sich die Wahrscheinlichkeit
für das Eintreten eines Ereignisses nicht ändert, wenn das andere Ereignis eintritt oder
nicht eintritt.
2.4
Kernel
Der folgende Abschnitt basiert auf [SS01] und soll einen eher intuitiven Zugang zu dem
Thema Kernel und deren Anwendung bieten. Wir interpretieren Kernel als eine Ähnlichkeitsfunktion für beliebige Objekte aus einer Menge X . Für die Menge der Graphen
11
G wäre ein Kernel also eine Funktion k, die je zwei Graphen eine reelle Zahl als Maß für
deren Ähnlichkeit zuordnet.
Sei also X eine nicht-leere Menge. Um die Ähnlichkeit von Objekten x1 , x2 ∈ X messen
zu können, benötigen wir eine Funktion k : X 2 → R. Wir nennen diese Funktion einen
Kernel. Wir verlangen außerdem, dass k symmetrisch (k(x1 , x2 ) = k(x2 , x1 )) ist. Die
Levenshtein-Distanz ist in diesem Sinne ein Kernel über der Menge der Zeichenketten.
Auch das Skalarprodukt im Rn , das durch hx1 , x2 i = ni=1 [x1 ]i [x2 ]i definiert ist, wobei [x1 ]i die i-te Komponente des Vektors bezeichnet, ist ein Kernel. Nicht nur im Rn
können durch ein Skalarprodukt Objekte der euklidischen Geometrie wie Winkel und
Längen definiert werden, sondern ganz allgemein kann in Skalarprodukträumen H, d.h.
Vektorräumen mit Skalarprodukt, die geometrische Anschauung dieser Objekte formal
bezeichnet werden. Für unsere Zwecke genügt das Verständnis von H als Skalarproduktraum, obwohl wir der Vollständigkeit halber erwähnen, dass sogar noch ein wenig mehr
gefordert wird: Genau genommen soll H ein sogenannter Hilbert-Raum sein. Die Details
der Unterscheidung von Skalarproduktraum und Hilbert-Raum sind in dieser Arbeit
nicht wichtig.
P
Einige Algorithmen des maschinellen Lernens wie zum Beispiel Support-Vektor-Maschinen gehen davon aus, dass die Daten in einem Hilbertraum H, dem sogenannten FeatureSpace, vorliegen. Mit anderen Worten: Wenn wir für Daten wie Graphen oder Zeichenketten eine geeignete Abbildung ϕ : X → H finden, können wir die Algorithmen des
maschinellen Lernens für diese Art von Objekten zugänglich machen. Wir nennen für
x1 ∈ X seinen Feature-Vektor die Auswertung der Abbildung ϕ(x1 ).
Eine wichtige Eigenschaft von Kerneln ist ihre positive Definitheit, denn wie sich herausstellt, gilt für sogenannte positiv definite Kernel k, dass
k(x1 , x2 ) = hϕ(x1 ), ϕ(x2 )i,
wobei x1 , x2 ∈ X sind und ϕ wie oben definiert ist. Mit einem positiv definiten Kernel lässt sich das Skalarprodukt der Feature-Vektoren in (irgend-)einem Feature-Space
berechnen und also lassen sich Methoden des maschinellen Lernens für Objekte wie
Graphen einsetzen.
Um uns dem Begriff der positiven Definitheit zu nähern, benötigen wir zunächst einige
Definitionen. Für Objekte x1 , . . . , xm ∈ X und einen Kernel k definieren wir die GramMatrix als Kij = k(xi , xj ). Weiter nennen wir eine Matrix K positiv (semi-)definit (psd),
wenn für alle ci ∈ R gilt, dass
m
X
ci cj Kij ≥ 0
i,j=1
Wir nennen einen Kernel k positiv (semi-)definit, wenn für alle m ∈ N und x1 , . . . , xm ∈
X die zugehörige Gram-Matrix positiv definit ist.
12
Wir wollen nun eine Idee davon vermitteln, wodurch Kernel k und Abbildung ϕ zusammenhängen [Mur12] und abschließend ein Beispiel für einen Kernel für Strings geben. Zu
einer positiv definiten Gram-Matrix kann die eindeutige Cholesky-Zerlegung K = LT DL
gefunden werden, wobei D die Diagonalmatrix der Eigenwerte λi > 0 von K ist und die
Spalten von L die Eigenvektoren von K sind. Dann können die Elemente Kij wie folgt
berechnet werden:
1
1
Kij = (D 2 L·,i )T (D 2 L·,j )
Dabei sei zur Schreibvereinfachung L·,i der i-te Spaltenvektor der Matrix L. Mit ϕ(xi ) =
1
D 2 L·,i können wir auch schreiben
Kij = ϕ(xi )T ϕ(xj ) = hϕ(xi ), ϕ(xj )i
Wir sehen nun, dass ein Kernel das Skalarprodukt von Feature-Vektoren in einem
Feature-Space ist, die durch die Eigenvektoren aus L definiert werden. Durch die Funktion ϕ ist also eine Abbildung aus X nach H gefunden. Es stellt sich heraus, dass die
explizite Kenntnis der Berechnungsvorschrift für die Funktion ϕ in vielen Anwendungen
nicht notwendig ist, häufig reicht es, das Skalarprodukt hϕ(xi ), ϕ(xj )i = k(xi , xj ) zu
berechnen [Mur12].
Um die Werte des Kernels als Ähnlichkeitsmaß interpretieren zu können, normalisieren
wir den Kernel, d.h. wir schränken seinen Wertebereich auf [0, 1] ein [SS01]. Der Kernel
wird normalisiert, indem wir für die Feature-Vektoren ϕ(xi ), ϕ(xj ) ∈ H die KosinusÄhnlichkeit berechnen:
cos(θ) =
k(xi , xj )
hϕ(xi ), ϕ(xj )i
e
=q
=: k(x
i , xj )
||ϕ(xi )|| ||ϕ(xj )||
k(xi , xi ) k(xj , xj )
Der Wert kann anschaulich als Winkel θ zwischen den Feature-Vektoren interpretiert
e
werden. Wir nennen k(x
i , xj ) den normalisierten Kernel.
2.4.1
Kernel für Strings
Die Levenshtein-Distanz ist nicht postiv definit [CHM04]. Wir können aber einen positiv
definiten Kernel für Strings s1 , s2 definieren:
k(s1 , s2 ) =

1
falls s1 = s2
.
0 sonst
Kernel, die wie oben definiert werden, heißen auch Dirac- oder Delta-Kernel [Bor07].
Einen anderen Kernel für Strings erhalten wir, indem wir die Ähnlichkeit der Strings als
die Anzahl von in beiden Strings vorkommenden Substrings definieren [LSS+ 02]. Dabei
beachten wir nicht nur die Substrings, die zusammenhängend in den Strings vorkommen.
13
Mit einer geringeren Gewichtung gehen auch die Substrings in die Kernelberechnung ein,
die nur mit Lücken zu finden sind.
In den beiden Strings s1 =„cat“ und s2 =„cart“ kommt zum Beispiel der Substring
u1 =„ca“ vor, aber auch (mit Lücken) der Substring u2 =„cat“. Das Vorkommen eines
Substrings bewerten wir mit der Länge seines Vorkommens in dem jeweiligen String.
Für einen Parameter λ ∈ (0, 1) ist der Wert von u1 in s1 bzw. in s2 gegeben durch λ2 .
Der Wert von u2 in s1 ist λ3 , wohingegen er in s2 gegeben ist durch λ4 .
n
Wir bilden einen String s ∈ Σ∗ nun in einen Feature Space R|Σ | ab. Jeder Substring
u ∈ Σn definiert dann eine Komponente des Feature Vektors wie folgt
λLänge des Vorkommens von u in s
X
ϕu (s) =
Vorkommen von u in s
n|
Durch komponentenweise Multiplikation der in den Feature Space R|Σ
Strings erhalten wir den String Subsequence Kernel:
k(s1 , s2 ) =
X
abgebildeten
ϕu (s1 )ϕu (s2 )
u∈Σn
2.4.2
Gute Kernel
Es stellt sich die Frage, welche Eigenschaften ein Kernel für Graphen erfüllen sollte. In
[Bor07] wird gefordert, dass ein guter Kernel
•
•
•
•
positiv definit ist
nicht nur für bestimmte Graphen zu berechnen ist
effizient zu berechnen ist
ausdrucksstark ist.
Die Kernelfunktion k = 0 ist zum Beispiel positiv definit und für alle Graphen effizient zu
berechnen, aber nicht ausdrucksstark in dem Sinne, dass Aussagen über die Ähnlichkeit
von Graphen ermöglicht werden. Der in der vorliegenden Arbeit vorgestellte Kernel ist
positiv definit und grundsätzlich ausdrucksstark. Allerdings werden wir sehen, dass er
nur auf attributierte Graphen beschränkt ist und auch nicht effizient zu berechnen ist.
14
Kapitel 3
Algorithmen
In diesem Kapitel stellen wir vier Algorithmen zum Graph Matching vor. Der erste
Algorithmus „VF2“ gehört zu den exakten Graph-Matching-Algorithmen. Der zweite
Algorithmus, der einen sogenannten fehlerkorrigierenden Subgraphisomorphismus findet, und der dritte Relaxationsalgorithmus gehören zu den inexakten Graph-MatchingAlgorithmen. Der zuletzt vorgestellte Algorithmus berechnet einen Graphkernel zwischen
zwei Graphen, d.h. eine reelle Zahl, und ist kein Graph-Matching-Algorithmus im engeren Sinne.
Wir wollen an dieser Stelle eine Übersicht über die Ausgaben der verschiedenen Algorithmen geben, wenn wir diese auf zwei Graphen G1 und G2 mit Knotenmengen V1 bzw.
V2 anwenden.
1. Durch den Algorithmus VF2 wird ein Subgraphisomorphismus zwischen den Graphen berechnet, d.h. eine bijektive Funktion f : V1 → S für S ⊆ V2 . Falls ein
solcher nicht existiert, wird keine Knotenzuordnung ausgegeben.
2. Einen fehlerkorrigierenden Subgraphisomorphismus zu finden, meint vereinfacht
gesagt, einen Subgraphisomorphismus zwischen einem in Struktur und Beschriftungen veränderten Graphen G1 und dem originalen Graphen G2 zu finden. Der
Algorithmus kennt dazu eine Reihe von sogenannten Grapheditoperationen, die
alle gewisse Kosten besitzen. Er bestimmt dann diejenigen kostengünstigsten Operationen, mit denen Graph G1 so zu einem Graph G01 mit Knoten V10 verändert
wird, dass daraus eine bijektive Funktion f : V10 → S für S ⊆ V2 bestimmt wird.
Der Algorithmus findet diejenigen fehlerkorrigierenden Subgraphisomorphismen
(1)
(2)
(m)
von Graphen aus einer Menge von Graphen B = {G1 , G1 , . . . , G1 } zu einem
Graphen G2 , die am kostengünstigsten sind. Das bedeutet, dass nur von den Sub(i)
graphen S (i) ⊆ G1 ∈ B ein solches Matching gefunden wird, zu denen die dazugehörigen Kosten verglichen mit den anderen möglichen Subgraphen von Graphen
aus B minimal sind.
3. Der Relaxationsalgorithmus findet eine Knotenzuordnung f : V1 → V2 . Relaxation
15
heißt die iterative Optimierung der Zielfunktion bzw. Knotenzuordnung f anhand
eines Gütekriteriums. Im Allgemeinen wird nicht das globale Maximum des Gütekriteriums gefunden. Auch ist die in diesem Verfahren gefundene Knotenzuordnung
im Allgemeinen nicht injektiv [Wil96].
4. Der im letzten Algorithmus berechnete normalisierte Graphkernel ist eine reelle
Zahl c ∈ [0, 1]. Aus dem Graphkernel kann keine Knotenzuordnung rekonstruiert
werden, wir können den Graphkernel lediglich als Ähnlichkeitsmaß zwischen zwei
Graphen interpretieren.
3.1
VF2
Der VF2-Algorithmus [CFSV04b] findet sowohl Graph- als auch Subgraphisomorphismen zwischen zwei Graphen G1 und G2 . Er findet strukturell exakte Matches, d.h. nur
solche, in denen alle Knoten und Kanten aus G1 im Graph G2 vorkommen. Es ist möglich, mit dem Algorithmus auch Matches zwischen zwei Graphen zu finden, wenn ihre
Kanten- und Knotenbeschriftungen nicht exakt identisch, sondern ähnlich sind.
Der Algorithmus konstruiert rekursiv ein partielles Matching f : V1 → V2 und erweitert
dieses sechs Regeln folgend schrittweise um je eine Zuordnung (mj , ni ), bis alle Knoten von G1 erfasst sind. Anfangs ist das partielle Matching leer. In jedem Schritt wird
zunächst eine Menge P an möglichen Zuordnungen der Form (mj , ni ) berechnet. Aus
dieser Menge wird anschließend anhand von sechs Regeln eine Zuordnung gesucht, sodass das partielle Matching erweitert um die Zuordnung ein gültiges partielles Matching
ergibt. Rekursiv wird dann die nächste Zuordnung gesucht. Andernfalls wird mittels
Backtracking einen Schritt zurückgegangen und eine andere Zuordnung aus P ausgewählt.
Algorithmus 3.1 VF2
Eingabe: Graphen G1 = (V1 , E1 , α1 , β1 ) und G2 = (V2 , E2 , α2 , β2 )
Ausgabe: ein Subgraphisomorphismus f : V1 → V2 oder ∅
function Match(partielles Matching f, G1 , G2 )
if f enthält alle Knoten aus G1 then
return f
else
Berechne die Menge möglicher Zuordnungen P bezüglich ≺ und f
for all (mj , ni ) ∈ P do
if alle 6 Regeln evaluieren zu wahr then
Berechne neues partielles Matching f 0 ← f ∪ {(mj , ni )}
Match(f 0 , G1 , G2 )
10: end function
1:
2:
3:
4:
5:
6:
7:
8:
9:
16
Algorithmus 3.1 gibt einen Überblick über den Ablauf des Algorithmus. Im Folgenden
sollen die Details zur Bildung von der Menge P möglicher Zuordnungen und die sechs
Regeln zur Evaluierung möglicher Zuordnungen erläutert werden.
Für die Bildung von P wird die Menge der Knoten in G1 einer totalen Ordnung (mit
≺ bezeichnet) unterworfen. Nur für den gemäß ≺ kleinsten nicht in P vorkommenden
Knoten mj ∈ V1 werden in einem Schritt mögliche Zuordnungen (mj , ni ) gesucht. Durch
diese Vorgehensweise wird der vom Algorithmus betrachtete Suchraum strukturiert, was
möglich ist, weil es für das eventuell letztlich gefundene Matching unerheblich ist, welche
Zuordnung (mj , ni ) zuerst hinzugefügt wurde.
Die Menge P wird aus den Mengen der Knoten bestimmt, die noch nicht im partiellen
Matching f enthalten sind. Dadurch garantiert der Algorithmus die Bildung eines injektiven Matchings. Es gibt drei Möglichkeiten, wie die Menge P gebildet werden kann:
Wir bezeichnen die jeweiligen Mengen mit Pi . Erstens werden alle Kombinationen von
Knoten der Graphen gebildet, die von den Knoten des partiellen Matchings aus f in G1
oder G2 über eine Kante erreicht werden. Seien T1out bzw. T2out die Mengen der Knoten von Graph G1 bzw. G2 , die noch nicht im Matching enthalten sind und von einem
Knoten im partiellen Matching aus über eine Kante erreicht werden.
Tiout = {v | v ∈ Vi ∧ v ∈
/ f ∧ ∃u ∈ f (v ∈ Succ(Gi , u))}
Dann ergibt sich
P1 = {(mj , ni ) | mj ∈ T1out ∧ ni ∈ T2out ∧ ¬∃mp ∈ V1 ( mp ∈ P1 ∧ mp ≺ mj )}
Falls P1 leer ist, werden zweitens Kombinationen von Knoten aus G1 und G2 gebildet,
von denen aus eine Kante in das partielle Matching hinein führt. Zu diesem Zweck
definieren wir analog T1in und T2in .
Tiin = {v | v ∈ Vi ∧ v ∈
/ f ∧ ∃u ∈ f (v ∈ P red(Gi , u))}
und daraus folgend
P2 = {(mj , ni ) | mj ∈ T1in ∧ ni ∈ T2in ∧ ¬∃mp ∈ V1 ( mp ∈ P2 ∧ mp ≺ mj )}
Falls es auch keine solchen Kombinationen gibt, werden drittens alle Kombinationen von
Knoten gebildet, die nicht im partiellen Matching sind.
P3 = {(mj , ni ) | mj ∈
/ f ∧ ni ∈
/ f ∧ ¬∃mp ∈ V1 ( mp ∈ P3 ∧ mp ≺ mj )}
Durch die Anwendung von Regeln auf die möglichen Zuordnungen aus P wird gleichzeitig
die Gültigkeit des Matchings und dessen Erweiterbarkeit überprüft. Eine Regel überprüft
die Ähnlichkeit der Knoten- und Kantenbeschriftungen, die anderen fünf Regeln die
strukturelle Eignung, das partielle Matching um die mögliche Zuordnung (mj , ni ) zu
erweitern.
17
Für die Knotenbeschriftungen und die Beschriftungen von allen ein- und ausgehenden
Kanten muss gelten, dass sie ähnlich sind:
α1 (mj ) ≈ α2 (ni ) ∧
∀(m0 , n0 ) ∈ f
(ni , n0 ) ∈ E2 ⇒ β 2 ((ni , n0 )) ≈ β 1 ((mj , m0 )) ∧
(R1)
(n0 , ni ) ∈ E2 ⇒ β 2 ((n0 , ni )) ≈ β 1 ((m0 , mj ))
Die Definition der Ähnlichkeit (≈) ist von der Anwendung abhängig. In dieser Arbeit
werden Ähnlichkeiten für Beschriftungen mit Strings und Zahlen definiert (siehe dazu
4.2.1). Man merkt, dass durch die erste Regel nur Kantenbeschriftungen von Vorgängern
und Nachfolgern von ni ∈ G2 überprüft werden. Dass keine Kanten in G1 vorhanden sind,
die keine entsprechende Kante in G2 besitzen, stellen wir erst mit den nächsten beiden
Regeln sicher. Die ersten beiden strukturellen Regeln überprüfen, dass zu allen bereits im
Matching enthaltenen Vorgängern bzw. Nachfolgern vom zuzuordnenden Knoten (ni , mj )
auch Vorgänger bzw. Nachfolger im anderen Graphen existieren, die einander jeweils
durch das partielle Matching zugeordnet sind.
∀n0 ∈ f ∩ Pred(G1 , ni ) ∃m0 ∈ Pred(G2 , mj ) (n0 , m0 ) ∈ f
∀m0 ∈ f ∩ Pred(G2 , mj ) ∃n0 ∈ Pred(G1 , ni ) (n0 , m0 ) ∈ f
∧
(R2)
Für Nachfolger:
∀n0 ∈ f ∩ Succ(G1 , ni ) ∃m0 ∈ Succ(G2 , mj ) (n0 , m0 ) ∈ f
∀m0 ∈ f ∩ Succ(G2 , mj ) ∃n0 ∈ Succ(G1 , ni ) (n0 , m0 ) ∈ f
∧
(R3)
Zur Veranschaulichung betrachten wir Abbildung 3.1. Sei das partielle Matching zu
diesem Zeitpunkt durch die Kombinationen (mk , nk ) für k ∈ {1, . . . , 6} gegeben. Die
mögliche Kombination (mj , ni ) verletzt (R1), weil für den zugeordneten Vorgänger m1
von mj der Knoten n1 kein Vorgänger von ni ist. Analog ist (R2) verletzt, wenn wir die
bereits festgelegte Zuordnung (m5 , n5 ) evaluieren.
m1
m4
mj
m2
m3
n1
m5
n2
m6
n4
ni
n3
(a) Graph G1
n5
n6
(b) Graph G2
Abbildung 3.1: Die Regeln (R2) und (R3)
18
Die drei bereits beschriebenen Regeln sind ausreichend, um einen Subgraphisomorphismus zwischen zwei Graphen zu finden, sofern f eine vollständige Abbildung. Der Algorithmus benutzt drei weitere Regeln, um ungültige partielle Matchings möglichst früh
zu erkennen.
Weil alle Knoten von Graph G1 in einem gültigen Matching vorhanden sein müssen, darf
es nicht mehr Vorgänger oder Nachfolger von mj ∈ V1 geben, die zugleich auch in T1in
oder T1out sind, als es Vorgänger oder Nachfolger von ni ∈ V2 aus T2in oder T2out gibt. Die
beiden daraus resultierenden Regeln prüfen also in Voraussicht, ob es schon wegen der
Anzahl verbleibender Knoten im Umfeld des möglichen neuen partiellen Matchings zu
Konflikten kommen kann.
Succ(G2 , ni ) ∩ T2in ≥ Succ(G1 , mj ) ∩ T1in Pred(G2 , ni ) ∩ T2in ≥ Pred(G1 , mj ) ∩ T1in Succ(G2 , ni ) ∩ T2out ≥ Succ(G1 , mj ) ∩ T1out Pred(G2 , ni ) ∩ T2out ≥ Pred(G1 , mj ) ∩ T1out ∧
(R4)
∧
(R5)
Wir wollen zum Verständnis der Regel beispielhaft Abbildung 3.2 betrachten, die Ausschnitte aus Graphen zeigt. Im Matching seien bereits die Knotenkombinationen (m1 , n1 ),
(m2 , n2 ) enthalten, sodass die Knoten ti bzw. t0i zu den Mengen T1in , T1out , T2in , T2out gehören. Gleichzeitig sind ti bzw. t0i Nachfolger von ni bzw. mj . Also ist |Succ(G2 , ni ) ∩ T2out | =
3 ≥ |Succ(G1 , mj ) ∩ T1out | = 2 und (R4) damit erfüllt. (R5) ist verletzt, denn für die zwei
Knoten t3 , t4 ∈ Succ(G1 , mj ) ∩ T1in existiert nur ein möglicher Partner in G2 : der Knoten
t04 .
t01
t1
m1
n1
t2
t02
ni
mj
m2
n2
t3
t03
t4
t04
(a) Ausschnitt aus Graph G1
(b) Ausschnitt aus Graph G2
Abbildung 3.2: Die Regeln (R4) und (R5)
Mit Hilfe der letzten Regel wird sichergestellt, dass es nicht mehr Vorgänger oder Nachfolger zu mj ∈ V1 gibt, die nicht direkt aus dem Umfeld des partiellen Matchings (d.h.
v∈
/ T1in ∪ T1out = T1 ) kommen. Diese Regel schaut quasi zwei Schritte des Algorithmus
19
voraus, da der Konflikt mit diesen Nachbarknoten des hinzuzufügenden Knotens im Vergleich zu (R4) und (R5) erst nach Erweiterung mit einer weiteren Zuordnung entstehen
könnte.
|Succ(G2 , ni ) \ (T2 ∪ {n|n ∈ f })| ≥ |Succ(G1 , mj ) \ (T1 ∪ {m|m ∈ f })| ∧
(R6)
|Pred(G2 , ni ) \ (T1 ∪ {n|n ∈ f })| ≥ |Pred(G1 , mj ) \ (T2 ∪ {m|m ∈ f })|
Im Beispiel von Abbildung 3.3 seien t1 , t2 , t01 nicht in T1 bzw. T2 und nicht im partiellen
Matching enthalten. Dann ist (R6) verletzt und kein Subgraphisomorphismus von G1
nach G2 möglich.
t1
mj
ni
t2
(a) Ausschnitt aus Graph G1
t01
(b) Ausschnitt aus Graph G2
Abbildung 3.3: Die Regel (R6)
Falls ein Graphisomorphismus gefunden werden soll, sollte in den Regeln 3, 4 und 5 das
≥ durch ein = ersetzt werden.
3.1.1
Komplexität
Der Suchraum des Algorithmus ist im schlimmsten Fall dadurch charakterisiert, dass
die Knoten aus V1 mit allen noch nicht im partiellen Matching vorhandenen Knoten
aus V2 zu möglichen Kombinationen verbunden werden. Der erste Knoten v1 ∈ V1 kann
auf alle Knoten aus V2 abgebildet werden. Diese erste Knotenzuordnung kann dann mit
allen möglichen Zuordnungen des zweiten Knotens v2 ∈ V1 auf (|V2 | − 1) Knoten aus V2
kombiniert werden. Es ergeben sich |V2 | · (|V2 | − 1) · . . . · (|V2 | − |V1 |) viele Kombinationen. Die Laufzeit zum Durchlaufen des Suchraums kann also mit O(|V2 |!) abgeschätzt
werden. In jedem Schritt müssen außerdem die Regeln evaluiert und der Folgezustand
gebildet werden, was in linearer Laufzeit möglich ist. Insgesamt erhalten wir damit als
Abschätzung eine exponentielle Laufzeit O(|V2 |! |V2 |).
3.2
Fehlerkorrigierende Subgraphisomorphismen
Im Folgenden wird zunächst ein Distanzmaß zwischen zwei Graphen ähnlich der Levenshtein-Distanz definiert. Es wird angegeben, mit welcher Anzahl von Einfüge- oder
20
Löschoperationen von Knoten und Kanten bzw. der Änderung von deren Beschriftung
ein Graph in einen anderen überführt werden kann. Damit wird es möglich sein, auch
zwischen strukturell unterschiedlichen Graphen Subgraphisomorphismen zu definieren:
Wir erlauben, dass ein Graph erst durch eine minimale Anzahl von Operationen in einen
zum ersten Graph isomorphen Graphen umgewandelt wird. Insofern ist der im Anschluss
dargestellte Algorithmus [MB98] in der Lage, nicht nur zwischen ähnlich beschrifteten
Graphen Subgraphisomorphismen zu erkennen, sondern auch zwischen strukturell ähnlichen.
3.2.1
Edit-Graphen und Subgraphisomorphismen
Zu einem Graphen G = (V, E, α, β) bezeichnet eine Grapheditoperation δ:
•
•
•
•
•
α(v) → lv , v ∈ V, lv ∈ LV : die Änderung der Beschriftung von Knoten v zu lv
β(e) → le , e ∈ E, le ∈ LE : die Änderung der Beschriftung von Kante e zu le
v → $, v ∈ V : das Löschen von Knoten v
e → $, e ∈ E: das Löschen von Kante e
$ → (u, v), u, v ∈ V : das Einfügen einer Kante zwischen den Knoten u, v
Der Edit-Graph δ(G) = (Vδ , Eδ , αδ , βδ ) zu einer Operation δ besteht aus:

V
− {v} wenn δ = (v → $)
sonst
• Vδ = 
V



E
∪ {e}
wenn δ = ($ → e)
• Eδ = E − {e}
wenn δ = (e → $)



E ∩ (Vδ × Vδ ) sonst
• αδ (v) =
• βδ (e) =

l
v
α(v)

l
wenn δ = (α(v) → lv )
sonst
wenn δ = (β(e) → le )
β(e) sonst
e
Durch eine Folge von Grapheditoperationen ∆ = (δ1 , . . . , δk ) kann ein Graph in einen
anderen Graphen ∆(G) = δk (. . . δ1 (G) . . . ) umgeformt werden, der auch als Edit-Graph
bezeichnet wird. Wir bemerken, dass das Hinzufügen von Knoten (δ = $ → v) nicht
notwendig ist, wenn es darum geht, einen Subgraphisomorphismus von ∆(G1 ) nach G2 zu
finden. Wenn mit jeder Operation δ bestimmte Kosten C(δ) verbunden sind, so sind die
Kosten von ∆, C(∆), die Summe der Kosten der einzelnen Operationen. In dieser Arbeit
werden Kostenfunktionen für Strings und Zahlen als Knoten- bzw. Kantenbeschriftungen
implementiert (siehe dazu 4.4).
21
Wir wollen von diesen Definitionen ausgehend nun den Subgraphisomorphismus zwischen
einem Edit-Graphen und einem anderen Graphen definieren. Ein fehlerkorrigierender
Subgraphisomorphismus zwischen G1 und G2 ist ein 2-Tupel f = (∆, f∆ ), sodass f∆ ein
Subgraphisomorphismus zwischen ∆(G1 ) und G2 ist.
Weil im Allgemeinen mehr als eine Folge an Operationen ∆ existiert, um zwischen zwei
Graphen G1 , G2 einen fehlerkorrigierenden Subgraphisomorphismus zu finden, definieren
wir als Subgraphdistanz d(G1 , G2 ) die minimalen Kosten der Operationen aller möglichen
fehlerkorrigierenden Subgraphisomorphismen. Das heißt
d(G1 , G2 ) = min{C(∆)|f = (∆, f∆ ) ist fehlerkorrigierender Subgraphisomorphismus}.
∆
3.2.2
Die Dekomposition
Der hier vorgestellte Algorithmus [MB98] findet den kostengünstigsten fehlerkorrigierenden Subgraphisomorphismus von einem editierten Graphen aus einer Menge B =
(1)
(n)
{G1 , . . . , G1 } zu einem Graphen G2 . Diese Anordnung ist dadurch motiviert, dass in
vielen Anwendungen nicht nur für einen Graphen G1 ein inexaktes Matching zu einem
Graphen G2 gesucht wird, sondern für eine ganze Graphdatenbank mit einer Menge an
Graphen dieses inexakte Matching zu bestimmen ist. Daher muss die Menge B in einem
Vorverarbeitungsschritt zuerst in eine andere Darstellung - die sogenannte Dekomposition - transformiert werden, die dann Ausgangspunkt des Matchingprozesses ist.
Eine Dekomposition definiert eine rekursive Zerlegung der Graphen aus B in kleinere
Subgraphen. Jedes 4-Tupel (G, G0 , G00 , E 0 ) der Dekompositionsmenge zerlegt den Graph
G in die Teilgraphen G0 und G00 und die Menge der verbindenden Kanten E 0 (vgl.
Definition Vereinigung von Graphen in Abschnitt 2.1).
(1)
(n)
Sei B = {G1 , . . . , G1 } eine Menge von Graphen. Eine Dekomposition (in Anlehnung
an [MB98]) D(B) ist eine Menge von 4-Tupeln (G, G0 , G00 , E 0 ), wobei
G, G0 ⊂ G, G00 ⊂ G Graphen sind
E 0 eine Knotenmenge ist, sodass G = G0 ∪E 0 G00
(i)
(i)
für jedes G1 ∈ B ein 4-Tupel (G1 , G0 , G00 , E 0 ) ∈ D(B) existiert
zu jedem (G, G0 , G00 , E 0 ) ∈ D(B) existiert kein anderes (Ĝ, Ĝ0 , Ĝ00 , Ê 0 ) ∈ D(B) mit
G = Ĝ
5. für jedes 4-Tupel (G, G0 , G00 , E 0 ) ∈ D(B) gilt
• wenn G0 mehr als einen Knoten besitzt, existiert (G0 , . . . , . . . , . . . ) ∈ D(B)
• wenn G00 mehr als einen Knoten besitzt, existiert (G00 , . . . , . . . , . . . ) ∈ D(B)
• wenn G0 aus einem Knoten besteht, existiert (G0 , ∅, ∅, ∅) ∈ D(B)
• wenn G00 aus einem Knoten besteht, existiert (G00 , ∅, ∅, ∅) ∈ D(B)
1.
2.
3.
4.
Durch Bedingung 4 ist sichergestellt, dass die Zerlegung an sich eindeutig ist; Bedingung
22
3 sorgt dafür, dass alle Graphen der Menge B erfasst sind. Weil Bedingung 5 besagt, dass
für jedes 4-Tupel (G, G0 , G00 , E 0 ), dessen Graph G aus mehr als einem Knoten besteht,
zwei „nachfolgende“ 4-Tupel für G0 und G00 existieren, können wir eine Dekomposition
als gerichteten Graphen darstellen. Von jedem 4-Tupel, das „Nachfolger“ in diesem Sinne
besitzt, gehen zwei Kanten zu den „nachfolgenden“ 4-Tupeln aus. Ein Beispiel für eine
Dekomposition von zwei Graphen ist in Abbildung 3.4 gegeben. Wir erkennen nun,
inwiefern die Dekomposition gemeinsame Subgraphen nur ein Mal berücksichtigt: Der
Graph g2 ist in zwei Subgraphen zerlegt worden und „teilt“ sich den Subgraphen s2 mit
dem Graphen g1 .
s3 c
s4 a
s5
b
(s2 , s4 , s5 , {e1 })
a
a
e1
b
b
c
b
a
e2
(a) Graph g1
c
a
c
b
b
(s1 , s3 , s2 , {e2 })
a
b
a
b
e3
a
e4
b
(g1 , s2 , s5 , {e3 , e4 })
e5
a
b
b
(g2 , s1 , s2 , {e5 })
(b) Graph g2
(c) Dekomposition
Abbildung 3.4: Dekomposition von zwei Graphen
Für eine Menge von Graphen B gibt es aber mehr als nur eine Möglichkeit, eine Dekomposition zu konstruieren. Der nachfolgend vorgestellte Algorithmus zur Erzeugung der
Dekomposition ist in [Mes95] beschrieben.
23
Algorithmus 3.2 Decompose in Anlehnung an [Mes95]
Eingabe: Graph G, ursprüngliche Dekomposition D̄(B), veränderte Dekomposition
D(B)
1: Finde den größten Subgraph Smax ⊆ G, zu dem ein 4-Tupel (Smax , G0 , G00 , E 0 ) ∈
D̄(B) existiert
2: if Smax ist isomorph zu G then
3:
return
. G ist bereits komplett in D̄(B) zerlegt
4: if kein Smax wurde gefunden then
5:
Wähle zufällig einen Subgraph Smax ⊆ G
6:
if G besteht aus einem Knoten then
7:
D(B) = D(B) ∪ {(G, ∅, ∅, ∅)}
8:
return
9:
else
10:
Decompose(Smax , D̄(B), D(B))
11: Decompose(G − Smax , D̄(B), D(B))
12: Füge das 4-Tupel (G, Smax , G − Smax , E) zu D(B) hinzu, wobei E die Menge der
Kanten zwischen Smax und G − Smax ist
13: return
Im Algorithmus 3.2 unterscheiden wir zwei Dekompositionen D(B), D̄(B). Die Dekompsosition D̄(B) wird nicht verändert, es ist die ursprüngliche Dekomposition, die zum
ersten Aufrufzeitpunkt des Algorithmus vorliegt. Wir benötigen sie, um den maximalen
Subgraph Smax zu finden. In der Dekompostion D(B) werden die Veränderungen durch
den Algorithmus vorgenommen: Zu Beginn des Algorithmus gilt D(B) = D̄(B), nach
Abschluss des Algorithmus ist der Graph G in der Dekomposition D(B) zerlegt. Wir
konstruieren die neue Dekomposition rekursiv. Der Algorithmus kennt zwei Abbruchkriterien: Entweder wir enden mit einem Graphen, der schon komplett in der Dekomposition D̄(B) enthalten ist (Zeile 3), oder wir treffen auf einen Graphen, der nur aus einem
Knoten besteht (Zeile 8). Diese Graphen können nicht weiter zerlegt werden.
Nachdem im Algorithmus also sichergestellt ist, dass Smax in D̄(B) vorhanden ist, zerlegen wir G − Smax und fügen anschließend das 4-Tupel zur Dekomposition hinzu.
Zwei Punkte verbleiben, die zu erklären sind. Wir bilden einen zufälligen Subgraph
Smax ⊆ G (Zeile 5), indem wir eine Hälfte der Knotenmenge V von G auswählen und den
induzierten Subgraph bilden. Der „größte“ Subgraph (Zeile 1) ist der (im Allgemeinen
nicht eindeutige) Subgraph, zu dem es keinen anderen Subgraphen gibt, der mehr Knoten
hat. Wir können ihn mit jedem exakten Graph-Matching-Algorithmus bestimmen.
24
3.2.3
Der Algorithmus
Seien nun also eine Dekomposition D(B) und ein Graph G2 gegeben. Der Algorithmus
findet dann die kostengünstigsten fehlerkorrigierenden Subgraphisomorphismen von Graphen aus B zu G2 . Vereinfachend gesagt werden von den Graphen aus der Dekomposition
schrittweise fehlerkorrigierende Subgraphisomorphismen zu dem Graph G2 konstruiert.
Wenn für zwei Graphen S1 , S2 ein solcher fehlerkorrigierender Subgraphisomorphismus
gefunden wurde und ein 4-Tupel (S, S1 , S2 , E) ∈ D(B) existiert, so werden diese fehlerkorrigierende Subgraphisomorphismen nach Möglichkeit kombiniert und ein fehlerkorrigierender Subgraphisomorphismus von S zu G2 gebildet.
Die ersten fehlerkorrigierenden Subgraphisomorphismen werden von Graphen Si gebildet, die genau einen Knoten enthalten. Allgemein sind mehrere fehlerkorrigierende Subgraphisomorphismen zu einem Graph G2 denkbar, die mit Kosten verbunden
sind (Entfernen des Knotens, Umbenennung), oder ein Subgraphisomorphismus ohne
Fehlerkorrektur, falls die Beschriftungen gleich sind. Wir speichern für jeden Graphen
zwei Listen von fehlerkorrigierenden Subgraphisomorphismen: open(Si ) und closed(Si ).
Einen neu gebildeten fehlerkorrigierenden Subgraphisomorphismus speichern wir zuerst
in open(Si ). Wenn wir ihn dann mit anderen fehlerkorrigierenden Subgraphisomorphismen wie oben beschrieben zu kombinieren versucht haben, speichern wir ihn in closed(Si ).
Um die kostengünstigste Lösung zu erhalten, wird im Algorithmus immer der fehlerkorrigierende Subgraphisomorphismus mit den geringsten Kosten als nächstes betrachtet.
Zur Schreibvereinfachung definieren wir daher auch die Kosten einer Liste als die Kosten
des kostengünstigsten Subgraphisomorphismus. Formal: Die Kosten einer Liste sind
C open(S) =

min
∞
f {C(f )|f
∈ open(S)} falls open(S) nicht leer
sonst
Die Kosten für closed(S) definieren wir analog.
Der sich ergebende Suchraum wird auch bei einer geeigneten Kostenfunktion schnell sehr
groß, wenn alle möglichen sich neu ergebenden fehlerkorrigierenden Subgraphisomorphismen betrachtet würden. Um die Suche effizient zu gestalten und weniger vielversprechend
wirkende fehlerkorrigierende Subgraphisomorphismen nicht weiter untersuchen zu müssen, betrachten wir bei der Auswahl des kostengünstigsten fehlerkorrigierenden Subgraphisomorphismus außerdem eine Heuristik h(S). Wir wählen als Ausgangspunkt für die
Bildung von Kombinationen von fehlerkorrigierenden Subgraphsiomorphismen dann also
denjenigen fehlerkorrigierenden Subgraphsiomorphismus S, für den C(S)+h(S) minimal
in D(B) ist.
Die hier verwendete Heuristik prüft, ob alle in einem fehlerkorrigierendem Subgraphisomorphismus aufeinander abgebildeten Knoten ähnlich sind. Sei also S = (∆, S∆ ) ein
25
fehlerkorrigierender Subgraphisomorphismus und eine Funktion ≈ : V → {true, false}
ein Ähnlichkeitsmaß für Knoten. Dann ist
h(S) =

0
falls für alle (v1 → v2 ) ∈ ∆ gilt: v1 ≈ v2
∞ sonst
Der Algorithmus konstruiert fehlerkorrigierende Subgraphisomorphismen, bis für einen
Graphen aus B ein solcher gefunden wurde. Anschließend werden nur noch fehlerkorrigierende Subgraphisomorphismen gesucht, die höchstens genauso „teuer“ sind. Für manche
Graphen aus B werden also eventuell keine fehlerkorrigierende Subgraphisomorphismen
gefunden, für manche eventuell mehrere.
Damit ergibt sich folgender Algorithmus:
Algorithmus 3.3 ErrorCorrectingSubgraph
Eingabe: Graph G2 = (V2 , E2 , α2 , β2 ), Menge an Graphen B, Dekomposition D(B)
Ausgabe: Für die Graphen aus B, für die die kostengünstigsten fehlerkorrigierenden
Subgraphisomorphismen existieren: dieses inexakte Matching
Parameter: ein Schwellwert T = ∞, eine Kostenfunktion für Grapheditoperationen
C(δ), eine Heuristik für Subgraphisomorphismen h(S)
1: for all S ∈ D(B) mit |VS | = 1, {v} = VS do
2:
Setze open(S) = VertexMatching(v, αS (v), G2 )
3: while Es gibt ein f1 ∈ open(S1 ), sodass C(open(S1 )) + h(S) ≤ T minimal in D(B)
und C(f1 ) minimal in open(S1 ) do
4:
Entferne f1 aus open(S1 ) und setze closed(S1 ) = closed(S1 ) ∪ {f1 }
5:
if S1 ist ein Graph aus der Menge B then
6:
Setze T = C(f1 )
7:
for all (S, S1 , S2 , E) ∈ D(B) oder (S, S2 , S1 , E) ∈ D(B) do
8:
for all f2 ∈ closed(S2 ) do
9:
f = Combine(S1 , S2 , E, G2 , f1 , f2 )
10:
if f ist nicht leer then
11:
Setze open(S) = open(S) ∪ {f }
(1)
(n)
12: return für jeden Graphen Gi ∈ B = {G1 , . . . , G1 }, für den ein Matching gefunden
wurde: closed(Gi )
Zwei Teilprobleme müssen wir noch genauer betrachten, die im Algorithmus 3.3 durch
Unterprogrammaufrufe VertexMatching und Combine angezeigt sind. VertexMatching realisiert das Finden von fehlerkorrigierenden Subgraphisomorphismen von
Graphen mit einem Knoten auf Graph G2 und Combine versucht zwei fehlerkorrigierende Subgraphisomorphismen zu S1 , S2 so zu kombinieren, dass ein neuer fehlerkorrigierender Subgraphisomorphismus von einem Graph S gefunden wird.
Die Aufgabe des Algorithmus 3.4 ist es, alle möglichen fehlerkorrigierenden Subgraphi-
26
somorphismen von einem Graphen S, der einen Knoten v mit Beschriftung l besitzt,
auf G2 zu finden. Zu diesem Zweck werden die Knoten des Graphs v2 ∈ G2 einzeln betrachtet: Der fehlerkorrigierende Subgraphisomorphismus ergibt sich aus der Änderung
der Knotenbeschriftung und einer Zuordnung f∆ (v) = v2 . Außerdem muss die mögliche Löschung des Knotens v in Betracht gezogen werden und in die Menge möglicher
fehlerkorrigierender Subgraphisomorphismen einbezogen werden.
Algorithmus 3.4 VertexMatching
Eingabe: Knoten v, Beschriftung l, Graph G2 = (V2 , E2 , α2 , β2 )
Ausgabe: Menge fehlerkorrigierender Subgraphisomorphismen F
1: F = ∅
. Menge möglicher fehlerkorrigierender Subgraphisomorphismen
2: for all v2 ∈ V2 do
3:
F = F ∪ {∆, f∆ } mit ∆ = (l → α2 (v2 )), f∆ (v) = v2
4: F = F ∪ {(v → $), ∅}
. Löschung des Knotens v
5: return F
Sei (S, S1 , S2 , E) ∈ D(B). Im Folgenden zeigen wir, wie es möglich ist, aus zwei fehlerkorrigierenden Subgraphisomorphismen f1 = (∆1 , f∆1 ), f2 = (∆2 , f∆2 ), die zu den
Teilgraphen S1 bzw. S2 gehören, einen fehlerkorrigierenden Subgraphisomorphismus von
S zu G2 zu konstruieren.
In Algorithmus 3.5 wird zuerst geprüft, dass die Knoten aus S1 und S2 durch f∆1 bzw.
f∆2 auf verschiedene Knoten in G2 abgebildet werden. Ansonsten kann kein gültiger fehlerkorrigierender Subgraphisomorphismus erzeugt werden. Weil auf die Operationen von
∆1 bzw. ∆2 nur auf S1 bzw. S2 definiert sind, können die Grapheditoperationen für den
fehlerkorrigierenden Subgraphisomorphismus von ∆(S1 ∪E S2 ) zu G2 durch Vereinigung
von ∆1 und ∆2 und noch zu bestimmenden Operationen ∆E auf der Menge der Kanten
E zwischen den Teilgraphen gebildet werden, d.h. ∆ = ∆1 ∪ ∆2 ∪ ∆E .
Wir betrachten bei der Bildung von ∆E erst v ∈ S1 , w ∈ S2 , dann w ∈ S1 , v ∈ S2 und
unterscheiden drei mögliche Fälle:
1. Wenn für e = (v, w) ∈ E eine Kante e2 =
f∆1 (v), f∆2 (w)
∈ E2 existiert und
β((v, w)) 6= β2 (f
∆1 (v), f∆2 (w)), dann ergänze ∆E um
(β(e) → β (e ))
falls Änderung der Beschriftung günstiger
2 2
die Operation
(e → $) ∪ ($ → e2 ) falls Löschen und Einfügen günstiger
2. Wenn für e = (v, w) ∈ E keine Kante e2 = f∆1 (v), f∆2 (w) ∈ E2 existiert, dann
ergänze ∆E um die Operation
der Kante)
(e → $) (Löschen
3. Wenn für eine Kante e2 =
f∆1 (v), f∆2 (w)
∈ E2 keine Kante e = (v, w) ∈ E
existiert, dann ergänze ∆E um die Operation ($ → e2 ) (Einfügen der Kante)
27
Algorithmus 3.5 Combine
Eingabe: Teilgraphen S1 , S2 , Kantenmenge E, Graph G2
Fehlerkorrigierende Subgraphisomorphismen f1 = (∆1 , f∆1 ), f2 = (∆2 , f∆2 )
mit ∆1 (S1 ) = (V∆1 , E∆1 , α∆1 , β∆1 ) und ∆2 (S2 ) = (V∆2 , E∆2 , α∆2 , β∆2 )
Ausgabe: ein fehlerkorrigierender Subgraphisomorphismus f = (∆, f∆ ) oder ∅
1: if f∆1 (V∆1 ) ∩ f∆2 (V∆2 ) 6= ∅ then
2:
return ∅
3: Erzeuge den fehlerkorrigierenden Subgraphisomorphismus
f = (∆, f∆ ) von S1 ∪E S2 nach G2 mit

f
f∆ (v) = 
wenn v ∈ V∆1
f∆2 (v) wenn v ∈ V∆2
∆1 (v)
und ∆ = ∆1 ∪ ∆2 ∪ ∆E , wobei ∆E die Grapheditoperationen für E sind
(siehe Text)
4: return f
3.2.4
Komplexität
Die Analyse der Laufzeit orientiert sich an [Mes95], weicht von dieser aber ab, weil
wir in dieser Arbeit nicht die dort gewählte Heuristik einsetzen. Wir nehmen an, dass
(1)
(L)
die Graphen B = {G1 , . . . , G1 } in folgende Dekomposition zerlegt wurden: Jeder
(i)
Graph wird in den einen gemeinsamen Subgraph S und den einzigartigen Graphen G1 −
S = Si zerlegt. Es gibt also L einzigartige Subgraphen. Der gemeinsame Subgraph S
kann eventuell der leere Graph sein, falls die Graphen keinen gemeinsamen Subgraphen
besitzen. Der gemeinsame Subgraph besitze n1 Knoten und die durchschnittliche Anzahl
an Knoten der einzigartigen Graphen Si sei im Mittel n2 , sodass n = n1 + n2 gilt.
Anschließend werden die sich ergebenden Subgraphen jeweils so zerlegt, dass in jedem
Schritt der Zerlegung ein Graph Sv , der aus einem Knoten besteht, „abgetrennt“ wird:
Aus einem Subgraph Si ergibt sich folglich das 4-Tupel (Si , Sv , Si − Sv , E). Si − Sv wird
dann weiter zerlegt.
Sei die Anzahl an Knoten in Graph G2 mit m bezeichnet. Wir betrachten zuerst die Si(1)
tuation, in der nur ein Graph G1 in der Dekomposition vorhanden ist. Wir können die
Anzahl fehlerkorrigierender Subgraphisomorphismen von (irgend-)einem Subgraphen S
(1)
mit k Knoten nach G2 schätzen durch O(mk ). Weil G1 in O(n) viele Subgraphen mit
unterschiedlicher Knotenanzahl k = 1, . . . , n zerlegt wurde, ist die Anzahl aller fehlerkorrigierender Subgraphisomorphismen beschränkt durch O(mn n). Wenn wir außerdem
die Bildung der Kombinationen von je zwei fehlerkorrigierenden Subgraphisomorphismen zu einem neuen berücksichtigen, bei der wir für alle Knoten des einen Subgraphen
je alle Knoten des anderen Subgraphen durchlaufen (vgl. Zeile 1 und Bildung von ∆E
in Zeile 3 in Algorithmus 3.5), ergibt sich insgesamt O(mn n2 ).
28
Wenn wir nun mehrere Graphen in der Dekomposition betrachten, können wir also folgern, dass wir für den gemeinsamen Subgraph die fehlerkorrigierenden Subgraphisomorphismen in O(mn1 n21 ) berechnen. Für die L einzigartigen Subgraphen der Dekomposition
ist die Laufzeit durch O(Lmn2 n22 ) beschränkt. Zuletzt müssen die fehlerkorrigierenden
Subgraphisomorphismen von den Graphen aus der Menge B zum Graph G2 durch Kombination gebildet werden, was durch O(Lmn n1 n2 ) beschränkt ist. Insgesamt ist die Laufzeit des Algorithmus damit also exponentiell in der mittleren Größe der Graphen aus B
beschränkt: O(mn1 n21 + Lmn2 n22 + Lmn n1 n2 ).
3.3
Diskrete Relaxation
Im Folgenden stellen wir einen Relaxationsalgorithmus zum Graph Matching vor. Dieser
optimiert iterativ eine globale Zielfunktion, die die sogenannte Konsistenz des Matchings,
also deren Güte, beschreibt. Der vorgestellte Ansatz[WH97] zählt zu den diskreten Relaxationsalgorithmen, d.h. in jedem Iterationsschritt wird jedem Knoten eines Graphs
ein einziger anderer Knoten des anderen Graphs zugeordnet.
Der hier vorgestellte Ansatz basiert darauf, mithilfe von bayesischer Stochastik ein Maß
der Konsistenz eines Graph Matchings zu definieren und dieses mithilfe diskreter Relaxation zu optimieren. Das gefundene Matching ist im Allgemeinen kein Subgraphisomorphismus [Wil96]. Stattdessen ordnet der Algorithmus „ähnliche“ Knoten zweier Graphen
einander zu. Formal wird eine Funktion f : V1 → V2 gefunden, die Knoten aus V1 auf
Knoten aus V2 abbildet.
Seien also zwei attributierte Graphen G1 = (V1 , E1 , α1 , β1 ) und G2 = (V2 , E2 , α2 , β2 )
gegeben. Wir bezeichnen die Beschriftungen der Graphen mit A1 = {x1v |v ∈ V1 : α1 (v1 ) =
x1v } und A2 = {x2v |v ∈ V2 : α2 (v2 ) = x2v }. Der Algorithmus nutzt die Information von
Kantenbeschriftungen nicht.
Die A-posteriori-Wahrscheinlichkeit, d.h. die Wahrscheinlichkeit eines unbekannten Matchings f bei „Beobachtung“ der Beschriftungen A1 , A2 ist die Zielfunktion der Maximuma-posteriori-Methode. Mit dem Satz von Bayes ergibt sich formal:
P (f |A1 , A2 ) =
P (A1 , A2 |f ) · P (f )
P (A1 , A2 )
Dabei ist P (A1 , A2 |f ) die bedingte Wahrscheinlichkeit der Beschriftungen für ein Matching, P (f ) die unbedingte Wahrscheinlichkeit eines Matchings und P (A1 , A2 ) die gemeinsame Wahrscheinlichkeit der beiden Beschriftungsmengen. Wenn wir weiter annehmen, dass für ein Matching die verschiedenen Paare der Knotenbeschriftungen stochas-
29
tisch unabhängig voneinander sind und den Satz von Bayes anwenden, so ergibt sich:
P (A1 , A2 |f )
Unabhängigkeit
=
Y
Bayes
P (x1u , x2v |u, v) =
Y
(u,v)∈f
(u,v)∈f
P (u, v|x1u , x2v )
P (x1u , x2v )
P (u, v)
Wir drücken die Gesamtwahrscheinlichkeit also durch die Wahrscheinlichkeit des Matchings zweier Knoten P (u, v), der Wahrscheinlichkeit des Auftretens von zwei Beschriftungen P (x1u , x2v ) und der Wahrscheinlichkeit des Matchings zweier Knoten unter der
Bedingung, dass ihre Knotenbeschriftungen bekannt sind, P (u, v|x1u , x2v ) aus. Um die
Zielfunktion gemäß Maximum-a-posteriori-Methode zu maximieren, werden die Wahrscheinlichkeiten P (A1 , A2 ) und P (x1u , x2v ) nicht betrachtet, weil sie nicht abhängig von
dem Matching sind; sie müssen nicht gesondert berechnet werden.
Die Wahrscheinlichkeiten P (u, v|x1u , x2v ) und P (u, v) sind abhängig vom Kontext der
Anwendung[WH97]. Die in dieser Arbeit betrachteten Implementierungen werden in 4.6
vorgestellt. Im Weiteren soll nun die Entwicklung eines Modells für P (f ) nachvollzogen
werden.
Um die Güte eines Matchings zu beurteilen und P (f ) zu berechnen, wird ein Kriterium entwickelt, das auf der einen Seite nicht die gesamte Topologie des Graphen in den
Blick nimmt, auf der anderen Seite aber die topologische Information auch nicht vollkommen außer Acht lässt. Wir betrachten daher strukturelle „Constraints“ von Graph
G2 , die vorgeben, welche Matchings von einem Knoten u ∈ V1 auf einen Knoten v ∈ V2
denkbar sind und nutzen die Super-Cliquen von Graph G2 aus. Weil benachbarte SuperCliquen miteinander in Beziehung stehen, verbindet sich mit dem Ansatz die Idee, dass
sich die Information von dem Matching einer Super-Clique durch Iteration während der
Relaxation auf den restlichen Graph auswirkt [Wil96].
Wenn wir einen Knoten u ∈ V1 betrachten, dann sei Cu seine Super-Clique und Ru =
(u, u1 , . . . , u|Cu |−1 ) die Relation
auf den Knoten der Super-Clique. Die abgebildete Super
Clique ist dann Γu = f (u), f (u1 ), . . . , f (u|Cu |−1 ) . Wir bezeichnen die Menge aller
Super-Cliquen von G2 , die mögliche Matchings von u auf irgendein v definieren, als
Dictionary für u: Θu . Die in Θu enthaltenen Super-Cliquen bilden Relationen Sv =
(v, v1 , . . . ).
Wir bestimmen ein Dictionary unter Berücksichtigung von Größenunterschieden in der
Knotenanzahl der Super-Cliquen, weil wir davon ausgehen, dass in Anwendungen Knoten fehlen oder Knoten, die nicht zugeordnet werden können, vorhanden sind. Für ein
u ∈ V1 wird Θu bestimmt, indem wir die Super-Cliquen von Graph G2 betrachten
und die kleinere Super-Clique mit sogenannten „dummy“ Knoten auffüllen. Wenn also
Succ(G2 , v) < Succ(G1 , u) gilt, so wird die Super-Clique von v zuerst mit „dummy“
Knoten aufgefüllt, ansonsten wird die Super-Clique von u aufgefüllt. Wir betrachten die
Anzahl der maximalen Knotendifferenz zwischen Super-Cliquen als Parameter für den
Algorithmus. Anschließend werden die äußeren Knoten um den Knoten v permutiert,
30
sodass alle möglichen Relationen Sv erzeugt werden (siehe Abbildung 3.5).
{u, u1 , u2 , u3 }
abgebildet aufΘu
u1
u3
u2
u
v1
v
(a) Super-Clique Cu in Graph G1
{ {v, v1 , $, $},
{v, $, v1 , $},
{v, $, $, v1 } }
(b) Super-Clique Cv in Graph G2
(c) Dictionary Θu
{u, u1 , $}
abgebildet auf Θu =
u
u1
v1
v
v2
(d) Super-Clique Cu in Graph G1 (e) Super-Clique Cv in Graph G2
{ {v, v1 , v2 },
{v, v2 , v1 } }
(f) Dictionary Θu
Abbildung 3.5: Beispiele von Super-Cliquen und Dictionaries
Algorithmus 3.6 ComposeSuperClique
Eingabe: Relation einer Super-Clique Ru , Graph G2 = (V2 , E2 ), Knotendifferenz d
Ausgabe: Dictionary Θu
1: for all v ∈ V2 do
2:
Bilde Relation der Super-Clique Sv = (v, v1 , . . . , vn )
3:
if ||Sv | − |Ru || ≤ d then
4:
Fülle die kleinere Relation mit „dummy“ Knoten $ auf, sodass |Sv | = |Ru |
5:
Permutiere alle Knoten außer v in Sv und füge die Permutation zu Θu hinzu
6: return Θu
Wir merken zur Bildung der Permutationen an, dass eventuell vorkommende „dummy“
Knoten $ nicht unterscheidbare Elemente sind. Das bedeutet, dass mathematisch präzise
Permutationen mit Wiederholung gebildet werden(vgl. dazu Abbildung 3.5c).
Der Wert für die Wahrscheinlichkeit P (f ) wird definiert als arithmetisches Mittel aller
1 P
P (Γu ). Für eine Super-Clique Ru
abgebildeten Super-Cliquen, d.h. P (f ) =
|V1 | u∈V1
wissen wir aber, dass alle möglichen Matchings in Θu enthalten sind, und folgern also
mit dem Satz von der totalen Wahrscheinlichkeit
P (Γu ) =
X
P (Γu | Sv ) · P (Sv )
Sv ∈Θu
Für die Wahrscheinlichkeit P (Sv ), dass eine Relation aus dem Dictionary richtig ist, neh-
31
men wir eine Gleichverteilung an, d.h. P (Sv ) = |Θ1u | . Im Folgenden soll nun ein Modell für
die Wahrscheinlichkeit P (Γu | Sv ) entwickelt werden, die beschreibt, dass eine abgebildete Super-Clique Γu durch die richtige Abbildung f entstanden ist unter der Bedingung,
dass Sv die „wahre“ Relation ist. Durch die Annahme, dass beim Matching Fehler mit
einer Wahrscheinlichkeit auftreten können, die einer gedächtnislosen Verteilung folgen,
können wir den Ausdruck als Produkt der einzelnen bedingten Wahrscheinlichkeiten
schreiben: P (Γu | Sv ) =
|S
Qv |
P (f (uk ) | vk ).
k=1
Unser Modell für fehlerhafte Matchings sieht zwei verschiedene Gründe vor: Zum einen
können Fehler durch falsche Zuordnung einzelner Knoten zueinander im Matchingprozess
entstehen, zum anderen können sie entstehen, wenn die Graphen strukturelle Unterschiede aufweisen. Wir nehmen an, dass die Wahrscheinlichkeit fehlerhafter Zuweisungen im
Matchingprozess Pe einer gleichverteilten, gedächtnislosen Verteilung folgt. Fehler durch
Strukturunterschiede treten annahmegemäß mit einer gleichverteilten Wahrscheinlichkeit Pφ auf. Das bedeutet, wenn wir einen Knoten u ∈ V1 auf einen „dummy“ Knoten
oder einen „dummy“ Knoten auf einen Knoten v ∈ V2 abbilden, so passiert das mit
Wahrscheinlichkeit Pφ . Es ergibt sich:


Pφ

wenn uk oder vk „dummy“ Knoten
P (f (uk ) | vk ) = (1 − Pφ )(1 − Pe ) wenn f (uk ) = vk



(1 − Pφ )Pe
wenn f (uk ) 6= vk
Für den Wert von Pe wird in der Implementierung zu [WH97] der Wert 0.3 vorgeschlagen.
Wir folgen diesem Vorschlag. Zu Pφ wird in dem Artikel angemerkt, dass der Parameter
vor allem aus formalen Gründen eingeführt wird.
Wenn wir eine abgebildete Super-Clique Γu mit einer Super-Clique Sv aus dem Dictionary Θu vergleichen, müssen wir also bestimmen:
• Die Anzahl der größeren der beiden Cliquen C = max{|Ru | , |Sv |}
• Die Anzahl an „dummy“ Knoten, mit denen Sv oder Ru aufgefüllt wude, ψ(Γu , Sv ) =
||Ru | − |Sv ||
• Die Anzahl der Unterschiede zwischen nicht-„dummy“ Knoten, die auf nicht-„dummy“ Knoten aus Sv abgebildet werden, die wir H(Γu , Sv ) nennen
Mit einigen Umformungen erhalten wir den folgenden Ausdruck
1 X
KΓ exp − ke H(Γu , Sv ) + kφ ψ(Γu , Sv )
P (Γu ) =
|Θu | Sv ∈Θu u
C
wobei KΓu = (1 − Pφ )(1 − Pe ) , ke = ln
(1 − Pφ )(1 − Pe )
1 − Pe
und kφ = ln
.
Pe
Pφ
Die Konsistenz des Matchings für eine abgebildete Super-Clique P (Γu ) wird damit also
als Summe über die Inhalte der Dictionaries bestimmt. Weil die Unterschiedlichkeit
32
der abgebildeten Super-Clique Γu auf mögliche Dictionary-Einträge Sv als Exponenten
H(Γu , Sv ) bzw. ψ(Γu , Sv ) in die Berechnung eingehen, werden viele Unterschiede zu einer
kleinen Maßzahl und große Ähnlichkeit zu einer großen Maßzahl führen.
Die Vorschrift für die Relaxation lautet damit
f = arg max
f
Y
(u,v)∈f
P (u, v|x1u , x2v ) X
P (Γu )
P (u, v)
u∈V1
Wir können das Matching f aber auch knotenweise optimieren, da eine Zuordnung
f (u) = v den Wert P (f ) nur im Umfeld von Knoten u beeinflusst.
f (u) = arg max
v∈V2
P (u, v|x1u , x2v ) X
P (Γu )
P (u, v)
u∈Ru
Algorithmus 3.7 DiskreteRelaxation
Eingabe: Graph G1 = (V1 , E1 , α1 , β1 ), Graph G2 = (V2 , E2 , α2 , β2 )
Ausgabe: Knotenabbildung f : V1 → V2
Parameter: maximale Schrittzahl I, Anzahl der Knotendifferenz von Super-Cliquen d
1: for all u ∈ V1 do
2:
Bilde Super-Clique Ru
3:
Setze Θu = composeSuperClique(Ru , G2 , d)
P (u, v|x1u , x2v )
4:
Finde initiales Matching f (u) = arg max
v∈V2
P (u, v)
5: while f wurde verändert und i ≤ I do
6:
for all u ∈ V1 do
P (u, v|x1u , x2v ) P
7:
Setze f (u) = arg max
P (Γu )
v∈V2
P (u, v)
u∈Ru
8:
i←i+1
9: return f
3.4
SMKernel
Der im folgenden vorgestellte Algorithmus aus [KM12] berechnet einen Kernel auf Graphen. Die Kernelfunktion wird über alle zwischen den Graphen existierenden Subgraphisomorphismen von G1 nach G2 und von G2 nach G1 definiert. Die Berechnung dieser
Art von Kerneln auf Graphen ist NP-vollständig, aber nach [Bor07] ist sie sehr ausdrucksstark, sodass sich die Frage stellt, ob es eine Möglichkeit gibt, die Information
des Kernels für Anwendungen nutzbar zu machen, in denen Subgraphisomorphismen
gesucht werden.
33
Gegeben die beiden Graphen G1 und G2 bezeichnen wir mit B(G1 , G2 ) die Menge aller
Bijektionen zwischen Knotenmengen V10 ⊆ V1 und V20 ⊆ V2 . Seien weiter λ : B(G1 , G2 ) →
R+ eine Gewichtungsfunktion und KV eine Kernelfunktion für Knoten und KE eine
Kernelfunktion für Kanten. Dann ist der Subgraph Matching Kernel die Funktion
ksm (G1 , G2 ) =
X
f ∈B(G1 ,G2 )
Y
λ(f )
Y
KV (v, f (v))
v∈V10
KE (e, ψf (e)).
e∈V10 ×V20
In [KM12] wird gezeigt, dass dieser Kernel positiv semi-definit ist. Wir erhalten als
Spezialfall davon einen anderen Kernel, wenn wir die Kernel-Funktionen KV für Knoten
und KE für Kanten als Dirac-Kernel wie folgt wählen

1
wenn α1 (v1 ) = α2 (v2 )
KV (v1 , v2 ) = 
0 sonst



1





KE (e1 , e2 ) = 






wenn e1 ∈ E1 ∧ e2 ∈ E2
∧β1 (e1 ) = β2 (e2 ) oder
e1 ∈
/ E1 ∧ e2 ∈
/ E2
0 sonst
Wir erkennen, dass durch die Wahl der Kernelfunktionen alle Bijektionen, die kein Subgraphisomorphismus sind, nicht zur Summe beitragen. Anstatt über die Bijektionen
aus B(G1 , G2 ) zu summieren, können wir nun durch die Wahl dieser Kernelfunktionen
über die Isomorphismen zwischen den Graphen summieren, die von Teilknotenmengen
V10 ⊆ V1 und V20 ⊆ V2 (ein sogenannter gemeinsamer Subgraphisomorphismus) induziert
werden, und erhalten einen weiteren Kernel. Sei also I(G1 , G2 ) diese Menge aller von
den Teilknotenmengen induzierten Isomorphismen zwischen G1 [V10 ] und G2 [V20 ]. Für eine
Gewichtungsfunktion λ : I(G1 , G2 ) → R+ ist der Common Subgraph Isomorphism (CSI)
Kernel definiert als
X
kcsi (G1 , G2 ) =
λ(f )
f ∈I(G1 ,G2 )
Nach [Lev73] gibt es eine Beziehung zwischen den gemeinsamen Subgraphisomorphismen
und den Cliquen im sogenannten Produktgraph von zwei Graphen , die die Berechnung
des CSI Kernels und des Subgraph Matching Kernels ermöglicht. Der (modulare) Produktgraph GP = (VP , EP ) zweier Graphen G1 , G2 ist definiert durch VP = {(v1 , v2 ) ∈ V1 ×
V2 |α1 (v1 ) = α2 (v2 )} und EP besitzt Kanten von (u1 , u2 ) ∈ VP zu (v1 , v2 ) ∈ VP , falls gilt
u1 6= v1 ∧ u2 6= v2 und entweder e1 = (u1 , v1 ) ∈ E1 ∧ e2 = (u2 , v2 ) ∈ E2 ∧ β1 (e1 ) = β2 (e2 )
(c-Kante) oder e1 ∈
/ E1 ∧ e2 ∈
/ E2 (d-Kante). Die Unterscheidung von c-Kanten und
d-Kanten wird bei der Kernelberechnung von maßgeblicher Bedeutung sein, wenn es um
die Geschwindigkeit geht (siehe dazu 4.6).
Ein Beispiel für einen Produktgraphen ist in Abbildung 3.6 gegeben. Gleiche Knoten
der Ausgangsgraphen werden zu einem Knoten im Produktgraphen und Kanten verbinden die Knoten entsprechend obiger Vorschrift. Dabei sind d-Kanten gestrichelt und
c-Kanten durchgängig gezeichnet.
34
1 N
O
1
2
C
3 O
(a) G1
C
N
2
(3, 1)
(2, 2)
4
3
5
C
C
(1, 3)
6 O
(3, 6)
(b) G2
(2, 4)
(2, 5)
(c) Produktgraph von G1 und G2
Abbildung 3.6: Zwei Graphen 3.6a, 3.6b und ihr Produktgraph 3.6c
Das Ergebnis von [Lev73] ist, dass jeder Clique C in GP ein gemeinsamer Subgraphisomorphismus f ∈ I(G1 , G2 ) zugeordnet werden kann. Deshalb kann der CSI Kernel durch
Bestimmung der Cliquen im Produktgraph berechnet werden. Dieses Resultat kann
durch Einführung des gewichteten Produktgraphs so erweitert werden, dass auch die Berechnung des Subgraph Matching Kernels möglich wird. Für zwei Kernelfunktionen KV
auf Knoten und KE auf Kanten ist der gewichtete Produktgraph GP = (VP , EP , αP , βP )
ein 4-Tupel
VP = {(v1 , v2 ) ∈ V1 × V2 | KV (v1 , v2 ) > 0}
EP = {( (u1 , u2 ), (v1 , v2 ) ) ∈ VP × VP | u1 6= v1 ∧ u2 6= v2 ∧ KE ( (u1 , v1 ), (u2 , v2 ) ) > 0}
αP (v) = KV (v1 , v2 )
∀(v1 , v2 ) ∈ VP
βP (e) = KE ( (u1 , v1 ), (u2 , v2 ) )
∀e ∈ EP
Die Knoten und Kanten des gewichteten Produktgraphs sind also mit den Werten des
Kernels auf den Knoten der Einzelgraphen bzw. des Kernels auf den Kanten der Einzelgraphen beschriftet. Wenn der Kernel KE auf den Kanten ein Dirac-Kernel ist, so können
auch im gewichteten Produktgraph d-Kanten und c-Kanten unterschieden werden. Im
Folgenden meinen wir den gewichteten Produktgraphen, wenn wir vom Produktgraphen
sprechen, soweit nicht anders angegeben.
e
Um den normalisierten Kernel k(G
1 , G2 ) zu berechnen, müssen neben dem Wert von
k(G1 , G2 ) auch die Werte der Kernel von k(G1 , G1 ) und k(G2 , G2 ) bekannt sein. Alle
drei Kernel werden durch die identische Funktion SMKernel rekurisv berechnet, die
systematisch die Cliquen eines gewichteten Produktgraphs aufzählt. In [KM12] wird zur
Verbesserung der Laufzeit des Algorithmus vorgeschlagen, die Rekursion bei Erreichen
einer bestimmten maximalen Größe kmax der Cliquen im Produktgraph abzubrechen.
Damit können also auch nur Subgraphen bis zur Größe kmax in die Berechnung des
Kernels miteinbezogen werden. Der so berechnete Kernel verbleibt positiv definit, weil
er äquivalent zu dem allgemeinen Subgraph Matching Kernel mit einer entsprechend
gewählten Gewichtungsfunktion λ ist. Es ergibt sich folgender Algorithmus, um den
Subgraph Matching Kernel zu berechnen.
35
Algorithmus 3.8 SubgraphMatchingKernel
Eingabe: Graphen G1 = (V1 , E1 , α1 , β1 ) und G2 = (V2 , E2 , α2 , β2 )
e
Ausgabe: der normalisierte Graphkernel k(G
1 , G2 ) ∈ [0, 1]
Parameter: Kernelfunktionen für Knoten KV und Kanten KE und max. Rekursionstiefe d, Gewichtungsfunktion λ
1: Erstelle gewichteten Produktgraph GP = (VP , EP , αP , βP ) aus G1 , G2
2: k(G1 , G2 ) = SMKernel(1, ∅, VP , GP , 0)
3: Erstelle gewichteten Produktgraph GP 0 = (VP 0 , EP 0 , αP 0 , βP 0 ) aus G1 , G1
4: k(G1 , G1 ) = SMKernel(1, ∅, VP 0 , GP 0 , 0)
5: Erstelle gewichteten Produktgraph GP 00 = (VP 00 , EP 00 , αP 00 , βP 00 ) aus G2 , G2
6: k(G2 , G2 ) = SMKernel(1, ∅, VP 00 , GP 00 , 0)
k(G1 ,G2 )
e
7: return k(G
1 , G2 ) = √
k(G1 ,G1 ) k(G2 ,G2 )
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
function SMKernel(w, C, P , GP , i)
Eingabe: das Gewicht w der Clique C, die Menge möglicher Knoten P für
eine Erweiterung der Clique, der Produktgraph GP , Rekursionstiefe i
while |P | > 0 und i <= d do
v ← ein Element von P
C 0 ← C ∪ {v}
w0 ← w · αP (v)
. Knotengewicht multiplizieren
for all u ∈ C do
w0 ← w · βP ((u, v))
. Kantengewicht multiplizieren
value ← value + w0 · λ(C 0 )
value ← value + SMKernel(w0 , C 0 , P ∩ Succ(GP , v), GP , i + 1)
. Clique
erweitern
P ← P \ {v}
return value
end function
3.4.1
Komplexität
Weil es eine Entsprechung von Cliquen im Produktgraph GP und für die Berechnung
des Kernels notwendigen Bijektionen zwischen den Graphen G1 , G2 gibt, können wir eine
obere Schranke für den Algorithmus
durch Betrachten der Bijektionen erhalten. In einem
n
Graph mit n Knoten gibt es k mögliche Subgraphen der Größe k. Außerdem gibt es
zwischen diesen Subgraphen maximal k! Isomorphismen, sodass wir die Cliquenanzahl
abschätzen durch
!
!
!
k
k
X
X
n1 n2
n1 n2
C(k) =
i!
≤
i
i
i
i=0
i=0
Damit besitzt der modifizierte Algorithmus polynomielle Laufzeit:O(nC(k)) = O(knk+1 ),
wobei n =n1 n2 . Der ursprüngliche Algorithmus besitzt dagegen exponentielle Laufzeit,
P
weil ni=0 ni = 2n .
36
Kapitel 4
Implementierung
Der folgende Abschnitt beschreibt die Implementierung der im vorherigen Kapitel vorgestellten Algorithmen in Java. In den gezeigten UML-Klassendiagrammen sind wegen der
besseren Übersichtlichkeit Getter- und Setter-Methoden nicht explizit aufgelistet. Die
Implementierung unterscheidet an einigen Stellen Knoten bzw. Kanten, die mit Strings
beschriftet sind, und Knoten bzw. Kanten, die mit Zahlen beschriftet sind. Diese Unterscheidung bezieht sich auf die in Kapitel 5 vorgestellten Anwendungen, in der Knoten
und Kanten mit diesen Beschriftungen evaluiert werden.
4.1
Externe Bibliotheken
4.1.1
Die JGraphT-Bibliothek
Wir benutzen zur Implementierung der Algorithmen die JGraphT-Bibliothek 1 , die uns
Datenstrukturen zur Repräsentation von Graphen zur Verfügung stellt. Wir werden hier
die wichtigsten Interfaces kurz vorstellen, einen Überblick bietet Abbildung 4.1. Die
Klasse Graph stellt einen Graph dar und kapselt den Zugriff auf Knoten und Kanten.
Wie alle Interfaces ist auch dieses ein generischer Typ und besitzt zwei Typparameter:
V für die Knotenklasse und E für die Kantenklasse. Die Typparameter sind in Kästen
mit gestrichelten Rändern in den UML-Diagrammen verzeichnet. Wir benutzen unsere
eigenen beschrifteten Knoten- und Kantenklassen, die insbesondere Methoden anbieten,
um die Ähnlichkeit zweier Beschriftungen festzustellen. Während unsere Klassen nach
außen das Interface Graph als Eingabe akzeptieren, unterscheiden sie in ihrer internen
Funktionsweise zwischen DirectedGraph und UndirectedGraph.
1
http://jgrapht.org - JGraphT offizielle Webseite
37
Nachbarknoten können über das Interface Graph nur durch Abfrage der ein- bzw. ausgehenden Kanten berechnet werden. Um einmal abgefragte Nachbarknoten bei erneuter
Abfrage nicht wieder berechnen zu müssen, werden zusätzlich die Klassen NeighborIndex
bzw. DirectedNeighborIndex verwendet. Diese speichern Nachbarknoten nach der ersten Abfrage ab und dienen als Cache. Das Interface ListenableGraph bietet die Möglichkeit, dass strukturelle Änderungen am zugrundeliegenden Graph von anderen Klassen
bemerkt werden können, sodass zum Beispiel ein NeighborIndex aktualisiert werden
kann. Wir repräsentieren die Dekomposition als ListenableGraph, die wir zum Berechnen der fehlerkorrigierenden Subgraphisomorphismen benötigen. Dadurch kann sie
einfacher um andere Graphen erweitert werden.
org jgrapht
V, E
V, E
«interface»
Graph
«interface»
DirectedGraph
V, E
«interface»
UndirectedGraph
V, E
«interface»
GraphMapping
V, E
«interface»
ListenableGraph
org jgrapht alg
V, E
DirectedNeighborIndex
V, E
NeighborIndex
Abbildung 4.1: Wichtige Interfaces und Klassen in JGraphT
38
4.1.2
Andere Hilfsfunktionen
Für einige spezielle Aufgabestellungen greifen wir auf frei verfügbare Bibliotheken zurück. Um die Levenshtein-Distanz zwischen Strings zu berechnen, setzen wir die Funktion
getLevenshteinDistance() aus dem Apache Commons Projekt2 ein. Die Permutation
der Knoten zur Berechnung der Dictionaries für die diskrete Relaxation wird nicht im
Rahmen dieser Arbeit implementiert, sondern hier wird eine Bibliothek aus Google Guava3 eingesetzt. Zuletzt wird für den String Subsequence Kernel, der in Abschnitt 2.4.1
vorgestellt ist, eine Implementierung des Software-Pakets Weka (Waikato Environment
for Knowledge Analysis)4 genutzt.
4.2
4.2.1
Allgemeine Klassen
Knoten- und Kantenklassen
entities
L
AbstractLabelVertex
– label : L
+ isSimilar (v : AbstractLabelVertex<L>) : boolean
+ isEqual (v : AbstractLabelVertex<L>) : boolean
+ relativeDistance (v : AbstractLabelVertex<L>) : double
«bind»
«bind»
L → Double
L → String
StringLabelVertex
NumberLabelVertex
– LEVENSHTEIN
THRESHOLD : double
– THRESHOLD : double
Abbildung 4.2: Klassen, die Knoten darstellen
2
http://commons.apache.org/ - Apache Commons
https://github.com/google/guava - Google Guava
4
http://www.cs.waikato.ac.nz/~ml/weka/ - Weka
3
39
entities
L
AbstractLabelEdge
– label : L
+ isSimilar (v : AbstractLabelEdge<L>) : boolean
+ isEqual (v : AbstractLabelEdge<L>) : boolean
+ relativeDistance (v : AbstractLabelEdge<L>) : double
«bind»
«bind»
L → Double
L → String
StringLabelEdge
NumberLabelEdge
– LEVENSHTEIN
THRESHOLD : double
– THRESHOLD : double
Abbildung 4.3: Klassen, die Kanten darstellen
Alle Klassen, die beschriftete Knoten oder Kanten implementieren, erben von den abstrakten Klassen AbstractLabelVertex und AbstractLabelEdge. Diese bieten Methoden an, mit der sich die Ähnlichkeit zweier Knoten feststellen lässt und diese Ähnlichkeit
auf ein Distanzmaß d ∈ [0, 1] abbilden lässt. Klassen, die von diesen abstrakten Klassen
erben, legen fest, welche Beschriftungen die Knoten bzw. Kanten tragen. Zum Beispiel
sind StringLabelVertex und StringLabelEdge mit Strings beschriftet, wohingegen
NumberLabelVertex und NumberLabelEdge mit Zahlen beschriftet sind. Die Distanz
zwischen zwei mit Strings beschrifteten Knoten bzw. Kanten wird mittels der in Abschnitt 2.2 vorgestellten Levenshtein-Distanz berechnet. Knoten und Kanten, die mit
Strings s1 , s2 beschriftet sind, sind ähnlich, wenn für den LevenshteinThreshold t gilt
levsim (s1 , s2 ) ≥ t. Ihre relative Distanz beträgt:
lev(s1 , s2 )
.
max{|s1 | , |s2 | , 1}
Knoten und Kanten, die mit Zahlen l1 , l2 beschriftet sind, sind ähnlich, falls für einen
Threshold t gilt: |l1 − l2 | ≤ t. Ihre relative Distanz beträgt:
|l1 − l2 |
min
,1 .
t
40
4.2.2
Die GraphMatcher-Klasse
Alle Klassen, die die vorgestellten Algorithmen implementieren, erben von der abstrakten
Klasse GraphMatcher. Diese bietet mit ihren Methoden eine einheitliche Schnittstelle,
um Daten über den Matchingprozess abzufragen. Auf diese Weise kann die programmatische Umsetzung der Evaluation einfacher erfolgen, weil davon ausgegangen wird, dass
die entsprechenden Klassen alle diese Methoden besitzen. Wenn also die Klasse SMKernel
für die Berechnung des Graph Kernels eine Methode matchGraphs() implementiert, so
ist das streng genommen semantisch falsch, weil der Graph Kernel kein Graph Matching
ist.
entities
V, E, VL, EL
GraphMatcher
+ g1 : Graph<V, E>
+ g2 : Graph<V, E>
# runtime : long
# timeSteps : Map<String, Long>
GraphMatcher(g1 : Graph<V, E>, g2 : Graph<V, E>,
edgeClass : Class<E>)
+ matchGraphs() : void
Abbildung 4.4: Die Klasse GraphMatcher
4.3
VF2
Der Algorithmus VF2 wird im Wesentlichen in der Klasse VF2 implementiert. Die Klasse
State repräsentiert den Zustand des Matching-Prozesses, die Klasse Pair eine mögliche
Zuordnung. Beide Klassen implementieren keine Algorithmen, sondern halten ausschließlich Daten vor.
41
vf2
V, E, VL, EL
Pair
1
1
VF2
state
1
1
State
Abbildung 4.5: Klassen im Package vf2
Wir halten uns bei der Implementierung an die Vorgaben aus [CFSV04b]. Der gegenwärtige Zustand von zugeordneten Knoten wird durch Arrays core_1 und core_2 dargestellt. Eine Zuordnung (vi , vj ) (der „i-te“ Knoten von G1 wird dem „j-ten“ Knoten von
G2 zugeordnet) bedeutet dann, dass core_1[i] = j und umgekehrt core_2[j] = i gilt.
Um die Mengen T1in , T2in , T1out , T2out der Knoten zu beschreiben, die durch in das partielle
Matching hinein- oder aus ihm herausführende Kanten mit dessen Knoten verbunden
sind, verwenden wir die übrigen vier Arrays. Wenn wir in der Rekursionstiefe k feststellen, dass der Knoten i nun zum ersten Mal im Graph G1 aus dem partiellen Matching
heraus erreichbar ist, setzen wir out_1[i] = k. Auf diese Weise kann das Wiederherstellen
dieser Mengen beim Backtracking von Stufe k auf Stufe k − 1 realisiert werden, indem
wir den Array dort zurücksetzen, wo k eingetragen ist.
State
NULL_NODES : int
+ G1 : int
+ G2 : int
+ core_1 : int[]
+ core_2 : int[]
+ in_1 : int[]
+ in_2 : int[]
+ out_1 : int[]
+ out_2 : int[]
+ depth : int
+ matchingFound : boolean
+ N : int
+ M : int
+ State (G1 : int, G2 : int)
+ Pair(n : int, m : int)
(a) Die Klasse State
(b) Die Klasse Pair
Pair
In der Klasse VF2 wird die Logik des Matching-Algorithmus implementiert (vgl. Algorithmus 3.1). Die Methode generateCandidates() konstruiert die Menge P neuer
möglicher Kombinationen von Knoten (mj , ni ) (Zeile 5). Die dabei eingesetzte Hilfsmethode findPairs() sucht zum kleinsten möglichen Index eines Knotens aus dem Array
m alle noch nicht zugeordneten Knoten im Array n und erzeugt daraus eine Liste an
42
möglichen Kombinationen. Diese werden dann auf Gültigkeit im Hinblick auf bestimmte
Regeln getestet (Zeile 7).
Die nachfolgende Tabelle gibt einen Überblick darüber, in welcher Methode welche Regel
evaluiert wird.
Regel
R1
R2
R3
R4
R5
R6
Methode
ruleSemantic()
rulePred()
ruleSucc()
ruleIn()
ruleOut()
ruleNew()
Hilfsmethode
–
predSuccHelper()
predSuccHelper()
cardInOutHelper()
cardInOutHelper()
newHelper()
Wenn eine mögliche Kombination alle Regeln erfüllt, so wird der Zustand des Matchings
durch updateVector() (Zeile 8) erneuert. Der Algorithmus des Matchings wird durch
matchGraphs() koordiniert.
43
V, E, VL, EL
VF2
# g1VertexOrder : List<V>
# g2VertexOrder : List<V>
# directedG1Neighbors : DirectedNeighborIndex<V, E>
# directedG2Neighbors : DirectedNeighborIndex<V, E>
# undirectedG1Neighbors : NeighborIndex<V, E>
# undirectedG2Neighbors : NeighborIndex<V, E>
+ mapping : GraphMapping<V, E>
+ VF2(g1 : Graph<V, E>, g2 : Graph<V, E>, edgeClass : Class<E>)
+ matchGraphs() : GraphMapping<V, E>
# match(state : State) : State
# updateVector(pairIndex : int, inOut : int[], predSucc : List<V>,
orderedVertices : List<V>, recursionDepth : int) : int[]
# restoreVector(vector : int[], currentDepth : int) : int[]
# generateCandidates (state : State) : List<Pair>
# findPairs(n : int[], m : int[], state : State) : List<Pair>
# feasible(pair : Pair, state : State) : boolean
# ruleSemantic(pair : Pair, state : State) : boolean
# rulePred(pair : Pair, state : State) : boolean
# ruleSucc(pair : Pair, state : State) : boolean
# predSuccHelper(mapping : int[], predSucc1 : List<V>, vertexList1 : List<V>,
predSucc2 : List<V>, vertexList2 : List<V>) : boolean
# ruleIn(pair : Pair, state : State) : boolean
# ruleOut(pair : Pair, state : State) : boolean
# cardInOutHelper(state : State, predSucc1 : List<V>, inOut1 : int[],
predSucc2 : List<V>, inOut2 : int[]) : boolean
# ruleNew(pair : Pair, state : State) : boolean
# newHelper(state : State, predSucc1 : List<V>, predSucc2 : List<V>) : boolean
– getG1Predecessors(v : V): List<V>
– getG2Predecessors(v : V): List<V>
– getG1Successors(v : V): List<V>
– getG2Successors(v : V): List<V>
Abbildung 4.7: Die Klasse VF2
44
4.4
Fehlerkorrigierende Subgraphisomorphismen
nsg
V, E, VL, EL
V, E, VL, EL
NSG
Decomposition
1
1
1
0...*
V, E, VL, EL
SubgraphIsomorphism
0...*
1
V, E, VL, EL
Combination
1
V, E, VL, EL
0...*
E
«interface»
ICostFunction
EdgeMapping
«enum»
EdgeOperation
«enum»
VertexOperation
EDGESUB
EDGEDEL
EDGEINS
VERTEXSUB
VERTEXDEL
Abbildung 4.8: Klassen im Package nsg
Die Implementierung des Algorithmus, der fehlerkorrigierende Subgraphisomorphismen
findet, ist auf acht Klassen verteilt. Zwei Phasen müssen unterschieden werden: In der
ersten Phase wird die Dekomposition gebildet, in der zweiten wird ein fehlerkorrigierender Subgraphisomorphismus von mindestens einem in der Dekomposition vorhandenen
Graphen zu einem anderen Graph gefunden. Die Klasse NSG dient als Einstiegspunkt
in den Algorithmus. Über decompose() wird ein neuer Graph zur Dekomposition hinzugefügt, mittels matchGraphs() der Matchingprozess gestartet. Die ersten fehlerkorrigierenden Subgraphisomorphismen zwischen Graphen aus der Dekomposition, die einen
Knoten enthalten, und dem Eingabegraphen werden durch vertexMatching() (siehe
unten) ermittelt. Nach dem Matching können die fehlerkorrigierenden Subgraphisomor-
45
phismen mit getAllSubgraphIsomorphisms() erfragt werden. Das Attribut fastEval
dient der Vereinfachung der späteren Evaluation: Wenn es wahr ist, wird lediglich ein
einziger fehlerkorrigierender Subgraphisomorphismus gefunden. Auf das Finden weiterer
fehlerkorrigierender Subgraphisomorphismen mit gleichen Kosten wird verzichtet.
V, E, VL, EL
NSG
# decomposition : Decomposition<V, E, VL, EL>
– threshold : int
– costFunction : ICostFunction<V, E, VL, EL>
– fastEval: boolean
+ NSG (G1 : Graph<V, E>, G2 : Graph<V, E>, edgeClass : Class<E>)
+ matchGraphs () : GraphMapping<V, E>
+ reset (dec : Decomposition<V, E, VL, EL>) : void
# matchGraph(matchedGraph : Graph<V, E>, threshold : int,
decomposition : Decomposition<V, E, VL, EL>) : void
+ decompose (decomposedGraph : Graph<V, E>, edgeClass : Class<E>,
decomposition : Decomposition<V, E, VL, EL>) :
Decomposition<V, E, VL, EL>
+ getAllSubgraphIsomorphisms() :
List<SubgraphIsomorphism<V, E, VL, EL>>
# vertexMatching (singleGraphVertex : V, matchedGraph : Graph<V, E>) :
List<SubgraphIsomorphism<V, E, VL, EL>>
Abbildung 4.9: Die Klasse NSG
Die Klasse Decomposition ist die Datenstruktur, in der die Zerlegung der Graphen für
das spätere Matching vorgehalten wird. Sie implementiert den rekursiven Zerlegungsalgorithmus in decomposeRec(). Für die in der Dekomposition vorkommenden 4-Tupel
(G, S1 , S2 , E) gibt es die Klasse Combination. Die Klasse Decomposition stellt nach
außen die Informationen über die Kombinationen zur Verfügung, die im Algorithmus
3.3 von den Listen open(S) und closed(S) benötigt werden. Beispielsweise kann die
Kombination, die unter allen Kombinationen der Dekomposition den günstigsten Subgraphisomorphismus enthält, durch getCheapestOpen() erhalten werden.
Betrachten wir nun, wie Algorithmus 3.2 zur Berechnung der Dekomposition in decomposeRec() umgesetzt wird. Wir bestimmen den größten Subgraph Smax (Zeile 1),
indem wir den Matching-Algorithmus der Klasse NSG so aufrufen, dass dieser nur fehlerkorrigierende Subgraphisomorphismen findet, die keine Kosten besitzen, d.h. „echte“ Subgraphisomorphismen sind. Weil wir die Dekomposition während des rekursiven
Aufrufs ändern, wird dieses Matching auf der Kopie der Dekomposition matchingCopy
(vgl. D̄(B)) ausgeführt. Algorithmisch eher einfach ist das Erstellen des neuen 4-Tupels
(G, Smax , G − Smax , E) (Zeile 12), wohingegen die Umsetzung in der Methode create-
46
NewCombination() mit einigem Aufwand verbunden ist, weil die Objekte der Knoten der
Subgraphen Smax bzw. G − Smax nicht zwangsläufig in dem Objekt von G vorkommen.
V, E, VL, EL
Decomposition
– decompositionGraph :
ListenableDirectedGraph<Combination<V, E, VL, EL>, DefaultEdge>
– decompGraphIndex :
DirectedNeighborIndex<Combination<V, E, VL, EL>, DefaultEdge>
– singleVertices : List<Combination<V, E, VL, EL>>
– matchingCopy : Decomposition<V, E, VL, EL>
+
+
+
+
+
Decomposition()
getNoCostAndMaximalFromClose() : Combination<V, E, VL, EL>
getCheapestOpen () : Combination<V, E, VL, EL>
resetCosts () : void
decompose (decomposedGraph : Graph<V, E>, edgeClass : Class<E>,
nsg : NSG<V, E, VL, EL>) : void
# decomposeRec (decomposedGraph : Graph<V, E>, edgeClass : Class<E>,
nsg : NSG<V, E, VL, EL>) : Combination<V, E, VL, EL>
# createNewCombination (decomposedGraph : Graph<V, E>,
edgeClass : Class<E>, halfVertexSet : Set<V>,
otherHalfVertexSet : Set<V>, maxSubgraph : Combination<V, E, VL, EL>,
modelMinusMaxSubgraph : Combination<V, E, VL, EL>
isoFromMax : Map<V, V>, isoFromSubgraphMinusMax : Map<V, V>) :
Combination<V, E, VL, EL>
Abbildung 4.10: Die Klasse Decomposition
Die Klasse Combination ist die Repräsentation der 4-Tupel aus der Dekomposition
D(B). In ihr werden hauptsächlich Listen von fehlerkorrigierenden Subgraphisomorphismen, die in der Klasse SubgraphIsomorphism implementiert sind, verwaltet. Die
Klasse stellt nach außen Methoden zur Verfügung, mit den Listen open und close zu
interagieren und zum Beispiel die kostengünstigsten fehlerkorrigierenden Subgraphisomorphismen aus der Liste zu erhalten.
47
V, E, VL, EL
Combination
+ G : Graph<V, E>
+ G1 : Combination<V, E, VL, EL>
+ G2 : Combination<V, E, VL, EL>
+ edges : Set<E>
– isModelGraph : boolean
– open : List<SubgraphIsomorphism<V, E, VL, EL>>
– close : List<SubgraphIsomorphism<V, E, VL, EL>>
+ Combination(g : Graph<V, E>, g1 : Combination<V, E, VL, EL>,
g2 : Combination<V, E, VL, EL>, edges : Set<E>,
close : SubgraphIsomorphism<V, E, VL, EL>)
+ openEmpty() : boolean
+ clearOpen() : void
+ setOpen(openList : List<SubgraphIsomorphism<V, E, VL, EL>>) : void
+ getOpenCosts() : double
+ addToOpen(iso : SubgraphIsomorphism<V, E, VL, EL>) : void
+ addAllToOpen(isoList : List<SubgraphIsomorphism<V, E, VL, EL>>) : void
+ closeEmpty() : boolean
+ clearClose() : void
+ getCloseCosts() : double
+ peekFirstFromClose() : SubgraphIsomorphism<V, E, VL, EL>
+ peekFirstFromOpen() : SubgraphIsomorphism<V, E, VL, EL>
+ pollFirstFromOpen() : SubgraphIsomorphism<V, E, VL, EL>
+ combineWithAllFromClose(isomorphism1 :
SubgraphIsomorphism<V, E, VL, EL>, successorCombi :
Combination<V, E, VL, EL>, mappedGraph : Graph<V, E>) :
List<SubgraphIsomorphism<V, E, VL, EL>>
Abbildung 4.11: Die Klasse Combination
Die Klasse SubgraphIsomorphism repräsentiert einen fehlerkorrigierenden Subgraphisomorphismus, weshalb sie die Kosten costs desselben und die Knoten- bzw. Kantenisomorphismen in vertexMap bzw. edgeMap speichert. Die Menge der Knotenzuordnungen
vertexMap wird rekurisv aus den fehlerkorrigierenden Subgraphisomorphismen berechnet, aus denen der betrachtete fehlerkorrigierende Subgraphisomorphismus durch Kombination gebildet wurde. Zu diesem Zweck existieren predecessor1 und predecessor2.
Hinzuzufügende Kanten sind in der Menge insertedEdges gespeichert. Kanten, die
durch den fehlerkorrigierenden Subgraphisomorphismus gelöscht werden, werden nicht
explizit gespeichert. Sie können aber gefunden werden, weil alle Kanten des dazugehörigen Graphen, die nicht durch die edgeMap abgebildet werden, als gelöscht angesehen
werden können. Analoges gilt für hinzugefügte Knoten: Wenn ein Knoten hinzugefügt
wurde, so wird ein Knoten, der nicht im ursprünglichen Graphen vorhanden ist, durch
48
die vertexMap abgebildet.
Der Konstruktor der Klasse SubgraphIsomorphism ist der zentrale Bestandteil der Methode vertexMatching() der Klasse NSG, die Algorithmus 3.4 verwirklicht. Wir bilden die einzelnen Knoten aufeinander ab und erschaffen dafür je ein Objekt der Klasse
SubgraphIsomorphism, das beschreibt, mit welcher Grapheditoperation und welchen
Kosten diese Abbildung funktioniert. Die Kostenfunktion ist ein Attribut der Klasse
Subgraphisomorphism. Sehr wichtig für die Speichereffizienz des Programms ist es, dass
wir im Konstruktor auch die Heuristik der Kosten berechnen. Die hier eingesetzte Heuristik, die in 3.2.3 beschrieben ist, kennt nur die Werte Unendlich und Null: Daher werden
Subgraphisomorphismen, die mit heuristischen Kosten von Unendlich verbunden sind,
nicht in die Dekomposition aufgenommen, um Speicherplatz zu sparen.
Außerdem wird Algorithmus 3.5 in der Klasse SubgraphIsomorphism realisiert. Um aus
zwei fehlerkorrigierenden Subgraphisomorphismen einen neuen zu bilden, gibt es die
Methode combine(). Diese überprüft, ob eine Kombination möglich ist, und wenn dies
der Fall ist, mit welchen Kosten ein neuer fehlerkorrigierender Subgraphisomorphismus
verbunden ist. Dazu wird intern eine Hilfsklasse EdgeMapping verwendet, die bei der
Suche von Mappings zwischen zwei Kanten genutzt wird.
49
V, E, VL, EL
SubgraphIsomorphism
–
–
–
–
–
–
–
–
costFunction : ICostFunction<V, E, VL, EL>
predecessor1 : SubgraphIsomorphism<V, E, VL, EL>
predecessor2 : SubgraphIsomorphism<V, E, VL, EL>
costs : double
heuristic : double
vertexMap : Map<V, V>
edgeMap : Map<E, E>
insertedEdges : Set<E>
+ SubgraphIsomorphism(mappingVertex : V, mappedVertex : V
costFunction : ICostFunction<V, E, VL, EL>)
+ getHeuristicAndCosts() : double
+ combine(input1 : SubgraphIsomorphism<V, E, VL, EL>,
input2 : SubgraphIsomorphism<V, E, VL, EL>, combination :
Combination<V, E, VL, EL>, mappedGraph :
Graph<V, E>) : SubgraphIsomorphism<V, E, VL, EL>
# mapEdge(outputEdge : E, inputEdge : E, mutableEdges : Set<E>) :
EdgeMapping<E>
+ compareTo(o : SubgraphIsomorphism<V, E, VL, EL>) : int
E
EdgeMapping
+ cost : double
+ map : Map.Entry<E, E>
EdgeMapping(inputEdge : E, outputEdge : E, cost : double)
Abbildung 4.12: Die Klasse SubgraphIsomorphism und die Hilfsklasse EdgeMapping
Es gibt verschiedene Klassen, die eine Kostenfunktion darstellen. Die Klasse StaticCosts
weist allen Grapheditoperationen jeweils ohne Betrachtung der Beschriftung statische
Kosten zu. Die Klassen NumberCosts und StringCosts implementieren eine Kostenfunktion, die bei der Berechnung der Kosten für die Ersetzungsoperationen von Knoten
bzw. Kanten die Beschriftungen der zu ersetzenden Knoten einbeziehen. Für zwei Knoten v1 , v2 mit relativer Distanz dv (diese ist auf Strings und Zahlen definiert, vgl. 4.2.1)
und Threshold tv bzw. für zwei Kanten e1 , e2 mit relativer Distanz de und Threshold te
gilt:
C(v1 → v2 ) = dv · tv
und
C(e1 → e2 ) = de · te .
Wir nennen diese zweite Kostenfunktion dynamisch.
50
V, E, VL, EL
«interface»
ICostFunction
+ getCosts(v1 : AbstractLabelVertex<VL>,
v2 : AbstractLabelVertex<VL>) : double
+ getCosts(e1 : AbstractLabelEdge<EL>,
e2 : AbstractLabelEdge<EL>) : double
V → StringLabelVertex,
E → StringLabelEdge,
VL → String,
«bind»
EL → String
V → NumberLabelVertex,
E → NumberLabelEdge,
VL → Double,
«bind»
EL → Double
NumberCosts
StringCosts
– edgedel : double
– edgeins : double
– vertexdel : double
– edgedel : double
– edgeins : double
– vertexdel : double
+ NumberCosts(edgedel : double,
edgeins : double,
vertexdel : double)
+ StringCosts(edgedel : double,
edgeins : double,
vertexdel : double)
V, E, VL, EL
StaticCosts
–
–
–
–
–
edgedel : double
edgeins : double
edgesub : double
vertexdel : double
vertexsub : double
+ StaticCosts(edgedel : double, edgeins : double,
edgesub : double, vertexdel : double,
vertexsub : double)
Abbildung 4.13: Klassen der Kostenfunktion
Der Algorithmus 3.3 zum Finden der fehlerkorrigierenden Subgraphisomorphismen wird
wie bereits angedeutet in der Methode matchGraph() der Klasse NSG umgesetzt. Zu
Anfang werden mittels vertexMatching() (Zeile 2) die ersten fehlerkorrigierenden Subgraphisomorphismen konstruiert. Anschließend wird aus der Decomposition jeweils die
Combination gesucht, deren Kosten minimal verglichen mit allen anderen und nicht hö-
51
her als der vorgegebene Schwellwert sind (Zeile 3). Der dazugehörige SubgraphIsomorphism wird aus der open-Liste entfernt und in die close-Liste eingefügt. Weil die Dekomposition effektiv als Graph implementiert ist, finden wir die zu diesem fehlerkorrigierenden Subgraphisomorphismus kombinierbaren fehlerkorrigierenden Subgraphisomorphismen ohne Schwierigkeiten (Zeile 7). Zur Bildung der neuen fehlerkorrigierenden
Subgraphisomorphismen setzen wir dann wie oben beschrieben die Methode combine()
der Klasse SubgraphIsomorphism ein (Zeile 9).
4.5
Diskrete Relaxation
Wir implementieren den Algorithmus zur diskreten Relaxation zum Großteil in der Klasse DiscreteRelax. Vor dem Matching müssen wir für jeden Knoten aus dem Graphen
G1 ein Dictionary bestimmen. Anstatt die Dictionaries komplett zu bestimmen, wählen
wir für jeden Knoten u ∈ G1 und seiner Super-Clique alle Knoten aus dem Graph G2 ,
deren Super-Cliquen in ihrer Größe um nicht mehr als die maximale Knotendifferenz
von der Größe der ersten Super-Clique abweichen. Das Bestimmen der Dictionaries, d.h.
also der Permutationen der äußeren Knoten, geschieht erst während der Ausführung der
Relaxation. Durch die Methode pad() realisieren wir das Auffüllen der Super-Clique,
die kleiner als die andere Super-Clique ist (Zeile 4 in Algorithmus 3.6). Mit permute()
werden die äußeren Knoten der größeren Super-Clique permutiert, um alle Vergleiche
der abgebildeten Super-Clique mit dem Dictionary-Eintrag zu erhalten (Zeile 5).
Der Matchingprozess matchGraphs() setzt Algorithmus 3.7 um. Es wird damit begonnen, dass eine erste Knotenzuordnung für jeden Knoten mit initMatching() gefunden
wird. Anschließend beginnt in relax() die eigentliche Relaxation. Die einzelnen Methoden übersetzen sich dann schrittweise in den Algorithmus: findMapping() findet für
einen Knoten u ∈ V1 die beste Zuordnung v ∈ V2 und nutzt dabei testMatching(),
um für eine konkrete Zuordnung die a-posteriori Wahrscheinlichkeit P (α1 (u), α2 (v) | f )
auszurechnen. Dazu wird ein Wert P (f ) benötigt, für dessen Berechnung wir die apriori Wahrscheinlichkeiten der einzelnen abgebildeten Super-Cliquen P (Γu ) berechnen.
Das geschieht in matchedSuperCliqueProb(). Weil dazu über alle Einträge aus dem
Dictionary iteriert wird, wird der Exponentialausdruck
exp
− ke H(Γu , Sv ) + kφ ψ(Γu , Sv )
für jeden Eintrag aus dem Dictionary einzeln in der Methode simplerConditionalProbMapping() berechnet.
52
V, E, VL, EL
DiscreteRelax
+ NULLNODES : int
+ PE : double
+ PPHI : double
+ DELTA : double
+ KE : double
+ KPHI : double
– directedG1NeighborIndex : DirectedNeighborIndex<V, E>
– directedG2NeighborIndex : DirectedNeighborIndex<V, E>
– undirectedG1NeighborIndex : NeighborIndex<V, E>
– undirectedG2NeighborIndex : NeighborIndex<V, E>
– dictionaries : Map<V, Collection<List<V>>>
– probabilityFunc : IVertexProbabilities<V, E>
+ DiscreteRelax (G1 : Graph<V, E>, G2 : Graph<V, E>,
edgeClass : Class<E>)
+ matchGraphs () : GraphMapping<V, E>
# initMatching () : Map<V, V>
# relax (initMatching : Map<V, V>) : Map<V, V>
# findMapping (g1Node : V, matching : Map<V, V>) : V
# testMatching (g1CentralNode : V, matching : Map<V, V>) : double
# getSuperCliqueMatching (g1Node : V, matching : Map<V, V>) : List<V>
# conditionalProb (g1Node : V, g2Node : V) : double
# constructDictionary (g1Node : V, nullNodes : int) : Collection<List<V>>
# matchedSuperCliqueProb (smaller : Collection<List<V>>,
padded : List<V>) : double
# simplerConditionalProbMapping (matchedSuperClique : List<V>,
dictionaryEntry : List<V>) : double
# permute (node : V, nodes : List<V>, nullNodes : int) : Collection<List<V>>
# pad (permutation : List<V>, startIndex : int, nullnodes : int)
: Collection<List<V>>
Abbildung 4.14: Die Klasse DiscreteRelax
Weil die bedingte Wahrscheinlichkeit für eine Knotenzuordnung als Parameter in Algorithmus 3.7 eingeht, wird für ihre Berechnung das Interface IVertexProbabilities
genutzt, deren Implementierungen in Abbildung 4.15 dargestellt sind. Die Funktion
P (u, v) = priorProb() wird sowohl für Strings als auch für Zahlen als gleichverteilt
angenommen:
1
P (u, v) =
.
|V2 |
53
Für Strings als Knotenbeschriftungen wählen wir die Funktion P (u, v|x1u , x2v ) wie folgt:
levsim (x1u , x2v )
1
2
w∈V2 levsim (xu , xw )
P (u, v|x1u , x2v ) = P
Die in 2.2 definierte Ähnlichkeit levsim von Knotenbeschriftungen wird durch diese Vorschrift mit allen anderen beobachteten Ähnlichkeiten in Beziehung gesetzt.
Für Zahlen als Knotenbeschriftungen wählen wir die Funktion P (u, v|x1u , x2v ) dem Ansatz
aus [WH97] folgend:
1
P (u, v|x1u , x2v )
=P
2 2
v)
)
exp (−0.5 (xu −x
σ2
1
w∈V2
2 2
w)
exp (−0.5 (xu −x
)
σ2
Dabei ist σ 2 die Varianz der Verteilung der zufällig beschrifteten Knoten. Weil die Knotenbeschriftung in der hier betrachteten Anwendung einer gleichverteilten Verteilung
folgt, gilt σ 2 = (max − min)/12. Mit dieser Formel kann in der Klasse NumberProbabilities die Varianz jeder gleichverteilten Knotenbeschriftung durch Angabe von min
und max berechnet werden. Die Idee der obigen Formel ist die Differenz der Knotenbeschriftungen als normalverteilt zu interpretieren und die betrachtete Differenz von x1u zu
x2v zu allen anderen (a posteriori) beobachteten Differenzen von Knotenbeschriftungen
in Beziehung zu setzen.
V, E
«interface»
IVertexProbabilities
+ priorProb(v1 : V, v2 : V, g1 : Graph<V, E>,
g2 : Graph<V, E>) : double
+ conditionalProb(v1 : V, v2 : V, g1 : Graph<V, E>,
g2 : Graph<V, E>) : double
V → NumberLabelVertex,
E → NumberLabelEdge
V → StringLabelVertex,
E → StringLabelEdge
«bind»
«bind»
NumberProbabilities
StringProbabilities
– min : double
– max : double
Abbildung 4.15: Klassen für die Berechnung der bedingten Wahrscheinlichkeit einer Knotenzuordnung
54
4.6
SMKernel
VL, EL
«interface»
IKernel
+ vertexKernel(v1 : AbstractLabelVertex<VL>,
v2 : AbstractLabelVertex<VL>) : double
+ edgeKernel(e1 : AbstractLabelEdge<EL>,
e2 : AbstractLabelEdge<EL>) : double
«bind»
VL → Double EL → Double
RBFKernelFunc
VL, EL
DiracKernel
– gamma : double
– CEdge : double
– DEdge : double
+ RBFKernelFunc(gamma : double)
– RBF(x : double, y : double) : double
+ useCEdges(use : boolean) : void
+ useDEdges(use : boolean) : void
«bind»
VL → String EL → String
StringKernelFunc
– kernel : StringKernel
+ StringKernelFunc(minSequence : int, maxSequence : int)
– init(minSequence : int, maxSequence : int) : void
– kernel(label1 : String, label2 : String) : double
Abbildung 4.16: Verschiedene Kernel für Knoten und Kanten
Wir implementieren verschiedene Kernel für Knoten und Kanten. Der einfachste Kernel
ist in der Klasse DiracKernel implementiert (vgl. Abschnitt 2.4.1): Wenn die Beschriftungen der Knoten bzw. Kanten gleich sind (nicht nur ähnlich), so ist der Wert des
Kernels 1, sonst 0. Durch die Funktionen useCEdges() bzw. useDEdges() kann die
Evaluation von c- und d-Kanten beeinflusst werden. Falls die Graphen G1 , G2 , die den
Produktgraph bilden, selbst nur sehr wenige Kanten besitzen, entsteht auch ein Produktgraph mit wenigen Kanten, wenn d-Kanten zu 0 evaluieren. Um eine Intuition dafür zu
erhalten, betrachten wir zwei Knoten des Produktgraphen v1P , v2P ∈ GP , die aus den
Knoten v11 , v21 ∈ G1 und v12 , v22 ∈ G2 „entstanden“ sind, d.h.
αP (v1P ) = KV (v11 , v12 ) und αP (v2P ) = KV (v21 , v22 ).
55
/ E2 , so wie
/ E1 und (v12 , v22 ) ∈
In diesem Fall existieren vielfach keine Kanten (v11 , v21 ) ∈
wir angenommen hatten. Im Produktgraph treten dann aber an dieser Stelle d-Kanten
zwischen v1P und v2P auf. Wenn im gewählten Dirac-Kernel d-Kanten zu 0 evaluieren, so
gibt es wenige Kanten im Produktgraph, was die Aufzählung der Cliquen beschleunigen
kann.
Die Klasse StringKernelFunc benutzt das Software-Paket Weka, um für zwei Strings
den Subsequence String Kernel zu berechnen. Es fließen nur gemeinsame Substrings der
Länge l ∈ [min, max] in die Berechnung dieses Kernels ein. Ein weiterer Kernel für
reelle Zahlen ist der sogenannte Radial Basis Function Kernel, der in RBFKernelFunc
implementiert ist. Er ist für einen Parameter γ ∈ [0, 1] zwischen zwei Zahlen x, y ∈ R
definiert durch
kRBF (x, y) = exp{−γ ||x − y||2 }.
smkernel
V, E, VL, EL
V
VertexPair
0...∗ 1
SMKernel
Abbildung 4.17: Klassen im Package smkernel
Die erste Aufgabe in der Implementierung des Algorithmus 3.8 für den Subgraph Matching Kernel ist die Erstellung des gewichteten Produktgraphs von zwei Graphen. Dessen Knoten sind Paare von Knoten, die während der Erstellung durch die Hilfsklasse
VertexPair repräsentiert sind.
In der Klasse SMKernel wird der Kernel
V
berechnet. Der Algorithmus untersucht im
Wesentlichen rekursiv alle Cliquen des
VertexPair
Produktgraphs und wird in der Methode smKernel() umgesetzt, die genau der
+ v1 : V
+ v2 : V
Funktion aus Zeile 8 in Algorithmus 3.8
entspricht. Durch die Attribute depth und
+ VertexPair(v1 : V, v2 : V)
deepest wird der vorzeitige Abbruch der
Rekursion umgesetzt, sobald eine maxiAbbildung 4.18: Die Klasse VertexPair
male Größe der Clique des Produktgraphs
erreicht wird (Zeile 9). Die Kernel k(G1 , G1 ) und k(G2 , G2 ) werden durch die Attribute
xxKernel bzw. yyKernel berechnet; mit ihnen wird der Kernel k(G1 , G2 ) normalisiert.
56
V, E, VL, EL
SMKernel
– productGraph : Graph<NumberLabelVertex, NumberLabelEdge>
– neighborIndex : NeighborIndex<NumberLabelVertex, NumberLabelEdge>
– directNeighborIndex : DirectedNeighborIndex<NumberLabelVertex,
NumberLabelEdge>
– weight : double
– kernelFunction : IKernel<VL, EL>
– depth : int
– deepest : int
– xxKernel : SMKernel<V, E, VL, EL>
– yyKernel : SMKernel<V, E, VL, EL>
+ SMKernel (G1 : Graph<V, E>, G2 : Graph<V, E>, edgeClass : Class<E>,
deepest : int, normalize : boolean)
+ matchGraphs() : GraphMapping<V, E>
# smKernel (localWeight : double, clique : Set<NumberLabelVertex>,
candidates : Set<NumberLabelVertex>) : void
# createProductGraph (g1 : Graph<V, E>, g2 : Graph<V, E>) :
Graph<NumberLabelVertex, NumberLabelEdge>
# getProductGraph() : Graph<NumberLabelVertex, NumberLabelEdge>
# getWeight() : double
– getNeighbors(vertex : NumberLabelVertex, prodGraph :
Graph<NumberLabelVertex, NumberLabelEdge>) :
Set<NumberLabelVertex>
57
Kapitel 5
Evaluation
FIn diesem Abschnitt sollen die in den vorherigen Abschnitten vorgestellten Algorithmen miteinander verglichen werden. Zunächst betrachten wir die Leistungsfähigkeit der
Algorithmen, wenn diese auf synthetischen Daten eingesetzt werden. In einem zweiten
Schritt sollen die Algorithmen auf realen Daten aus einer Bibliotheksdatenbank eingesetzt werden mit dem Ziel, Duplikate in dieser zu finden. Während der zweite Versuch
mit den realen Daten eher dazu dienen soll, die qualitativen Resultate der Algorithmen
zu untersuchen, wird mit dem Versuch an den synthetischen Daten eher auf die Laufzeit
der Algorithmen hin untersucht. Weil für die synthtetischen Daten allerdings bekannt ist,
welche Subgraphisomorphismen gefunden werden können, werden in diesem Abschnitt
auch Aussagen über ihre qualitative Leistungsstärke getroffen.
Für die Versuche wird ein Rechner des Fachgebiets für Datenbanken und Informationssysteme benutzt. Dieser besitzt einen Intel Xeon E3-1276V3 4-Kern-Prozessor mit 3,6
GHz, 8 virtuellen Kernen und 32 GB Arbeitsspeicher.
5.1
Synthetische Graphen
Für einen ersten Vergleich der Laufzeiten benutzen wir die synthetisch erzeugten attributierten Graphen aus [HBA13]. Es handelt sich um 180 Graphpaare (G1 , G2 ), die sich
in ihrer Knotenanzahl und der Wahrscheinlichkeit p für eine gerichtete Kante zwischen
zwei Knoten unterscheiden. Knoten und Kanten sind gemäß einer gleichförmigen Verteilung mit reellen Ziffern aus dem Bereich [−100, 100] beschriftet. Die Graphpaare werden erzeugt, indem zuerst ein Pattern-Graph G1 entsprechend vorgegebener Knotenzahl
und Wahrscheinlichkeit p hergestellt wird und dieser zur Erzeugung vom sogenannten
Target-Graph G2 um weitere Knoten und Kanten erweitert wird. Die dabei entstehenden
Subgraphen G1 sind im Allgemeinen nicht knoten-induziert durch G2 . Folgende Para-
58
meter sind für die Größe von G1 , die Größe von G2 und die Wahrscheinlichkeit p einer
Kante zwischen zwei Knoten möglich:
1. |V1 | ∈ {10, 25, 50}
2. |V2 | ∈ {50, 100, 250, 500}
3. p ∈ {0.01, 0.05, 0.1}
Zu jeder Kombination existieren 5 Graphpaare.
5.1.1
VF2
Damit der Algorithmus VF2 auf den gegebenen Graphpaaren funktioniert, werden diese
vor der Ausführung so verändert, dass der Graph G1 einen knoten-induzierten Subgraph
von Graph G2 darstellt. Für die Ähnlichkeitsfunktion, die zur Auswertung von Regel
R1 in Bezug auf Knoten v1 ∈ G1 , v2 ∈ G2 bzw. Kanten e1 ∈ G1 , e2 ∈ G2 genutzt wird,
wählen wir den Schwellwert tv = te = 2, d.h.
v1 ≈ v2 ⇔ |α1 (v1 ) − α2 (v2 )| ≤ tv = 2
e1 ≈ e2 ⇔ |β1 (e1 ) − β2 (e2 )| ≤ te = 2
Mit diesen Werten benötigt der Algorithmus pro Graph durchschnittlich 7.6 s bei einer Standardabweichung von 95 s. Bei Betrachtung der einzelnen Werte fällt auf, dass
der Algorithmus nur bei einigen wenigen Graphen eine sehr viel längere Laufzeit aufweist als bei den anderen. Diese wenigen Graphen zeichnen sich alle durch eine geringe
Kantenwahrscheinlichkeit (p = 0.01) aus. Zudem ist die Ordnung der Knoten, die der
Algorithmus zur systematischen Untersuchnung benutzt, gerade so, dass die ersten Knoten von Graph G1 im richtigen Matching zu Knoten aus G2 zugeordnet werden müssen,
die in der Ordnung sehr weit hinten stehen. Bevor also die ersten richtigen Zuordnungen
feststehen, müssen viele weitere Kombinationen probiert werden. Diese Beobachtungen
deuten darauf hin, dass sich für den Algorithmus bei Graphen mit wenigen Kanten im
Vergleich zur Knotenanzahl ein sehr großer Suchraum ergibt, in dem die Information
über die Richtigkeit eines einzelnen Knotenmatchings unter Umständen erst sehr viel
später im weiteren Verlauf des Matchingsprozesses erkannt werden kann.
Kantenwahrscheinlichkeit
0.01
0.05
0.1
„falsche“ Knotenzuordnungen für tv = 2
502
42
11
„falsche“ Knotenzuordnungen für tv = 1
360
33
8
Tabelle 5.1: „Falsche“ Knotenzuordnungen bei unterschiedlichen Schwellwerten tv und
te = 2
59
Eine weitere Beobachtung ist, dass der Algorithmus mit dem obigen Schwellwert 2 viele Matchings ausgibt, in denen nicht der exakte Pattern-Graph wiedergefunden wurde,
sondern eine Knotenzuordnung, die nach dem Kriterium der oben definierten Knotenund Kantenähnlichkeit als richtig anzusehen ist. In Tabelle 5.1 sehen wir, dass mit zunehmender Kantenwahrscheinlichkeit p weniger „falsche“ Knotenzuordnungen gefunden
werden. Ein Grund dafür könnte sein, dass durch mehr Kanten zwischen den Knoten
im Pattern-Graph Knotenzuordnungen ausgeschlossen werden können, weil diese nicht
die notwendigen Nachbarknoten besitzen. Wenn wir aber den Schwellwert tv senken, so
können wir auf diese Situation einwirken und von vornherein Knoten als verschieden
ausschließen. Es sei hier angemerkt, dass der Algorithmus mit einem Schwellwert von
tv = te = 0 anstatt 2 ausschließlich „richtige“ Matchings findet.
Laufzeit [ms]
3
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
2
1
0
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.1: Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph
In Abbildung 5.1 werden nur die Graphen mit Kantenwahrscheinlichkeiten von p ∈
{0.05, 0.1} betrachtet, um die theoretische Laufzeitkomplexität zu untersuchen. Aus diesem Grund sind die Werte auch nicht mehr in der Nähe des oben angegebenen Mittelwertes von 7.6 s. Wir erkennen, dass sowohl mit zunehmender Größe des Target-Graphs
als auch mit zunehmender Größe des Pattern-Graphs die Laufzeit ansteigt. Da aus der
theoretischen Überlegung folgt, dass die Laufzeit bei zunehmender Graphgröße exponentiell ansteigt, ist eine exponentielle Trendlinie für den Pattern-Graph mit 50 Knoten
eingezeichnet.
5.1.2
Fehlerkorrigierende Subgraphisomorphismen
Die Menge B an Graphen als Eingabe für den Algorithmus besteht für jeden Durchlauf
aus dem Pattern-Graph G2 . Dieser wird in einem ersten Schritt in die Dekomposition überführt, was in der Zeitmessung berücksichtigt ist. Zudem wird als Eingabe in den
60
Algorithmus eine Kostenfunktion der Grapheditoperationen und eine Heuristik, die Kosten schätzt, übergeben. In Versuchen stellt sich heraus, dass der Algorithmus wegen der
Optimalität der gelieferten Ergebnisse sehr viel Hauptspeicher benötigt, um alle möglichen Grapheditieroperationen miteinander kombinieren zu können. Bei der Definition
der Heuristik halten wir uns an die Beschreibungen aus 3.2.3 und definieren diese für
einen fehlerkorrigierenden Subgraphisomorphismus S = (∆, S∆ ):
h(S) =

0
falls für alle (v1 → v2 ) ∈ ∆ gilt: |α1 (v1 ) − α2 (v2 )| ≤ 1
∞ sonst
Das heißt, dass nur solche Knotenersetzungen überhaupt betrachtet werden sollen, bei
denen die Beschriftungen nicht mehr als um Wert 1 verschieden sind.
Weitere Versuche haben den Einfluss der Kostenfunktion gezeigt: Wenn wir alle Grapheditieroperationen mit dem gleichen Gewicht bewerten, können wir bei einzelnen Graphen nicht den kostengünstigsten fehlerkorrigierenden Subgraphisomorphismus finden,
weil die Suche danach mehr als 28 GB Hauptspeicher benötigt. Aus diesem Grund wird
hier eine statische Kostenfunktion gewählt, bei der wir die Operationen auf Kanten mit
dem Wert 1 gewichten und Operationen auf Knoten (d.h. Umbenennung und Löschung)
mit dem Wert 60 gewichten. Damit drücken wir also vereinfacht gesagt aus, dass in
dieser Anwendung jede Grapheditierung der Kanten ausprobiert werden soll, während
eine Grapheditierung der Knoten eher unwahrscheinlich ist. In die Kostenfunktion fließt
damit das Wissen ein, das wir über die Anwendung haben: dass wir nämlich die Beschriftungen des Pattern-Graphs genau so im Target-Graphen wiederfinden.
Laufzeit [ms]
104
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
103
102
101
100
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.2: Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph
Auch in Abbildung 5.2 erkennen wir den Unterschied zwischen verschiedenen Graphgrößen sowohl von Pattern- als auch von Target-Graph. Die exponentielle Trendlinie deutet
die zunehmende Laufzeit an, die theoretisch zu erwarten ist.
61
Grapheditkosten als Ähnlichkeitsmaß
Es stellt sich die Frage, ob es möglich ist, aus einer Menge von Graphen den Graph zu
finden, der am ähnlichsten zu einem vorgegebenen ist. Als Ähnlichkeitsmaß bieten sich
in diesem Zusammenhang die Grapheditkosten an. Wir geben also einen Pattern-Graph
an und führen für jeden Target-Graph die Suche nach einem fehlerkorrigierenden Subgraphisomorphismus durch. Anschließend berechnen wir die relativen Grapheditkosten,
d.h. wir dividieren die jeweils errechneten Kosten, die sich zwischen dem Target- und
dem Pattern-Graph ergeben, durch die Kosten, die sich zwischen dem Pattern-Graph
und dem „richtigen“ Target-Graph ergeben. Die relativen Grapheditkosten sind also
größer als 100%, weil die Grapheditkosten zwischen Pattern-Graph und dem „richtigen“
Target-Graph minimal sind.
Relative Grapheditkosten
In Abbildung 5.3 ist das Ergebnis zu sehen, wenn wir die Durchschnittswerte der relativen Grapheditkosten für fünf Pattern-Graphen mit |V1 | = 10, |V2 | = 50, p = 0.1 berechnen. Es werden dynamische Kosten für Knoten und Kanten eingesetzt, die Heuristik
ist die gleiche, die oben bereits beschrieben wurde. Mit zunehmender Größe der TargetGraphen werden die Kosten geringer. Dies ist damit zu begründen, dass mehr Knoten
in den Target-Graphen vorkommen und damit die Wahrscheinlichkeit erhöht wird, dass
deren Beschriftung betragsmäßig nahe an den durch den Pattern-Graph vorgegebenen
Knoten liegt. Bei den Kantenwahrscheinlichkeiten verhält es sich andersherum: Durch
eine hohe Kantenwahrscheinlichkeit exisitieren eher viele Kanten, die entfernt werden
müssen, was die Kosten erhöht.
p = 0.1
p = 0.05
p = 0.01
2.8
2.6
2.4
2.2
2
1.8
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.3: Relative Grapheditkosten bei verschiedenen Größen von Pattern- und
Target-Graph
Insgesamt können wir festhalten, dass sich die Grapheditkosten als ein Ähnlichkeitsmaß
eignen, weil die durchschnittlichen Grapheditkosten 280% bis 180% über den günstigsten
62
Grapheditkosten für den (fast) exakten Subgraphisomorphismus liegen. Die Grapheditkosten werden im Mittel für ein Paar aus Pattern- und Target-Graph in rund 1, 5s
berechnet.
5.1.3
Diskrete Relaxation
Ein wesentlicher Teil der Berechnung des Graph Matchings bei der diskreten Relaxation
ist die Berechnung der sogenannten Dictionaries Θu , d.h. der Permutationen von SuperCliquen Sv um Knoten v ∈ G2 , auf die eine Super-Clique Cu um den Knoten u ∈ G1
abgebildet werden kann. Wir nehmen in das Dictionary nur Super-Cliquen auf, die nicht
mehr als maximal 5 Knoten verschieden groß sind:
|Sv | − |Cu | ≤5
(Rel 1)
Die maximale Schrittzahl I ist als Parameter des Algorithmus auf 14 gesetzt.
Wie bereits in Abschnitt 3.3 erwähnt, wird der Parameter Pφ , der die Wahrscheinlichkeit
für strukturelle Unterschiede beschreibt, vor allem aus formalen Gründen eingeführt. In
dem hier vorgestellten Experiment zeigt sich, dass bei den von uns betrachteten Daten
mit einem Wert von Pφ = 0.5 die meisten richtigen Knotenzuordnungen erfolgen.
Im Folgenden sollen nur die Graphen mit Kantenwahrscheinlichkeit p = 0.01 betrachtet
werden, weil die Bildung der Permutationen der in den Dictionaries enthaltenen SuperCliquen sehr zeitaufwendig ist. Für Knotenwahrscheinlichkeiten p ∈ {0.05, 0.1} müssen
zum Beispiel Permutationen von 11 Knoten errechnet werden, was 11! ≈ 40 Millionen
Mögichkeiten entspricht.
Laufzeit [ms]
105
104
103
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
2
10
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.4: Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph
In Abbildung 5.4 erkennen wir das bereits bei den vorherigen Algorithmen beobachtete
63
Muster, dass die Laufzeit bei ansteigender Graphgröße wächst. Es ist eine exponentielle
Trendlinie für die Pattern-Graphen der Größe 50 eingezeichnet. Wir können außerdem
beobachten, dass der Algorithmus in den 25 Fällen nach zwei Schritten, in den verbleibenden 35 Fällen nach drei Schritten konvergiert.
Richtige Knotenzuordnungen
(korrigiert)
Es stellt sich die Frage, ob durch die diskrete Relaxation die richtigen Subgraphisomorphismen gefunden werden. Wir stellen zunächst fest, dass die Einschränkung der
Dictionaries in (Rel 1) dazu führt, dass gerade bei den Target-Graphen der Größe 50
die Super-Cliquen Sv um den Knoten v ∈ G2 , auf den Knoten u ∈ G1 richtigerweise abgebildet werden müssen, nicht in das Dictionary Θu aufgenommen werden. Wenn aber
ein größerer Wert als 5 für die Differenz der Knotenanzahlen gewählt wird, wird die
Berechnung der Permutationen zeitlich wieder „zu aufwendig“.
0.6
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
0.5
0.4
0.3
0.2
0.1
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.5: Richtige Knotenzuordnungen bei verschiedenen Größen von Pattern- und
Target-Graph
In Abbildung 5.5 ist die Gesamtheit der Knotenzuordnung insofern korrigiert, als nur die
Knotenzuordnungen berücksichtigt sind, die durch die Vorgabe aus (Rel 1) durch den
Algorithmus überhaupt erkannt werden können. Mit zunehmender Größe des TargetGraphen werden immer weniger richtige Zuordnungen gefunden. Werden alle falschen
Knotenzuordnungen betrachtet, die eigentlich auffindbar wären, so weicht die Zahl, mit
der der gefundene Knoten v ∈ G2 bechriftet ist, von der Zahl, mit der der vorgegebene Knoten u ∈ G1 beschriftet ist, d.h. also |α1 (u) − α2 (v)|, im arithmetischen Mittel
um 2.7 von dieser ab. Der Algorithmus findet also grundsätzlich nicht völlig abwegige
Knotenzuordnungen, wenn nur die Bechriftung der Knoten betrachtet wird.
Bei 50% der findbaren, aber falsch zugeordneten Knoten ist die Super-Clique des Knotens
u ∈ G1 im Pattern-Graph von der Größe 0 und der zuzuordnende Knoten v ∈ G2
im Target-Graph besitzt eine Clique mit einer größeren Super-Clique. Dagegen besitzt
64
der zugeordnete Knoten v 0 ∈ G2 aus dem Target-Graph ebenfalls eine Super-Clique
der Größe 0. Wir erkennen in diesen Fällen, dass der Algorithmus hier die relationale
Information, dass die Super-Cliquen um u bzw. v für eine Zuordnung zu verschieden
sind, nutzt und eine Zuordnung ausschließt. Stattdessen werden diese Knoten einem
anderen Knoten v 0 zugeordnet.
Höhere Kantenwahrscheinlichkeiten
Weil bisher nur die Graphen mit Kantenwahrscheinlichkeit p = 0.01 betrachtet wurden,
sollen die Experimente nun auf einige ausgewählte Kombinationen von Graphen mit höheren Kantenwahrscheinlichkeiten ausgeweitet, um das eben erläuterte Ergebnis näher
zu untersuchen. Insbesondere soll überprüft werden, ob der Algorithmus bei mehr verfügbarer relationaler Information durch die höhere Kantenwahrscheinlichkeit mehr richtige
Knotenzuordnungen findet. Dabei betrachten wir nur Kombinationen, in denen keine
Super-Cliquen mit mehr als 10 Knoten berechnet werden müssen. Weil nun zu betrachtende Super-Cliquen größer sind, erhöht sich auch die Laufzeit des Algorithmus: Zum
Beispiel dauert es bei p = 0.1 für Pattern-Graphen der Größe 10 und Target-Graphen
der Größe 50 im Durchschnitt 941ms, wohingegen es bei p = 0.01 nur 30ms dauert.
p = 0.1
Pattern-Graph 25
Pattern-Graph 10
Richtige Knotenzuordnungen
(korrigiert)
0.6
0.5
p = 0.05
Pattern-Graph 25
Pattern-Graph 10
0.4
p = 0.01
Pattern-Graph 25
Pattern-Graph 10
0.3
0.2
40
50
60
70
80
90
100 110
Anzahl der Knoten des Target-Graphen
Abbildung 5.6: Richtige Knotenzuordnungen bei verschiedenen Größen von Pattern- und
Target-Graph für höhere Kantenwahrscheinlichkeiten
In Abbildung 5.6 ist die relative Anzahl richtig zugeordneter Knoten für verschiedene
Kantenwahrscheinlichkeiten zu sehen. Für den Target-Graphen der Größe 100 liegt das
Ergebnis, das sich für die Graphen mit p = 0.01 und p = 0.05 bildet, in einem Bereich
65
von 30−40%. Bei dem Target-Graphen der Größe 50 ist eine höhere Streuung der relativ
richtigen Knotenzuordnungen auszumachen. Auffällig ist zudem, dass für p = 0.05 bei
einem Pattern-Graph der Größe 10 die Anzahl richtiger Knotenzuordnungen zunimmt.
Wir können zusammenfassend aber festhalten, dass höhere Kantenwahrscheinlichkeiten
eher keine Verbesserung der erzielten Ergebnisse ermöglichen.
Auch bei den Graphen höherer Kantenwahrscheinlichkeit ist bei den auffindbaren Knotenzuordnungen auffällig, dass 50% der Knoten, die falsch zugeordnet werden, SuperCliquen der Größe 0 besitzen. Von den richtig zugeordneten Knotenzuordnungen besitzen
nur 25% der Knoten Super-Cliquen der Größe 0. Eine Super-Clique der Größe 0 beeinträchtigt also den Algorithmus, weil keine relationale Information außer der, dass der
Knoten keine Super-Clique besitzt, benutzt werden kann.
5.1.4
SMKernel
Die Berechnung des Graph Kernels hängt wesentlich von den Kerneln für Knoten und
Kanten ab. Insbesondere entstehen mit Kerneln auf Kanten, die hauptsächlich Werte > 0
liefern, Produktgraphen, die sehr dicht sind und folglich viele Cliquen enthalten. Deren
Aufzählung dauert sehr lange, sodass wir uns hier auf den Dirac-Kernel für Kanten
beschränken und diesen so modifizieren, dass d-Kanten zu 0 evaluieren. Auch für die
Knoten benutzen wir einen Dirac-Kernel:

1
falls α1 (v1 ) = α2 (v2 )
KV =
0 sonst
KE =

1
0
falls e1 ∈ E1 ∧ e2 ∈ E2 ∧ β1 (e1 ) = β2 (e2 )
sonst
Wir berechnen den normalisierten Graph-Kernel ohne Einschränkung der maximalen
Cliquen-Größe, d.h.
k(G1 , G2 )
e
k(G
1 , G2 ) = q
k(G1 , G1 ) k(G2 , G2 )
66
250
Laufzeit [ms]
200
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
150
100
50
0
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.7: Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph
In Abbildung 5.7 sehen wir, dass die Laufzeit für die Berechnung des Kernels mit zunehmender Größe des Target-Graphen steigt. Die Größe des Pattern-Graphen hingegen
spielt für die Laufzeit eine untergeordnete Rolle. Die Beobachtung, dass die Laufzeit
im Wesentlichen von der Größe des Target-Graphen abhängt, kann durch eine weitere
Zahl bekräftigt werden: Insgesamt 99% der durchschnittlichen Laufzeit wird für die Berechnung des Kernels k(G2 , G2 ) verwendet. Die Berechnung dieses Kernels ist für große
Graphen der entscheidende Faktor in der Zusammensetzung der Laufzeitkomponenten.
Es stellt sich die Frage, wie aussagekräftig der berechnete Kernelwert ist. Dazu tragen
wir für die verschiedenen Größen der Target-Graphen die Kernelwerte bei verschiedenen
Größen der Pattern-Graphen in ein Diagramm ein. Wenn wir zunächst die Grapheditkosten in Abbildung 5.8 vernachlässigen, erkennen wir, dass mit zunehmender Größe
der Target-Graphen bei allen Pattern-Graphen der Kernelwert abnimmt. Diese Daten
deuten darauf hin, dass der Kernelwert kein guter Indikator für die Güte des gefundenen
Subgraphisomorphismus ist.
67
120
0.8
e
Kernel k(G
1 , G2 )
100
80
0.6
60
0.4
40
20
0.2
0
0
durchschnittliche Graphedit-Kosten
Grapheditkosten
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
Kernel
Pattern-Graph 50
Pattern-Graph 25
Pattern-Graph 10
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
e
Abbildung 5.8: Vergleich von Kernelwerten k(G
1 , G2 ) und Grapheditkosten
Um die Hypothese zu überprüfen, dass aus den Kernelwerten keine Rückschlüsse gewonnen werden können, wie „gut“ ein Subgraphisomorphismus zwischen den Graphen
ist, tragen wir außerdem die in Abschnitt 5.1.2 berechneten Grapheditkosten in das
Diagramm ein. Während diese unabhängig von der Größe des Target-Graphen für je
eine Größe des Pattern-Graphen annähernd konstant bleiben, nimmt der Kernel für
zunehmende Größen ab. Der Kernelwert lässt sich nicht (zumindest nicht so intuitiv)
wie die Grapheditkosten als Distanzmaß zwischen dem perfekten und dem gefundenen
fehlerkorrigierten Subgraphisomorphismus interpretieren.
Graph Kernel als Ähnlichkeitsmaß
Wie schon bei den fehlerkorrigierenden Subgraphisomorphismen untersuchen wir nun, ob
es möglich ist, aus einer Menge von Graphen den Graph zu finden, der am ähnlichsten zu
einem vorgegebenen ist. Der Graph Kernel soll als Ähnlichkeitsmaß verwendet werden.
Der normalisierte Graph Kernel wird für den ersten Pattern-Graph mit |V1 | = 10 und
p = 0.1 als G1 und alle Target-Graphen jeweils als G2 berechnet. Als Kernel auf den
Knoten benutzen wir einen RBF-Kernel mit γ = 0.5 (siehe dazu 4.6), auf den Kanten
benutzen wir einen Dirac-Kernel. Wir beschränken die Cliquen-Größe nicht. Nach der
68
Berechnung dividieren wir den normalisierten Graph Kernel durch den normalisierten
Graph Kernel, der sich zwischen Pattern- und „richtigem“ Target-Graphen ergibt. Wir
sprechen vom relativen Graph Kernel, weil die sich daraus ergebenden Werte also kleiner
als 100% sind, da der Graph Kernel mit diesem „richtigen“ Target-Graphen maximal
ist.
Relativer Graph Kernel
0.6
p = 0.1
p = 0.05
p = 0.01
0.55
0.5
0.45
0.4
100
200
300
400
500
Anzahl der Knoten des Target-Graphen
Abbildung 5.9: Relative Graph Kernel bei verschiedenen Größen von Pattern- und
Target-Graph
In Abbildung 5.9 erkennen wir, dass sich die Werte des relativen Graph Kernels zwischen
40% und 60% bewegen. Das heißt, dass selbst sehr große Werte für den Graph Kernel
nur etwa 60% der Ähnlichkeit anzeigen, die zwischen Pattern- und „richtigem“ TargetGraph erreicht wird. Ein systematicher Einfluss der Kantenwahrscheinlichkeit ist nicht
zu erkennen. Allerdings kann davon gesprochen werden, dass größere Target-Graphen
eine höhere Ähnlichkeit zu dem Pattern-Graphen besitzen als kleinere Target-Graphen.
Von diesen Ergebnissen ausgehend könnte man den Graph Kernel für geeignet halten,
den ähnlichsten Graph aus einer Menge zu bestimmen.
Allerdings können die Ergebnisse im Gegensatz zu den fehlerkorrigierenden Subgraphisomorphismen nur unter einem sehr viel höheren Zeitaufwand bestimmt werden: Durchschnittlich dauert es 31 Minuten, den normalisierten Graph Kernel auszurechnen. Dabei
wird 95% der Zeit dafür aufgewendet, den Produktgraphen zu erstellen. Das bedeutet,
dass selbst ein schneller zu berechnender Graph Kernel keinen Vorteil bringt, wenn dieser
immer noch den Produktgraph benötigt.
69
5.2
Reale Daten einer Bibliotheksdatenbank
Für einen qualitativen Vergleich der Algorithmen verwenden wir die Daten der Bibliotheksdatenbank des Fachgebiets für Datenbanken und Informationssysteme. Diese beinhaltet die Daten zu mehr als 20.000 Büchern, Zeitschriftenartikeln und anderen wissenschaftlichen Arbeiten. Ein Auschnitt ihres Schemas ist in Listing 5.1 gezeigt.
SCHRIFT (Schrift, Autor, Titel, Schrifttyp → SCHRIFTTYP)
FLIT (Schrift, ISBN, Verlag, Auflage, Instorg, Ort, Erscheinungsjahr,
Zeitschrreihe)
SCHRIFTTYP (Schrifttyp, Typ)
SCHLAGWORT (Schrift → SCHRIFT, Schlagwort)
Listing 5.1: Ausschnitt aus dem Schema der Bibliotheksdatenbank
Weil die Datenbank Duplikate enthält, d.h. Bücher, die mit verschiedenen Informationen
eingetragen sind, aber das gleiche Buch in dem Bestand der Bibliothek bezeichnen, wollen
wir mittels Graph Matching versuchen, diese zu identifizieren. Zu diesem Zweck werden
die Daten der Datenbank als Graph modelliert und die Matching-Algorithmen mit dem
Ziel angewendet, einen Subgraph, der ein Buch beschreibt, an anderer Stelle in dem
Datenbankgraph wiederzufinden und damit mögliche Duplikate zu erkennen.
Der Datenbankgraph wird erstellt, indem aus den einzelnen Schriften Graphen wie in
Abbildung 5.10 gezeigt gebildet werden: Um den Titel werden die einzelnen Attribute
als Knoten angelegt. In dem Beispiel sind manche Beschriftungen zur übersichtlicheren Darstellung mit drei Punkten abgekürzt. Diese Graphen nennen wir im Folgenden
Büchergraphen.
temporal DBS
Barbara
Studienarbeit
Implementierung
einer . . .
Kuhn
Barbara
Implementierung
einer . . .
Institut für . . .
Studienarbeit
SQL+T
Hannover
Kuhn
(a) Buch mit Inventarnummer 95
(b) Buch mit Inventarnummer 5934
Abbildung 5.10: Büchergraphen für Duplikate aus der Bibliotheksdatenbank
Schließlich werden die einzelnen Graphen in einen gemeinsamen Graphen überführt,
den wir im Folgenden als Datenbankgraph G2 bezeichnen. Wenn die einzelnen Graphen
gemeinsame Knoten (d.h. Knoten, die das gleiche beschreiben, z.B. einen Verlag oder ein
Erscheinungsjahr, und genau die gleiche Beschriftung tragen) besitzen, wird von diesen
Attributknoten im Graph G2 jeweils nur ein einziger erstellt. Ausgenommen von dieser
70
Regel sind die Attributknoten, die den Titel der Schrift bezeichnen: Für jede Schrift
wird ein Titelknoten erstellt. Im Beispiel besitzen die beiden Bücher 95 und 5934 den
Namen der Autorin und den Typ „Studienarbeit“. Die Knoten der Titel sind daher im
Datenbankgraph jeweils über eigene Kanten mit diesen Attributknoten verbunden. Ein
Beispiel dazu ist in Abbildung 5.11 dargestellt.
Implementierung einer . . .
Barbara
SQL+T
Kuhn
Studienarbeit
Implementierung einer . . .
Hannover
temporal DBS
Institut für . . .
Abbildung 5.11: Der Datenbankgraph für die Bücher 95 und 5934
Für das Graph Matching wird jeweils ein Buchgraph G1 aus dem Datenbankgraph G2
entfernt. Attributknoten, die der Graph G1 mit anderen Graphen gemeinsam hat, werden
nicht entfernt. Für den konkreten Versuch werden einige zufällig ausgewählte Einträge
aus der Datenbank und die oben gezeigten Bücher mit den Primärschlüsseln 95 und 5934
zu einem Datenbankgraph zusammengestellt.
5.2.1
VF2
Der Algorithmus VF2 wird mit dem Schwellert 0.8 für die Levenshtein-Distanz für
Knoten- und Kantenbeschriftungen eingesetzt. Anders als für die anderen Algorithmen
können wir in den hier beschriebenen Versuchen nach einem Buchgraph G1 in dem gesamten aus 20.000 Büchern bestehenden Datenbankgraph G2 suchen. Die Suche nach
jedem Buch mittels des oben beschrieben Vorgehens erfolgt in insgesamt 100 Minuten.
Bei der Suche werden 1583 Buchgraphen gefunden, die sich auf andere Subgraphen des
Datenbankgraphs abbilden lassen. Wir schildern im Folgenden einige Beobachtungen zu
den gefundenen Subgraphisomorphismen, die anhand von Stichproben gemacht werden.
Zunächst gibt es einige Abschluss- und Studienarbeiten, die am Fachgebiet für Datenbanken und Informationssysteme verfasst wurden, die als Duplikate in der Datenbank
vorhanden sind (siehe dazu das Beispiel in 5.10). Die Arbeiten sind zweifach eingetragen:
Eine Eintragung ist nur in der Relation SCHRIFT vorgenommen, die andere Eintragung
ist zusätzlich noch in der Relation FLIT verzeichnet. Insofern bildet ein Buchgraph einen
echten Teilgraph des anderen Buchgraphs und dieser ist auch als Subgraph im Datenbankgraph auffindbar. Allerdings gelingt es nicht, einen Subgraphisomorphismus von
dem zweiten umfangreicheren Buchgraph zum Datenbankgraph zu identifizieren.
71
Die zweite und wohl auch umfangreichste Gruppe von gefundenen Subgraphisomorphismen besteht aus Einträgen in die Datenbank, bei denen beide Bücher exakt gleiche
Attribute (abgesehen vom Primärschlüssel Schrift) besitzen. Es könnte sich um mehrfach angeschaffte Bücher handeln, weshalb in diesen Fällen weitere Attribute manuell
verglichen werden wie etwa die DokNr oder das Erfdatum (Erfassungsdatum), die in
dieser Modellierung vernachlässigt werden. Bei den Büchern handelt es sich laut Dokumentennummer um unterschiedliche Bücher. Bei einigen wenigen eventuellen Duplikaten
ist aber auffällig, dass die Erfassungsdaten auseinanderfallen, sodass es sich zum Beispiel um Nachbestellungen oder um doppelte Erfassungen handeln könnte. An dieser
Stelle ist also Expertenwissen über die Bibliotheksdatenbank notwendig, um beurteilen
zu können, ob die Bücher Mehrfachanschaffungen oder tatsächlich Duplikate sind.
Die dritte Gruppe, die wir identifizieren, sind Bücher, die Attribute besitzen, deren
Namen nicht exakt übereinstimmen. Hierunter fallen vor allem Bücher, die aus mehreren
Teilen bestehen, wie etwa „The Art of Computer Programming“ von Donald Knuth. Der
Algorithmus findet hier wegen der geringen Levenshtein-Distanz zwischen „Vol. 1“ und
„Vol. 2“ fälschlicherweise einen Subgraphisomorphismus.
Richtiger Attributname
Das ist Informatik
Concepts in Programming Languages
A Dynamic Framework for Object Projection Views
OOPSLA + ECOOP ’90 . . .
Universität Antwerpen
Falscher Attributname
Was ist Informatik?
Concepts of Programming Languages
A dynamic f ramework for object
projection views
OOPSLA ’90/ECOOP ’90 . . .
Universiteit Antwerpen
Tabelle 5.2: Ähnliche Knotenbeschriftungen in erkannten Subgraphisomorphismen
In Tabelle 5.2 sind gefundene Knotenbeschriftungen aufgelistet, die aus durch den Algorithmus erkannten Subgraphisomorphismen stammen. Alle diese Bücher könnten Mehrfachanschaffungen sein, die ein Mal falsch erfasst wurden. Es könnten aber auch Duplikate sein, wenn sie zum Beispiel zuerst falsch erfasst wurden, später festgestellt wurde,
dass sie noch nicht in der Datenbank enthalten sind, weil die Suche nach dem Titel
ohne Resultat blieb, und sie schließlich erneut erfasst wurden. Die weitere Analyse der
Ergebnisse des Algorithmus VF2 muss hier durch einen Experten erfolgen.
5.2.2
Fehlerkorrigierende Subgraphisomorphismen
Wie bereits gesehen ist für die Konstruktion der fehlerkorrigierenden Subgraphisomorphismen von besonders großer Bedeutung, dass mit einer „guten“ Heuristik der Suchraum stark eingeschränkt wird, sodass dessen Durchsuchen nicht zu viel Speicherplatz
benötigt. Aus diesem Grund modifizieren wir die Heuristik für einen fehlerkorrigierenden
72
Subgraphisomorphismus S = (∆, S∆ ):









0


levsim (α1 (v1 ), α2 (v2 )) ≤ 0.8,




 falls |α (v )| ≥ 4 und |α (v
1
1
2
falls für alle (v1 → v2 ) ∈ ∆ gilt: 
h(S) =

α (v ) = α2 (v2 ),


 1 1





sonst





∞ sonst
2 )|
≥4
Mit dieser Modifikation stellen wir sicher, dass kurze Strings (kürzer als 5 Zeichen) als
Knotenbeschriftungen nicht nach dem Kriterium der Levenshtein-Distanz bzw. Ähnlichkeit beurteilt werden. In den gefundenen fehlerkorrigierenden Subgraphisomorphismen
können sie nur auf identische Strings abgebildet werden. Insbesondere verhindern wir
so, dass sehr viele Ersetzungen von Knotenbeschriftungen für Jahreszahlen oder Initialen von Autoren vorgenommen werden. Durch die im weiteren Verlauf entstehenden
Kombinationsmöglichkeiten würde der Algorithmus zu viele fehlerkorrigierende Subgraphisomorphismen produzieren.
Weil wir in der Modellierung Initialen von verschiedenen Autoren unterscheiden, auch
wenn diese gleich lauten, ergibt sich ein weiteres Problem: Der Vornamenbuchstabe beispielsweise „M.“ kann in dem von uns konstruierten Datenbankgraph aus 1000 Buchgraphen 40 verschiedenen Autoren zugeordnet werden. Wenn alle möglichen Ersetzungen
ausprobiert würden, so würde ein zu großer Suchraum entstehen. Dieses Problem wird
gelöst, indem die ansonsten verwendete Modellierung geändert wird und die Attributknoten für Vor- und Nachname der Autoren zu einem Attributknoten zusammengefasst
werden.
Kuhn, Barbara
95
Kuhn, Barbara
Studienarbeit
temporal DBS
Studienarbeit
5934 SQL+T
Implementierung
einer . . .
temporal DBS
(a) Buch mit Inventarnummer 5934
SQL+T
Hannover
Institut für
Informationssysteme . . .
Hannover
Institut für
Informatik . . .
Implementierung
einer . . .
(b) Fehlerkorrigierender Subgraphisomorphismus auf Buch mit Inventarnummer
95
Abbildung 5.12: Ein fehlerkorrigierender Subgraphisomorphismus
Der Versuch wird auf einem Datenbankgraph von 1000 Buchgraphen durchgeführt. In
Abbildung 5.12 ist der fehlerkorrigierende Subgraphisomorphismus von Buch 5934 auf
den Datenbankgraph dargestellt. Es ist zu erkennen, dass der Knoten „SQL+T“ gelöscht
73
wird und der Knoten „Institut für Informatik“ ersetzt wird. Weil der Graph um das
Buch 95 nur Kanten zu zwei Knoten enthält, werden einige Kanten eingefügt: Diese sind
gestrichelt dargestellt. Wir können ersehen, dass der Algorithmus plausible Ergebnisse
liefert. Im Gegensatz zum Algorithmus VF2 ist es hier aber nicht so einfach, Duplikate
auszuschließen: Der Algorithmus findet immer einen fehlerkorrigierenden Subgraphisomorphismus. Die Kosten sind zwar intuitiv zu interpretieren, aber ohne Normierung
kann keine direkte Erkenntnis gewonnen werden, ob ein Duplikat vorliegt.
5.2.3
Diskrete Relaxation
Wie bereits in 5.1.3 ist auch in dieser Anwendung die Bildung der Permutationen der
Super-Cliquen problematisch, weil sie sehr zeitaufwendig ist. Zunächst werden aus den
20000 Buchgraphen all diejenigen herausgesucht, die aus höchstens 7 Knoten bestehen,
um Permutationen mit höchstens 6 Knoten berechnen zu müssen. Es verbleiben 4620
Graphen, die in einen Datenbankgraph überführt werden. Die Zuordnung der Attributknoten, die um den mittleren Knoten gelegen sind, wird im Wesentlichen über die Wahrscheinlichkeit P (u, v|x1u , x2v ) bestimmt, weil sie keine Super-Clique mit anderen Knoten
besitzen. Das heißt, sie werden dem Knoten mit der geringsten Levenshtein-Distanz
zugeordnet. Diese Überlegung bestätigt sich im praktischen Versuch.
Für den mittleren Knoten findet eine Relaxation statt. Auch wenn auf das Auffüllen
mit „dummy“ Knoten verzichtet wird, dauert die Relaxation für einen Buchgraphen im
Durchschnitt etwa 5 Minuten. Wir können beobachten, dass auch diesem Knoten ein
Knoten mit besonders geringer Levenshtein-Distanz zugeordnet wird. Insgesamt können
wir festhalten, dass die hier vorgenommene Modellierung für die Evaluation der diskreten Relaxation ungeeignet ist. Wir können in diesem Versuch nicht den Einfluss der
relationalen Information für die Relaxation beobachten.
5.2.4
SMKernel
Die Normalisierung des Kernels k(G1 , G2 ) stellt ein großes Problem bei der Berechnung
dar. Selbst bei der Wahl sehr restriktiver Kernelfunktionen für Knoten und Kanten auf
einem Datenbankgraph G2 für 52 Buchgraphen kann der Kernel k(G2 , G2 ), der für die
Normalisierung benötigt wird, nicht ohne erheblichen Zeitaufwand berechnet werden.
Wir wählen für den Kernel auf den Knoten einen Substring Sequence Kernel mit der
minimalen Substringlänge 5 und der maximalen Substringlänge 9, um zu verhindern,
dass kurze gemeinsame Substrings wie zum Beispiel gemeinsame Jahreszahlen im Produktgraph einen Knoten bilden. Weiter wählen wir für den Kernel auf den Kanten einen
Dirac-Kernel, bei dem die d-Kanten nicht ausgewertet werden (zur Begründung siehe
4.6). Wir setzen die maximale Cliquengröße auf 5 fest.
74
Für die Versuche bilden wir einen Datenbankgraph aus 50 zufällig ausgewählten Buchgraphen und den beiden Büchern 95 und 5934. Der entstehende Produktgraph besitzt
ungefähr 35.000 Knoten und 18.000 Kanten. Die Berechnung des für die Normalisierung
benötigten Wertes k(G2 , G2 ) dauert im Durchschnitt ungefähr 5 Minuten.
normalisierter Kernel
0.3
Buchgraphen
Buch 5934
Buch 95
0.25
0.2
0.15
0
10
20
30
40
50
Nach Kernelwert sortierte Buchgraphen
Abbildung 5.13: Die normalisierten Kernelwerte für verschiedene Buchgraphen
In Abbildung 5.13 erkennen wir, dass fast alle Kernelwerte nahe beieinander in einem
Berich von 15% − 30% liegen. Es zeigt sich, dass das Buch 95, für das der Algorithmus VF2 einen exakten Subgraphisomorphismus findet, hier nicht an erster Stelle liegt.
Stattdessen ist für das Buch 5934 der Kernelwert der größte. Dies kann daran liegen,
dass von einer Teilmenge der Knoten von Buch 5934 zu allen Knoten des Buchs 95
ein Isomorphismus existiert. Darüber hinaus besitzt das Buch 5934 viele Attribute, die
zumindest als Substring als irgendein Attributwert auch in anderen Buchgraphen auftreten. Für das Buch 95 hingegen besteht ein Subgraphisomorphismus zu dem Buch 5934,
zu anderen Buchgraphen werden allerdings keine Isomorphismen aus mehreren Knoten
mit hohen Kernelwerten gefunden. Aus diesem Grund ist der Kernelwert insgesamt „im
Mittelfeld“.
Der zweitgrößte Wert gehört zu einem technischen Report mit dem Titel „Specification
and Prototyping of a Compiler for a small Applicative Language“. Der Buchgraph ist
kein Subgraph zu einem anderen Buchgraphen. Wir können nur vermuten, warum er
einen vergleichsweise hohen Kernelwert erhalten hat. Zum einen besitzt er einen sehr
langen Titel mit einigen Schlüsselwörtern, die auch zumindest als Teilstring in anderen
Titeln zu finden sind. Dies führt dazu, dass solche anderen Titel mit diesem einen gemeinsamen Knoten im Produktgraph bilden. Zudem besitzt er Attribute, die Substrings
wie „Informatik“ oder „Universität“ besitzen, die sich auch in vielen anderen Buchgraphen wiederfinden. Dies führt dazu, dass ein relativ zu den anderen Buchgraphen hoher
Wert k(G1 , G2 ) erzeugt wird.
75
Der Buchgraph mit dem geringsten Kernelwert besitzt das Titelattribut „Proc. of the
1994 CAS Conference, Toronto, Canada“. Die Beschriftungen der Attributknoten im Datenbankgraph bieten kaum Übereinstimmungen zu diesem. Außerdem besitzt der Buchgraph lediglich zwei weitere Attribute, sodass auch in der Summation kein größerer
Kernelwert entsteht.
76
Kapitel 6
Fazit & Ausblick
In dieser Arbeit wurden vier Algorithmen zum Graph Matching auf attributierten Graphen vorgestellt, implementiert und evaluiert. Die vier Algorithmen decken ein breites
Spektrum der in diesem Bereich entwickelten Algorithmen ab. Die Ergebnisse sollen nun
zusammengefasst werden und ein Vergleich der Algorithmen trotz ihrer Unterschiedlichkeit formuliert werden.
Der Algorithmus VF2 ist als Vertreter des exakten Graph Matchings sehr schnell und
auch die Anforderungen an die Speicherkapazität sind sehr gering: Einige Arrays genügen, um die erforderlichen Informationen zu repräsentieren. Falls wenig strukturelle
Information vorhanden ist und die Schwellwerte für die Vergleiche von Knoten- und Kantenbeschriftungen nicht „eng genug“ gewählt sind, kann es zu falschen Knotenzuordnungen kommen. Außerdem sind bei Graphen mit wenigen Kanten die vorausschauenden
Regeln wenig effektiv und der Suchraum kann nicht wesentlich eingeschränkt werden.
Der Algorithmus VF2 war der einzige, der aus einem Datenbankgraph, der alle Bücher
der Bibliotheksdatenbank umfasst, Subgraphisomorphismen finden konnte. Sein Einsatz
scheint insbesondere dann geeignet, wenn von den zu matchenden Buchgraphen bekannt
ist, dass sie die gleiche Struktur besitzen, die Beschriftungen der Knoten und Kanten
aber voneinander abweichen können.
Beim Algorithmus der fehlerkorrigierenden Subgraphisomorphismen zeigte sich, dass die
Optimalität, mit der der Algorithmus einen fehlerkorrigierenden Subgraphisomorphismus findet, zu langen Laufzeiten bzw. einem hohen Speicherbedarf führt. Dieser Laufzeit
muss in einer Anwendung durch den Einsatz einer Heuristik begegnet werden, die den
Suchraum geeignet einschränkt. Die Kosten, die sich ergeben, sind direkt als Distanzmaß
zwischen zwei Graphen zu interpretieren. Wenn der ähnlichste Graph aus einer Menge
von Graphen zu einem vorgegebenen Graphen gefunden werden soll, sind die geringsten
Kosten ein eindeutiges Anzeichen für eine große Ähnlichkeit der Graphen.
Um den Algorithmus zu verbessern, könnte bei der Bildung der Dekomposition angesetzt
werden: Wenn stark zusammenhängende Komponenten bei der Zerlegung eines hinzu-
77
zufügenden Knotens möglichst spät getrennt werden, ergibt sich für das Matching der
umgekehrte Effekt, dass die dazu gebildeten fehlerkorrigierenden Subgraphisomorphismen sehr früh im Matching-Prozess miteinander kombiniert werden. Dadurch wird die
Kombination von vermeintlich „günstigen“ Fehlerkorrekturen vermieden, deren Kosten
sonst erst in späteren Stadien erkennbar wären.
Die diskrete Relaxation hängt sehr stark von der Größe der Super-Cliquen ab: Das Bilden
der Permutation dauert bei vielen Vorgängerknoten sehr lange und ist für Anwendungen,
in denen schnelle Antworten benötigt werden, also nicht verwendbar. Die Struktur der
Modellierung der Bibliotheksdatenbank ist nicht geeignet, um sinnvolle Aussagen über
die Leistungsfähigkeit des Algorithmus zu treffen. Bei den synthetischen Algorithmen
zeigt sich, dass die Größenunterschiede der abgebildeten Super-Clique zu den Einträgen
des Dictionaries dafür sorgen, dass falsche Knotenzuordnung gewählt werden.
Wir vermuten, dass sich die diskrete Relaxation eher dazu eignet, sehr schnell zwischen
zwei ähnlich großen Graphen, die richtige Knotenzuordnung zu finden, denn gerade bei
den kleineren synthetischen Target-Graphen wurden viele richtige Knotenzuordnungen
identifiziert. Es könnte also weiterführend überprüft werden, ob sich für strukturell verschiedene, aber ähnlich große Graphen ein Geschwindigkeitsvorteil der diskreten Relaxation gegenüber der Suche nach fehlerkorrigierenden Subgraphisomorphismen ergibt.
Für die Berechnung des Graph Kernels zeigt sich, dass diese in ihrer Laufzeit sehr stark
von der Größe des größeren der beiden Graphen abhängt. Anhand der synthetischen Graphen wird deutlich, dass die Werte des normalisierten Kernels abnehmen, je mehr sich
die beiden Graphen in ihrer Größe unterscheiden, obwohl ein (quasi) exakter Subgraphisomorphismus zwischen den Graphen existiert. In der Anwendung, aus einer Menge von
Graphen denjenigen aus der Menge mit der größten Ähnlichkeit zu einem anderen Graph
zu finden, sind die Werte des Kernels zwar prinzipiell geeignet. Wegen der langwierigen
Erstellung des Produktgraphs dauert die Ausführung aber insgesamt sehr viel länger als
die Berechnung des fehlerkorrigierenden Subgraphisomorphismus. Insbesondere anhand
der Bibliotheksdatenbank können wir erkennen, dass nicht ein Subgraphisomorphismus
zu hohen Kernelwerten führt, sondern viele kleine Gemeinsamkeiten der verglichenen
Graphen. Die Ausdrucksstärke des Graph Kernels können wir also insofern bestätigen,
als er sehr viele übereinstimmende Details zwischen den beiden Graphen anzeigt.
Zusammenfassend scheint der Algorithmus VF2 das Mittel der Wahl für strukturell
übereinstimmende Graphen zu sein. Der Algorithmus der fehlerkorrigierenden Subgraphisomorphismen muss für jede Anwendung in seinen Parametern sehr genau angepasst
werden, ist dann aber ein geeigneter Kandidat, auch strukturelle Unterschiede zu überbrücken. Die diskrete Relaxation scheint eher geeignet, in Szenarien eingesetzt zu werden, wenn zwei Graphen ähnlich groß sind. In seiner hier vorgestellten Form ist die
Berechnung des Graph Kernels nicht geeignet, bei der Suche nach Ähnlichkeit zwischen
Graphen eingesetzt zu werden.
78
Abbildungsverzeichnis
3.1
Die Regeln (R2) und (R3) . . . . . . . . . . . . . . . . . . . . . . . . . .
18
3.2
Die Regeln (R4) und (R5) . . . . . . . . . . . . . . . . . . . . . . . . . .
19
3.3
Die Regel (R6) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
3.4
Dekomposition von zwei Graphen . . . . . . . . . . . . . . . . . . . . . .
23
3.5
Beispiele von Super-Cliquen und Dictionaries . . . . . . . . . . . . . . . .
31
3.6
Zwei Graphen 3.6a, 3.6b und ihr Produktgraph 3.6c . . . . . . . . . . . .
35
4.1
Wichtige Interfaces und Klassen in JGraphT . . . . . . . . . . . . . . . .
38
4.2
Klassen, die Knoten darstellen . . . . . . . . . . . . . . . . . . . . . . . .
39
4.3
Klassen, die Kanten darstellen . . . . . . . . . . . . . . . . . . . . . . . .
40
4.4
Die Klasse GraphMatcher . . . . . . . . . . . . . . . . . . . . . . . . . .
41
4.5
Klassen im Package vf2 . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
4.7
Die Klasse VF2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
4.8
Klassen im Package nsg . . . . . . . . . . . . . . . . . . . . . . . . . . .
45
4.9
Die Klasse NSG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
4.10 Die Klasse Decomposition . . . . . . . . . . . . . . . . . . . . . . . . . .
47
4.11 Die Klasse Combination . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
4.12 Die Klasse SubgraphIsomorphism und die Hilfsklasse EdgeMapping . . .
50
4.13 Klassen der Kostenfunktion . . . . . . . . . . . . . . . . . . . . . . . . .
51
4.14 Die Klasse DiscreteRelax . . . . . . . . . . . . . . . . . . . . . . . . . .
53
4.15 Klassen für die Berechnung der bedingten Wahrscheinlichkeit einer Knotenzuordnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
4.16 Verschiedene Kernel für Knoten und Kanten . . . . . . . . . . . . . . . .
55
4.17 Klassen im Package smkernel . . . . . . . . . . . . . . . . . . . . . . . .
56
4.18 Die Klasse VertexPair . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
79
5.1
Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph . .
60
5.2
Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph . .
61
5.3
Relative Grapheditkosten bei verschiedenen Größen von Pattern- und
Target-Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
5.4
Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph . .
63
5.5
Richtige Knotenzuordnungen bei verschiedenen Größen von Pattern- und
Target-Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
Richtige Knotenzuordnungen bei verschiedenen Größen von Pattern- und
Target-Graph für höhere Kantenwahrscheinlichkeiten . . . . . . . . . . .
65
5.7
Laufzeiten bei verschiedenen Größen von Pattern- und Target-Graph . .
67
5.8
e
Vergleich von Kernelwerten k(G
1 , G2 ) und Grapheditkosten . . . . . . . .
68
5.9
Relative Graph Kernel bei verschiedenen Größen von Pattern- und TargetGraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
5.10 Büchergraphen für Duplikate aus der Bibliotheksdatenbank . . . . . . . .
70
5.11 Der Datenbankgraph für die Bücher 95 und 5934 . . . . . . . . . . . . .
71
5.12 Ein fehlerkorrigierender Subgraphisomorphismus . . . . . . . . . . . . . .
73
5.13 Die normalisierten Kernelwerte für verschiedene Buchgraphen . . . . . .
75
5.6
80
Tabellenverzeichnis
5.1
5.2
„Falsche“ Knotenzuordnungen bei unterschiedlichen Schwellwerten tv und
te = 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
Ähnliche Knotenbeschriftungen in erkannten Subgraphisomorphismen . .
72
81
Literaturverzeichnis
[Bor07]
K. M. Borgwardt. Graph Kernels. In D. Wagner, Hg., Ausgezeichnete Informatikdissertationen 2007, Bd. D-8 von LNI. GI, 2007. ISBN 978-3-88579412-7, 41–50.
[BOS+ 05]
K. M. Borgwardt, C. S. Ong, S. Schönauer, S. V. N. Vishwanathan, A. J.
Smola, H. Kriegel. Protein function prediction via graph kernels. In Proceedings Thirteenth International Conference on Intelligent Systems for Molecular Biology 2005, Detroit, MI, USA, 25-29 June 2005. 2005, 47–56. URL
http://dx.doi.org/10.1093/bioinformatics/bti1007.
[CFSV04a] D. Conte, P. Foggia, C. Sansone, M. Vento. Thirty Years Of Graph Matching
In Pattern Recognition. IJPRAI, 18(3), 2004, 265–298. URL http://dx.
doi.org/10.1142/S0218001404003228.
[CFSV04b] L. P. Cordella, P. Foggia, C. Sansone, M. Vento. A (Sub)Graph Isomorphism
Algorithm for Matching Large Graphs. IEEE Trans. Pattern Anal. Mach.
Intell., 26(10), 2004, 1367–1372. URL http://doi.ieeecomputersociety.
org/10.1109/TPAMI.2004.75.
[CHM04]
C. Cortes, P. Haffner, M. Mohri. Rational Kernels: Theory and Algorithms.
Journal of Machine Learning Research, 5, 2004, 1035–
1062. URL http://www.ai.mit.edu/projects/jmlr/papers/volume5/
cortes04a/cortes04a.pdf.
[FPV14]
P. Foggia, G. Percannella, M. Vento. Graph Matching and Learning in
Pattern Recognition in the Last 10 Years. IJPRAI, 28(1), 2014. URL
http://dx.doi.org/10.1142/S0218001414500013.
[GJ79]
M. R. Garey, D. S. Johnson. Computers and Intractability: A Guide to the
Theory of NP-Completeness. W. H. Freeman, 1979. ISBN 0-7167-1044-7.
[HBA13]
P. Héroux, P. L. Bodic, S. Adam. Datasets for the Evaluation of
Substitution-Tolerant Subgraph Isomorphism. In B. Lamiroy, J. Ogier, Hg.,
Graphics Recognition. Current Trends and Challenges - 10th International
Workshop, GREC 2013, Bethlehem, PA, USA, August 20-21, 2013, Revised
82
Selected Papers, Bd. 8746 von Lecture Notes in Computer Science. Springer, 2013. ISBN 978-3-662-44853-3, 240–251. URL http://dx.doi.org/
10.1007/978-3-662-44854-0_19.
[KM12]
N. Kriege, P. Mutzel. Subgraph Matching Kernels for Attributed Graphs.
In Proceedings of the 29th International Conference on Machine Learning,
ICML 2012, Edinburgh, Scotland, UK, June 26 - July 1, 2012. icml.cc /
Omnipress, 2012. URL http://icml.cc/discuss/2012/542.html.
[KS99]
E. W. Kamen, J. K. Su. Introduction to Optimal Estimation. Springer
London, 1999. ISBN 978-1-85233-133-7, 978-1-4471-0417-9.
[Lev73]
G. Levi. A note on the derivation of maximal common subgraphs of two
directed or undirected graphs. CALCOLO, 9(4), 1973, 341–352. ISSN 00080624. URL http://dx.doi.org/10.1007/BF02575586.
[LSS+ 02]
H. Lodhi, C. Saunders, J. Shawe-Taylor, N. Cristianini, C. J. C. H. Watkins.
Text Classification using String Kernels. Journal of Machine Learning Research, 2, 2002, 419–444. URL http://www.jmlr.org/papers/v2/lodhi02a.
html.
[MB98]
B. T. Messmer, H. Bunke. A New Algorithm for Error-Tolerant Subgraph
Isomorphism Detection. IEEE Trans. Pattern Anal. Mach. Intell., 20(5),
1998, 493–504. URL http://doi.ieeecomputersociety.org/10.1109/
34.682179.
[Mes95]
B. T. Messmer. Efficient Graph Matching Algorithms for Preprocessed Model
Graphs. 1995. Aufgerufen: 04.07.2015, URL http://citeseerx.ist.psu.
edu/viewdoc/summary?doi=10.1.1.33.4206.
[MRS08]
C. D. Manning, P. Raghavan, H. Schütze. Introduction to Information Retrieval. Cambridge University Press, New York, NY, USA, 2008. ISBN
0521865719, 9780521865715.
[Mur12]
K. P. Murphy. Machine Learning: A Probabilistic Perspective. The MIT
Press, 2012. ISBN 0262018020, 9780262018029.
[SS01]
B. Schölkopf, A. J. Smola. Learning with Kernels: Support Vector Machines,
Regularization, Optimization, and Beyond. MIT Press, Cambridge, MA,
USA, 2001. ISBN 0262194759.
[WH96]
R. C. Wilson, E. R. Hancock. A Bayesian compatibility model for graph
matching. Pattern Recognition Letters, 17(3), 1996, 263–276. URL http:
//dx.doi.org/10.1016/0167-8655(95)00115-8.
[WH97]
R. C. Wilson, E. R. Hancock. Structural Matching by Discrete Relaxation.
IEEE Trans. Pattern Anal. Mach. Intell., 19(6), 1997, 634–648. URL http:
//doi.ieeecomputersociety.org/10.1109/34.601251.
83
[Wil96]
R. Wilson. Inexact Graph Matching Using Symbolic Constraints. Dissertation, University of York, 1996.
URL http://www.bmva.org/
thesis-archive/1996/1996-wilson.pdf.
84
Erklärung
Hiermit versichere ich, dass ich die vorliegende Arbeit und die zugehörige Implementierung selbstständig verfasst und dabei nur die angegebeben Quellen und Hilfsmittel
verwendet habe.
Hannover, 09.07.2015
Simon Wingert
85
Herunterladen