哈工大人工智能实验1--知识表示代码

感谢唐神的指导

参考:

3.3. Knowledge-Lecture 1 - CS50's Introd(Av767530276,P3)_哔哩哔哩_bilibili

《人工智能导论》哈工大赵铁军教授亲授!_哔哩哔哩_bilibili

http://t.csdn.cn/Yd2vE

人工智能实验1-知识表示

实验内容:

参照课程第二部分讲授的知识表示方法完成,包括产生式系统、框架系统、语义网络等(还可以选择其他方法)解决以下问题(不限于此),必要时上网查找有关参考文献。

猴子摘香蕉问题:

一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等)。设房间里还有一只可被猴子移动的箱子,且猴子登上箱子时才能摘到香蕉,问猴子在某一状态下(设猴子位置为A,香蕉位置在B,箱子位置为C),如何行动可摘取到香蕉。

8e89c7e56f544b6994382ddbcde07d9b.png

6d9f9d52554542a88a4fa4ca77a3d385.png

64b3c699a1d240f6bd101cb955793aa8.png

 代码部分和注解

首先猴子先找到箱子 然后猴子 把箱子推到香蕉的正下方 然后猴子爬上箱子 最后猴子摘到香蕉。

from itertools import count
from typing import Any, Callable, Dict, List, NamedTuple, Set, Type, TypeVar

''' 首先定义几个类 
monkey banana box 父类是所有子类的 所有的object从父类baseobj object是所有类的基类
init构造函数 构造实例时候调用的函数 相当于实例的初始化过程 
每个实例有一个很重要的属性 self.pos是实例中的属性 pos是传入的属性 ":" "str" '->代表返回值类型'相当于一个注解 但是对程序运行没有实际作用
'''
class BaseObj(object):
    def __init__(self, pos: str) -> None:#初始化 如果激活obj类的属性
        self.pos = pos                  #当前实体
    
    def move(self, pos: str) -> None:   #move是一个方法 方法是定义中类中的函数 他的特征是第一个参数是self代表当前的实例
        self.pos = pos                  #self是obj定义的实例 self.pos = pos相当于 激活了pos属性
    
    @property                           #装饰器 作用:装饰的方法把他伪装起一个属性  把函数看成一个属性 从实例中
    def state(self) -> Dict[str, Any]:
        return {"pos": self.pos}        #当我尝试从实例中访问名为state属性时候 他自动执行state函数并把返回值给state属性 作为实例的属性
                                        #return sum()

class Monkey(BaseObj):
    def __init__(self, pos: str) -> None:
        super().__init__(pos)           #记住格式 super() 当子类和父类定义了两个同名的方法 如果子类想调用父类的函数功能时就需要用super().函数名
        self.on_box = False             #只要定义的同名函数 父类的函数会被覆盖掉
                                        #当父类发生改变的时候子类也会改变 父亲由卖刀改成改成卖鞋的, 孩子也变成买鞋的。

    def climb(self, box: "Box") -> None:
        assert self.pos == box.pos     #断言 必须是同一位置才能运行这个函数否则会报错 如果 self.pos==bos.pos 把on_box修改成true否则就报错
        self.on_box = True
    
    def push_box(self, box: "Box", target: str) -> None: #“Box”指的是下方的Box类 因为还没有定义所以必须要提前声明一下
        assert self.pos == box.pos
        self.move(target)
        box.move(target)
    
    @property
    def state(self) -> Dict[str, Any]:
        return {"m_pos": self.pos, "on_box": self.on_box}


class Box(BaseObj):
    @property
    def state(self) -> Dict[str, Any]:
        return {"b_pos": self.pos}
    

class Banana(BaseObj):
    def __init__(self, pos: str) -> None:
        super().__init__(pos)
        self.picked = False
    
    def pick(self) -> None:
        self.picked = True
    
    @property
    def state(self) -> Dict[str, Any]:
        return {"n_pos": self.pos, "picked": self.picked}


