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>