diff --git a/pyswarms/backend/topology/pyramid.py b/pyswarms/backend/topology/pyramid.py index 3d618e82..86c2fee8 100644 --- a/pyswarms/backend/topology/pyramid.py +++ b/pyswarms/backend/topology/pyramid.py @@ -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( diff --git a/pyswarms/backend/topology/random.py b/pyswarms/backend/topology/random.py index d53cdd97..f03f6ed4 100644 --- a/pyswarms/backend/topology/random.py +++ b/pyswarms/backend/topology/random.py @@ -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: @@ -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 ---------- @@ -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: adj_matrix[i][j] = 1 return adj_matrix diff --git a/pyswarms/backend/topology/ring.py b/pyswarms/backend/topology/ring.py index 3f1ed440..3c6e2018 100644 --- a/pyswarms/backend/topology/ring.py +++ b/pyswarms/backend/topology/ring.py @@ -72,7 +72,7 @@ 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) @@ -80,7 +80,7 @@ def compute_gbest(self, swarm, p, 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: msg = "Please pass a Swarm class. You passed {}".format( diff --git a/tests/backend/topology/conftest.py b/tests/backend/topology/conftest.py index d4e5e199..4aade1b1 100644 --- a/tests/backend/topology/conftest.py +++ b/tests/backend/topology/conftest.py @@ -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 diff --git a/tests/backend/topology/test_pyramid.py b/tests/backend/topology/test_pyramid.py index bd8bf359..dc0b1ced 100644 --- a/tests/backend/topology/test_pyramid.py +++ b/tests/backend/topology/test_pyramid.py @@ -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]) diff --git a/tests/backend/topology/test_random.py b/tests/backend/topology/test_random.py index d1ba10c4..15872897 100644 --- a/tests/backend/topology/test_random.py +++ b/tests/backend/topology/test_random.py @@ -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]) @@ -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) diff --git a/tests/backend/topology/test_ring.py b/tests/backend/topology/test_ring.py index eb776a7a..8f3366fc 100644 --- a/tests/backend/topology/test_ring.py +++ b/tests/backend/topology/test_ring.py @@ -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]) @@ -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) diff --git a/tests/backend/topology/test_star.py b/tests/backend/topology/test_star.py index d47dd5d1..aab347a3 100644 --- a/tests/backend/topology/test_star.py +++ b/tests/backend/topology/test_star.py @@ -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)])