Prolog编程求解图搜索问题

实验题目

在这里插入图片描述

Prolog安装及基本用法

Prolog安装:
实验环境:Ubuntu20.04
在终端键入sudo apt-get install swi-prolog完成Prolog环境的安装。
安装成功后,键入swipl XXX.pl执行程序。
Prolog基本用法:

(1)介绍:
Prolog是一种声明式逻辑编程语言。
Prolog 所有语句的结尾都用一个"点"(.)表示结束。换行,可以使用nl命令。退出 SWI-Prolog,可以使用halt命令。

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

(3)关系和属性
两个对象之间的关系,使用括号表示。比如,jack 的朋友是 peter,写成friend(jack, peter).。如果括号里面只有一个参数,就表示对象拥有该属性,比如 jack 是男性,写成male(jack).。
(4)用法
Prolog语法无非就是事实+规则+查询。
(5)Prolog表:
 表是Prolog中一种非常有用的数据结构。表的表述能力很强,数字中的序列、集合,通常语言中的数组、记录等均可用表来表示。表的最大特点是其长度不固定,在程序的运行过程中可动态地变化。具体来讲,就是在程序运行时,可对表实行一些操作,如给表中添加一个元素,或从中删除一个元素,或者将两个表合并为一个表等。用表还可以方便地构造堆栈、队列、链表、树等动态数据结构。
  表还有一个重要特点,就是它可以分为头和尾两部分。表头是表中第一个元素,而表尾是表中除第一个元素外的其余元素按原来顺序组成的表。
  在程序中是用“|”来区分表头和表尾的,而且还可以使用变量.例如一般地用"[H|T]"来表示一个表,其中 H、T 都是变量,H 为表头,T为表尾。注意,此处 H 是一个元素(表中第一个元素),而 T 则是一个表(除第一个元素外表中的其余元素按原来顺序组成的表)。表的这种表示法很有用,它为表的操作提供了极大的方便 。
  在这里插入图片描述

Prolog求解八皇后问题

(1)问题描述
八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

(2)算法解析
首先先描述游戏规则:
1.每个皇后有一个行号和列号,行号和列号的取值范围在1~8之间;
2.一个棋盘上有八个皇后;
3.任意两个皇后不可以共享一行;
4.任意两个皇后不可以共享一列;
5.任意两个皇后不可以在同一个对角线上(左下角->右上角);
6。任意两个皇后不可以在同一个对角线上(右下角->左上角)。
(3)Prolog代码及其解析

/*调用谓词all_different要用的库(clpfd),该谓词用来检查类表中是否有重复元素*/
:- use_module(library(clpfd)). 

/*该函数的作用就是利用谓词member产生在1-8的合法范围之内的列表元素(_,Col)*/
/*类似于函数方法,定义了参数其解的形式 (_,Col)*/
valid_queen((_,Col)) :-
     Range=[1,2,3,4,5,6,7,8],
     member(Col,Range).
     /*表示Col在Range中为真*/

/*递归产生每个元素都是合法元素的列表*/
/*传进一个参数Board=[(1,_),(2,_),(3,_),(4,_),(5,_),(6,_),(7,_),(8,_)],
递归调用valid_queen((_,Col))来填写每个下划线中的内容,最后返回完整合法的Board*/
valid_board([]).
valid_board([Head|Tail]) :- valid_queen(Head),valid_board(Tail).
/*表头是表中第一个元素,而表尾是表中除第一个元素外的其余元素按原来顺序组成的表。*/
/*每次数组加,|就会分为头和剩下的元素,通过递归进行所有合法元素判断*/

/*用户拷贝输出*/
out([],[]).
out([(_,Col)|QueenTail],[Col|MTail]) :-
    out(QueenTail,MTail).
    
/*提取列表组合的列号*/
cols([],[]).
cols([(_,Col)|QueenTail],[Col|ColsTail]) :-
    cols(QueenTail,ColsTail).
/*从头到尾遍历QueenTail列表,将QueenTail中的元素相应的匹配赋值给ColsTail列表的对应元素*/
/*可进行验证
| ?- rows([(1,1),(1,5),(2,5),(2,2),(8,8),(4,4),(4,5),(5,4)],Rows).
     Rows = [1,1,2,2,8,4,4,5]
     yes    */

/*右斜对角线 ,提取列表组合的(列-行)这个定植*/
diags1([],[]).
diags1([(Row,Col)|QueensTail], [Diagonal|DiagonalsTail]) :- 
      Diagonal is Col - Row,
      diags1(QueensTail,DiagonalsTail).
/*可进行验证
| ?- diags1([(2,2),(8,8)],Diags1).
     Diags1 = [0,0]
     yes   */   
      
/*左斜对角线,提取列表组合的(列+行)这个定植*/
diags2([],[]).
diags2([(Row,Col)|QueensTail], [Diagonal|DiagonalsTail]) :- 
      Diagonal is Col + Row,
      diags2(QueensTail,DiagonalsTail).
/*可进行验证
|?- diags2([(4,5),(5,4)],Diags2).
    Diags2 = [9,9]
    yes   */   
     
     
eight_queens(M) :-
/*定义了参数Board其解的形式*/
Board=[(1,_),(2,_),(3,_),(4,_),(5,_),(6,_),(7,_),(8,_)],

/*调用valid_board()得到一个在合法边界范围的列表Borad*/
valid_board(Board),
/*如果下面3个条件满足则表明Board列表是一个解,打印输出*/

/*提取列号,右斜对角线:(行-列),左斜对角线:列+行)*/
cols(Board,Cols),
diags1(Board,Diags1),
diags2(Board,Diags2),

/*元素不存在重复,返回真*/
all_different(Cols),
all_different(Diags1),
all_different(Diags2),

/*化简拷贝Board输出*/
out(Board,M).


(4)实验结果
按;输出下一个组合
按.结束
在这里插入图片描述

验证:
通过VScode之前已经正确通过的C++代码写的程序输出的结果一致,一共有92种方案。
在这里插入图片描述




在这里插入图片描述

实验总结

Prolog编程语言是人工智能应用广泛的逻辑型编程语言,但是其也有一定的限制,其采用的搜索是基于深度优先的搜索,搜索的时间会相对来说慢一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值