Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format code using black and add pre-commit hooks #137

Merged
merged 3 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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