Skip to content

Commit c2feef6

Browse files
authored
Merge pull request #13 from NimishVerma/master
Adding GWO
2 parents 28f04b9 + 1445851 commit c2feef6

File tree

12 files changed

+243
-5
lines changed

12 files changed

+243
-5
lines changed

.idea/swarmlib.iml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.pylintrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# A comma-separated list of package or module names from where C extensions may
44
# be loaded. Extensions are loading into the active Python interpreter and may
55
# run arbitrary code
6-
extension-pkg-whitelist=
6+
extension-pkg-whitelist=numpy
77

88
# Add files or directories to the blacklist. They should be base names, not
99
# paths.
@@ -25,7 +25,7 @@ jobs=1
2525
load-plugins=pylint_quotes,pylintfileheader
2626

2727
# Option for the pylintfileheader plugin
28-
file-header=# ------------------------------------------------------------------------------------------------------\n# Copyright \(c\) Leo Hanisch. All rights reserved.\n# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.\n# ------------------------------------------------------------------------------------------------------\n
28+
file-header=# ------------------------------------------------------------------------------------------------------\n# Copyright \(c\) Leo Hanisch( and contributors)?. All rights reserved.\n# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.\n# ------------------------------------------------------------------------------------------------------\n
2929

3030
# Pickle collected data for later comparisons.
3131
persistent=yes

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 3-Clause License
22

3-
Copyright (c) 2018, Leo Hanisch
3+
Copyright (c) 2018, Leo Hanisch and contributors.
44
All rights reserved.
55

