I’m trying to do Ant Colony Optimization in Julia, and I’ve run into a problem that when using rand I always get the lowest value possible.
Most part of the function isn’t important I just didn’t want it to leave out.
Using Random
function selectNextNode(ant, possiblePaths, graph, pheoromoneExponent, desirabilityExponent)
sum = 0
probabilities = Float64[]
for possibleNode in possiblePaths
sum += (((graph.pheromoneMatrix[ant.currentLocation, possibleNode]) ^ pheromoneExponent) * (1/ graph.adjMatrix[ant.currentLocation, possibleNode]) ^ desirabilityExponent)
push!(probabilities, ((graph.pheromoneMatrix[ant.currentLocation, possibleNode]) ^ pheromoneExponent ) * (1/graph.adjMatrix[ant.currentLocation, possibleNode]) ^ desirabilityExponent)
end
rnd = rand(0:sum)
println("Random number between 0 and $sum is $rnd")
for i in 1:length(possiblePaths)
if(rnd < probabilities[i])
return possiblePaths[i]
end
rnd -= probabilities[i]
end
end
The range object 0:sum creates an iterator that returns 0, 0+1, 0+2, etc., until it reaches a value greater than sum. Since sum is always less than 1 it will only return 0.
The trouble is that rand(S) returns a random element of the set S, and the set S you’re providing has only the element 0.0. For example, 0:0.3 is the set of Float64’s between 0.0 and 0.3 in default steps of 1.0. So 0:0.3 has only one element, 0.0.
Instead, use rnd = sum*rand(). The rand() will be a random Float64 between 0.0 and 1.0, which is then scaled to 0.0 to sum by the multiplication.
help?> rand(S)
rand([rng=GLOBAL_RNG], [S], [dims...])
Pick a random element or array of random elements from the set of values specified by S; S can be
• an indexable collection (for example 1:9 or ('x', "y", :z)),
• an AbstractDict or AbstractSet object,
• a string (considered as a collection of characters), or
• a type: the set of values to pick from is then equivalent to typemin(S):typemax(S) for integers (this is not applicable to BigInt), to
[0, 1) for floating point numbers and to [0, 1)+i[0, 1) for complex floating point numbers;
S defaults to Float64. When only one argument is passed besides the optional rng and is a Tuple, it is interpreted as a collection of values (S)
and not as dims.
Incidentally, I would advise against using common base function names as variable identifiers to prevent these types of problems:
julia> sum = 0
0
julia> sum([1, 2, 3])
ERROR: MethodError: objects of type Int64 are not callable
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
[1] top-level scope
@ REPL[2]:1