class Rule(NamedTuple):      #typing用于类型注解的一个内置库  NameTuple是这个库中 带有名字的一个类
    case: Dict[str, Any]
    act: Callable[["Simulation"], None] #方括号 表示注解 返回值是none 参数类型是simulation类的一个实例


T_Obj = TypeVar("T_Obj", bound=BaseObj)


class Simulation(object):
    def __init__(self) -> None:
        self.objects: List[BaseObj] = []
        self.rules: List[Rule] = []
    
    def add_obj(self, obj: BaseObj) -> None:            #添加对象
        self.objects.append(obj)
    
    def add_rule(self, rule: Rule) -> None:              #添加规则
        self.rules.append(rule)

    def at(self, pos: str) -> Set[BaseObj]:               #返回所有在这个位置的实例baseobj的集合
        return {i for i in self.objects if i.pos == pos}

    def get_obj(self, obj_type: Type[T_Obj]) -> T_Obj:
        for i in self.objects:
            if isinstance(i, obj_type):
                return i
        raise ValueError(f"cannot find {obj_type.__qualname__} object")

    @property
    def state(self) -> Dict[str, Any]:
        s = {}
        for i in self.objects:
            s.update(i.state)
        return s

    def eval(self, final_state: Dict[str, Any]) -> None:
        print(f"start state: {self.state}")
        print("Init", end='')
        for _ in range(10):
            for i, r in zip(count(), self.rules):  #i是表项 r是规则
                if r.case == self.state:
                    print(f" -> {i}", end="")
                    r.act(self)
                if self.state == final_state:
                    print(f"\nfinal state: {final_state}")
                    return
        raise RuntimeError(f"cannot reach state {final_state}")


if __name__ == "__main__":
    env = Simulation()
    env.add_obj(Monkey('A'))
    env.add_obj(Box('B'))
    env.add_obj(Banana('C'))
    env.add_rule(
        Rule(
            {"m_pos": 'A', "b_pos": 'B', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).move('B')       #匿名函数 有一个参数env 和把monkey移动到box这个位置 箱子和猴子放一块
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'B', "b_pos": 'B', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).push_box(env.get_obj(Box), "C")  #定义猴子把箱子推到香蕉正下方的行为
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).climb(env.get_obj(Box))
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": True, "picked": False},
            lambda env: env.get_obj(Banana).pick()
        )
    )
    env.eval({"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": True, "picked": True}) #传入终态参数

运行结果截图

9d5710a3cddd4f0dadd215a433807635.png

from itertools import count
from typing import Any, Callable, Dict, List, NamedTuple, Set, Type, TypeVar

''' 首先定义几个类 
monkey banana box 父类是所有子类的 所有的object从父类baseobj object是所有类的基类
init构造函数 构造实例时候调用的函数 相当于实例的初始化过程 
每个实例有一个很重要的属性 self.pos是实例中的属性 pos是传入的属性 ":" "str" '->代表返回值类型'相当于一个注解 但是对程序运行没有实际作用
'''


class BaseObj(object):
    def __init__(self, pos: str) -> None:  # 初始化 如果激活obj类的属性
        self.pos = pos  # 当前实体

    def move(self, pos: str) -> None:  # move是一个方法 方法是定义中类中的函数 他的特征是第一个参数是self代表当前的实例
        self.pos = pos  # self是obj定义的实例 self.pos = pos相当于 激活了pos属性

    @property  # 装饰器 作用:装饰的方法把他伪装起一个属性  把函数看成一个属性 从实例中
    def state(self) -> Dict[str, Any]:
        return {"pos": self.pos}  # 当我尝试从实例中访问名为state属性时候 他自动执行state函数并把返回值给state属性 作为实例的属性
        # return sum()


