命题逻辑推理:怪兽世界《人工智能案例与实验》

问题描述:

人工智能第七章——命题逻辑(待补充)_联机搜索实现wumpus世界-CSDN博客

运行结果:

(A11 & B)
[~P11, ~B11, B21, (B11 <=> (P12 | P21)), (B21 <=> ((P11 | P22) | P31))]
True
False

源代码:

import collections
from collections import defaultdict, Counter

class Expr:
    def __init__(self, op, *args):  # 表达式包含操作符和若干参数
        self.op = str(op)
        self.args = args

    def __invert__(self):  # 重载逻辑非
        return Expr('~', self)

    def __and__(self, rhs):  # 重载逻辑与
        return Expr('&', self, rhs)

    def __or__(self, rhs):  # 重载逻辑或
        if isinstance(rhs, Expr):
            return Expr('|', self, rhs)
        else:  # 处理 ==> 类符号,A==>B 已经转换为 A'/== '/B
            return PartialExpr(rhs, self)

    def __eq__(self, other):
        return isinstance(other, Expr) and self.op == other.op and self.args == other.args

    def __hash__(self):
        return hash(self.op) ^ hash(self.args)

    def __repr__(self):
        op = self.op
        args = [str(arg) for arg in self.args]
        if op.isidentifier():  # f(x) or f(x, y)
            return '{}({})'.format(op, ', '.join(args)) if args else op
        elif len(args) == 1:  # ~x or ~(x + 1)
            return op + args[0]
        else:  # (x - y)
            opp = (' ' + op + ' ')
            return '(' + opp.join(args) + ')'

class PartialExpr:
    def __init__(self, op, lhs):
        self.op, self.lhs = op, lhs

    def __or__(self, rhs):
        return Expr(self.op, self.lhs, rhs)

    def __repr__(self):
        return "PartialExpr('{}', {})".format(self.op, self.lhs)

def expr(x):
    if isinstance(x, str):
        for op in ['==>', '<==', '<=>']:
            x = x.replace(op, '|' + repr(op) + '|')
        return eval(x, defaultkeydict(Symbol))  # eval 用符号分割子串,子串作为原子命题
    else:
        return x

def Symbol(name):  # 处理原子命题
    return Expr(name)

class defaultkeydict(collections.defaultdict):
    # 类似 defaultdict,但是使用 default_factory 来对 key 进行处理
    def __missing__(self, key):
        self[key] = result = self.default_factory(key)
        return result

class KB:
    def __init__(self, sentence=None):
        self.rules = []
        if sentence:
            self.tell(sentence)

    def tell(self, sentence):
        self.rules.append(expr(sentence))

    def ask(self, query):
        return tt_entails(Expr('&', *self.rules), expr(query))

def tt_entails(kb, alpha):
    symbols = list(prop_symbols(kb & alpha))
    return tt_check_all(kb, alpha, symbols, {})
    # 通过枚举方法检查是否可以推导出 query
    # 由 KB 推导出 alpha
    # 分解所有的命题词
    # 枚举所有命题词的各种赋值,并检查 kb 是否蕴含 alpha

def prop_symbols(x):
    if not isinstance(x, Expr):
        return set()
    elif is_prop_symbol(x.op):  # 原子语句,操作符为单命题词
        return {x}
    else:  # 符合语句,递归分解操作参数
        return {symbol for arg in x.args for symbol in prop_symbols(arg)}

def tt_check_all(kb, alpha, symbols, model):
    if not symbols:  # 各命题词都已纳入了模型
        if pl_true(kb, model):  # 模型满足 kb
            result = pl_true(alpha, model)  # 是否满足语句 alpha
            assert result in (True, False)
            return result
        else:
            return True
    else:  # 递归,枚举每个命题词的不同赋值
        P, rest = symbols[0], symbols[1:]
        model[P] = True
        res1 = tt_check_all(kb, alpha, rest, model)
        model[P] = False
        res2 = tt_check_all(kb, alpha, rest, model)
        return res1 and res2

def is_prop_symbol(s):  # 命题词单首字母大写
    return isinstance(s, str) and s[0].isupper()

def pl_true(exp, model={}):
    # exp 是一个表达式,model 是一个以命题词为 key 的词典
    if exp in (True, False):
        return exp
    op, args = exp.op, exp.args
    if is_prop_symbol(op):  # 原子语句
        return model.get(exp)
    elif op == '~':
        p = pl_true(args[0], model)
        if p is None:
            return None
        else:
            return not p
    elif op == '|':
        result = False
        for arg in args:
            p = pl_true(arg, model)
            if p is True:
                return True
            if p is None:
                result = None
        return result
    elif op == '&':
        result = True
        for arg in args:
            p = pl_true(arg, model)
            if p is False:
                return False
            if p is None:
                result = None
        return result
    p, q = args  
    if op == '==>':
       # 到此时应是蕴含表达式
        return pl_true(~p | q, model)  # 根据公式 (4.1) 处理 =>
    
    pt = pl_true(p, model)
    if pt is None:
        return None
    qt = pl_true(q, model)
    if qt is None:
        return None
    if op == '<=>':
        return pt == qt
    else:
        raise ValueError(
            'Illegal operator in logic expression' + str(exp))

if __name__ == '__main__':
    s = expr('A11&B')
    print(s)
    kb = KB()
    
    kb.tell('~P11')
    kb.tell('~B11')
    kb.tell('B21')
    kb.tell('B11<=>(P12|P21)')
    kb.tell('B21<=>(P11|P22|P31)')
    
    print(kb.rules)
    print(kb.ask('~P12'))
    print(kb.ask('~P22'))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值