2

I am working on a generic algorithm, I have a population and a function to calculate distance. The problem comes in when I call calcDistance(population[i]) in a for loop, it turns into an infinity loop. But when using dev tool to manually input each "i", there are no problem. Please Help

// points is an array of point store in another JS file
var totalPoints;

var bestdistance = Infinity;
var bestorder;

var totalPopulation = 5;
var population = [];
var fitness = []


function btnClick() {
    var canvas = document.getElementById("myCanvas");
    canvas.removeEventListener('click', trackClicker);
    totalPoints = points.length;

    var order = [];
    for (i=0; i<totalPoints; i++) {
        order[i] = i;
    }

    for (i=0; i<totalPopulation; i++) {
        population[i] = shuffle(order.slice());
    }
    console.log(population);

    // problem
    for (i=0; i<totalPopulation; i++) {
        console.log(calcDistance(population[i]));
    }
    console.log(fitness);
}

function shuffle(arr) {
    // not important
}

function calcDistance(arr) {
    var d = 0;
    for (i=0; i<totalPoints-1; i++) {
        var p1 = points[arr[i]];
        var p2 = points[arr[i+1]];

        d += Math.sqrt(Math.pow(p2.x-p1.x,2) + Math.pow(p2.y-p1.y,2));
    }

    if (d < bestdistance) {
        bestdistance = d;
        bestorder = arr.slice();
    }
    return d;
}

WARNING: The snippet below is an infinite loop and will crash your browser. It has also been slightly modified from the above so it runs in the snippet.

var totalPoints;

var bestdistance = Infinity;
var bestorder;

var totalPopulation = 5;
var population = [];
var fitness = []

let points = [{
    x: 1,
    y: 1
  },
  {
    x: 2,
    y: 2
  },
  {
    x: 3,
    y: 3
  }
]

function btnClick() {
  totalPoints = points.length;

  var order = [];
  for (i = 0; i < totalPoints; i++) {
    order[i] = i;
  }

  // problem
  for (i = 0; i < totalPopulation; i++) {
    console.log(calcDistance(population[i]));
  }
  console.log(fitness);
}

function calcDistance(arr) {
  var d = 0;
  for (i = 0; i < totalPoints - 1; i++) {
    var p1 = points[i];
    var p2 = points[i + 1];

    d += Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  }

  if (d < bestdistance) {
    bestdistance = d;
  }
  return d;
}

//temp
btnClick();

4
  • How many points are there? Sometimes there is considerable lag when trying to write say thousands of messages to the console at once. Also, are you certain that it never ends because console.log(fitness); won't log anything at this point as it is empty. Commented May 17, 2017 at 22:34
  • I am testing it with 3 point and 5 population Commented May 17, 2017 at 22:37
  • yes because I have tested with multiple input suppose if i did console.log(population[i]) it works find and print empty fitness but there is a problem with calcDistance(population[i]) Commented May 17, 2017 at 22:38
  • 4
    How about making the loop iterator i local by declaring it with for (var i = ...? Commented May 17, 2017 at 22:40

1 Answer 1

3

By glancing at your code I suspect the global loop iterator variable i is the culprit.

Change it to a local variable by declaring it e.g. with var:

 for (var i = 0; ...; i++) { ... }

The 'inner' loop in calcDistance resets i to 0 and increments to totalPoints-1. So after each run of that function, i equals totalPoints-1:

function calcDistance(arr) {
    var d = 0;
    for (i=0; i<totalPoints-1; i++) { 
       ...
    }
    ...
}

But the 'outer' loop in whose body calcDistance is called also relies on the same iterator variable i. It terminates when i >= totalPopulation which might never be the case as i is always reset to totalPoints-1.

Here is the fixed code with local i:

var totalPoints;

var bestdistance = Infinity;
var bestorder;

var totalPopulation = 5;
var population = [];
var fitness = []

let points = [{
    x: 1,
    y: 1
  },
  {
    x: 2,
    y: 2
  },
  {
    x: 3,
    y: 3
  }
]

function btnClick() {
  totalPoints = points.length;

  var order = [];
  for (var i = 0; i < totalPoints; i++) {
    order[i] = i;
  }

  // problem
  for (var i = 0; i < totalPopulation; i++) {
    console.log(calcDistance(population[i]));
  }
  console.log(fitness);
}

function calcDistance(arr) {
  var d = 0;
  for (var i = 0; i < totalPoints - 1; i++) {
    var p1 = points[i];
    var p2 = points[i + 1];

    d += Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  }

  if (d < bestdistance) {
    bestdistance = d;
  }
  return d;
}

//temp
btnClick();

Sign up to request clarification or add additional context in comments.

7 Comments

I just added a snippet to the question if you wanted to trial this?
fixed so it's broken as intended now.
@Zze Included your snippet. Now OP should understand the importance of 'keeping things local' :)
I actually assumed that this was the cause of the error initially, execpt he explicitly stated: "... in dev tools manually (stepped through) each 'i', there are no problem". This is definitely the correct answer though.
Thank you very much for all the advice
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.