class Monkey(BaseObj):
    def __init__(self, pos: str) -> None:
        super().__init__(pos)  # 记住格式 super() 当子类和父类定义了两个同名的方法 如果子类想调用父类的函数功能时就需要用super().函数名
        self.on_box = False  # 只要定义的同名函数 父类的函数会被覆盖掉
        # 当父类发生改变的时候子类也会改变 父亲由卖刀改成改成卖鞋的, 孩子也变成买鞋的。

    def climb(self, box: "Box") -> None:
        assert self.pos == box.pos  # 断言 必须是同一位置才能运行这个函数否则会报错 如果 self.pos==bos.pos 把on_box修改成true否则就报错
        self.on_box = True

    def push_box(self, box: "Box", target: str) -> None:  # “Box”指的是下方的Box类 因为还没有定义所以必须要提前声明一下
        assert self.pos == box.pos
        self.move(target)
        box.move(target)

    @property
    def state(self) -> Dict[str, Any]:
        return {"m_pos": self.pos, "on_box": self.on_box}


class Box(BaseObj):
    @property
    def state(self) -> Dict[str, Any]:
        return {"b_pos": self.pos}


class Banana(BaseObj):
    def __init__(self, pos: str) -> None:
        super().__init__(pos)
        self.picked = False

    def pick(self) -> None:
        self.picked = True

    @property
    def state(self) -> Dict[str, Any]:
        return {"n_pos": self.pos, "picked": self.picked}


class Rule(NamedTuple):  # typing用于类型注解的一个内置库  NameTuple是这个库中 带有名字的一个类
    case: Dict[str, Any]
    act: Callable[["Simulation"], None]  # 方括号 表示注解 返回值是none 参数类型是simulation类的一个实例


T_Obj = TypeVar("T_Obj", bound=BaseObj)


class Simulation(object):
    def __init__(self) -> None:
        self.objects: List[BaseObj] = []
        self.rules: List[Rule] = []

    def add_obj(self, obj: BaseObj) -> None:  # 添加对象
        self.objects.append(obj)

    def add_rule(self, rule: Rule) -> None:  # 添加规则
        self.rules.append(rule)

    def at(self, pos: str) -> Set[BaseObj]:  # 返回所有在这个位置的实例baseobj的集合
        return {i for i in self.objects if i.pos == pos}

    def get_obj(self, obj_type: Type[T_Obj]) -> T_Obj:
        for i in self.objects:
            if isinstance(i, obj_type):
                return i
        raise ValueError(f"cannot find {obj_type.__qualname__} object")

    @property
    def state(self) -> Dict[str, Any]:
        s = {}
        for i in self.objects:
            s.update(i.state)
        return s

    def eval(self, final_state: Dict[str, Any]) -> None:
        print(f"start state: {self.state}")
        print("Init", end='')
        for _ in range(10):
            for i, r in zip(count(), self.rules):  # i是表项 r是规则
                if r.case == self.state:
                    print(f" -> {i}", end="")
                    r.act(self)
                if self.state == final_state:
                    print(f"\nfinal state: {final_state}")
                    return
        raise RuntimeError(f"cannot reach state {final_state}")


if __name__ == "__main__":
    env = Simulation()
    env.add_obj(Monkey('B'))
    env.add_obj(Box('A'))
    env.add_obj(Banana('C'))
    env.add_rule(
        Rule(
            {"m_pos": 'B', "b_pos": 'A', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).move('A')  # 匿名函数 有一个参数env 和把monkey移动到box这个位置 箱子和猴子放一块
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'A', "b_pos": 'A', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).push_box(env.get_obj(Box), "C")  # 定义猴子把箱子推到香蕉正下方的行为
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": False, "picked": False},
            lambda env: env.get_obj(Monkey).climb(env.get_obj(Box))
        )
    )
    env.add_rule(
        Rule(
            {"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": True, "picked": False},
            lambda env: env.get_obj(Banana).pick()
        )
    )
    env.eval({"m_pos": 'C', "b_pos": 'C', "n_pos": 'C', "on_box": True, "picked": True})  # 传入终态参数

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值