启发式算法(环境并没有聪明与笨的区别)
资讯
2024-01-29
370
1. 启发式算法,环境并没有聪明与笨的区别?
达尔文所谓的自然选择,终究是优胜劣汰的含义。但是,优良的性状的选择,取决于环境。换句话说就是,自然选择,其实重在优胜劣汰的淘汰环节,而环境来决定谁该被淘汰。
但是我们来想想,为什么人类基本无需自然选择也能进化的如此好呢?其实有两个原因。
1. 自然选择还是存在,人类从古至今发生了多少次战争,而那些环节,也是自然选择的一部分,只不过被我们所忽视了而已。
2. 如今人类无需自然选择也能进化,其终究是因为人类的自我意识和高度的智慧已经能通过思考与检验来决定发展方向。换句话说就是,现在人类的生物本身并不一定在进化,但是人类把智慧的产物-科技作为重要的产物,让其不断更新,积累,发展。而每个新生的人类,都需要学习前人的知识和经验,这才有了我们现在所觉得的,人类无需自然淘汰也仍然在进化。
另外关于发展的快慢问题,其实现在,根据自然选择,优胜劣汰,已经在计算机上有了一种启发式算法-遗传算法。但是与之类似的,还有蚁群算法、禁忌搜索算法、神经网络算法,没有哪个比遗传算法差。所以,并不一定只有自然选择,才是最好的选择。
2. 为什么人工智能用Python?
Python带有大量内置库。 许多库都用于人工智能和机器学习。 其中一些库是Tensorflow(这是高级神经网络库),scikit-learn(用于数据挖掘,数据分析和机器学习),pylearn2(比scikit-learn更灵活)等。
Python对于OpenCV具有简单的实现。 Python广受所有人欢迎的原因在于其功能强大且易于实现。
对于其他语言,学生和研究人员需要先学习该语言,然后才能使用该语言进行ML或AI。python并非如此。 即使是具有非常基础知识的程序员也可以轻松地处理python。 除此之外,与C,C ++或Java相比,某人花在编写和调试python代码上的时间要少得多。 这正是AI和ML的学生想要的。 他们不想花时间调试语法错误的代码,而是想花更多时间在与AI和ML相关的算法和启发式算法上。
不仅可以在线获取库,还可以轻松获取接口的处理方法(包括其教程)。 人们构建自己的库并将其上传到GitHub或其他地方,以供他人使用。
3. 车载网络基本原理?
车载网络(Vehicle-to-Everything,V2X)是指将各种智能设备、传感器、控制器等连接到汽车上,并通过无线网络互相通信,实现车辆与周围环境、车辆与车辆、车辆与设备之间的实时、智能、可靠的数据交换。下面是车载网络的基本原理:
传感器技术:车载传感器可以实时感知车辆周围的环境信息,如车速、位置、方向、加速度、温度、湿度等。这些传感器数据可以通过无线网络传输到车载网络中,进行处理分析。
无线通信技术:车载网络通常采用2.4GHz和5GHz两种频段进行通信,以实现远距离的数据传输。其中,2.4GHz频段通常用于车辆与车辆之间的通信,5GHz频段通常用于车辆与设备之间的通信。
数据融合技术:车载网络中的各种传感器和设备会产生大量的数据,如何有效地处理和分析这些数据是非常重要的。通过数据融合技术,可以将多个传感器和设备的数据进行融合处理,提高数据的准确性和可靠性。
安全技术:车载网络的安全性非常重要,因为任何数据泄露或篡改都可能对车辆和驾驶员造成严重的后果。车载网络通常采用加密技术、身份验证技术等手段来保证数据的安全性。
优化技术:车载网络需要实现各种智能功能,如导航、娱乐、车辆控制等,因此需要对车辆的运行效率进行优化,提高车辆的使用效率和舒适性。优化技术包括启发式算法、全局最优策略等。
以上就是车载网络的基本原理,车载网络的应用范围非常广泛,包括智能交通、智能驾驶、智能制造等领域。随着技术的不断发展和应用场景的不断扩大,车载网络将会在未来发挥越来越重要的作用。
4. java遗传算法排课如何性能优化?
问题描述
如图所示,在X轴上有5个点,分别为x1, x2, x3, x4, x5。这5个点的实际间距已知为L,但实际中由于测量误差的存在,每个点x1, x2, x3, x4, x5会有一系列如图中黑色圈内所示的测量点。那么如何在实际测量点中取值可以使得相邻位置的间距最接近L,问题可以描述为如下数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
解决思路
通过查询资料发现,我要解决的问题和TSP问题(旅行商问题)很像。TSP问题中是预先给定数量已知位置固定的点,然后求得是旅行商人从任意一个点出发遍历所有的点(中间每个点只能经过一次)最后回到这个点时路径最短,具体可以参考维基百科旅行商问题。
我要解决问题的特点是点之间的间距固定,但每个点的位置上有n个测量点,我的最终目的是选择最优的测量点使得路径距离和4L之间的偏差最小,换言之也是使得路径的最短(只不过是与4L做差值之后最短),这就与TSP问题不谋而合了。虽然每个位置上有个n个测量点,但每次只从每个位置上取出一个测量点,这样就形成一条线路,然后计算路径间距,最后通过比较即可选择出最优的路径,这就和TSP问题求解的思路是一样的了。
但是如果遍历每个位置上的点来求所有的路线,这样当测量点数n比较大时计算量就相对很大了,所以就想到了用启发式搜索算法的方式来搜索最优解,最后使用遗传算法来解决这个问题。
遗传算法
遗传算法,顾名思义,可以联想到自然界种群繁衍、基因遗传的过程,实际上它也是借鉴进化生物学中的一些现象发展起来的(交叉,变异,选择以及遗传等等)维基百科遗传算法,是一种通过模拟生物进化过程搜索最优解的启发式搜索算法。
遗传算法的本质就是模仿自然界优胜劣汰、适者生存的过程。它往往从实际问题的解集出发通过一定的编码方式形成问题域中“基因”、“染色体”和“个体”的概念,进而确定初始种群(由一定数量的个体组成),然后根据问题域中的适应度函数(Fitness Function),通过一代代的选择(Selection)、交叉(Crossover)和变异(Mutation)等方式模拟这个种群的进化过程,最后逐渐进化出较好的个体(也就是解集中近似的最优解)。将遗传算法应用到实际问题的流程大致如下:
1. 对实际问题的解集进行编码,使其可以对应生物遗传过程中“基因”、“染色体”和“个体”的概念。比如本题中,解集就是每个位置上的随机选一个测量点连起来的路径,这样我可以对测量点进行编号,使得每个测量点就代表了一个“基因”,然后一条路劲就代表了一条“染色体”,进而形成一个个体(每个个体只有一条“染色体”)。具体如下图所示:
2. 确定问题域中的适应度函数(Fitness Function)。这个一般实际问题都会已经给出,比如本题中的适应度函数就是前面所述的数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
3. 确定初始种群(population)。这个可以用random的方式随机生成,如果为了比较快的收敛到较优解,也可以一开始就生成一些表现优良的“个体”。
4. 然后根据适应度函数进行选择(Selection)、交叉(Crossover)和变异(Mutation),通过一定代数的遗传即可选出近似的最优解。
以上就是我查阅资料后对遗传算法的一个基本的理解,下面我将具体介绍每个步骤中使用的方法(包括编码的方式,个体的选择,交叉的方式等)并展示相应的代码。(如果还想对遗传算法有更深入的了解,可以看这里知乎如何通俗易懂的理解遗传算法)
解题过程
1. 编码方式
对问题域的解集进行编码,获得相应的“基因”、“染色体”等,常用的编码方式有两种:
1) 实数编码:使用实数进行编码(比如0,1,2等等)。
2) 二进制编码:这个编码方式就是使用二进制0、1来表示问题域中解集。
对于本题中,每个位置上有n个测量点,显然用二进制编码方式不太合适,而如果用实数编码的方式则可以很好的表示每个位置上的测量点。因此,我使用实数(0 ~ n-1)对每个位置上的测量点进行编号,这样我只要新建一个二维数组即可表示每个位置上的所有测量点。同时,使用random的方式随机生成测量点,即可将测量点的坐标值保存在数组中对应的位置。其代码如下:
//pointNum是位置数(本题中是5),realPointNum是每个位置上实际的测量点数
class GARandom {
private int pointNum,realPointNum;
public GARandom(int pointNum,int realPointNum) {
this.pointNum = pointNum;
this.realPointNum = realPointNum;
}
public double[][] randomInitPopulation(){
double[][] x = new double[pointNum][realPointNum];
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x[0].length; j++) {
if(i == j){
x[i][j] = i * 10;//将一组收敛值放入其中,用以后面测试算法的性能
}else{
x[i][j] = i * 10 + (i + 1)*Math.random();
}
}
}
return x;
}
}
2. 确定适应度函数
本题的适应度函数就是要使得相邻位置的间距最接近L,即前面所描述的数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
题目中有5个位置,也就是要选出使每两个相邻的位置最接近固定间距L的测量点。所以可以像TSP问题一样事先计算出相邻位置测量点之间的距离并将其保存在数组中,然后在种群进化的过程中,根据种群的“染色体”(也就是路径)计算出总的偏差,以此来判断其适应度的好坏(这里是距离越小适应度越好)。计算相邻位置测量点距离的代码如下:
//求得每两个位置,所有点之间的距离
distance = new double[pointNum - 1][realPointNum][realPointNum];
for (int i = 0; i < pointNum - 1; i++) {
for (int j = 0; j < realPointNum; j++) {
for (int k = 0; k < realPointNum; k++) {
distance[i][j][k] = Math.abs(x[i + 1][k] - x[i][j] - L);
}
}
}
评价个体适应度的代码如下:
//根据先验条件求得个体适应度,并根据适应度求得单个个体的概率以及个体的累积概率
//以便选择阶段使用
private void evaluate(int[][] chromosome) {
int k = 0;
double len = 0;
double sumFitness = 0;
double[] tempFitness = new double[scale];
//根据距离数组求得每条路径的适应度,也就是和固定距离L的偏差的和
while (k < chromosome.length) {
for (int i = 0; i < chromosome[k].length - 1; i++) {
len += distance[i][chromosome[k][i]][chromosome[k][i + 1]];
}
fitness[k] = len;
len = 0;
k++;
}
//求总的适应度
for (int i = 0; i < scale; i++) {
tempFitness[i] = 10.0 / (fitness[i] + 1);//计算适应度,这里距离越小适应度越大,因此采用倒数的方式表示
sumFitness += tempFitness[i];
}
//根据适应度,转化成相应的单个个体概率和个体的累积概率,用于后面的轮盘赌选择策略
double tempP = 0;
for (int i = 0; i < scale; i++) {
ps[i] = tempFitness[i] / sumFitness;//单个个体概率
tempP += ps[i];
pc[i] = tempP;//个体累积概率
}
}
3. 确定初始种群
这里我采用了随机生成的方式,但是为了使初始种群中能覆盖所有经过实数编号的测量点(0 ~ n-1),所以我让前n个体的“染色体”如下所示:
这种方式使得初始种群的前n个个体的“染色体”排列是全0,全1直到全n-1,这样尽可能将所有的测量点都覆盖进去,避免随机生成的时候漏掉一些测量点。其代码如下:
//生成父代种群的“染色体”,也就是随机选取每个位置上的点组成一个网络
//scale是种群规模,pointNum是位置数(x1-x5)
oldPopulation = new int[scale][pointNum];
for (int i = 0; i < scale; i++) {
for (int j = 0; j < pointNum; j++) {
if (i < realPointNum){
oldPopulation[i][j] = i;
}else{
oldPopulation[i][j] = rand.nextInt(realPointNum);
}
}
}
4. 选择(Selection)
确定初始种群后,就根据适应度函数计算出初代最优的个体,并将其直接遗传给子代。这里这么做的原因是,保存表现最优良的个体,让其余个体进行交叉或变异(当然还有其他的方式,这个由你自己决定),这种方式也叫做精英选择。然后通过轮盘赌选择方式,随机选择个体放到子代中去。这个轮盘赌选择方式是根据每个个体适应度占总适应度的概率进行选择的,想详细了解的可以看这篇博文轮盘赌策略。选择阶段的代码如下:
//精英选择(选择上一代中fitness最好的个体,然后直接保存到下一代中)
private void selectMaxFitness() {
int maxId = 0;
double tempFitness = fitness[0];
//
for (int i = 1; i < scale; i++) {
if (tempFitness > fitness[i]) {
tempFitness = fitness[i];
maxId = i;
}
}
if (bestLength > tempFitness) {
bestLength = tempFitness;
bestGen = t;
System.arraycopy(oldPopulation[maxId], 0, bestChoice, 0, pointNum);
}
copyPopulation(0, maxId);
}
//轮盘赌选择策略
private void select() {
int j, selectId;
double r;
selectMaxFitness();//精英选择,保留上一代fitness最好的个体
for (int i = 1; i < scale; i++) {
r = rand.nextDouble();
for (j = 0; j < scale; j++) {
if (r <= pc[j]) {
break;
}
}
if (j < scale) {
selectId = j;
copyPopulation(i, selectId);
}
}
}
5. 交叉(Crossover)
选择完之后,就要对这些个体进行“染色体”交叉,用以产生子代。交叉的方式有很多,我这里选择了最简单的单点交叉,即通过random.nextDouble()随机生成一个数,当它小于交叉概率时,即表明可以进行“染色体”的交叉,然后随机生成一个索引值,然后将相邻的“染色体”位于索引值后的部分进行交叉。其代码如下:
//单点交叉
private void crossover() {
for (int k = 1; k < scale/2; k += 2) {
double pCrossoverTemp = rand.nextDouble();
//小于交叉概率时进行“染色体”交叉,将交叉索引(包括交叉索引处的元素)后的元素进行互换
if (pCrossoverTemp <= pCrossover) {
int tempCrossover;
int indexCrossover = 1 + rand.nextInt(pointNum - 1);//排除索引值为0的情况,整体交换没有意义
for (int i = indexCrossover; i < pointNum; i++) {
tempCrossover = newPopulation[k][i];
newPopulation[k][i] = newPopulation[k + 1][i];
newPopulation[k + 1][i] = tempCrossover;
}
}
}
}
当然这是最最简单的交叉算子,如果想使用表现更好的算子,可以看这篇博文遗传算法中几种交叉算子。
6. 变异(Mutation)
变异这个部分,我没有查阅很多资料,直接用了最简单的单点变异。其代码如下:
private void mutation() {
for (int i = 1; i < scale; i++) {
double pMutationTemp = rand.nextDouble();
if (pMutationTemp < pMutation) {
//随机选择变异位置
int mutationIndex = rand.nextInt(pointNum);
//将变异位置的值保存下来
int temp = newPopulation[i][mutationIndex];
//获得变异值
int mutationTemp = rand.nextInt(realPointNum);
//确保变异值和之前的值不一样
while (mutationTemp == temp) {
mutationTemp = rand.nextInt(realPointNum);
}
newPopulation[i][mutationIndex] = mutationTemp;
}
}
}
7. 重复操作
从确定初代种群开始到经过第一次的选择、交叉和变异这就产生了第一个子代。然后重复4、5、6这三个步骤,整个遗传算法就有如自然界进化一般,在适应度函数的制约下,自动朝着最优解的方向“进化”而去,当然遗传算法一般得到只是最优解的近似解。
代码测试
测试输入
初始种群的大小设定为30,即初始种群包含30个个体;每个位置实际测量点的数量设定为10个;“进化”的代数设定为2000,即算法要历经2000代的“遗传进化”;相邻位置的固定间距设定为10;交叉概率定为0.8;变异概率定为0.1。
测试结果
由上图可以看出经过2000次的选择、交叉和变异,在固定间距是10的情况下,算法在第355代找到了最佳的路径01234,也就是我事先输入到数组的0,10,20,30,40这组数据。
5. 雷丁算法是什么?
你好,雷丁算法(Reduction Algorithm)是一种用于规划和调度问题的启发式算法。它能够有效地解决很多复杂的实际问题,如工作车间调度、生产流程规划等。
雷丁算法的主要思想是将一个大问题分解成若干个小问题,然后通过一系列的优化步骤,逐步将小问题合并成大问题的最优解。这个算法的优点在于其简单性和灵活性,可以适用于各种不同类型的问题,同时也可以根据问题的特点进行改进和优化。
具体来说,雷丁算法的步骤包括:
1. 将大问题分解成若干个小问题;
2. 对每个小问题进行求解,并得到一个局部最优解;
3. 将所有局部最优解合并成一个全局最优解;
4. 如果全局最优解不满足要求,则返回步骤2,否则算法结束。
总的来说,雷丁算法是一种非常实用的算法,它可以帮助人们在处理复杂问题时更加高效、准确地进行规划和调度,从而提高生产效率和经济效益。
6. mean算法一定能收敛吗?
不一定。k-means算法的收敛性取决于初始质心的选择和数据的分布情况。如果初始质心的选择不合适,可能会导致算法无法收敛或者收敛到局部最优解而非全局最优解。此外,如果数据分布不均匀或者存在噪声,也可能会影响算法的收敛性。
为了提高k-means算法的收敛性,可以采用以下方法:
选择合适的初始质心,例如使用k-means++算法来选择初始质心;
对数据进行预处理,例如去除噪声或者进行归一化处理;
增加迭代次数或者设置收敛阈值,以确保算法能够收敛到最优解。
需要注意的是,k-means算法是一种启发式算法,其结果可能会受到初始质心的影响。因此,在使用k-means算法时,需要进行多次试验并比较结果,以确保得到的聚类结果是合理的。
7. sg循环是什么?
SG循环是一种用于解决组合优化问题的启发式算法。它通过不断调整解的邻域来寻找更优解。在每一次迭代中,SG循环会选择一个解的邻域,并根据一定的策略选择一个新的解。如果新解比当前解更优,则接受新解并更新当前解。这个过程会重复执行,直到达到停止条件。SG循环的优点是简单易实现,适用于大规模问题。它被广泛应用于诸如旅行商问题、车辆路径问题等组合优化问题的求解中。
本站涵盖的内容、图片、视频等数据系网络收集,部分未能与原作者取得联系。若涉及版权问题,请联系我们删除!联系邮箱:ynstorm@foxmail.com 谢谢支持!
1. 启发式算法,环境并没有聪明与笨的区别?
达尔文所谓的自然选择,终究是优胜劣汰的含义。但是,优良的性状的选择,取决于环境。换句话说就是,自然选择,其实重在优胜劣汰的淘汰环节,而环境来决定谁该被淘汰。
但是我们来想想,为什么人类基本无需自然选择也能进化的如此好呢?其实有两个原因。
1. 自然选择还是存在,人类从古至今发生了多少次战争,而那些环节,也是自然选择的一部分,只不过被我们所忽视了而已。
2. 如今人类无需自然选择也能进化,其终究是因为人类的自我意识和高度的智慧已经能通过思考与检验来决定发展方向。换句话说就是,现在人类的生物本身并不一定在进化,但是人类把智慧的产物-科技作为重要的产物,让其不断更新,积累,发展。而每个新生的人类,都需要学习前人的知识和经验,这才有了我们现在所觉得的,人类无需自然淘汰也仍然在进化。
另外关于发展的快慢问题,其实现在,根据自然选择,优胜劣汰,已经在计算机上有了一种启发式算法-遗传算法。但是与之类似的,还有蚁群算法、禁忌搜索算法、神经网络算法,没有哪个比遗传算法差。所以,并不一定只有自然选择,才是最好的选择。
2. 为什么人工智能用Python?
Python带有大量内置库。 许多库都用于人工智能和机器学习。 其中一些库是Tensorflow(这是高级神经网络库),scikit-learn(用于数据挖掘,数据分析和机器学习),pylearn2(比scikit-learn更灵活)等。
Python对于OpenCV具有简单的实现。 Python广受所有人欢迎的原因在于其功能强大且易于实现。
对于其他语言,学生和研究人员需要先学习该语言,然后才能使用该语言进行ML或AI。python并非如此。 即使是具有非常基础知识的程序员也可以轻松地处理python。 除此之外,与C,C ++或Java相比,某人花在编写和调试python代码上的时间要少得多。 这正是AI和ML的学生想要的。 他们不想花时间调试语法错误的代码,而是想花更多时间在与AI和ML相关的算法和启发式算法上。
不仅可以在线获取库,还可以轻松获取接口的处理方法(包括其教程)。 人们构建自己的库并将其上传到GitHub或其他地方,以供他人使用。
3. 车载网络基本原理?
车载网络(Vehicle-to-Everything,V2X)是指将各种智能设备、传感器、控制器等连接到汽车上,并通过无线网络互相通信,实现车辆与周围环境、车辆与车辆、车辆与设备之间的实时、智能、可靠的数据交换。下面是车载网络的基本原理:
传感器技术:车载传感器可以实时感知车辆周围的环境信息,如车速、位置、方向、加速度、温度、湿度等。这些传感器数据可以通过无线网络传输到车载网络中,进行处理分析。
无线通信技术:车载网络通常采用2.4GHz和5GHz两种频段进行通信,以实现远距离的数据传输。其中,2.4GHz频段通常用于车辆与车辆之间的通信,5GHz频段通常用于车辆与设备之间的通信。
数据融合技术:车载网络中的各种传感器和设备会产生大量的数据,如何有效地处理和分析这些数据是非常重要的。通过数据融合技术,可以将多个传感器和设备的数据进行融合处理,提高数据的准确性和可靠性。
安全技术:车载网络的安全性非常重要,因为任何数据泄露或篡改都可能对车辆和驾驶员造成严重的后果。车载网络通常采用加密技术、身份验证技术等手段来保证数据的安全性。
优化技术:车载网络需要实现各种智能功能,如导航、娱乐、车辆控制等,因此需要对车辆的运行效率进行优化,提高车辆的使用效率和舒适性。优化技术包括启发式算法、全局最优策略等。
以上就是车载网络的基本原理,车载网络的应用范围非常广泛,包括智能交通、智能驾驶、智能制造等领域。随着技术的不断发展和应用场景的不断扩大,车载网络将会在未来发挥越来越重要的作用。
4. java遗传算法排课如何性能优化?
问题描述
如图所示,在X轴上有5个点,分别为x1, x2, x3, x4, x5。这5个点的实际间距已知为L,但实际中由于测量误差的存在,每个点x1, x2, x3, x4, x5会有一系列如图中黑色圈内所示的测量点。那么如何在实际测量点中取值可以使得相邻位置的间距最接近L,问题可以描述为如下数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
解决思路
通过查询资料发现,我要解决的问题和TSP问题(旅行商问题)很像。TSP问题中是预先给定数量已知位置固定的点,然后求得是旅行商人从任意一个点出发遍历所有的点(中间每个点只能经过一次)最后回到这个点时路径最短,具体可以参考维基百科旅行商问题。
我要解决问题的特点是点之间的间距固定,但每个点的位置上有n个测量点,我的最终目的是选择最优的测量点使得路径距离和4L之间的偏差最小,换言之也是使得路径的最短(只不过是与4L做差值之后最短),这就与TSP问题不谋而合了。虽然每个位置上有个n个测量点,但每次只从每个位置上取出一个测量点,这样就形成一条线路,然后计算路径间距,最后通过比较即可选择出最优的路径,这就和TSP问题求解的思路是一样的了。
但是如果遍历每个位置上的点来求所有的路线,这样当测量点数n比较大时计算量就相对很大了,所以就想到了用启发式搜索算法的方式来搜索最优解,最后使用遗传算法来解决这个问题。
遗传算法
遗传算法,顾名思义,可以联想到自然界种群繁衍、基因遗传的过程,实际上它也是借鉴进化生物学中的一些现象发展起来的(交叉,变异,选择以及遗传等等)维基百科遗传算法,是一种通过模拟生物进化过程搜索最优解的启发式搜索算法。
遗传算法的本质就是模仿自然界优胜劣汰、适者生存的过程。它往往从实际问题的解集出发通过一定的编码方式形成问题域中“基因”、“染色体”和“个体”的概念,进而确定初始种群(由一定数量的个体组成),然后根据问题域中的适应度函数(Fitness Function),通过一代代的选择(Selection)、交叉(Crossover)和变异(Mutation)等方式模拟这个种群的进化过程,最后逐渐进化出较好的个体(也就是解集中近似的最优解)。将遗传算法应用到实际问题的流程大致如下:
1. 对实际问题的解集进行编码,使其可以对应生物遗传过程中“基因”、“染色体”和“个体”的概念。比如本题中,解集就是每个位置上的随机选一个测量点连起来的路径,这样我可以对测量点进行编号,使得每个测量点就代表了一个“基因”,然后一条路劲就代表了一条“染色体”,进而形成一个个体(每个个体只有一条“染色体”)。具体如下图所示:
2. 确定问题域中的适应度函数(Fitness Function)。这个一般实际问题都会已经给出,比如本题中的适应度函数就是前面所述的数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
3. 确定初始种群(population)。这个可以用random的方式随机生成,如果为了比较快的收敛到较优解,也可以一开始就生成一些表现优良的“个体”。
4. 然后根据适应度函数进行选择(Selection)、交叉(Crossover)和变异(Mutation),通过一定代数的遗传即可选出近似的最优解。
以上就是我查阅资料后对遗传算法的一个基本的理解,下面我将具体介绍每个步骤中使用的方法(包括编码的方式,个体的选择,交叉的方式等)并展示相应的代码。(如果还想对遗传算法有更深入的了解,可以看这里知乎如何通俗易懂的理解遗传算法)
解题过程
1. 编码方式
对问题域的解集进行编码,获得相应的“基因”、“染色体”等,常用的编码方式有两种:
1) 实数编码:使用实数进行编码(比如0,1,2等等)。
2) 二进制编码:这个编码方式就是使用二进制0、1来表示问题域中解集。
对于本题中,每个位置上有n个测量点,显然用二进制编码方式不太合适,而如果用实数编码的方式则可以很好的表示每个位置上的测量点。因此,我使用实数(0 ~ n-1)对每个位置上的测量点进行编号,这样我只要新建一个二维数组即可表示每个位置上的所有测量点。同时,使用random的方式随机生成测量点,即可将测量点的坐标值保存在数组中对应的位置。其代码如下:
//pointNum是位置数(本题中是5),realPointNum是每个位置上实际的测量点数
class GARandom {
private int pointNum,realPointNum;
public GARandom(int pointNum,int realPointNum) {
this.pointNum = pointNum;
this.realPointNum = realPointNum;
}
public double[][] randomInitPopulation(){
double[][] x = new double[pointNum][realPointNum];
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x[0].length; j++) {
if(i == j){
x[i][j] = i * 10;//将一组收敛值放入其中,用以后面测试算法的性能
}else{
x[i][j] = i * 10 + (i + 1)*Math.random();
}
}
}
return x;
}
}
2. 确定适应度函数
本题的适应度函数就是要使得相邻位置的间距最接近L,即前面所描述的数学公式:
F=min∑|xi+1−xi−L|,1≤i≤4
F=min∑|xi+1−xi−L|,1≤i≤4
题目中有5个位置,也就是要选出使每两个相邻的位置最接近固定间距L的测量点。所以可以像TSP问题一样事先计算出相邻位置测量点之间的距离并将其保存在数组中,然后在种群进化的过程中,根据种群的“染色体”(也就是路径)计算出总的偏差,以此来判断其适应度的好坏(这里是距离越小适应度越好)。计算相邻位置测量点距离的代码如下:
//求得每两个位置,所有点之间的距离
distance = new double[pointNum - 1][realPointNum][realPointNum];
for (int i = 0; i < pointNum - 1; i++) {
for (int j = 0; j < realPointNum; j++) {
for (int k = 0; k < realPointNum; k++) {
distance[i][j][k] = Math.abs(x[i + 1][k] - x[i][j] - L);
}
}
}
评价个体适应度的代码如下:
//根据先验条件求得个体适应度,并根据适应度求得单个个体的概率以及个体的累积概率
//以便选择阶段使用
private void evaluate(int[][] chromosome) {
int k = 0;
double len = 0;
double sumFitness = 0;
double[] tempFitness = new double[scale];
//根据距离数组求得每条路径的适应度,也就是和固定距离L的偏差的和
while (k < chromosome.length) {
for (int i = 0; i < chromosome[k].length - 1; i++) {
len += distance[i][chromosome[k][i]][chromosome[k][i + 1]];
}
fitness[k] = len;
len = 0;
k++;
}
//求总的适应度
for (int i = 0; i < scale; i++) {
tempFitness[i] = 10.0 / (fitness[i] + 1);//计算适应度,这里距离越小适应度越大,因此采用倒数的方式表示
sumFitness += tempFitness[i];
}
//根据适应度,转化成相应的单个个体概率和个体的累积概率,用于后面的轮盘赌选择策略
double tempP = 0;
for (int i = 0; i < scale; i++) {
ps[i] = tempFitness[i] / sumFitness;//单个个体概率
tempP += ps[i];
pc[i] = tempP;//个体累积概率
}
}
3. 确定初始种群
这里我采用了随机生成的方式,但是为了使初始种群中能覆盖所有经过实数编号的测量点(0 ~ n-1),所以我让前n个体的“染色体”如下所示:
这种方式使得初始种群的前n个个体的“染色体”排列是全0,全1直到全n-1,这样尽可能将所有的测量点都覆盖进去,避免随机生成的时候漏掉一些测量点。其代码如下:
//生成父代种群的“染色体”,也就是随机选取每个位置上的点组成一个网络
//scale是种群规模,pointNum是位置数(x1-x5)
oldPopulation = new int[scale][pointNum];
for (int i = 0; i < scale; i++) {
for (int j = 0; j < pointNum; j++) {
if (i < realPointNum){
oldPopulation[i][j] = i;
}else{
oldPopulation[i][j] = rand.nextInt(realPointNum);
}
}
}
4. 选择(Selection)
确定初始种群后,就根据适应度函数计算出初代最优的个体,并将其直接遗传给子代。这里这么做的原因是,保存表现最优良的个体,让其余个体进行交叉或变异(当然还有其他的方式,这个由你自己决定),这种方式也叫做精英选择。然后通过轮盘赌选择方式,随机选择个体放到子代中去。这个轮盘赌选择方式是根据每个个体适应度占总适应度的概率进行选择的,想详细了解的可以看这篇博文轮盘赌策略。选择阶段的代码如下:
//精英选择(选择上一代中fitness最好的个体,然后直接保存到下一代中)
private void selectMaxFitness() {
int maxId = 0;
double tempFitness = fitness[0];
//
for (int i = 1; i < scale; i++) {
if (tempFitness > fitness[i]) {
tempFitness = fitness[i];
maxId = i;
}
}
if (bestLength > tempFitness) {
bestLength = tempFitness;
bestGen = t;
System.arraycopy(oldPopulation[maxId], 0, bestChoice, 0, pointNum);
}
copyPopulation(0, maxId);
}
//轮盘赌选择策略
private void select() {
int j, selectId;
double r;
selectMaxFitness();//精英选择,保留上一代fitness最好的个体
for (int i = 1; i < scale; i++) {
r = rand.nextDouble();
for (j = 0; j < scale; j++) {
if (r <= pc[j]) {
break;
}
}
if (j < scale) {
selectId = j;
copyPopulation(i, selectId);
}
}
}
5. 交叉(Crossover)
选择完之后,就要对这些个体进行“染色体”交叉,用以产生子代。交叉的方式有很多,我这里选择了最简单的单点交叉,即通过random.nextDouble()随机生成一个数,当它小于交叉概率时,即表明可以进行“染色体”的交叉,然后随机生成一个索引值,然后将相邻的“染色体”位于索引值后的部分进行交叉。其代码如下:
//单点交叉
private void crossover() {
for (int k = 1; k < scale/2; k += 2) {
double pCrossoverTemp = rand.nextDouble();
//小于交叉概率时进行“染色体”交叉,将交叉索引(包括交叉索引处的元素)后的元素进行互换
if (pCrossoverTemp <= pCrossover) {
int tempCrossover;
int indexCrossover = 1 + rand.nextInt(pointNum - 1);//排除索引值为0的情况,整体交换没有意义
for (int i = indexCrossover; i < pointNum; i++) {
tempCrossover = newPopulation[k][i];
newPopulation[k][i] = newPopulation[k + 1][i];
newPopulation[k + 1][i] = tempCrossover;
}
}
}
}
当然这是最最简单的交叉算子,如果想使用表现更好的算子,可以看这篇博文遗传算法中几种交叉算子。
6. 变异(Mutation)
变异这个部分,我没有查阅很多资料,直接用了最简单的单点变异。其代码如下:
private void mutation() {
for (int i = 1; i < scale; i++) {
double pMutationTemp = rand.nextDouble();
if (pMutationTemp < pMutation) {
//随机选择变异位置
int mutationIndex = rand.nextInt(pointNum);
//将变异位置的值保存下来
int temp = newPopulation[i][mutationIndex];
//获得变异值
int mutationTemp = rand.nextInt(realPointNum);
//确保变异值和之前的值不一样
while (mutationTemp == temp) {
mutationTemp = rand.nextInt(realPointNum);
}
newPopulation[i][mutationIndex] = mutationTemp;
}
}
}
7. 重复操作
从确定初代种群开始到经过第一次的选择、交叉和变异这就产生了第一个子代。然后重复4、5、6这三个步骤,整个遗传算法就有如自然界进化一般,在适应度函数的制约下,自动朝着最优解的方向“进化”而去,当然遗传算法一般得到只是最优解的近似解。
代码测试
测试输入
初始种群的大小设定为30,即初始种群包含30个个体;每个位置实际测量点的数量设定为10个;“进化”的代数设定为2000,即算法要历经2000代的“遗传进化”;相邻位置的固定间距设定为10;交叉概率定为0.8;变异概率定为0.1。
测试结果
由上图可以看出经过2000次的选择、交叉和变异,在固定间距是10的情况下,算法在第355代找到了最佳的路径01234,也就是我事先输入到数组的0,10,20,30,40这组数据。
5. 雷丁算法是什么?
你好,雷丁算法(Reduction Algorithm)是一种用于规划和调度问题的启发式算法。它能够有效地解决很多复杂的实际问题,如工作车间调度、生产流程规划等。
雷丁算法的主要思想是将一个大问题分解成若干个小问题,然后通过一系列的优化步骤,逐步将小问题合并成大问题的最优解。这个算法的优点在于其简单性和灵活性,可以适用于各种不同类型的问题,同时也可以根据问题的特点进行改进和优化。
具体来说,雷丁算法的步骤包括:
1. 将大问题分解成若干个小问题;
2. 对每个小问题进行求解,并得到一个局部最优解;
3. 将所有局部最优解合并成一个全局最优解;
4. 如果全局最优解不满足要求,则返回步骤2,否则算法结束。
总的来说,雷丁算法是一种非常实用的算法,它可以帮助人们在处理复杂问题时更加高效、准确地进行规划和调度,从而提高生产效率和经济效益。
6. mean算法一定能收敛吗?
不一定。k-means算法的收敛性取决于初始质心的选择和数据的分布情况。如果初始质心的选择不合适,可能会导致算法无法收敛或者收敛到局部最优解而非全局最优解。此外,如果数据分布不均匀或者存在噪声,也可能会影响算法的收敛性。
为了提高k-means算法的收敛性,可以采用以下方法:
选择合适的初始质心,例如使用k-means++算法来选择初始质心;
对数据进行预处理,例如去除噪声或者进行归一化处理;
增加迭代次数或者设置收敛阈值,以确保算法能够收敛到最优解。
需要注意的是,k-means算法是一种启发式算法,其结果可能会受到初始质心的影响。因此,在使用k-means算法时,需要进行多次试验并比较结果,以确保得到的聚类结果是合理的。
7. sg循环是什么?
SG循环是一种用于解决组合优化问题的启发式算法。它通过不断调整解的邻域来寻找更优解。在每一次迭代中,SG循环会选择一个解的邻域,并根据一定的策略选择一个新的解。如果新解比当前解更优,则接受新解并更新当前解。这个过程会重复执行,直到达到停止条件。SG循环的优点是简单易实现,适用于大规模问题。它被广泛应用于诸如旅行商问题、车辆路径问题等组合优化问题的求解中。
本站涵盖的内容、图片、视频等数据系网络收集,部分未能与原作者取得联系。若涉及版权问题,请联系我们删除!联系邮箱:ynstorm@foxmail.com 谢谢支持!