-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathpso.py
140 lines (115 loc) · 4.99 KB
/
pso.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import random
import math
import matplotlib.pyplot as plt
from util import City, read_cities, write_cities_and_return_them, generate_cities, path_cost
class Particle:
def __init__(self, route, cost=None):
self.route = route
self.pbest = route
self.current_cost = cost if cost else self.path_cost()
self.pbest_cost = cost if cost else self.path_cost()
self.velocity = []
def clear_velocity(self):
self.velocity.clear()
def update_costs_and_pbest(self):
self.current_cost = self.path_cost()
if self.current_cost < self.pbest_cost:
self.pbest = self.route
self.pbest_cost = self.current_cost
def path_cost(self):
return path_cost(self.route)
class PSO:
def __init__(self, iterations, population_size, gbest_probability=1.0, pbest_probability=1.0, cities=None):
self.cities = cities
self.gbest = None
self.gcost_iter = []
self.iterations = iterations
self.population_size = population_size
self.particles = []
self.gbest_probability = gbest_probability
self.pbest_probability = pbest_probability
solutions = self.initial_population()
self.particles = [Particle(route=solution) for solution in solutions]
def random_route(self):
return random.sample(self.cities, len(self.cities))
def initial_population(self):
random_population = [self.random_route() for _ in range(self.population_size - 1)]
greedy_population = [self.greedy_route(0)]
return [*random_population, *greedy_population]
# return [*random_population]
def greedy_route(self, start_index):
unvisited = self.cities[:]
del unvisited[start_index]
route = [self.cities[start_index]]
while len(unvisited):
index, nearest_city = min(enumerate(unvisited), key=lambda item: item[1].distance(route[-1]))
route.append(nearest_city)
del unvisited[index]
return route
def run(self):
self.gbest = min(self.particles, key=lambda p: p.pbest_cost)
print(f"initial cost is {self.gbest.pbest_cost}")
plt.ion()
plt.draw()
for t in range(self.iterations):
self.gbest = min(self.particles, key=lambda p: p.pbest_cost)
if t % 20 == 0:
plt.figure(0)
plt.plot(pso.gcost_iter, 'g')
plt.ylabel('Distance')
plt.xlabel('Generation')
fig = plt.figure(0)
fig.suptitle('pso iter')
x_list, y_list = [], []
for city in self.gbest.pbest:
x_list.append(city.x)
y_list.append(city.y)
x_list.append(pso.gbest.pbest[0].x)
y_list.append(pso.gbest.pbest[0].y)
fig = plt.figure(1)
fig.clear()
fig.suptitle(f'pso TSP iter {t}')
plt.plot(x_list, y_list, 'ro')
plt.plot(x_list, y_list, 'g')
plt.draw()
plt.pause(.001)
self.gcost_iter.append(self.gbest.pbest_cost)
for particle in self.particles:
particle.clear_velocity()
temp_velocity = []
gbest = self.gbest.pbest[:]
new_route = particle.route[:]
for i in range(len(self.cities)):
if new_route[i] != particle.pbest[i]:
swap = (i, particle.pbest.index(new_route[i]), self.pbest_probability)
temp_velocity.append(swap)
new_route[swap[0]], new_route[swap[1]] = \
new_route[swap[1]], new_route[swap[0]]
for i in range(len(self.cities)):
if new_route[i] != gbest[i]:
swap = (i, gbest.index(new_route[i]), self.gbest_probability)
temp_velocity.append(swap)
gbest[swap[0]], gbest[swap[1]] = gbest[swap[1]], gbest[swap[0]]
particle.velocity = temp_velocity
for swap in temp_velocity:
if random.random() <= swap[2]:
new_route[swap[0]], new_route[swap[1]] = \
new_route[swap[1]], new_route[swap[0]]
particle.route = new_route
particle.update_costs_and_pbest()
if __name__ == "__main__":
cities = read_cities(64)
pso = PSO(iterations=1200, population_size=300, pbest_probability=0.9, gbest_probability=0.02, cities=cities)
pso.run()
print(f'cost: {pso.gbest.pbest_cost}\t| gbest: {pso.gbest.pbest}')
x_list, y_list = [], []
for city in pso.gbest.pbest:
x_list.append(city.x)
y_list.append(city.y)
x_list.append(pso.gbest.pbest[0].x)
y_list.append(pso.gbest.pbest[0].y)
fig = plt.figure(1)
fig.suptitle('pso TSP')
plt.plot(x_list, y_list, 'ro')
plt.plot(x_list, y_list)
plt.show(block=True)