You are on page 1of 5

Andrew Emrazian – u0349111

CS 4300 - AI
Oct 6, 2016
Assignment A4a: Resolution Theorem Prover
1. Introduction

In this assignment I implemented a resolution theorem prover. The program processes logical
statements that are in conjunctive normal form (CNF) referred to as a knowledge base KB. A
query clause a is negated and added to the KB in order to prove by contradiction. Each pair of
logical clauses that contains complementary literals is resolved to produce a new clause, which is
added to the set if it is not already present. The process continues until one of two things
happens:

• there are no new clauses that can be added, in which case KB does not entail a; or,
• two clauses resolve to yield the empty clause, in which case KB entails a.

The empty clause—a disjunction of no disjuncts—is equivalent to False because a disjunction is


true only if at least one of its disjuncts is true. I will also explore the following question:

• How does the number of clauses change when there is no solution depending on different
or additional KB clauses?

2. Method

This assignment consists of 3 Matlab functions

1. CS4300_RTP.m

This is the main program in observation. The pseudo code is listed in figure 7.9 above. My
program takes each disjunctive literal of the theorem clause that is given and adds each
negated literal as a separate conjunctive clause to the sentences structure. It checks each pair
of clauses in the structure for any new resolvents. The way that I am checking to see if any
new resolved clauses are a subset of the clauses structure is by taking the total number of

1
clauses in the existing structure, adding the new clauses, remove all of the duplicate clauses,
and then take the total number of clauses again. If the total number of clauses after s greater
than before, repeat the resolution process. The empty clause, which proves the query, is
represented if a resolvent has a clause that is empty (i.e.
isempty(resolvents(k).clauses)).

DP(1).clauses = [-1,2,3,4];
DP(2).clauses = [-2];
DP(3).clauses = [-3];
DP(4).clauses = [1];
thm(1).clauses = [4];
vars = [1,2,3,4];
resolution = CS4300_RTP(DP,thm,vars);

2. CS4300_PL_Resolve.m

This helper function acts as defined and used in the pseudo code in figure 7.9 above. Every
combination of elements is checked between the two lists of literals. If there are opposing
literals of the same atom, union of the lists minus the atom are a resolvent. The three cases
here are represented as follows:
• Opposing literals resulting in disjunctives.
resolvents(k).clauses = <some list>
• Single opposing literals cancel (the empty clause).
resolvents(k).clauses = []
• No opposing literals. resolvents = []

clause_i = [-2, -1, 3, 4];


clause_j = [1, 2, 4, 5];
res = CS4300_PL_Resolve(clause_i, clause_j);

3. CS4300_Testing.m
I have testing file where I have several tests cases. There are also some calls that gather
the clause length of some resolutions.

[ test1, test2, clause_growth ] = CS4300_Testing();

3. Verification of Program
I verified my application with a few examples. First, with the very simple example given
in class. Second, with example from the book in wumpus world. Third, an example that is
not proved.

1) We have a knowledge base, 𝐾𝐵 = {(𝐴) ∧ (¬𝐴 ∨ 𝐵)}, and a theorem query, 𝛼 =


𝐵, that we are trying to prove. Using these as input to the Resolution Theorem
Prover produces:

Sentences Clause 1 Clause 2 Resolvents New


1. A ∅

2
2. ~A, B 1 2 {B} {B}
3. ~B 1 3 {} {B}
2 3 {~A} {B, ~A}
Add New to Sentences and repeat
4. B ∅
5. ~A 1 2 {B} {B}
1 3 {} {B}
1 4 {} {B}
1 5 {∅}
Theorem proved

2) The example form the function header has a knowledge base, 𝐾𝐵 = {(¬1 ∨ 2 ∨
3 ∨ 4 ) ∧ (¬2) ∧ (¬3) ∧ (1)}, and a theorem query, 𝛼 = 4, that we are trying to
prove. This example is longer but it matched my verification throughout the entire
process. Using these as input to the Resolution Theorem Prover produces
(simplified by only showing steps that will add to the sentences structure):

Sentences Clause Clause Resolvents New


