03.11.2012 Aufrufe

Informatik I - Institut für Informatik - Christian-Albrechts-Universität zu ...

Informatik I - Institut für Informatik - Christian-Albrechts-Universität zu ...

Informatik I - Institut für Informatik - Christian-Albrechts-Universität zu ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

Deklaration verwendet. Diese Rechenvorschrift isempty testet mittels einer verborgenen<br />

Hilfsrechenvorschrift ise, ob eine Menge leer ist. Auch die <strong>zu</strong>letzt deklarierte Rechenvorschrift<br />

elem verwendet eine Hilfsrechenvorschrift. Sie realisiert die Auswahl eines Knotens<br />

aus einer nichtleeren Menge, wie sie in (R5) <strong>für</strong> z vorausgesetzt wird, in deterministischer<br />

Weise. Es wird der kleinste in der Menge liegende Knoten abgeliefert.<br />

Im dritten Schritt haben wir nun Graphen <strong>zu</strong> implementieren. Wir stellen den vorausgesetzten<br />

Graphen g = (V, R) dar durch eine Funktion, die jedem Knoten die Menge seiner<br />

Nachfolger <strong>zu</strong>ordnet. Dies führt in ML <strong>zu</strong>r nachfolgenden Deklaration:<br />

type graph = node->nodeset;<br />

Damit wird im Prinzip jedem Knoten eine Nachfolgermenge <strong>zu</strong>geordnet. Natürlich sind wir<br />

bei dem speziellen Objekt g des Typs graph, das den vorausgesetzten Graphen g = (V, R)<br />

beschreibt, nur an den Werten von g bei Argumenten zwischen 1 und N interessiert.<br />

Aufbauend auf den Typ graph der Funktionen von den Knoten in die Knotenmengen<br />

erhalten wir auch eine äußerst einfache Realisierung der Nachfolgerfunktion succ wie folgt:<br />

fun succ (g : graph, x : node) : nodeset = g(x);<br />

Nach diesen Vorbereitungen können wir nun die obigen Rekursionen (R1) bis (R5) direkt<br />

nach ML übertragen. Wir erhalten die folgende Rechenvorschrift:<br />

fun reach (g : graph, x : node) : nodeset =<br />

let fun succs (s : nodeset) : nodeset =<br />

if isempty(s)<br />

then s<br />

else let val y : node = elem(s);<br />

in union(succ(g,y),succs(delete(s,y))) end;<br />

fun F (k : int) : nodeset =<br />

if k = 0 then insert(empty,x)<br />

else insert(succs(F(k-1)),x)<br />

in F(N-1) end;<br />

Im Vergleich <strong>zu</strong> den Funktionen reach, F und succs von oben sind in der Rechenvorschrift<br />

reach die Rechenvorschriften F und succs lokal deklariert. Durch diese Unterordnung ist<br />

es möglich, in F und succs jeweils mit einem Parameter aus<strong>zu</strong>kommen.<br />

Bei der oben angegebenen einfachen Implementierung von Mengen und Graphen durch<br />

Funktionstypen stellt sich natürlich das Problem, einen konkreten Graphen auf<strong>zu</strong>bauen<br />

und das Resultat einer Algorithmenanwendung <strong>zu</strong> visualisieren. Das erste Problem kann<br />

etwa gelöst werden durch die zwei nachfolgenden Rechenvorschriften:<br />

fun arcinsert (g : graph, x : node, y : node) : graph =<br />

fn (u : node) => if u = x then insert(succ(g,u),y)<br />

else succ(g,u);<br />

fun create (w : node list) : graph =<br />

if null(w) then fn (u : node) => empty<br />

else arcinsert(create(tl(tl(w))),hd(w),hd(tl(w)));<br />

152

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!