Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 66aa7b0

Browse files
committed
logic.py cleanup and minor bugfixing: pretty much done now.
1 parent 31204b3 commit 66aa7b0

File tree

1 file changed

+38
-47
lines changed

1 file changed

+38
-47
lines changed

logic.py

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def tell(self, sentence):
7979
self.clauses.extend(conjuncts(to_cnf(sentence)))
8080

8181
def ask_generator(self, query):
82-
"Yield the empty substitution if KB implies query."
82+
"Yield the empty substitution if KB implies query; else nothing."
8383
if tt_entails(Expr('&', *self.clauses), query):
8484
yield {}
8585

@@ -316,18 +316,23 @@ def parse_definite_clause(s):
316316
#______________________________________________________________________________
317317

318318
def tt_entails(kb, alpha):
319-
"""Does kb entail the sentence alpha? Use truth tables. [Fig. 7.10]
319+
"""Does kb entail the sentence alpha? Use truth tables. For propositional
320+
kb's and sentences. [Fig. 7.10]
320321
>>> tt_entails(expr('P & Q'), expr('Q'))
321322
True
322323
"""
324+
assert not variables(alpha)
323325
return tt_check_all(kb, alpha, prop_symbols(kb & alpha), {})
324326

325327
def tt_check_all(kb, alpha, symbols, model):
326328
"Auxiliary routine to implement tt_entails."
327329
if not symbols:
328-
if pl_true(kb, model): return pl_true(alpha, model)
329-
else: return True
330-
assert result is not None
330+
if pl_true(kb, model):
331+
result = pl_true(alpha, model)
332+
assert result in (True, False)
333+
return result
334+
else:
335+
return True
331336
else:
332337
P, rest = symbols[0], symbols[1:]
333338
return (tt_check_all(kb, alpha, rest, extend(model, P, True)) and
@@ -344,7 +349,8 @@ def prop_symbols(x):
344349
for symbol in prop_symbols(arg)))
345350

346351
def tt_true(alpha):
347-
"""Is the sentence alpha a tautology? (alpha will be coerced to an expr.)
352+
"""Is the propositional sentence alpha a tautology? (alpha will be
353+
coerced to an expr.)
348354
>>> tt_true(expr("(P >> Q) <=> (~P | Q)"))
349355
True
350356
"""
@@ -472,20 +478,19 @@ def distribute_and_over_or(s):
472478
"""
473479
if s.op == '|':
474480
s = NaryExpr('|', *s.args)
481+
if s.op != '|':
482+
return distribute_and_over_or(s)
475483
if len(s.args) == 0:
476484
return FALSE
477485
if len(s.args) == 1:
478486
return distribute_and_over_or(s.args[0])
479487
conj = find_if((lambda d: d.op == '&'), s.args)
480488
if not conj:
481-
return NaryExpr(s.op, *s.args)
489+
return s
482490
others = [a for a in s.args if a is not conj]
483-
if len(others) == 1:
484-
rest = others[0]
485-
else:
486-
rest = NaryExpr('|', *others)
487-
return NaryExpr('&', *map(distribute_and_over_or,
488-
[(c|rest) for c in conj.args]))
491+
rest = NaryExpr('|', *others)
492+
return NaryExpr('&', *[distribute_and_over_or(c|rest)
493+
for c in conj.args])
489494
elif s.op == '&':
490495
return NaryExpr('&', *map(distribute_and_over_or, s.args))
491496
else:
@@ -584,7 +589,7 @@ def tell(self, sentence):
584589
self.clauses.append(sentence)
585590

586591
def ask_generator(self, query):
587-
"Yield the empty substitution if KB implies query."
592+
"Yield the empty substitution if KB implies query; else nothing."
588593
if pl_fc_entails(self.clauses, query):
589594
yield {}
590595

@@ -794,10 +799,10 @@ def unify(x, y, s):
794799
return unify_var(y, x, s)
795800
elif isinstance(x, Expr) and isinstance(y, Expr):
796801
return unify(x.args, y.args, unify(x.op, y.op, s))
797-
elif isinstance(x, str) or isinstance(y, str) or not x or not y:
798-
# orig. return if_(x == y, s, None) but we already know x != y
802+
elif isinstance(x, str) or isinstance(y, str):
799803
return None
800-
elif issequence(x) and issequence(y) and len(x) == len(y) and x:
804+
elif issequence(x) and issequence(y) and len(x) == len(y):
805+
if not x: return s
801806
return unify(x[1:], y[1:], unify(x[0], y[0], s))
802807
else:
803808
return None
@@ -833,7 +838,6 @@ def occur_check(var, x, s):
833838
def extend(s, var, val):
834839
"""Copy the substitution s and extend it by setting var to val;
835840
return copy.
836-
837841
>>> ppsubst(extend({x: 1}, y, 2))
838842
{x: 1, y: 2}
839843
"""
@@ -859,7 +863,7 @@ def subst(s, x):
859863

860864
def fol_fc_ask(KB, alpha):
861865
"""Inefficient forward chaining for first-order logic. [Fig. 9.3]
862-
KB is an FOLHornKB and alpha must be an atomic sentence."""
866+
KB is a FolKB and alpha must be an atomic sentence."""
863867
while True:
864868
new = {}
865869
for r in KB.clauses:
@@ -883,20 +887,19 @@ def standardize_apart(sentence, dic=None):
883887
if sentence in dic:
884888
return dic[sentence]
885889
else:
886-
standardize_apart.counter += 1
887-
v = Expr('v_%d' % standardize_apart.counter)
890+
v = Expr('v_%d' % standardize_apart.counter.next())
888891
dic[sentence] = v
889892
return v
890893
else:
891894
return Expr(sentence.op,
892895
*[standardize_apart(a, dic) for a in sentence.args])
893896

