Use dictionaries instead of index list in ant_colony
Everything use cities tuples as keys.
This commit is contained in:
parent
28e5ce5e8d
commit
26599368c4
1 changed files with 65 additions and 47 deletions
108
ant_colony.py
108
ant_colony.py
|
|
@ -4,6 +4,7 @@ import sys
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
import path
|
||||||
|
|
||||||
|
|
||||||
def log( *args ):
|
def log( *args ):
|
||||||
|
|
@ -23,40 +24,39 @@ def tour(lst):
|
||||||
yield (a,b)
|
yield (a,b)
|
||||||
|
|
||||||
|
|
||||||
def euclidian_distance( ci, cj ):
|
def euclidian_distance( ci, cj, graph = None):
|
||||||
return math.sqrt( float(ci[0] - cj[0])**2 + float(ci[1] - cj[1])**2 )
|
return math.sqrt( float(ci[0] - cj[0])**2 + float(ci[1] - cj[1])**2 )
|
||||||
|
|
||||||
|
def graph_distance( ci, cj, graph ):
|
||||||
|
p,c = path.astar( graph, ci, cj )
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
def cost( permutation, cost_func, cities ):
|
def cost( permutation, cost_func, cities ):
|
||||||
dist = 0
|
dist = 0
|
||||||
for i,j in tour(permutation):
|
for ci,cj in tour(permutation):
|
||||||
dist += cost_func(cities[i],cities[j])
|
dist += cost_func( ci, cj, cities )
|
||||||
return dist
|
return dist
|
||||||
|
|
||||||
|
|
||||||
def random_permutation( cities ):
|
def initialize_pheromone_matrix( cities, init_value ):
|
||||||
# like random.shuffle(cities) but on a copy
|
rows = {}
|
||||||
return sorted( cities, key=lambda i: random.random())
|
for i in cities:
|
||||||
|
cols = {}
|
||||||
|
for j in cities:
|
||||||
def initialize_pheromone_matrix( nb_cities, init_value ):
|
cols[j] = init_value
|
||||||
rows = []
|
rows[i] = cols
|
||||||
for i in range(nb_cities):
|
|
||||||
cols = []
|
|
||||||
for j in range(nb_cities):
|
|
||||||
cols.append( init_value )
|
|
||||||
rows.append(cols)
|
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
def choose( cities, last, exclude, pheromones, w_heuristic, w_history ):
|
def choose( cities, last, exclude, pheromones, w_heuristic, w_history, cost_func = graph_distance ):
|
||||||
choices = []
|
choices = []
|
||||||
for i,city in enumerate(cities):
|
for city in cities:
|
||||||
if i in exclude:
|
if city in exclude:
|
||||||
continue
|
continue
|
||||||
c = {"city" : i}
|
c = {"city" : city}
|
||||||
c["history"] = pheromones[last][i] ** w_history
|
c["history"] = pheromones[last][city] ** w_history
|
||||||
c["distance"] = euclidian_distance( cities[last], city )
|
c["distance"] = cost_func( last, city, cities )
|
||||||
c["heuristic"] = (1.0 / c["distance"]) ** w_heuristic
|
c["heuristic"] = (1.0 / c["distance"]) ** w_heuristic
|
||||||
c["proba"] = c["history"] * c["heuristic"]
|
c["proba"] = c["history"] * c["heuristic"]
|
||||||
choices.append(c)
|
choices.append(c)
|
||||||
|
|
@ -64,7 +64,7 @@ def choose( cities, last, exclude, pheromones, w_heuristic, w_history ):
|
||||||
|
|
||||||
|
|
||||||
def proba_select( choices ):
|
def proba_select( choices ):
|
||||||
s = 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"]
|
||||||
|
|
||||||
|
|
@ -82,14 +82,14 @@ def greedy_select( choices ):
|
||||||
return c["city"]
|
return c["city"]
|
||||||
|
|
||||||
|
|
||||||
def walk( cities, pheromone, w_heuristic, c_greedy ):
|
def walk( cities, pheromone, 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.randint(0,len(cities)-1) ]
|
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 = 1.0 )
|
choices = choose( cities, permutation[-1], permutation, pheromone, 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_select( choices )
|
||||||
|
|
@ -116,19 +116,25 @@ def update_local( pheromones, candidate, w_pheromone, init_pheromone ):
|
||||||
pheromones[j][i] = value
|
pheromones[j][i] = value
|
||||||
|
|
||||||
|
|
||||||
def search( max_iterations, nb_ants, decay, w_heuristic, w_pheromone, c_greedy, cities):
|
def random_permutation( cities ):
|
||||||
best = { "permutation" : random_permutation(range(len(cities))) }
|
# like random.shuffle(cities) but on a copy
|
||||||
best["cost"] = cost( best["permutation"], euclidian_distance, cities )
|
return sorted( cities, key=lambda i: random.random())
|
||||||
|
|
||||||
|
|
||||||
|
def search( max_iterations, nb_ants, decay, w_heuristic, w_pheromone, w_history, c_greedy, cities, cost_func = graph_distance ):
|
||||||
|
best = { "permutation" : random_permutation(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_pheromone_matrix( len(cities), init_pheromone )
|
pheromone = initialize_pheromone_matrix( cities, init_pheromone )
|
||||||
|
|
||||||
for i in range(max_iterations):
|
for i in range(max_iterations):
|
||||||
log( i )
|
log( i )
|
||||||
solutions = []
|
solutions = []
|
||||||
for j in range(nb_ants):
|
for j in range(nb_ants):
|
||||||
log( "." )
|
log( "." )
|
||||||
candidate = {}
|
candidate = {}
|
||||||
candidate["permutation"] = walk( cities, pheromone, w_heuristic, c_greedy )
|
candidate["permutation"] = walk( cities, pheromone, w_heuristic, w_history, c_greedy, cost_func )
|
||||||
candidate["cost"] = cost( candidate["permutation"], euclidian_distance, 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( pheromone, candidate, w_pheromone, init_pheromone )
|
||||||
|
|
@ -142,21 +148,33 @@ if __name__ == "__main__":
|
||||||
max_it = 40
|
max_it = 40
|
||||||
num_ants = 10
|
num_ants = 10
|
||||||
decay = 0.1
|
decay = 0.1
|
||||||
c_heur = 2.5
|
w_heur = 2.5
|
||||||
c_local_phero = 0.1
|
w_local_phero = 0.1
|
||||||
c_greed = 0.9
|
c_greed = 0.9
|
||||||
|
w_history = 1.0
|
||||||
|
|
||||||
print "Berlin euclidian TSP"
|
print """Graph TSP:
|
||||||
berlin52 = [[565,575],[25,185],[345,750],[945,685],[845,655],
|
-1 0 2 : x
|
||||||
[880,660],[25,230],[525,1000],[580,1175],[650,1130],[1605,620],
|
1 o o-----o
|
||||||
[1220,580],[1465,200],[1530,5],[845,680],[725,370],[145,665],
|
| | |
|
||||||
[415,635],[510,875],[560,365],[300,465],[520,585],[480,415],
|
0 o--o-----o
|
||||||
[835,625],[975,580],[1215,245],[1320,315],[1250,400],[660,180],
|
| |
|
||||||
[410,250],[420,555],[575,665],[1150,1160],[700,580],[685,595],
|
| |
|
||||||
[685,610],[770,610],[795,645],[720,635],[760,650],[475,960],
|
-2 o--o-----o
|
||||||
[95,260],[875,920],[700,500],[555,815],[830,485],[1170,65],
|
:
|
||||||
[830,610],[605,625],[595,360],[1340,725],[1740,245]]
|
y
|
||||||
|
"""
|
||||||
|
G = {
|
||||||
|
( 0, 0) : [(-1, 0),( 0, 1),( 2, 0),( 0,-2)],
|
||||||
|
( 0, 1) : [( 0, 0),( 2, 1)],
|
||||||
|
( 0,-2) : [( 0, 0),( 2,-2),(-1,-2)],
|
||||||
|
(-1, 0) : [(-1, 1),( 0, 0)],
|
||||||
|
(-1, 1) : [(-1, 0)],
|
||||||
|
(-1,-2) : [( 0,-2)],
|
||||||
|
( 2, 0) : [( 2, 1),( 2,-2),( 0, 0)],
|
||||||
|
( 2, 1) : [( 0, 1),( 2, 0)],
|
||||||
|
( 2,-2) : [( 2, 0),( 0,-2)],
|
||||||
|
}
|
||||||
|
|
||||||
best = search( max_it, num_ants, decay, c_heur, c_local_phero, c_greed, berlin52 )
|
best = search( max_it, num_ants, decay, w_heur, w_local_phero, w_history, c_greed, G, cost_func = graph_distance )
|
||||||
print best["cost"], best["permutation"]
|
print best["cost"], best["permutation"]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue