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

Fix bug in topology classes #176

Merged
merged 1 commit into from
Jul 23, 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
2 changes: 1 addition & 1 deletion pyswarms/backend/topology/pyramid.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def compute_gbest(self, swarm):
# Obtain best cost and position
best_cost = np.min(swarm.pbest_cost[best_neighbor])
best_pos = swarm.pbest_pos[
np.argmin(swarm.pbest_cost[best_neighbor])
best_neighbor[np.argmin(swarm.pbest_cost[best_neighbor])]
]
except AttributeError:
msg = "Please pass a Swarm class. You passed {}".format(
Expand Down
7 changes: 2 additions & 5 deletions pyswarms/backend/topology/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def compute_gbest(self, swarm, k):
# Obtain best cost and position
best_cost = np.min(swarm.pbest_cost[best_neighbor])
best_pos = swarm.pbest_pos[
np.argmin(swarm.pbest_cost[best_neighbor])
best_neighbor[np.argmin(swarm.pbest_cost[best_neighbor])]
]

except AttributeError:
Expand Down Expand Up @@ -169,9 +169,6 @@ def __compute_neighbors(self, swarm, k):
graph needs edges to change it to a connected
graph.

.. note:: If the graph isn't connected, it is possible that the
PSO algorithm does not find the best position within
the swarm.

Parameters
----------
Expand Down Expand Up @@ -206,7 +203,7 @@ def __compute_neighbors(self, swarm, k):
# Generate connected graph.
while connected_components(adj_matrix, directed=False, return_labels=False) != 1:
for i, j in itertools.product(range(swarm.n_particles), repeat=2):
if dist_matrix[i][j] == 0:
if dist_matrix[i][j] == np.inf:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the bug in the Random class right? 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right 👍

adj_matrix[i][j] = 1

return adj_matrix
4 changes: 2 additions & 2 deletions pyswarms/backend/topology/ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ def compute_gbest(self, swarm, p, k):
if k == 1:
# The minimum index is itself, no mapping needed.
best_neighbor = swarm.pbest_cost[self.neighbor_idx][:, np.newaxis].argmin(
axis=1
axis=0
)
else:
idx_min = swarm.pbest_cost[self.neighbor_idx].argmin(axis=1)
best_neighbor = self.neighbor_idx[np.arange(len(self.neighbor_idx)), idx_min]
# Obtain best cost and position
best_cost = np.min(swarm.pbest_cost[best_neighbor])
best_pos = swarm.pbest_pos[
np.argmin(swarm.pbest_cost[best_neighbor])
best_neighbor[np.argmin(swarm.pbest_cost[best_neighbor])]
]
except AttributeError:
msg = "Please pass a Swarm class. You passed {}".format(
Expand Down
52 changes: 37 additions & 15 deletions tests/backend/topology/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,42 @@
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([[9.95838686e-01, 5.87433429e-04, 6.49113772e-03],
[1.00559609e+00, 3.96477697e-02, 7.67205397e-01],
[2.87990950e-01, -3.64932609e-02, 1.89750725e-02],
[1.11646877e+00, 3.12037361e-03, 1.97885369e-01],
[8.96117216e-01, -9.79602053e-03, -1.66139336e-01],
[9.90423669e-01, 1.99307974e-03, -1.23386797e-02],
[2.06800701e-01, -1.67869387e-02, 1.14268810e-01],
[4.21786494e-01, 2.58755510e-02, 6.62254843e-01],
[9.90350831e-01, 3.81575154e-03, 8.80833545e-01],
[9.94353749e-01, -4.85086205e-02, 9.85313500e-03]]),
"velocity": np.array([[2.09076818e-02, 2.04936403e-03, 1.06761248e-02],
[1.64940497e-03, 5.67924469e-03, 9.74902301e-02],
[1.50445516e-01, 9.11699158e-03, 1.51474794e-02],
[2.94238740e-01, 5.71545680e-04, 1.54122294e-02],
[4.10430034e-02, 6.51847479e-04, 6.25109226e-02],
[6.71076116e-06, 1.89615516e-04, 4.65023770e-03],
[4.76081378e-02, 4.24416089e-03, 7.11856172e-02],
[1.33832808e-01, 1.81818698e-02, 1.16947941e-01],
[1.22849955e-03, 1.55685312e-03, 1.67819003e-02],
[5.60617396e-03, 4.31819608e-02, 2.52217220e-02]]),
"current_cost": np.array([1.07818462, 5.5647911, 19.6046078, 14.05300016, 3.72597614, 1.01169386,
16.51846203, 32.72262829, 3.80274901, 1.05237138]),
"pbest_cost": np.array([1.00362006, 2.39151041, 2.55208424, 5.00176207, 1.04510827, 1.00025284,
6.31216654, 2.53873121, 2.00530884, 1.05237138]),
"pbest_pos": np.array([[9.98033031e-01, 4.97392619e-03, 3.07726256e-03],
[1.00665809e+00, 4.22504014e-02, 9.84334657e-01],
[1.12159389e-02, 1.11429739e-01, 2.86388193e-02],
[1.64059236e-01, 6.85791237e-03, -2.32137604e-02],
[9.93740665e-01, -6.16501403e-03, -1.46096578e-02],
[9.90438476e-01, 2.50379538e-03, 1.87405987e-05],
[1.12301876e-01, 1.77099784e-03, 1.45382457e-01],
[4.41204876e-02, 4.84059652e-02, 1.05454822e+00],
[9.89348409e-01, -1.31692358e-03, 9.88291764e-01],
[9.99959923e-01, -5.32665972e-03, -1.53685870e-02]]),
"best_cost": 1.0002528364353296,
"best_pos": np.array([9.90438476e-01, 2.50379538e-03, 1.87405987e-05]),
"options": {'c1': 0.5, 'c2': 0.3, 'w': 0.9},
}
return Swarm(**attrs_at_t)


@pytest.fixture(scope="module")
def k():
"""Default neighbor number"""
_k = 1
return _k
8 changes: 4 additions & 4 deletions tests/backend/topology/test_pyramid.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
def test_compute_gbest_return_values(swarm, static):
"""Test if compute_gbest() gives the expected return values"""
topology = Pyramid(static=static)
expected_cost = 1
expected_pos = np.array([1, 2, 3])
expected_cost = 1.0002528364353296
expected_pos = np.array([9.90438476e-01, 2.50379538e-03, 1.87405987e-05])
pos, cost = topology.compute_gbest(swarm)
assert cost == expected_cost
assert (pos == expected_pos).all()
assert cost == pytest.approx(expected_cost)
assert (pos == pytest.approx(expected_pos))


@pytest.mark.parametrize("static", [True, False])
Expand Down
21 changes: 16 additions & 5 deletions tests/backend/topology/test_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ def test_update_gbest_neighborhood(swarm, k, static):
"""Test if update_gbest_neighborhood gives the expected return values"""
topology = Random(static=static)
pos, cost = topology.compute_gbest(swarm, k=k)
expected_pos = np.array([1, 2, 3])
expected_cost = 1
assert (pos == expected_pos).all()
assert cost == expected_cost
expected_pos = np.array([9.90438476e-01, 2.50379538e-03, 1.87405987e-05])
expected_cost = 1.0002528364353296
assert cost == pytest.approx(expected_cost)
assert (pos == pytest.approx(expected_pos))


@pytest.mark.parametrize("static", [True, False])
Expand Down Expand Up @@ -57,16 +57,27 @@ def test_compute_neighbors_return_values(swarm, k, static):


@pytest.mark.parametrize("static", [True, False])
@pytest.mark.parametrize("k", [1])
def test_compute_neighbors_adjacency_matrix(swarm, k, static):
"""Test if __compute_neighbors() gives the expected matrix"""
np.random.seed(1)
topology = Random(static=static)
adj_matrix = topology._Random__compute_neighbors(swarm, k)
comparison_matrix = np.array([[1, 1, 0], [1, 1, 1], [0, 1, 1]])
comparison_matrix = np.array([[1, 1, 1, 0, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 0, 0, 0, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 0, 1, 1, 0, 1, 0, 1],
[0, 1, 1, 0, 1, 0, 1, 0, 1, 1],
[0, 1, 1, 0, 1, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 1, 0, 1, 1, 1, 0],
[1, 1, 1, 0, 1, 1, 1, 0, 0, 1]])
assert np.allclose(adj_matrix, comparison_matrix, atol=1e-8)


@pytest.mark.parametrize("static", [True, False])
@pytest.mark.parametrize("k", [1])
def test_neighbor_idx(swarm, k, static):
"""Test if the neighbor_idx attribute is assigned"""
topology = Random(static=static)
Expand Down
10 changes: 5 additions & 5 deletions tests/backend/topology/test_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ def test_update_gbest_neighborhood(swarm, p, k, static):
"""Test if update_gbest_neighborhood gives the expected return values"""
topology = Ring(static=static)
pos, cost = topology.compute_gbest(swarm, p=p, k=k)
expected_pos = np.array([1, 2, 3])
expected_cost = 1
assert (pos == expected_pos).all()
assert cost == expected_cost
expected_pos = np.array([9.90438476e-01, 2.50379538e-03, 1.87405987e-05])
expected_cost = 1.0002528364353296
assert cost == pytest.approx(expected_cost)
assert (pos == pytest.approx(expected_pos))


@pytest.mark.parametrize("static", [True, False])
Expand Down Expand Up @@ -50,7 +50,7 @@ def test_compute_position_return_values(swarm, bounds, static):
@pytest.mark.parametrize("static", [True, False])
@pytest.mark.parametrize("k", [1, 2, 3])
@pytest.mark.parametrize("p", [1, 2])
def test_neighbor_idx(swarm, static, p , k):
def test_neighbor_idx(swarm, static, p, k):
"""Test if the neighbor_idx attribute is assigned"""
topology = Ring(static=static)
p = topology.compute_gbest(swarm, p=p, k=k)
Expand Down
8 changes: 4 additions & 4 deletions tests/backend/topology/test_star.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
def test_compute_gbest_return_values(swarm):
"""Test if compute_gbest() gives the expected return values"""
topology = Star()
expected_cost = 1
expected_pos = np.array([1, 2, 3])
expected_cost = 1.0002528364353296
expected_pos = np.array([9.90438476e-01, 2.50379538e-03, 1.87405987e-05])
pos, cost = topology.compute_gbest(swarm)
assert cost == expected_cost
assert (pos == expected_pos).all()
assert cost == pytest.approx(expected_cost)
assert (pos == pytest.approx(expected_pos))


@pytest.mark.parametrize("clamp", [None, (0, 1), (-1, 1)])
Expand Down