Reputation: 186
I recently wrote a program that does Ant Colony Optimization on a graph.
The following code has a bug in it I can't understand.
Map<Node, Edge> nodesLinkedToCurrentNode = a.getCurrentNode().getLinkedNodes();
TreeMap<Double, Node> probabilitiesForNodes = new TreeMap<>();
double totalProb = 0d;
for (Node n : graph.values()) {
if (!a.getVisited().contains(n)) {
//For each node that has not yet been visited
//calculate it's weighted probabily
double weightedProbability
= (Math.pow(nodesLinkedToCurrentNode.get(n).getPheremoneLevel(), RPI))
* (Math.pow((double) 1 / nodesLinkedToCurrentNode.get(n).getDistance(), RHI));
totalProb += weightedProbability;
//Map the node to its probability
probabilitiesForNodes.put(weightedProbability, n);
}
}
double testTotalProb = 0d;
for (Double d : probabilitiesForNodes.keySet()) {
testTotalProb += d;
}
if (testTotalProb != totalProb) { <----------How can this happen??
System.out.println("Why?");
totalProb = testTotalProb;
}
That if statement executes all the time and I don't understand why.
I'm just incrementing a value, but for some reason, it's not being incremented properly.
I made the project open source, if you want to check it out
The java file with the code in it
I replicated the bug with the following code:
TreeMap<Double, String> probabilitiesForNodes = new TreeMap<>();
double totalProb = 0d;
for (int i = 1; i < 10; i++) {
//For each node that has not yet been visited
//calulate it's weighted probabily
double weightedProbability
= (Math.pow(0.7 + 1 / i, 2))
* (Math.pow((double) 1 / 30, i));
totalProb += weightedProbability;
String sudoNode = "node" + i;
//Map the node to its probability
probabilitiesForNodes.put(weightedProbability, sudoNode);
}
double testTotalProb = 0d;
for (Double d : probabilitiesForNodes.keySet()) {
testTotalProb += d;
}
if (testTotalProb != totalProb) {
System.out.println("Why?");
totalProb = testTotalProb;
}
Upvotes: 3
Views: 95
Reputation: 200168
You are working with double
numbers so you should expect this. Specifically you obtain totalProb
and testTotalProb
by iteratively adding the same double
numbers, but in different order. Since adding doubles is not an exactly associative operation, enough discrepancy occurs to make your equality test fail.
Another thing that can happen is a collision on the same Double
key. There is nothing stopping two nodes from having exactly the same weighted probability. So for starters you can just check the sizes of the two collections.
Upvotes: 4