Sie sind auf Seite 1von 32

Kurze Beweise für Unerfüllbarkeit

Kooperation zwischen
dem Hector-Seminar und
der TU Darmstadt

Diese Arbeit wurde von Fabian Tolksdorf, Simon Kind


und Elijah Guttman im Jahr 2021/2022
in Zusammenarbeit mit der Technischen Universität Darmstadt
unter der Betreuung von Moritz Lichter ausgeführt.
INHALTSVERZEICHNIS 1

Inhaltsverzeichnis
1 Abstract 3

2 Einleitung 4
2.1 Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.1 Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.2 Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.3 Formeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.4 Konjunktive Normalform . . . . . . . . . . . . . . . . . . . . . 8
2.2.5 Erfüllbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.6 Beweis und Herleitung . . . . . . . . . . . . . . . . . . . . . . 9

3 Material und Methoden 10


3.1 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Symmetrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.4 SAT-Solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.5 Pigeonhole Principle . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4 Projektarbeit 17
4.1 Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 Ein Bericht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3 Wie findet man den kürzesten Beweis heraus? . . . . . . . . . . . . . 21
4.4 Die Umsetzung der Prinzipien im Programm . . . . . . . . . . . . . . 22
4.4.1 Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.4.2 Symmetrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.4.3 Die Erstellung der Lösungsformel . . . . . . . . . . . . . . . . 22
INHALTSVERZEICHNIS 2

4.4.4 Der Beweis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

5 Ergebnisse 24
5.1 Laufzeit des Pigeonhole Principles . . . . . . . . . . . . . . . . . . . . 24

6 Zusammenfassung, Diskussion und Ausblick 25

7 Danksagung 26

8 Quellen 27
8.1 Literatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
8.2 Internetquellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

9 Anhang 28
9.1 Fachbegriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
9.2 UML-Klassendiagramm . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1 ABSTRACT 3

1 Abstract

The task of this project was to devise a program that can find the shortest possi-
ble proof for the unsatisfiability of a formula presented in the conjunctive normal
form. This has been achieved by using several methods, for example resolution and
symmetries. These two methods are able to create all possible clauses concerning
the given formula. A single propositional formula is created using a combination
of these clauses and the knowledge of the clauses used to derive them. This single
propositional formula is given to a SAT-Solver which determines which clauses are
required for the requested proof of the empty clause. This information can be extrac-
ted via backtracking as they are not directly included in the result the SAT-Solver
provides.
2 EINLEITUNG 4

2 Einleitung

2.1 Aufgabenstellung

Das Ziel unserer Projektarbeit war, den kürzesten Beweis zu bestimmen, mit dem
man zeigen kann, dass eine aussagenlogische Formel, die in der konjunktiven Nor-
malform dargestellt ist, nicht erfüllbar ist. Das heißt, dass man keine Belegung für
die Literale finden kann, für die die Formel als Gesamtes einen positiven Wahrheits-
wert annimmt. Dies wollen wir erreichen, indem wir ein Programm schreiben. Wozu
ist das überhaupt nötig? Jeden Wert für jede Variable in eine Formel einzusetzten,
bis man eine Lösung findet, ist sehr zeitintensiv. Jede Variable hat zwei Zustände
und somit gibt es 2n verschiedene Möglichkeiten für die Werte der Variablen, wobei
n die Anzahl der Variablen ist. Bei 10 Variablen sind das beispielsweise 1024 ver-
schiedene Möglichkeiten. Dies per Hand zu machen ist sehr langwierig und selbst
ein Programm, das alle Möglichkeiten ausprobiert, wäre sehr ineffizient. Somit ergibt
sich der Bedarf nach einem Programm, das dies möglichst effizient ausführt.

2.2 Grundlagen

Eine Elementaraussage ist eine einzelne, nicht zusammengesetzte Aussage, der ein
passender Wahrheitswert, ”wahr” oder ”falsch”, zugeordnet werden kann. Ausgehend
von Elementaraussagen ordnet man in der Aussagenlogik, einem Teilgebiet der Logik,
Aussagen und Verknüpfungen derer durch Junktoren passende Wahrheitswerte zu.
Junktoren sind, innerhalb der Aussagenlogik, logische Operatoren beziehungsweise
Verknüpfungen, die Aussagen verbinden.
2 EINLEITUNG 5

2.2.1 Literale

Wir definieren ein Literal als eine Variable oder ihre Negation. Ein Literal kann nur
die Werte 0 und 1 annehmen.

2.2.2 Operatoren

Man hält Dinge und Zusammenhänge in schriftlicher Form mit genormten symbo-
lischen Zeichen fest. Dies nennt sich Notation. Die Notation einer Aussage wird
mit einem Großbuchstaben ausgeführt, zum Beispiel A. Um zu schreiben, dass eine
Aussage nicht erfüllt ist, nutzt man die Notation ¬A (sprich ”nicht A”) mit dem
Negationszeichen ¬. ¬A ist also genau dann erfüllt, wenn A nicht erfüllt ist (siehe
Fig. 1).

A ¬A
0 1
1 0

Fig. 1: Wahrheitstabelle der Negation

Um auszudrücken, dass zwei Aussagen erfüllt sind, verwendet man die Notation A∧B
(sprich ”A und B”) mit dem Konjunktor ∧. Die Aussage A ∧ B ist also genau dann
wahr, wenn sowohl A als auch B erfüllt sind. Dies nennt man eine Konjunktion (siehe
Fig. 2).
2 EINLEITUNG 6

A B A∧B
0 0 0
0 1 0
1 0 0
1 1 1

Fig. 2: Wahrheitstabelle der Konjunktion

Dass mindestens eine mehrerer Aussagen erfüllt ist, hält man mit der Notation A∨B
(sprich ”A oder B”) mit dem Disjunktor ∨ fest. Die Aussage A ∨ B ist also genau
dann wahr, wenn A, B oder A und B erfüllt sind. Dies nennt man eine Disjunktion
oder Klausel (siehe Fig. 3).

A B A∨B
0 0 0
0 1 1
1 0 1
1 1 1

Fig. 3: Wahrheitstabelle der Disjunktion

