昆明理工大学 人工智能 实验报告

时间:2024.5.8

昆明理工大学信息工程与自动化学院学生实验报告

( 20##—— 20## 学年 第 一 学期 )

课程名称:人工智能导论   开课实验室:信自楼432室   20##年10月26日

                           目录

一、实验问题... 3

二、实验目的... 3

三、实验原理... 3

四、程序框图... 4

五、实验结果及分析... 5

1、随机检验... 5

2、该问题广度优先搜索算法的搜索树;... 6

3、该问题的Open 表和 Closed 表:... 7

六、结论... 7

七、源程序及注释... 8

一、实验问题

八数码问题的求解,及程序设计。具体要求如下

在3*3的方格中的棋盘中任意摆放1到8个自然数和一个空格,其初始状态如下:

请选择一种盲目搜索的算法或选择一种启发式搜索的算法编程求解八数码问题,初始状态任选,并对使用进行合理分析做出合理结果。

二、实验目的

1、熟悉人工智能系统中的问题求解过程;

2、熟悉状态空间的满目搜索和启发式搜索算法的运用;

3、熟悉对八码数问题的建模、求解及编程语言的运用;

三、实验原理

经过分析,8数码问题中可采用的搜速策略共有:

1.广度优先搜索

2.深度优先搜索

2.有界深度优先搜索

4.最好优先搜索

5.局部择优搜索

一共五种。其中,广度优先搜索法是可采纳的,有界深度优先搜索法是不完备的,最好优先和局部择优搜索法是启发式搜索法。在实验时,我采用了广度优先算法

广度优先算法搜索原理:

广度优先搜索就是始终先在同一级节点中考查,只有当同一级节点考察完之后,才考查下一级的节点。

(1)把起始节点放到OPEN表中;

(2)如果OPEN是个空表,则没有解,失败退出;否则继续; 

(3)把第一个节点从OPEN表中移除,并把它放入CLOSED的扩展节点表中;

(4)扩展节点n。如果没有后继节点,则转向(2); 

(5)把n的所有后继结点放到OPEN表末端,并提供从这些后继结点回到n的指针;

(6)如果n的任意一个后继结点是目标节点,则找到一个解答,成功退出,否则转(2)

四、程序框图

五、实验结果及分析

1、随机检验

初始状态为:

的运行结果为:

运行结果如图所示;

目标状态为:

2、该问题广度优先搜索算法的搜索树;

3、该问题的Open 表和 Closed 表:

六、结论

  通过实验问题的求解过程就是搜索的过程,让我明白了采用适合的搜索算法是关键的,因为一个合适的算法对求解过程的效率有很大的影响,包括各种规则、过程和算法等推理技术。八数码问题中,将牌的移动来描述规则,是一种相对较简单的方法。虽然我使用的广度优先算法实现八数码问题,但是我不得不说广度优先算法其实是一种比较费劲的方式;然而深度优先将是一个相对好的方法,利用深度优先不但减少了程序实现的时间,是一种不错的方式。但最好的方式是启发式搜索方式实现,在很大程度上相对于前两种方式是一种非常好的实现方式,不但节省了时间,也节省了空间。  这次试验使我对搜索算法有了一定的了解,并对实现这个问题的执行过程有了更一步的认识。也通过它解决了八数码问题,但在实际的过程中还存在很多问题,也看了一些辅助书籍,以后还要加强学习,加强理论与实际的练习。总之,这次试验让我受益匪浅。

七、源程序及注释

//八数码问题——广度优先

#include <iostream.h>

struct Snode

{

       int parent;  //指向该结点父节点的编号

    int map[9];

public:

    void TransformIn(const int *d);

    void TransformOut(int *d);

};

void Snode::TransformIn(const int *d)

{

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

              map[i]=d[i];

}

#define MAX_OPEN_LEN 50000

#define MAX_CLOSE_LEN 50000

Snode OPEN[MAX_OPEN_LEN];

int op=0;

Snode CLOSE[MAX_CLOSE_LEN];

int cp=0;

int result[50000][9];   //result数组用于保存路径,纵向9个数为对应的map数组

int have(Snode &node1,Snode &node2)  //判断是否为新节点

{

       int flag=1;

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

       {

              if(node1.map[i]!=node2.map[i]) flag=0;

       }

       return flag;

}

inline void swapn(int &a,int &b)

{

       int tmp=a;

    a=b;

    b=tmp;

}

//判断节点是否为目标节点

int judge(Snode &node)

{

       int flag=1;

       int g[9]={1,2,3,8,0,4,7,6,5};

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

       {

              if(node.map[i]!=g[i])

                     flag=0;

       }

       return flag;

}

int Astar(const int *d)

{

       int begin=0;                    //begin含义是每次从OPEN表中去除要扩展的那个节点

       int node_number=1;              //扩展节点数,初始时已有OPEN[0]节点,故为1,即node_number=cp+op

       static int dp[4]={-3,-1,1,3};   //-3表示向上移动,3表示向下移动,-1表示向左移动,1表示向右移动

    op=1;

    cp=0;

    OPEN[begin].TransformIn(d);

       OPEN[begin].parent=-1;         //根节点的parent值设置为-1

    while(op>0)//OPEN表不为空

       {

              int i=0,zero,pos,j=0,k=0;

        if(judge(OPEN[begin])==1)  //找到的这个节点已经是目标节点

              {

                     CLOSE[cp]=OPEN[begin];

                     while(begin!=-1)         //while循环用于把路径存入数组result中,顺序是从目标节点到根节点

                     {

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

                        {

                               result[j][i]=OPEN[begin].map[i];

                        }

                        j=j+1;

                        begin=OPEN[begin].parent;

                     }

                     for(i=j-1;i>=0;i--)        //两层for循环用于把result数组中保存的路径输出,从最后一个向前输出

                     {

                            for(k=0;k<9;k++)

                            {

                                   cout<

                                if(k%3==2)  cout<

                            }

                            cout<

                     }

                     cout<<"生成的节点总数为:"<

               cout<<"扩展的节点总数为:"<

            return 1;

              }

       for(zero=0;zero<9;++zero)

          {

                 if(OPEN[begin].map[zero]==0)

           break;                        //跳出当前for循环,向下执行

          }

       for(i=0;i<4;++i)

          {

           if(zero==0&&(i==0||i==1))  continue;     //判断zero位置怎样可以移动,与上边的判断相同

           if(zero==1&&i==0)         continue;

           if(zero==2&&(i==0||i==2))  continue;

           if(zero==3&&i==1)         continue;

           if(zero==5&&i==2)         continue;

           if(zero==6&&(i==1||i==3))  continue;

           if(zero==7&&i==3)         continue;

           if(zero==8&&(i==2||i==3))  continue;

           pos=zero+dp[i];

                swapn(OPEN[begin].map[zero],OPEN[begin].map[pos]);   //交换位置

           Snode child;

           child.TransformIn(OPEN[begin].map);

                

           for(j=0;j

                 {

                        if(have(CLOSE[j],child)==1)

                               break;

                 }

           if(j==cp)                         //得到新节点

                 {                

                        OPEN[op]=child;             //先使用op,再op加1

                        OPEN[op].parent=begin;

                        op=op+1;

                     node_number=node_number+1;

                        if(node_number==10000)              //有些情况可能不存在解,这里当op等于10000时退出,并返回0

                        {

                             cout<<"node_number="<

                             cout<<"op="<

                             return 0;

                        }

                 }

           swapn(OPEN[begin].map[zero],OPEN[begin].map[pos]);        //前边把OPEN[min]的值进行了交换,现在再换回去,保持OPEN[min]的map数组

          }

          CLOSE[cp++]=OPEN[begin];

          begin=begin+1;

       }

    return 0;

}

void OutputSolution()

{

       cout<<"Succeed!\n";

}

int main(void)

{

       //int map[9]={ 2, 8, 3, 1, 4, 0, 7, 6, 5 };

       //{1,3,4,2,8,6,5,7,0};

       //{6,4,7,8,5,0,3,2,1};

       //{1,2,3,4,5,6,7,8,0};

       //{2,8,3,1,0,4,7,6,5};

       //{1,3,4,0,6,2,8,7,5};

    int map[9];

       cout<<"请输入初始数组:"<

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

              for(int j=0;j<3;j++)

                     cin>>map[3*i+j];

       if(Astar(map))

              cout<<"Succeed!"<

    else

    cout<<"no solution!\n";

       cout<<"按n键退出"<

       char c;

       cin>>c;

       if(cin&&c!='n')

       {

              return 0;

       }

    return 0;

}

更多相关推荐:
大连理工大学实验报告模版

【大物实验】拉伸法测弹性模量http://hi.baidu.com/%CE%D2%B5%C4%D3%EE%D6%AE%D6%E6/blog/item/2fa915f54e65df75dcc4741b.html【…

RLC电流研究实验报告-大连理工大物实验

RLC串联电路特性的研究实验报告电阻、电容及电感是电路中的基本元件,由RC、RL、RLC构成的串联电路具有不同的特性,包括暂态特性、稳态特性、谐振特性.它们在实际应用中都起着重要的作用。一、实验目的1.通过研究…

大连理工大学 大物实验报告 温度传感技术

这个实验操作步骤比较简单,实验过程中主要就是等待,不难。老师是武震林,人特别好。报告为什么扣分,我也不太清楚,可能是数据点没用X表示。需要注意的是伏安特性曲线要过原点,有些点要舍去。

大连理工大学盘锦校区大学物理实验报告页

大连理工大学大学物理实验报告实验报告完成日期学号姓名班级实验准备时间第周周第节实验完成时间第周周第节实验名称大连理工大学大学物理实验实验报告附件1预习与准备学号姓名班级实验准备时间年月日第周周第节实验名称大连理...

大工大物实验报告——低压气体直流击穿特性

低压气体直流击穿特性实验目的1研究低气压的实验和维持方法了解气压的测量原理2观测直流暗放电的脉冲现象研究电子碰撞引起雪崩电离的过程掌握分析和识别微观现象的实验方法认识低气压气体直流击穿现象研究雪崩电离过程与气体...

大工电机与拖动实验报告一

实验报告一实验名称:单相变压器实验实验目的:1.通过空载和短路实验测定变压器的变比和参数。2.通过负载实验测取变压器的运行特性。实验项目:1.空载实验测取空载特性。2.短路实验测取短路特性。3.负载实验保持,的…

20xx年大连理工大学考研884物理化学及实验凯程学员回忆版

凯程考研集训营为学生引路为学员服务20xx年大连理工大学考研884物理化学及实验凯程学员回忆版选择填空题12小题每小题2分共24分恒温下反应As3Bg2CgDl判断该反应过程的H和U的大小正确答案是HU对于理想...

柏诺兹(J - 大学物理 大连理工大学国家级精品课程建设工程

柏诺兹JGeorgBednorz19xx和缪勒KarlAMuller19xx因发现钡镧铜氧系统中的高Tc超导电性共同分享了19xx年度诺贝尔物理学奖超导电性的发现使人们认识到超导技术有广泛的应用前景为了寻找更适...

大连理工大学物理与光电工程学院

大连理工大学物理与光电工程学院20xx年硕士研究生复试标准及复试方法学术型和全日制专业学位一复试分数线二复试比例以网上公布的复试名单为准按照物理学一级学科招生人数不含推免生下同的120来确定复试人数分专业排序录...

大连理工大学物理与光电工程学院

大连理工大学物理与光电工程学院20xx年硕士研究生复试标准及复试方法学术型和全日制专业学位一复试分数线二复试比例以网上公布的复试名单为准按照物理学一级学科招生人数不含推免生下同的120来确定复试人数分专业排序录...

大连理工大学考研物理试题及答案

考试日期20xx年1月19日下午大连理工大学二三年硕士生入学考试化工原理及实验试题注试题必须注明题号答在答题纸上否则试卷作废一填空45分1流体流动的两种基本类型为判断流体流动类型的无因次数群特征数2在重力场中流...

大连理工大学数字图像处理实验预习报告2

数字图像处理实验预习报告学院系电信学部专业电子信息工程班级电子1102姓名陈柯锦学号20xx81442组实验时间实验室实验台指导教师签字邢慧玲成绩实验名称图像的边缘检测一实验目的和要求1理解图像边缘提取的基本概...

大连理工大学大物实验报告(17篇)