ljvmiranda921/pyswarms

best_pos would always be np.ndarray([]) when objective function return array with all being 'inf'

LuoYuanzhen opened this issue · 2 comments

Describe the bug
When objective function returns a ndarray with all 'inf' like [inf, inf, ..., inf], the attribute 'best_pos' of Swarm would still be the default value np.ndarray([]). It seems that the intial swarm particle's loss is all inf or nan causes the bug.

To Reproduce
A simple test code can reproduce it:

def f(pos):
    return np.full(pos.shape[0], np.inf)
def test_pso():
    options = {'c1': 0.5, 'c2': 0.3, 'w': 0.9}
    optimizer = ps.single.GlobalBestPSO(n_particles=100, dimensions=55, options=options)
    optimizer.optimize(f, iters=100)

run test_pso(), I got a Traceback of ValueError:

"Traceback (most recent call last):
File "/test/test_evo.py", line 58, in
test_pso2()
File "/test/test_evo.py", line 44, in test_pso2
optimizer.optimize(f, iters=100)
File "/anaconda3/envs/pytorch-gpu/lib/python3.9/site-packages/pyswarms/single/global_best.py", line 243, in optimize
self.swarm.velocity = self.top.compute_velocity(
File "/anaconda3/envs/pytorch-gpu/lib/python3.9/site-packages/pyswarms/backend/topology/star.py", line 133, in compute_velocity
return ops.compute_velocity(swarm, clamp, vh, bounds=bounds)
File "/anaconda3/envs/pytorch-gpu/lib/python3.9/site-packages/pyswarms/backend/operators.py", line 140, in compute_velocity
* (swarm.best_pos - swarm.position)
ValueError: operands could not be broadcast together with shapes (0,) (100,55)"

Expected behavior
Expected that when objective function returns all inf or nan, just simply set the "best_pos" as like position[0].

Environment (please complete the following information):

  • OS: [Linux]
  • Version [Ubuntu 18.04]
  • PySwarms Version [v.3.4.2]
  • Python Version [3.9]

Additional context
I guess just simply change

if np.min(swarm.pbest_cost) < swarm.best_cost:

as

if np.min(swarm.pbest_cost) <= swarm.best_cost:

might be worked.

It seems, in the case where the objective function returns np.inf everywhere, that a lack of a best position would be the expected behavior. If a best position is actually set, that would imply that a best position could be found by the algorithm, which in this case it can not (as everywhere it samples it gets results it cannot understand).

Simply using a <= instead of a < would imply that a best position could be found, and also would not work, as while np.inf <= np.inf returns True, if the objective function were to return nan, np.nan <= np.inf returns False.

I think a better solution would be to simply add a check for if the size of the best_pos array is 0 in ops.compute_velocity. I can probably implement this fairly easily, if that seems like a good solution.

stale commented

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.