1
2
3
4
5
6
7
8 from nltk.sem.logic import *
9
10 from api import Prover, ProverCommand
11
12 """
13 Module for a tableau-based First Order theorem prover.
14 """
15
17
38
41 self.sets = tuple(set() for i in range(17))
42
44 new_agenda = Agenda()
45 set_list = [s.copy() for s in self.sets]
46
47 new_allExs = set()
48 for allEx in set_list[Categories.ALL]:
49 new_allEx = AllExpression(allEx.variable, allEx.term)
50 try:
51 new_allEx._used_vars = set(used for used in allEx._used_vars)
52 except AttributeError:
53 new_allEx._used_vars = set()
54 new_allExs.add(new_allEx)
55 set_list[Categories.ALL] = new_allExs
56
57 set_list[Categories.N_EQ] = set(NegatedExpression(n_eq.term)
58 for n_eq in set_list[Categories.N_EQ])
59
60 new_agenda.sets = tuple(set_list)
61 return new_agenda
62
64 return self.sets[index]
65
66 - def put(self, expression):
67 if isinstance(expression, AllExpression):
68 ex_to_add = AllExpression(expression.variable, expression.term)
69 try:
70 ex_to_add._used_vars = set(used for used in expression._used_vars)
71 except AttributeError:
72 ex_to_add._used_vars = set()
73 else:
74 ex_to_add = expression
75 self.sets[self._categorize_expression(ex_to_add)].add(ex_to_add)
76
80
87
89 """ Pop the first expression that appears in the agenda """
90 for i in range(len(self.sets)):
91 if self.sets[i]:
92 if i in [Categories.N_EQ, Categories.ALL]:
93 for ex in self.sets[i]:
94 try:
95 if not ex._exhausted:
96 self.sets[i].remove(ex)
97 return(ex, i)
98 except AttributeError:
99 self.sets[i].remove(ex)
100 return(ex, i)
101 else:
102 return (self.sets[i].pop(), i)
103 return (None, None)
104
105
107 self.sets = tuple(set(ex.replace(old.variable, new) for ex in s) for s in self.sets)
108
112
116
138
162
164 (current, category) = agenda.pop_first()
165
166
167 if not current:
168 debug_line('AGENDA EMPTY', (debug[0], debug[1]+1))
169 return False
170
171 proof_method = { Categories.ATOM: _attempt_proof_atom,
172 Categories.N_ATOM: _attempt_proof_n_atom,
173 Categories.N_EQ: _attempt_proof_n_eq,
174 Categories.D_NEG: _attempt_proof_d_neg,
175 Categories.N_ALL: _attempt_proof_n_all,
176 Categories.N_EXISTS: _attempt_proof_n_some,
177 Categories.AND: _attempt_proof_and,
178 Categories.N_OR: _attempt_proof_n_or,
179 Categories.N_IMP: _attempt_proof_n_imp,
180 Categories.OR: _attempt_proof_or,
181 Categories.IMP: _attempt_proof_imp,
182 Categories.N_AND: _attempt_proof_n_and,
183 Categories.IFF: _attempt_proof_iff,
184 Categories.N_IFF: _attempt_proof_n_iff,
185 Categories.EQ: _attempt_proof_eq,
186 Categories.EXISTS: _attempt_proof_some,
187 Categories.ALL: _attempt_proof_all,
188 }[category]
189
190 debug_line(current, debug)
191 return proof_method(current, agenda, accessible_vars, atoms, debug)
192
194 if debug[0]:
195 additional = ''
196 if isinstance(data, AllExpression):
197 try:
198 additional += ': %s' % str([ve.variable.name for ve in data._used_vars])
199 except AttributeError:
200 additional += ': []'
201
202 if isinstance(data, Expression):
203 data = data
204
205 print '%s%s%s' % (' '*debug[1], data, additional)
206
217
228
230
231
232
233 if current.term.first == current.term.second:
234 debug_line('CLOSED', (debug[0], debug[1]+1))
235 return True
236
237 agenda[Categories.N_EQ].add(current)
238 current._exhausted = True
239 return _attempt_proof(agenda, accessible_vars|set([current.term.first, current.term.second]), atoms, (debug[0], debug[1]+1))
240
244
248
252
257
259 agenda.put(-current.term.first)
260 agenda.put(-current.term.second)
261 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
262
264 agenda.put(current.term.first)
265 agenda.put(-current.term.second)
266 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
267
274
281
288
290 new_agenda = agenda.clone()
291 agenda.put(current.first)
292 agenda.put(current.second)
293 new_agenda.put(-current.first)
294 new_agenda.put(-current.second)
295 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1)) and \
296 _attempt_proof(new_agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
297
299 new_agenda = agenda.clone()
300 agenda.put(current.term.first)
301 agenda.put(-current.term.second)
302 new_agenda.put(-current.term.first)
303 new_agenda.put(current.term.second)
304 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1)) and \
305 _attempt_proof(new_agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
306
317
323
325 try:
326 current._used_vars
327 except AttributeError:
328 current._used_vars = set()
329
330
331 if accessible_vars:
332
333 bv_available = accessible_vars - current._used_vars
334
335 if bv_available:
336 variable_to_use = list(bv_available)[0]
337 debug_line('--> Using \'%s\'' % variable_to_use, (debug[0], debug[1]+2))
338 current._used_vars |= set([variable_to_use])
339 agenda.put(current.term.replace(current.variable, variable_to_use))
340 agenda[Categories.ALL].add(current)
341 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
342
343 else:
344
345 debug_line('--> Variables Exhausted', (debug[0], debug[1]+2))
346 current._exhausted = True
347 agenda[Categories.ALL].add(current)
348 return _attempt_proof(agenda, accessible_vars, atoms, (debug[0], debug[1]+1))
349
350 else:
351 new_unique_variable = IndividualVariableExpression(unique_variable())
352 debug_line('--> Using \'%s\'' % new_unique_variable, (debug[0], debug[1]+2))
353 current._used_vars |= set([new_unique_variable])
354 agenda.put(current.term.replace(current.variable, new_unique_variable))
355 agenda[Categories.ALL].add(current)
356 agenda.mark_alls_fresh()
357 return _attempt_proof(agenda, accessible_vars|set([new_unique_variable]), atoms, (debug[0], debug[1]+1))
358
359
378
380 tableau_test(r'man(x)')
381 tableau_test(r'(man(x) -> man(x))')
382 tableau_test(r'(man(x) -> --man(x))')
383 tableau_test(r'-(man(x) and -man(x))')
384 tableau_test(r'(man(x) or -man(x))')
385 tableau_test(r'(man(x) -> man(x))')
386 tableau_test(r'-(man(x) and -man(x))')
387 tableau_test(r'(man(x) or -man(x))')
388 tableau_test(r'(man(x) -> man(x))')
389 tableau_test(r'(man(x) iff man(x))')
390 tableau_test(r'-(man(x) iff -man(x))')
391 tableau_test('all x.man(x)')
392 tableau_test('all x.all y.((x = y) -> (y = x))')
393 tableau_test('all x.all y.all z.(((x = y) & (y = z)) -> (x = z))')
394 tableau_test('-all x.some y.F(x,y) & some x.all y.(-F(x,y))')
395 tableau_test('some x.all y.sees(x,y)')
396
397 p1 = LogicParser().parse(r'all x.(man(x) -> mortal(x))')
398 p2 = LogicParser().parse(r'man(Socrates)')
399 c = LogicParser().parse(r'mortal(Socrates)')
400 print '%s, %s |- %s: %s' % (p1, p2, c, Tableau(c, [p1,p2]).prove())
401
402 p1 = LogicParser().parse(r'all x.(man(x) -> walks(x))')
403 p2 = LogicParser().parse(r'man(John)')
404 c = LogicParser().parse(r'some y.walks(y)')
405 print '%s, %s |- %s: %s' % (p1, p2, c, Tableau(c, [p1,p2]).prove())
406
407 p = LogicParser().parse(r'((x = y) & walks(y))')
408 c = LogicParser().parse(r'walks(x)')
409 print '%s |- %s: %s' % (p, c, Tableau(c, [p]).prove())
410
411 p = LogicParser().parse(r'((x = y) & ((y = z) & (z = w)))')
412 c = LogicParser().parse(r'(x = w)')
413 print '%s |- %s: %s' % (p, c, Tableau(c, [p]).prove())
414
415 p = LogicParser().parse(r'some e1.some e2.(believe(e1,john,e2) & walk(e2,mary))')
416 c = LogicParser().parse(r'some e0.walk(e0,mary)')
417 print '%s |- %s: %s' % (p, c, Tableau(c, [p]).prove())
418
419 c = LogicParser().parse(r'(exists x.exists z3.((x = Mary) & ((z3 = John) & sees(z3,x))) <-> exists x.exists z4.((x = John) & ((z4 = Mary) & sees(x,z4))))')
420 print '|- %s: %s' % (c, Tableau(c, []).prove())
421
422
423
424
425
430
431 if __name__ == '__main__':
432 testTableau()
433