@@ -287,6 +287,7 @@ def is_literal(s):
287
287
>>> is_literal(expr('x')) # XXX I guess this is intended?
288
288
True
289
289
"""
290
+ #XXX return is_symbol(s.op) or (s.op == '~' and is_literal(s.args[0]))
290
291
return is_symbol (s .op ) or (s .op == '~' and is_symbol (s .args [0 ].op ))
291
292
292
293
def literals (s ):
@@ -372,7 +373,7 @@ def tt_check_all(kb, alpha, symbols, model):
372
373
if not symbols :
373
374
if pl_true (kb , model ): return pl_true (alpha , model )
374
375
else : return True
375
- assert result != None
376
+ assert result is not None
376
377
else :
377
378
P , rest = symbols [0 ], symbols [1 :]
378
379
return (tt_check_all (kb , alpha , rest , extend (model , P , True )) and
@@ -385,11 +386,8 @@ def prop_symbols(x):
385
386
elif is_prop_symbol (x .op ):
386
387
return [x ]
387
388
else :
388
- s = set (())
389
- for arg in x .args :
390
- for symbol in prop_symbols (arg ):
391
- s .add (symbol )
392
- return list (s )
389
+ return list (set (symbol for arg in x .args
390
+ for symbol in prop_symbols (arg )))
393
391
394
392
def tt_true (alpha ):
395
393
"""Is the sentence alpha a tautology? (alpha will be coerced to an expr.)
@@ -412,31 +410,31 @@ def pl_true(exp, model={}):
412
410
return model .get (exp )
413
411
elif op == '~' :
414
412
p = pl_true (args [0 ], model )
415
- if p == None : return None
413
+ if p is None : return None
416
414
else : return not p
417
415
elif op == '|' :
418
416
result = False
419
417
for arg in args :
420
418
p = pl_true (arg , model )
421
- if p == True : return True
422
- if p == None : result = None
419
+ if p is True : return True
420
+ if p is None : result = None
423
421
return result
424
422
elif op == '&' :
425
423
result = True
426
424
for arg in args :
427
425
p = pl_true (arg , model )
428
- if p == False : return False
429
- if p == None : result = None
426
+ if p is False : return False
427
+ if p is None : result = None
430
428
return result
431
429
p , q = args
432
430
if op == '>>' :
433
431
return pl_true (~ p | q , model )
434
432
elif op == '<<' :
435
433
return pl_true (p | ~ q , model )
436
434
pt = pl_true (p , model )
437
- if pt == None : return None
435
+ if pt is None : return None
438
436
qt = pl_true (q , model )
439
- if qt == None : return None
437
+ if qt is None : return None
440
438
if op == '<=>' :
441
439
return pt == qt
442
440
elif op == '^' :
@@ -589,7 +587,7 @@ def disjuncts(s):
589
587
#______________________________________________________________________________
590
588
591
589
def pl_resolution (KB , alpha ):
592
- "Propositional Logic Resolution : say if alpha follows from KB. [Fig. 7.12]"
590
+ "Propositional-logic resolution : say if alpha follows from KB. [Fig. 7.12]"
593
591
clauses = KB .clauses + conjuncts (to_cnf (~ alpha ))
594
592
new = set ()
595
593
while True :
@@ -623,19 +621,18 @@ def pl_resolve(ci, cj):
623
621
#______________________________________________________________________________
624
622
625
623
class PropHornKB (PropKB ):
626
- "A KB of Propositional Horn clauses."
624
+ "A KB of propositional Horn clauses."
627
625
628
626
def tell (self , sentence ):
629
- "Add a Horn Clauses to this KB."
627
+ "Add a Horn clause to this KB."
630
628
op = sentence .op
631
- assert op == '>>' or is_prop_symbol (op ), "Must be Horn Clause"
629
+ assert op == '>>' or is_prop_symbol (op ), "Must be Horn clause" # XXX use is_definite_clause?
632
630
self .clauses .append (sentence )
633
631
634
632
def ask_generator (self , query ):
635
- "Yield the empty substitution if KB implies query; else False"
636
- if not pl_fc_entails (self .clauses , query ):
637
- return
638
- yield {}
633
+ "Yield the empty substitution if KB implies query."
634
+ if pl_fc_entails (self .clauses , query ):
635
+ yield {}
639
636
640
637
def retract (self , sentence ):
641
638
"Remove the sentence's clauses from the KB"
@@ -644,16 +641,17 @@ def retract(self, sentence):
644
641
self .clauses .remove (c )
645
642
646
643
def clauses_with_premise (self , p ):
647
- """The list of clauses in KB that have p in the premise.
644
+ """Return a list of the clauses in KB that have p in their premise.
648
645
This could be cached away for O(1) speed, but we'll recompute it."""
649
646
return [c for c in self .clauses
650
- if c .op == '>>' and p in conjuncts (c .args [0 ])]
647
+ if c .op == '>>' and p in conjuncts (c .args [0 ])] # XXX use parse_definite_clause?
651
648
652
649
def pl_fc_entails (KB , q ):
653
650
"""Use forward chaining to see if a HornKB entails symbol q. [Fig. 7.14]
654
651
>>> pl_fc_entails(Fig[7,15], expr('Q'))
655
652
True
656
653
"""
654
+ # XXX use parse_definite_clause?
657
655
count = dict ([(c , len (conjuncts (c .args [0 ]))) for c in KB .clauses
658
656
if c .op == '>>' ])
659
657
inferred = DefaultDict (False )
@@ -714,7 +712,7 @@ def dpll(clauses, symbols, model):
714
712
P , value = find_unit_clause (clauses , model )
715
713
if P :
716
714
return dpll (clauses , removeall (P , symbols ), extend (model , P , value ))
717
- P = symbols .pop ()
715
+ P = symbols .pop () # XXX is this side-effect more global than desired?
718
716
return (dpll (clauses , symbols , extend (model , P , True )) or
719
717
dpll (clauses , symbols , extend (model , P , False )))
720
718
@@ -784,8 +782,9 @@ def WalkSAT(clauses, p=0.5, max_flips=10000):
784
782
raise NotImplementedError
785
783
model [sym ] = not model [sym ]
786
784
787
-
785
+ #______________________________________________________________________________
788
786
# PL-Wumpus-Agent [Fig. 7.19]
787
+
789
788
class PLWumpusAgent (agents .Agent ):
790
789
"An agent for the wumpus world that does logical inference. [Fig. 7.19]" ""
791
790
def __init__ (self ):
@@ -807,7 +806,7 @@ def program(percept):
807
806
if KB .ask ('~P_%d,%d & ~W_%d,%d' % (i , j , i , j )) != False :
808
807
raise NotImplementedError
809
808
KB .ask ('~P_%d,%d | ~W_%d,%d' % (i , j , i , j )) != False
810
- if action == None :
809
+ if action is None :
811
810
action = random .choice (['Forward' , 'Right' , 'Left' ])
812
811
return action
813
812
@@ -831,7 +830,7 @@ def unify(x, y, s):
831
830
>>> ppsubst(unify(x + y, y + C, {}))
832
831
{x: y, y: C}
833
832
"""
834
- if s == None :
833
+ if s is None :
835
834
return None
836
835
elif x == y :
837
836
return s
@@ -865,30 +864,19 @@ def unify_var(var, x, s):
865
864
def occur_check (var , x , s ):
866
865
"""Return true if variable var occurs anywhere in x
867
866
(or in subst(s, x), if s has a binding for x)."""
868
-
869
867
if var == x :
870
868
return True
871
869
elif is_variable (x ) and s .has_key (x ):
872
- return occur_check (var , s [x ], s ) # fixed
873
- # What else might x be? an Expr, a list, a string?
870
+ return occur_check (var , s [x ], s )
874
871
elif isinstance (x , Expr ):
875
- # Compare operator and arguments
876
872
return (occur_check (var , x .op , s ) or
877
873
occur_check (var , x .args , s ))
878
- elif isinstance (x , list ) and x != []:
879
- # Compare first and rest
880
- return (occur_check (var , x [0 ], s ) or
881
- occur_check (var , x [1 :], s ))
874
+ elif isinstance (x , list ):
875
+ return any (occur_check (var , element , s )
876
+ for element in x )
882
877
else :
883
- # A variable cannot occur in a string
878
+ assert isinstance ( x , ( str , int )), x
884
879
return False
885
-
886
- #elif isinstance(x, Expr):
887
- # return var.op == x.op or occur_check(var, x.args)
888
- #elif not isinstance(x, str) and issequence(x):
889
- # for xi in x:
890
- # if occur_check(var, xi): return True
891
- #return False
892
880
893
881
def extend (s , var , val ):
894
882
"""Copy the substitution s and extend it by setting var to val;
0 commit comments