zoukankan      html  css  js  c++  java
  • 利用p5js库来实现基于随机搜索的旅行商问题

    p5js是一个javascript库,用来在浏览器上画图。具体关于p5js的使用方法请下载以前我在群文件里上传的p5js.pptx来复习一下,在sketch.js 里编写代码,在index.html里查看结果。sketch.js里必须包含两个函数,setup函数是初始化函数,只在网页打开时执行一次,draw函数是一个死循环,只要网页不关闭draw函数里的内容被反复执行。具体例子如下:

    1 function setup() {
    2 
    3 }
    4 
    5 function draw() {
    6 
    7 }

     在本次实验中所有的代码都写在setup里面,draw里面空着即可。随机搜索算法是基于暴力法的简化算法,假设有四座城市ABCD,要想找到遍历这四座城市的最短路径,暴力法的思路是列举所有可能的访问路线,例如ABCD,ACBD,ADCB等共有4的阶乘个访问路线,暴力法把所有可能的路线都计算一次距离,再从中找出距离最短的那条。

    为了节约时间,随机搜索算法并不像暴力法那样计算所有可能的访问路线,而是随机生成n个访问路线(n由你自己指定),从这随机生成的n条路线中挑出最短的那条作为结果返回,本次实验用的正是随机搜索算法来解决旅行商问题。首先,创建一个宽400像素,高300像素的画布,画布的背景设置为黑色。

     1 function setup(){
     2 
     3 createCanvas(400, 300);
     4 background(0);
     5 
     6 }
     7 
     8 function draw(){
     9 
    10 }

     在sketch.js的开头要先定义四个变量,cities变量是一个空列表,存放各个城市的横纵座标,totalCities是城市的个数,recordDistance存放目前最短随机路径的总长度,bestEver存放当前找到的最短随机路径。

    var cities = [];
    var totalCities = 4;
    
    var recordDistance;
    var bestEver;

     下面这段代码是随机生成一个包含totalCities个城市的随机路径数组cities,random(width)和random(height)表示在画布上随机产生一个坐标点,cities数组的每个元素都代表一个城市的坐标点,cities的下标代表城市访问的先后顺序。

    1 for (var i = 0; i < totalCities; i++) {
    2     var v = createVector(random(width), random(height));
    3     cities[i] = v;
    4   }

     calcDistance这个函数接受一个代表访问路径(包含各个城市座标点)的数组,然后计算出这个访问路径的总长度。

    function calcDistance(points) {
      var sum = 0;
      for (var i = 0; i < points.length - 1; i++) {
        var d = dist(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
        sum += d;
      }
      return sum;
    }

     下面这段代码就利用了上面的calcDistance函数来计算出当前随机路径数组cities的总长度,将这个长度存在recordDistance整型变量(目前最短路径长度)里面,同时利用slice()函数把cities数组拷贝到存放当前最佳路径的bestEver数组里面。

    var d = calcDistance(cities);
    recordDistance = d;
    bestEver = cities.slice();

     在随机搜索算法里如何生成随机路径是一个问题,我们采用的是在当前路径里随机挑选两个城市(PS:即随机生成两个cities数组的下标),然后交换这两个城市在cities里面的位置即可。比如原来的路径是ABCD, 随机生成两个下标0,1,交换后得到的新路径是BACD。生成随机两个城市下标的代码如下:

    var i = floor(random(cities.length));
    var j = floor(random(cities.length));

    给出两个下标位置,交换它们在路径数组的对应元素的swap函数如下,a是路径数组,i,j是待交换元素的下标:

    function swap(a, i, j) {
      var temp = a[i];
      a[i] = a[j];
      a[j] = temp;
    }

     利用calcDistance来计算cities路径数组中存放的当前路径长度,如果当前路径长度d小于目前找到的最短路径长度recordDistance,则把当前路径长度赋值给recordDistance变量, 把当前路径cities拷贝赋值给存放当前最短路径的bestEver数组。

    var d = calcDistance(cities);
      if (d < recordDistance) {
        recordDistance = d;
        bestEver = cities.slice();
      }

     随机搜索可以指定搜索路径的条数,在下面的代码里我们指定了搜索条数为20条,从这20条里面找到最短的那条路径。

     for (let k = 0;k < 20; k++){
    
      var i = floor(random(cities.length));
      var j = floor(random(cities.length));
      swap(cities, i, j);
    
      var d = calcDistance(cities);
      if (d < recordDistance) {
        recordDistance = d;
        bestEver = cities.slice();
      }
    
    }

     最后我们利用p5js的绘图功能将最短路径在浏览器里面画出来(具体的绘图方法见QQ群文件里的p5js.pptx文件)

     stroke(255, 0, 255);
      strokeWeight(4);
      noFill();
      beginShape();
      for (var i = 0; i < cities.length; i++) {
        vertex(bestEver[i].x, bestEver[i].y);
      }
      endShape();
    var cities = [];
    var totalCities = 4;
    var recordDistance;
    var bestEver;
    function setup() {
       
      createCanvas(400, 300);
      background(0);
      for (var i = 0; i < totalCities; i++) {
        var v = createVector(random(width), random(height));
        cities[i] = v;
      }
      
      var d = calcDistance(cities);
      recordDistance = d;
      bestEver = cities.slice();
      
      for (let k = 0;k < 20; k++){
    
      var i = floor(random(cities.length));
      var j = floor(random(cities.length));
      swap(cities, i, j);
    
      var d = calcDistance(cities);
      if (d < recordDistance) {
        recordDistance = d;
        bestEver = cities.slice();
      }
    
    }
      stroke(255, 0, 255);
      strokeWeight(4);
      noFill();
      beginShape();
      for (var i = 0; i < cities.length; i++) {
        vertex(bestEver[i].x, bestEver[i].y);
      }
      endShape();
    }
    
    function draw() {
     
    }
    
    function swap(a, i, j) {
      var temp = a[i];
      a[i] = a[j];
      a[j] = temp;
    }
    function calcDistance(points) {
      var sum = 0;
      for (var i = 0; i < points.length - 1; i++) {
        var d = dist(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
        sum += d;
      }
      return sum;
    }

    下面是效果截屏:

     

    民大赵老师
  • 相关阅读:
    iOS开发UI篇—使用storyboard创建导航控制器以及控制器的生命周期
    IOS开发UI篇—导航控制器属性和基本使用
    基于XMPP协议的aSmack源码分析
    XMPP-for-Android
    wecontact
    MyPhone
    Video conference server OpenMCU-ru
    WebRTC_Wrapper
    Sip-MCU
    WebRTC学习笔记
  • 原文地址:https://www.cnblogs.com/gezhaoatdlnu/p/12713715.html
Copyright © 2011-2022 走看看