人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的定义可以分为两部分,即“人工”和“智能”。“人工”比较好理解,争议性也不大。有时我们会要考虑什么是人力所能及制造的,或者人自身的智能程度有没有高到可以创造人工智能的地步,等等。但总的来说,“人工系统”就是通常意义下的人工系统。
人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的“容器”。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。
人工智能是一门极富挑战性的科学,从事这项工作的人必须懂得计算机知识,心理学和哲学。人工智能是包括十分广泛的科学,它由不同的领域组成,如机器学习,计算机视觉等等,总的说来,人工智能研究的一个主要目标是使机器能够胜任一些需要人类智能才能完成的复杂工作。但不同的时代、不同的人对这种“复杂工作”的理解是不同的。
用JAVA语言编写和调试一个基于宽度优先搜索法的解决“野人与传教士过河”问题的程序。目的是学会运用知识表示方法和搜索策略求解一些考验智力的简单问题,熟悉简单智能算法的开发过程并理解其实现原理。
野人与传教士渡河问题:3个野人与3个传教士打算乘一条船到对岸去,该船一次最多能运2个人,在任何时候野人人数超过传教士人数,野人就会把传教士吃掉,如何用这条船把所有人安全的送到对岸?
野人与传教士渡河问题实验原理:
先实现宽度优先搜索
定义一个结构体或类来保存状态信息,状态信息包括当前某一岸边野人和传教士的人数,船所在位置,以及指向前次状态节点的指针或其在链表中的编号等
每次船运载的人数只有5种可能
1野人;1传教士;2野人;2传教士;1野人1传教士
1.为了避免重复,我们将搜索过的状态记录下来,之后避开搜索这个状态。
2.我们把满足条件的状态称为安全状态,首先要定义出安全状态,通过对问题的分析, 不难得出只有满足以下条件之一的状态才是安全的(以左岸为例):
1)传教士与野人的数目相等;
2)传教士都在左岸;
3)传教士都不在左岸。
我们只对安全的状态进行深度优先搜索,直至找到一个合法的解。
野人传教士渡河问题程序功能结构图:
流程图:
数据结构定义:
class state //定义状态类
public int left_c; //定义左岸传教士
public int left_y; //定义左岸野人
public int boat; //定义船的位置
public int right_c; //定义右岸传教士
public int right_y; //定义右岸野人
主要变量:
nullboat.setleft_c //空数组中左岸传教士人数
nullboat.setleft_y //空数组中左岸野人人数
nullboat.setright_c //空数组中右岸传教士人数
nullboat.setright_y //空数组中右岸野人人数
nullboat.setboat //空数组中船的位置
import java.util.ArrayList; //Java数组类
import java.util.List;class state{ //定义状态类public int left_c; //定义左岸传教士public int left_y; //定义左岸野人public int boat; //定义船的位置public int right_c; //定义右岸传教士public int right_y; //定义右岸野人public state(int left_c,int left_y,int boat,int right_c,int right_y) //state方法重写{ super();this.left_c=left_c;this.left_y=left_y;this.boat=boat;this.right_c=right_c;this.right_y=right_y;}public void setleft_c(int i) { // TODO Auto-generated method stubthis.left_c=i;}public void setleft_y(int left_y2) {// TODO Auto-generated method stubthis.left_y=left_y2;}public void setright_c(int i) {// TODO Auto-generated method stubthis.right_c=i;}public void setright_y(int right_y2) {// TODO Auto-generated method stubthis.right_y=right_y2;}public void setboat(int i) {// TODO Auto-generated method stubthis.boat=i;}
}public class Cross { //过河方法//static List<state> list=new ArrayList<state>(); //数组集合
// static state state;
// static List<state> list;public static void robot(state state,List<state> list){ //将class state变成数组if (state.right_c == 3 && state.right_y== 3) //判断是否完成过河{ System.out.println("\n\n以下本次过河的方法以及实时状态。\n");System.out.println("船位置"+"\t"+"左传"+"\t"+"左野"+"\t"+"右传"+"\t"+"右野");for (int i = 0; i < list.size(); i++){//输出船的位置,左岸传教士人数,左岸野人数,右岸传教士人数,右岸野人数System.out.println(list.get(i).boat+"\t "+list.get(i).left_c+"\t "+list.get(i).left_y+"\t "+list.get(i).right_c+"\t "+list.get(i).right_y);}return ;}// 判断是否重复操作 for (int i= 0; i < list.size() - 1; i++) {if (list.get(i).left_c == state.left_c && list.get(i).left_y == state.left_y&&list.get(i).boat==state.boat) {return ;}}// 人数合理吗for (int i= 0; i < list.size() - 1; i++) {if (state.left_c< 0 || state.left_y< 0 || state.right_c< 0 || state.right_y< 0) //判断人数是否小于0{return ;}}// 传教士被吃了没if ((state.left_c < state.left_y && state.left_c != 0)|| (state.right_c< state.right_y && state.right_c != 0)){return ;} //定义一个空的状态 state nullboat = new state(0, 0, 0, 0, 0);//两个传教士过河nullboat.setleft_c(state.left_c - 2 * state.boat); //此时左岸传教士人数为1nullboat.setleft_y(state.left_y); //此时左岸野人人数为3nullboat.setright_c(state.right_c + 2 * state.boat); //此时右岸传教士人数为2nullboat.setright_y(state.right_y); //此时右岸野人人数为0nullboat.setboat(-state.boat); //此时船在右岸list.add(nullboat);robot(nullboat, list);list.remove(list.size() - 1);// 两个野人过河nullboat.setleft_c(state.left_c); //此时左岸传教士人数为3nullboat.setleft_y(state.left_y - 2 * state.boat); //此时左岸野人人数为1nullboat.setright_c(state.right_c); //此时右岸传教士人数为0nullboat.setright_y(state.right_y + 2 * state.boat); //此时右岸野人人数为2nullboat.setboat(-state.boat); //此时船在右岸list.add(nullboat);robot(nullboat,list);list.remove(list.size() - 1);// 一个野人,一个传教士 nullboat.setleft_c(state.left_c - 1 * state.boat); //此时左岸传教士人数为2nullboat.setleft_y(state.left_y - 1 * state.boat); //此时左岸野人人数为2nullboat.setright_c(state.right_c + 1 * state.boat); //此时右岸传教士人数为1nullboat.setright_y(state.right_y + 1 * state.boat); //此时右岸野人人数为1nullboat.setboat(-state.boat); //此时船在右岸list.add(nullboat);robot(nullboat, list);list.remove(list.size() - 1);// 一个传教士过河nullboat.setleft_c(state.left_c - 1 * state.boat); //此时左岸传教士人数为2nullboat.setleft_y(state.left_y); //此时左岸野人人数为3nullboat.setright_c(state.right_c + 1 * state.boat); //此时右岸传教士人数为1nullboat.setright_y(state.right_y); //此时右岸野人人数为0nullboat.setboat(-state.boat); //此时船在右岸list.add(nullboat);robot(nullboat, list);list.remove(list.size() - 1);// 一个野人过河nullboat.setleft_c(state.left_c); //此时左岸传教士人数为3nullboat.setleft_y(state.left_y - 1 * state.boat); //此时左岸野人人数为2nullboat.setright_c(state.right_c); //此时右岸传教士人数为0nullboat.setright_y(state.right_y + 1 * state.boat); //此时右岸野人人数为1nullboat.setboat(-state.boat); //此时船在右岸list.add(nullboat);robot(nullboat, list);list.remove(list.size() - 1);return ;} public static void main(String[] args) { //主函数 List<state> list = new ArrayList<state>();state begin =new state(3,3,1,0,0); //定义初始状态的船位置、左右传教士人数和野人人数list.add(begin);robot(begin, list);}
}
体会
在传教士和野人渡河问题中,在讨论用产生式系统求解问题时,有时引入状态空间图的概念很有帮助。状态空间图是一个有向图,其节点可表示问题的各种状态(综合数据库),节点之间的弧线代表一些操作(产生式规则),它们可把一种状态导向另一种状态。这样建立起来的状态空间图,描述了问题所有可能出现的状态及状态和操作之间的关系,因而可以较直观地看出问题的解路径及其性质。