zoukankan      html  css  js  c++  java
  • 人工智能技术导论——使用PROLOG逻辑语言解决爱因斯坦斑马问题

    一、背景

    在上一篇博客https://www.cnblogs.com/wkfvawl/p/12056951.html上,我简单介绍了一下Prolog的一些基本语法,这篇博客主要通过老师课上讲过的一个问题,来体验一下prolog在逻辑推理上的优势。

    在介绍问题之前,先引入一道Prolog题:

    试编写一个描述亲属关系的Prolog程序,然后再给出一些事实数据,建立一个小型演绎数据库。

    提示:可以以父亲和母亲为基本基本关系(作为基本谓词),再由此描述祖父、祖母、兄弟、姐妹以及其他亲属关系。

        mother(a,c). 
        mother(a,d).    
        mother(c,g). 
        mother(c,f). 
        father(b,c). 
        father(b,d). 
        father(e,g). 
        father(e,f). 
        grandfather(X,Z):-father(X,Z),father(Y,Z). 
        grandmother(X,Z):-mother(X,Y),mother(Y,Z). 
        sister(X,Y):-mother(Z,X),mother(Z,Y). 
        aunt(X,Y):-mother(Z,Y),sister(Z,X).

    这里使用SWI-Prolog进行测试

    注意,在 Prolog 中一个词若以小写开头,那么它是一个固定值,若以大写字母开头,则是一个变量。 

    继续定义规则:

     family(F,M,C) :-father(F,C), mother(M,C).

    提出查询,比如

    prolog 将会求出X可能的取值并输出到控制台,中间的下划线是一个占位符,不会进行求值。有了上面的基础知识后,我们就可以利用它来解决逻辑问题了,下面就让我们来解决“斑马难题”吧。

    二、爱因斯坦逻辑难题

    有5间不同颜色的房间,每间住个不同国籍的人,每人有自己喜欢的饮料、香烟和宠物。已知信息:
    英国人在红房间中
    西班牙人有一条狗
    挪威人住在左边第一间房里
    黄房间中的人在抽库尔斯牌香烟
    抽切斯菲尔德牌香烟的人是养了一只狐狸的人的邻居
    挪威人住在蓝房间隔壁
    抽温斯顿牌香烟的人有一只蜗牛
    抽幸运牌香烟的人喝橘子汁
    乌克兰人喝茶
    日本人抽国会牌香烟
    抽库尔斯牌烟的房间在有匹马的房间隔壁
    绿房间中的人喝咖啡
    绿房间在白房间的左边
    中间房间的人喝牛奶

    这道题的解题关键在于,要以一种清晰的方式将每个房子相关的属性(颜色、国籍、香烟、宠物、饮料、编号)列出来,前面5个提示中包含了5个国家,那可以利用这一点画出一个表格,每一行表示一个国家,每一列表示房子的一种属性。一步步根据提示得到一些推论,将结果填入表格,答案便渐渐清晰起来,使用这种人工方式推理的结果如下图所示:

    虽然我们知道了解题的关键,但这个问题仍然需要经过很多步的推导才能得出结果,如果使用 prolog 那得到这个问题的答案就简单多了,只需要定义好事实和规则,然后向 Prolog 提出问题,逻辑引擎就会为我们查出结果来。

    下面是解决这个问题的 Prolog 代码。

    house(A,[A,_,_,_,_]).
    house(A,[_,A,_,_,_]).
    house(A,[_,_,A,_,_]).
    house(A,[_,_,_,A,_]).
    house(A,[_,_,_,_,A]).
    
    left(A,B,[A,B,_,_,_]).
    left(A,B,[_,A,B,_,_]).
    left(A,B,[_,_,A,B,_]).
    left(A,B,[_,_,_,A,B]).
    
    middle(A,[_,_,A,_,_]).
    
    first(A,[A,_,_,_,_]).
    
    neighbor(A,B,[A,B,_,_,_]).
    neighbor(A,B,[_,A,B,_,_]).
    neighbor(A,B,[_,_,A,B,_]).
    neighbor(A,B,[_,_,_,A,B]).
    neighbor(A,B,[B,A,_,_,_]).
    neighbor(A,B,[_,B,A,_,_]).
    neighbor(A,B,[_,_,B,A,_]).
    neighbor(A,B,[_,_,_,B,A]).
    
    attr(Country,Pet,Color,Drink,Smoke).
    
    all_houses(Houses) :-
        house(attr(britsh,_,red,_,_), Houses),           
        house(attr(spain,dog,_,_,_), Houses),
        house(attr(japan,_,_,_,congressCigarettes), Houses),
        house(attr(ukraine,_,_,tea,_), Houses),
        house(attr(norway,_,_,_,_), Houses),
        first(attr(norway,_,_,_,_), Houses),
        left(attr(_,_,green,_,_), attr(_,_,white,_,_), Houses),
        house(attr(_,snail,_,_,winstonCigarettes), Houses),
        house(attr(_,_,yellow,_,coorsCigarettes), Houses),
        middle(attr(_,_,_,milk,_), Houses),
        house(attr(_,_,green,cafe,_), Houses),
        neighbor(attr(norway,_,_,_,_), attr(_,_,blue,_,_), Houses),
        house(attr(_,_,_,orange,luckCigarattes), Houses),
        neighbor(attr(_,fox,_,_,_), attr(_,_,_,_,chesfieldCigarettes), Houses),
        neighbor(attr(_,horse,_,_,_), attr(_,_,_,_,coorsCigarettes), Houses),
    
        house(attr(_,zebra,_,_,_), Houses),
        house(attr(_,_,_,water,_), Houses).

    在事实部分,将房子看做一个整体,描述了房子在5所房子中、房子的左右关系、中间的房子处于什么位置、第一所房子处于什么位置、房子间的相邻关系以及每所房子拥有哪些属性。
    规则部分包含了对题目中提示的描述和最终问题的描述,这些定义是为了告诉逻辑引擎,在求值时必须满足这些条件。
    最终的查询为 all_houses(A) ,prolog 逻辑引擎将会查找出满足结果的房子数组,注意每所房子由它的属性组成,这样最后得到的结果为:

  • 相关阅读:
    基于Python自动生成小学四则运算题目的命令行程序(软工第二次作业)
    第一次个人编程作业
    自我介绍+软工五问
    如何清理 Docker 占用的磁盘空间
    复审与事后分析
    团队作业5——测试与发布(Alpha版本)
    项目冲刺总结集合贴
    团队作业3:需求改进&系统设计
    团队作业2——需求规格说明书
    团队作业1——团队展示&选题
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12058173.html
Copyright © 2011-2022 走看看