NiaOrg / NiaPy

Python microframework for building nature-inspired algorithms. Official docs: https://niapy.org
https://niapy.org
MIT License
258 stars 78 forks source link

ConalgTestCase related tests warnings #364

Closed sisco0 closed 2 years ago

sisco0 commented 2 years ago

While running the make test command related to #363 I found out the next warning in these tests:

niapy/tests/test_clonalg.py::ClonalgTestCase::test_custom
niapy/tests/test_clonalg.py::ClonalgTestCase::test_griewank
  /home/thebittendonut/dev/NiaPy/niapy/algorithms/basic/clonalg.py:140: RuntimeWarning: overflow encountered in exp
    mutation_rate = np.exp(self.mutation_factor * affinity[i // self.num_clones])

It would be good to ensure that we are not facing a severe bug in this test.

After reviewing these changes, I have perceived that these lines were introduced in 97de2326, as no modulus operations were had in prior versions. Could you help on this topic @zStupan? The cited warning seems to happen as we are passing a not-a-very-but-a-large-enough value into the np.exp function, which produces an overflow, the same behavior is seen when running the next command which prints the inf symbolic value:

pipenv run python3 -c "import numpy as np; print(np.exp(1140));"

Steps to reproduce make test under any commit coming from 97de2326.

git checkout 0fb2a904638377419d802f4e9f0112a1e1266fcf
make install
pipenv run pytest -k "ClonAlg"

The related CI run is linked here as well.

Expected behavior No warnings should be shown when running make test.

Actual behavior The warnings described above are shown when running make test.

System configuration

Click to view more details ```text ❯ pipenv run python3 --version; uname -a; lsb_release -a; git rev-parse --verify HEAD; pip freeze Python 3.8.10 Linux dev 5.8.0-63-generic #71-Ubuntu SMP Tue Jul 13 15:59:12 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.10 Release: 20.10 Codename: groovy 0fb2a904638377419d802f4e9f0112a1e1266fcf absl-py==1.0.0 backports.entry-points-selectable==1.1.1 brotlipy==0.7.0 CacheControl==0.12.10 cachy==0.3.0 certifi==2021.5.30 cffi @ file:///tmp/build/80754af9/cffi_1625814692085/work chardet @ file:///tmp/build/80754af9/chardet_1607706775000/work cleo==0.8.1 clikit==0.6.2 conda==4.10.3 conda-package-handling @ file:///tmp/build/80754af9/conda-package-handling_1618262147379/work crashtest==0.3.1 cryptography @ file:///tmp/build/80754af9/cryptography_1616767007030/work distlib==0.3.4 filelock==3.4.2 html5lib==1.1 idna @ file:///home/linux1/recipes/ci/idna_1610986105248/work jax==0.2.26 jeepney==0.7.1 keyring==21.8.0 lockfile==0.12.2 msgpack==1.0.3 numpy==1.20.2 opt-einsum==3.3.0 packaging==20.9 pastel==0.2.1 pexpect==4.8.0 pkginfo==1.8.2 platformdirs==2.4.1 poetry==1.1.12 poetry-core==1.0.7 ptyprocess==0.7.0 pycosat==0.6.3 pycparser @ file:///tmp/build/80754af9/pycparser_1594388511720/work pylev==1.4.0 pyOpenSSL @ file:///tmp/build/80754af9/pyopenssl_1608057966937/work pyparsing==3.0.6 PySocks @ file:///tmp/build/80754af9/pysocks_1605305812635/work requests @ file:///tmp/build/80754af9/requests_1608241421344/work requests-toolbelt==0.9.1 ruamel-yaml-conda @ file:///tmp/build/80754af9/ruamel_yaml_1616016711199/work scipy==1.7.3 SecretStorage==3.3.1 shellingham==1.4.0 six @ file:///tmp/build/80754af9/six_1623709665295/work tomlkit==0.8.0 tqdm @ file:///tmp/build/80754af9/tqdm_1625563689033/work typing_extensions==4.0.1 urllib3 @ file:///tmp/build/80754af9/urllib3_1625084269274/work virtualenv==20.10.0 webencodings==0.5.1 ```
zStupan commented 2 years ago

The clonalg implementation was ported from this ruby implementation by Jason Brownlee. The ruby implementation also produces infinite mutation rates at higher dimensions.

It's because of the way affinity is calculated. The original article proposes that for optimization purposes, the affinity is simply the value of the fitness function. Then the mutation rate is computed as exp(-rho * affinity) where rho is our mutation_factor (which should be > 0). This way the mutation rate will always be on the interval [0, 1]. It will move towards 0, the higher the affinity (fitness), and towards 1 the lower the affinity, so the inequality in the mutation method should also be flipped.

https://github.com/NiaOrg/NiaPy/blob/30c9d5332f9f743cbe6d49d08c3c843fb5c37d5e/niapy/algorithms/basic/clonalg.py#L129-L132

Line 130 should be flip = self.random(bitstring.shape) > mutation_rate, that way, the larger the fitness the more chance there will be for a bit to be flipped.