Skip to content

Commit

Permalink
Merge pull request #137 from ljvmiranda921/format-code
Browse files Browse the repository at this point in the history
Format code using black and add pre-commit hooks
  • Loading branch information
Lj Miranda authored Jun 18, 2018
2 parents 853772f + 297a403 commit f59e73c
Show file tree
Hide file tree
Showing 57 changed files with 1,378 additions and 722 deletions.
5 changes: 5 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[flake8]
ignore = E203, E266, E501, W503, F403, F401
max-line-length = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/ambv/black
rev: stable
hooks:
- id: black
language_version: python3.6
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v1.2.3
hooks:
- id: flake8
6 changes: 4 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ Ready to contribute? Here's how to set up `pyswarms` for local development.

Now you can make your changes locally.

5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox. In addition, ensure that your code is formatted using black::

$ flake8 pyswarms tests
$ black pyswarms tests
$ python setup.py test or py.test
$ tox

To get flake8 and tox, just pip install them into your virtualenv.
To get flake8, black, and tox, just pip install them into your virtualenv. If you wish,
you can add pre-commit hooks for both flake8 and black to make all formatting easier.

6. Commit your changes and push your branch to GitHub::

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[![Documentation Status](https://readthedocs.org/projects/pyswarms/badge/?version=master)](https://pyswarms.readthedocs.io/en/master/?badge=development)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg )](https://raw.githubusercontent.com/ljvmiranda921/pyswarms/master/LICENSE)
[![DOI](http://joss.theoj.org/papers/10.21105/joss.00433/status.svg)](https://doi.org/10.21105/joss.00433)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
[![Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pyswarms/Issues)

PySwarms is an extensible research toolkit for particle swarm optimization
Expand Down
16 changes: 16 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[tool.black]
line-length = 79
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
10 changes: 3 additions & 7 deletions pyswarms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
"""

__author__ = """Lester James V. Miranda"""
__email__ = '[email protected]'
__version__ = '0.2.0'
__email__ = "[email protected]"
__version__ = "0.2.0"

from .single import global_best, local_best
from .discrete import binary

__all__ = [
'global_best',
'local_best',
'binary'
]
__all__ = ["global_best", "local_best", "binary"]
4 changes: 3 additions & 1 deletion pyswarms/backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

from .generators import *
from .operators import *
from .swarms import *
from .swarms import *

__all__ = ["generators", "operators", "swarms"]
80 changes: 57 additions & 23 deletions pyswarms/backend/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
from .swarms import Swarm


def generate_swarm(n_particles, dimensions, bounds=None, center=1.00, init_pos=None):
def generate_swarm(
n_particles, dimensions, bounds=None, center=1.00, init_pos=None
):
"""Generates a swarm
Parameters
Expand Down Expand Up @@ -44,25 +46,37 @@ def generate_swarm(n_particles, dimensions, bounds=None, center=1.00, init_pos=N
if (init_pos is not None) and (bounds is None):
pos = init_pos
elif (init_pos is not None) and (bounds is not None):
if not (np.all(bounds[0] <= init_pos) and np.all(init_pos <= bounds[1])):
raise ValueError('User-defined init_pos is out of bounds.')
if not (
np.all(bounds[0] <= init_pos) and np.all(init_pos <= bounds[1])
):
raise ValueError("User-defined init_pos is out of bounds.")
pos = init_pos
elif (init_pos is None) and (bounds is None):
pos = center * np.random.uniform(low=0.0, high=1.0, size=(n_particles, dimensions))
pos = center * np.random.uniform(
low=0.0, high=1.0, size=(n_particles, dimensions)
)
else:
lb, ub = bounds
min_bounds = np.repeat(np.array(lb)[np.newaxis, :], n_particles, axis=0)
max_bounds = np.repeat(np.array(ub)[np.newaxis, :], n_particles, axis=0)
pos = center * np.random.uniform(low=min_bounds, high=max_bounds,
size=(n_particles, dimensions))
min_bounds = np.repeat(
np.array(lb)[np.newaxis, :], n_particles, axis=0
)
max_bounds = np.repeat(
np.array(ub)[np.newaxis, :], n_particles, axis=0
)
pos = center * np.random.uniform(
low=min_bounds, high=max_bounds, size=(n_particles, dimensions)
)
except ValueError:
raise
else:
return pos

def generate_discrete_swarm(n_particles, dimensions, binary=False, init_pos=None):

def generate_discrete_swarm(
n_particles, dimensions, binary=False, init_pos=None
):
"""Generates a discrete swarm
Parameters
----------
n_particles : int
Expand All @@ -78,19 +92,22 @@ def generate_discrete_swarm(n_particles, dimensions, binary=False, init_pos=None
try:
if (init_pos is not None) and binary:
if not len(np.unique(init_pos)) == 2:
raise ValueError('User-defined init_pos is not binary!')
raise ValueError("User-defined init_pos is not binary!")
pos = init_pos
elif (init_pos is not None) and not binary:
pos = init_pos
elif (init_pos is None) and binary:
pos = np.random.randint(2, size=(n_particles, dimensions))
else:
pos = np.random.random_sample(size=(n_particles, dimensions)).argsort(axis=1)
pos = np.random.random_sample(
size=(n_particles, dimensions)
).argsort(axis=1)
except ValueError:
raise
else:
return pos


def generate_velocity(n_particles, dimensions, clamp=None):
"""Initializes a velocity vector
Expand All @@ -111,19 +128,29 @@ def generate_velocity(n_particles, dimensions, clamp=None):
velocity matrix of shape (n_particles, dimensions)
"""
try:
min_velocity, max_velocity = (0,1) if clamp==None else clamp
velocity = ((max_velocity - min_velocity)
* np.random.random_sample(size=(n_particles, dimensions))
+ min_velocity)
min_velocity, max_velocity = (0, 1) if clamp is None else clamp
velocity = (max_velocity - min_velocity) * np.random.random_sample(
size=(n_particles, dimensions)
) + min_velocity
except (ValueError, TypeError):
raise
else:
return velocity

def create_swarm(n_particles, dimensions, discrete=False, binary=False,
options={}, bounds=None, center=1.0, init_pos=None, clamp=None):

def create_swarm(
n_particles,
dimensions,
discrete=False,
binary=False,
options={},
bounds=None,
center=1.0,
init_pos=None,
clamp=None,
):
"""Abstracts the generate_swarm() and generate_velocity() methods
Parameters
----------
n_particles : int
Expand Down Expand Up @@ -156,10 +183,17 @@ def create_swarm(n_particles, dimensions, discrete=False, binary=False,
a Swarm class
"""
if discrete:
position = generate_discrete_swarm(n_particles, dimensions, binary=binary)
position = generate_discrete_swarm(
n_particles, dimensions, binary=binary
)
else:
position = generate_swarm(n_particles, dimensions, bounds=bounds,
center=center, init_pos=init_pos)
position = generate_swarm(
n_particles,
dimensions,
bounds=bounds,
center=center,
init_pos=init_pos,
)

velocity = generate_velocity(n_particles, dimensions, clamp=clamp)
return Swarm(position, velocity, options=options)
return Swarm(position, velocity, options=options)
61 changes: 40 additions & 21 deletions pyswarms/backend/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
# Create a logger
logger = logging.getLogger(__name__)


def compute_pbest(swarm):
"""Takes a swarm instance and updates the personal best scores
You can use this method to update your personal best positions.
.. code-block:: python
Expand All @@ -37,7 +38,7 @@ def compute_pbest(swarm):
It updates your :code:`current_pbest` with the personal bests acquired by
comparing the (1) cost of the current positions and the (2) personal
bests your swarm has attained.
If the cost of the current position is less than the cost of the personal
best, then the current position replaces the previous personal best
position.
Expand All @@ -58,25 +59,28 @@ def compute_pbest(swarm):
# Infer dimensions from positions
dimensions = swarm.dimensions
# Create a 1-D and 2-D mask based from comparisons
mask_cost = (swarm.current_cost < swarm.pbest_cost)
mask_pos = np.repeat(mask_cost[:, np.newaxis], swarm.dimensions, axis=1)
mask_cost = swarm.current_cost < swarm.pbest_cost
mask_pos = np.repeat(mask_cost[:, np.newaxis], dimensions, axis=1)
# Apply masks
new_pbest_pos = np.where(~mask_pos, swarm.pbest_pos, swarm.position)
new_pbest_cost = np.where(~mask_cost, swarm.pbest_cost, swarm.current_cost)
new_pbest_cost = np.where(
~mask_cost, swarm.pbest_cost, swarm.current_cost
)
except AttributeError:
msg = 'Please pass a Swarm class. You passed {}'.format(type(swarm))
msg = "Please pass a Swarm class. You passed {}".format(type(swarm))
logger.error(msg)
raise
else:
return (new_pbest_pos, new_pbest_cost)


def compute_velocity(swarm, clamp):
"""Updates the velocity matrix
This method updates the velocity matrix using the best and current
positions of the swarm. The velocity matrix is computed using the
cognitive and social terms of the swarm.
A sample usage can be seen with the following:
.. code-block :: python
Expand Down Expand Up @@ -107,33 +111,43 @@ def compute_velocity(swarm, clamp):
try:
# Prepare parameters
swarm_size = swarm.position.shape
c1 = swarm.options['c1']
c2 = swarm.options['c2']
w = swarm.options['w']
c1 = swarm.options["c1"]
c2 = swarm.options["c2"]
w = swarm.options["w"]
# Compute for cognitive and social terms
cognitive = (c1 * np.random.uniform(0,1, swarm_size) * (swarm.pbest_pos - swarm.position))
social = (c2 * np.random.uniform(0, 1, swarm_size) * (swarm.best_pos - swarm.position))
cognitive = (
c1
* np.random.uniform(0, 1, swarm_size)
* (swarm.pbest_pos - swarm.position)
)
social = (
c2
* np.random.uniform(0, 1, swarm_size)
* (swarm.best_pos - swarm.position)
)
# Compute temp velocity (subject to clamping if possible)
temp_velocity = (w * swarm.velocity) + cognitive + social

if clamp is None:
updated_velocity = temp_velocity
else:
min_velocity, max_velocity = clamp
mask = np.logical_and(temp_velocity >= min_velocity,
temp_velocity <= max_velocity)
mask = np.logical_and(
temp_velocity >= min_velocity, temp_velocity <= max_velocity
)
updated_velocity = np.where(~mask, swarm.velocity, temp_velocity)
except AttributeError:
msg = 'Please pass a Swarm class. You passed {}'.format(type(swarm))
msg = "Please pass a Swarm class. You passed {}".format(type(swarm))
logger.error(msg)
raise
except KeyError:
msg = 'Missing keyword in swarm.options'
msg = "Missing keyword in swarm.options"
logger.error(msg)
raise
else:
return updated_velocity


def compute_position(swarm, bounds):
"""Updates the position matrix
Expand All @@ -160,15 +174,20 @@ def compute_position(swarm, bounds):

if bounds is not None:
lb, ub = bounds
min_bounds = np.repeat(np.array(lb)[np.newaxis, :], swarm.n_particles, axis=0)
max_bounds = np.repeat(np.array(ub)[np.newaxis, :], swarm.n_particles, axis=0)
mask = (np.all(min_bounds <= temp_position, axis=1)
* np.all(temp_position <= max_bounds, axis=1))
min_bounds = np.repeat(
np.array(lb)[np.newaxis, :], swarm.n_particles, axis=0
)
max_bounds = np.repeat(
np.array(ub)[np.newaxis, :], swarm.n_particles, axis=0
)
mask = np.all(min_bounds <= temp_position, axis=1) * np.all(
temp_position <= max_bounds, axis=1
)
mask = np.repeat(mask[:, np.newaxis], swarm.dimensions, axis=1)
temp_position = np.where(~mask, swarm.position, temp_position)
position = temp_position
except AttributeError:
msg = 'Please pass a Swarm class. You passed {}'.format(type(swarm))
msg = "Please pass a Swarm class. You passed {}".format(type(swarm))
logger.error(msg)
raise
else:
Expand Down
Loading

0 comments on commit f59e73c

Please sign in to comment.