Man drückt mit der Notation A ↔ B (sprich ”A ist gleich B”) mit dem Symbol ↔
aus, dass zwei Aussagen denselben Wahrheitswert haben. Die Aussage A ↔ B ist
also genau dann wahr, wenn A und B beide erfüllt beziehungsweise beide nicht erfüllt
sind. Dies nennt man eine Bijunktion (siehe Fig. 4).
2 EINLEITUNG 7

A B A↔B
0 0 1
0 1 0
1 0 0
1 1 1

Fig. 4: Wahrheitstabelle der Bijunktion

Wenn eine Aussage unabhängig vom Wahrheitswert ihrer Bestandteile immer wahr
ist, kann man sie eine Tautologie nennen. Eine Bijunktion kann eine Äquivalenz
genannt werden, falls sie eine Tautologie ist. Man notiert Äquivalenzen mit dem
Symbol ⇔. Per Definition ist die Aussage A ⇔ B also immer wahr.

Dass genau eine zweier Aussagen wahr ist, schreibt man mit der Notation A ⊕ B
(sprich ”A ist kontravalent zu B”) mit dem Symbol ⊕. Die Aussage A⊕B ist also genau
dann wahr, wenn nur A oder nur B erfüllt ist. Dies nennt man eine Kontravalenz
(siehe Fig. 5).

A B A⊕B
0 0 0
0 1 1
1 0 1
1 1 0

Fig. 5: Wahrheitstabelle der Kontravalenz

Um festzuhalten, dass es nicht wahr ist, dass eine Aussage A erfüllt und eine Aussage
B nicht erfüllt ist, nutzt man die Notation A → B mit dem Symbol →. Die Aussage
A → B ist also nur genau dann nicht wahr, wenn A erfüllt und B nicht erfüllt ist.
Dies nennt man eine Subjunktion (siehe Fig. 6).
2 EINLEITUNG 8

A B A→B
0 0 1
0 1 1
1 0 0
1 1 1

Fig. 6: Wahrheitstabelle der Subjunktion

Sobald eine Subjunktion eine Tautologie ist, kann man sie eine Implikation nennen.
Man notiert diese mit dem Symbol ⇒. Die Aussage A ⇒ B ist also per Definition
immer wahr.

2.2.3 Formeln

Wir definieren Formeln als die Verknüpfung mehrerer Literale durch Operatoren.
Hierbei kann man Klammern benutzen, um die Ausführungsreihenfolge festzule-
gen.

z.B.: A ∧ ¬B , (A ∨ ¬B) ∧ (C ∨ D)

2.2.4 Konjunktive Normalform

Die konjunktive Normalform, kurz auch KNF, ist eine spezielle Form einer Formel.
Sie besteht aus Konjunktionen von Disjunktionen. Man kann jede Formel in eine
in der konjunktiven Normalform umformen. Alle Formeln in der KNF werden nach
folgender Formel definiert: !
n
^ mi
_
Li,j
i=1 j=1

Dabei sind alle Li,j Literale. Ein Paar Beispielformeln in der KNF:
2 EINLEITUNG 9

(A ∨ ¬B) ∧ (C)

(A ∨ B) ∧ (¬B ∨ C)

(¬A ∨ B ∨ C) ∧ (¬B ∨ D) ∧ (¬D ∨ A)

Wir definieren die einzelnen Gruppen an Disjunktionen als Klauseln. Somit wären
im letzten Beispiel (¬A ∨ B ∨ C), (¬B ∨ D) und(¬D ∨ A) Klauseln.

2.2.5 Erfüllbarkeit

Eine Formel ist genau dann erfüllbar, wenn es mindestens eine Möglichkeit gibt,
den Literalen die Werte so zuzuteilen, dass die Formel im Gesamten für diese eine
Belegung wahr wird. Im Umkehrschluss heißt eine Formel unerfüllbar, wenn es keine
entsprechende Belegung der Literale gibt, für die die Formel wahr ergibt. In der
Projektarbeit ist nur der zweite Fall von Relevanz.

2.2.6 Beweis und Herleitung

Ein Beweis ist eine Herleitung, die zu dem eigentlichen Ziel, das bewiesen werden
soll, führt. Eine Herleitung im Kontext des Projektes zeigt wiederum, welche Klauseln
benötigt werden, um zu zeigen, dass es eine andere Klausel geben können wird.
3 MATERIAL UND METHODEN 10

3 Material und Methoden

3.1 Java

Als Programmiersprache für unser Projekt haben wir Java gewählt. Dafür gibt es
mehrere Gründe. Zwar wäre ein C-Dialekt aufgrund seiner Eigenschaft als Compiler-
Sprache effizienter. Da wir jedoch Java bereits können, ist dies der primäre Grund
für unsere Wahl. Java kompiliert im Gegensatz zu C-Dialekten den geschriebenen
Code zunächst einmal in einen sogenannten Bytecode, der anders als die kompilier-
ten C-Programme plattformunabhängig ist, da der Bytecode kein “richtiger” Ma-
schinencode ist, aber diesem sehr nahe kommt und somit deutlich schneller als eine
reine Interpreter-Sprache 1 läuft, wodurch das Programm nicht für jedes System neu
kompiliert werden muss. Dies ist ein großer Vorteil, da dann insbesondere auf schwä-
cheren Computern, besonders bei großen Programmen, aufwändigere Kompilierung
notwendig ist und somit dann auch neu heruntergeladene Software kurzfristiger und
schneller nach dem Herunterladen ausgeführt werden kann.

3.2 Resolution

Resolution ist ein logisches Verfahren, mit dem man eine Formel auf ihre Lösbarkeit
überprüfen kann. Eine Formel gilt als lösbar, wenn man eine wahre Aussage als
Ergebnis der Formel herausbekommen kann. Resolution funktioniert nur bei Formeln,

1
Interpreter-Sprache: Eine Interpreter-Sprache funktioniert so, dass ein Programm die geschrie-
benen Programmzeilen nach und nach verarbeitet und dann, entsprechend der Befehle, die im
Programm stehen, handelt. Diese Programme sind meist in einer Compiler-Sprache geschrieben, da
diese dann mit maximaler Geschwindigkeit laufen können, weil sie im Maschinencode direkt für den
Prozessor verarbeitbar vorliegen.
3 MATERIAL UND METHODEN 11

die in der konjunktiven Normalform stehen. Hierbei widerlegt man, dass die Formel
lösbar ist, indem man eine Klausel herleitet, der man leicht ansehen kann, dass sie
nicht erfüllbar ist.

