Skip to content

Commit

Permalink
Merge pull request #138 from ljvmiranda921/add-pre-commit-hooks
Browse files Browse the repository at this point in the history
Add pre-commit hooks
  • Loading branch information
Lj Miranda authored Jun 18, 2018
2 parents a8eb9f3 + fbbbdac commit 71918fc
Show file tree
Hide file tree
Showing 37 changed files with 546 additions and 287 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
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
)/
'''
2 changes: 2 additions & 0 deletions pyswarms/backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
from .generators import *
from .operators import *
from .swarms import *

__all__ = ["generators", "operators", "swarms"]
6 changes: 3 additions & 3 deletions pyswarms/backend/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def generate_discrete_swarm(
n_particles, dimensions, binary=False, init_pos=None
):
"""Generates a discrete swarm
Parameters
----------
n_particles : int
Expand Down Expand Up @@ -128,7 +128,7 @@ 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
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
Expand All @@ -150,7 +150,7 @@ def create_swarm(
clamp=None,
):
"""Abstracts the generate_swarm() and generate_velocity() methods
Parameters
----------
n_particles : int
Expand Down
10 changes: 4 additions & 6 deletions pyswarms/backend/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

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 @@ -38,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 @@ -60,9 +60,7 @@ def compute_pbest(swarm):
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_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(
Expand All @@ -82,7 +80,7 @@ def compute_velocity(swarm, clamp):
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
8 changes: 4 additions & 4 deletions pyswarms/backend/swarms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
@attrs
class Swarm(object):
"""A Swarm Class
This class offers a generic swarm that can be used in most use-cases
such as single-objective optimization, etc. It contains various attributes
that are commonly-used in most swarm implementations.
To initialize this class, **simply supply values for the position and
velocity matrix**. The other attributes are automatically filled. If you want to
initialize random values, take a look at:
initialize random values, take a look at:
* :func:`pyswarms.backend.generators.generate_swarm`: for generating positions randomly.
* :func:`pyswarms.backend.generators.generate_velocity`: for generating velocities randomly.
* :func:`pyswarms.backend.generators.generate_velocity`: for generating velocities randomly.
If your swarm requires additional parameters (say c1, c2, and w in gbest
PSO), simply pass them to the :code:`options` dictionary.
Expand Down Expand Up @@ -73,7 +73,7 @@ class Swarm(object):
pbest_cost : numpy.ndarray (default is empty array)
personal best costs of each particle of shape :code:`(n_particles, )`
best_cost : float (default is :code:`np.inf`)
best cost found by the swarm
best cost found by the swarm
current_cost : numpy.ndarray (default is empty array)
the current cost found by the swarm of shape :code:`(n_particles, dimensions)`
"""
Expand Down
2 changes: 1 addition & 1 deletion pyswarms/backend/topology/ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def compute_velocity(self, swarm, clamp=None):
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
2 changes: 1 addition & 1 deletion pyswarms/backend/topology/star.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def compute_velocity(self, swarm, clamp=None):
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
12 changes: 6 additions & 6 deletions pyswarms/single/global_best.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
.. math::
v_{ij}(t + 1) = m * v_{ij}(t) + c_{1}r_{1j}(t)[y_{ij}(t) − x_{ij}(t)]
v_{ij}(t + 1) = m * v_{ij}(t) + c_{1}r_{1j}(t)[y_{ij}(t) − x_{ij}(t)]
+ c_{2}r_{2j}(t)[\hat{y}_{j}(t) − x_{ij}(t)]
Here, :math:`c1` and :math:`c2` are the cognitive and social parameters
respectively. They control the particle's options in choosing how to
react given two choices: (1) to follow its *personal best* or (2) follow
the swarm's *global best* position. Overall, this dictates if the swarm
is explorative or exploitative in nature. In addition, a parameter
:math:`w` controls the inertia of the swarm's movement.
respectively. They control the particle's behavior given two choices: (1) to
follow its *personal best* or (2) follow the swarm's *global best* position.
Overall, this dictates if the swarm is explorative or exploitative in nature.
In addition, a parameter :math:`w` controls the inertia of the swarm's
movement.
An example usage is as follows:
Expand Down
4 changes: 3 additions & 1 deletion pyswarms/utils/plotters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
3D spaces.
"""

from .plotters import *
from .plotters import plot_cost_history, plot_contour, plot_surface

__all__ = ["plotters", "formatters"]
2 changes: 1 addition & 1 deletion pyswarms/utils/plotters/formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Animator(object):
You can use this class to modify options on how the animation will be run
in the :func:`pyswarms.utils.plotters.plot_contour` and
:func:`pyswarms.utils.plotters.plot_surface` methods.
.. code-block :: python
from pyswarms.utils.plotters import plot_contour
Expand Down
7 changes: 3 additions & 4 deletions pyswarms/utils/plotters/plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,14 @@

# Import modules
import logging
from collections import namedtuple

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation, cm
from mpl_toolkits.mplot3d import Axes3D

# Import from package
from .formatters import Designer, Animator, Mesher
from .formatters import Designer, Animator

# Initialize logger
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -255,10 +254,10 @@ def plot_surface(
This is useful for plotting the swarm's 2-dimensional position with
respect to the objective function. The value in the z-axis is the fitness
of the 2D particle when passed to the objective function. When preparing the
position history, make sure that the:
position history, make sure that the:
* first column is the position in the x-axis,
* second column is the position in the y-axis; and
* second column is the position in the y-axis; and
* third column is the fitness of the 2D particle
The :class:`pyswarms.utils.plotters.formatters.Mesher` class provides a
Expand Down
3 changes: 2 additions & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ scipy>=0.17.0
numpy>=1.13.0
matplotlib>=1.3.1
pytest==3.6.1
attrs==18.1.0
attrs==18.1.0
pre-commit
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
'matplotlib>=1.3.1',
'mock==2.0.0',
'pytest==3.2.1',
'attrs==18.1.0'
'attrs==18.1.0',
'pre-commit'
]

setup_requirements = [
Expand All @@ -34,7 +35,8 @@
'matplotlib>=1.3.1',
'mock==2.0.0',
'pytest==3.2.1',
'attrs==18.1.0'
'attrs==18.1.0',
'pre-commit'
]

setup(
Expand Down
17 changes: 9 additions & 8 deletions tests/backend/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@
# Import from package
from pyswarms.backend.swarms import Swarm


@pytest.fixture
def swarm():
"""A contrived instance of the Swarm class at a certain timestep"""
attrs_at_t = {
'position' : np.array([[5,5,5], [3,3,3], [1,1,1]]),
'velocity' : np.array([[1,1,1], [1,1,1], [1,1,1]]),
'current_cost' : np.array([2,2,2]),
'pbest_cost' : np.array([1,2,3]),
'pbest_pos' : np.array([[1,2,3], [4,5,6], [7,8,9]]),
'best_cost' : 1,
'best_pos' : np.array([1,1,1]),
'options' : {'c1' : 0.5, 'c2': 1, 'w': 2}
"position": np.array([[5, 5, 5], [3, 3, 3], [1, 1, 1]]),
"velocity": np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]),
"current_cost": np.array([2, 2, 2]),
"pbest_cost": np.array([1, 2, 3]),
"pbest_pos": np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
"best_cost": 1,
"best_pos": np.array([1, 1, 1]),
"options": {"c1": 0.5, "c2": 1, "w": 2},
}
return Swarm(**attrs_at_t)
44 changes: 28 additions & 16 deletions tests/backend/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
import pyswarms.backend as P


@pytest.mark.parametrize('bounds', [None, ([2,2,2], [5,5,5]), ([-1,-1,0], [2,2,5])])
@pytest.mark.parametrize('center', [1, [3,3,3], [0.2,0.2,0.1]])
@pytest.mark.parametrize(
"bounds", [None, ([2, 2, 2], [5, 5, 5]), ([-1, -1, 0], [2, 2, 5])]
)
@pytest.mark.parametrize("center", [1, [3, 3, 3], [0.2, 0.2, 0.1]])
def test_generate_swarm_return_values(bounds, center):
"""Tests if generate_swarm() returns expected values"""
pos = P.generate_swarm(n_particles=2, dimensions=3, bounds=bounds,
center=center)
pos = P.generate_swarm(
n_particles=2, dimensions=3, bounds=bounds, center=center
)
if bounds is None:
min_bounds, max_bounds = (0.0, 1.00)
else:
Expand All @@ -23,37 +26,46 @@ def test_generate_swarm_return_values(bounds, center):
upper_bound = center * np.array(max_bounds)
assert (pos <= upper_bound).all() and (pos >= lower_bound).all()


def test_generate_swarm_out_of_bounds():
"""Tests if generate_swarm() raises ValueError when initialized with the wrong value"""
bounds = ([1,1,1], [5,5,5])
init_pos = np.array([[-2,3,3], [6,8,1]])
bounds = ([1, 1, 1], [5, 5, 5])
init_pos = np.array([[-2, 3, 3], [6, 8, 1]])
with pytest.raises(ValueError):
pos = P.generate_swarm(n_particles=2, dimensions=3, bounds=bounds,
init_pos=init_pos)
pos = P.generate_swarm(
n_particles=2, dimensions=3, bounds=bounds, init_pos=init_pos
)


@pytest.mark.parametrize('binary', [False, True])
@pytest.mark.parametrize("binary", [False, True])
def test_generate_discrete_binary_swarm(binary):
"""Tests if generate_discrete_swarm(binary=True) returns expected values"""
dims = 3
pos = P.generate_discrete_swarm(n_particles=2, dimensions=dims, binary=binary)
pos = P.generate_discrete_swarm(
n_particles=2, dimensions=dims, binary=binary
)
if binary:
assert len(np.unique(pos)) <= 2 # Might generate pure 0 or 1
assert len(np.unique(pos)) <= 2 # Might generate pure 0 or 1
else:
assert (np.max(pos, axis=1) == dims - 1).all()

@pytest.mark.parametrize('init_pos', [None, np.array([[4,2,1], [1,4,6]])])

@pytest.mark.parametrize("init_pos", [None, np.array([[4, 2, 1], [1, 4, 6]])])
def test_generate_discrete_swarm(init_pos):
"""Tests if init_pos actually sets the position properly"""
dims = 3
pos = P.generate_discrete_swarm(n_particles=2, dimensions=dims, init_pos=init_pos)
pos = P.generate_discrete_swarm(
n_particles=2, dimensions=dims, init_pos=init_pos
)
if init_pos is None:
assert (np.max(pos, axis=1) == dims - 1).all()
else:
assert np.equal(pos, init_pos).all()

@pytest.mark.parametrize('clamp', [None, (0,1), (2,5), (1,6)])

@pytest.mark.parametrize("clamp", [None, (0, 1), (2, 5), (1, 6)])
def test_generate_velocity_return_values(clamp):
"""Tests if generate_velocity() returns expected values"""
min_clamp, max_clamp = (0,1) if clamp == None else clamp
min_clamp, max_clamp = (0, 1) if clamp == None else clamp
velocity = P.generate_velocity(n_particles=2, dimensions=3, clamp=clamp)
assert (velocity <= max_clamp).all() and (velocity >= min_clamp).all()
assert (velocity <= max_clamp).all() and (velocity >= min_clamp).all()
14 changes: 9 additions & 5 deletions tests/backend/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,26 @@

def test_compute_pbest_return_values(swarm):
"""Test if compute_pbest() gives the expected return values"""
expected_cost = np.array([1,2,2])
expected_pos = np.array([[1,2,3], [4,5,6], [1,1,1]])
expected_cost = np.array([1, 2, 2])
expected_pos = np.array([[1, 2, 3], [4, 5, 6], [1, 1, 1]])
pos, cost = P.compute_pbest(swarm)
assert (pos == expected_pos).all()
assert (cost == expected_cost).all()

@pytest.mark.parametrize('clamp', [None, (0,1), (-1,1)])

@pytest.mark.parametrize("clamp", [None, (0, 1), (-1, 1)])
def test_compute_velocity_return_values(swarm, clamp):
"""Test if compute_velocity() gives the expected shape and range"""
v = P.compute_velocity(swarm, clamp)
assert v.shape == swarm.position.shape
if clamp is not None:
assert (clamp[0] <= v).all() and (clamp[1] >= v).all()

@pytest.mark.parametrize('bounds', [None, ([-5,-5,-5],[5,5,5]),
([-10, -10, -10],[10, 10, 10])])

@pytest.mark.parametrize(
"bounds",
[None, ([-5, -5, -5], [5, 5, 5]), ([-10, -10, -10], [10, 10, 10])],
)
def test_compute_position_return_values(swarm, bounds):
"""Test if compute_position() gives the expected shape and range"""
p = P.compute_position(swarm, bounds)
Expand Down
Loading

0 comments on commit 71918fc

Please sign in to comment.