66
Redistribution and use in source and binary forms, with or without

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Currently, the following algorithms are implemented:
1515
* [Particle Swarm Optimization](#particle-swarm-optimization)
1616
* [Ant Colony Optimization](#ant-colony-optimization)
1717
* [Artificial Bee Colony](#artificial-bee-colony)
18+
* [Grey Wolf Optimization](#grey-wolf-optimization)
1819

1920
## Installation
2021

@@ -214,3 +215,37 @@ problem = ABCProblem(bees=10, function=FUNCTIONS['michalewicz'])
214215
best_bee = problem.solve()
215216
problem.replay()
216217
```
218+
219+
### Grey Wolf Optimization
220+
221+
The Grey Wolf Optimization (GWO) algorithm was proposed by S. Mirjalili et al. in the paper [Grey Wolf Optimizer](https://www.sciencedirect.com/science/article/pii/S0965997813001853?casa_token=IJMUjrkkBVkAAAAA:TIW5bZqXDqgQwD1aX-5vqsDvmf4AgWFODvWepUiZi79MgSii3MlDMXMwgMVPcQvuGlZYLKm5GA).
222+
The paper proposed a novel algorithm based on the hunting and the hierarchy structure in grey wolves
223+
224+
#### Features
225+
226+
Enables the GWO algorithm to one of the provided 2D functions. The algorithm tries to find the global minimum of the selected function.
227+
228+
Currently two functions can be selected:
229+
* [ackley](https://www.sfu.ca/~ssurjano/ackley.html)
230+
* [michalewicz](https://www.sfu.ca/~ssurjano/michal.html)
231+
232+
![GWO Sample](https://raw.githubusercontent.com/HaaLeo/swarmlib/master/doc/gwo.gif)
233+
234+
235+
To print all available options execute:
236+
237+
```
238+
swarm wolves -h
239+
```
240+
241+
#### API
242+
243+
In addition to the cli you can also use the API:
244+
245+
```python
246+
from swarmlib import GWOProblem, FUNCTIONS
247+
248+
problem = GWOProblem(wolves=10, function=FUNCTIONS['michalewicz'])
249+
best_wolf = problem.solve()
250+
problem.replay()
251+
```

doc/gwo.gif

1.44 MB
Loading

swarmlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
from .cuckoosearch.cuckoo_problem import CuckooProblem
99
from .pso.pso_problem import PSOProblem
1010
from .abc.abc_problem import ABCProblem
11+
from .gwo.gwo_problem import GWOProblem
1112
from .util.functions import FUNCTIONS

swarmlib/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .cuckoosearch.main import configure_parser as cuckoo_parser
1414
from .pso.main import configure_parser as pso_parser
1515
from .abc.main import configure_parser as abc_parser
16-
16+
from .gwo.main import configure_parser as gwo_parser
1717
from ._version import __version__
1818

1919
logging.basicConfig(
@@ -62,7 +62,7 @@ def run_swarm():
6262
cuckoo_parser(sub_parsers)
6363
pso_parser(sub_parsers)
6464
abc_parser(sub_parsers)
65-
65+
gwo_parser(sub_parsers)
6666
args = vars(parser.parse_args())
6767
if args:
6868
algorithm = args.pop('func')

swarmlib/gwo/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# ------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Leo Hanisch and contributors. All rights reserved.
3+
# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.
4+
# ------------------------------------------------------------------------------------------------------

swarmlib/gwo/gwo_problem.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Leo Hanisch and contributors. All rights reserved.
3+
# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.
4+
# ------------------------------------------------------------------------------------------------------
5+
6+
import logging
7+
from copy import deepcopy
8+
from .wolf import Wolf
9+
from .visualizer import Visualizer
10+
11+
# pylint: disable=too-many-instance-attributes
12+
13+
LOGGER = logging.getLogger(__name__)
14+
15+
16+
class GWOProblem:
17+
def __init__(self, **kwargs):
18+
"""
19+
Initialize a new grey wolf optimization problem.
20+
"""
21+
22+
self.__iteration_number = kwargs.get('iteration_number', 30)
23+
self.__wolves = [
24+
Wolf(**kwargs)
25+
for _ in range(kwargs['wolves'])
26+
]
27+
self.__alpha, self.__beta, self.__delta = self.__wolves[:3] # random alpha beta delta for initial coloring
28+
# Initialize visualizer for plotting
29+
positions = [wolf.position for wolf in self.__wolves]
30+
self.__visualizer = Visualizer(**kwargs)
31+
self.__visualizer.add_data(
32+
positions=positions) # ,alpha_pos =self.alpha.position,beta_pos=self.beta.position,delta_pos=self.delta.position)
33+
34+
def solve(self) -> Wolf:
35+
36+
for iter_no in range(self.__iteration_number + 1):
37+
a_parameter = 2 - iter_no * ((2) / self.__iteration_number)
38+
# Update alpha beta delta
39+
self.__wolves.sort(key=lambda wolf: wolf.value)
40+
41+
self.__alpha, self.__beta, self.__delta = deepcopy(self.__wolves[:3])
42+
43+
for wolf in self.__wolves:
44+
wolf.step(a_parameter, self.__alpha.position, self.__beta.position, self.__delta.position)
45+
46+
# Add data for plot
47+
positions = [particle.position for particle in self.__wolves]
48+
self.__visualizer.add_data(
49+
positions=positions) # ,alpha_pos =self.alpha.position,beta_pos=self.beta.position,delta_pos=self.delta.position)
50+
51+
LOGGER.info('Last best solution="%s" at position="%s"', self.__alpha.value, self.__alpha.position)
52+
return self.__alpha
53+
54+
def replay(self):
55+
"""
56+
Start the problems visualization.
57+
"""
58+
self.__visualizer.replay()
59+
60+
# print(GWOProblem(function=FUNCTIONS['michalewicz'], wolves=20, iteration_number=10))

swarmlib/gwo/main.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# ------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Leo Hanisch and contributors. All rights reserved.
3+
# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.
4+
# ------------------------------------------------------------------------------------------------------
5+
import logging
6+
7+
from .gwo_problem import GWOProblem
8+
from ..util.functions import FUNCTIONS
9+
10+
LOGGER = logging.getLogger(__name__)
11+
12+
13+
def _run_gwo(args):
14+
LOGGER.info('Start grey wolf optimization with parameters="%s"', args)
15+
args['function'] = FUNCTIONS[args['function']]
16+
17+
problem = GWOProblem(**args)
18+
problem.solve()
19+
problem.replay()
20+
21+
22+
def configure_parser(sub_parsers):
23+
"""
24+
Get the argument parser for grey wolf optimization
25+
"""
26+
27+
parser = sub_parsers.add_parser(
28+
'wolves',
29+
description='Solving an minimization problem using the grey wolf optimization algorithm',
30+
help='Grey Wolf optimization algorithm for minimization problem')
31+
32+
parser.add_argument(
33+
'-f',
34+
'--function',
35+
type=str,
36+
default='michalewicz',
37+
help='Choose the function that is used for searching the minimum.',
38+
choices=['michalewicz', 'ackley'])
39+
parser.add_argument(
40+
'-u',
41+
'--upper-boundary',
42+
type=float,
43+
default=4.,
44+
help='Upper boundary of the function (default 4)')
45+
parser.add_argument(
46+
'-l',
47+
'--lower-boundary',
48+
type=float,
49+
default=0.,
50+
help='Lower boundary of the function (default 0)')
51+
parser.add_argument(
52+
'-n',
53+
'--iteration-number',
54+
type=int,
55+
default=30,
56+
help='Number of iterations to execute (default 30)')
57+
parser.add_argument(
58+
'wolves',
59+
type=int,
60+
help='Number of wolves used for solving')
61+
62+
parser.set_defaults(func=_run_gwo)

swarmlib/gwo/visualizer.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# ------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Leo Hanisch and contributors. All rights reserved.
3+
# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.
4+
# ------------------------------------------------------------------------------------------------------
5+
6+
import numpy as np
7+
from ..util.base_visualizer import BaseVisualizer
8+
9+
class Visualizer(BaseVisualizer):
10+
def replay(self):
11+
self._velocities = [self._positions[index+1]-position for index, position in enumerate(self._positions[:-1])]
12+
self._velocities.insert(0, np.zeros(self._positions[0].shape))
13+
self._velocities.append(np.zeros(self._positions[0].shape))
14+
super().replay()

swarmlib/gwo/wolf.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# ------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Leo Hanisch and contributors. All rights reserved.
3+
# Licensed under the BSD 3-Clause License. See LICENSE.txt in the project root for license information.
4+
# ------------------------------------------------------------------------------------------------------
5+
6+
# pylint: disable-msg=too-many-locals
7+
from typing import Tuple
8+
import numpy as np
9+
10+
from ..util.coordinate import Coordinate
11+
12+
13+
class Wolf(Coordinate):
14+
def step(self, a_parameter, alpha_pos: Tuple[float, float], beta_pos: Tuple[float, float],
15+
delta_pos: Tuple[float, float]) -> None:
16+
"""
17+
Execute a wolf step.
18+
Update the wolf's position and value.
19+
20+
Arguments:
21+
alpha_pos {Tuple[float, float]} -- The alpha position
22+
beta_pos {Tuple[float, float]} -- The beta position
23+
delta_pos {Tuple[float, float]} -- The delta position
24+
"""
25+
26+
27+
r_1 = np.random.random() # r_1 is a random number in [0,1]
28+
r_2 = np.random.random() # r_2 is a random number in [0,1]
29+
30+
a_1 = 2 * a_parameter * r_1 - a_parameter # Equation (3.3)
31+
c_1 = 2 * r_2 # Equation (3.4)
32+
33+
d_alpha = abs(c_1 * alpha_pos - self._position) # Equation (3.5)-part 1
34+
x_1 = alpha_pos - a_1 * d_alpha # Equation (3.6)-part 1
35+
36+
r_1 = np.random.random()
37+
r_2 = np.random.random()
38+
39+
a_2 = 2 * a_parameter * r_1 - a_parameter # Equation (3.3)
40+
c_2 = 2 * r_2 # Equation (3.4)
41+
42+
d_beta = abs(c_2 * beta_pos - self._position) # Equation (3.5)-part 2
43+
x_2 = beta_pos - a_2 * d_beta # Equation (3.6)-part 2
44+
45+
r_1 = np.random.random()
46+
r_2 = np.random.random()
47+
48+
a_3 = 2 * a_parameter * r_1 - a_parameter # Equation (3.3)
49+
c_3 = 2 * r_2 # Equation (3.4)
50+
51+
d_delta = abs(c_3 * delta_pos - self._position) # Equation (3.5)-part 3
52+
x_3 = delta_pos - a_3 * d_delta # Equation (3.5)-part 3
53+
54+
self._position = (x_1 + x_2 + x_3) / 3 # Equation (3.7)

0 commit comments

Comments
 (0)