当前位置:文档之家› 人工智能实验报告,包括八数码问题八皇后问题和tsp问题

人工智能实验报告,包括八数码问题八皇后问题和tsp问题

人工智能实验报告,包括八数码问题八皇后问题和tsp问题
人工智能实验报告,包括八数码问题八皇后问题和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; 所屏蔽方向:一个屏蔽方向,防止回推。

Direction :enum Direction{None,Up,Down,Left,Right};//方向枚举

struct Chess * Parent; 父节点:指向父亲节点。

下一步可以通过启发搜索算法构造搜索树。

1、局部搜索树样例:

2、搜索过程

搜索采用广度搜索方式,利用待处理队列辅助,逐层搜索(跳过劣质节点)。搜索过程如下:

(1)、把原棋盘压入队列;

(2)、从棋盘取出一个节点;

(3)、判断棋盘估价值,为零则表示搜索完成,退出搜索;

(4)、扩展子节点,即从上下左右四个方向移动棋盘,生成相应子棋盘;

(5)、对子节点作评估,是否为优越节点(子节点估价值小于或等于父节点则为优越节点),是则把子棋盘压入队列,否则抛弃;

(5)、跳到步骤(2);

3、算法的评价

完全能解决简单的八数码问题,但对于复杂的八数码问题还是无能为力。现存在的一些优缺点。

1、可以改变数码规模(N),来扩展成N*N的棋盘,即扩展为N数码问题的求解过程。

2、内存泄漏。由于采用倒链表的搜索树结构,简化了数据结构,但有部分被抛弃节点的内存没有很好的处理,所以会造成内存泄漏;

3、采用了屏蔽方向,有效防止往回搜索(节点的回推),但没能有效防止循环搜索,所以不能应用于复杂度较大的八数码问题;

源码:

#include "stdio.h"

#include "stdlib.h"

#include "time.h"

#include "string.h"

#include

#include

using namespace std;

const int N=3;//3*3棋盘

const int Max_Step=30;//最大搜索深度

enum Direction{None,Up,Down,Left,Right};//方向

struct Chess//棋盘

{

int cell[N][N];//数码数组

int Value;//评估值

Direction BelockDirec;//所屏蔽方向

struct Chess * Parent;//父节点

};

//打印棋盘

void PrintChess(struct Chess *TheChess)

