Allgemeine Lösungsbeschreibung

Transcription

Allgemeine Lösungsbeschreibung
Belegarbeit
Erstellung eines ProLog Programms
Christian Fischer,
Matthias Lenk,
44597 BNC
44683 BNC
Aufgabenstellung:
Erstellung eines POLOG Programms, mit dem alle nicht- repetitiven Wörter über dem
Alphabet [a,b,c] der Länge m bestimmt werden.
w = a …a ist nicht- repetitiv, wenn keine Teilsequenz xx = x …x x …x für n = 1, 2,…,m/2
1
m
in w existiert.
abcacbabcbac
nicht- repetitiv
1
n 1
n
abcbca
repetitiv
Mathematische Grundidee:
Es werden Kombinationen der vorgegebenen Länge m über dem Alphabet [a,b,c] erstellt,
indem aus einem Ausgangswort durch Anhängen von zwei „erlaubten“ Zeichen zwei neue
Wörter gebildet werden.
Dabei müssen nicht alle Kombinationen erstellt werden, sondern es genügt, wenn man
ausgehend von [a,b], Wörter erstellt. Die fehlenden Wörter werden durch Permutation von
[a,b,c] untereinander, erstellt. Ob ein Element vor oder hinter dem Wort angefügt wird, spielt
keine Rolle, da die Wörter vorwärts als auch rückwärts gelesen werden können.
Alle neu gebildeten Wörter werden auf Wiederholung der Länge 2 bis m//2 ab der ersten
Stelle im Wort geprüft.
Nach erfolgloser Prüfung (keine Übereinstimmung der Teilsequenzen), wird wieder jeweils
ein „erlaubtes“ Zeichen angehängt. Ansonsten wird das Wort verworfen.
Ist die gewünschte Stellenanzahl erreicht, liegt 1/6 der gesuchten Wörter vor. Die restlichen
Wörter werden, wie bereits erwähnt, aus den geprüften erstellt, indem die darin enthaltenen
Elemente [a,b,c] untereinander ersetzt werden. Es gibt 3! Permutationen, abzüglich der bereits
existierenden, also fünf Umwandlungen, die für jedes Element eines Wortes durchgeführt
werden müssen.
1. a -> a, b -> c, c -> b
2. b -> b, a -> c, c -> a
3. c -> c, a -> b, b -> a
4. a -> b, b -> c, c -> a
5. a -> c, c -> b, b -> a
Funktionsweise des Algorithmus:
Zur Speicherstruktur: Jedes Wort, bestehend aus [a, b, c], wird als Liste gespeichert.
Die Wörter selbst werden wiederum in einer Liste abgelegt.
Bsp.: [[a,b,c,a],[a,b,c,b],[a,c,b,a]]
1. Nach Programmstart wird automatisch die Funktion <start> aufgerufen, in der der
Anwender die Stellenanzahl eingibt. Anschließend wird eine Ausgangsliste mit den
beiden Ausgangswörtern [[a,b,a],[c,b,a]] erstellt und die Funktion <erstelle>
aufgerufen.
2. Ausgehend von der Ausgangsliste werden die möglichen Wörter der Länge i (i=4,..,m)
erstellt, indem das erste Element eines jeden Wortes gelesen und wiederum aus der
Liste mit den Elementen [a,b,c] gelöscht wird. So verbleiben nur zwei Elemente aus
dieser Liste, die jeweils an das Wort angehängt werden, wodurch zwei neue Wörter
entstehen. Dadurch wird gleich beim Erstellen vermieden, dass unnötig viele
Kombinationen erzeugt werden. Die neuen Wörter werden in einer separaten Liste
gespeichert.
3. Nachdem jeweils zwei Wörter auf die genannte Weise erstellt wurden, werden diese
der Funktion <pruefe> übergeben. Es werden immer zwei Teilsequenzen der Länge 2
bis, falls nötig, m//2, ab der ersten Position, aus dem Wort miteinander auf Gleichheit
überprüft. Die Teilsequenzen werden mittels der Funktion <hole_elem> ermittelt.
4. Ist die Ausgangsliste aus 2. komplett durchlaufen und die Wortlänge m noch nicht
erreicht, dient die separat erstellte Liste als neue Ausgangsliste…
Ist die Stellenanzahl erreicht, (STELLEN<L) schlägt fehl, wird die Speicherstruktur
vereinfacht, indem die Liste mit den Listen zu einer einzigen Liste abgeflacht wird, da
für den folgenden Schritt die Elemente aus der Liste nur noch der Reihe nach
ausgelesen werden müssen.
5. Weiter wird <subst> aufgerufen. Hier werden lediglich die restlichen Wörter durch
Permutation von [a,b,c] erstellt. Dabei wird zunächst das erste Element aus der
abgeflachten Liste entnommen (und aus dieser gelöscht) und dessen Position in der
Liste [a,b,c] ermittelt. Mittels dieser Position wird nun je ein Element aus den Listen
[b,a,c], [b,c,a], [a,c,b], [c,a,b], [c,b,a] selektiert. Die fünf Listen stellen die
Permutationen von [a,b,c] dar. Diese fünf erhaltenen Elemente werden für jeden
Durchlauf von <subst>, bis die angegebene Länge erreicht ist, zu fünf Wörtern
zusammengefügt und anschließend ausgegeben.
Dieser Schritt wird wiederholt, bis die abgeflachte Liste leer ist. – Ende
6. Programmneustart mittels <start.>.
Erläuterungen zu den Funktionen
start/0
erstelle/4
pruefe/5
hole_elem/4
subst/8
Ziel des Programms.
Liest die Stellenanzahl von der Tastatur ein, prüft anschließend, ob er
größer als drei und ein Integerwert ist.
Erstellt neue Wörter durch das Anhängen von zwei Elementen aus
[a,b,c] an bereits geprüfte Wörter.
Überprüft, ob ein Wort zwei gleiche Teilsequenzen enthält.
Erhöht, falls erforderlich, die Länge der Teilsequenzen.
Stellt mittels Backtracking die Teilsequenzen aus einem Wort
zusammen.
[Erstellt die restlichen Wörter.]
[Gibt alle Wörter aus.]
Bemerkung: Um den Algorithmus weiter zu beschleunigen, kann man
auf die Umwandlung der Listen zu Atomen
verzichten. Die
Umwandlung dient lediglich der besseren Lesbarkeit für den Nutzer.
Es wurde eine zweite Version implementiert (repetitiv_short.pl), in der
komplett auf die Erzeugung der restlichen Wörter, sowie auf die
Umwandlung zu Atomen verzichtet wurde. Hier werden nur die nicht
permutierten Listen ausgegeben.
Eingebrachte Verbesserungen:
1. Beim Erstellen der Wörter wird darauf geachtet, dass keine zwei gleichen Elemente
hintereinander angefügt werden. Das Element, das nicht verwendet werden darf, wird
der Liste der möglichen Elemente gelöscht.
2. Beim Anfügen von Elementen werden die Elemente vor dem Wort angefügt.
3. Alle Wörter beginnen beim Erstellen mit [a,b], dadurch müssen nur 1/6 der Wörter auf
diese Weise erstellt werden.
4. Als Datenstruktur werden Listen verwendet, mit denen effektiver als mit Strings
umgegangen werden kann.
5. Die Wörter werden sofort nach dem Erstellen geprüft.
6. Es werden nur die Teilsequenzen aller möglichen Längen ab der ersten Position im
Wort verglichen.
7. Die Permutation am Ende, um die restlichen Wörter zu Erstellen, wird per Selektion
realisiert, ohne zu prüfen, um welches Element es sich konkret handelt.
8. In einer zweiten Programmversion (repetitiv_short.pl), wird auf das Erstellen und
Konvertieren der restlichen Listen verzichten, was gerade bei einer höheren
Stellenanzahl sinnvoll erscheint (s. Testläufe).
Testläufe/ Vergleich:
Testsystem:
CPU:
AMD Athlon XP (Barton) 2800+
Speicher FSB:
333 MHz (1024 MB)
SWI- Prolog Version 5.4.7
Alte Programmversion
Stellenanzahl
10
11
12
13
14
15
16
17
18
Zeit1
0,06
0,14
0,43
1,38
5,30
21,49
89,77
582,96
1912,06
Zeit2
0,05
0,13
0,44
1,43
5,32
21,58
90,85
583,71
1923,02
Zeit3
0,05
0,15
0,43
1,43
5,42
21,45
90,47
580,57
1905,61
Wörter
144
204
264
342
456
618
798
1044
1392
Zeit3
0,01
0,03
0,05
0,08
0,09
0,15
0,23
0,31
0,55
0,75
1,21
1,78
2,76
3,75
5,55
8,64
13,12
29,91
70,42
169,06
Wörter
144
204
264
342
456
618
798
1044
1392
Aktuelle Programmversion (repetitiv.pl)
Stellenanzahl
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
28
30
32
Zeit1
0,01
0,01
0,05
0,06
0,09
0,12
0,21
0,33
0,56
0,72
1,18
1,81
2,78
3,99
5,61
8,80
12,87
33,61
70,64
189,25
Zeit2
0,02
0,01
0,04
0,06
0,10
0,13
0,20
0,30
0,53
0,80
1,15
1,75
2,85
3,82
5,52
8,53
13,03
29,85
70,68
169,19
Aktuelle Programmversion (repetitiv_short.pl)
Stellenanzahl
28
30
32
33
Zeit1
25,25
61,05
149,73
235,55
Zeit2
25,45
61,25
150,08
233,24
*Alle Zeitangaben in Sekunden
Zeit3
25,41
61,12
149,83
229,87
Verallgemeinerung
Das verwendete Alphabet kann problemlos durch entsprechende Ergänzungen erweitert
werden.
Letztlich kann man sagen, dass sich die Programmiersprache Prolog gut für derartige
kombinatorische Aufgabenstellungen eignet, insofern die Speicherstrukturen nicht zu
komplex werden.

Documents pareils