esa / pagmo2

A C++ platform to perform parallel computations of optimisation tasks (global and local) via the asynchronous generalized island model.
https://esa.github.io/pagmo2/
GNU General Public License v3.0
808 stars 160 forks source link

[BUG] gaco hangs when initial population is outside bounds #493

Open jschueller opened 2 years ago

jschueller commented 2 years ago

when some points of the initial population are outside the bounds and the objective tend to make it go outside, gaco can hang:

#include <pagmo/algorithms/gaco.hpp>
#include <pagmo/population.hpp>
#include <pagmo/problems/rosenbrock.hpp>

using namespace pagmo;

struct problem1 {
    vector_double fitness(const vector_double &x) const
    {
        return {x[1]};
    }
    std::pair<vector_double, vector_double> get_bounds() const
    {
        return {{-1.5, -1.5}, {1.5, 1.5}};
    }
    vector_double::size_type get_nobj() const
    {
        return 1;
    }
};

int main()
{
  try {
    problem prob{problem1{}};

    population pop1{prob, 0, 0};
    int size = 100;
//     std::uniform_real_distribution<double> unif(-1.5, 1.5); // OK
    std::uniform_real_distribution<double> unif(-3., 3.);  // FREEZE
    std::default_random_engine re;
    for (int i=0; i<size; ++i)
    {
      vector_double x(2);
      x[0] = unif(re);
      x[1] = unif(re);
      pop1.push_back(x);
    }

    gaco user_algo1{10u};
    pop1 = user_algo1.evolve(pop1);

    }
    catch(const std::exception & exc) {
        std::cout << "ex="<<exc.what() <<std::endl;
        return 2;
    }
    return 0;
}

more generally, do we have to check is the population is inside the bounds before calling pagmo, or do the algorithms will manage to "jump" inside the bounds ?

bluescarni commented 2 years ago

Any idea @Sceki ?

more generally, do we have to check is the population is inside the bounds before calling pagmo, or do the algorithms will manage to "jump" inside the bounds ?

As I wrote in the other thread, what happens with out-of-bounds conditions is algorithm-dependent. But in any case it should never lead to a hang/crash, and if it does it's a bug.

Sceki commented 2 years ago

I believe that the problem is that this while loop can be endless in case the initial population is out of bounds: https://github.com/esa/pagmo2/blob/master/src/algorithms/gaco.cpp#L855.

I think there are two possibilities: either we avoid the while loop (i.e., the re-sampling until we satisfy the bounds) for the case in which the user decides that out-of-bounds solutions are acceptable, or we simply do not accept initial populations that are out of bounds. In the former case, we would need to add a boolean flag (similar to the cmaes force_boundsone) and skip that while loop (i.e., the re-sampling) in case that is set to true.

I am a bit busy these days, but I will try to fix it with a PR as soon as possible..

jschueller commented 2 years ago

yes, a simple throw to reject initial populations out of bounds would be the simplest

bluescarni commented 2 years ago

I believe that the problem is that this while loop can be endless in case the initial population is out of bounds: https://github.com/esa/pagmo2/blob/master/src/algorithms/gaco.cpp#L855.

I think there are two possibilities: either we avoid the while loop (i.e., the re-sampling until we satisfy the bounds) for the case in which the user decides that out-of-bounds solutions are acceptable, or we simply do not accept initial populations that are out of bounds. In the former case, we would need to add a boolean flag (similar to the cmaes force_boundsone) and skip that while loop (i.e., the re-sampling) in case that is set to true.

I am a bit busy these days, but I will try to fix it with a PR as soon as possible..

Cheers!

Do you think it helps algorithmic performance to allow for out-of-bounds individuals? If you think it does not, then I'd personally be more in favour of throwing, rather than adding another configuration parameter.

Sceki commented 2 years ago

Indeed, another configuration parameter seems a bit too much, and if the bounds are chosen wide enough the performance should be the same, so I will just throw I guess :)