{

printf("------------------------------------------------------------------------\n");

for(int i=0;i

{

printf("\t");

for(int j=0;j

{

printf("%d\t",TheChess->cell[i][j]);

}

printf("\n");

}

printf("\t\t\t\t差距:%d\n",TheChess->Value);

}

//移动棋盘

struct Chess * MoveChess(struct Chess * TheChess,Direction Direct,bool CreateNewChess) {

struct Chess * NewChess;

//获取空闲格位置

int i,j;

for(i=0;i

{

bool HasGetBlankCell=false;

for(j=0;j

{

if(TheChess->cell[i][j]==0)

{

HasGetBlankCell=true;

break;

}

}

if(HasGetBlankCell)

break;

}

//移动数字

int t_i=i,t_j=j;

bool AbleMove=true;

switch(Direct)

{

case Up:

t_i++;

if(t_i>=N)

AbleMove=false;

break;

case Down:

t_i--;

if(t_i<0)

AbleMove=false;

break;

case Left:

t_j++;

if(t_j>=N)

AbleMove=false;

break;

case Right:

t_j--;

if(t_j<0)

AbleMove=false;

break;

};

if(!AbleMove)//不可以移动则返回原节点

{

return TheChess;

}

if(CreateNewChess)

{

NewChess=new Chess();

for(int x=0;x

{

for(int y=0;y

NewChess->cell[x][y]=TheChess->cell[x][y];

}

}

else

NewChess=TheChess;

NewChess->cell[i][j]=NewChess->cell[t_i][t_j];

NewChess->cell[t_i][t_j]=0;

return NewChess;

}

//初始化一个初始棋盘

struct Chess * RandomChess(const struct Chess * TheChess) {

int M=30;//随机移动棋盘步数

struct Chess * NewChess;

NewChess=new Chess();

memcpy(NewChess,TheChess,sizeof(Chess));

srand((unsigned)time(NULL));

for(int i=0;i

{

int Direct=rand()%4;

//printf("%d\n",Direct);

NewChess=MoveChess(NewChess,(Direction) Direct,false);

}

return NewChess;

}

//估价函数

int Appraisal(struct Chess * TheChess,struct Chess * Target) {

int Value=0;

for(int i=0;i

{

for(int j=0;j

{

if(TheChess->cell[i][j]!=Target->cell[i][j])

Value++;

}

}

TheChess->Value=Value;

return Value;

}

//搜索函数

struct Chess * Search(struct Chess* Begin,struct Chess * Target) {

Chess * p1,*p2,*p;

int Step=0;//深度

p=NULL;

queue Queue1;

Queue1.push(Begin);

//搜索

do{

p1=(struct Chess *)Queue1.front();

Queue1.pop();

for(int i=1;i<=4;i++)//分别从四个方向推导出新子节点

{

Direction Direct=(Direction)i;

if(Direct==p1->BelockDirec)//跳过屏蔽方向

continue;

p2=MoveChess(p1,Direct,true);//移动数码

if(p2!=p1)//数码是否可以移动

{

Appraisal(p2,Target);//对新节点估价

if(p2->Value<=p1->Value)//是否为优越节点

{

p2->Parent=p1;

switch(Direct)//设置屏蔽方向,防止往回推

{

case Up:p2->BelockDirec=Down;break;

case Down:p2->BelockDirec=Up;break;

case Left:p2->BelockDirec=Right;break;

case Right:p2->BelockDirec=Left;break;

}

Queue1.push(p2);//存储节点到待处理队列

if(p2->Value==0)//为0则,搜索完成

{

p=p2;

i=5;

}

}

else

{

delete p2;//为劣质节点则抛弃

p2=NULL;

}

}

}

Step++;

if(Step>Max_Step)

return NULL;

}while(p==NULL || Queue1.size()<=0);

return p;

}

main()

{

Chess * Begin,Target,* T;

//设定目标棋盘[0 1 2],[3 4 5],[6 7 8]

for(int i=0;i

{

for(int j=0;j

{

Target.cell[i][j]=i*N+j;

}

}

//获取初始棋盘

Begin=RandomChess(&Target);

Appraisal(Begin,&Target);

Begin->Parent=NULL;

Begin->BelockDirec=None;

Target.Value=0;

printf("目标棋盘:\n");

PrintChess(&Target);

printf("初始棋盘:\n");

PrintChess(Begin);

//图搜索

T=Search(Begin,&Target);

//打印

if(T)

{

/*把路径倒序*/

Chess *p=T;

stackStack1;

while(p->Parent!=NULL)

{

Stack1.push(p);

p=p->Parent;

}

printf("搜索结果:\n");

while(!Stack1.empty())

{

PrintChess(Stack1.top());

Stack1.pop();

}

printf("\n完成!");

}else

printf("搜索不到结果.深度为%d\n",Max_Step);

scanf("%d",T);

}

八皇后问题

八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

基本思想:在open表中保留已生成而未考察的结点,并用启发函数h(x)对它们全部进行估价,从中选出最优结点进行扩展,而不管这个结点出现在搜索树的什么地方。

(1)把初始结点S0放入open表中,计算h(S0);

(2)若open表为空,则搜索失败,EXIT;

(3)移出open表中第一个结点N放入closed表中,并冠以序号n

(4)若目标结点Sg=N则搜索成功,EXIT

(5)若N不可扩展,则转步骤(2);

(6)扩展N,计算每个子结点x的函数值h(x),并将所有子结点配以指向N的返回指针后放入open表中,再对open表中的所有子结点按其函数值大小以升序排序,转步骤2;

//采用启发式修补解N皇后问题

#include

#include

//采用启发式修补解N皇后问题

#include

#include

using https://www.doczj.com/doc/6014416474.html,space std;

void shuffle(int Queen[],const int n)

...{//随机取得各行的初始皇后位置,以Queen[i]表示第i行的皇后位置

for(int i=0;i

Queen[i]=abs(rand())%n;

}

int collision(int Queen[],const int row,const int column,const int n)

...{ //计算每个位置的冲突值

int bug=0;

for(int i=0;i

...{

if ((i!=row)&&(Queen[i]==column||(Queen[i]-column)==(i-row)

||(Queen[i]-column)==(row-i)))//同列,同对角线的情况

bug ;

}

return bug;

}

void show(int Queen[],const int n)

...{//打印皇后图

cout<<"╭";

for(int k=0;k

cout<<"─┬";

cout<<"─╮"<

for(int i=0;i

...{

cout<<"│";

for(int j=0;j

cout<<((j==Queen[i])? "凤" :" ")<<"│";//有皇后的位置用"凤"

cout<

cout<<"├";

for(j=0;j

cout<<"─┼";

cout<<"─┤"<

}

cout<<"│";

for(int j=0;j

cout<<((j==Queen[n-1])? "凤" :" ")<<"│";//有皇后的位置用,没有的用_ cout<

cout<<"╰";

for(k=0;k

cout<<"─┴";

cout<<"─╯"<

cout<

}

int repair(int Queen[],const int n)

...{ //启发式修补

int max=-1;//标志行行之间冲突数

int minbug=n;

int count=0;

while(max!=0&&count<=100)

...{

max=0;

for(int i=0;i

...{

minbug=collision(Queen,i,Queen[i],n);//取得当前的冲突数,不断优化int temp=Queen[i];

for(int j=0;j

...{

int bug=collision(Queen,i,j,n);

if(bug<=minbug&&j!=temp)

...{ //保持皇后在等冲突的情况下不断变更位置,有利于后面行的优化

minbug=bug;

Queen[i]=j;

}

}

if (minbug>max)

max=minbug;

}

show(Queen,n);

count ;

}

return count;

}

void main()

...{

int n=-1;

int step=0;

cout<<"Welcome to N Queen Settlement"<

cout<<"Input N (you would better input a interge minor to 15):"<

cin>>n;

if(n<=0)

...{

cout<<"Illegal Input!"<

return;

}

int* Queen=new int[n];

srand(time(NULL));//取得随机种子

shuffle(Queen,n);

cout<<"The oringinal state:"<

show(Queen,n);

step=repair(Queen,n);

if(step>100)

...{

cout<<"Could find solution within 100 steps,Try again!"<

return;

}

cout<<"After "<

cout<<"The goal state arrives!"<

}

汉诺塔问题

遗传算法求TSP问题

遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法,它最初由美国Michigan大学J.Holland教授于1975年首先提出来的,并出版了颇有影响的专著《Adaptation in Natural and Artificial Systems》,GA这个名称才逐渐为人所知,J.Holland教授所提出的GA通常为简单遗传算法(SGA)。

遗传算法是从代表问题可能潜在的解集的一个种群(population)开始的,而一个种群则由经过基因(gene)编码的一定数目的个体(individual)组成。每个个体实际上是染色体(chromosome)带有特征的实体。染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体的形状的外部表现,如黑头发的特征是由染色体中控制这一特征的某种基因组合决定的。因此,在一开始需要实现从表现型到基因型的映射即编码工作。由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码,初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代(generation)演化产生出越来越好的近似解,在每一代,根据问题域中个体的适应度(fitness)大小选择(selection)个体,并借助于自然遗传学的遗传算子(genetic operators)进行组合交叉(crossover)和变异(mutation),产生出代表新的解集的种群。这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码(decoding),可以作为问题近似最优解。

遗传算法特点

遗传算法是一类可用于复杂系统优化的具有鲁棒性的搜索算法,与传统的优化算法相比,主要有以下特点:

1、遗传算法以决策变量的编码作为运算对象。传统的优化算法往往直接决策变量的实际值本身,而遗传算法处理决策变量的某种编码形式,使得我们可以借鉴生物

学中的染色体和基因的概念,可以模仿自然界生物的遗传和进化机理,也使得我们能够方便的应用遗传操作算子。

2、遗传算法直接以适应度作为搜索信息,无需导数等其它辅助信息。

3、遗传算法使用多个点的搜索信息,具有隐含并行性。

4、遗传算法使用概率搜索技术,而非确定性规则。

/*********************************************************************** *遗传算法解决TSP问题*

*code by 小白at July.30 *

***********************************************************************/ def.h

-------------------------------

#ifndef _GENERATION_AMOUNT

#define _GENERATION_AMOUNT 201 //每一代的生存数

#define _CITY_AMOUNT 10 //城市数,等于基因数

//#define _XCHG_GENE_AMOUNT_WHEN_MIX 2 //每次杂交所交换的碱基数量

#define _TIMES 50 //定义进化次数

#define _DISP_INTERV AL 5 //每隔多少次显示基因中的最高适应度

#define _CONTAINER std::vector //定义个体基因容器类型

#define _CONTAINER_P std::vector //定义适应度容器类型

#define _P(a,x,y) *(a+(x)+(y)*_CITY_AMOUNT)

#define _P_GENE_ABERRANCE 10 //变异概率1%

#define _P_GENE_MIX (_GENERATION_AMOUNT-1)/2 //杂交次数

#define _INFINITE 100000

typedef int DISTANCE; //距离矩阵的数据存储类型

#endif

___________________________________________________________________________ TSP.cpp

____________________________________________________________________________ #include

#include

#include

#include

#include

#include "def.h"

#include "TSP.h"

void main()

{

const static DISTANCE distance[][_CITY_AMOUNT]

= {

0, 1, 4, 6, 8, 1, 3, 7, 2, 9,

1, 0, 7, 5, 3, 8, 3, 4, 2, 4,

4, 7, 0, 3, 8, 3, 7, 9, 1, 2,

6, 5, 3, 0, 3, 1, 5, 2, 9, 1,

8, 3, 8, 3, 0, 2, 3, 1, 4, 6,

1, 8, 3, 1, 2, 0, 3, 3, 9, 5,

3, 3, 7, 5, 3, 3, 0, 7, 5, 9,

7, 4, 9, 2, 1, 3, 7, 0, 1, 3,

2, 2, 1, 9, 4, 9, 5, 1, 0, 1,

9, 4, 2, 1, 6, 5, 9, 3, 1, 0

}; //城市间的距离矩阵

//distance[i][j]代表i城市与j城市的距离

/*

const static DISTANCE distance[][_CITY_AMOUNT]

={

0, 1, 4, 6, 8, 1, 3, 7, 2, 9, 7, 3, 4, 5, 8, 9, 2, 8, 2, 8,

1, 0, 7, 5, 3, 8, 3, 4, 2, 4, 4, 6, 2, 8, 2, 9, 4, 5, 2, 1,

4, 7, 0, 3, 8, 3, 7, 9, 1, 2, 5, 8, 1, 8, 9, 4, 7, 4, 8, 4,

6, 5, 3, 0, 3, 1, 5, 2, 9, 1, 3, 5, 7, 3, 4, 7, 3, 4, 5, 2,

8, 3, 8, 3, 0, 2, 3, 1, 4, 6, 3, 8, 4, 5, 2, 8, 1, 7, 4, 7,

1, 8, 3, 1, 2, 0, 3, 3, 9, 5, 4, 5, 2, 7, 3, 6, 2, 3, 7, 1,

3, 3, 7, 5, 3, 3, 0, 7, 5, 9, 3, 4, 5, 9, 3, 7, 3, 2, 8, 1,

7, 4, 9, 2, 1, 3, 7, 0, 1, 3, 4, 5, 2, 7, 6, 3, 3, 8, 3, 5,

2, 2, 1, 9, 4, 9, 5, 1, 0, 1, 3, 4, 7, 3, 7, 5, 9, 2, 1, 7,

9, 4, 2, 1, 6, 5, 9, 3, 1, 0, 3, 7, 3, 7, 4, 9, 3, 5, 2, 5,

7, 4, 5, 3, 3, 4, 3, 4, 3, 3, 0, 5, 7, 8, 4, 3, 1, 5, 9, 3,

3, 6, 8, 5, 8, 5, 4, 5, 4, 7, 5, 0, 8, 3, 1, 5, 8, 5, 8, 3,

4, 2, 1, 7, 4, 2, 5, 2, 7, 3, 7, 8, 0, 5, 7, 4, 8, 3, 5, 3,

5, 8, 8, 3, 5, 7, 9, 7, 3, 7, 8, 3, 5, 0, 8, 3, 1, 8, 4, 5,

8, 2, 9, 4, 2, 3, 3, 6, 7, 4, 4, 1, 7, 8, 0, 4, 2, 1, 8, 4,

9, 9, 4, 7, 8, 6, 7, 3, 5, 9, 3, 5, 4, 3, 4, 0, 4, 1, 8, 4,

2, 4, 7, 3, 1, 2, 3, 3, 9, 3, 1, 8, 8, 1, 2, 4, 0, 4, 3, 7,

8, 5, 4, 4, 7, 3, 2, 8, 2, 5, 5, 5, 3, 8, 1, 1, 4, 0, 2, 6,

2, 2, 8, 5, 4, 7, 8, 3, 1, 2, 9, 8, 5, 4, 8, 8, 3, 2, 0, 4,

8, 1, 4, 2, 7, 1, 1, 5, 7, 5, 3, 3, 3, 5, 4, 4, 7, 6, 4, 0

};

*/

Csga<_CONTAINER, _CONTAINER_P> CUnit((DISTANCE *)distance); //初始化

//开始遗传算法

if(!CUnit.fnCreateRandomGene()) //产生随机的基因

{

exit(0);

}

//循环基因编译,杂交,淘汰过程

CUnit.fnEvalAll();

for ( int i = 0; i < _TIMES; ++i )

{

//CUnit.fnDispProbability();

CUnit.fnGeneAberrance(); //基因变异

//CUnit.fnDispProbability();

CUnit.fnGeneMix(); //基因杂交

CUnit.fnEvalAll();

//每隔_DISP_INTERV AL显示一次结果

if ( (i+1)%_DISP_INTERV AL == 0 || i == 0)

{

cout << "第" << i+1 << "代" << std::endl;

CUnit.fnDispProbability();

CUnit.fnDispHistoryMin();

}

}

CUnit.fnDispHistoryMin();

}

___________________________________________________________________________ tsp.h

___________________________________________________________________________ #include "def.h"

using namespace std;

template

class Csga

{

public:

Csga();

Csga(DISTANCE *lpDistance); //构造函数

~Csga(); //析构函数

bool fnCreateRandomGene(); //产生随机基因

bool fnGeneAberrance(); //基因变异

bool fnGeneMix(); //基因交叉产生新的个体测试并淘汰适应度低的个体

bool fnEvalAll(); //测试所有基因的适应度

int fnEvalOne(T &Gene); //测试某一个基因的适应度

void fnDispProbability(); //显示每个个体的权值

void fnDispHistoryMin();

private:

bool fnGeneAberranceOne(const int &i, const int &j);//变异某个基因

T m_GenerationGene[_GENERA TION_AMOUNT]; //定义每个群体的基因P m_vProbability; //定义每个群体的适应度

DISTANCE *lpCityDistance;

int HistoryMin;

T HistoryMinWay;

T m_GenerationGeneBk[_GENERATION_AMOUNT];

};

//构造函数

template

Csga::Csga()

{

}

template

Csga::Csga(DISTANCE *lpDistance)

{

lpCityDistance = lpDistance;

m_vProbability.reserve(_CITY_AMOUNT);

HistoryMin = _INFINITE;

//cout << _P(lpCityDistance, 3, 2); //调试用

}

//析构函数

template

Csga::~Csga()

{

}

//产生随机基因

template

bool Csga::fnCreateRandomGene()

{

srand( time(0) ); //初始化随机数

//cout << "\t基因序列" << std::endl; //调试用

//生成随机基因

for(int j, temp, i = 0; i < _GENERATION_AMOUNT; ++i)

{

m_GenerationGene[i].reserve(_CITY_AMOUNT);

for (j = 0; j < _CITY_AMOUNT; ++j)

{

do

{

temp = rand()%_CITY_AMOUNT;

}while (find(m_GenerationGene[i].begin(), m_GenerationGene[i].end(), temp) != m_GenerationGene[i].end());

m_GenerationGene[i].push_back(temp);

}//end for

/*copy( m_GenerationGene[i].begin(), m_GenerationGene[i].end(),

std::ostream_iterator(cout," ") );

cout << std::endl; */ //调试用

}

return true;

}

//基因变异

template

bool Csga::fnGeneAberrance()

{

int i, j;

int temp;

srand(time(0));

//抽选一代中的某个基因进行变异

for (i = 0; i < _GENERA TION_AMOUNT; ++i)

{

for (j = 0; j < _CITY_AMOUNT; ++j)

{

temp = rand()%10000;

if ( temp > 0 && temp <= _P_GENE_ABERRANCE)

{

//随机抽选到的基因进行变异

if(!fnGeneAberranceOne(i, j)) {exit(0);}

}//end if

}//end for j

}//end for i

return true;

}

//变异第i个基因的第j位染色体

template

bool Csga::fnGeneAberranceOne(const int &i, const int &j)

{

int temp; //基因变异结果

srand(time(0));

T::iterator pos;

//找到变异位与另外一位交换

pos = std::find(m_GenerationGene[i].begin(), m_GenerationGene[i].end(), temp);

if (pos != m_GenerationGene[i].end())

{

*pos = m_GenerationGene[i][j];

m_GenerationGene[i][j] = temp;

return true;

}

return false;

}

inline int fnRndBoundary(int iBegin, int iEnd)

{

return rand()%(iEnd-iBegin) + iBegin;

}

//基因交叉产生新的个体并淘汰适应度低的个体

template

bool Csga::fnGeneMix()

{

srand(time(0));

std::vector temp; //选择池

P vProbabilityBk; //临时保存适应度

vProbabilityBk = m_vProbability;

temp.reserve( ((_GENERATION_AMOUNT+1)*_GENERATION_AMOUNT)/2 );

P::iterator pos;

for (int i = _GENERA TION_AMOUNT; i > 0; --i)

{

pos = std::min_element(vProbabilityBk.begin(), vProbabilityBk.end());

temp.insert( temp.end(), i, (int)(pos-vProbabilityBk.begin()) );

*pos = _INFINITE;

}

/************************************************************************** fnDispProbability();

cout << "\ttemp\n" << std::endl; //调试用

copy( temp.begin(), temp.end(), std::ostream_iterator(cout," ") );

cout << std::endl; //调试用

**************************************************************************/ #define _MIN_ELEMENT std::min_element(m_vProbability.begin(), m_vProbability.end())

m_GenerationGeneBk[_GENERA TION_AMOUNT-1] = m_GenerationGene[_MIN_ELEMENT - m_vProbability.begin()];

int iFather; //父亲的代号

int iMother; //母亲的代号

T Child1, Child2; //父亲与母亲杂交出的子女的基因

T::iterator tempIter;

int LowBoundary;

int HighBoundary;

//int iChild1Probability,iChild2Probability;

T fatherBk,motherBk;

T::iterator V_iter;

P::iterator P_iter;

int iDistance;

srand(time(0));

#ifndef _ITEMP

#define _ITEMP rand()%(((_GENERATION_AMOUNT+1)*_GENERATION_AMOUNT)/2)

#endif

for (i = 0; i < _P_GENE_MIX; ++i) //杂交_P_GENE_MIX/10次

{

iFather = temp[_ITEMP];

do

{

iMother = temp[_ITEMP];

}while(iMother == iFather);

Child1.reserve(_CITY_AMOUNT); //初始化子女的碱基数

Child2.reserve(_CITY_AMOUNT);

Child1.clear();

Child2.clear();

LowBoundary = fnRndBoundary(0, _CITY_AMOUNT-2);

HighBoundary= fnRndBoundary(LowBoundary+1, _CITY_AMOUNT-1);

/**********************************************************************

cout << "iMother:" << iMother << std::endl;

cout << "iFather:" << iFather << std::endl;

cout << "LowBoundary:" << LowBoundary << std::endl;

cout << "HighBoundary:" << HighBoundary << std::endl;

**********************************************************************/

fatherBk = m_GenerationGene[iFather];

用A算法解决八数码问题演示教学

用A算法解决八数码 问题

用A*算法解决八数码问题 一、 题目:八数码问题也称为九宫问题。在3×3的棋盘,有八个棋子,每个 棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要解决的问题是:任意给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。 二、 问题的搜索形式描述 状态:状态描述了8个棋子和空位在棋盘的9个方格上的分布。 初始状态:任何状态都可以被指定为初始状态。 操作符:用来产生4个行动(上下左右移动)。 目标测试:用来检测状态是否能匹配上图的目标布局。 路径费用函数:每一步的费用为1,因此整个路径的费用是路径中的步数。 现在任意给定一个初始状态,要求找到一种搜索策略,用尽可能少的步数得到上图的目标状态算法介绍 三、 解决方案介绍 1.A*算法的一般介绍 A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。对 于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价 值,即 ()()()()()()**f g n sqrt dx nx dx nx dy ny dy ny =+--+--; 这样估价函数f 在g 值一定的情况下,会或多或少的受估价值h 的制 约,节点距目标点近,h 值小,f 值相对就小,能保证最短路的搜索向终点的方向进行。明显优于盲目搜索策略。

A star算法在静态路网中的应用 2.算法伪代码 创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。算起点的估价值,将起点放入OPEN表。 while(OPEN!=NULL) { 从OPEN表中取估价值f最小的节点n; if(n节点==目标节点) {break;} for(当前节点n 的每个子节点X) { 算X的估价值; if(X in OPEN) { if( X的估价值小于OPEN表的估价值 ) {把n设置为X的父亲; 更新OPEN表中的估价值; //取最小路径的估价值} } if(X inCLOSE) { if( X的估价值小于CLOSE表的估价值 )

八数码问题求解--实验报告讲解

实验报告 一、实验问题 八数码问题求解 二、实验软件 VC6.0 编程语言或其它编程语言 三、实验目的 1. 熟悉人工智能系统中的问题求解过程; 2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用; 3. 熟悉对八数码问题的建模、求解及编程语言的应用。 四、实验数据及步骤 (一、)实验内容 八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。 2 8 3 1 2 3 1 4 8 4 7 6 5 7 6 5 (a) 初始状态(b) 目标状态 图1 八数码问题示意图 (二、)基本数据结构分析和实现 1.结点状态 我采用了struct Node数据类型 typedef struct _Node{

int digit[ROW][COL]; int dist; // distance between one state and the destination一 个表和目的表的距离 int dep; // the depth of node深度 // So the comment function = dist + dep.估价函数值 int index; // point to the location of parent父节点的位置 } Node; 2.发生器函数 定义的发生器函数由以下的四种操作组成: (1)将当前状态的空格上移 Node node_up; Assign(node_up, index);//向上扩展的节点 int dist_up = MAXDISTANCE; (2)将当前状态的空格下移 Node node_down; Assign(node_down, index);//向下扩展的节点 int dist_down = MAXDISTANCE; (3)将当前状态的空格左移 Node node_left; Assign(node_left, index);//向左扩展的节点 int dist_left = MAXDISTANCE; (4)将当前状态的空格右移 Node node_right; Assign(node_right, index);//向右扩展的节点 int dist_right = MAXDISTANCE; 通过定义结点状态和发生器函数,就解决了8数码问题的隐式图的生成问题。接下来就是搜索了。 3.图的搜索策略 经过分析,8数码问题中可采用的搜速策略共有:1.广度优先搜索、2.深度优先搜索、2.有界深度优先搜索、4.最好优先搜索、5.局部择优搜索,一共五种。其中,广度优先搜索法是可采纳的,有界深度优先搜索法是不完备的,最好优先和局部择优搜索法是启发式搜索法。 实验时,采用了广度(宽度)优先搜索来实现。 (三、)广度(宽度)优先搜索原理 1. 状态空间盲目搜索——宽度优先搜索 其基本思想是,从初始节点开始,向下逐层对节点进形依次扩展,并考察它是否为目标节点,再对下层节点进行扩展(或搜索)之前,必须完成对当层的所有节点的扩展。再搜索过程中,未扩展节点表OPEN中的节点排序准则是:先进入的节点排在前面,后进入的节点排在后面。其搜索过程如图(1)所示。

人工智能实验报告大全

人工智能实验报告大 全

人工智能课内实验报告 (8次) 学院:自动化学院 班级:智能1501 姓名:刘少鹏(34) 学号: 06153034 目录 课内实验1:猴子摘香蕉问题的VC编程实现 (1) 课内实验2:编程实现简单动物识别系统的知识表示 (5)

课内实验3:盲目搜索求解8数码问题 (18) 课内实验4:回溯算法求解四皇后问题 (33) 课内实验5:编程实现一字棋游戏 (37) 课内实验6:字句集消解实验 (46) 课内实验7:简单动物识别系统的产生式推理 (66) 课内实验8:编程实现D-S证据推理算法 (78)

人工智能课内实验报告实验1:猴子摘香蕉问题的VC编程实现 学院:自动化学院 班级:智能1501 姓名:刘少鹏(33) 学号: 06153034 日期: 2017-3-8 10:15-12:00

实验1:猴子摘香蕉问题的VC编程实现 一、实验目的 (1)熟悉谓词逻辑表示法; (2)掌握人工智能谓词逻辑中的经典例子——猴子摘香蕉问题的编程实现。 二、编程环境 VC语言 三、问题描述 房子里有一只猴子(即机器人),位于a处。在c处上方的天花板上有一串香蕉,猴子想吃,但摘不到。房间的b处还有一个箱子,如果猴子站到箱子上,就可以摸着天花板。如图1所示,对于上述问题,可以通过谓词逻辑表示法来描述知识。要求通过VC语言编程实现猴子摘香蕉问题的求解过程。 图1 猴子摘香蕉问题

四、源代码 #include unsigned int i; void Monkey_Go_Box(unsigned char x, unsigned char y) { printf("Step %d:monkey从%c走到%c\n", ++i, x, y);//x表示猴子的位置,y为箱子的位置 } void Monkey_Move_Box(char x, char y) { printf("Step %d:monkey把箱子从%c运到%c\n", ++i, x, y);//x表示箱子的位置,y为香蕉的位置 } void Monkey_On_Box() { printf("Step %d:monkey爬上箱子\n", ++i); } void Monkey_Get_Banana() { printf("Step %d:monkey摘到香蕉\n", ++i); } void main() { unsigned char Monkey, Box, Banana; printf("********智能1501班**********\n"); printf("********06153034************\n"); printf("********刘少鹏**************\n"); printf("请用a b c来表示猴子箱子香蕉的位置\n"); printf("Monkey\tbox\tbanana\n"); scanf("%c", &Monkey); getchar(); printf("\t"); scanf("%c", &Box); getchar(); printf("\t\t"); scanf("%c", &Banana); getchar(); printf("\n操作步骤如下\n"); if (Monkey != Box) { Monkey_Go_Box(Monkey, Box); } if (Box != Banana)

A星算法求八数码问题试验报告

人工智能实验报告实验名称:八数码问题 姓名:xx 学号:2012210xx xx计算机学院

2014年1月14日 一.实验目的. 的思想,启发式搜索,来求解在代价最小的情况下将九宫格从一掌握A* 个状态转为另状态的路径。 二.实验内容且要求在有限步的操作内,使其转化为目标状态,给定九宫 格的初始状态,并打印出求解路径。例如(即移动的步数最少)所得到的解是代 价最小解 3 8 2 4 6 1 5 0 7 3 2 8 4 6 1 5 0 7 A*三、算法思想:1、思想:估价值与实际A*算法是一种静态路网中求 解最短路最有效的直接搜索方法。值越接近,估价函数取得就越好、原理:2 f(n)=g(n)+h(n), 估价函数公式表示为:是在状态空g(n) 是从初始点经由节点n到目标点的估价函数,其中 f(n) 到目标节点最佳路径的估计nh(n) 是从间中从初始节点到n节点的实际代价,h(n)的选取:代价。保证找到最短路径(最优解的)条件,关键在于估价函数到目标节点的距离实际值,这种情况下,搜索的点数多,搜索估价值h(n)<= n等于h(n)范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计如

果估那么搜索将严格沿着最短路径进行此时的搜索效率是最高的。最短距离, ,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。价值>实际值 四、算法流程:

1、使用了CreateChild()函数,求得了任意未拓展九宫格的扩展结点,便于拓展子空间,搜索所有情况。 关键代码: bool CreateChild(NOExtend ns[],NOExtend ne){

八数码问题人工智能实验报告

基于人工智能的状态空间搜索策略研究 ——八数码问题求解 (一)实验软件 TC2.0 或VC6.0编程语言或其它编程语言 (二)实验目的 1. 熟悉人工智能系统中的问题求解过程; 2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用; 3. 熟悉对八数码问题的建模、求解及编程语言的应用。 (三)需要的预备知识 1. 熟悉TC 2.0或VC6.0 编程语言或者其它编程语言; 2. 熟悉状态空间的宽度优先搜索、深度优先搜索和启发式搜索算法; 3. 熟悉计算机语言对常用数据结构如链表、队列等的描述应用; 4. 熟悉计算机常用人机接口设计。 (四)实验数据及步骤 1. 实验内容 八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。 图1 八数码问题示意图 请任选一种盲目搜索算法(深度优先搜索或宽度优先搜索)或任选一种启发式搜索方法(A 算法或A* 算法)编程求解八数码问题(初始状态任选),并对实验结果进行分析,得出合理的结论。 2. 实验步骤 (1)分析算法基本原理和基本流程; 程序采用宽度优先搜索算法,基本流程如下:

(2)确定对问题描述的基本数据结构,如Open表和Closed表等;

(3)编写算符运算、目标比较等函数; (4)编写输入、输出接口; (5)全部模块联调; (6)撰写实验报告。 (五)实验报告要求 所撰写的实验报告必须包含以下内容: 1. 算法基本原理和流程框图; 2. 基本数据结构分析和实现; 3. 编写程序的各个子模块,按模块编写文档,含每个模块的建立时间、功能、输入输出参数意义和与其它模块联系等; 4. 程序运行结果,含使用的搜索算法及搜索路径等; 5. 实验结果分析; 6. 结论; 7. 提供全部源程序及软件的可执行程序。 附:实验报告格式 一、实验问题 二、实验目的 三、实验原理 四、程序框图 五、实验结果及分析 六、结论

游戏人工智能实验报告四

实验四有限状态机实验 实验报告 一、实验目的 通过蚂蚁世界实验掌握游戏中追有限状态机算法 二、实验仪器 Windows7系统 Microsoft Visual Studio2015 三、实验原理及过程 1)制作菜单 设置参数:点击会弹出对话框,设置一些参数,红、黑蚂蚁的家会在地图上标记出来 运行:设置好参数后点击运行,毒药、食物、水会在地图上随机显示 下一步:2只红蚂蚁和2只黑蚂蚁会随机出现在地图上,窗口右方还会出现红、黑蚂蚁当前数量的统计 不断按下一步,有限状态机就会不断运行,使蚁群产生变化 2)添加加速键 资源视图中 下方

选择ID和键值 3)新建头文件def.h 在AntView.cpp中加入#include"def.h" 与本实验有关的数据大都是在这里定义的 int flag=0; #define kForage 1 #define kGoHome 2 #define kThirsty 3 #define kDead 4 #define kMaxEntities 200 class ai_Entity{ public: int type; int state; int row; int col; ai_Entity(); ~ai_Entity() {} void New (int theType,int theState,int theRow,int theCol); void Forage(); void GoHome(); void Thirsty(); void Dead(); }; ai_Entity entityList[kMaxEntities]; #define kRedAnt 1 #define kBlackAnt 2

C语言实现8数码问题

1、实验目的 (1)熟悉人工智能系统中的问题求解过程; (2)熟悉状态空间中的盲目搜索策略; (3)掌握盲目搜索算法,重点是宽度优先搜索和深度优先搜索算法。 2、实验要求 用VC语言编程,采用宽度优先搜索和深度优先搜索方法,求解8数码问题3、实验内容 (1)采用宽度优先算法,运行程序,要求输入初始状态 假设给定如下初始状态S0 2 8 3 1 6 4 7 0 5 和目标状态Sg 2 1 6 4 0 8 7 5 3 验证程序的输出结果,写出心得体会。 (2)对代码进行修改(选作),实现深度优先搜索求解该问题

提示:每次选扩展节点时,从数组的最后一个生成的节点开始找,找一个没有被扩展的节点。这样也需要对节点添加一个是否被扩展过的标志。 4 源代码及实验结果截图 #include #include #include //八数码状态对应的节点结构体 struct Node{ int s[3][3];//保存八数码状态,0代表空格 int f,g;//启发函数中的f和g值 struct Node * next; struct Node *previous;//保存其父节点 }; int open_N=0; //记录Open列表中节点数目 //八数码初始状态 int inital_s[3][3]={ 2,8,3,1,6,4,7,0,5 }; //八数码目标状态 int final_s[3][3]={ 2,1,6,4,0,8,7,5,3 };

//------------------------------------------------------------------------ //添加节点函数入口,方法:通过插入排序向指定表添加 //------------------------------------------------------------------------ void Add_Node( struct Node *head, struct Node *p) { struct Node *q; if(head->next)//考虑链表为空 { q = head->next; if(p->f < head->next->f){//考虑插入的节点值比链表的第一个节点值小 p->next = head->next; head->next = p; } else { while(q->next)//考虑插入节点x,形如a<= x <=b { if((q->f < p->f ||q->f == p->f) && (q->next->f > p->f || q->next->f == p->f)){ p->next = q->next; q->next = p; break; } q = q->next; } if(q->next == NULL) //考虑插入的节点值比链表最后一个元素的值更大 q->next = p; }

八数码实验报告人工智能课设报告

学生实验报告 实验课名称:人工智能 实验名称: 八数码 专业名称:计算机科学与技术 班级: 学号: 学生姓名: 教师姓名: 2010 年10 月20日 一.实验内容 用OPEN表和CLOSED表解决搜索问题。 二.实验题目 采用启发式算法(如A*算法)求解八数码问题。 三.实验要求 1.必须使用OPEN表和CLOSED表。 2.明确给出问题描述。系统初始状态。目标状态和启发式函数。 3.除了初始状态以外,至少搜索四层。 4.给出解路径(解图)。 四.实验过程 ①问题:初始状态到目标状态是否可解如何判断? 答:实验过程自己给出的初始状态使用A*算法求解,并不是所有的初始状态都可解到达目标状态。因为八数码问题其实是0~9的一个排列,而排列有奇排列和偶排列,从奇排列不能转化为偶排列或者相反。例如:函数f(s)表示s前比s 小的数字的数目(s 则当f(a8)+f(a7)+……+f(a1)为偶数时才能重排成,所以嘛,上面那个有解的. ②问题描述: 在3X3的九宫格棋盘上,摆有8个将牌,每一个将牌都刻有1~8数码中的某一个数码。棋盘中留有一个空格,允许周围的某一个将牌向空格移动,这样通过移动将牌就可以不断地改变将牌的布局。这种游戏的求解的问题是:给定一种处

世的将牌布局或结构和一个目标的布局,问如何移动将牌,实现从从初始状态到目标状态的转变。 下面给出初始状态和目标状态: 初始状态:Array 目标状态: 评价函数f(n)形式为:f(n)=g(n)+h(n),其中g(n)是节点所处的深度, h(n)是启发式函数,这里启发式函数h(n)表示“不在位”的将牌个数,这时f(n) 注意:移动规则为左-→上→右→下。 ③搜索过程: 因此可得解路径:S(4)→B(4)→D(5)→E(5)→I(5)→K(5)→L(5). ④得到OPEN表和CLOSED表 OPEN表

启发式搜索算法解决八数码问题(C语言)

1、程序源代码 #include #include struct node{ int a[3][3];//用二维数组存放8数码 int hx;//函数h(x)的值,表示与目标状态的差距 struct node *parent;//指向父结点的指针 struct node *next;//指向链表中下一个结点的指针 }; //------------------hx函数-------------------// int hx(int s[3][3]) {//函数说明:计算s与目标状态的差距值 int i,j; int hx=0; int sg[3][3]={1,2,3,8,0,4,7,6,5}; for(i=0;i<3;i++) for(j=0;j<3;j++) if(s[i][j]!=sg[i][j]) hx++; return hx; } //-------------hx函数end----------------------// //-------------extend扩展函数----------------// struct node *extend(node *ex) { //函数说明:扩展ex指向的结点,并将扩展所得结点组成一条//单链表,head指向该链表首结点,并且作为返回值 int i,j,m,n; //循环变量 int t; //临时替换变量 int flag=0; int x[3][3];//临时存放二维数组 struct node *p,*q,*head; head=(node *)malloc(sizeof(node));//head p=head; q=head; head->next=NULL;//初始化 for(i=0;i<3;i++)//找到二维数组中0的位置 { for(j=0;j<3;j++)

八数码问题C语言A星算法详细实验报告含代码

一、实验内容和要求 八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。 例如: [ (a) 初始状态 (b) 目标状态 图1 八数码问题示意图 请任选一种盲目搜索算法(广度优先搜索或深度优先搜索)或任选一种启发式搜索方法(全局择优搜索,加权状态图搜索,A 算法或 A* 算法)编程求解八数码问题(初始状态任选)。选择一个初始状态,画出搜索树,填写相应的OPEN 表和CLOSED表,给出解路径,对实验结果进行分析总结,得出结论。 二、实验目的 1. 熟悉人工智能系统中的问题求解过程; 2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用; % 3. 熟悉对八数码问题的建模、求解及编程语言的应用。 三、实验算法 A*算法是一种常用的启发式搜索算法。 在A*算法中,一个结点位置的好坏用估价函数来对它进行评估。A*算法的估价函数可表示为: f'(n) = g'(n) + h'(n) 这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值(也称为最小耗费或最小代价),h'(n)是n到目标的最短路经的启发值。由于这个f'(n)其实是无法预先知道的,所以实际上使用的是下面的估价函数: f(n) = g(n) + h(n) 其中g(n)是从初始结点到节点n的实际代价,h(n)是从结点n到目标结点的最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已

知的。用f(n)作为f'(n)的近似,也就是用g(n)代替g'(n),h(n)代替h'(n)。这样必须满足两个条件:(1)g(n)>=g'(n)(大多数情况下都是满足的,可以不用考虑),且f必须保持单调递增。(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费h(n)<=h'(n)。第二点特别的重要。可以证明应用这样的估价函数是可以找到最短路径的。 *算法的步骤 A*算法基本上与广度优先算法相同,但是在扩展出一个结点后,要计算它的估价函数,并根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都是估价函数最小的结点。 A*算法的步骤如下: & 1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。 2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。否则对结点进行扩展。 3)检查扩展出的新结点是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。跳至第五步。 4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。 5)如果队列头的结点还可以扩展,直接返回第二步。否则将队列头指针指向下一结点,再返回第二步。 四、程序框图

人工智能 八数码实验

人工智能作业八数码问题

一、题目 八数码问题: 初始状态图:目标状态图: 二、算符与状态空间 算符:左、上、右、下 状态空间: 状态: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)),

人工智能实验报告大全

人工智能课内实验报告 (8次) 学院:自动化学院 班级:智能1501 姓名:刘少鹏(34) 学号: 06153034

目录 课内实验1:猴子摘香蕉问题的VC编程实现 (1) 课内实验2:编程实现简单动物识别系统的知识表示 (5) 课内实验3:盲目搜索求解8数码问题 (18) 课内实验4:回溯算法求解四皇后问题 (33) 课内实验5:编程实现一字棋游戏 (37) 课内实验6:字句集消解实验 (46) 课内实验7:简单动物识别系统的产生式推理 (66) 课内实验8:编程实现D-S证据推理算法 (78)

人工智能课内实验报告实验1:猴子摘香蕉问题的VC编程实现 学院:自动化学院 班级:智能1501 姓名:刘少鹏(33) 学号: 06153034 日期: 2017-3-8 10:15-12:00

实验1:猴子摘香蕉问题的VC编程实现 一、实验目的 (1)熟悉谓词逻辑表示法; (2)掌握人工智能谓词逻辑中的经典例子——猴子摘香蕉问题的编程实现。 二、编程环境 VC语言 三、问题描述 房子里有一只猴子(即机器人),位于a处。在c处上方的天花板上有一串香蕉,猴子想吃,但摘不到。房间的b处还有一个箱子,如果猴子站到箱子上,就可以摸着天花板。如图1所示,对于上述问题,可以通过谓词逻辑表示法来描述知识。要求通过VC语言编程实现猴子摘香蕉问题的求解过程。 图1 猴子摘香蕉问题 四、源代码 #include unsigned int i; void Monkey_Go_Box(unsigned char x, unsigned char y) {

用盲目搜索技术解决八数码问题

. 用盲目搜索技术解决八数码问题 题目 在3×3的棋盘,有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上 标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要解决的问题是:任意给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。 算法流程 使用宽度优先搜索 从初始节点开始,向下逐层对节点进形依次扩展,并考察它是否为目标节点,再对下层节点进行扩展(或搜索)之前,必须完成对当层的所有节点的扩展。再搜 索过程中,未扩展节点表OPEN中的节点排序准则是:先进入的节点排在前面, 后进入的节点排在后面。 宽度优先算法如下: 把初始结点S0放入OPEN表中 若OPEN表为空,则搜索失败,问题无解 取OPEN表中最前面的结点N放在CLOSE表中,并冠以顺序编号n 若目标结点,则搜索成功,问题有解N?Sg若N无子结点,则转2 扩展结点N,将其所有子结点配上指向N的放回指针,依次放入OPEN表的尾部,转2 源程序 #include 文档Word . #include #include

using namespace std; const int ROW = 3;//行数 const int COL = 3;//列数 const int MAXDISTANCE = 10000;//最多可以有的表的数目const int MAXNUM = 10000; typedef struct _Node{ int digit[ROW][COL]; int dist;//distance between one state and the destination 一个表和目的表的距离 int dep; // the depth of node深度 // So the comment function = dist + dep.估价函数值 int index; // point to the location of parent父节点的位置} Node; Node src, dest;// 父节表目的表 vector node_v; // store the nodes存储节点 文档Word . bool isEmptyOfOPEN() //open表是否为空

八数码问题C语言A星算法详细实验报告含代码

八数码问题C语言A星算法详细实验报告含代 码 Document serial number【UU89WT-UU98YT-UU8CB-UUUT-UUT108】

一、实验内容和要求 八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。 例如: (a) 初始状态 (b) 目标状态 图1 八数码问题示意图 请任选一种盲目搜索算法(广度优先搜索或深度优先搜索)或任选一种启发式搜索方法(全局择优搜索,加权状态图搜索,A 算法或 A* 算法)编程求解八数码问题(初始状态任选)。选择一个初始状态,画出搜索树,填写相应的OPEN表和CLOSED表,给出解路径,对实验结果进行分析总结,得出结论。 二、实验目的 1. 熟悉人工智能系统中的问题求解过程; 2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用; 3. 熟悉对八数码问题的建模、求解及编程语言的应用。 三、实验算法 A*算法是一种常用的启发式搜索算法。 在A*算法中,一个结点位置的好坏用估价函数来对它进行评估。A*算法的估价函数可表示为: f'(n) = g'(n) + h'(n)

这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值(也称为最小耗费或最小代价),h'(n)是n到目标的最短路经的启发值。由于这个f'(n)其实是无法预先知道的,所以实际上使用的是下面的估价函数: f(n) = g(n) + h(n) 其中g(n)是从初始结点到节点n的实际代价,h(n)是从结点n到目标结点的最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。用f(n)作为f'(n)的近似,也就是用g(n)代替 g'(n),h(n)代替h'(n)。这样必须满足两个条件:(1)g(n)>=g'(n)(大多数情况下都是满足的,可以不用考虑),且f必须保持单调递增。(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费 h(n)<=h'(n)。第二点特别的重要。可以证明应用这样的估价函数是可以找到最短路径的。 *算法的步骤 A*算法基本上与广度优先算法相同,但是在扩展出一个结点后,要计算它的估价函数,并根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都是估价函数最小的结点。 A*算法的步骤如下: 1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。

启发式搜索 八数码问题

启发式搜索 1. 介绍 八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格(以数字0来表示),与空格相邻的棋子可以移到空格中。 要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。 所谓问题的一个状态就是棋子在棋盘上的一种摆法。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。 2. 使用启发式搜索算法求解8数码问题。 1) A ,A 星算法采用估价函数 ()()()()w n f n d n p n ??=+??? , 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。 2) 宽度搜索采用f(i)为i 的深度,深度搜索采用f(i)为i 的深度的倒数。 3. 算法流程 ① 把起始节点S 放到OPEN 表中,并计算节点S 的)(S f ; ② 如果OPEN 是空表,则失败退出,无解; ③ 从OPEN 表中选择一个f 值最小的节点i 。如果有几个节点值相同,当其中有一个 为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点i ; ④ 把节点i 从 OPEN 表中移出,并把它放入 CLOSED 的已扩展节点表中; ⑤ 如果i 是个目标节点,则成功退出,求得一个解; ⑥ 扩展节点i ,生成其全部后继节点。对于i 的每一个后继节点j : 计算)(j f ;如果j 既不在OPEN 表中,又不在CLOCED 表中,则用估价函数f 把 它添入OPEN 表中。从j 加一指向其父节点i 的指针,以便一旦找到目标节点时记住一个解答路径;如果j 已在OPEN 表或CLOSED 表中,则比较刚刚对j 计算过的f 和前面计算过的该节点在表中的f 值。如果新的f 较小,则 (I)以此新值取代旧值。 (II)从j 指向i ,而不是指向他的父节点。 (III)如果节点j 在CLOSED 表中,则把它移回OPEN 表中。 ⑦ 转向②,即GOTO ②。

A星算法求八数码问题实验报告

人工智能实验报告 实验名称:八数码问题 姓名:xx 学号:2012210xx xx计算机学院 2014年1月14日

一.实验目的 掌握A*的思想,启发式搜索,来求解在代价最小的情况下将九宫格从一个状态转为另状态的路径。 二.实验内容 给定九宫格的初始状态,要求在有限步的操作内,使其转化为目标状态,且所得到的解是代价最小解(即移动的步数最少)并打印出求解路径。例如 2 8 3 1 6 4 7 0 5 2 8 3 1 6 4 7 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)等于最短距离,那么搜索将严格沿着最短路径进行此时的搜索效率是最高的。如果估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

四、算法流程: 是 是,输出路径 否,生成n 的所有子状态 Heuristic_Search(启发式搜索) While (未拓展表不为空?) 从未拓展表中删除第一个状态n N 为目标状态? Case:此子状态 不在拓展表和 未拓展表中 Case:此子状态在未拓展表中 Case:此子状态在拓展表 计算该子状态的估价函数值; 记录比已有的路径更短 的路径 记录比已有的路径更短的路径 返回

人工智能实验报告

实验报告 1.对CLIPS和其运行及推理机制进行介绍 CLIPS是一个基于前向推理语言,用标准C语言编写。它具有高移植性、高扩展性、 强大的知识表达能力和编程方式以及低成本等特点。 CLIPS由两部分组成:知识库、推理机。它的基本语法是: (defmodule< module-n ame >[< comme nt >]) CLIPS的基本结构: (1).知识库由事实库(初始事实+初始对象实例)和规则库组成。 事实库: 表示已知的数据或信息,用deftemplat,deffact定义初始事实表FACTLIS,由关系名、后跟 零个或多个槽以及它们的相关值组成,其格式如下: 模板: (deftemplate [] *) :: = | 事实: (deffacts [] *) 当CLIPS系统启动推理时,会把所有用deffact定义的事实自动添加到工作存储器中。常用命令如下:asser:把事实添加到事实库(工作存储器)中retract:删除指定事实 modify :修改自定义模板事实的槽值duplicate :复制事实 clear:删除所有事实 规则库 表示系统推理的有关知识,用defrule命令来定义,由规则头、后跟零个或多个条件元素以 及行为列表组成,其格式如下: (defrule [] * ; =>

八数码问题报告

八数码问题分析 班级:计算机1041 学号:01 姓名:李守先 2013年9月26日

摘要 八数码问题(Eight-puzzle Problem )是人工智能中一个很典型的智力问题。 本文以状态空间搜索的观点讨论了八数码问题,给出了八数码问题的Java 算法与实现的思想, 分析了A*算法的可采纳性等及系统的特点。 关键词 九宫重排, 状态空间, 启发式搜索, A*算法 1 引言 九宫重排问题(即八数码问题)是人工智能当中有名的难题之一。问题是在3×3方格盘上,放有八个数码,剩下一个位置为空,每一空格其上下左右的数码可移至空格。问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始状态转化为目标状态。状态转换的规则:空格周围的数移向空格,我们可以看作是空格移动,它最多可以有4个方向的移动,即上、下、左、右。九宫重排问题的求解方法,就是从给定的初始状态出发,不断地空格上下左右的数码移至空格,将一个状态转化成其它状态,直到产生目标状态。 图1 许多学者对该问题进行了有益的探索[1,2,4,6]。给定初始状态,9个数在3×3中的放法共有9!=362880种,其状态空间是相当大的。因此, 有必要考虑与问题相关的启发性信息来指导搜索,以提高搜索的效率。当然,还有个很重要的问题:每个初始状态都存在解路径吗?文献给出了九宫重排问题是否有解的判别方法:九宫重排问题存在无解的情况,当遍历完所有可扩展的状态也没有搜索到目标状态就判断为无解。可以根据状态的逆序数来先验的判断是否有解,当初始状态的逆序数和目标状态的逆序数的奇偶性相同时,问题有解;否则问题无解。状态的逆序数是定义把三行数展开排成一行,并且丢弃数字 0 不计入其中,ηi 是第 i 个数之前比该数小的数字的个数,则 η=Σηi 是该状态的逆序数,图2说明了逆序数计算的过程 。 本文介绍用JAVA 编写九宫重排问题游戏。游戏规则是,可随机产生或由用户设置初始状态,由初始状态出发,不断地在空格上下左右的数码移至空格,若能排出目标状态,则成功。为了避免对无解节点进行无用搜索,首先对初始节点进行逆序数分析,对有解的节点进行搜索,从而节省了资源,也提高了效率。本文内容安排: 第2部分介绍几个相关的概念和A*算法以及可采纳性 ;

八数码问题实验报告讲解

《八数码问题》实验报告 一、实验目的: 熟练掌握启发式搜索A *算法。 二、实验内容: 使用启发式搜索算法求解8数码问题。编制程序实现求解8数码问题A *算法,采用估价函数 ()()()()w n f n d n p n ??=+??? , 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。 三、实验原理: 1. 问题描述: 八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格(以数字0来表示),与空格相邻的棋子可以移到空格中。 要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。 所谓问题的一个状态就是棋子在棋盘上的一种摆法。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。 2. 原理描述: 启发式搜索 (1)原理 启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路径,提高了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。 (2)估价函数

计算一个节点的估价函数,可以分成两个部分: 1、 已经付出的代价(起始节点到当前节点); 2、 将要付出的代价(当前节点到目标节点)。 节点n 的估价函数)(n f 定义为从初始节点、经过n 、到达目标节点的路径的最小代价 的估计值,即)(* n f = )(* n g + )(* n h 。 )(*n g 是从初始节点到达当前节点n 的实际代价; )(*n h 是从节点n 到目标节点的最佳路径的估计代价。 )(*n g 所占的比重越大,越趋向于宽度优先或等代价搜索;反之,)(*n h 的比重越大, 表示启发性能就越强。 (3)算法描述: ① 把起始节点S 放到OPEN 表中,并计算节点S 的)(S f ; ② 如果OPEN 是空表,则失败退出,无解; ③ 从OPEN 表中选择一个f 值最小的节点i 。如果有几个节点值相同,当其中有一个 为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点i ; ④ 把节点i 从 OPEN 表中移出,并把它放入 CLOSED 的已扩展节点表中; ⑤ 如果i 是个目标节点,则成功退出,求得一个解; ⑥ 扩展节点i ,生成其全部后继节点。对于i 的每一个后继节点j : 计算)(j f ;如果j 既不在OPEN 表中,又不在CLOCED 表中,则用估价函数f 把 它添入OPEN 表中。从j 加一指向其父节点i 的指针,以便一旦找到目标节点时记住一个解答路径;如果j 已在OPEN 表或CLOSED 表中,则比较刚刚对j 计算过的f 和前面计算过的该节点在表中的f 值。如果新的f 较小,则 (I)以此新值取代旧值。 (II)从j 指向i ,而不是指向他的父节点。 (III)如果节点j 在CLOSED 表中,则把它移回OPEN 表中。 ⑦ 转向②,即GOTO ②。 (3)算法流程图:

相关主题
文本预览
相关文档 最新文档