Allgemein geht man bei der Resolution nach einer allgemeinen Regel vor:

Man habe zwei Klauseln C1 und C2 in einer Formel die in der KNF ist. Nun gibt es
ein Literal, dass in C1 positiv enthalten und in C2 negativ enthalten ist.

L ∈ C1

L ∈ C2

Man kann daraufhin die Vereinigung der beiden Klauseln C1 und C2 ohne das po-
sitive und negative Literal herleiten. Die neu hergeleitete Klausel wird Resolvente
genannt.

CR = (C1 \ {L}) ∨ C2 \ {L})

z.B. (A ∨ ¬B) ∧ (¬A ∨ C) → (¬B ∨ C)

oder (G ∨ ¬H ∨ I) ∧ (¬G ∨ K) → (¬H ∨ I ∨ K)

Diese restlichen Literale können auch dieselben sein.

(A ∨ ¬B ∨ C) ∧ (¬A ∨ ¬B ∨ D) → (¬B ∨ C ∨ D)

Diese Resolvente ist nicht äquivalent zu den Ausgangsklauseln, wenn aber beide
Ausgangsklauseln gleichzeitig erfüllbar sind, muss auch die Resolvente erfüllbar sein.
Ist die Resolvente nicht erfüllbar, so können die beiden Ausgangsformeln auch nicht
erfüllbar sein. Man kann mit jeder neuen, durch Resolution entstandenen Klausel
ebenfalls weitere Resolutionsschritte durchführen.
3 MATERIAL UND METHODEN 12

Wenn in zwei Klauseln nur ein Literal und seine Verneinung stehen, entsteht eine
leere Klausel.

z.B. (A) ∧ (¬A) → ()

Eine leere Klausel, geschrieben {}, kann nicht erfüllt werden, da sie aus Klauseln
hergeleitet wird, die eine Formel bereits unerfüllbar machen.

Dies ist der Endpunkt der Resolution, da nie beide Klauseln gleichzeitig erfüllt sein
können. Dies müsste aber so sein, damit die Formel erfüllbar sein kann.

Die Geschwindigkeit jedes Beweises wächst exponentiell mit der Anzahl der Litera-
le.

Beispielresolution:

((A ∨ ¬B) ∧ (A ∨ B ∨ C) ∧ (¬A ∨ C) ∧ (B ∨ ¬C) ∧ (¬A ∨ ¬B ∨ ¬C))


hhhh
@ h%hhhh  
@ % hhhh 
hhhh
@ %  hhh
@%   hhh
(A ∨ C) (¬B ∨ ¬C)
 
 
Z  
Z  
Z  
Z
Z  
ZZ 
(C) (¬C)
@
@
@
@
()
3 MATERIAL UND METHODEN 13

3.3 Symmetrie

Symmetrien sind eine Erweiterung der Resolution. Um den folgenden Absatz zu


verstehen werden Kenntnisse über Permutationen benötigt. Haben wir n Elemente,
so ist eine Permutation dieser Elemente eine Abbildung, die jedem Element der
Menge ein Element der Menge zuordnet. Dabei werden zwei verschiedene Elemente
nie auf das gleiche Element abgebildet. Eine Menge mit n Elementen hat n! viele
Permutationen.

Die Permutation, die B und C vertauscht, wird mit (ACB) bezeichnet. (CAB) be-
schreibt die Permutation bei der A auf C, B auf A und C auf B abgebildet wird.
Die Ursprungsreihenfolge gilt auch als eine Permutation. In unseren Beispielen wäre
dies (ABC).

Haben wir nun eine Menge an Variablen V und σ ist eine Permutation dieser Varia-
blen, dann definieren wir, dass für jede Klausel C, die man mit den Variablen aus
V konstruieren kann, σ(C) die resultierende Klausel ist, wenn man die Permutation
σ auf die Variablen von C anwendet. Für eine Menge von Klauseln Γ ist σ(Γ) als
{σ(C)|C ∈ Γ} definiert.

Die Formel (A ∨ ¬B) ∧ (¬A ∨ C) ∧ (B ∨ ¬C) hätte somit die Permutationen

1. (ABC): (A ∨ ¬B) ∧ (¬A ∨ C) ∧ (B ∨ ¬C)

2. (ACB): (A ∨ ¬C) ∧ (¬A ∨ B) ∧ (C ∨ ¬B)

3. (BAC): (B ∨ ¬A) ∧ (¬B ∨ C) ∧ (A ∨ ¬C)

4. (BCA): (B ∨ ¬C) ∧ (¬B ∨ A) ∧ (C ∨ ¬A)

5. (CAB): (C ∨ ¬A) ∧ (¬C ∨ B) ∧ (A ∨ ¬B)


3 MATERIAL UND METHODEN 14

6. (CBA): (C ∨ ¬B) ∧ (¬C ∨ A) ∧ (B ∨ ¬A)

Wenn nun eine Klausel C aus einer Menge von Klauseln Γ hergeleitet wurde und
σ(Γ) = Γ gilt, dass heißt die Klauseln in σ(Γ) und Γ enthalten die exakt gleichen
Klauseln, kann σ(C) als nächster Schritt der Herleitung ermittelt werden.

Bei (A ∨ ¬B) ∧ (A ∨ ¬C) kann man Symmetrie anwenden, da, wenn man die Reihen-
folge der Variablen von 1, 2, 3 auf 1, 3, 2 ändert, die Formel: (A ∨ ¬C) ∧ (A ∨ ¬B)
entsteht. Beide Formeln sind exakt gleich.

Somit könnte man Symmetrie bei (A ∨ ¬B) ∧ (¬A ∨ C) nicht anwenden, da


(A∨¬C)∧(¬A∨B) nicht die gleichen Klauseln wie die Ursprungsformel enthält.

Man kann Symmetrien nun mit Resolution zusammen dafür nutzen, um schneller
zu Ergebnissen zu kommen, da man Symmetrien auf durch Resolution hergeleitete
Klauseln anwenden kann.

Ein Beispiel:
(¬A ∨ B) ∧ (¬B ∨ C) ∧ (¬C ∨ A)

Sowohl die Permutation (CAB) als auch (BCA) enthalten die gleichen Klauseln wie
die Ursprungsformel:

(CAB) : (¬B ∨ C) ∧ (¬C ∨ A) ∧ (¬A ∨ B)

(BCA) : (¬C ∨ A) ∧ (¬A ∨ B) ∧ (¬B ∨ C)

Leiten wir aus der Ursprungsformel nun zum Beispiel die Klausel (¬A ∨ C) her, so
können wir ebenfalls die Klauseln (¬C ∨ B) und (¬B ∨ C) herleiten, wenn wir die
jeweilige Permutation anwenden.
3 MATERIAL UND METHODEN 15

3.4 SAT-Solver

Ein SAT-Solver wird dazu verwendet um zu prüfen, ob eine gegebene aussagenlogi-


sche Formel erfüllbar ist. Dabei ist “SAT” die englische Abkürzung für “satisfiabili-
ty”, was wiederum das Erfüllbarkeitsproblem darstellt. Außerdem kann der gewählte
2
SAT4J bei erfüllbarer Formel auch direkt eine mögliche Belegung der Literale be-
3
reitstellen. Da SAT NP-vollständig ist, ist davon auszugehen, dass es keinen Algo-
rithmus gibt, der die Formel effizient löst und somit immer am schnellsten ist. Daher
wird in der Implementation der ebengenannte SAT4J verwendet, um zumindest ei-
ne etwas effizientere Ausführung als bei einem selbsterstellten Solver, der erst noch
optimiert werden müsste, verwendet. Die Wahl fällt unter anderem auf SAT4J, da
dieser über ein Maven-Repository, ein Weg Software-Bibliotheken anderer Entwick-
ler zu verwenden, sehr einfach in den eigenen Java-Code eingebunden werden kann
und somit nicht wie das verwendete Programm zur Bestimmung der Symmetrien
anderweitig eingebunden werden muss.

3.5 Pigeonhole Principle

Das Pigeonhole Principle, auch P HPmn genannt, besagt Folgendes: Wenn wir n Tau-
ben und m Taubenschläge (Pigeonholes) bei n > m haben und wir jeden Tauben-
schlag der Reihe nach belegen, muss in einem Taubenschlag mehr als eine Taube
sein. Dies kann für jegliche Gegenstände und Gruppen angewendet werden. Nun ist
aber zu beweisen, dass das Prinzip nicht wahr ist, also in jedem Taubenschlag nur
eine Taube ist.

Es klingt erst einmal leicht zu beweisen, ob man n Tauben in m Taubenschläge vertei-


2
https://sat4j.org/
3
NP-vollständig bedeutet, dass sich das Problem vermutlich nicht effizient lösen lässt.
3 MATERIAL UND METHODEN 16

len kann oder nicht. Die benötigte Formel soll aber in der konjunktiven Normalform
sein, damit man Resolution anwenden und sich die Lösbarkeit logisch herleiten kann.
Hierfür werden zwei verschiedene Arten von Klauseln hergeleitet.

Die Tauben-Klauseln: für i ∈ [n]: (xi,1 ∨ xi,2 ∨ ... ∨ xi,m )

Diese Klauseln sagen aus, dass jede Taube i in irgendeinem Loch von 1 bis m sein
muss.

Die Schlag-Klauseln: für i 6= k, j ∈ [m]: (¬xi,j ∨ ¬xk,j )

Diese Klauseln sagen aus, dass nicht zwei Tauben zusammen in einem Schlag sein
können.

Alleine für drei Tauben und zwei Schläge ist dies eine relativ lange Formel:

(x1,1 ∨ x1,2 )∧(x2,1 ∨ x2,2 )∧(x3,1 ∨ x3,2 )∧(¬x1,1 ∨ ¬x2,1 )∧(¬x1,1 ∨ ¬x3,1 )∧(¬x2,1 ∨ ¬x3,1 )∧
(¬x1,2 ∨ ¬x2,2 ) ∧ (¬x1,2 ∨ ¬x3,2 ) ∧ (¬x2,2 ∨ ¬x3,2 )

Die Beweise für das P HPmn werden exponentiell länger, weshalb man, wenn man
nur Resolution benutzt um es zu lösen man exponentiell lange braucht. Benutzt
man aber Symmetrie, kann man die Länge des Beweises auf polynomiale Länge
verringern, da man dafür dank Symmetrie eine deutlich geringere Anzahl an Klauseln
benötigt. Allgemein hat ein P HPmn n!∗m! viele Permutationen. Beispielsweise hat das
P HP23 bereits 12 Permutationen. Es ist ein gutes Beispiel, um die Effizienz unseres
Programms zu testen, da wir durch das Pigeonhole Principle einfach symmetriereiche
Formeln generieren können.
4 PROJEKTARBEIT 17

4 Projektarbeit

4.1 Ziele

Da die Ziele des Projekts bereits in der Aufgabenstellung diskutiert wurden, wird
hiermit schlicht daran erinnert, dass ein Programm zu schreiben ist, das in einiger-
maßen vernünftiger Zeit den, beziehungsweise einen, kürzestmöglichen Beweis findet,
dass eine aussagenlogische Formel, die in der konjunktiven Normalform steht, nicht
erfüllbar ist.

4.2 Ein Bericht

Zu Beginn galt es erst einmal, sich die Grundlagen anzueignen. Darunter fallen etwa
eine Wiederholung der Aussagenlogik sowie auch bereits die erste Methode, mit der
man zumindest beweisen kann, dass eine Formel unerfüllbar ist: Die Resolution. Wie
sie funktioniert wurde bereits bei den Methoden erklärt, jedoch findet man mithilfe
der Resolution vielmehr heraus, welche zusätzlichen Klauseln man aus den gegebe-
nen “erzeugen” kann und somit für den späteren Beweis zur Verfügung hat.
Schließlich wurde Java als Programmiersprache gewählt und es ging nun daran, ein
erstes Datenmodell zur Darstellung der KNFs und Klauseln zu entwickeln. So wur-
de schnell der Datentyp CNF (englische Abkürzung: “conjunctive normal form” ->
KNF) entwickelt. Die erste Version davon bestand eigentlich nur aus einem Wrapper
für eine Liste von Listen für einen Integer, der die verschiedenen Variablen darstellt,
wobei beispielsweise dann 1 A und −1 ¬A repräsentiert.
Um die Handhabung von KNFs zu simplifizieren wurden Methoden geschrieben, die
aus einem gegebenen String die entsprechende KNF generieren und, bei Bedarf, dann
4 PROJEKTARBEIT 18

auch wieder besser lesbar ausgeben (siehe Methoden convertFromString(rawinput :


String) und toString() : String). So müssen diese nicht aufwändig händisch in das
Programm eingetragen werden, sogenanntes “Hardcoding”. Anschließend wurde auch
schon bereits die erste Version der Resolution implementiert. Dazu wurden weitere
Klassen erstellt, die die verarbeiteten Daten verwalten, konkret zunächst das soge-
nannte “ResolutionSet”, das alle nötigen Informationen zu einer neu erstellten Klausel
speichert, sowie “ResolutionResult”, das wiederum die verschiedenen Instanzen des
ResolutionSet verwaltet.
Somit konnten wir nun bereits bestimmen, ob die angegebene Formel erfüllbar ist,
was nützlich ist, um, im Falle der Erfüllbarkeit, erst gar nicht weiter zu rechnen und
somit kostbare Rechenzeit zu sparen. Mit der Zeit wird schnell klar, dass die Art,
Klauseln als Datentyp Liste zu speichern, nicht ausreicht, da ein Bedarf besteht, wei-
tere Informationen zur entsprechenden Klausel zu hinterlegen, etwa ob die Klausel
bereits gegeben war oder aus welchen Klauseln sie hergeleitet werden kann. Wenn
man nun den Zweck des ResolutionSet als temporärer Speicher von Klauseln, die
durch Resolution entstanden sind, betrachtet, sieht man, dass die Klasse “Clause”,
die eine Klausel und diverse weitere Eigenschaften dieser speichert (siehe Attribute
von Clause), bereits alle Funktionen ersetzen kann, wodurch diese nun obsolet wird.
Nun war es der Plan, erste Beweise zu bestimmen. Da dies jedoch nicht wie erwünscht
im Programm funktionierte, wurde mangels Ideen beschlossen, zunächst die Möglich-
keiten der Symmetrie zu erarbeiten und dann anschließend die Beweise direkt richtig
umzusetzen, da Symmetrien eine weitere Möglichkeit sind, die Herleitung von Klau-
seln darzustellen. Dabei entstehen zwar, wie bereits nach wenigen Versuchen klar
wurde, keine neuen Klauseln, die man nicht auch mit der Resolution erhalten würde,
jedoch kann man diese einzeln schneller berechnen. Die Berechnung der Symmetrien
4
wird durch das Programm “Nauty Traces” ermöglicht. Somit wurde Symmetrie di-

4
https://pallini.di.uniroma1.it/
4 PROJEKTARBEIT 19

rekt auch in den Resolutionsprozess eingearbeitet. Da nun jedoch nicht sichtbar war,
dass die Resolution weitere Klauseln auch bereits vor der Resolution zu Tage fördern
kann, entschieden wir uns dazu, zunächst nur noch eine Klausel durch die reguläre
Resolution entstehen zu lassen. Somit konnte schnell die Hypothese aufgestellt wer-
den, dass Symmetrie nicht die Anzahl der benötigten Schritte beeinflusst, sondern
nur die Beweise für die einzelnen Klauseln kürzer macht, was sich schlussendlich auch
als wahr herausgestellt hat (siehe Ergebnisse zum PHP).
Da nun also auch die Symmetrie integriert war, ging es daran, den kürzesten Be-
weis für die leere Klausel zu finden. Der erste Ansatz war es, von eben jener leeren
Klausel ausgehend alle möglichen Ursprungskombinationen durchzugehen und dann
jeweils mitzuzählen, welche die kürzeste ist. Wir entschieden uns, dann die jeweili-
gen Herleitungen für die Klauseln in ihnen selbst zu cachen um den Rechenaufwand
zu minimieren. Letztendlich führte dieser Weg der Beweissuche jedoch dazu, dass
einerseits Endlosschleifen entstehen konnten, da es durchaus vorkommen kann, dass
eine Klausel X eine Klausel Y herleiten kann, aber auch die Klausel Y die Klausel X
herleitet. Somit ruft sich die rekursiv implementierte Methode immer wieder selbst
auf und benötigt aufgrund des cachens somit sehr viel Platz, weshalb sich am Ende
Java mit einem StackOverFlowError beschwert.
Somit wurde beschlossen, zunächst einmal nur den erstgefundenen Beweis zu be-
rechnen, indem man simpel den ersten Ursprüngen der Klauseln folgt, bis man bei
den gegebenen ankommt. Man hat so zumindest einen ersten Beweis, mit dem man
die weiteren Schritte entwickeln kann, bevor es dann an den richtigen Beweis geht.
Somit war es wieder an der Zeit, eine Idee zu entwickeln, mit der man die Endlos-
schleifen umgehen kann, sodass sich das Programm nicht mehr aufhängen würde. Es
kam die Idee auf, der rekursiven Methode eine Liste an IDs, eine Nummer, die jeder
Klausel zugeteilt wird, jener Klauseln mitzugeben, die bereits im aktuellen Durch-
lauf aufgerufen wurden, jedoch war es aufgrund der schieren Masse immer noch ein
4 PROJEKTARBEIT 20

