diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml deleted file mode 100644 index ed1dee6..0000000 --- a/.github/workflows/python-app.yml +++ /dev/null @@ -1,36 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: FireflyAlgorithm - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: "3.9" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 pytest numpy - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test with pytest - run: | - pytest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..493457e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,53 @@ +name: fireflyalgorithm + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ['3.9', '3.10', '3.11', '3.12'] + defaults: + run: + shell: bash + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Get full Python version + id: full-python-version + run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") + - name: Install poetry + run: | + curl -sL https://install.python-poetry.org | python - -y + - name: Update path + if: ${{ matrix.os != 'windows-latest' }} + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Update Windows path + if: ${{ matrix.os == 'windows-latest' }} + run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH + - name: Configure poetry + run: poetry config virtualenvs.in-project true + - name: Set up cache + uses: actions/cache@v3 + id: cache + with: + path: .venv + key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + - name: Ensure cache is healthy + if: steps.cache.outputs.cache-hit == 'true' + run: timeout 10s poetry run pip --version || rm -rf .venv + - name: Install dependencies + run: poetry install + - name: Run tests + run: poetry run pytest diff --git a/CHANGELOG.md b/CHANGELOG.md index af1306e..18d1380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.3.4](https://github.com/firefly-cpp/FireflyAlgorithm/tree/0.3.4) (2022-12-13) + +[Full Changelog](https://github.com/firefly-cpp/FireflyAlgorithm/compare/0.3.3...0.3.4) + +**Merged pull requests:** + +- logo add [\#10](https://github.com/firefly-cpp/FireflyAlgorithm/pull/10) ([rhododendrom](https://github.com/rhododendrom)) + +## [0.3.3](https://github.com/firefly-cpp/FireflyAlgorithm/tree/0.3.3) (2022-10-31) + +[Full Changelog](https://github.com/firefly-cpp/FireflyAlgorithm/compare/0.3.2...0.3.3) + ## [0.3.2](https://github.com/firefly-cpp/FireflyAlgorithm/tree/0.3.2) (2022-07-12) [Full Changelog](https://github.com/firefly-cpp/FireflyAlgorithm/compare/0.3.1...0.3.2) diff --git a/LICENSE b/LICENSE index 0500760..0d39b71 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 firefly-cpp +Copyright (c) 2017-2023 firefly-cpp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 48d016f..8516155 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/fireflyalgorithm.svg) ![PyPI - Downloads](https://img.shields.io/pypi/dm/fireflyalgorithm.svg) [![Downloads](https://pepy.tech/badge/fireflyalgorithm)](https://pepy.tech/project/fireflyalgorithm) +[![AUR package](https://img.shields.io/aur/version/python-fireflyalgorithm?color=blue&label=Arch%20Linux&logo=arch-linux)](https://aur.archlinux.org/packages/python-fireflyalgorithm) [![GitHub license](https://img.shields.io/github/license/firefly-cpp/FireflyAlgorithm.svg)](https://github.com/firefly-cpp/FireflyAlgorithm/blob/master/LICENSE) ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/firefly-cpp/FireflyAlgorithm.svg) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/firefly-cpp/FireflyAlgorithm.svg)](http://isitmaintained.com/project/firefly-cpp/FireflyAlgorithm "Average time to resolve an issue") @@ -24,6 +25,7 @@ This package implements a nature-inspired algorithm for optimization called Fire ## Installation: +Install FireflyAlgorithm with pip: ```sh pip install fireflyalgorithm ``` @@ -31,15 +33,16 @@ To install FireflyAlgorithm on Fedora, use: ```sh dnf install python-fireflyalgorithm ``` +To install FireflyAlgorithm on Arch Linux, please use an [AUR helper](https://wiki.archlinux.org/title/AUR_helpers): +```sh +$ yay -Syyu python-fireflyalgorithm +``` ## Usage: ```python -import numpy as np from fireflyalgorithm import FireflyAlgorithm - -def sphere(x): - return np.sum(x ** 2) +from fireflyalgorithm.problems import sphere FA = FireflyAlgorithm() best = FA.run(function=sphere, dim=10, lb=-5, ub=5, max_evals=10000) @@ -47,6 +50,42 @@ best = FA.run(function=sphere, dim=10, lb=-5, ub=5, max_evals=10000) print(best) ``` +### Command line interface + +The package also comes with a simple command line interface which allows you to evaluate the algorithm on several +popular test functions + +```shell +firefly-algorithm -h +``` + +```text +usage: firefly-algorithm [-h] --problem PROBLEM -d DIMENSION -l LOWER -u UPPER -nfes MAX_EVALS [-r RUNS] [--pop-size POP_SIZE] [--alpha ALPHA] [--beta-min BETA_MIN] [--gamma GAMMA] [--seed SEED] + +Evaluate the Firefly Algorithm on one or more test functions + +options: + -h, --help show this help message and exit + --problem PROBLEM Test problem to evaluate + -d DIMENSION, --dimension DIMENSION + Dimension of the problem + -l LOWER, --lower LOWER + Lower bounds of the problem + -u UPPER, --upper UPPER + Upper bounds of the problem + -nfes MAX_EVALS, --max-evals MAX_EVALS + Max number of fitness function evaluations + -r RUNS, --runs RUNS Number of runs of the algorithm + --pop-size POP_SIZE Population size + --alpha ALPHA Randomness strength + --beta-min BETA_MIN Attractiveness constant + --gamma GAMMA Absorption coefficient + --seed SEED Seed for the random number generator +``` + +**Note:** The CLI script can also run as a python module (python -m niaarm ...) + + ## Reference Papers: I. Fister Jr., X.-S. Yang, I. Fister, J. Brest. [Memetic firefly algorithm for combinatorial optimization](http://www.iztok-jr-fister.eu/static/publications/44.pdf) in Bioinspired Optimization Methods and their Applications (BIOMA 2012), B. Filipic and J.Silc, Eds. diff --git a/examples/run.py b/examples/run.py index 8597751..645070a 100644 --- a/examples/run.py +++ b/examples/run.py @@ -1,9 +1,5 @@ -import numpy as np from fireflyalgorithm import FireflyAlgorithm - - -def sphere(x): - return np.sum(x ** 2) +from fireflyalgorithm.problems import sphere FA = FireflyAlgorithm() diff --git a/fireflyalgorithm/__init__.py b/fireflyalgorithm/__init__.py index 48f3ef7..627a2d6 100644 --- a/fireflyalgorithm/__init__.py +++ b/fireflyalgorithm/__init__.py @@ -1,5 +1,5 @@ from fireflyalgorithm.fireflyalgorithm import FireflyAlgorithm -__all__ = ['FireflyAlgorithm'] +__all__ = ["FireflyAlgorithm"] -__version__ = '0.3.4' +__version__ = "0.4.0" diff --git a/fireflyalgorithm/__main__.py b/fireflyalgorithm/__main__.py new file mode 100644 index 0000000..75c1ac9 --- /dev/null +++ b/fireflyalgorithm/__main__.py @@ -0,0 +1,6 @@ +import sys +from fireflyalgorithm import cli + + +if __name__ == "__main__": + sys.exit(cli.main()) diff --git a/fireflyalgorithm/cli.py b/fireflyalgorithm/cli.py new file mode 100644 index 0000000..b08d4fd --- /dev/null +++ b/fireflyalgorithm/cli.py @@ -0,0 +1,79 @@ +import argparse +import numpy as np +from fireflyalgorithm.problems import PROBLEMS, get_problem +from fireflyalgorithm.fireflyalgorithm import FireflyAlgorithm + + +def get_parser(): + parser = argparse.ArgumentParser( + prog="firefly-algorithm", + description="Evaluate the Firefly Algorithm on one or more test functions", + ) + + problem_functions = list(PROBLEMS.keys()) + parser.add_argument( + "--problem", + type=str, + required=True, + choices=problem_functions, + metavar="PROBLEM", + help="Test problem to evaluate", + ) + parser.add_argument( + "-d", "--dimension", type=int, required=True, help="Dimension of the problem" + ) + parser.add_argument( + "-l", "--lower", type=float, required=True, help="Lower bounds of the problem" + ) + parser.add_argument( + "-u", "--upper", type=float, required=True, help="Upper bounds of the problem" + ) + parser.add_argument( + "-nfes", + "--max-evals", + type=int, + required=True, + help="Max number of fitness function evaluations", + ) + parser.add_argument( + "-r", "--runs", type=int, default=1, help="Number of runs of the algorithm" + ) + parser.add_argument("--pop-size", type=int, default=20, help="Population size") + parser.add_argument("--alpha", type=float, default=1.0, help="Randomness strength") + parser.add_argument( + "--beta-min", type=float, default=1.0, help="Attractiveness constant" + ) + parser.add_argument( + "--gamma", type=float, default=0.01, help="Absorption coefficient" + ) + parser.add_argument("--seed", type=int, help="Seed for the random number generator") + return parser + + +def main(): + parser = get_parser() + args = parser.parse_args() + + algorithm = FireflyAlgorithm( + args.pop_size, args.alpha, args.beta_min, args.gamma, args.seed + ) + problem = get_problem(args.problem) + dim = args.dimension + lb = args.lower + ub = args.upper + max_evals = args.max_evals + runs = args.runs + + fitness = np.empty(runs) + for i in range(runs): + fitness[i] = algorithm.run(problem, dim, lb, ub, max_evals) + + if runs == 1: + print(f"Best fitness: {fitness[0]}") + else: + print(f"Best: {fitness.min()}") + print(f"Worst: {fitness.max()}") + print(f"Mean: {fitness.mean()}") + print(f"Std: {fitness.std()}") + + return 0 diff --git a/fireflyalgorithm/problems.py b/fireflyalgorithm/problems.py new file mode 100644 index 0000000..20a412d --- /dev/null +++ b/fireflyalgorithm/problems.py @@ -0,0 +1,270 @@ +import numpy as np + + +def ackley(x): + a = 20 + b = 0.2 + c = 2 * np.pi + dim = len(x) + + val1 = np.sum(np.square(x)) + val2 = np.sum(np.cos(c * x)) + + temp1 = -b * np.sqrt(val1 / dim) + temp2 = val2 / dim + + return -a * np.exp(temp1) - np.exp(temp2) + a + np.exp(1) + + +def alpine1(x): + return np.sum(np.abs(np.sin(x) + 0.1 * x)) + + +def alpine2(x): + return np.prod(np.sqrt(x) * np.sin(x)) + + +def cigar(x): + return x[0] ** 2 + 1000000 * np.sum(x[1:] ** 2) + + +def cosine_mixture(x): + return -0.1 * np.sum(np.cos(5 * np.pi * x)) - np.sum(x**2) + + +def csendes(x): + mask = x != 0 + return np.sum(np.power(x[mask], 6) * (2 + np.sin(1 / x[mask]))) + + +def dixon_price(x): + dim = len(x) + indices = np.arange(2, dim) + val = np.sum(indices * (2 * x[2:] ** 2 - x[1 : dim - 1]) ** 2) + return (x[0] - 1) ** 2 + val + + +def griewank(x): + dim = len(x) + i = np.arange(1, dim + 1) + val1 = np.sum(x**2 / 4000) + val2 = np.prod(np.cos(x / np.sqrt(i))) + return val1 - val2 + 1 + + +def katsuura(x): + dim = len(x) + k = np.atleast_2d(np.arange(1, 33)).T + i = np.arange(0, dim * 1) + inner = np.round(2**k * x) * (2.0 ** (-k)) + return np.prod(np.sum(inner, axis=0) * (i + 1) + 1) + + +def levy(x): + w = 1 + (x - 1) / 4 + wi = w[:-1] + term1 = np.sin(np.pi * w[0]) ** 2 + term2 = np.sum((wi - 1) ** 2 * (1 + 10 * np.sin(np.pi * wi + 1))) + term3 = (w[-1] - 1) ** 2 * (1 + np.sin(2 * np.pi * w[-1]) ** 2) + return term1 + term2 + term3 + + +def michalewicz(x): + dim = len(x) + m = 10 + i = np.arange(1, dim + 1) + return -np.sum(np.sin(x) * np.sin(i * x**2 / np.pi) ** (2 * m)) + + +def perm1(x): + dim = len(x) + beta = 0.5 + k = np.atleast_2d(np.arange(dim) + 1).T + j = np.atleast_2d(np.arange(dim) + 1) + s = (j**k + beta) * ((x / j) ** k - 1) + return np.sum(np.sum(s, axis=1) ** 2) + + +def perm2(x): + dim = len(x) + beta = 10 + k = np.atleast_2d(np.arange(dim) + 1).T + j = np.atleast_2d(np.arange(dim) + 1) + s = (j + beta) * (x**k - (1 / j) ** k) + return np.sum(np.sum(s, axis=1) ** 2) + + +def pinter(x): + dim = len(x) + x = np.asarray(x) + sub = np.roll(x, 1) + add = np.roll(x, -1) + indices = np.arange(1, dim + 1) + + a = sub * np.sin(x) + np.sin(add) + b = (sub * sub) - 2 * x + 3 * add - np.cos(x) + 1 + + val1 = np.sum(indices * x * x) + val2 = np.sum(20 * indices * np.power(np.sin(a), 2)) + val3 = np.sum(indices * np.log10(1 + indices * np.power(b, 2))) + + return val1 + val2 + val3 + + +def powell(x): + x1 = x[0::4] + x2 = x[1::4] + x3 = x[2::4] + x4 = x[3::4] + + term1 = (x1 + 10 * x2) ** 2 + term2 = 5 * (x3 - x4) ** 2 + term3 = (x2 - 2 * x3) ** 4 + term4 = 10 * (x1 - x4) ** 4 + return np.sum(term1 + term2 + term3 + term4) + + +def quing(x): + dim = len(x) + return np.sum(np.power(x**2 - np.arange(1, dim + 1), 2)) + + +def quintic(x): + return np.sum(np.abs(x**5 - 3 * x**4 + 4 * x**3 + 2 * x**2 - 10 * x - 4)) + + +def rastrigin(x): + dim = len(x) + return 10 * dim + np.sum(x**2 - 10 * np.cos(2 * np.pi * x)) + + +def rosenbrock(x): + return np.sum(100.0 * (x[1:] - x[:-1] ** 2) ** 2 + (1 - x[:-1]) ** 2, axis=0) + + +def salomon(x): + val = np.sqrt(np.sum(x**2)) + return 1 - np.cos(2 * np.pi * val) + 0.1 * val + + +def schaffer2(x): + return ( + 0.5 + + (np.sin(x[0] ** 2 - x[1] ** 2) ** 2 - 0.5) + / (1 + 0.001 * (x[0] ** 2 + x[1] ** 2)) ** 2 + ) + + +def schaffer4(x): + return ( + 0.5 + + (np.cos(np.sin(x[0] ** 2 - x[1] ** 2)) ** 2 - 0.5) + / (1 + 0.001 * (x[0] ** 2 + x[1] ** 2)) ** 2 + ) + + +def schwefel(x): + dim = len(x) + return 418.982887272433799807913601398 * dim - np.sum( + x * np.sin(np.sqrt(np.abs(x))) + ) + + +def schwefel21(x): + return np.amax(np.abs(x)) + + +def schwefel22(x): + return np.sum(np.abs(x)) + np.prod(np.abs(x)) + + +def sphere(x): + return np.sum(x**2) + + +def step(x): + return np.sum(np.floor(np.abs(x))) + + +def step2(x): + return np.sum(np.floor(x + 0.5) ** 2) + + +def styblinski_tang(x): + return 0.5 * np.sum(x**4 - 16 * x**2 + 5 * x) + + +def trid(x): + sum1 = np.sum((x - 1) ** 2) + sum2 = np.sum(x[1:] * x[:-1]) + return sum1 - sum2 + + +def weierstrass(x): + dim = len(x) + kmax = 20 + a = 0.5 + b = 3 + + k = np.atleast_2d(np.arange(kmax + 1)).T + t1 = a**k * np.cos(2 * np.pi * b**k * (x + 0.5)) + t2 = dim * np.sum(a**k.T * np.cos(np.pi * b**k.T)) + + return np.sum(np.sum(t1, axis=0)) - t2 + + +def whitley(x): + xi = x + xj = np.atleast_2d(x).T + + temp = 100 * ((xi**2) - xj) + (1 - xj) ** 2 + inner = (temp**2 / 4000) - np.cos(temp) + 1 + return np.sum(np.sum(inner, axis=0)) + + +def zakharov(x): + dim = len(x) + sum1 = np.sum(x**2) + sum2 = 0.5 * np.sum(np.arange(1, dim + 1) * x) + return sum1 + sum2**2 + sum2**4 + + +PROBLEMS = { + "ackley": ackley, + "alpine1": alpine1, + "alpine2": alpine2, + "cigar": cigar, + "cosine_mixture": cosine_mixture, + "csendes": csendes, + "dixon_price": dixon_price, + "griewank": griewank, + "katsuura": katsuura, + "levy": levy, + "michalewicz": michalewicz, + "perm1": perm1, + "perm2": perm2, + "pinter": pinter, + "powell": powell, + "quing": quing, + "quintic": quintic, + "rastrigin": rastrigin, + "rosenbrock": rosenbrock, + "salomon": salomon, + "schaffer2": schaffer2, + "schaffer4": schaffer4, + "schwefel": schwefel, + "schwefel21": schwefel21, + "schwefel22": schwefel22, + "sphere": sphere, + "step": step, + "step2": step2, + "styblinski_tang": styblinski_tang, + "trid": trid, + "weierstrass": weierstrass, + "whitley": whitley, + "zakharov": zakharov, +} + + +def get_problem(name): + return PROBLEMS[name] diff --git a/poetry.lock b/poetry.lock index 883a10b..0bf4182 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,226 +1,142 @@ -[[package]] -name = "attrs" -version = "22.1.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -tests_no_zope = ["cloudpickle", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] -tests = ["cloudpickle", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] -docs = ["sphinx-notfound-page", "zope.interface", "sphinx", "furo"] -dev = ["cloudpickle", "pre-commit", "sphinx-notfound-page", "sphinx", "furo", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "exceptiongroup" -version = "1.0.0" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] [package.extras] test = ["pytest (>=6)"] -[[package]] -name = "importlib-metadata" -version = "5.0.0" -description = "Read metadata from Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "jaraco.tidelift (>=1.4)"] -perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] - [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = "*" - -[[package]] -name = "numpy" -version = "1.21.6" -description = "NumPy is the fundamental package for array computing with Python." -category = "main" -optional = false -python-versions = ">=3.7,<3.11" +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "numpy" -version = "1.23.4" -description = "NumPy is the fundamental package for array computing with Python." -category = "main" +version = "1.26.1" +description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.8" +python-versions = "<3.13,>=3.9" +files = [ + {file = "numpy-1.26.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82e871307a6331b5f09efda3c22e03c095d957f04bf6bc1804f30048d0e5e7af"}, + {file = "numpy-1.26.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdd9ec98f0063d93baeb01aad472a1a0840dee302842a2746a7a8e92968f9575"}, + {file = "numpy-1.26.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d78f269e0c4fd365fc2992c00353e4530d274ba68f15e968d8bc3c69ce5f5244"}, + {file = "numpy-1.26.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ab9163ca8aeb7fd32fe93866490654d2f7dda4e61bc6297bf72ce07fdc02f67"}, + {file = "numpy-1.26.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:78ca54b2f9daffa5f323f34cdf21e1d9779a54073f0018a3094ab907938331a2"}, + {file = "numpy-1.26.1-cp310-cp310-win32.whl", hash = "sha256:d1cfc92db6af1fd37a7bb58e55c8383b4aa1ba23d012bdbba26b4bcca45ac297"}, + {file = "numpy-1.26.1-cp310-cp310-win_amd64.whl", hash = "sha256:d2984cb6caaf05294b8466966627e80bf6c7afd273279077679cb010acb0e5ab"}, + {file = "numpy-1.26.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd7837b2b734ca72959a1caf3309457a318c934abef7a43a14bb984e574bbb9a"}, + {file = "numpy-1.26.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1c59c046c31a43310ad0199d6299e59f57a289e22f0f36951ced1c9eac3665b9"}, + {file = "numpy-1.26.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d58e8c51a7cf43090d124d5073bc29ab2755822181fcad978b12e144e5e5a4b3"}, + {file = "numpy-1.26.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6081aed64714a18c72b168a9276095ef9155dd7888b9e74b5987808f0dd0a974"}, + {file = "numpy-1.26.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:97e5d6a9f0702c2863aaabf19f0d1b6c2628fbe476438ce0b5ce06e83085064c"}, + {file = "numpy-1.26.1-cp311-cp311-win32.whl", hash = "sha256:b9d45d1dbb9de84894cc50efece5b09939752a2d75aab3a8b0cef6f3a35ecd6b"}, + {file = "numpy-1.26.1-cp311-cp311-win_amd64.whl", hash = "sha256:3649d566e2fc067597125428db15d60eb42a4e0897fc48d28cb75dc2e0454e53"}, + {file = "numpy-1.26.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d1bd82d539607951cac963388534da3b7ea0e18b149a53cf883d8f699178c0f"}, + {file = "numpy-1.26.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:afd5ced4e5a96dac6725daeb5242a35494243f2239244fad10a90ce58b071d24"}, + {file = "numpy-1.26.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03fb25610ef560a6201ff06df4f8105292ba56e7cdd196ea350d123fc32e24e"}, + {file = "numpy-1.26.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcfaf015b79d1f9f9c9fd0731a907407dc3e45769262d657d754c3a028586124"}, + {file = "numpy-1.26.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e509cbc488c735b43b5ffea175235cec24bbc57b227ef1acc691725beb230d1c"}, + {file = "numpy-1.26.1-cp312-cp312-win32.whl", hash = "sha256:af22f3d8e228d84d1c0c44c1fbdeb80f97a15a0abe4f080960393a00db733b66"}, + {file = "numpy-1.26.1-cp312-cp312-win_amd64.whl", hash = "sha256:9f42284ebf91bdf32fafac29d29d4c07e5e9d1af862ea73686581773ef9e73a7"}, + {file = "numpy-1.26.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bb894accfd16b867d8643fc2ba6c8617c78ba2828051e9a69511644ce86ce83e"}, + {file = "numpy-1.26.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e44ccb93f30c75dfc0c3aa3ce38f33486a75ec9abadabd4e59f114994a9c4617"}, + {file = "numpy-1.26.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9696aa2e35cc41e398a6d42d147cf326f8f9d81befcb399bc1ed7ffea339b64e"}, + {file = "numpy-1.26.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5b411040beead47a228bde3b2241100454a6abde9df139ed087bd73fc0a4908"}, + {file = "numpy-1.26.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1e11668d6f756ca5ef534b5be8653d16c5352cbb210a5c2a79ff288e937010d5"}, + {file = "numpy-1.26.1-cp39-cp39-win32.whl", hash = "sha256:d1d2c6b7dd618c41e202c59c1413ef9b2c8e8a15f5039e344af64195459e3104"}, + {file = "numpy-1.26.1-cp39-cp39-win_amd64.whl", hash = "sha256:59227c981d43425ca5e5c01094d59eb14e8772ce6975d4b2fc1e106a833d5ae2"}, + {file = "numpy-1.26.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:06934e1a22c54636a059215d6da99e23286424f316fddd979f5071093b648668"}, + {file = "numpy-1.26.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76ff661a867d9272cd2a99eed002470f46dbe0943a5ffd140f49be84f68ffc42"}, + {file = "numpy-1.26.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6965888d65d2848e8768824ca8288db0a81263c1efccec881cb35a0d805fcd2f"}, + {file = "numpy-1.26.1.tar.gz", hash = "sha256:c8c6c72d4a9f831f328efb1312642a1cafafaa88981d9ab76368d50d07d93cbe"}, +] [[package]] name = "packaging" -version = "21.3" +version = "23.2" description = "Core utilities for Python packages" -category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["railroad-diagrams", "jinja2"] - [[package]] name = "pytest" -version = "7.2.0" +version = "7.4.3" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, +] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "typing-extensions" -version = "4.4.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "zipp" -version = "3.10.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" optional = false python-versions = ">=3.7" - -[package.extras] -docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "jaraco.tidelift (>=1.4)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "jaraco.functools", "more-itertools", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] - -[metadata] -lock-version = "1.1" -python-versions = "^3.7" -content-hash = "7886afe25f44148269aae9b5a98e0030046b4c5d7b8ad6a1c9dc6be8a57e1219" - -[metadata.files] -attrs = [] -colorama = [] -exceptiongroup = [] -importlib-metadata = [] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -numpy = [ - {file = "numpy-1.21.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8737609c3bbdd48e380d463134a35ffad3b22dc56295eff6f79fd85bd0eeeb25"}, - {file = "numpy-1.21.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fdffbfb6832cd0b300995a2b08b8f6fa9f6e856d562800fea9182316d99c4e8e"}, - {file = "numpy-1.21.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3820724272f9913b597ccd13a467cc492a0da6b05df26ea09e78b171a0bb9da6"}, - {file = "numpy-1.21.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f17e562de9edf691a42ddb1eb4a5541c20dd3f9e65b09ded2beb0799c0cf29bb"}, - {file = "numpy-1.21.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f30427731561ce75d7048ac254dbe47a2ba576229250fb60f0fb74db96501a1"}, - {file = "numpy-1.21.6-cp310-cp310-win32.whl", hash = "sha256:d4bf4d43077db55589ffc9009c0ba0a94fa4908b9586d6ccce2e0b164c86303c"}, - {file = "numpy-1.21.6-cp310-cp310-win_amd64.whl", hash = "sha256:d136337ae3cc69aa5e447e78d8e1514be8c3ec9b54264e680cf0b4bd9011574f"}, - {file = "numpy-1.21.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6aaf96c7f8cebc220cdfc03f1d5a31952f027dda050e5a703a0d1c396075e3e7"}, - {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:67c261d6c0a9981820c3a149d255a76918278a6b03b6a036800359aba1256d46"}, - {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a6be4cb0ef3b8c9250c19cc122267263093eee7edd4e3fa75395dfda8c17a8e2"}, - {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c4068a8c44014b2d55f3c3f574c376b2494ca9cc73d2f1bd692382b6dffe3db"}, - {file = "numpy-1.21.6-cp37-cp37m-win32.whl", hash = "sha256:7c7e5fa88d9ff656e067876e4736379cc962d185d5cd808014a8a928d529ef4e"}, - {file = "numpy-1.21.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bcb238c9c96c00d3085b264e5c1a1207672577b93fa666c3b14a45240b14123a"}, - {file = "numpy-1.21.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:82691fda7c3f77c90e62da69ae60b5ac08e87e775b09813559f8901a88266552"}, - {file = "numpy-1.21.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:643843bcc1c50526b3a71cd2ee561cf0d8773f062c8cbaf9ffac9fdf573f83ab"}, - {file = "numpy-1.21.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:357768c2e4451ac241465157a3e929b265dfac85d9214074985b1786244f2ef3"}, - {file = "numpy-1.21.6-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f411b2c3f3d76bba0865b35a425157c5dcf54937f82bbeb3d3c180789dd66a6"}, - {file = "numpy-1.21.6-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4aa48afdce4660b0076a00d80afa54e8a97cd49f457d68a4342d188a09451c1a"}, - {file = "numpy-1.21.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a96eef20f639e6a97d23e57dd0c1b1069a7b4fd7027482a4c5c451cd7732f4"}, - {file = "numpy-1.21.6-cp38-cp38-win32.whl", hash = "sha256:5c3c8def4230e1b959671eb959083661b4a0d2e9af93ee339c7dada6759a9470"}, - {file = "numpy-1.21.6-cp38-cp38-win_amd64.whl", hash = "sha256:bf2ec4b75d0e9356edea834d1de42b31fe11f726a81dfb2c2112bc1eaa508fcf"}, - {file = "numpy-1.21.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4391bd07606be175aafd267ef9bea87cf1b8210c787666ce82073b05f202add1"}, - {file = "numpy-1.21.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67f21981ba2f9d7ba9ade60c9e8cbaa8cf8e9ae51673934480e45cf55e953673"}, - {file = "numpy-1.21.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee5ec40fdd06d62fe5d4084bef4fd50fd4bb6bfd2bf519365f569dc470163ab0"}, - {file = "numpy-1.21.6-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1dbe1c91269f880e364526649a52eff93ac30035507ae980d2fed33aaee633ac"}, - {file = "numpy-1.21.6-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9caa9d5e682102453d96a0ee10c7241b72859b01a941a397fd965f23b3e016b"}, - {file = "numpy-1.21.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58459d3bad03343ac4b1b42ed14d571b8743dc80ccbf27444f266729df1d6f5b"}, - {file = "numpy-1.21.6-cp39-cp39-win32.whl", hash = "sha256:7f5ae4f304257569ef3b948810816bc87c9146e8c446053539947eedeaa32786"}, - {file = "numpy-1.21.6-cp39-cp39-win_amd64.whl", hash = "sha256:e31f0bb5928b793169b87e3d1e070f2342b22d5245c755e2b81caa29756246c3"}, - {file = "numpy-1.21.6-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd1c8f6bd65d07d3810b90d02eba7997e32abbdf1277a481d698969e921a3be0"}, - {file = "numpy-1.21.6.zip", hash = "sha256:ecb55251139706669fdec2ff073c98ef8e9a84473e51e716211b41aa0f18e656"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [] -tomli = [ +files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -typing-extensions = [] -zipp = [] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9,<3.13" +content-hash = "aa27aa586ebf5e13d1936db455cb5da27cc641ae1ffc6434877928a3baa9bb82" diff --git a/pyproject.toml b/pyproject.toml index cbf1ab2..9476ee2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "fireflyalgorithm" -version = "0.3.4" +version = "0.4.0" description = "Implementation of Firefly Algorithm in Python" authors = ["Iztok Fister Jr. ", "Luka Pečnik ", "Žiga Stupan "] license = "MIT" @@ -13,14 +13,14 @@ include = [ ] [tool.poetry.dependencies] -python = "^3.7" -numpy = [ - { version = "^1.21.5", python = ">=3.7,<3.11" }, - { version = "^1.22.0", python = "^3.11" } -] +python = "^3.9,<3.13" +numpy = "^1.26.1" + +[tool.poetry.group.test.dependencies] +pytest = "^7.4.3" -[tool.poetry.dev-dependencies] -pytest = "^7.0.1" +[tool.poetry.scripts] +firefly-algorithm = 'fireflyalgorithm.cli:main' [build-system] requires = ["poetry-core"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 24ce15a..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -numpy diff --git a/tests/test_firefly.py b/tests/test_firefly.py index cc048b7..3a05a3d 100644 --- a/tests/test_firefly.py +++ b/tests/test_firefly.py @@ -1,15 +1,10 @@ from unittest import TestCase - -import numpy as np from fireflyalgorithm import FireflyAlgorithm - -def sphere(x): - return np.sum(x ** 2) +from fireflyalgorithm.problems import sphere class TestFA(TestCase): - def test_algorithm(self): - FA = FireflyAlgorithm() - best = FA.run(function=sphere, dim=10, lb=-5, ub=5, max_evals=10000) + algorithm = FireflyAlgorithm() + best = algorithm.run(function=sphere, dim=10, lb=-5, ub=5, max_evals=10000) self.assertLess(best, 5) diff --git a/tests/test_problems.py b/tests/test_problems.py new file mode 100644 index 0000000..7ced6bb --- /dev/null +++ b/tests/test_problems.py @@ -0,0 +1,214 @@ +from unittest import TestCase +import numpy as np +from fireflyalgorithm.problems import ( + get_problem, + ackley, + alpine1, + alpine2, + cigar, + cosine_mixture, + csendes, + dixon_price, + griewank, + katsuura, + levy, + michalewicz, + perm1, + perm2, + pinter, + powell, + quing, + quintic, + rastrigin, + rosenbrock, + salomon, + schaffer2, + schaffer4, + schwefel, + schwefel21, + schwefel22, + sphere, + step, + step2, + styblinski_tang, + trid, + weierstrass, + whitley, + zakharov, +) + + +class TestProblems(TestCase): + def test_problem_factory(self): + self.assertRaises(KeyError, get_problem, "spherekjl2") + self.assertEqual(get_problem("ackley"), ackley) + self.assertEqual(get_problem("alpine1"), alpine1) + self.assertEqual(get_problem("alpine2"), alpine2) + self.assertEqual(get_problem("cigar"), cigar) + self.assertEqual(get_problem("cosine_mixture"), cosine_mixture) + self.assertEqual(get_problem("csendes"), csendes) + self.assertEqual(get_problem("dixon_price"), dixon_price) + self.assertEqual(get_problem("griewank"), griewank) + self.assertEqual(get_problem("katsuura"), katsuura) + self.assertEqual(get_problem("levy"), levy) + self.assertEqual(get_problem("michalewicz"), michalewicz) + self.assertEqual(get_problem("perm1"), perm1) + self.assertEqual(get_problem("perm2"), perm2) + self.assertEqual(get_problem("pinter"), pinter) + self.assertEqual(get_problem("powell"), powell) + self.assertEqual(get_problem("quing"), quing) + self.assertEqual(get_problem("quintic"), quintic) + self.assertEqual(get_problem("rastrigin"), rastrigin) + self.assertEqual(get_problem("rosenbrock"), rosenbrock) + self.assertEqual(get_problem("salomon"), salomon) + self.assertEqual(get_problem("schaffer2"), schaffer2) + self.assertEqual(get_problem("schaffer4"), schaffer4) + self.assertEqual(get_problem("schwefel"), schwefel) + self.assertEqual(get_problem("schwefel21"), schwefel21) + self.assertEqual(get_problem("schwefel22"), schwefel22) + self.assertEqual(get_problem("sphere"), sphere) + self.assertEqual(get_problem("step"), step) + self.assertEqual(get_problem("step2"), step2) + self.assertEqual(get_problem("styblinski_tang"), styblinski_tang) + self.assertEqual(get_problem("trid"), trid) + self.assertEqual(get_problem("weierstrass"), weierstrass) + self.assertEqual(get_problem("whitley"), whitley) + self.assertEqual(get_problem("zakharov"), zakharov) + + def test_ackley(self): + x = np.zeros(5) + self.assertAlmostEqual(ackley(x), 0.0) + + def test_alpine1(self): + x = np.zeros(5) + self.assertAlmostEqual(alpine1(x), 0.0) + + def test_alpine2(self): + x = np.full(5, 7.9170526982459462172) + self.assertAlmostEqual(alpine2(x), 2.8081311800070053291**5) + + def test_cigar(self): + x = np.zeros(5) + self.assertAlmostEqual(cigar(x), 0.0) + + def test_cosine_mixture(self): + x = np.zeros(5) + self.assertAlmostEqual(cosine_mixture(x), -0.5) + + def test_csendes(self): + x = np.zeros(5) + self.assertAlmostEqual(csendes(x), 0.0) + + def test_dixon_price(self): + x = np.array([2 ** -((2**i - 2) / 2**i) for i in range(1, 6)]) + self.assertAlmostEqual(dixon_price(x), 0.0) + + def test_griewank(self): + x = np.zeros(5) + self.assertAlmostEqual(griewank(x), 0.0) + + def test_katsuura(self): + x = np.zeros(5) + self.assertAlmostEqual(katsuura(x), 1.0) + + def test_levy(self): + x = np.full(5, 1) + self.assertAlmostEqual(levy(x), 0.0) + + def test_michalewicz(self): + x = np.array([2.20290552014618, 1.57079632677565]) + self.assertAlmostEqual(michalewicz(x), -1.80130341009855321) + + def test_perm1(self): + x = np.arange(1, 6) + self.assertAlmostEqual(perm1(x), 0.0) + + def test_perm2(self): + x = 1 / np.arange(1, 6) + self.assertAlmostEqual(perm2(x), 0.0) + + def test_pinter(self): + x = np.zeros(5) + self.assertAlmostEqual(pinter(x), 0.0) + + def test_powell(self): + x = np.zeros(5) + self.assertAlmostEqual(powell(x), 0.0) + + def test_quing(self): + x = np.sqrt(np.arange(1, 6)) + self.assertAlmostEqual(quing(x), 0.0) + + def test_quintic(self): + x = np.full(5, -1) + self.assertAlmostEqual(quintic(x), 0.0) + + def test_rastrigin(self): + x = np.zeros(5) + self.assertAlmostEqual(rastrigin(x), 0.0) + + def test_rosenbrock(self): + x = np.full(5, 1) + self.assertAlmostEqual(rosenbrock(x), 0.0) + + def test_salomon(self): + x = np.zeros(5) + self.assertAlmostEqual(rastrigin(x), 0.0) + + def test_schaffer2(self): + x = np.zeros(5) + self.assertAlmostEqual(schaffer2(x), 0.0) + + def test_schaffer4(self): + x1 = np.array([0, 1.253131828792882]) + x2 = np.array([0, -1.253131828792882]) + x3 = np.array([1.253131828792882, 0]) + x4 = np.array([-1.253131828792882, 0]) + self.assertAlmostEqual(schaffer4(x1), 0.292578632035980) + self.assertAlmostEqual(schaffer4(x2), 0.292578632035980) + self.assertAlmostEqual(schaffer4(x3), 0.292578632035980) + self.assertAlmostEqual(schaffer4(x4), 0.292578632035980) + + def test_schwefel(self): + x = np.full(5, 420.968746) + self.assertAlmostEqual(schwefel(x), 0.0) + + def test_schwefel21(self): + x = np.zeros(5) + self.assertAlmostEqual(schwefel21(x), 0.0) + + def test_schwefel22(self): + x = np.zeros(5) + self.assertAlmostEqual(schwefel22(x), 0.0) + + def test_sphere(self): + x = np.zeros(5) + self.assertAlmostEqual(sphere(x), 0.0) + + def test_step(self): + x = np.full(5, 0.5) + self.assertAlmostEqual(step(x), 0.0) + + def test_step2(self): + x = np.full(5, 0.5) + self.assertAlmostEqual(step(x), 0.0) + + def test_styblinski_tang(self): + x = np.full(5, -2.903534018185960) + self.assertAlmostEqual(styblinski_tang(x), -39.16616570377142 * 5) + + def test_trid(self): + x = np.array([6, 10, 12, 12, 10, 6]) + self.assertAlmostEqual(trid(x), -50) + + def test_weierstrass(self): + x = np.zeros(5) + self.assertAlmostEqual(weierstrass(x), 0.0) + + def test_whitley(self): + x = np.full(5, 1) + self.assertAlmostEqual(whitley(x), 0.0) + + def test_zakharov(self): + x = np.zeros(5) + self.assertAlmostEqual(zakharov(x), 0.0)