Skip to content

Commit 2a02eef

Browse files
Create PSO_w_constraints.py
1 parent 055be7e commit 2a02eef

File tree

1 file changed

+273
-0
lines changed

1 file changed

+273
-0
lines changed

PSO_w_constraints.py

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Sun Apr 12 18:04:30 2020
4+
5+
@author: Basharat
6+
7+
#!/usr/bin/env python3
8+
# -*- coding: utf-8 -*-
9+
10+
"""
11+
12+
13+
14+
15+
import numpy as np
16+
from sko.tools import func_transformer
17+
# Now Plot the animation
18+
import matplotlib.pyplot as plt
19+
from matplotlib.animation import FuncAnimation
20+
21+
# PSO (Particle swarm optimization) algorithm
22+
class PSO():
23+
"""
24+
Parameters
25+
--------------------
26+
cost_func : function
27+
The func you want to do optimal
28+
dimension : int
29+
Number of dimension, which is number of parameters of func.
30+
N : int
31+
Size of population, which is the number of Particles.
32+
max_iteration : int
33+
Max no of iterations
34+
35+
Attributes
36+
----------------------
37+
pbest_x : array_like, shape is (N,dim)
38+
best location of every particle in history
39+
pbest_y : array_like, shape is (N,1)
40+
best image of every particle in history
41+
gbest_x : array_like, shape is (1,dim)
42+
general best location for all particles in history
43+
gbest_y : float
44+
general best image for all particles in history
45+
gbest_y_hist : list
46+
gbest_y of every iteration
47+
"""
48+
49+
def __init__(self, cost_func, dimension, population_size=40, max_iteration=150, lb=None, ub=None, w=0.8, c1=0.5, c2=0.5):
50+
self.func = func_transformer(cost_func)
51+
52+
self.w = w # inertia weight
53+
self.c1, self.c2 = c1, c2 # parameters to control personal best, global best respectively
54+
self.N = population_size # number of particles
55+
self.dimension = dimension # dimension of particles, which is the number of variables of func
56+
self.max_iter = max_iteration # max iter
57+
58+
self.has_constraints = not (lb is None and ub is None)
59+
self.lb = -np.ones(self.dimension) if lb is None else np.array(lb)
60+
self.ub = np.ones(self.dimension) if ub is None else np.array(ub)
61+
v_high = self.ub - self.lb
62+
63+
assert self.dimension == len(self.lb) == len(self.ub), 'dimension == len(lb) == len(ub) is not True'
64+
assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound'
65+
66+
self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.N, self.dimension)) # position of particles
67+
self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.N, self.dimension)) # speed of particles
68+
self.Y = self.calculate_objfunc_Y() # y = f(x) for all particles
69+
70+
self.pbest_x = self.X.copy() # personal best location of every particle in history
71+
self.pbest_y = self.Y.copy() # best objective cost of every particle in history
72+
73+
self.gbest_x = np.zeros((1, self.dimension)) # global best location for all particles
74+
self.gbest_y = np.inf # global best objective cost for all particles
75+
76+
self.gbest_y_hist = [] # gbest_y of every iteration
77+
self.update_gbest()
78+
79+
# record verbose values
80+
self.record_mode = False
81+
self.record_value = {'X': [], 'V': [], 'Y': []}
82+
83+
# Update the velocity to get new value
84+
def update_V(self):
85+
r1 = np.random.rand(self.N, self.dimension)
86+
r2 = np.random.rand(self.N, self.dimension)
87+
88+
self.V = self.w * self.V + \
89+
self.c1 * r1 * (self.pbest_x - self.X) + \
90+
self.c2 * r2 * (self.gbest_x - self.X)
91+
92+
# Update the position to get new value
93+
def update_X(self):
94+
self.X = self.X + self.V
95+
96+
if self.has_constraints:
97+
self.X = np.clip(self.X, self.lb, self.ub)
98+
99+
# Calculate objective function of all particles
100+
def calculate_objfunc_Y(self):
101+
# calculate y for every x in X
102+
self.Y = self.func(self.X).reshape(-1, 1)
103+
return self.Y
104+
105+
# Local best position of all the particles
106+
def update_pbest(self):
107+
'''
108+
personal best
109+
:return:
110+
'''
111+
self.pbest_x = np.where(self.pbest_y > self.Y, self.X, self.pbest_x)
112+
self.pbest_y = np.where(self.pbest_y > self.Y, self.Y, self.pbest_y)
113+
114+
# Global best position of all the particles
115+
def update_gbest(self):
116+
'''
117+
global best
118+
:return:
119+
'''
120+
if self.gbest_y > self.Y.min():
121+
self.gbest_x = self.X[self.Y.argmin(), :].copy()
122+
self.gbest_y = self.Y.min()
123+
124+
# Track values by iteration to print later
125+
def recorder(self):
126+
if not self.record_mode:
127+
return
128+
self.record_value['X'].append(self.X)
129+
self.record_value['V'].append(self.V)
130+
self.record_value['Y'].append(self.Y)
131+
132+
# Run PSO algorithm
133+
def run(self, max_iter=None):
134+
self.max_iter = max_iter or self.max_iter
135+
for iter_num in range(self.max_iter):
136+
self.update_V()
137+
self.recorder()
138+
self.update_X()
139+
self.calculate_objfunc_Y()
140+
self.update_pbest()
141+
self.update_gbest()
142+
143+
self.gbest_y_hist.append(self.gbest_y)
144+
return self
145+
146+
fit = run
147+
148+
149+
#--- COST FUNCTIONS ------------------------------------------------------------+
150+
# function we are attempting to optimize (minimize)
151+
152+
def costFunc0(x):
153+
[x1, x2] = x
154+
return x1 ** 2 + (x2 - 0.05) ** 2
155+
156+
def costFunc1(x):
157+
total=0
158+
for i in range(len(x)):
159+
total+=x[i]**2
160+
return total
161+
162+
## https://www.researchgate.net/publication/261197555_A_generic_particle_swarm_optimization_Matlab_function
163+
# function we are attempting to optimize (minimize)
164+
def costFunc2(x):
165+
n = len(x)
166+
sum_1=0
167+
for i in range(len(x)):
168+
sum_1+=x[i]**2
169+
170+
sum_2=0
171+
for i in range(len(x)):
172+
sum_2+= np.cos(2*np.pi*x[i])
173+
174+
f = 20 + np.exp(1) - 20*np.exp(-0.2*np.sqrt((1/n)*sum_1)) - np.exp((1/n)*sum_2);
175+
return f
176+
177+
# https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/september/test-run-multi-swarm-optimization
178+
def costFunc3(x):
179+
f=0
180+
for i in range(len(x)):
181+
f += (x[i]**2) - (10 * np.cos(2 * np.pi * x[i]))
182+
return f + 20
183+
184+
185+
########################################
186+
####### CHANGE THE FUNCTION BELOW ######
187+
########################################
188+
f = costFunc0
189+
190+
########################################
191+
####### MAIN PSO call ######
192+
########################################
193+
#pso = PSO(func=demo_func, dimension=2, population_size=30, max_iter=100, lb=[-1, -1], ub=[1, 1])
194+
pso = PSO(cost_func=f, dimension=2, population_size=30, max_iteration=100, lb=[-1, -1], ub=[1, 1])
195+
#pso = PSO(cost_func=f, dimension=2, population_size=3, max_iteration=5, lb=[-1, -1], ub=[1, 1])
196+
pso.record_mode = True
197+
pso.run()
198+
print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y)
199+
200+
201+
202+
203+
########################################
204+
####### Plot PSO on 3D surfice ######
205+
########################################
206+
#==================================
207+
# Plotting the pso
208+
fig = plt.figure()
209+
ax = fig.add_subplot(111, projection='3d')
210+
211+
ax.set_title('title', loc='center')
212+
line = ax.plot([], [], 'b.')
213+
214+
X_grid, Y_grid = np.meshgrid(np.linspace(-1.0, 1.0, 40), np.linspace(-1.0, 1.0, 40))
215+
Z_grid = f((X_grid, Y_grid))
216+
ax.plot_surface(X_grid, Y_grid, Z_grid, cmap='jet', linewidth=0, antialiased=True, alpha=0.5)
217+
218+
ax.set_xlim(-1, 1)
219+
ax.set_ylim(-1, 1)
220+
221+
plt.ion()
222+
p = plt.show()
223+
224+
def animate(frame):
225+
i, j = frame // 10, frame % 10
226+
ax.set_title('iter = ' + str(i))
227+
X_tmp = X_list[i] + V_list[i] * j / 10.0
228+
plt.setp(line, 'xdata', X_tmp[:, 0], 'ydata', X_tmp[:, 1])
229+
return line
230+
231+
ani = FuncAnimation(fig, animate, blit=True, interval=40, frames=400)
232+
plt.show()
233+
234+
235+
236+
###########################################################
237+
####### Plot PSO on contour and animate particles ######
238+
###########################################################
239+
record_value = pso.record_value
240+
X_list, V_list = record_value['X'], record_value['V']
241+
242+
fig, ax = plt.subplots(1, 1)
243+
244+
# Plotting the pso
245+
# fig = plt.figure()
246+
# ax = fig.add_subplot(111, projection='3d')
247+
248+
ax.set_title('title', loc='center')
249+
line = ax.plot([], [], 'b.')
250+
251+
X_grid, Y_grid = np.meshgrid(np.linspace(-1.0, 1.0, 40), np.linspace(-1.0, 1.0, 40))
252+
Z_grid = f((X_grid, Y_grid))
253+
ax.contour(X_grid, Y_grid, Z_grid, 10)
254+
255+
ax.set_xlim(-1, 1)
256+
ax.set_ylim(-1, 1)
257+
258+
plt.ion()
259+
p = plt.show()
260+
261+
262+
def update_scatter(frame):
263+
i, j = frame // 10, frame % 10
264+
ax.set_title('iter = ' + str(i))
265+
X_tmp = X_list[i] + V_list[i] * j / 10.0
266+
plt.setp(line, 'xdata', X_tmp[:, 0], 'ydata', X_tmp[:, 1])
267+
return line
268+
269+
270+
ani = FuncAnimation(fig, update_scatter, interval=25, frames=250, repeat=True)
271+
plt.show()
272+
273+
#ani.save('pso.gif', writer='pillow')

0 commit comments

Comments
 (0)