You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ant Colony Optimization algorithms always intrigued me. They are loosely based in biology and the real protocols ants use to communicate and plan routes. They do this by coordinating through small pheromone messages: chemical trails they leave as they move forward, signaling for other ants to follow them. Even though each ant is not especially smart, and they follow simple rules individually, collectively they can converge to complex behaviors as a system, and amazing properties emerge.
13
18
14
19
In the computational sense, Ant Colony Optimization algorithms solve complex optimization problems for which a closed-form or polynomial solution does not exist, by trying different "routes" across some relevant space or graph, and trying to find the most efficient one (typically the shortest) from two points that satisfies some constraints.
@@ -87,7 +92,41 @@ That is, the probability of choosing a certain edge will be proportional to:
87
92
88
93
Where P is the level of pheromones in that edge, and D the distance the edge covers. To get the distribution we sample from at each random jump, we normalize these weight coefficients so they add up to one.
89
94
<divclass="wide-eighty">
90
-
{% raw %}<divid="gist1"></div>{% endraw %}
95
+
{% raw %}
96
+
<pre><codeclass="language-python">
97
+
def traverse_graph(g, source_node = 0):
98
+
ALPHA = 0.9
99
+
BETA = 1.5
100
+
visited = np.asarray([1 for _ in range(g.nodes)]) #originally no nodes have been visited
101
+
visited[source_node] = 0 # except the initial/source node.
102
+
103
+
cycle = [source_node]
104
+
steps = 0
105
+
current = source_node
106
+
total_length = 0
107
+
while steps < g.nodes -1:
108
+
109
+
jumps_neighbors = []
110
+
jumps_values = []
111
+
for node in range(g.nodes):
112
+
if visited[node] != 0:
113
+
pheromone_level = max(g.intensity[current][node], 1e-5) #constant added to encourage exploration
114
+
v = (pheromone_level**ALPHA ) / (g.distance[current][node]**BETA)
best_cycle = best_so_far # can be pre set or set to None
153
+
best_length = cycle_length(g, best_so_far) #hardcoded instance. Else use None
154
+
if use_inertia: #this is adding pheromones everywhere if the process stagnates. This did not improve my results and is left off.
155
+
old_best = None
156
+
inertia = 0
157
+
patience = 100
158
+
159
+
for iteration in range(iterations):
160
+
cycles = [traverse_graph(g, random.randint(0, g.nodes -1)) for _ in range(ants_per_iteration)] # could be trivially parallelized if not on Mac through multiprocessing
161
+
cycles.sort(key = lambda x: x[1])
162
+
cycles = cycles[: ants_per_iteration//2] #optionally keep best half.
163
+
164
+
if best_cycle: #elitism
165
+
cycles.append((best_cycle, best_length))
166
+
if use_inertia:
167
+
old_best = best_length
168
+
169
+
for cycle, total_length in cycles: # pheromone update
0 commit comments