sehr ineffizientes Verfahren. Dadurch, dass immer noch alle Herleitungen gespeichert
werden mussten, kam es immer noch zum StackOverFlowError. Es entstand die Op-
tion, auch die Herleitungen und ihren zugehörigen Datentyp “Derivation” rekursiv
zu speichern, um an Speicherplatz zu sparen, da so immer nur Teile der einzelnen
Beweise gespeichert werden. Jedoch mussten all diese Instanzen der Herleitungen
wieder gespeichert werden und um Dopplungen zu vermeiden musste bei jeder neuen
Herleitung diese mit allen bestehenden abgeglichen werden. Dies gestaltet sich we-
gen der rekursiven Bauweise als sehr aufwendig, da die Derivation erst einmal gebaut
werden muss. Dies stellt einen nicht aufbringbaren Zeitaufwand für den Gewinn an
Speicherplatz dar.
Nun war wieder eine neue Variante der Beweisbestimmung erforderlich. Diesmal wur-
de ein vollständig anderer Ansatz gewählt, der zum Erfolg führen sollte. Dieser be-
stand darin, zunächst einmal allen Klauseln und deren Ursprungskombinationen wei-
tere IDs zu geben, was bei den Klauseln jedoch nicht mehr nötig war, da bei diesen
bereits zu Beginn eine ID zur besseren Verarbeitung festgelegt wird. Wenn man diese
IDs nun als Literale eindeutig beschreibt und bestimmten Formeln folgend in eine
neue KNF verpackt und diese vom SAT-Solver lösen lässt, kann man herausfinden,
ob ein Beweis einer beliebigen Länge n oder kürzer existiert.
Nun kann man mit dem Wissen, dass der erste gefundene Beweis eine bestimmte
Länge besitzt, den Bereich eingrenzen, welche Länge der Beweis haben kann. Daher
haben wir eine Methode geschrieben, die die Länge des kürzestmöglichen Beweises
herausfinden kann, indem sie das noch relevante Intervall halbiert und dann für die
Mitte prüft, ob ein entsprechender Beweis existiert. Sie entscheidet daraufhin, ob ein
kürzerer oder längerer Beweis gesucht ist.
So stellt sich die Frage, wie man nun davon auf einen Beweis schließen kann. Man
merkt sich, welche der relevanten Literale zu welcher Klausel gehören. Indem wir
betrachten, welche Wahrheitsbelegung der SAT-Solver für die Formel zurückgibt,
4 PROJEKTARBEIT 21

können wir auswählen, welche Klauseln wir für den Beweis benötigen und uns den
Beweis damit bauen. Jetzt benötigen wir jedoch noch eine Funktion, die überprüft, ob
ein gefundener Beweis gültig ist. Dafür wird ein Resolutionsschritt auf alle Klauseln
angewendet, um dann zu testen, ob die gerade zu prüfende Klausel dort enthalten
ist, womit sich die zu erwartende Gültigkeit bestätigt. Und somit ist ein im Rahmen
seiner Möglichkeiten funktionierendes Programm entstanden.

4.3 Wie findet man den kürzesten Beweis heraus?

Die Idee, jetzt den kürzesten Beweis auch wirklich bestimmen zu können, beruht
darauf zu sagen, dass grundsätzlich jede Klausel mit jedem beliebigen Ursprung ein
Teil eines Beweises sein könnte. Dabei überprüfen wir dann, ob es einen Beweis von
maximal der Länge l gibt. So legen wir nun fest, dass wir die Klauseln C1 . . . Ck
nennen, wobei dann k die ID der leeren Klausel ist. Eine Klausel Ci können wir in
der Form xi,j weiterverwenden. Dies bedeutet, dass die Klausel an j-ter Stelle im
Beweis steht. Zudem definieren wir, dass wir die möglichen Ursprünge der Klausel
mit dem Index i als Ci : Ui,1 . . . Ui,n schreiben. Dabei trägt n den Wert der Anzahl der
Ursprünge der Klausel. Analog zur Klausel kann man auch den Ursprung Ui,m für die
einzelnen Positionen im Beweis mit yi,m,1 . . . yi,m,l beschreiben. Da wir wissen, dass der
jeweilige Ursprung auf zwei anderen Klauseln Ca und Cb basiert, beziehungsweise nur
auf einem der beiden, im Falle von Symmetrie, können wir sagen, dass diese bereits
bereits vor dem Schritt j im Beweis enthalten sein müssen. Dies lässt sich durch die
Formel
_ _
yi,m,j ⇒ ( xa,j 0 ) ∧ ( xb,j 0 )
j 0 6j j 0 6j

festlegen. Außerdem muss die leere Klausel Ck = ∅ irgendwo im Beweis enthalten


W
sein, was man mithilfe der Disjunktion j6l xk,j sicherstellen kann. Zusätzlich gilt es
4 PROJEKTARBEIT 22

W
festzulegen, dass aus i6k xi,j für jedes j die Bedingung #xi,j 6 1 gilt. Wenn wir
nun suchen, wie wir dafür sorgen können, dass alle Bedingungen erfüllt sind, finden
wir einen Beweis, der maximal die gegebene Länge besitzt. Damit haben wir jedoch
noch nicht den kürzestmöglichen Beweis, aber dazu mehr bei der Umsetzung.

4.4 Die Umsetzung der Prinzipien im Programm

4.4.1 Resolution

Um zu prüfen, ob eine Resolution möglich ist, bilden wir, indem wir über alle Klauseln
zweifach iterieren, alle möglichen verschiedenen Kombinationen. Nun prüfen wir bei
jeder von ihnen, wie viele Literale die entgegengesetzte Negation besitzen. Im Fall,
dass dies 1 beträgt, wird eine Resolution angewendet, indem alle anderen Literale in
eine neue Klausel eingebunden werden, sofern es diese noch nicht gibt.

4.4.2 Symmetrie

Die Verwendung der Symmetrie im Programm ist eng verbunden mit derer der Reso-
lution, da die Symmetrie die neuen Klauseln der Resolution abwartet und daraufhin
alle möglichen Permutationen auf jene anwendet, wo dies nur möglich ist, sodass wir
neue Klauseln beziehungsweise Herleitungen erhalten.

4.4.3 Die Erstellung der Lösungsformel

Die Erstellung der Lösungsformel läuft insofern ab, dass alle genannten Bedingungen
so umgeformt werden, dass sie in eine einzige Konjunktive Normalform passen. Dies
4 PROJEKTARBEIT 23

geschieht etwa wie folgt (A → B) ⇔ (¬A ∨ B) und kann ideal über Wahrheitstabel-
len bestimmt und überprüft werden. So können auch die ’De Morganschen Regeln’
weiterhelfen: ¬(A ∧ B) ⇔ ¬A ∨ ¬B und ¬(A ∨ B) ⇔ ¬A ∧ ¬B.
Um nun aber noch die Übersicht über all die Indizes zu behalten, berechnen wir mit-
hilfe von den bereits zugeteilten IDs der Klauseln addiert mit der höchsten verteilten
ID multipliziert mit der Position im Beweis ein eindeutig benanntes Literal.

4.4.4 Der Beweis

