Package spade :: Module logic
[hide private]
[frames] | no frames]

Module logic

source code

Representations and Inference for Logic (Chapters 7-10)

Covers both Propositional and First-Order Logic. First we have four
important data types:

    KB            Abstract class holds a knowledge base of logical expressions
    KB_Agent      Abstract class subclasses agents.Agent
    Expr          A logical expression
    substitution  Implemented as a dictionary of var:value pairs, {x:1, y:x}

Be careful: some functions take an Expr as argument, and some take a KB.
Then we implement various functions for doing logical inference:

    pl_true          Evaluate a propositional logical sentence in a model
    tt_entails       Say if a statement is entailed by a KB
    pl_resolution    Do resolution on propositional sentences
    dpll_satisfiable See if a propositional sentence is satisfiable
    WalkSAT          (not yet implemented)

And a few other functions:

    to_cnf           Convert to conjunctive normal form
    unify            Do unification of two FOL sentences
    diff, simp       Symbolic differentiation and simplification             

Classes [hide private]
  KB
A Knowledge base to which you can tell and ask sentences.
  PropKB
A KB for Propositional Logic.
  Expr
A symbolic mathematical expression.
  PropHornKB
A KB of Propositional Horn clauses.
  FolKB
A knowledge base consisting of first-order definite clauses >>> kb0 = FolKB([expr('Farmer(Mac)'), expr('Rabbit(Pete)'), ...
  logicTest
### PropKB >>> kb = PropKB() >>> kb.tell(A & B) >>> kb.tell(B >> C) >>> kb.ask(C) ## The result {} means true, with no substitutions {} >>> kb.ask(P) False >>> kb.retract(B) >>> kb.ask(C) False
Functions [hide private]
 
every(predicate, seq)
True if every element of seq satisfies predicate.
source code
 
isnumber(x)
Is x a number? We say it is if it has a __int__ method.
source code
 
issequence(x)
Is x a sequence? We say it is if it has a __getitem__ method.
source code
 
num_or_str(x)
The argument is a string; convert to a number if possible, or strip it.
source code
 
expr(s)
Create an Expr representing a logic expression by parsing the input string.
source code
 
is_symbol(s)
A string s is a symbol if it starts with an alphabetic char.
source code
 
is_var_symbol(s)
A logic variable symbol is an initial-lowercase string.
source code
 
is_prop_symbol(s)
A proposition logic symbol is an initial-uppercase string other than TRUE or FALSE.
source code
 
is_positive(s)
s is an unnegated logical expression >>> is_positive(expr('F(A, B)')) True >>> is_positive(expr('~F(A, B)')) False
source code
 
is_negative(s)
s is a negated logical expression >>> is_negative(expr('F(A, B)')) False >>> is_negative(expr('~F(A, B)')) True
source code
 
is_literal(s)
s is a FOL literal >>> is_literal(expr('~F(A, B)')) True >>> is_literal(expr('F(A, B)')) True >>> is_literal(expr('F(A, B) & G(B, C)')) False
source code
 
literals(s)
returns the list of literals of logical expression s.
source code
 
variables(s)
returns the set of variables in logical expression s.
source code
 
is_definite_clause(s)
returns True for exprs s of the form A & B & ...
source code
 
tt_entails(kb, alpha)
Use truth tables to determine if KB entails sentence alpha.
source code
 
tt_check_all(kb, alpha, symbols, model)
Auxiliary routine to implement tt_entails.
source code
 
prop_symbols(x)
Return a list of all propositional symbols in x.
source code
 
tt_true(alpha)
Is the sentence alpha a tautology? (alpha will be coerced to an expr.) >>> tt_true(expr("(P >> Q) <=> (~P | Q)")) True
source code
 
pl_true(exp, model={})
Return True if the propositional logic expression is true in the model, and False if it is false.
source code
 
to_cnf(s)
Convert a propositional logical sentence s to conjunctive normal form.
source code
 
eliminate_implications(s)
Change >>, <<, and <=> into &, |, and ~.
source code
 
move_not_inwards(s)
Rewrite sentence s by moving negation sign inward.
source code
 
distribute_and_over_or(s)
Given a sentence s consisting of conjunctions and disjunctions of literals, return an equivalent sentence in CNF.
source code
 
NaryExpr(op, *args)
Create an Expr, but with an nary, associative op, so we can promote nested instances of the same op up to the top level.
source code
 
conjuncts(s)
Return a list of the conjuncts in the sentence s.
source code
 
disjuncts(s)
Return a list of the disjuncts in the sentence s.
source code
 
pl_resolution(KB, alpha)
Propositional Logic Resolution: say if alpha follows from KB.
source code
 
pl_resolve(ci, cj)
Return all clauses that can be obtained by resolving clauses ci and cj.
source code
 
pl_fc_entails(KB, q)
Use forward chaining to see if a HornKB entails symbol q.
source code
 
dpll_satisfiable(s)
Check satisfiability of a propositional sentence.
source code
 
dpll(clauses, symbols, model)
See if the clauses are true in a partial model.
source code
 
find_pure_symbol(symbols, unknown_clauses)
Find a symbol and its value if it appears only as a positive literal (or only as a negative) in clauses.
source code
 
find_unit_clause(clauses, model)
A unit clause has only 1 variable that is not bound in the model.
source code
 
literal_symbol(literal)
The symbol in this literal (without the negation).
source code
 
WalkSAT(clauses, p=0.5, max_flips=10000) source code
 
update_position(x, y, orientation, action) source code
 
unify(x, y, s)
Unify expressions x,y with substitution s; return a substitution that would make x,y equal, or None if x,y can not unify.
source code
 
is_variable(x)
A variable is an Expr with no args and a lowercase symbol as the op.
source code
 
unify_var(var, x, s) source code
 
occur_check(var, x, s)
Return true if variable var occurs anywhere in x (or in subst(s, x), if s has a binding for x).
source code
 
extend(s, var, val)
Copy the substitution s and extend it by setting var to val; return copy.
source code
 
subst(s, x)
Substitute the substitution s into the expression x.
source code
 
fol_fc_ask(KB, alpha)
Inefficient forward chaining for first-order logic.
source code
 
standardize_apart(sentence, dic={})
Replace all the variables in sentence with new variables.
source code
 
test_ask(q) source code
 
fol_bc_ask(KB, goals, theta={})
A simple backward-chaining algorithm for first-order logic.
source code
 
subst_compose(s1, s2)
Return the substitution which is equivalent to applying s2 to the result of applying s1 to an expression.
source code
 
diff(y, x)
Return the symbolic derivative, dy/dx, as an Expr.
source code
 
simp(x) source code
 
d(y, x)
Differentiate and then simplify.
source code
 
pretty(x) source code
 
pretty_dict(d)
Print the dictionary d.
source code
 
pretty_set(s)
Print the set s.
source code
 
pp(x) source code
 
ppsubst(s)
Pretty-print substitution s
source code
 
ppdict(d) source code
 
ppset(s) source code
Variables [hide private]
  _NaryExprTable = {'&': TRUE, '*': 1, '+': 0, '|': FALSE}
  test_kb = FolKB(map(expr, ['Farmer(Mac)', 'Rabbit(Pete)', 'Mot...
  A = A
  B = B
  C = C
  F = F
  FALSE = FALSE
  G = G
  ONE = 1
  P = P
  Q = Q
  TRUE = TRUE
  TWO = 2
  ZERO = 0
  __package__ = 'spade'
  x = x
  y = y
  z = z
Function Details [hide private]

every(predicate, seq)

source code 

True if every element of seq satisfies predicate. >>> every(callable, [min, max]) 1 >>> every(callable, [min, 3]) 0

num_or_str(x)

source code 

The argument is a string; convert to a number if possible, or strip it. >>> num_or_str('42') 42 >>> num_or_str(' 42x ') '42x'

expr(s)

source code 
Create an Expr representing a logic expression by parsing the input
string. Symbols and numbers are automatically converted to Exprs.
In addition you can use alternative spellings of these operators:
  'x ==> y'   parses as   (x >> y)    # Implication
  'x <== y'   parses as   (x << y)    # Reverse implication
  'x <=> y'   parses as   (x % y)     # Logical equivalence
  'x =/= y'   parses as   (x ^ y)     # Logical disequality (xor)
But BE CAREFUL; precedence of implication is wrong. expr('P & Q ==> R & S')
is ((P & (Q >> R)) & S); so you must use expr('(P & Q) ==> (R & S)').
>>> expr('P <=> Q(1)')
(P <=> Q(1))
>>> expr('P & Q | ~R(x, F(x))')
((P & Q) | ~R(x, F(x)))

literals(s)

source code 

returns the list of literals of logical expression s. >>> literals(expr('F(A, B)')) [F(A, B)] >>> literals(expr('~F(A, B)')) [~F(A, B)] >>> literals(expr('(F(A, B) & G(B, C)) ==> R(A, C)')) [F(A, B), G(B, C), R(A, C)]

variables(s)

source code 

returns the set of variables in logical expression s. >>> ppset(variables(F(x, A, y))) set([x, y]) >>> ppset(variables(expr('F(x, x) & G(x, y) & H(y, z) & R(A, z, z)'))) set([x, y, z])

is_definite_clause(s)

source code 

returns True for exprs s of the form A & B & ... & C ==> D, where all literals are positive. In clause form, this is ~A | ~B | ... | ~C | D, where exactly one clause is positive. >>> is_definite_clause(expr('Farmer(Mac)')) True >>> is_definite_clause(expr('~Farmer(Mac)')) False >>> is_definite_clause(expr('(Farmer(f) & Rabbit(r)) ==> Hates(f, r)')) True >>> is_definite_clause(expr('(Farmer(f) & ~Rabbit(r)) ==> Hates(f, r)')) False

tt_entails(kb, alpha)

source code 

Use truth tables to determine if KB entails sentence alpha. [Fig. 7.10] >>> tt_entails(expr('P & Q'), expr('Q')) True

pl_true(exp, model={})

source code 

Return True if the propositional logic expression is true in the model, and False if it is false. If the model does not specify the value for every proposition, this may return None to indicate 'not obvious'; this may happen even when the expression is tautological.

to_cnf(s)

source code 

Convert a propositional logical sentence s to conjunctive normal form. That is, of the form ((A | ~B | ...) & (B | C | ...) & ...) [p. 215] >>> to_cnf("~(B|C)") (~B & ~C) >>> to_cnf("B <=> (P1|P2)") ((~P1 | B) & (~P2 | B) & (P1 | P2 | ~B)) >>> to_cnf("a | (b & c) | d") ((b | a | d) & (c | a | d)) >>> to_cnf("A & (B | (D & E))") (A & (D | B) & (E | B))

eliminate_implications(s)

source code 

Change >>, <<, and <=> into &, |, and ~. That is, return an Expr that is equivalent to s, but has only &, |, and ~ as logical operators. >>> eliminate_implications(A >> (~B << C)) ((~B | ~C) | ~A)

move_not_inwards(s)

source code 

Rewrite sentence s by moving negation sign inward. >>> move_not_inwards(~(A | B)) (~A & ~B) >>> move_not_inwards(~(A & B)) (~A | ~B) >>> move_not_inwards(~(~(A | ~B) | ~~C)) ((A | ~B) & ~C)

distribute_and_over_or(s)

source code 

Given a sentence s consisting of conjunctions and disjunctions of literals, return an equivalent sentence in CNF. >>> distribute_and_over_or((A & B) | C) ((A | C) & (B | C))

NaryExpr(op, *args)

source code 

Create an Expr, but with an nary, associative op, so we can promote nested instances of the same op up to the top level. >>> NaryExpr('&', (A&B),(B|C),(B&C)) (A & B & (B | C) & B & C)

conjuncts(s)

source code 

Return a list of the conjuncts in the sentence s. >>> conjuncts(A & B) [A, B] >>> conjuncts(A | B) [(A | B)]

disjuncts(s)

source code 

Return a list of the disjuncts in the sentence s. >>> disjuncts(A | B) [A, B] >>> disjuncts(A & B) [(A & B)]

pl_resolution(KB, alpha)

source code 

Propositional Logic Resolution: say if alpha follows from KB. [Fig. 7.12]

pl_resolve(ci, cj)

source code 

Return all clauses that can be obtained by resolving clauses ci and cj. >>> for res in pl_resolve(to_cnf(A|B|C), to_cnf(~B|~C|F)): ... ppset(disjuncts(res)) set([A, C, F, ~C]) set([A, B, F, ~B])

pl_fc_entails(KB, q)

source code 

Use forward chaining to see if a HornKB entails symbol q. [Fig. 7.14] >>> pl_fc_entails(Fig[7,15], expr('Q')) True

dpll_satisfiable(s)

source code 

Check satisfiability of a propositional sentence. This differs from the book code in two ways: (1) it returns a model rather than True when it succeeds; this is more useful. (2) The function find_pure_symbol is passed a list of unknown clauses, rather than a list of all clauses and the model; this is more efficient. >>> ppsubst(dpll_satisfiable(A&~B)) {A: True, B: False} >>> dpll_satisfiable(P&~P) False

find_pure_symbol(symbols, unknown_clauses)

source code 

Find a symbol and its value if it appears only as a positive literal (or only as a negative) in clauses. >>> find_pure_symbol([A, B, C], [A|~B,~B|~C,C|A]) (A, True)

find_unit_clause(clauses, model)

source code 

A unit clause has only 1 variable that is not bound in the model. >>> find_unit_clause([A|B|C, B|~C, A|~B], {A:True}) (B, False)

literal_symbol(literal)

source code 

The symbol in this literal (without the negation). >>> literal_symbol(P) P >>> literal_symbol(~P) P

unify(x, y, s)

source code 

Unify expressions x,y with substitution s; return a substitution that would make x,y equal, or None if x,y can not unify. x and y can be variables (e.g. Expr('x')), constants, lists, or Exprs. [Fig. 9.1] >>> ppsubst(unify(x + y, y + C, {})) {x: y, y: C}

extend(s, var, val)

source code 

Copy the substitution s and extend it by setting var to val; return copy.

>>> ppsubst(extend({x: 1}, y, 2))
{x: 1, y: 2}

subst(s, x)

source code 

Substitute the substitution s into the expression x. >>> subst({x: 42, y:0}, F(x) + y) (F(42) + 0)

fol_fc_ask(KB, alpha)

source code 

Inefficient forward chaining for first-order logic. [Fig. 9.3] KB is an FOLHornKB and alpha must be an atomic sentence.

standardize_apart(sentence, dic={})

source code 

Replace all the variables in sentence with new variables. >>> e = expr('F(a, b, c) & G(c, A, 23)') >>> len(variables(standardize_apart(e))) 3 >>> variables(e).intersection(variables(standardize_apart(e))) set([]) >>> is_variable(standardize_apart(expr('x'))) True

fol_bc_ask(KB, goals, theta={})

source code 

A simple backward-chaining algorithm for first-order logic. [Fig. 9.6] KB should be an instance of FolKB, and goals a list of literals.

>>> test_ask('Farmer(x)')
['{x: Mac}']
>>> test_ask('Human(x)')
['{x: Mac}', '{x: MrsMac}']
>>> test_ask('Hates(x, y)')
['{x: Mac, y: Pete}']
>>> test_ask('Loves(x, y)')
['{x: MrsMac, y: Mac}', '{x: MrsRabbit, y: Pete}']
>>> test_ask('Rabbit(x)')
['{x: MrsRabbit}', '{x: Pete}']

subst_compose(s1, s2)

source code 

Return the substitution which is equivalent to applying s2 to the result of applying s1 to an expression.

>>> s1 = {x: A, y: B}
>>> s2 = {z: x, x: C}
>>> p = F(x) & G(y) & expr('H(z)')
>>> subst(s1, p)
((F(A) & G(B)) & H(z))
>>> subst(s2, p)
((F(C) & G(y)) & H(x))
>>> subst(s2, subst(s1, p))
((F(A) & G(B)) & H(x))
>>> subst(subst_compose(s1, s2), p)
((F(A) & G(B)) & H(x))
>>> subst(s1, subst(s2, p))
((F(C) & G(B)) & H(A))
>>> subst(subst_compose(s2, s1), p)
((F(C) & G(B)) & H(A))
>>> ppsubst(subst_compose(s1, s2))
{x: A, y: B, z: x}
>>> ppsubst(subst_compose(s2, s1))
{x: C, y: B, z: A}
>>> subst(subst_compose(s1, s2), p) == subst(s2, subst(s1, p))
True
>>> subst(subst_compose(s2, s1), p) == subst(s1, subst(s2, p))
True

diff(y, x)

source code 

Return the symbolic derivative, dy/dx, as an Expr. However, you probably want to simplify the results with simp. >>> diff(x * x, x) ((x * 1) + (x * 1)) >>> simp(diff(x * x, x)) (2 * x)

pretty_dict(d)

source code 

Print the dictionary d.

Prints a string representation of the dictionary with keys in sorted order according to their string representation: {a: A, d: D, ...}. >>> pretty_dict({'m': 'M', 'a': 'A', 'r': 'R', 'k': 'K'}) "{'a': 'A', 'k': 'K', 'm': 'M', 'r': 'R'}" >>> pretty_dict({z: C, y: B, x: A}) '{x: A, y: B, z: C}'

pretty_set(s)

source code 

Print the set s.

>>> pretty_set(set(['A', 'Q', 'F', 'K', 'Y', 'B']))
"set(['A', 'B', 'F', 'K', 'Q', 'Y'])"
>>> pretty_set(set([z, y, x]))
'set([x, y, z])'

Variables Details [hide private]

test_kb

Value:
FolKB(map(expr, ['Farmer(Mac)', 'Rabbit(Pete)', 'Mother(MrsMac, Mac)',\
 'Mother(MrsRabbit, Pete)', '(Rabbit(r) & Farmer(f)) ==> Hates(f, r)',\
 '(Mother(m, c)) ==> Loves(m, c)', '(Mother(m, r) & Rabbit(r)) ==> Rab\
bit(m)', '(Farmer(f)) ==> Human(f)', '(Mother(m, h) & Human(h)) ==> Hu\
man(m)']))