javascript TSP

遗传算法解决旅行商问题学习笔记

在选修课人工智能快结课时,老师叫我们用遗传算法去解决旅行商问题,说实现的语言不限,既然不限语言,这次我就尝试这用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即可

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值