Den kürzestmöglichen Beweis erhalten wir nun, indem wir das Intervall der noch
möglichen Längen des Beweises halbieren und dann mittels des SAT-Solvers unter-
suchen, ob der mittlere Wert als Länge für den Beweis ein Ergebnis liefert. Ent-
sprechend wird dann entschieden, welche Hälfte des Intervalls weiterverwendet wird.
Wenn anschließend die obere und untere Grenze des Intervalls identisch sind, haben
wir die Länge des kürzestmöglichen Beweis herausgefunden. Nun haben wir jedoch
immernoch keinen Beweis. Diesen erhalten wir ebenso über den SAT-Solver, da die-
ser eine Belegung ausgibt, welche Literale wahr sind, damit die Formel wahr wird.
Diese geben allerdings keinen direkten Rückschluss darauf, welche Klauseln an wel-
cher Stelle des Beweises stehen, da wir lediglich die Informationen erhalten, welche
der verteilten “Namen” erfüllt sind. Stattdessen müssen wir die Technik des Back-
tracking anwenden, also speichern wir, welcher “Name” zu welcher Klausel an welcher
Position gehört und wissen dann entsprechend, welche Klauseln wir wann im Beweis
verwenden müssen und wir haben unseren Beweis.
5 ERGEBNISSE 24

5 Ergebnisse

5.1 Laufzeit des Pigeonhole Principles

Wir haben unser Programm mit dem Pigeonhole Principle getestet, um zu überprü-
fen, wie viel schneller das Programm mit Symmetrie einen Beweis findet, als das
Programm ohne Symmetrie.

In unserem Programm verringert Symmetrie die Laufzeit des P HP12 von durch-
schnittlich 4,2 ms auf 3,7 ms und des P HP23 von durchschnittlich 64014 ms auf
211 ms. Beide liefen 10 Mal auf demselben System.

Symmetrie spart also auch schon bei kleinen PHPs sehr viel Zeit.

Vom P HP34 wurde selbst mit Symmetrie nach langer Zeit kein Ergebnis gefunden.
Dies liegt an Limitationen der Computer, die uns zur Verfügung stehen, unserer
Wahl der Programmiersprache und natürlich auch an unserem Programm, dass nicht
perfekt optimiert ist.

Auch die Länge des Beweises wird durch Symmetrie verkürzt. Beim P HP12 gibt es
noch keine Veränderung der Beweislänge. Aber bereits beim P HP23 wird die Länge
des kürzesten Beweises, den das Programm findet, um 3 verkürzt. Ohne Symmetrie
enthält dieser nämlich 10 Klauseln. Wendet man jedoch Symmetrie an, wird die
Länge des Beweises auf 7 reduziert.
6 ZUSAMMENFASSUNG, DISKUSSION UND AUSBLICK 25

6 Zusammenfassung, Diskussion und Ausblick

Letztendlich ist es uns erfolgreich gelungen ein Programm zu schreiben, das kürzeste
Beweise für die Unerfüllbarkeit aussagenlogischer Formeln aufstellt. Dies ist jedoch
limitiert, wie am Beispiel des Pigeonhole Principle zu sehen ist. In diesem Fall funk-
tioniert das Programm konkret bei P HP34 nicht mehr, da zu viele Klauseln durch
Resolution und Symmetrie gefunden werden, wodurch die Zeit pro Schritt durch Ver-
wendung jeder möglichen Kombination quadratisch ansteigt. Das Problem mit der
Limitierung der Länge der KNFs auf Seiten des SAT-Solvers lässt sich vermutlich
insofern verringern, dass man in den SAT-Solver erst gar nicht die selbst generierten
zur Berechnung des Beweises erstellten Klauseln verwendet, sondern die Formel so
5
schreibt, dass diese sozusagen dadurch ersetzt werden, wie man in diesem Paper
beschrieben wird.

5
https://digibuo.uniovi.es/dspace/bitstream/10651/53830/1/Computing%20Shortes
t.pdf
7 DANKSAGUNG 26

7 Danksagung

An dieser Stelle möchten wir uns bei all denjenigen bedanken, die uns die Teilnahme
am Hector Seminar und am Kooperationsprojekt ermöglicht haben.

Zuerst gebührt unser Dank Herr Moritz Lichter der TU Darmstadt, der das Koope-
rationsprojekt geleitet hat und uns in der Erstellung der Ausarbeitung unterstützt
hat. So hat er uns freundlicherweise auch die Einbindung von “Nauty Traces” zur
Verfügung gestellt.

Ebenfalls möchten wir uns bei unseren Betreuern Herr Oliver Rudolph, Frau Gisela
Döbbeling und Herr Thomas Rödler bedanken, die uns über die Jahre im Hector
Seminar begleitet haben.

Ein besonderer Dank gilt Hans-Werner Hector, der uns überhaupt die Teilnahme am
Hector Seminar ermöglicht hat.
8 QUELLEN 27

8 Quellen

8.1 Literatur

1. Krishnamurthy, Balakrishnan: Short Proofs for Tricky Formulas, Acta Infor-


matica 22, Springer: 1985, 253-275

2. Urquhart, Alasdair: The symmetry rule in propositional logic, Discrete Applied


Mathematics 96–97, Elsevier, Amsterdam: 1999, 177–193

8.2 Internetquellen

Internetquellen mit Datum

1. https://www2.informatik.hu-berlin.de/logik/lehre/WS21-22/Logik/dow
nloads/LogInf-Skript.pdf 11.10.2022

2. https://de.wikipedia.org/wiki/Resolution_(Logik) 11.10.2022

3. https://de.wikipedia.org/wiki/Permutation 11.10.2022

4. https://de.wikipedia.org/wiki/Aussagenlogik 11.10.2022

5. https://de.wikipedia.org/wiki/Aussage_(Logik) 11.10.2022

6. https://de.wikipedia.org/wiki/Negationszeichen 11.10.2022

7. https://de.wikipedia.org/wiki/Konjunktion_(Logik) 11.10.2022

8. https://de.wikipedia.org/wiki/Disjunktion 11.10.2022
9 ANHANG 28

9. https://de.wikipedia.org/wiki/Implikation 11.10.2022

10. https://de.wikipedia.org/wiki/Subjunktion 11.10.2022

11. https://de.wikipedia.org/wiki/Kontravalenz 11.10.2022

12. https://de.wikipedia.org/wiki/Bikonditional 11.10.2022

13. https://de.wikipedia.org/wiki/NP-Vollständigkeit 12.10.2022

14. https://de.wikipedia.org/wiki/Erfüllbarkeitsproblem_der_Aussagenlogi
k 12.10.2022

