做网站买服务器,企业网站如何seo,wordpress 禁止百度转码,银行门户网站开发一、实验目的 本实验课程是计算机、智能、物联网等专业学生的一门专业课程#xff0c;通过实验#xff0c;帮助学生更好地掌握人工智能相关概念、技术、原理、应用等#xff1b;通过实验提高学生编写实验报告、总结实验结果的能力#xff1b;使学生对智能程序、智能算法等有…一、实验目的 本实验课程是计算机、智能、物联网等专业学生的一门专业课程通过实验帮助学生更好地掌握人工智能相关概念、技术、原理、应用等通过实验提高学生编写实验报告、总结实验结果的能力使学生对智能程序、智能算法等有比较深入的认识。本实验通过不同知识的表达与推理问题强化学生对知识表示的了解和应用为人工智能后续环节的课程奠定基础。 二、基本要求
1、实验前复习《人工智能》课程中的有关内容。
2、准备好实验数据。
3、编程或验证需要独立完成程序应加适当的注释。
4、完成实验报告。 三、实验软件
使用C或CVisual studio平台等,或其它语言,如matlab或Python。 四、实验内容
一猴子摘香蕉问题
利用一阶谓词逻辑求解猴子摘香蕉问题房内有一个猴子一个箱子天花板上挂了一串香蕉其位置如图1所示猴子为了拿到香蕉它必须把箱子搬到香蕉下面然后再爬到箱子上。请定义必要的谓词列出问题的初始化状态即下图所示状态目标状态猴子拿到了香蕉站在箱子上箱子位于位置b。附加从初始状态到目标状态的谓词演算过程。 1、定义描述环境状态的谓词。
AT(x,w)x在w处个体域x?{monkey}w?{a,b,c,box}
HOLD(x,t)x手中拿着t个体域t?{box,banana}
EMPTY(x)x手中是空的
ON(t,y)t在y处个体域y?{b,c,ceiling}
CLEAR(y)y上是空的
BOX(u)u是箱子个体域u?{box}
BANANA(v)v是香蕉个体域v?{banana}
2、使用谓词、连结词、量词来表示环境状态。
问题的初始状态可表示为SoAT(monkey,a)-EMPTY(monkey)-ON(box,c)-ON(banana,ceiling)-CLEAR(b)-BOX(box)-BANANA(banana)
要达到的目标状态为SgAT(monkey,box)-HOLD(monkey,banana)-ON(box,b)-CLEAR(ceiling)-CLEAR(c)-BOX(box)-BANANA(banana)
3、从初始状态到目标状态的转化, 猴子需要完成一系列操作, 定义操作类谓词表示其动作。
WALK(m,n)猴子从m走到n处个体域m,n?{a,b,c}
CARRY(s,r)猴子在r处拿到s个体域r?{c,ceiling}s?{box,banana}
CLIMB(u,b)猴子在b处爬上u
这3个操作也可分别用条件和动作来表示。条件直接用谓词公式表示是为完成相应操作所必须具备的条件当条件中的事实使其均为真时则可激活操作规则于是可执行该规则中的动作部分。动作通过前后状态的变化表示即通过从动作前删除或增加谓词公式来描述动作后的状态。 4、按照行动计划, 一步步进行状态替换, 直至目标状态
AT(monkey,a)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?
BANANA(banana)
AT(monkey,c)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?
BANANA(banana)
AT(monkey,c)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR(c)?BOX(box)?
BANANA(banana)
AT(monkey,b)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR(c)?BOX(box)?
BANANA(banana)
AT(monkey,box)?EMPTY(monkey)?ON(box,b)?ON(banana,ceiling)?CLEAR(c)?BOX(box)?
BANANA(banana)
AT(monkey,box)?HOLD(monkey,banana)?ON(box,b)?CLEAR(ceiling)?CLEAR(c)?BOX(box)?
BANANA(banana)目标得解
猴子行动的规则序列是WALK(a,c)→CARRY(c,box)→WALK(c,b)→CLIMB(box,b)→
CARRY(banana,ceiling)
5、参考代码
#include stdio.h
struct State
{int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/int box; /*-1:box at A;0:box at B;1:box at C;*/int banana; /*Banana at B,Banana0*/int monbox; /*-1: monkey on the box;1: monkey the box;*/
};
struct State States [150];
char* routesave[150];
/*function monkeygoto,it makes the monkey goto the other place*/
void monkeygoto(int b,int i)
{ int a;ab;if (a-1){routesave[i]Monkey go to A;States[i1]States[i];States[i1].monkey-1;}else if(a0){routesave[i]Monkey go to B;States[i1]States[i];States[i1].monkey0;}else if(a1){routesave[i]Monkey go to C;States[i1]States[i];States[i1].monkey1;}else{printf(parameter is wrong);}
}
/*end function monkeyygoto*/
/*function movebox,the monkey move the box to the other place*/
void movebox(int a,int i)
{ int B;Ba;if(B-1){routesave[i]monkey move box to A;States[i1]States[i];States[i1].monkey-1;States[i1].box-1;}else if(B0){routesave[i] monkey move box to B;States[i1]States[i];States[i1].monkey0;States[i1].box0;}else if(B1){routesave[i] monkey move box to C;States[i1]States[i];States[i1].monkey1;States[i1].box1;}else{printf(parameter is wrong);}
}
/*end function movebox*/
/*function climbonto,the monkey climb onto the box*/
void climbonto(int i)
{routesave[i]Monkey climb onto the box;States[i1]States[i];States[i1].monbox1;
}
/*function climbdown,monkey climb down from the box*/
void climbdown(int i)
{ routesave[i]Monkey climb down from the box;States[i1]States[i];States[i1].monbox-1;
}
/*function reach,if the monkey,box,and banana are at the same place,the monkey reach banana*/
void reach(int i)
{ routesave[i]Monkey reach the banana;
}
/*output the solution to the problem*/
void showSolution(int i)
{int c;printf (%s \n, Result to problem:);for(c0; ci1; c){printf (Step %d : %s \n,c1,routesave[c]);}printf(\n);
}
/*perform next step*/
void nextStep(int i)
{int c;int j;if(i150){printf(%s \n, steplength reached 150,have problem );return;}for (c0; ci; c) /*if the current state is same to previous,retrospect*/{if(States[c].monkeyStates[i].monkeyStates[c].boxStates[i].boxStates[c].bananaStates[i].bananaStates[c].monboxStates[i].monbox){return;}}if(States[i].monbox1States[i].monkey0States[i].banana0States[i].box0){showSolution(i);printf(Press any key to continue \n);getchar();/*to save screen for user,press any key to continue*/return;} ji1; if(States[i].monkey0){ if(States[i].box0){if(States[i].monbox-1){climbonto(i);reach(i1);nextStep(j);/*monkeygoto(-1,i);nextStep(j);monkeygoto(0,i);nextStep(j);movebox(-1,i);nextStep(j);movebox(0,i);nextStep(j);*/}else{reach(i1);nextStep(j);/*climbdown(i);nextStep(j);*/}}else if(States[i].box1){/*monkeygoto(-1,i);nextStep(j);*/monkeygoto(1,i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}else /*box-1*/{monkeygoto(-1,i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}}/*end if*/if(States[i].monkey-1){ if(States[i].box-1){if(States[i].monbox-1){ movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}else{climbdown(i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}}else if(States[i].box0){ monkeygoto(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}else{monkeygoto(1,i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}}/*end if*/if(States[i].monkey1){ if (States[i].box1){if(States[i].monbox-1){ movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}else{climbdown(i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j); }}else if(States[i].box-1){ monkeygoto(-1,i);nextStep(j);movebox(0,i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}else{monkeygoto(0,i);nextStep(j);movebox(0,i);nextStep(j);climbonto(i);reach(i1);nextStep(j);}}/*end if*/
}/*end nextStep*/
int main()
{States[0].monkey-1;States[0].box1;States[0].banana0;States[0].monbox-1;nextStep(0);
} 二传教士(牧师)与野人问题
问题描述
有n个牧师和n个野人准备渡河但只有一条能容纳c个人的小船为了防止野人侵犯牧师要求无论在何处牧师的人数不得少于野人的人数(除非牧师人数为0)且假定野人与牧师都会划船试设计一个算法确定他们能否渡过河去若能则给出小船来回次数最少的最佳方案。
实验步骤
输入牧师人数(即野人人数)n小船一次最多载人量c。
输出若问题无解则显示Failed否则显示Successed输出所有可行方案并标注哪一组是最佳方案。用三元组(X1, X2, X3)表示渡河过程中的状态。并用箭头连接相邻状态以表示迁移过程初始状态-中间状态-目标状态。
例当输入n2c2时输出221-200-211-010-021-000
其中X1表示起始岸上的牧师人数X2表示起始岸上的野人人数X3表示小船现在位置(1表示起始岸0表示目的岸)。
要求写出算法的设计思想和源程序并有用户界面实现人机交互控制台或者窗口都可以进行输入和输出结果如
Please input n: 2 Please input c: 2
Optimal Procedure: 221-200-211-010-021-000
Successed or Failed?: Successed 五、学生实验报告要求
1对于猴子摘香蕉问题根据自己编写代码或者参考代码用不同的初始状态测试代码记录每种初始状态下的输出结果并对每个结果进行解释。 2完善猴子摘香蕉问题参考代码参考代码中有什么问题应该如何修改会更好。
问题
1. 数组索引和函数调用 使用数组索引i访问和更新状态。确保数组索引在范围内以避免潜在的内存问题。 考虑将状态数组封装在结构体内部或将其作为参数传递给函数而不是使用全局数组。
2. 字符串赋值 避免直接将字符串赋值给 routesave[i]例如 routesave[i] Monkey go to A;使用strcpy或类似的函数进行字符串赋值以避免潜在的问题。
3. 未使用的变量 movebox函数中声明了变量int B;但未使用。移除它以避免混淆。
4. 递归函数 nextStep 函数是递归的它一直调用自身。这可能会导致大量步骤时发生堆栈溢出。考虑使用迭代方法或者根据需要增加堆栈大小。
5. 内存管理 代码使用一个固定大小的数组 (States[150]) 存储状态。如果状态数量不能事先确定考虑使用动态内存分配或其他数据结构。 3传教士(牧师)与野人问题写出状态表示的数据结构还有每种解的状态迁移图示。
struct State {int m;//传教士int c;//野人int dep;//已划船次数int boat;//左岸是否有船bool friend operator (const struct State a, const struct State b)//为实现自定义类型的set提供排序规则{return a.dep b.dep;//升序排序}
};
例n2,c2时
1.(2,2,1) - (2,0,0) - (2,1,1) - (0,1,0) - (0,2,1) - (0,0,0)
2.(2,2,1) - (2,0,0) - (2,1,1) - (0,1,0) - (1,1,1) - (0,0,0)
3.(2,2,1) - (1,1,0) - (2,1,1) - (0,1,0) - (0,2,1) - (0,0,0)
4.(2,2,1) - (1,1,0) - (2,1,1) - (0,1,0) - (1,1,1) - (0,0,0) 4写出传教士(牧师)与野人问题的程序清单(语言不限)
#includeiostream
#includeset
#includevector
using namespace std;int n, c;//传教士的人数及船的载客量
int min_deep INT_MAX;//船的最小来回次数
int path 0;//可达路径的数量struct State {int m;//传教士int c;//野人int dep;//已划船次数int boat;//左岸是否有船bool friend operator (const struct State a, const struct State b)//为实现自定义类型的set提供排序规则{return a.dep b.dep;//升序排序}
};
setState Set;//自定义类型State实现set
vectorvectorState res;//保存所有路径//判断状态是否已经在当前路径中避免重复加入
bool isExist(State next)
{for (auto it Set.begin(); it ! Set.end(); it)if (it-m next.m it-c next.c it-boat next.boat)return true;return false;
}
//输出路径
void output()
{for (int i 0; i res.size(); i){if (res[i].size() min_deep 1)//判断是否为最优路径cout optimal endl;cout Solution i 1 endl;for (int j 0; j res[i].size(); j)//依次输出路径上的各个状态cout ( res[i][j].m , res[i][j].c , res[i][j].boat ) endl;cout endl;}
}
//用深度优先进行搜索
void dfs(State s)
{Set.insert(s);//加入当前路径的集合中(已按状态的先后顺序排序if (s.m 0 s.c 0)//目标状态{if (s.dep min_deep)//记录最短路径的划船次数min_deep s.dep;path;vectorState v(Set.begin(), Set.end());res.push_back(v);//保存该路径Set.erase(--Set.end());//已达终点进行回退return;}if (s.boat 1)//左岸{for (int i c; i 1; i--)//船载i从左往右划{if (i s.m s.c)//i多于左岸的总人数continue;for (int j i; j 0; j--)//船上有j个野人{if (j s.c || i - j s.m)//多于左岸传教士、野人的实际人数continue;if (j ! i j i - j)//船上传教士的人数少于野人的人数continue;if (s.m - (i - j) ! 0 s.m - (i - j) ! n s.m - (i - j) ! s.c - j)//左岸剩下的传教士与野人的人数不相等continue;State next;next.boat 0;next.m s.m - (i - j);next.c s.c - j;next.dep s.dep 1;if (!isExist(next))//判断当前路径是否存在该状态dfs(next);}}}else//右岸{for (int i c; i 1; i--)//船载i个人从右往左划{if (i (n - s.m) (n - s.c))//i多于右岸的总人数continue;for (int j i; j 0; j--)//船上有j个野人{if (j n - s.c || i - j n - s.m)//多于右岸传教士、野人的实际人数continue;if (j ! i j i - j)//船上野人的数量大于传教士的数量continue;if (n - s.m - (i - j) ! 0 n - s.m - (i - j) ! n n - s.m - (i - j) ! n - s.c - j)//右岸剩下的传教士人数与野人不相等continue;State next;next.boat 1;next.m s.m (i - j);next.c s.c j;next.dep s.dep 1;if (!isExist(next))//判断当前路径是否存在该状态dfs(next);}}}Set.erase(--Set.end());//无路可走进行回退
}int main()
{cout 请输入传教士野人人数:;cin n;cout endl;cout 请输入船的载人量;cin c;State start;//初始状态start.m start.c n;start.boat 1;start.dep 0;dfs(start);cout Successed or Failed?:;if (path 0)cout failed endl;else{cout Successed endl;output();cout 共有 path 条路径。 endl;cout min_deep min_deep endl;}
}
5实验结果讨论。 这是n2,c2的情况共有四种情况的最短路径最短路径为5 这是n3,c2的情况共有四种情况的最短路径最短路径为11 3 汉诺塔问题
汉诺塔问题来自一个古老的传说在世界刚被创建的时候有一座钻石宝塔塔A),其上有64个金碟。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔塔B和塔C。从世界创始之日起婆罗门的牧师们就一直在试图把塔A上的碟子移动到塔C上去其间借助于塔B的帮助。每次只能移动一个碟子任何时候都不能把一个碟子放在比它小的碟子上面。当牧师们完成任务时世界末日也就到了。 采用问题归约法把汉诺塔问题分成以下三个步骤实现
将塔A上的n-1个碟子借助塔C先移到塔B上把塔A上剩下的一个碟子移到塔C上把n-1个碟子从塔B借助于塔A移到塔C上
实验要求
让盘子数从2 开始到7进行实验记录程序运行时间和递归调用次数。 2.画出盘子数n和运行时间t 、递归调用次数m的关系图并进行分析 分析
运行时间 vs 盘子数n 通常来说汉诺塔问题的解决时间呈指数增长。图表中应该看到一个指数曲线显示随着盘子数的增加解决问题所需的时间迅速增加。但是运行时间都太短了看不出明显趋势。
递归调用次数 vs 盘子数n 递归调用次数也是指数级增长的因为每增加一个盘子递归调用次数就翻倍。这与汉诺塔问题的递归性质相一致。
在解决类似指数级增长问题时递归算法可能会面临的性能挑战。
实验代码
import timedef hanoi(n, source, target, auxiliary):global recursive_callsif n 0:recursive_calls 1hanoi(n - 1, source, auxiliary, target)# 移动盘子# print(fMove disk {n} from {source} to {target})hanoi(n - 1, auxiliary, target, source)def run_experiment(n):global recursive_callsrecursive_calls 0start_time time.time()hanoi(n, A, C, B)end_time time.time()execution_time end_time - start_timereturn execution_time, recursive_calls# 实验
results []
for i in range(2, 8):time_taken, calls_made run_experiment(i)results.append((i, time_taken, calls_made))# 打印结果
print(n\tTime(s)\tRecursive Calls)
for result in results:print(f{result[0]}\t{result[1]:.6f}\t{result[2]})import matplotlib.pyplot as pltdef plot_results(results):n_values [result[0] for result in results]time_values [result[1] for result in results]calls_values [result[2] for result in results]# Plotting time vs nplt.figure(figsize(10, 5))plt.subplot(1, 2, 1)plt.plot(n_values, time_values, markero)plt.title(Time vs Number of Disks)plt.xlabel(Number of Disks (n))plt.ylabel(Time (s))# Plotting recursive calls vs nplt.subplot(1, 2, 2)plt.plot(n_values, calls_values, markero, colorr)plt.title(Recursive Calls vs Number of Disks)plt.xlabel(Number of Disks (n))plt.ylabel(Recursive Calls)plt.tight_layout()plt.show()# 实验
results []
for i in range(2, 8):time_taken, calls_made run_experiment(i)results.append((i, time_taken, calls_made))# 绘制图表
plot_results(results)