logic.py 39,6 ko
Newer Older
        if op == '+': return diff(u, x) + diff(v, x)
        elif op == '-' and len(args) == 1: return -diff(u, x)
        elif op == '-': return diff(u, x) - diff(v, x)
        elif op == '*': return u * diff(v, x) + v * diff(u, x)
        elif op == '/': return (v*diff(u, x) - u*diff(v, x)) / (v * v)
        elif op == '**' and isnumber(x.op):
            return (v * u ** (v - 1) * diff(u, x))
        elif op == '**': return (v * u ** (v - 1) * diff(u, x)
                                 + u ** v * Expr('log')(u) * diff(v, x))
        elif op == 'log': return diff(u, x) / u
        else: raise ValueError("Unknown op: %s in diff(%s, %s)" % (op, y, x))

def simp(x):
    if not x.args: return x
    args = map(simp, x.args)
    u, op, v = args[0], x.op, args[-1]
withal's avatar
withal a validé
    if op == '+':
        if v == ZERO: return u
        if u == ZERO: return v
        if u == v: return TWO * u
        if u == -v or v == -u: return ZERO
withal's avatar
withal a validé
    elif op == '-' and len(args) == 1:
        if u.op == '-' and len(u.args) == 1: return u.args[0] ## --y ==> y
withal's avatar
withal a validé
    elif op == '-':
        if v == ZERO: return u
        if u == ZERO: return -v
        if u == v: return ZERO
        if u == -v or v == -u: return ZERO
withal's avatar
withal a validé
    elif op == '*':
        if u == ZERO or v == ZERO: return ZERO
        if u == ONE: return v
        if v == ONE: return u
        if u == v: return u ** 2
withal's avatar
withal a validé
    elif op == '/':
        if u == ZERO: return ZERO
        if v == ZERO: return Expr('Undefined')
        if u == v: return ONE
        if u == -v or v == -u: return ZERO
withal's avatar
withal a validé
    elif op == '**':
        if u == ZERO: return ZERO
        if v == ZERO: return ONE
        if u == ONE: return ONE
        if v == ONE: return u
withal's avatar
withal a validé
    elif op == 'log':
        if u == ONE: return ZERO
    else: raise ValueError("Unknown op: " + op)
    ## If we fall through to here, we can not simplify further
    return Expr(op, *args)

def d(y, x):
    "Differentiate and then simplify."
withal's avatar
withal a validé
    return simp(diff(y, x))
#_______________________________________________________________________________

# Utilities for doctest cases
# These functions print their arguments in a standard order
# to compensate for the random order in the standard representation

def pretty(x):
    t = type(x)
    if t is dict:  return pretty_dict(x)
    elif t is set: return pretty_set(x)
    else:          return repr(x)
def pretty_dict(d):
    """Return dictionary d's repr but with the items sorted.
    >>> 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}'
    return '{%s}' % ', '.join('%r: %r' % (k, v)
                              for k, v in sorted(d.items(), key=repr))
def pretty_set(s):
    """Return set s's repr but with the items sorted.
    >>> 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])'
    return 'set(%r)' % sorted(s, key=repr)
def pp(x):
    print pretty(x)
def ppsubst(s):
    """Pretty-print substitution s"""
    ppdict(s)
def ppdict(d):
    print pretty_dict(d)
def ppset(s):
    print pretty_set(s)
peter.norvig's avatar
peter.norvig a validé
#________________________________________________________________________

class logicTest: """
### PropKB
>>> kb = PropKB()
>>> kb.tell(A & B)
>>> kb.tell(B >> C)
>>> kb.ask(C) ## The result {} means true, with no substitutions
{}
withal's avatar
withal a validé
>>> kb.ask(P)
peter.norvig's avatar
peter.norvig a validé
False
>>> kb.retract(B)
withal's avatar
withal a validé
>>> kb.ask(C)
peter.norvig's avatar
peter.norvig a validé
False

withal's avatar
withal a validé
>>> pl_true(P, {})
>>> pl_true(P | Q, {P: True})
peter.norvig's avatar
peter.norvig a validé
True

# Notice that the function pl_true cannot reason by cases:
withal's avatar
withal a validé
>>> pl_true(P | ~P)
peter.norvig's avatar
peter.norvig a validé

# However, tt_true can:
withal's avatar
withal a validé
>>> tt_true(P | ~P)
peter.norvig's avatar
peter.norvig a validé
True

# The following are tautologies from [Fig. 7.11]:
withal's avatar
withal a validé
>>> tt_true("(A & B) <=> (B & A)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A | B) <=> (B | A)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("((A & B) & C) <=> (A & (B & C))")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("((A | B) | C) <=> (A | (B | C))")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("~~A <=> A")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A >> B) <=> (~B >> ~A)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A >> B) <=> (~A | B)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A <=> B) <=> ((A >> B) & (B >> A))")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("~(A & B) <=> (~A | ~B)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("~(A | B) <=> (~A & ~B)")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A & (B | C)) <=> ((A & B) | (A & C))")
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> tt_true("(A | (B & C)) <=> ((A | B) & (A | C))")
peter.norvig's avatar
peter.norvig a validé
True

# The following are not tautologies:
withal's avatar
withal a validé
>>> tt_true(A & ~A)
peter.norvig's avatar
peter.norvig a validé
False
withal's avatar
withal a validé
>>> tt_true(A & B)
peter.norvig's avatar
peter.norvig a validé
False

### [Fig. 7.13]
>>> alpha = expr("~P12")
>>> to_cnf(Fig[7,13] & ~alpha)
((~P12 | B11) & (~P21 | B11) & (P12 | P21 | ~B11) & ~B11 & P12)
withal's avatar
withal a validé
>>> tt_entails(Fig[7,13], alpha)
peter.norvig's avatar
peter.norvig a validé
True
withal's avatar
withal a validé
>>> pl_resolution(PropKB(Fig[7,13]), alpha)
peter.norvig's avatar
peter.norvig a validé
True

### [Fig. 7.15]
withal's avatar
withal a validé
>>> pl_fc_entails(Fig[7,15], expr('SomethingSilly'))
peter.norvig's avatar
peter.norvig a validé
False

### Unification:
withal's avatar
withal a validé
>>> unify(x, x, {})
peter.norvig's avatar
peter.norvig a validé
{}
withal's avatar
withal a validé
>>> unify(x, 3, {})
peter.norvig's avatar
peter.norvig a validé
{x: 3}


withal's avatar
withal a validé
>>> to_cnf((P&Q) | (~P & ~Q))
peter.norvig's avatar
peter.norvig a validé
((~P | P) & (~Q | P) & (~P | Q) & (~Q | Q))
"""