15. https://en.wikipedia.org/wiki/Boolean_satisfiability_problem 12.10.2022

16. https://en.wikipedia.org/wiki/Java_(programming_language) 12.10.2022

17. https://de.wikipedia.org/wiki/Java_(Programmiersprache) 12.10.2022

9 Anhang

9.1 Fachbegriffe

• Attribut: Ein Attribut ist eine Variable, die in einem Datentyp in der Objek-
torientierten Programmierung gespeichert wird. Alternativ könnte man auch
sagen, dass es eine Eigenschaft einer Klasse ist.

• cachen: Cachen ist eine Möglichkeit, so zu programmieren, dass man Metho-


denaufrufe minimieren kann, indem man häufig benötigte Zwischenergebnisse
speichert, sodass man sie nur einmal berechnen muss.
9 ANHANG 29

• rekursiv: Wenn eine Methode rekursiv ist, ruft sie sich selbst auf und greift
etwa auf den Rückgabewert zurück. Das heißt, dass um etwa einen n-ten Wert
zu berechnen, man alle Werte von 1 bis n - 1 berechnen muss.
9 ANHANG 30

9.2 UML-Klassendiagramm
E1, E2
Pair
-item1 : E1
-item2 : E2
Main
+Pair()
+Pair(item1 : E1, item2 : E2)
+main(args : String[])
+getItem1() : E1
1..1 +setItem1(item1 : E1)
+getItem2() : E2
+setItem2(item2 : E2)

calls
1..n

Resolution
-cnf : CNF
+Resolution(cnf : CNF)
+doOneStep(withSymmetry : boolean) : ResolutionResult
+execute(withSymmetry : boolean)
+checkProof(derivationList : List<Integer>, clauseID : int) : boolean
+checkProof(derivation : Derivation) : boolean
+firstProof(id : int) : Derivation
1..1 +getMappingOfLength(length : int) : Pair<int[], HashMap<Integer, Integer>> 1..1
+hasProofOfLength(length : int) : boolean
+getShortestProof(firstProofLength : int) : Derivation
+shortestProof(firstProofLength : int) : int
1..1 1..1 1..1
calls creates uses
1..1

SymmetryTool
-cnf : CNF
0..n
-withNegationSymmetries : boolean
-adjMatrix : boolean[][] Derivation
-firstClauseVertex : int
-symmetries : List<Symmetry> -cnf : CNF
-clause : int 1..1
-NAUTY_CMD : String -derivationList : List<Integer>
ResolutionResult
+SymmetryTool(cnf : CNF, withNegationSymmetries : boolean) +Derivation(cnf : CNF, derivation : List<Integer>)
+SymmetryTool(cnf : CNF) +contains(item : int) : boolean -results : List<Clause>
-litVertex(lit : int) : int +containsAny(list : List<Integer>) : boolean -cnf : CNF
uses -reverseLitVertex(vertex : int) : int works with +getClause() : int
+ResolutionResult(cnf : CNF)
-setEdge(u : int, v : int) +getDerivation() : List<Integer>
+toCNF() : CNF
-isEdge(u : int, v : int) : boolean +getDerivation(elementariesIncluded : boolean) : List<Integer>
+addResult(clause : Clause, origin1 : int, origin2 : int) : boolean
-computeGraph() +size() : int
+addResult(clause : Clause, origin : int) : boolean
-writeInt(writer : BufferedWriter, i : int) +size(elementariesIncluded : boolean) : int
-writeGraph(out : OutputStream) +equals(obj : Object) : boolean 1..1
-translateGraphToCNFSymmetry(gsym : int[]) : Symmetry +toStringWithoutElementaries() : String
-readAutomorphisms(in : InputStream) +toString(elementariesIncluded : boolean) : String
-getNautyWrapperExecutable() : String +toString() : String
-callNauty()
+computeSymmetries()
+getSymmetries() : List<Symmetry>
+main(args : String[])
1..1
discovers is converted to
1..1

CNF
-clauses : List<Clause>
-maxLiteral : int
-lastElementaryIndex : int
+CNF()
1..n 1..n 1..1
+CNF(clauses : List<Clause>)
Symmetry +combine(cnf1 : CNF, cnf2 : CNF)
+getMaxLiteral() : int
-cnf : CNF +contains(clause : List<Integer>) : boolean
-permutation : int[] +contains(clause : Clause) : boolean
+convertFromString(rawinput : String)
+Symmetry(cnf : CNF)
+get(index : int) : Clause
-litPosition(lit : int) : int
+get(clause : Clause) : Clause
+setLitImage(fromLit : int, toLit : int)
+get(list : List<Integer>) : Clause
+apply(lit : int) : int
+getLastElementaryIndex() : int
+toString() : String
+length() : int
+order()
+orderSingle(clause : List<Integer>) : List<Integer>
+output()
+print()
+size()
+toString() : String
+iterator() : Iterator<Clause>
1..1
consists of
2..n

Clause
-ID : int
-clause : List<Integer>
-elementary : boolean
-origins1 : List<Integer>
-origins2 : List<Integer>
-originIDs : List<Integer>
-fromSymmetry : List<Boolean>
+Clause(clause : List<Integer>, origin1 : int, origin2 : int, ID : int)
+Clause(clause : List<Integer>, origin : int, ID : int)
+Clause(clause : List<Integer>, ID : int)
+isElementary() : boolean
+isFromSymmetry(num : int) : boolean
+getClause() : List<Integer>
+setClause(clause : List<Integer>)
+getID() : int
+addOrigin(origin : int)
+addOrigins(origin1 : int, origin2 : int)
+checkOrigins(origin1 : int, origin2 : int) : boolean
+getOrigins1() : List<Integer>
+getOrigins2() : List<Integer>
+getOriginIDs() : List<Integer>
+hasOrigin(origin : int) : boolean
+toString() : String
9 ANHANG 31

Eigenständigkeitserklärung

Hiermit versicheren wir, dass wir diese Arbeit unter der Beratung durch Moritz
Lichter selbstständig verfasst haben und keine anderen als die angegebenen Quellen
und Hilfsmittel benutzt wurden, sowie Zitate kenntlich gemacht haben. Unterschrif-
ten:

Ort, Datum:

Das könnte Ihnen auch gefallen