use the full-matrix pheromones model
This commit is contained in:
parent
b5a56c9cb5
commit
3f556fe0e7
1 changed files with 61 additions and 24 deletions
|
|
@ -8,6 +8,7 @@ import path
|
||||||
|
|
||||||
|
|
||||||
def LOG( *args ):
|
def LOG( *args ):
|
||||||
|
"""Print something on stderr and flush"""
|
||||||
for msg in args:
|
for msg in args:
|
||||||
sys.stderr.write( str(msg) )
|
sys.stderr.write( str(msg) )
|
||||||
sys.stderr.write(" ")
|
sys.stderr.write(" ")
|
||||||
|
|
@ -15,6 +16,7 @@ def LOG( *args ):
|
||||||
|
|
||||||
|
|
||||||
def LOGN( *args ):
|
def LOGN( *args ):
|
||||||
|
"""Print something on stdeer, with a trailing new line, and flush"""
|
||||||
LOG( *args )
|
LOG( *args )
|
||||||
LOG("\n")
|
LOG("\n")
|
||||||
|
|
||||||
|
|
@ -40,18 +42,9 @@ def cost( permutation, cost_func, cities ):
|
||||||
return dist
|
return dist
|
||||||
|
|
||||||
|
|
||||||
def initialize_pheromones( cities, init_value ):
|
def look( cities, last, exclude, pheromones, w_heuristic, w_history, cost_func = graph_distance ):
|
||||||
rows = {}
|
|
||||||
for i in cities:
|
|
||||||
cols = {}
|
|
||||||
for j in cities:
|
|
||||||
cols[j] = init_value
|
|
||||||
rows[i] = cols
|
|
||||||
return rows
|
|
||||||
|
|
||||||
|
|
||||||
def choose( cities, last, exclude, pheromones, w_heuristic, w_history, cost_func = graph_distance ):
|
|
||||||
choices = []
|
choices = []
|
||||||
|
# gather informations about possible moves
|
||||||
for current in cities:
|
for current in cities:
|
||||||
if current in exclude:
|
if current in exclude:
|
||||||
# This is faster than "if current not in exclude"
|
# This is faster than "if current not in exclude"
|
||||||
|
|
@ -65,7 +58,7 @@ def choose( cities, last, exclude, pheromones, w_heuristic, w_history, cost_func
|
||||||
return choices
|
return choices
|
||||||
|
|
||||||
|
|
||||||
def proba_select( choices ):
|
def proba_choose( choices ):
|
||||||
s = float(sum( c["proba"] for c in choices ))
|
s = float(sum( c["proba"] for c in choices ))
|
||||||
if s == 0.0:
|
if s == 0.0:
|
||||||
return random.choice(choices)["city"]
|
return random.choice(choices)["city"]
|
||||||
|
|
@ -79,24 +72,24 @@ def proba_select( choices ):
|
||||||
return c[-1]["city"]
|
return c[-1]["city"]
|
||||||
|
|
||||||
|
|
||||||
def greedy_select( choices ):
|
def greedy_choose( choices ):
|
||||||
c = max( choices, key = lambda c : c["proba"] )
|
c = max( choices, key = lambda c : c["proba"] )
|
||||||
return c["city"]
|
return c["city"]
|
||||||
|
|
||||||
|
|
||||||
def walk( cities, pheromone, w_heuristic, w_history, c_greedy, cost_func = graph_distance, ):
|
def walk( cities, pheromones, w_heuristic, w_history, c_greedy, cost_func = graph_distance ):
|
||||||
assert( len(cities) > 0 )
|
assert( len(cities) > 0 )
|
||||||
# permutations are indices
|
# permutations are indices
|
||||||
# randomly draw the first city index
|
# randomly draw the first city index
|
||||||
permutation = [ random.choice( cities.keys() ) ]
|
permutation = [ random.choice( cities.keys() ) ]
|
||||||
# then choose the next ones to build the permutation
|
# then choose the next ones to build the permutation
|
||||||
while len(permutation) < len(cities):
|
while len(permutation) < len(cities):
|
||||||
choices = choose( cities, permutation[-1], permutation, pheromone, w_heuristic, w_history, cost_func )
|
choices = look( cities, permutation[-1], permutation, pheromones, w_heuristic, w_history, cost_func )
|
||||||
do_greedy = ( random.random() <= c_greedy )
|
do_greedy = ( random.random() <= c_greedy )
|
||||||
if do_greedy:
|
if do_greedy:
|
||||||
next_city = greedy_select( choices )
|
next_city = greedy_choose( choices )
|
||||||
else:
|
else:
|
||||||
next_city = proba_select( choices )
|
next_city = proba_choose( choices )
|
||||||
permutation.append( next_city )
|
permutation.append( next_city )
|
||||||
|
|
||||||
# assert no duplicates
|
# assert no duplicates
|
||||||
|
|
@ -104,27 +97,71 @@ def walk( cities, pheromone, w_heuristic, w_history, c_greedy, cost_func = graph
|
||||||
return permutation
|
return permutation
|
||||||
|
|
||||||
|
|
||||||
def update_global( pheromones, candidate, decay ):
|
def initialize_pheromones_whole( cities, init_value ):
|
||||||
|
rows = {}
|
||||||
|
for i in cities:
|
||||||
|
cols = {}
|
||||||
|
for j in cities:
|
||||||
|
cols[j] = init_value
|
||||||
|
rows[i] = cols
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def update_global_whole( pheromones, candidate, graph, decay ):
|
||||||
for i,j in tour(candidate["permutation"]):
|
for i,j in tour(candidate["permutation"]):
|
||||||
value = ((1.0 - decay) * pheromones[i][j]) + (decay * (1.0/candidate["cost"]))
|
value = ((1.0 - decay) * pheromones[i][j]) + (decay * (1.0/candidate["cost"]))
|
||||||
pheromones[i][j] = value
|
pheromones[i][j] = value
|
||||||
pheromones[j][i] = value
|
pheromones[j][i] = value
|
||||||
|
|
||||||
|
|
||||||
def update_local( pheromones, candidate, w_pheromone, init_pheromone ):
|
def update_local_whole( pheromones, candidate, graph, w_pheromone, init_pheromone ):
|
||||||
for i,j in tour(candidate["permutation"]):
|
for i,j in tour(candidate["permutation"]):
|
||||||
value = ((1.0 - w_pheromone) * pheromones[i][j]) + (w_pheromone * init_pheromone)
|
value = ((1.0 - w_pheromone) * pheromones[i][j]) + (w_pheromone * init_pheromone)
|
||||||
pheromones[i][j] = value
|
pheromones[i][j] = value
|
||||||
pheromones[j][i] = value
|
pheromones[j][i] = value
|
||||||
|
|
||||||
|
|
||||||
|
def initialize_pheromones_neighbors( cities, init_value ):
|
||||||
|
rows = {}
|
||||||
|
for i in cities:
|
||||||
|
cols = {}
|
||||||
|
for j in cities:
|
||||||
|
# set an init value for neighbors only
|
||||||
|
if j in cities[i]:
|
||||||
|
cols[j] = init_value
|
||||||
|
else: # else, there should be no edge
|
||||||
|
cols[j] = 0
|
||||||
|
rows[i] = cols
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def update_global_neighbors( pheromones, candidate, graph, decay ):
|
||||||
|
for ci,cj in tour(candidate["permutation"]):
|
||||||
|
# subpath between ci and cj
|
||||||
|
p,c = path.astar( graph, ci, cj )
|
||||||
|
# deposit pheromones on each edges of the subpath
|
||||||
|
for i,j in zip(p,p[1:]):
|
||||||
|
value = ((1.0 - decay) * pheromones[i][j]) + (decay * (1.0/candidate["cost"]))
|
||||||
|
pheromones[i][j] = value
|
||||||
|
pheromones[j][i] = value
|
||||||
|
|
||||||
|
|
||||||
|
def update_local_neighbors( pheromones, candidate, graph, w_pheromone, init_pheromone ):
|
||||||
|
for ci,cj in tour(candidate["permutation"]):
|
||||||
|
p,c = path.astar( graph, ci, cj )
|
||||||
|
for i,j in zip(p,p[1:]):
|
||||||
|
value = ((1.0 - w_pheromone) * pheromones[i][j]) + (w_pheromone * init_pheromone)
|
||||||
|
pheromones[i][j] = value
|
||||||
|
pheromones[j][i] = value
|
||||||
|
|
||||||
|
|
||||||
def search( cities, max_iterations, nb_ants, decay, w_heuristic, w_pheromone, w_history, c_greedy, cost_func = graph_distance ):
|
def search( cities, max_iterations, nb_ants, decay, w_heuristic, w_pheromone, w_history, c_greedy, cost_func = graph_distance ):
|
||||||
# like random.shuffle(cities) but on a copy
|
# like random.shuffle(cities) but on a copy
|
||||||
best = { "permutation" : sorted( cities, key=lambda i: random.random()) }
|
best = { "permutation" : sorted( cities, key=lambda i: random.random()) }
|
||||||
best["cost"] = cost( best["permutation"], cost_func, cities )
|
best["cost"] = cost( best["permutation"], cost_func, cities )
|
||||||
|
|
||||||
init_pheromone = 1.0 / float(len(cities)) * best["cost"]
|
init_pheromone = 1.0 / float(len(cities)) * best["cost"]
|
||||||
pheromone = initialize_pheromones( cities, init_pheromone )
|
pheromones = initialize_pheromones_whole( cities, init_pheromone )
|
||||||
|
|
||||||
for i in range(max_iterations):
|
for i in range(max_iterations):
|
||||||
LOG( i )
|
LOG( i )
|
||||||
|
|
@ -132,15 +169,15 @@ def search( cities, max_iterations, nb_ants, decay, w_heuristic, w_pheromone, w_
|
||||||
for j in range(nb_ants):
|
for j in range(nb_ants):
|
||||||
LOG( "." )
|
LOG( "." )
|
||||||
candidate = {}
|
candidate = {}
|
||||||
candidate["permutation"] = walk( cities, pheromone, w_heuristic, w_history, c_greedy, cost_func )
|
candidate["permutation"] = walk( cities, pheromones, w_heuristic, w_history, c_greedy, cost_func )
|
||||||
candidate["cost"] = cost( candidate["permutation"], cost_func, cities )
|
candidate["cost"] = cost( candidate["permutation"], cost_func, cities )
|
||||||
if candidate["cost"] < best["cost"]:
|
if candidate["cost"] < best["cost"]:
|
||||||
best = candidate
|
best = candidate
|
||||||
update_local( pheromone, candidate, w_pheromone, init_pheromone )
|
update_local_whole( pheromones, candidate, cities, w_pheromone, init_pheromone )
|
||||||
update_global( pheromone, best, decay )
|
update_global_whole( pheromones, best, cities, decay )
|
||||||
LOGN( best["cost"] )
|
LOGN( best["cost"] )
|
||||||
|
|
||||||
return best,pheromone
|
return best,pheromones
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue