logic.py 72,3 ko
Newer Older
def fol_bc_or(kb, goal, theta):
    for rule in kb.fetch_rules_for_goal(goal):
withal's avatar
withal a validé
        lhs, rhs = parse_definite_clause(standardize_variables(rule))
        for theta1 in fol_bc_and(kb, lhs, unify_mm(rhs, goal, theta)):
withal's avatar
withal a validé
            yield theta1

def fol_bc_and(kb, goals, theta):
withal's avatar
withal a validé
    if theta is None:
        pass
    elif not goals:
        yield theta
withal's avatar
withal a validé
    else:
        first, rest = goals[0], goals[1:]
        for theta1 in fol_bc_or(kb, subst(theta, first), theta):
            for theta2 in fol_bc_and(kb, rest, theta1):
withal's avatar
withal a validé
                yield theta2
# A simple KB that defines the relevant conditions of the Wumpus World as in Figure 7.4.
C.G.Vedant's avatar
C.G.Vedant a validé
# See Sec. 7.4.3
wumpus_kb = PropKB()

P11, P12, P21, P22, P31, B11, B21 = expr('P11, P12, P21, P22, P31, B11, B21')
wumpus_kb.tell(~P11)
wumpus_kb.tell(B11 | '<=>' | (P12 | P21))
wumpus_kb.tell(B21 | '<=>' | (P11 | P22 | P31))
C.G.Vedant's avatar
C.G.Vedant a validé
wumpus_kb.tell(~B11)
wumpus_kb.tell(B21)

test_kb = 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)) ==> Rabbit(m)',
                           '(Farmer(f)) ==> Human(f)',
                           # Note that this order of conjuncts
                           # would result in infinite recursion:
                           # '(Human(h) & Mother(m, h)) ==> Human(m)'
                           '(Mother(m, h) & Human(h)) ==> Human(m)']))

crime_kb = FolKB(map(expr, ['(American(x) & Weapon(y) & Sells(x, y, z) & Hostile(z)) ==> Criminal(x)',
                            'Owns(Nono, M1)',
                            'Missile(M1)',
                            '(Missile(x) & Owns(Nono, x)) ==> Sells(West, x, Nono)',
                            'Missile(x) ==> Weapon(x)',
                            'Enemy(x, America) ==> Hostile(x)',
                            'American(West)',
                            'Enemy(Nono, America)']))
# ______________________________________________________________________________

# Example application (not in the book).
# You can use the Expr class to do symbolic differentiation. This used to be
# a part of AI; now it is considered a separate field, Symbolic Algebra.

def diff(y, x):
    """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))
    """
MircoT's avatar
MircoT a validé
    if y == x:
Peter Norvig's avatar
Peter Norvig a validé
        return 1
MircoT's avatar
MircoT a validé
    elif not y.args:
Peter Norvig's avatar
Peter Norvig a validé
        return 0
    else:
        u, op, v = y.args[0], y.op, y.args[-1]
MircoT's avatar
MircoT a validé
        if op == '+':
            return diff(u, x) + diff(v, x)
        elif op == '-' and len(y.args) == 1:
MircoT's avatar
MircoT a validé
            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)
MircoT's avatar
MircoT a validé
        elif op == '**':
            return (v * u ** (v - 1) * diff(u, x) +
                    u ** v * Expr('log')(u) * diff(v, x))
MircoT's avatar
MircoT a validé
        elif op == 'log':
            return diff(u, x) / u
        else:
            raise ValueError('Unknown op: {} in diff({}, {})'.format(op, y, x))
    """Simplify the expression x."""
    if isnumber(x) or not x.args:
MircoT's avatar
MircoT a validé
        return x
MircoT's avatar
MircoT a validé
    args = list(map(simp, x.args))
    u, op, v = args[0], x.op, args[-1]
withal's avatar
withal a validé
    if op == '+':
Peter Norvig's avatar
Peter Norvig a validé
        if v == 0:
MircoT's avatar
MircoT a validé
            return u
Peter Norvig's avatar
Peter Norvig a validé
        if u == 0:
MircoT's avatar
MircoT a validé
            return v
        if u == v:
Peter Norvig's avatar
Peter Norvig a validé
            return 2 * u
MircoT's avatar
MircoT a validé
        if u == -v or v == -u:
Peter Norvig's avatar
Peter Norvig a validé
            return 0
withal's avatar
withal a validé
    elif op == '-' and len(args) == 1:
MircoT's avatar
MircoT a validé
        if u.op == '-' and len(u.args) == 1:
            return u.args[0]  # --y ==> y
withal's avatar
withal a validé
    elif op == '-':
Peter Norvig's avatar
Peter Norvig a validé
        if v == 0:
MircoT's avatar
MircoT a validé
            return u
Peter Norvig's avatar
Peter Norvig a validé
        if u == 0:
MircoT's avatar
MircoT a validé
            return -v
        if u == v:
Peter Norvig's avatar
Peter Norvig a validé
            return 0
MircoT's avatar
MircoT a validé
        if u == -v or v == -u:
Peter Norvig's avatar
Peter Norvig a validé
            return 0
withal's avatar
withal a validé
    elif op == '*':
Peter Norvig's avatar
Peter Norvig a validé
        if u == 0 or v == 0:
            return 0
        if u == 1:
MircoT's avatar
MircoT a validé
            return v
Peter Norvig's avatar
Peter Norvig a validé
        if v == 1:
MircoT's avatar
MircoT a validé
            return u
        if u == v:
            return u ** 2
withal's avatar
withal a validé
    elif op == '/':
Peter Norvig's avatar
Peter Norvig a validé
        if u == 0:
            return 0
        if v == 0:
MircoT's avatar
MircoT a validé
            return Expr('Undefined')
        if u == v:
Peter Norvig's avatar
Peter Norvig a validé
            return 1
MircoT's avatar
MircoT a validé
        if u == -v or v == -u:
Peter Norvig's avatar
Peter Norvig a validé
            return 0
withal's avatar
withal a validé
    elif op == '**':
Peter Norvig's avatar
Peter Norvig a validé
        if u == 0:
            return 0
        if v == 0:
            return 1
        if u == 1:
            return 1
        if v == 1:
MircoT's avatar
MircoT a validé
            return u
withal's avatar
withal a validé
    elif op == 'log':
Peter Norvig's avatar
Peter Norvig a validé
        if u == 1:
            return 0
MircoT's avatar
MircoT a validé
    else:
        raise ValueError('Unknown op: ' + op)
MircoT's avatar
MircoT a validé
    # If we fall through to here, we can not simplify further
    """Differentiate and then simplify.
    >>> d(x * x - x, x)
    ((2 * x) - 1)
    """
withal's avatar
withal a validé
    return simp(diff(y, x))