894-
standardize_apart.counter = 0
897+
standardize_apart.counter = itertools.count()
895898

896899
#______________________________________________________________________________
897900

898-
class FolKB (KB):
899-
"""A knowledge base consisting of first-order definite clauses
901+
class FolKB(KB):
902+
"""A knowledge base consisting of first-order definite clauses.
900903
>>> kb0 = FolKB([expr('Farmer(Mac)'), expr('Rabbit(Pete)'),
901904
... expr('(Rabbit(r) & Farmer(f)) ==> Hates(f, r)')])
902905
>>> kb0.tell(expr('Rabbit(Flopsie)'))
@@ -906,7 +909,6 @@ class FolKB (KB):
906909
>>> kb0.ask(expr('Wife(Pete, x)'))
907910
False
908911
"""
909-
910912
def __init__(self, initial_clauses=[]):
911913
self.clauses = [] # inefficient: no indexing
912914
for clause in initial_clauses:
@@ -924,15 +926,13 @@ def ask_generator(self, query):
924926
def retract(self, sentence):
925927
self.clauses.remove(sentence)
926928

927-
def test_ask(q, kb=None):
928-
e = expr(q)
929-
vars = variables(e)
930-
ans = fol_bc_ask(kb or test_kb, [e])
931-
res = []
932-
for a in ans:
933-
res.append(pretty(dict([(x, v) for (x, v) in a.items() if x in vars])))
934-
res.sort(key=str)
935-
return res
929+
def test_ask(query, kb=None):
930+
q = expr(query)
931+
vars = variables(q)
932+
answers = fol_bc_ask(kb or test_kb, [q])
933+
return sorted([pretty(dict((x, v) for x, v in a.items() if x in vars))
934+
for a in answers],
935+
key=repr)
936936

937937
test_kb = FolKB(
938938
map(expr, ['Farmer(Mac)',
@@ -991,7 +991,7 @@ def fol_bc_ask(KB, goals, theta={}):
991991
for ans in fol_bc_ask(KB, new_goals, subst_compose(theta1, theta)):
992992
yield ans
993993

994-
def subst_compose (s1, s2):
994+
def subst_compose(s1, s2):
995995
"""Return the substitution which is equivalent to applying s2 to
996996
the result of applying s1 to an expression.
997997
@@ -1021,18 +1021,9 @@ def subst_compose (s1, s2):
10211021
>>> subst(subst_compose(s2, s1), p) == subst(s1, subst(s2, p))
10221022
True
10231023
"""
1024-
sc = {}
1025-
for x, v in s1.items():
1026-
if s2.has_key(v):
1027-
w = s2[v]
1028-
sc[x] = w # x -> v -> w
1029-
else:
1030-
sc[x] = v
1031-
for x, v in s2.items():
1032-
if not (s1.has_key(x)):
1033-
sc[x] = v
1034-
# otherwise s1[x] preemptys s2[x]
1035-
return sc
1024+
result = dict((x, s2.get(v, v)) for x, v in s1.items())
1025+
result.update((x, v) for x, v in s2.items() if x not in s1)
1026+
return result
10361027

10371028
#______________________________________________________________________________
10381029

0 commit comments

Comments
 (0)