-
Notifications
You must be signed in to change notification settings - Fork 0
/
infer.py
81 lines (64 loc) · 1.79 KB
/
infer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import copy
def toTuple(clause):
unitSet = set()
for unit in clause:
unitSet.add(unit)
return tuple(unitSet)
def resolve(c1, c2):
"""A resolution algorithm for propositional logic.
Return all possible clauses resolved from c1 and c2
c1: a tuple of units
c2: a tuple of units
"""
res = set()
c1Set = set(c1)
for unit in c2:
unit_copy = ~copy.deepcopy(unit)
c1List = list(c1)
if unit_copy in c1Set:
c1List.remove(unit_copy)
# compute resolvent
resolvent = set(c1List)
c2ResSet = set([u for u in c2 if not u == unit])
resolvent = resolvent.union(c2ResSet)
res.add(tuple(resolvent))
return res
def resolution(kb, a):
"""A resolution algorithm for propositional logic.
Return if kb entails a
Each pair that contains complementary literals is resolved to produce a new clause.
The new clause is added to the knowledge base if not already present.
The algorithm halts
- when there are no new claused that can be added.
KB doesn't entail a
- or when two clauses resolve to yield the empty clause
KB entails a
"""
clauses = kb.clauses().union((~copy.deepcopy(a)).cnf())
resolvedPairs = set()
new = set()
while(True):
for c1 in clauses:
for c2 in clauses:
if c1 is not c2:
if not kb.resolve(c1,c2) \
and tuple([c1, c2]) not in resolvedPairs\
and tuple([c1, c2]) not in resolvedPairs :
resolvents = resolve(c1, c2)
if () in resolvents:
return True
if kb.has(c1) and kb.has(c2):
for r in resolvents:
kb.add(r)
kb.markResolved(c1,c2)
else:
resolvedPairs.add(tuple([c1, c2]))
new = new.union(resolvents)
isNewSubset = True
for c in new:
if not c in clauses:
isNewSubset = False
if isNewSubset:
return False
else:
clauses = clauses.union(new)