人工智能 八数码实验
A星算法求八数码问题实验报告
A星算法求八数码问题实验报告人工智能实验报告实验名称:八数码问题姓名:xx学号:2012210xxxx计算机学院2014年1月14日一.实验目的掌握A*的思想,启发式搜索,来求解在代价最小的情况下将九宫格从一个状态转为另状态的路径。
二.实验内容给定九宫格的初始状态,要求在有限步的操作内,使其转化为目标状态,且所得到的解是代价最小解(2 8 31 6 47 0 52 8 31 6 47 0 5三、A*算法思想:1、思想:A*算法是一种静态路网中求解最短路最有效的直接搜索方法。
估价值与实际值越接近,估价函数取得就越好2、原理:估价函数公式表示为: f(n)=g(n)+h(n),其中 f(n) 是从初始点经由节点n到目标点的估价函数,g(n) 是在状态空间中从初始节点到n节点的实际代价,h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。
但能得到最优解。
并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行此时的搜索效率是最高的。
如果估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
四、算法流程:Heuristic_Search(启发式搜索)While是从未拓展表中删N为目是,输出路径否,生成n的所有子状态Case:此子状Case:此子状Case:此子状计算该子状记录比已有记录比已有返回五、关键技术:1、使用了CreateChild()函数,求得了任意未拓展九宫格的扩展结点,便于拓展子空间,搜索所有情况。
关键代码:bool CreateChild(NOExtend ns[],NOExtend ne){int i,j,k=0;for(i=0;i<3;i++){for(j=0;j<3;j++){if(ne.cur_sudoku.num[i][j]==0){ //寻找九宫格空缺所在的坐标if(i-1>=0){ //将空格向上移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);//先把未改变的九宫格复制给九宫格数组的某一元素ns[k].cur_sudoku.num[i][j]=ne.cur_sudoku.num[i-1][j];//然后仅改变此二维九宫格的两项值即可ns[k].cur_sudoku.num[i-1][j]=0;ns[k].dx=1;k++;}if(j+1<=2){ //将空格向右移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i][j+1];ns[k].cur_sudoku.num[i][j+1]=0;ns[k].dx=1;k++;}if(i+1<=2){ //将空格向下移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i+1][j];ns[k].cur_sudoku.num[i+1][j]=0;ns[k].dx=1;k++;}if(j-1>=0){ //将空格向左移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i][j-1];ns[k].cur_sudoku.num[i][j-1]=0;ns[k].dx=1;k++;}return 1;}}}return 0;2、用启发式搜索函数寻找求解路径,运用了A*算法的思想,能够更快的求解出最优解。
人工智能8位数码难题的问题求解
#define DOWN 1
#define LEFT 2
#define RIGHT 3
#define Bit char
typedef struct maps
{
Bit detail[9];
int myindex; //记录自己节点在hash表中的位置
Bit position; //记录空格(0)在序列中的位置
实验软硬件要求:网络计算机,c++编程环境
实验内容、方法和步骤(可附页)
我们将八数码难题分布在3×3方格棋盘上,分别放置了标有数字1,2,3,4,5,6,7,8的八张牌,初始状态S0,目标状态如图所示,可以使用的操作有:空格上移,空格左移,空格右移,空格下移。我们将是用广度优先搜索算法来解决这一问题。
int newindex = Parent.myindex ;
Bit *p = Parent.detail;
switch(direct)
{
case UP :
{
newindex -= 3*40320 ;
newindex += ( p[ i - 2 ] > p[ i - 3 ]) ? ( Factorial[ p[ i - 3 ] ] ) : ( - Factorial[ p[ i - 2 ] ] );
}p,*PMap;
Map org; //初始状态
int EndIndex; //目标,上移,下移,左移,右移
int const derection[4] ={ -3 , 3 , -1 , 1 } ;
//可移动的四个方向
int const Factorial[9] = {40320 , 5040 , 720 , 120 , 24 , 6 , 2 , 1 , 1 };
人工智能实验总结
总结
宽度优先搜索法
在有解的情形总能保证搜索到最短路经,也 就是移动最少步数的路径。但宽度优先搜索法的 最大问题在于搜索的结点数量太多,因为在宽度 优先搜索法中,每一个可能扩展出的结点都是搜 索的对象。随着结点在搜索树上的深度增大,搜 索的结点数会很快增长,并以指数形式扩张,从 而所需的存储空间和搜索花费的时间也会成倍增 长。
1 2
0 1 0 1
0 0 1 1
0 1 1 0
神经网络设计
用两层神经网络来实现,其中隐层为随机 感知器层(net1),神经网络元数目设计为 3,其权值和阈值是随机的,它的输出作为 输出层(分类层)的输入;输出层为感知 器层(net2),其神经元数为1,这里仅对 该层进行训练。
程序运行结果
随机感知器层的权值向量 iw1 = 0.4267 -0.6556 -0.5439 0.9376 -0.1007 -0.2886 随机感知器层的阈值向量 b1 = 0.4074 0.0441 0.8658
运行结果分析
上面实验结果可以看出,城市数目为30的 时候,当迭代次数为100,算法收敛慢,在 迭代次数内最优解没有达到稳定,没有搜 索到最好的解。 迭代次数为200和250的时候,算法基本达 到收敛,最优解在100代以后趋于稳定,表 明搜索到问题的最优解。
运行结果
当城市数目改变的时候: CityNum=50;最大代数gnmax=100;
程序运行结果
第二层感知器层的权值向量和阈值向量 iw2 = -3 -2 2 b2 = 2
人工智能_八数码实验报告【范本模板】
西安郵電大学人工智能实验报告书(三)学院:自动化学院专业:智能科学与技术班级:智能1403姓名:刘忠强时间:2016—3—29一、实验目的1. 熟悉人工智能系统中的问题求解过程;2。
熟悉状态空间的盲目搜索策略;3.掌握盲目收索算法,重点是宽度优先收索和深度优先收索.二、实验算法广度优先收索是一种先生成的节点先扩展的策略。
它的过程是:从初始节点开始逐层向下扩展,再第n层节点还没有完全搜索之前,不进如第n+1层节点.Open表中的节点总是按进入的先后排序,先进入的节点排在前面,够进入的排在后面。
三、程序框图四、实验结果及分析初始状态:目标状态:2 83 2 1 61 6 4 4 0 87 0 5 7 5 3五、源程序及注释#include <iostream〉#include <ctime>#include 〈vector〉using namespace std;const int ROW = 3;const int COL = 3;const int MAXDISTANCE = 10000;const int MAXNUM = 10000;int abs(int a){if (a>0) return a;else return —a;}typedef struct _Node{int digit[ROW][COL];int dist; // 距离int dep; // 深度int index; // 索引值} Node;Node src, dest;vector〈Node〉 node_v; // 储存节点bool isEmptyOfOPEN(){ //判断Open表是否空for (int i = 0; i 〈 node_v.size(); i++){if (node_v[i]。
dist != MAXNUM)return false;}return true;}bool isEqual(int index, int digit[][COL]) { //判断节点是否与索引值指向的节点相同for (int i = 0; i 〈 ROW; i++)for (int j = 0; j 〈 COL; j++){if (node_v[index].digit[i][j] != digit[i][j])return false;}return true;}ostream& operator<<(ostream& os, Node& node){for (int i = 0; i < ROW; i++) {for (int j = 0; j 〈 COL; j++)os <〈 node。
八数码问题
+0*6!+
3*7!+(98)*
8!=
55596<9!
具体的原因可以去查查一些数学书,其中
123456789的哈希值是
0最小,876543210
的哈希值是(9!1)
最大,而其他值都在
0到(
9!1)
中,且均唯一。
Q5:如何使搜索只求得最佳的解?
要寻找这一系列中间状态的方法是搜索,但搜索很容易遇到时间和空间上的问题。以下就是搜
索的基本原理:
由
137246852状态可以衍生三个状态,假如选择
了
123746855,则又衍生三个状态,继续按某策略进
行选择,一直到衍生出的新状态为目标状态
END为止。
容易看出,这样的搜索类似于从树根开始向茎再向叶
括两步操作
ld,可能与平时玩这类游戏的习惯不符合,但这是为了和
ACM例题相统一。
对应地,每种操作引起的状态变化如下:
r:num值++
l:num值u:
有点复杂
int
t0=
9num%
10+
1
int
t1=
num/1e(t0)
int
t2=
t1%1000
END,所以优先级高。
在计算
difference和
manhattan时,推荐都将空格忽略,因为在
difference中空格可有可无,对整
体搜索影响不大。
考虑下面两个状态(左需要
3步到达
END态,右需要
4步到达
人工智能实验一 八数码问题
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n) 其中 f(n) 是节点 n 的估价函数,g(n)是在状态空间中从初始节点到 n 节点的实际代价, h(n)是从 n 到目标节点最佳路径的估计代价。 在此八数码问题中,显然 g(n)就是从初始状 态变换到当前状态所移动的步数,估计函数 f(n)我们就可采用当前状态各个数字牌不在目标
附录—源代码及其注释 #include "stdafx.h" #include "iostream.h" #include <time.h> #include <stdio.h> #include <dos.h> #include <conio.h> static int target[9]={1,2,3,8,0,4,7,6,5}; //class definition
eight_num(int init_num[9]); eight_num(int num1,int num2,int num3,int num4,int num5,int num6,int num7,int num8,int num9) {
num[0]=num1; num[1]=num2; num[2]=num3; num[3]=num4; num[4]=num5; num[5]=num6; num[6]=num7; num[7]=num8; num[8]=num9; } eight_num(void) { for (int i=0;i<9;i++)
八数码问题人工智能实验报告
基于人工智能的状态空间搜索策略研究——八数码问题求解(一)实验软件或编程语言或其它编程语言(二)实验目的1. 熟悉人工智能系统中的问题求解过程;2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用;3. 熟悉对八数码问题的建模、求解及编程语言的应用。
(三)需要的预备知识1. 熟悉或编程语言或者其它编程语言;2. 熟悉状态空间的宽度优先搜索、深度优先搜索和启发式搜索算法;3. 熟悉计算机语言对常用数据结构如链表、队列等的描述应用;4. 熟悉计算机常用人机接口设计。
(四)实验数据及步骤1. 实验内容八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。
437465图1 八数码问题示意图请任选一种盲目搜索算法(深度优先搜索或宽度优先搜索)或任选一种启发式搜索方法(A 算法或 A* 算法)编程求解八数码问题(初始状态任选),并对实验结果进行分析,得出合理的结论。
2. 实验步骤(1)分析算法基本原理和基本流程;程序采用宽度优先搜索算法,基本流程如下:(2)确定对问题描述的基本数据结构,如 Open 表和 Closed 表等;(3)编写算符运算、目标比较等函数;(4)编写输入、输出接口;(5)全部模块联调;(6)撰写实验报告。
(五)实验报告要求所撰写的实验报告必须包含以下内容:1. 算法基本原理和流程框图;2. 基本数据结构分析和实现;3. 编写程序的各个子模块,按模块编写文档,含每个模块的建立时间、功能、输入输出参数意义和与其它模块联系等;4. 程序运行结果,含使用的搜索算法及搜索路径等;5. 实验结果分析;6. 结论;7. 提供全部源程序及软件的可执行程序。
附:实验报告格式一、实验问题二、实验目的三、实验原理四、程序框图五、实验结果及分析六、结论。
人工智能实验报告,包括八数码问题八皇后问题和tsp问题
八数码问题(一)问题描述在一个3*3的方棋盘上放置着1,2,3,4,5,6,7,8八个数码,每个数码占一格,且有一个空格。
这些数码可以在棋盘上移动,其移动规则是:与空格相邻的数码方格可以移入空格。
现在的问题是:对于指定的初始棋局和目标棋局,给出数码的移动序列。
该问题称八数码难题或者重排九宫问题。
(二)问题分析八数码问题是个典型的状态图搜索问题。
搜索方式有两种基本的方式,即树式搜索和线式搜索。
搜索策略大体有盲目搜索和启发式搜索两大类。
盲目搜索就是无“向导”的搜索,启发式搜索就是有“向导”的搜索。
1、启发式搜索由于时间和空间资源的限制,穷举法只能解决一些状态空间很小的简单问题,而对于那些大状态空间的问题,穷举法就不能胜任,往往会导致“组合爆炸”。
所以引入启发式搜索策略。
启发式搜索就是利用启发性信息进行制导的搜索。
它有利于快速找到问题的解。
由八数码问题的部分状态图可以看出,从初始节点开始,在通向目标节点的路径上,各节点的数码格局同目标节点相比较,其数码不同的位置个数在逐渐减少,最后为零。
所以,这个数码不同的位置个数便是标志一个节点到目标节点距离远近的一个启发性信息,利用这个信息就可以指导搜索。
即可以利用启发信息来扩展节点的选择,减少搜索范围,提高搜索速度。
启发函数设定。
对于八数码问题,可以利用棋局差距作为一个度量。
搜索过程中,差距会逐渐减少,最终为零,为零即搜索完成,得到目标棋局。
(三)数据结构与算法设计该搜索为一个搜索树。
为了简化问题,搜索树节点设计如下:struct Chess//棋盘{int cell[N][N];//数码数组int Value;//评估值Direction BelockDirec;//所屏蔽方向struct Chess * Parent;//父节点};int cell[N][N]; 数码数组:记录棋局数码摆放状态。
int Value; 评估值:记录与目标棋局差距的度量值。
Direction BelockDirec; 所屏蔽方向:一个屏蔽方向,防止回推。
人工智能实验报告八数码
人工智能实验报告八数码
人工智能实验报告:八数码
引言
人工智能(AI)是当今世界上最热门的领域之一,它已经在许多领域取得了巨大的成功,包括医疗保健、金融、交通和娱乐等。
在这篇实验报告中,我们将探讨人工智能在解决八数码问题上的应用。
八数码问题是一个经典的智力游戏,它要求玩家将一个3x3的方格中的数字1-8和一个空白格按照一定的规则进行移动,最终达到特定的排列顺序。
这个问题看似简单,但实际上是一个复杂的组合优化问题,需要大量的搜索和计算才能找到最优解。
实验目的
本实验旨在使用人工智能技术解决八数码问题,通过比较不同算法的表现,评估它们在解决这一问题上的效率和准确性。
实验方法
我们使用了两种经典的人工智能算法来解决八数码问题,分别是深度优先搜索(DFS)和A*搜索算法。
我们编写了相应的程序,并在相同的硬件环境下进行了实验。
实验结果
通过实验我们发现,深度优先搜索算法在解决八数码问题上存在着局部最优解的问题,容易陷入死循环。
而A*搜索算法则能够更快地找到最优解,并且在解决问题时所需的搜索次数更少。
结论
本实验结果表明,A*搜索算法在解决八数码问题上表现更优秀,具有更高的效率和准确性。
这为我们在实际应用中选择合适的人工智能算法提供了重要的参考。
未来展望
随着人工智能技术的不断发展,我们相信在解决类似的组合优化问题上会出现更多更高效的算法。
我们将继续深入研究,探索更多的人工智能算法,并将其应用于更广泛的领域,为人类社会带来更多的便利和创新。
人工智能-A算法求解8数码问题
实验四 A*算法求解8数码问题一、实验目的熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解8数码难题,理解求解流程和搜索顺序。
二、实验原理A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。
对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。
因此,f 是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价g(n)以及从节点n 到达目标节点的估价代价h(n),且h(n)<=h*(n),h*(n)为n节点到目标节点的最优路径的代价。
八数码问题是在3×3的九宫格棋盘上,排放有8个刻有1~8数码的将牌。
棋盘中有一个空格,允许紧邻空格的某一将牌可以移到空格中,这样通过平移将牌可以将某一将牌布局变换为另一布局。
针对给定的一种初始布局或结构(目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。
如图1所示表示了一个具体的八数码问题求解。
图1 八数码问题的求解三、实验内容1、参考A*算法核心代码,以8数码问题为例实现A*算法的求解程序(编程语言不限),要求设计两种不同的估价函数。
2、在求解8数码问题的A*算法程序中,设置相同的初始状态和目标状态,针对不同的估价函数,求得问题的解,并比较它们对搜索算法性能的影响,包括扩展节点数、生成节点数等。
3、对于8数码问题,设置与图1所示相同的初始状态和目标状态,用宽度优先搜索算法(即令估计代价h(n)=0的A*算法)求得问题的解,记录搜索过程中的扩展节点数、生成节点数。
4、提交实验报告和源程序。
四.实验截图五.源代码#include<iostream>#include"stdio.h"#include"stdlib.h"#include"time.h"#include"string.h"#include<queue>#include<stack>using namespace std;const int N=3;//3*3棋?盘ìconst int Max_Step=32;//最?大洙?搜?索÷深?度èenum Direction{None,Up,Down,Left,Right};//方?向ò,?分?别纄对?应畖上?下?左哩?右?struct Chess//棋?盘ì{int chessNum[N][N];//棋?盘ì数簓码?int Value;//评à估à值μDirection BelockDirec;//所ù屏á蔽?方?向òstruct Chess * Parent;//父?节ú点?};void PrintChess(struct Chess *TheChess);//打洙?印?棋?盘ìstruct Chess * MoveChess(struct Chess * TheChess,Direction Direct,bool CreateNewChess);//移?动ˉ棋?盘ì数簓字?int Appraisal(struct Chess * TheChess,struct Chess * Target);//估à价?函ˉ数簓struct Chess * Search(struct Chess* Begin,struct Chess * Target);//A*搜?索÷函ˉ数簓int main(){//本?程ì序ò的?一?组哩?测a试?数簓据Y为a/*初?始?棋?盘ì*1 4 0**3 5 2**6 7 8**//*目?标括?棋?盘ì*0 1 2**3 4 5**6 7 8**/Chess Target;Chess *Begin,*ChessList;Begin=new Chess;int i;cout<<"请?输?入?初?始?棋?盘ì,?各÷数簓字?用?空?格?隔?开a:阰"<<endl;for(i=0;i<N;i++){for(int j=0;j<N;j++){cin>>Begin->chessNum[i][j];}}cout<<"请?输?入?目?标括?棋?盘ì,?各÷数簓字?用?空?格?隔?开a:阰"<<endl;for(i=0;i<N;i++){for(int j=0;j<N;j++){cin>>Target.chessNum[i][j];}}//获?取?初?始?棋?盘ìAppraisal(Begin,&Target);Begin->Parent=NULL;Begin->BelockDirec=None;Target.Value=0;cout<<"初?始?棋?盘ì:";PrintChess(Begin);cout<<"目?标括?棋?盘ì:";PrintChess(&Target);ChessList=Search(Begin,&Target);//搜?索÷//打洙?印?if(ChessList){/*将?返う?回?的?棋?盘ì列表括?利?用?栈?将?其?倒?叙e*/Chess *p=ChessList;stack<Chess *>Stack;while(p->Parent!=NULL){Stack.push(p);p=p->Parent;}cout<<"搜?索÷结á果?:"<<endl;int num=1;while(!Stack.empty()){cout<<"第台?<<num<<"步?: ";num++;PrintChess(Stack.top());Stack.pop();}cout<<"\n完?成é!"<<endl;}elsecout<<"搜?索÷不?到?结á果?,?搜?索÷深?度è大洙?于?2\n"<<endl;return 0;}//打洙?印?棋?盘ìvoid PrintChess(struct Chess *TheChess){cout<<"(评à估à值μ为a";cout<<TheChess->Value;cout<<")"<<endl;for(int i=0;i<N;i++){cout<<" ";for(int j=0;j<N;j++){cout<<TheChess->chessNum[i][j]<<" ";}cout<<endl;}}//移?动ˉ棋?盘ìstruct Chess * MoveChess(struct Chess * TheChess,Direction Direct,bool CreateNewChess) {struct Chess * NewChess;//获?取?空?闲D格?位?置?int i,j;for(i=0;i<N;i++){bool HasGetBlankCell=false;for(j=0;j<N;j++){if(TheChess->chessNum[i][j]==0){HasGetBlankCell=true;break;}}if(HasGetBlankCell)break;}int ii=i,jj=j;bool AbleMove=true;//判D断?是?否?可é以?移?动ˉswitch(Direct){case Up:i++;if(i>=N)AbleMove=false;break;case Down:i--;if(i<0)AbleMove=false;break;case Left:j++;if(j>=N)AbleMove=false;break;case Right:j--;if(j<0)AbleMove=false;break;};if(!AbleMove)//不?可é以?移?动ˉ则ò返う?回?原-节ú点?{return TheChess;}if(CreateNewChess){NewChess=new Chess();for(int x=0;x<N;x++){for(int y=0;y<N;y++)NewChess->chessNum[x][y]=TheChess->chessNum[x][y];//创洹?建¨新?棋?盘ì,?此?时骸?值μ与?原-棋?盘ì一?致?}}elseNewChess=TheChess;NewChess->chessNum[ii][jj] = NewChess->chessNum[i][j];//移?动ˉ数簓字?NewChess->chessNum[i][j]=0;//将?原-数簓字?位?置?设Θ?置?为a空?格?return NewChess;}//估à价?函ˉ数簓int Appraisal(struct Chess * TheChess,struct Chess * Target){int Value=0;for(int i=0;i<N;i++){for(int j=0;j<N;j++){if(TheChess->chessNum[i][j]!=Target->chessNum[i][j])Value++;}}TheChess->Value=Value;return Value;}//A*搜?索÷函ˉ数簓struct Chess * Search(struct Chess* Begin,struct Chess * Target){Chess *p1,*p2,*p;int Step=0;//深?度èp=NULL;queue<struct Chess *> Queue;Queue.push(Begin);//初?始?棋?盘ì入?队ó//搜?索÷do{p1=(struct Chess *)Queue.front();Queue.pop();//出?队ófor(int i=1;i<=4;i++)//分?别纄从洙?四?个?方?向ò推?导?出?新?子哩?节ú点? {Direction Direct=(Direction)i;if(Direct==p1->BelockDirec)//跳?过y屏á蔽?方?向òcontinue;p2=MoveChess(p1,Direct,true);//移?动ˉ数簓码?if(p2!=p1)//数簓码?是?否?可é以?移?动ˉ{Appraisal(p2,Target);//对?新?节ú点?估à价?if(p2->Value<=p1->Value)//是?否?为a优?越?节ú点?{p2->Parent=p1;switch(Direct)//设Θ?置?屏á蔽?方?向ò,防え?止1往?回?推?{case Up:p2->BelockDirec=Down;break;case Down:p2->BelockDirec=Up;break;case Left:p2->BelockDirec=Right;break;case Right:p2->BelockDirec=Left;break;}Queue.push(p2);//存?储洹?节ú点?到?待鋣处鋦理え?队ó列if(p2->Value==0)//为a0则ò,搜?索÷完?成é{p=p2;i=5;}}else{delete p2;//为a劣ⅷ?质ê节ú点?则ò抛×弃úp2=NULL;}}}Step++;if(Step>Max_Step)return NULL;}while(p==NULL || Queue.size()<=0);return p;}六、实验报告要求1、分析不同的估价函数对A*搜索算法性能的影响等。
人工智能实验报告 八数码问题
实验一 启发式搜索算法姓名:徐维坚 学号:2220103484 日期:2012/6/29一、实验目的:熟练掌握启发式搜索A *算法及其可采纳性。
二、实验内容:使用启发式搜索算法求解8数码问题。
1) 编制程序实现求解8数码问题A *算法,采用估价函数()()()()w n f n d n p n ⎧⎪=+⎨⎪⎩, 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。
2) 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是()p n 的上界 的()h n 的定义,并测试使用该估价函数是否使算法失去可采纳性。
三、实验原理:1. 问题描述:八数码问题也称为九宫问题。
在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。
棋盘上还有一个空格(以数字0来表示),与空格相邻的棋子可以移到空格中。
要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。
所谓问题的一个状态就是棋子在棋盘上的一种摆法。
解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
2. 原理描述:2.1 有序搜索算法:(1)原理:在搜索过程中,OPEN 表中节点按照其估价函数值以递增顺序排列,选择OPEN 表中具有最小估价函数值的节点作为下一个待扩展的节点,这种搜索方法称为有序搜索。
在本例中,估价函数中的)(n g 取节点深度)(n d ,)(n h 为节点n 的状态与目标状态之间错放的个数,即函数)(n ω。
(2)算法描述:① 把起始节点S 放到OPEN 表中,并计算节点S 的)(S f ;② 如果OPEN 是空表,则失败退出,无解;③ 从OPEN 表中选择一个f 值最小的节点i 。
如果有几个节点值相同,当其中有一个 为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点i ;④ 把节点i 从 OPEN 表中移出,并把它放入 CLOSED 的已扩展节点表中;⑤ 如果i 是个目标节点,则成功退出,求得一个解;⑥ 扩展节点i ,生成其全部后继节点。
人工智能 八数码难题
实验报告课程名称人工智能_____________实验项目八数码难题______________实验仪器电脑、visual C++_________系别____________ 专业__ _____班级/学号学生姓名_ _________实验日期____成绩_______________________指导教师_________一、实验目的理解并熟悉掌握深度优先搜索和广度优先搜索地方法。
二、实验内容九宫格中有8个数码,其中只有一个空,规则是只能把一个数码移动到空的格子中,要求从一个初始状态移动到一个目标状态所要花费的最少步数【算法分析】解决此类问题的办法是宽度搜索,深度搜索耗时太大无法接受。
当需要移动的步数很多时,普通的宽度搜索仍旧无法满足需要,需要对其进行优化。
这个问题也可以推广到流行的拼图游戏。
【具体步骤】一、确定问题规模(考虑搜索的时间代价)二、确定产生式规则(如果规则太多,则时间代价会很大)三、套用经典宽度搜索框架写程序三、代码和结果#include <stdlib.h>#include <stdio.h>typedef struct Node {int num[9]; //棋盘状态int deepth; //派生的深度g(n)int diffnum; //不在位的数目h(n)int value; //耗散值f(n)=g(n)+h(n)struct Node * pre;struct Node * next;struct Node * parent;}numNode; /* ---------- end of struct numNode ---------- */int origin[9]; //棋盘初始状态int target[9]; //棋盘目标状态int numNode_num,total_step;numNode *open,*close; //Open表和Close表numNode *create_numNode(){return (numNode *)malloc(sizeof(numNode));}numNode *open_getfirst(numNode *head); //返回第一项,并从Open表中删除void open_insert(numNode *head,numNode *item); //向Open表中按序插入新节点void close_append(numNode *head,numNode *item); //向Close表中插入新节点int expand(numNode *item); //扩展节点int print_result(numNode *item); //打印结果numNode *copy_numNode(numNode *orgin);char isNewNode(numNode *open,numNode *close,int num[9]);//是否在Open表或Close表中void print_num(int num[9]); //打印棋盘状态int diff(int num[9]); //求不在位棋子的个数void init(); //初始化,获得棋盘初始状态和目标状态void swap(int *a,int *b);int operate(int num[],int op);void free_list(numNode *head);/** === FUNCTION ======================================================================* Name: 主函數* Description: 程序入口*=============================================================================== ======*/intmain ( int argc, char *argv[] ){//初始化Open表和Close表open=create_numNode();close=create_numNode();open->pre=open->next=close->pre=close->next=NULL;init(); //由用户输入初始和目标状态//初始化初始节点numNode *p1;p1=create_numNode();p1->parent=NULL;p1->deepth=0;int i=0;for ( i=0; i<9; i++){p1->num[i]=origin[i];}open_insert(open,p1);numNode_num=1;p1=open_getfirst(open);while (p1!=NULL){close_append(close,p1);if(expand(p1))return EXIT_SUCCESS;p1=open_getfirst(open);}printf("No solution!\n");return EXIT_SUCCESS;} /* ---------- end of function main ---------- */voidinit ( ){while(1){printf("Please input opriginal status:\nFor example:123456780 stands for\n""1 2 3\n""4 5 6\n""7 8 0\n");char temp[10];scanf("%s",&temp);int i=0;for ( i=0;i<9 && temp[i]-'0'>=0 && temp[i]-'0'<=8; i++) {origin[i]=temp[i]-'0';}printf("Please input target status:\n");scanf("%s",&temp);int j=0;for ( j=0; j<9 && temp[j]-'0'>=0 && temp[j]-'0'<=8; j++){target[j]=temp[j]-'0';}system("cls");if ( i==9&&j==9){break;}}} /* ----- end of function init ----- */voidopen_insert (numNode *head,numNode *item){numNode *p,*q;p=head->next;q=head;while ( p!=NULL && item->value > p->value ){q=p;p=p->next;}q->next=item;item->pre=q;item->next=p;if(p!=NULL){p->pre=item;}} /* ----- end of function open_insert ----- */numNode *open_getfirst (numNode *head){numNode *p;if ( head->next == NULL ){return NULL;}p=head->next;head->next=p->next;if ( p->next != NULL ){p->next->pre=head;}p->pre=NULL;p->next=NULL;return p;} /* ----- end of function open_getfirst ----- */voidclose_append (numNode *head,numNode *item) {item->next=head->next;item->pre=head;head->next=item;if ( item->next!=NULL ){item->next->pre=item;}} /* ----- end of function close_append ----- */intexpand (numNode *p1){numNode * p2;int op=1;for ( op=1; op<=4; op++){p2=copy_numNode(p1);operate(p2->num,op);if(isNewNode(open,close,p2->num)=='N'){p2->parent=p1;p2->deepth=p1->deepth+1;p2->diffnum=diff(p2->num);p2->value=p2->deepth+p2->diffnum;if(p2->diffnum==0){total_step=print_result(p2);printf("Total step: %d\n",total_step);free_list(open);free_list(close);return 1;}else{numNode_num++;open_insert(open,p2);}}elsefree(p2);}return 0;} /* ----- end of function expand ----- */intoperate(int m[], int op){int blank;blank=0;while (m[blank]!=0 && blank<9 )++blank;if (blank==9)return 1;switch (op) {case 1: /* up */if (blank>2)swap(m+blank,m+blank-3);break;case 2: /* down */if (blank<6)swap(m+blank,m+blank+3);break;case 3: /* left */if (blank!=0 && blank!=3 && blank!=6)swap(m+blank,m+blank-1);break;case 4: /* right */if (blank!=2 && blank!=5 && blank!=8)swap(m+blank,m+blank+1);break;default : return 1;}return 0;}voidswap(int *a, int *b){int c;c=*a;*a=*b;*b=c;}numNode *copy_numNode (numNode *origin){numNode *p;p=create_numNode();p->deepth=origin->deepth;p->diffnum=origin->diffnum;p->value=origin->value;int i;for ( i=0; i<9; i++){(p->num)[i]=(origin->num)[i];}return p;} /* ----- end of function copy_numNode ----- */intdiff (int num[9]){int i,diffnum=0;for(i=0;i<9;i++)if(num[i]!=target[i])diffnum++;return diffnum;} /* ----- end of function diff ----- */charisNewNode (numNode *open,numNode *close,int num[9]) {numNode *p;int i=0;p=open->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'O'; //Openp=p->next;}p=close->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'C'; //Closep=p->next;}return 'N';} /* ----- end of function isNewNode ----- */voidfree_list (numNode *head){numNode *p,*q;p=head->next;while ( p!=NULL ){q=p->next;free(p);p=q;}free(head);} /* ----- end of function free_list ----- */voidprint_num (int num[9]){int i;for ( i=0; i<9; i++){printf("%d\t",num[i]);if((i%3)==2)printf("\n");}} /* ----- end of function print_num ----- */intprint_result ( numNode *item){numNode *p;int step;p=item;if(p!=NULL){step=print_result(p->parent);printf("\nStep %d:\n",step+1);print_num(p->num);return step+1;}else{return -1;}}四.实验心得这次试验让我更加深入了解了什么是人工智能,让我了解了人工智能的作用以及含义和人工智能的使用范围以及对于我们未来生活得作用的广大。
人工智能-八数码游戏问题
if(The_graph->form[i][j]!=End_graph->form[i][j])
{
valute++;
}
}
}
The_graph->evalue=valute;
return valute;
}
/////////移动数码组
Graph *Move(Graph *The_graph,int Direct,int CreatNew_graph)
e、判断压入队的子节点数码组(优越点)的评估值,为零则表示搜索完成,退出搜索;
f、跳到步骤2;
四、数据结构的设计
数码结构体
typedef struct node//八数码结构体
{
int form[N][N];//数码组
int evalue;//评估值,差距
int udirec;//所屏蔽方向,防止往回推到上一状态,1上2下3左4右
struct node *parent;//父节点
}Graph;
Graph *Qu[MAX]; //队列
Graph *St[MAX]; //堆栈
/////////打印数码组
void Print(;
if(The_graph==NULL)
printf("图为空\n");
#define N 3 //数码组大小
#define Max_Step 50 //最大搜索深度
#define MAX 50
typedef struct node//八数码结构体
{
int form[N][N];//数码组
int evalue;//评估值
int udirect;//所屏蔽方向,防止往回推到上已状态,1上2下3左4右
人工智能导论实验一 基于图搜索技术的八数码问题求解
广州大学学生实验报告开课学院及实验室:计算机科学与工程实验室 2020年10月14日(***报告只能为文字和图片,老师评语将添加到此处,学生请勿作答***)一、实验内容1. 分别用广度优先搜索策略、深度优先搜索策略和启发式搜索算法(至少两种)求解八数码问题;分析估价函数对启发式搜索算法的影响;探究讨论各个搜索算法的特点。
二、实验设备1. 实验设备:计算机;2. 平台:Windows操作系统,Visual C++ 6.0 / Python Anaconda三、实验步骤1. 随机生成一个八数码问题分布,设计一个可解的目标状态(要求棋盘9个位置都不同)2. 分别用广度优先搜索策略、深度优先搜索策略和至少两种启发式搜索算法求解八数码问题3. 分析估价函数对启发式搜索算法的影响4. 探究讨论各个搜索算法的特点四、分析说明(包括核心代码及解释)广度优先搜索:首先创建一个结构体node,来记录节点移动方向和扩展的节点。
struct node{int ab[3][3];//节点int direction;//方向};struct node sh[102], end;int count = 1;然后创建一个init函数来初始化棋盘起始状态和目标状态,使用for语句填写棋盘数字用loction函数确定0节点的位置,通过for语句和if语句判断sh[num].ab[i / 3][i % 3] == 0,即可得到0节点的位置Sign函数用来获取棋盘状态,将当前棋盘数字顺序生成一个数,即可得知棋盘状态。
Mobile函数用来移动0节点,先用loction函数获取0节点的位置,再通过if语句来判断0节点位置和所能移动方向,然后进行移动。
Display函数使用for语句来打印当前棋盘。
Search函数使用display函数来打印从初始状态移动到目标状态的中间状态棋盘,在while(1)语句下利用mobile函数移动0节点,直到目标状态找到或者超过寻找次数。
人工智能八数码游戏
实验一:八数码游戏问题一、八数码游戏问题简介九宫排字问题(又称八数码问题)是人工智能当中有名的难题之一。
问题是在3X3方格盘上,放有八个数码,剩下第九个为空,每一空格其上下左右的数码可移至空格。
问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始位置转化为目标位置。
(a)初始状态小)目标状态图八数码游戏二、实验目的1.熟悉人工智能系统中的问题求解过程;2.熟悉状态空间的盲目搜索和启发式搜索算法的应用;3.熟悉对八数码问题的建模、求解及编程语言的应用。
三、实验的思路八数码问题:在3X3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。
例如:(a)初始状态图1八数码问题示意图1 .启发函数设定由八数码问题的部分状态图可以看出,从初始节点开始,在通向目标节点的 路径上,各节点的数码格局同目标节点相比较,其数码不同的位置个数在逐渐减 少,最后为零,因此可以把数码不同的位置个数作为标志一个节点到目标节点距 离远近的一个启发性信息,利用这个信息来扩展节点的选择,减少搜索范围,提 高搜索速度。
2 .搜索过程:(搜索采用广度搜索方式,利用待处理队列辅助,逐层搜索(跳过 劣质节点))a 、把初始数码组压入队列;b 、从队列中取出一个数码组节点;c 、扩展子节点,即从上下左右四个方向移动空格,生成相应子节点:d 、对子节点数码组作评估,是否为优越节点,即其评估值是否小于等于其 父节点加一,是则将其压入队,否则抛弃。
e 、判断压入队的子节点数码组(优越点)的评估值,为零则表示搜索完成, 退出搜索;f 、跳到步骤2;四、数据结构的设计//八数码结构体 //数码组 //评估值,差距//所屏蔽方向,防止往回推到上一状态,1上2下3左4//父节点数码结构体typedef struct node(int form[N][N];int evalue;int udirec; 右 struct node *parent;}Graph;Graph *Qu[MAX];//队列Graph *St[MAX];//堆栈起始成功是否有后继节点为目标节点?... 是否open 表为空表? ..否 否 是是—工失败扩展节点n ,把其后裔放入open 表的前头把open 表中的第一个节点n移入close 表把s 放入open 表五、实验过程及代码#include <stdio.h> } 〃设计了搜索深度范围,防止队列内存越界#include <stdlib.h> #include <time.h>#define N 3 〃数码组大小#define Max_Step 50 //最大搜索深度#define MAX 50typedef struct node//八数码结构体( int form[N][N];//数码组int evalue;//评估值int udirect;〃所屏蔽方向,防止往回推到上已状态,1上2下3左4右struct node "parentJ/父节点}Graph;Graph *Qu[MAX]; 〃队列Graph *St[MAX]; 〃堆栈/////////打印数码组void Print(Graph *The_graph) ( int i,j; if(The_graph==NULL) printf("图为空\n"); else ( printf(" -------------------------- \n");for(i=0;i<N;i++) ( printf("|\t"); for(j=0;j<N;j++)( printf("%d\t",The_graph->form[i][j]);/遍历打印} printf("\t|\n");} printf("|\t\t\t 差距:%d\t|\n",The_graph->evalue);//差距显示printf(" ----------------- \n");〃〃〃〃/评价函数int Evaluate(Graph *The_graph,Graph *End_graph)(int 丫21a©=0;//差距数int i,j;for(i=0;i<N;i++)(for(j=0;j<N;j++)(if(The_graph->form[i][j]!=End_graph->form[i][j])(valute++;)))The_graph->evalue=valute;return valute;)/////////移动数码组Graph *Move(Graph *The_graph,int Direct,int CreatNew_graph) (Graph *New_graph;int HasGetBlank=0;//是否获取空格位置int Ab1eMove=1;//是否可移动int i,j,t_i,t_j,x,y;for(i=0;i<N;i++)//获取空格坐标i,j(for(j=0;j<N;j++)(if(The_graph->form[i][j]==0)(HasGetBlank=1;break;))if(HasGetBlank==1)break;)//printf("空格位置:%d,%d\n”,i,j);t_i=i;t_j=j;〃移动空格switch(Direct) (case 1:〃上t_i--;if(t_i<0)AbleMove=0;break;case 2:〃下t_i++;if(t_i>=N)AbleMove=0;break;case 3:〃左t_j--;if(t_j<0)AbleMove=0;break;case 4:〃右t_j++; if(t_j>=N)AbleMove=0; break;)if(AbleMove==0)//不能移动则返回原节点(return The_graph;)if(CreatNew_graph==1)(New_graph=(Graph *)malloc(sizeof(Graph));//生成节点for(x=0;x<N;x++) ( for(y=0;y<N;y++)(New_graph->form[x][y]=The_graph->form[x][y];/复制数码组)) else(New_graph=The_graph;)〃移动后New_graph->form[i][j]=New_graph->form[t_i][t_j];New_graph->form[t_i][t_j]=0;//printfC移动产生的新图:\n");//Print(New_graph);return New_graph;)/////////搜索函数Graph *Search(Graph *Begin,Graph *End) (Graph *g1,*g2,*g;int Step=0;//^^int Direct=0;//方向int i;int front,rear;front=rear=-1;//队列初始化g=NULL;rear++;//A^Qu[rear]=Begin;while(rear!=front)//队列不空(front++;//出队g1=Qu[front];//printf("开始第%d 个图:\n",front);//Print(g1);代班=1;1<=4计+)//分别从四个方向推导出新子节点(Direct=i;if(Direct==g1->udirect)//跳过屏蔽方向continue;g2=Move(g1, Direct, 1);//移动数码组if(g2!=g1)//数码组是否可以移动(〃可以移动Evaluate(g2, End);//评价新的节点//printfC开始产生的第%d个图:\n",i);//Print(g2);if(g2->evalue<=g1->evalue+1) (〃是优越节点g2->parent=g1;〃移动空格switch①irect)//设置屏蔽方向,防止往回推(case 1://上g2->udirect=2;break;case 2://下g2->udirect=1;break;case 3://左g2->udirect=4;break;case 4://右g2->udirect=3; break;)rear++;Qu[rear]=g2;//存储节点到待处理队列if(g2->evalue==0)〃为0 则搜索完成(g=g2;//i=5;break;))else(free(g2);//抛弃劣质节点g2=NULL;)))if(g!=NULL)〃为0则搜索完成(if(g->evalue==0)(break;Step++;//统计深度if(Step>Max_Step) (break;))return g;) int main (int argc, const char * argv[])(// insert code here...Graph Begin_graph={{{2,8,3},{1,6,4},{7,0,5}},0,0,NULL);/*Graph Begin_graph={{{2,8,3},{1,0,4},{7,6,5}},0,0,NULL };Graph Begin_graph={{{2,0,1},{4,6,5},{3,7,8}},0,0,NULL};*///目标数码组Graph End_graph={{{1,2,3},{8,0,4},{7,6,5}},0,0,NULL };Evaluate(&Begin_graph, &End_graph);//对初始的数码组评价printf("初始数码组:\n");Print(&Begin_graph);printf("目标数码组:\n");Print(&End_graph);Graph *G,*P;int top=-1;〃图搜索G=Search(&Begin_graph, &End_graph);〃打印if(G)(〃把路径倒序P=G;〃压栈while(P!=NULL)(top++;St[top]=P;P=P->parent;}printf("vvvvvvvvvvvvvvv 搜索结果〃弹栈打印while(top>-l)(P=St[top];top-;Print(P);}printf("««««««««<^^»»»»»»»»»\n"); } else(printf("搜索不到结果,深度为%d\n",Max_Step);〃设计搜索深度范围主要是防止队列内存越界return 0;六、实验结果。
八数码问题,实验报告
八数码问题,实验报告八数码实验报告利用人工智能技术解决八数码游戏问题1.八数码游戏问题简介九宫排字问题(又称八数码问题)是人工智能当中有名的难题之一。
问题是在3×3方格盘上,放有八个数码,剩下第九个为空,每一空格其上下左右的数码可移至空格。
问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始位置转化为目标位置。
2.八数码游戏问题的状态空间法表示①建立一个只含有初始节点S0的搜索图G,把S0放入OPEN表中②建立CLOSED表,且置为空表③判断OPEN表是否为空表,若为空,则问题无解,退出④选择OPEN表中的第一个节点,把它从OPEN表移出,并放入CLOSED表中,将此节点记为节点n⑤考察节点n是否为目标节点,若是,则问题有解,成功退出。
问题的解就是沿着n到S0的路径得到。
若不是转⑥⑥扩展节点n生成一组不是n的祖先的后继节点,并将它们记为集合M,将M中的这些节点作为n的后继节点加入图G中⑦对未在G中出现过的(OPEN和CLOSED表中未出现过的)集合M中的节点, 设置一个指向父节点n的指针,并把这些节点放入OPEN表中;对于已在G中出现过的M中的节点,确定是否需要修改指向父节点的指针;对于已在G中出现过并已在closed表中的M中的节点,确定是否需要修改通向他们后继节点的指针。
⑧按某一任意方式或某种策略重排OPEN表中节点的顺序⑨转③3.八数码游戏问题的盲目搜索技术宽度优先搜索:1、定义如果搜索是以接近起始节点的程度依次扩展节点的,那么这种搜索就叫做宽度优先搜索(breadth-first search)。
2、特点这种搜索是逐层进行的;在对下一层的任一节点进行搜索之前,必须搜索完本层的所有节点。
3、宽度优先搜索算法(1) 把起始节点放到OPEN表中(如果该起始节点为一目标节点,则求得一个解答)。
(2) 如果OPEN是个空表,则没有解,失败退出;否则继续。
(3) 把第一个节点(节点n)从OPEN表移出,并把它放入CLOSED 的扩展节点表中。
武汉理工大学人功智能概论八数码实验报告
武汉理工大学学生实验报告书实验课程名称人工智能概论B 实验名称八数码问题开课学院计算机科学与技术学院指导老师姓名学生姓名学号学生专业班级2016 —2017 学年第一学期一、实验要求及问题描述采取分组形式,2人一组,一人使用盲目搜索中的宽度优先搜索算法,另一人使用启发式搜索中的全局择优搜索或A*算法。
每组提交一份大作业报告,该报告包括设计、实现、测试、实验对比结果分析、结论、个人体会与总结。
提交截止时间:2016.11.18对任意的八数码问题,给出求解结果。
例如:对于如下具体八数码问题:⇨通过设计启发函数,编程实现求解过程,如果问题有解,给出数码移动过程,否则,报告问题无解。
250 123873 804641 765二、实验原理2.1 状态空间表示1、建立只有初始节点S0的搜索图,并将S放入OPEN表中;2、建立CLOSE表并置空;3、对OPEN表进行判断,若OPEN表为空,则无解;4、将OPEN表中的第一个节点移出,放入CLOSE表中,记为节点n;5、判断节点n是否为目标节点。
是,则有解,解为沿n到S的路径,否,则进行步骤6;6、由节点n生成一组不是n的祖先的后继节点,记为集合P,将P中节点作为n的后继加入搜索图;7、对于在OPEN表和CLOSE表中没有出现过的集合P中的节点,设置指向节点n的指针,把这些节点放入OPEN表中;对于在OPEN表和CLOSE表中已经出现过的P中的节点,确定是否修改指向父节点的指针;8、重拍OPEN表节点顺序;9、转到步骤3。
2.2 数据结构设计//宽度优先搜索中,八数码地图节点结构体struct EightDigit{int Cube[3][3];Direction LastDirection;struct EightDigit *Parent;};//全局择优搜索中,八数码节点结构体struct node{int index;//结点序号int p_index;//父结点序号int matrix[3][3];// 八数码状态int h_function;//启发式函数值};node open[SIZE]; //存放已经生成的未考察的节点node closed[SIZE]; //存放已经考察过得节点2.3 启发式函数与相关算法//计算节点启发式函数值int arouse(int a[][3]){int num=0;int i,j;for(i=0;i<3;i++){for(j=0;j<3;j++){if(a[i][j]==end[i][j]){num++;}}}return 9-num;}//空白节点移动算法int location = locate(now, 0);int i, j;i = location / 3;j = location % 3;copy_matrix(extend, now);if (i > 0) //空格上移{int *p = &extend[i][j];int *q = &extend[i - 1][j];exchange(p, q);if (judge()){inopen(extend);}}copy_matrix(extend, now);if (i < 2) //空格下移{exchange(&extend[i][j], &extend[i + 1][j]);if (judge()){inopen(extend);}}copy_matrix(extend, now);if (j > 0) //空格左移{exchange(&extend[i][j], &extend[i][j - 1]);if (judge()){inopen(extend);}}copy_matrix(extend, now);if (j < 2) //空格右移{exchange(&extend[i][j], &extend[i][j + 1]);if (judge()){inopen(extend);}}2.3 广度优先搜索算法1、把起始节点放到OPEN表中(如果该起始节点为一目标节点,则求得一个解答);2、如果OPEN是个空表,则没有解,失败退出;否则继续;3、把第一个节点(节点n)从OPEN表移出,并把它放入CLOSE的扩展节点表中;4、扩展节点n。
人工智能实验报告-八数码(五篇模版)
人工智能实验报告-八数码(五篇模版)第一篇:人工智能实验报告-八数码《人工智能》实验一题目实验一启发式搜索算法1.实验内容:使用启发式搜索算法求解8数码问题。
⑴ 编制程序实现求解8数码问题A*算法,采用估价函数⎧⎪w(n),f(n)=d(n)+⎨pn⎪⎩()其中:d(n)是搜索树中结点n的深度;w(n)为结点n的数据库中错放的棋子个数;p(n)为结点n的数据库中每个棋子与其目标位置之间的距离总和。
⑵ 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是p(n)的上界的h(n)的定义,并测试使用该估价函数是否使算法失去可采纳性。
2.实验目的熟练掌握启发式搜索A算法及其可采纳性。
3.数据结构与算法设计该搜索为一个搜索树。
为了简化问题,搜索树节点设计如下:typedef struct Node//棋盘 {//节点结构体int data[9];double f,g;struct Node * parent;//父节点}Node,*Lnode;int data[9];数码数组:记录棋局数码摆放状态。
struct Chess * Parent;父节点:指向父亲节点。
下一步可以通过启发搜索算法构造搜索树。
1、局部搜索树样例:*2、搜索过程搜索采用广度搜索方式,利用待处理队列辅助,逐层搜索(跳过劣质节点)。
搜索过程如下:(1)、把原棋盘压入队列;(2)、从棋盘取出一个节点;(3)、判断棋盘估价值,为零则表示搜索完成,退出搜索;(4)、扩展子节点,即从上下左右四个方向移动棋盘,生成相应子棋盘;(5)、对子节点作评估,是否为优越节点(子节点估价值小于或等于父节点则为优越节点),是则把子棋盘压入队列,否则抛弃;(5)、跳到步骤(2);3、算法的评价完全能解决简单的八数码问题,但对于复杂的八数码问题还是无能为力。
现存在的一些优缺点。
1、可以改变数码规模(N),来扩展成N*N的棋盘,即扩展为N 数码问题的求解过程。
人工智能关于八数码问题论文
人工智能关于八数码问题论文摘要:八数码问题是人工智能中一个很典型的智力问题。
本文以状态空间搜索的观点讨论了八数码问题,给出了八数码问题的Java算法与实现的思想,分析了A算法的可采纳性等及系统的特点。
关键词九宫重排,状态空间,启发式搜索,A算法1引言九宫重排问题是人工智能当中有名的难题之一。
问题是在3×3方格盘上,放有八个数码,剩下一个位置为空,每一空格其上下左右的数码可移至空格。
问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始状态转化为目标状态。
状态转换的规则:空格四周的数移向空格,我们可以看作是空格移动,它最多可以有4个方向的移动,即上、下、左、右。
九宫重排问题的求解方法,就是从给定的初始状态出发,不断地空格上下左右的数码移至空格,将一个状态转化成其它状态,直到产生目标状态。
一、问题描述1.1 待解决问题的解释八数码游戏(八数码问题)描述为:在3×3组成的九宫格棋盘上,摆有八个将牌,每一个将牌都刻有1-8八个数码中的某一个数码。
棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。
这种游戏求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标的布局(称目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。
1.2 问题的搜索形式描述(4要素)初始状态:8个数字将牌和空格在九宫格棋盘上的所有格局组成了问题的状态空间。
其中,状态空间中的任一种状态都可以作为初始状态。
后继函数:通过移动空格(上、下、左、右)和周围的任一棋子一次,到达新的合法状态。
目标测试:比较当前状态和目标状态的格局是否一致。
路径消耗:每一步的耗散值为1,因此整个路径的耗散值是从起始状态到目标状态的棋子移动的总步数。
1.3 解决方案介绍(原理)对于八数码问题的解决,首先要考虑是否有答案。
每一个状态可认为是一个1×9的矩阵,问题即通过矩阵的变换,是否可以变换为目标状态对应的矩阵?由数学知识可知,可计算这两个有序数列的逆序值,如果两者都是偶数或奇数,则可通过变换到达,否则,这两个状态不可达。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能作业八数码问题
一、题目
八数码问题:
初始状态图:目标状态图:
二、算符与状态空间
算符:左、上、右、下
状态空间:
状态:A=(X0,X1,X2,X3,X4,X5,X6,X7,X8) 初始状态:S0=(0,4,1,5,2,8,3,6,7);
目标状态:Sg=(0,1,7,5,2,8,3,6,4)。
三、搜索树
22
求解:
四、Open 表,Closed 表
Open 表: Closed 表:
五、程序代码
/* 3_13.pro eight puzzle */
trace
DOMAINS
state=st(in,in,in,in,in,in,in,in,in)
in=integer
DATABASE-mydatabase
open(state,integer)
closed(integer,state,integer)
res(state)
mark(state)
fail_
PREDICATES
solve
search(state,state)
result
searching
step4(integer,state)
step56(integer,state)
equal(state,state)
repeat
resulting(integer)
rule(state,state)
GOAL
solve.
CLAUSES
solve:-search(st(0,4,1,5,2,8,3,6,7),st(0,1,7,5,2,8,3,6,4)),result. search(Begin,End):-retractall(_,mydatabase),
assert(closed(0,Begin,0)),assert(open(Begin,0)),
assert(mark(End)),repeat,searching,!.
result:-not(fail_),retract(closed(0,_,0)),closed(M,_,_),resulting(M), !.
result:-beep,write("sorry don't find a road!").
searching:-open(State,Pointer),retract(open(State,Pointer)),
closed(No,_,_),No2=No+1,asserta(closed(No2,State,Pointer)),
!,step4(No2,State).
searching:-assert(fail_).
step4(_,State):-mark(End),equal(State,End).
step4(No,State):-step56(No,State),!,fail.
step56(No,StateX):-rule(StateX,StateY),not(open(StateY,_)),
not(closed(_,StateY,_)),assertz(open(StateY,No)),fail.
step56(_,_):-!.
equal(X,X).
repeat.
repeat:-repeat.
resulting(N):-closed(N,X,M),asserta(res(X)),resulting(M).
resulting(_):-res(X),write(X),nl,fail.
resulting(_):-!.
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
st(X8,X1,X2,X3,X4,X5,X6,X7,X0)):-X0=0.
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
st(X2,X1,X0,X3,X4,X5,X6,X7,X8)):-X0=0.
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
st(X4,X1,X2,X3,X0,X5,X6,X7,X8)):-X0=0.
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
st(X6,X1,X2,X3,X4,X5,X0,X7,X8)):-X0=0.
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
st(X0,X2,X1,X3,X4,X5,X6,X7,X8)):-X1=0.
st(X0,X2,X8,X3,X4,X5,X6,X7,X1)):-X1=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X2,X1,X3,X4,X5,X6,X7,X8)):-X2=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X3,X2,X4,X5,X6,X7,X8)):-X2=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X2,X1,X0,X3,X4,X5,X6,X7,X8)):-X2=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X3,X2,X4,X5,X6,X7,X8)):-X3=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X4,X3,X5,X6,X7,X8)):-X3=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X4,X1,X2,X3,X0,X5,X6,X7,X8)):-X4=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X4,X3,X5,X6,X7,X8)):-X4=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X5,X4,X6,X7,X8)):-X4=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X4,X6,X5,X7,X8)):-X5=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X5,X4,X6,X7,X8)):-X5=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X4,X5,X7,X6,X8)):-X6=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X6,X1,X2,X3,X4,X5,X0,X7,X8)):-X6=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X4,X6,X5,X7,X8)):-X6=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8),
rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X4,X5,X7,X6,X8)):-X7=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X8,X2,X3,X4,X5,X6,X7,X1)):-X8=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X8,X1,X2,X3,X4,X5,X6,X7,X0)):-X8=0. rule(st(X0,X1,X2,X3,X4,X5,X6,X7,X8), st(X0,X1,X2,X3,X4,X5,X6,X8,X7)):-X8=0.
六、运行结果截图
编译后:
运行后:。