0

Just for fun I am creating a basic JavaScript implementation of the traveling salesman problem.

It will basically create an array of cities with random coordinates, plot them on a canvas, then show the path between them. I then have a button which launches a 'findBetterRoute' function, which simply swaps two cities over, and if the path is better it will pass the new route back, if it's worse it will pass the original back. However, I am finding that the last part isn't working - it will sometimes plot a route that is longer than the original and I can't for the life of me fathom what I am doing wrong.

Here is my code:

<html>

<head>
  <title>The Traveling Salesman Problem</title>
</head>

<body onload="drawInitial()">
  <canvas id="TSP" width="1000" height="1000" style="border:1px solid #000000;"></canvas>
  <script>
    var canvas = document.getElementById("TSP");
    var ctx = canvas.getContext("2d");
    var numberofCities = 5;
    let city = [numberofCities];

    for (i = 0; i < numberofCities; i++) {
      city[i] = [Math.random() * 1000 + 1, Math.random() * 1000 + 1];
    }

    function drawInitial() {
      drawPath(city);
    }

    function drawPath(cityarray) {
      ctx.moveTo(cityarray[0][0], cityarray[0][1]);
      for (i = 0; i < cityarray.length; i++) {
        if (i != 0) {
          ctx.lineTo(cityarray[i][0], cityarray[i][1]);
          ctx.stroke();
        }
        ctx.beginPath();
        ctx.arc(cityarray[i][0], cityarray[i][1], 2, 0, Math.PI * 2, true);
        ctx.fill();
      }
      ctx.lineTo(city[0][0], city[0][1]);
      ctx.stroke();
      ctx.font = "30px Arial";
      ctx.fillText("Path Length: " + parseInt(calculatePathLength(city)), 10, 50);
    }

    function calculatePathLength(cityarray) {
      let pathLength = 0;
      for (i = 0; i < (cityarray.length - 1); i++) {
        pathLength = pathLength + Math.sqrt((Math.pow((cityarray[i][0] - cityarray[i + 1][0]), 2)) + (Math.pow((cityarray[i][1] - cityarray[i + 1][1]), 2)))
      }
      pathLength = pathLength + Math.sqrt((Math.pow((cityarray[numberofCities - 1][0] - cityarray[0][0]), 2)) + (Math.pow((cityarray[numberofCities - 1][1] - cityarray[0][1]), 2)))
      return pathLength;
    }

    function swap2RandomCities(cityarray) {
      var city1 = 1;
      var city2 = 2;
      do {
        city1 = parseInt(Math.random() * numberofCities);
        city2 = parseInt(Math.random() * numberofCities);
      } while (city1 == city2);
      var swapArray = [];
      swapArray[0] = [cityarray[city1][0], cityarray[city1][1]];
      swapArray[1] = [cityarray[city2][0], cityarray[city2][1]];
      cityarray[city1] = swapArray[1];
      cityarray[city2] = swapArray[0];
      return cityarray;
    }

    function findBetterRoute(cityArray) {
      var currentlength = calculatePathLength(cityArray);
      var newRoute = swap2RandomCities(cityArray);
      if (calculatePathLength(newRoute) < currentlength) {
        return newRoute;
      } else {
        return cityArray;
      }
    }

    function ButtonClick() {
      city = findBetterRoute(city);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      drawPath(city);
    }
  </script>
  <button onclick="ButtonClick()">Find Better Route</button>
</body>

</html>
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • Have you checked what `calculatePathLength(newRoute) < currentlength` produces? And by extension what `calculatePathLength(newRoute)` and `currentlength` are? – VLAZ May 13 '21 at 10:07
  • Useful: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173) and [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – VLAZ May 13 '21 at 10:08
  • I've worked out it's not a case of the if statement not working - for some reason the original array changes as soon as the swap2RandomCities() function is called. – Simon Hayes May 13 '21 at 15:36

0 Answers0