遗传算法解决旅行商问题学习笔记
在选修课人工智能快结课时,老师叫我们用遗传算法去解决旅行商问题,说实现的语言不限,既然不限语言,这次我就尝试这用js来实现遗传算法,最终结果还有一点问题,也再次请教如果大佬看见在评论区给予指导。
这是没有进化之前:
n代以后:
这里我发现虽然比一开始要好很多,但是明显感觉还有比这更好的解法,估计是我i的代码逻辑有问题,一下我将对我的学习经验进行记录。
首先我先随机生成50个点,代表50个城市:
class random_city{ //初始化n个城市对象
constructor(n){
this.city_number=n;
this.city_ps=[]; //城市坐标
this.city_id=[]; //城市代号
this.can=$('#can');
this.cheight=this.can.height();
this.cwidth=this.can.width();
for(let i=0;i<this.city_number;i++){
this.city_ps.push({
id:i,
x:random(10,this.cwidth-10),
y:random(10,this.cheight-10)
})
this.city_id.push(i)
}
}
}
生成初始父代
function shuffle(arr) { //打乱数组生成父代
var length = arr.length,
randomIndex,
temp;
while (length) {
randomIndex = Math.floor(Math.random() * (length--));
temp = arr[randomIndex];
arr[randomIndex] = arr[length];
arr[length] = temp
}
return arr;
}
function makeOrigin(city_id){ //生成50个个体组成初代
let originFather=[];
for(let i=0;i<50;i++){
originFather[i]=[].concat(shuffle(city_id))
originFather[i].socer=0;
}
// console.log(originFather)
//console.log(originFather)
return originFather
}
一代进化
function evolution(originFather,city_ps){ //一代个体的进化
let a = new Array(50)
let i = a.length;
let crosszi=random(0,50);
while(i--){a[i] = i}
let selected=shuffle(a)
for(let i=0;i<50;i+=2){
if(crosszi>crossmay)continue;
let son=cross(originFather[selected[i]],originFather[selected[i+1]],city_ps) //交叉生成后代
let no=[originFather[selected[i]],originFather[selected[i+1]],son.son1,son.son2]
no.sort(function(a,b){
return b.socer-a.socer;
})
if(random(0,50)<selectmay){
originFather[selected[i]]=no[0];
originFather[selected[i+1]]=no[1];
}
}
}
交叉
function cross(father,mather,city_ps){ //交叉生成后代
let randomindex=random(0,50)
let son1=[];
let son2=[];
let indextepm;
circlebg=father[randomindex]
index=randomindex;
for(;;){
son1[index]=father[index];
son2[index]=mather[index];
indextepm=mather[index];
if(mather[index]===circlebg){
break;
}
index=father.indexOf(indextepm);
}
for(let i=0;;i++){
if(i===50)break
if(son1[i]==undefined){
son1[i]=mather[i];
}
if(son2[i]==undefined){
son2[i]=father[i];
}
}
//------------------------------------------------进行替换
son1.socer=signsoce(son1,city_ps);
son2.socer=signsoce(son2,city_ps);
return son={son1,son2}
}
变异
function mutated(origin,city_ps){
let best=getbestps(origin)
for(let i=0;i<50;i++){
if(random(0,49)<mutatedmay&&i!==best)
{
for(let j=0;j<3;j++)
{
let first=random(0,50)
let end=random(0,50);
let temp;
temp=origin[i][first];
origin[i][first]=origin[i][end];
origin[i][end]=temp;
origin[i].socer=signsoce(origin[i],city_ps)
}
}
}
总结
在本次学习中,知道了很多只有实践才知道的东西,比如一开始我以为只需要交叉就行,在我的想想中,在进过多次交叉之后,应该能组成任何想要的个体,但如果在算法中将变异率调至0时我发现最后会得到一个局部最好,没办法继续向后发展。在我加如变异之后,在运算到一定代数之后,进化的非常慢。我就想通过把遍一律调大进行加快进化,但当把变异调大到一定几率之后,就会拖慢进化速率,甚至一直无法进化,在一个分数阶段停留。在查到一定资料后得知,可以动态的改变变异率来提高运算效率。
github链接: clone之后直接打开index.html即可