zoukankan      html  css  js  c++  java
  • Prolog

    Prolog简介

    部分资料来自于:

    http://www.ruanyifeng.com/blog/2019/01/prolog.html
    https://blog.csdn.net/laoyao_legend/article/details/84870827

    Prolog是一款面向逻辑问题的编程软件(不是离散要求的话,我估计我到死都不会接触这一款)

    比如,"苏格拉底是人,人都会死,所以苏格拉底会死"这一类的问题。

    只要给定事实和规则,它会自动分析其中的逻辑关系,然后允许用户通过输入和查询,完成复杂的逻辑运算。

    (底层估计是强连通分量或者暴力枚举的实现吧,类似于2-SAT问题?不纠结,用就完事了)

    运行环境 SWI-Prolog

    https://www.swi-prolog.org/

    基本框架

    运行模块

    这是在程序运行阶段,你要进行输入,输入的是命令

    脚本编辑模块

    这是在程序运行之前所要预加载的脚本,你在其中要写定逻辑规则和事实,作为运行基础


    语法部分

    基本格式

    开头以"?-"作为命令提示符,表示某个程序的开始

    所有语句均以"."作为结束标志

    单独语句中有多个命令用","分隔

    退出可使用halt命令

    输入输出

    1)输出语句:write()

    下面展示的是经典程序

    ?- write("Hello, world").
    Hello, world!
    true.
    

    注意为什么会有多打印个true呢?

    Prolog中的命令本身就是一个表达式,命令完成以后,会返回值,并且显示出来

    2)换行命令nl:

    ?- write('Hello,'), nl, write('world').
    Hello,
    world
    true.
    

    3)输入语句read(变量名)

    后面具体脚本在谈怎么用

    变量&常量

    变量和常量规则很简单:小写字母开头的字符串,就是常量;大写字母开头的字符串,就是变量

    ?- write(abc).
    abc
    true.
    
    ?- Abc=1,write(Abc).
    1
    Abc = 1.
    

    关系

    两个对象之间的关系,使用括号表示。比如,Jack 的朋友是 Peter,写成

    friend(jack, peter).

    关系名(A,B)值A对于B是什么/A是B的什么

    这里仅代表单向关系, 如果表示双向关系

    friend(jack,prter).
    friend(peter,jack).
    

    如果括号里面只有一个参数,就表示对象拥有该属性,比如 Jack 是男性,写成male(jack).

    规则

    规则是推理方法,即如何从一个论断得到另一个论断。

    friend(X, Y):-friend(Y,X).
    

    长得比较有内涵的符号":-"表示推理关系

    上面代码中,X和Y都是大写,表示这是两个变量。

    含义是只要右边的表达式friend(Y, X)为true,那么左边的表达式friend(X, Y)也为true。

    因此,根据这条规则,friend(Jack, Peter)就可以推理得到friend(Peter, Jack)。

    如果一条规则取决于多个条件,可以使用逗号分隔,如

    mother(X, Y) :- child(Y,X), female(X).
    

    注意在Prolog中,符号"+"进行表示

    以及在规则设定可以面向多元如,color(A,B,C),differ(A,B,C,D)

    在具体编程中,

    关系的声明一般使用常量,表示具体的内容满足什么属性。而规则一般使用的是变量,表示抽象出来的对象应有什么属性

    当你进行查询的时候,计算机无非是尝试对规则下抽象对象赋以具体值,也就是求抽象对象的可行解

    查询

    Prolog支持查询已经设定的条件

    比如我们在脚本里面写了friend这个规则,我们就可以进行查询

    如:查询john有多少个朋友

    ?- friend(john, Who).
    Who = julia ;
    Who = jack.
    

    注意如果有多种情况,可以键入“;”查看下一组赋值情况

    Who是抽象的,它具体是多少,计算机尝试去给它赋具体值,julia是一个可行解,jack也是一个可行解,它就会输出

    函数listing(关系),用于列出所有使关系的元素

    如:

    ?- listing(friend).
    friend(john, julia).
    friend(john, jack).
    friend(julia, sam).
    friend(julia, molly).
    true.
    

    例子:

    注意:prolog不支持中文,我在Nodepad++上进行编辑,实际脚本没有以下中文批注

    /*
    作者:tsy
    @Written by tsy
    
    建模思路分析:
    我们要找到凶手
    这一逻辑问题要落脚于建立正确的匹配关系,即谁拥有什么物品,在哪个房间
    Prolog的编程要求我们区分清楚抽象对象和具体对象,那我们如何选定嘞?
    当我们讨论什么物品,还是什么房间的时候,我们论述的展开都是建立在“人”之上的,
    即我们可以理解成拥有什么物品的人,在什么房间的人,论述的主体始终离不开“人”
    所以我们要将物品对应的人,以及房间对应的人,抽象出来,作为变量(大写),求解的正是这些	变量的解情况
    而这些可行解应该从具体的人中进行选择,故人名应该看作常量(小写)
    */
    
    //前置条件(1):三男三女,均为常量
    man(george).
    man(john).
    man(robert).
    woman(barbara).
    woman(christine).
    woman(yolanda).
    
    person(X):-man(X).
    person(X):-woman(X).
    
    //抽象的事物与具体的人只能一一建立匹配关系,即所有解不能出现相同的
    differ(A,B,C,D,E,F):-
    person(A),person(B),person(C),person(D),person(E),person(F),
    +A=B,+A=C,+A=D,+A=E,+A=F,
    +B=C,+B=D,+B=E,+B=F,
    +C=D,+C=E,+C=F,
    +D=E,+D=F,
    +E=F.
    
    //前置条件(2)&&前置条件(3):
    
    murderer(X):-
    differ(Bathroom,Diningroom,Kitchen,Livingroom,Pantry,Study),
    differ(Bag,Firearm,Gas,Knife,Poison,Rope),
    
    //线索一:厨房里面是一个男人,里面的凶器不是绳索、刀子、包、毒药
    man(Kitchen),
    +Kitchen=Rope,
    +Kitchen=Knife,
    +Kitchen=Bag,
    +Kitchen=Firearm,
    
    //线索二:Barbara 和 Yolanda 在浴室和书房,好好理解这句话的意思,我一开始搞错了
    woman(Bathroom), woman(Study), 
    +Bathroom=christine, +Study=christine, 
    +Diningroom=barbara, +Kitchen=barbara, 
    +Livingroom=barbara, +Pantry=barbara,
    +Diningroom=yolanda, +Kitchen=yolanda, 
    +Livingroom=yolanda, +Pantry=yolanda,
    
    //线索三:带包的那个人不是 Barbara 和 George,也不在浴室和饭厅
    +Bag=barbara,
    +Bag=george,
    +Bag=Bathroom,
    +Bag=Diningroom,
    
    //线索四:书房里面是一个带绳子的女人
    woman(Rope),
    Rope=Study,
    
    //线索五:起居室里面那件凶器,与 John 或 George 在一起。注意John和George都是男人,故可将后半句转义。
    man(Livingroom),
    +Livingroom=robert,
    
    //线索六:刀子不在饭厅
    +Knife=Diningroom,
    
    //线索七:书房和食品储藏室里面的凶器,没跟 Yolanda 在一起
    +Study=yolanda,
    +Pantry=yolanda,
    
    //线索八:George所在的那间屋子有火枪
    Firearm=george,
    
    //线索九:Boddy 先生死在食品储藏室里,那里的凶器是煤气
    Pantry=Gas,
    X=Gas.
    

    运行结果

    我这里键入了分号让他输出下一组可行解

    结果flase,说明christine是唯一的可行解

    注意可能脚本编译会warning:Poison这个没有添加任何约束条件,但代码能跑

    为了美观我在脚本里面加了Poison=Poison

  • 相关阅读:
    字符转换(2,8,10,16进制,ASCII码)
    js正则表达式验证
    不能在DropDownList 中选择多个项
    SQL中sum(),avg()等统计结果为null的解决方法
    文本框TextBox只允许输入数字,不用onkeyup
    ORA01830: 日期格式图片在转换整个输入字符串之前结束
    Oracle数据库中的左连接与右连接
    asp.net服务器验证控件失效的问题
    在博客园开通博客的第一天
    米勒拉宾素数测试
  • 原文地址:https://www.cnblogs.com/et3-tsy/p/12813714.html
Copyright © 2011-2022 走看看