1 2
1. ~1,2,3,4 ∅
2. ~2 1 2 {~1,3,4} {{~1,3,4}}
3. ~3 1 3 {~1,2,4} {{~1,3,4},{~1,2,4}}
4. 1 1 4 {2,3,4} {{~1,3,4},{~1,2,4},{2,3,4}}
5. ~4 1 5 {~1,2,3} {{~1,3,4},{~1,2,4},{2,3,4},{~1,2,3}}
Add New to Sentences and repeat
6. ~1,3,4 2 7 {~1,4} {{~1,4}}
7. ~1,2,4 2 8 {3,4} {{~1,4},{3,4}}
8. 2,3,4 2 9 {~1,3} {{~1,4},{3,4},{~1,3}}
9. ~1,2,3 3 8 {2,4} {{~1,4},{3,4},{~1,3},{2,4}}
3 9 {~1,2} {{~1,4},{3,4},{~1,3},{2,4},{~1,2}}
4 9 {2,3} {{~1,4},{3,4},{~1,3},{2,4},{~1,2},{2,3}}
Add New to Sentences and repeat
10. ~1,4 10 4 {4} {{4}}
11. 3,4 10 5 {~1} {{4},{~1}}
12. ~1,3 11 5 {3} {{4},{~1},{3}}
13. 2,4 13 5 {2} {{4},{~1},{3},{2}}
14. ~1,2
15. 2,3
Add New to Sentences and repeat
16. 4 2 19 {∅} {∅}
17. ~1
18. 3
19. 2

3
Theorem proved

3) A another example would be a set of clauses that doesn’t return the empty set.
𝐾𝐵 = {1 ∧ 2 ∧ 3 ∧ 4 ∧ 5 ∧ 6 ∧ 7 ∧ 8}, and a theorem query, 𝛼 = ¬1 ∨ 9. This
can’t be proven, so it should return the set of clauses as a result of resolution. The
result again matched my programs output.
Sentences Clause Clause Resolvents New
1 2
1. 1 ∅
2. 2 No resolvents are returned from any clause
combination, return sentences.
3. 3
4. 4
5. 5
6. 6
7. 7
8. 8
9. ~9

4. Data and Analysis

I tried to explore how the theorem size effected unsolvable knowledge base sizes. Most
of the examples that only increased the size of the returned resolution by how many the
number of disjuncts that I added to the theorem conjunct.

I have some incremental tests that are hard coded in the CS4300_Testing file. Test2
returns resolvents that didn’t reach the empty clause. The following tests add a new
clause to the unsolvable example before it.

DP(1).clauses = [-1,2,3,4];
DP(2).clauses = [-2];
DP(3).clauses = [-3];
DP(4).clauses = [1];
DP(5).clauses = [-1,2,3,5];
DP(6).clauses = [-1,2,3,6];
DP(7).clauses = [-1,2,3,8];
DP(8).clauses = [-1,2,3,9];
thm(1).clauses = [-1,2,3,7];
vars = [1,2,3,4,5,6,7,8,9];
test6 = CS4300_RTP(DP,thm,vars);

Tests 4,5, & 6 each added a new clause resulting the last test which is listed above. The
increase in clauses is as follows:
• test3: 22

4
• test4: 28
• test5: 36
• test6: 44

5. Interpretation

I did try several approaches to grow the clauses at a consistent rate but the above was the only
cases that showed expected results.
From the different experiments that I tried, the number of resulting clauses depends on the
number of complementary literals that a clauses have. So either having several clauses with
overlap or long disjuncts with many complementary literals. As for finding a ratio between the
input and the output, I wasn’t able to find one.

6. Critique

I noticed a pattern during verification on the longer example that there could probably be an
optimization while comparing every i and j clause. I skipped comparing the clauses where clause
i and j have already been resolved. Since my clauses structure is stable it was easier to notice. If
you keep track of which clauses have been resolved this could save you time.

My technique for gathering varying clause lengths could have been done better.

7. Log

I spent about 10 hours coding the assignment.


I spent about 4 hours on this write up.
14 hours in total

You might also like