diff --git a/.github/img/2d-f12010.png b/.github/img/2d-f12010.png
new file mode 100644
index 0000000..6937489
Binary files /dev/null and b/.github/img/2d-f12010.png differ
diff --git a/.github/img/3d-f12010.png b/.github/img/3d-f12010.png
new file mode 100644
index 0000000..7813911
Binary files /dev/null and b/.github/img/3d-f12010.png differ
diff --git a/CITATION.cff b/CITATION.cff
index 9c1aba7..cba994e 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -5,7 +5,7 @@ authors:
given-names: "Nguyen"
orcid: "https://orcid.org/0000-0001-9994-8747"
title: "Opfunu: An Open-source Python Library for Optimization Benchmark Functions"
-version: 1.0.1
+version: 1.0.4
doi: 10.5281/zenodo.3620960
date-released: 2022-07-13
url: "https://github.com/thieu1995/opfunu"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..faacb26
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,95 @@
+# Contributing to Opfunu
+
+We appreciate your interest in contributing to Opfunu! This guide details how to contribute in a way that is efficient
+for everyone.
+
+## Table of Contents
+
+- [Code of Conduct](#code-of-conduct)
+- [Getting Started](#getting-started)
+- [How Can I Contribute?](#how-can-i-contribute)
+- [Pull Requests](#pull-requests)
+- [Issue Tracking](#issue-tracking)
+
+## Code of Conduct
+
+All contributors are expected to adhere to the project's [Code of Conduct](CODE_OF_CONDUCT.md). Please read the document before contributing.
+
+## Getting Started
+
+1. Fork the project repository and clone your fork:
+
+ ```
+ git clone https://github.com/thieu1995/opfunu.git
+ ```
+
+2. Create a new branch for your changes:
+
+ ```
+ git checkout -b name-of-your-branch
+ ```
+
+3. Make your changes and commit them:
+
+ ```
+ git commit -m "Detailed commit message"
+ ```
+
+4. Push your changes to your fork:
+
+ ```
+ git push origin name-of-your-branch
+ ```
+
+5. Create a pull request from your branch to the Opfunu main branch.
+
+## How Can I Contribute?
+
+Here are some ways to contribute:
+
+- Improve documentation
+- Fix bugs or add new features
+- Write tutorials or blog posts
+- Review code submissions
+- Test the application and report issues
+
+However, before contributing, make sure that the unit tests pass and that new functionality is covered by unit tests.
+The unit tests can be run using `pytest`. Change working directory to opfunu and then use:
+
+```python
+# Test CEC-based functions
+python -m pytest tests/cec_based
+
+# Test Name-based functions
+python -m pytest tests/name_based
+```
+
+Or you can test all files by:
+
+```python
+python -m pytest
+```
+
+
+## Pull Requests
+
+[Pull requests](https://github.com/thieu1995/opfunu/pulls) are the best way to propose changes to the codebase. We
+actively welcome your pull requests:
+
+1. Fork the repo and create your branch from `main`.
+2. If you've added code that should be tested, add tests.
+3. If you've changed APIs, update the documentation.
+4. Ensure the test suite passes.
+5. Issue that pull request!
+
+## Issue Tracking
+
+We use [GitHub issues](https://github.com/thieu1995/opfunu/issues) to track public bugs and requests. Please ensure
+your description is clear and has sufficient instructions to be able to reproduce the issue.
+
+## Any questions?
+
+Don't hesitate to contact us if you have any questions. Contact [@thieu1995](mailto:nguyenthieu2102@gmail.com)
+or ask your question on issues.
+
+Thank you for your contributions!
diff --git a/ChangeLog.md b/ChangeLog.md
index f6d1093..6bff3d5 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,15 +1,30 @@
-# Version 1.0.4
+# Version 1.0.5
+ Fix schaffer_f7_func to match the cec implementation and reference document
+ Fix zakharov_func to match the cec implementation and reference document
+ Added a direct conversion of the lunacek_bi_rastrigin_cec_func
+ Added tests for cec functions comparing outputs to the reference implementations
---------------------------------------------------------------------
+# Version 1.0.4
+
++ Fix p value in F10 and F17 of CEC-2017
++ Add plot_latex to Benchmark class.
++ User can use draw_latex from opfunu to draw their latex equation.
++ Update examples for draw latex function
+
+---------------------------------------------------------------------
+
# Version 1.0.3
+ Optimized katsuura_func performance, at 1M ndim > 80x speedup
++ Add plot_2d, plot_3d to Benchmark class.
++ User can use draw_2d, draw_3d from opfunu to draw their function.
++ Add tutorial on how to integrate with other optimization frameworks like Mealpy, Opytimizer, Niapy
++ Update examples and update documentations
++ Update citation and paper (Got published at Journal of Open Research Software)
---------------------------------------------------------------------
+
# Version 1.0.2
+ Fix modified_schwefel_func() in operator.py
diff --git a/README.md b/README.md
index fa67e85..5e1a77a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
---
-[![GitHub release](https://img.shields.io/badge/release-1.0.2-yellow.svg)](https://github.com/thieu1995/opfunu/releases)
+[![GitHub release](https://img.shields.io/badge/release-1.0.4-yellow.svg)](https://github.com/thieu1995/opfunu/releases)
[![Wheel](https://img.shields.io/pypi/wheel/gensim.svg)](https://pypi.python.org/pypi/opfunu)
[![PyPI version](https://badge.fury.io/py/opfunu.svg)](https://badge.fury.io/py/opfunu)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/opfunu.svg)
@@ -34,6 +34,28 @@ optimization benchmark functions. Contains all CEC competition functions from 20
* **Dependencies:** numpy, matplotlib
+# Citation Request
+
+Please include these citations if you plan to use this library:
+
+- LaTeX:
+
+```bibtex
+ @article{Van_Thieu_2024_Opfunu,
+ author = {Van Thieu, Nguyen},
+ title = {Opfunu: An Open-source Python Library for Optimization Benchmark Functions},
+ doi = {10.5334/jors.508},
+ journal = {Journal of Open Research Software},
+ month = {May},
+ year = {2024}
+ }
+```
+
+- APA:
+
+ Van Thieu, N. (2024). Opfunu: An Open-source Python Library for Optimization Benchmark Functions. Journal of Open Research Software, 12(1), 8. https://doi.org/10.5334/jors.508
+
+
# Installation and Usage
### Install with pip
@@ -57,44 +79,13 @@ $ python
>>> opfunu.CEC_DATABASE # List all cec_based functions
>>> opfunu.ALL_DATABASE # List all functions in this library
->>> opfunu.get_functions_by_classname("CEC2014")
+>>> opfunu.get_functions_by_classname("MiShra04")
>>> opfunu.get_functions_based_classname("2015")
->>> opfunu.get_functions_by_ndim(30)
->>> opfunu.get_functions_based_ndim(2)
->>> opfunu.get_all_named_functions()
->>> opfunu.get_all_cec_functions()
->>> opfunu.get_functions()
->>> opfunu.get_cecs()
-```
+>>> opfunu.get_functions_by_ndim(2)
+>>> opfunu.get_functions_based_ndim(50)
-### Lib's structure
-
-```code
-
-docs
-examples
-opfunu
- cec_based
- cec.py
- cec2005.py
- cec2008.py
- ...
- cec2021.py
- cec2022.py
- name_based
- a_func.py
- b_func.py
- ...
- y_func.py
- z_func.py
- utils
- operator.py
- validator.py
- visualize.py
- __init__.py
- benchmark.py
-README.md
-setup.py
+>>> opfunu.get_name_based_functions(ndim=10, continuous=True)
+>>> opfunu.get_cec_based_functions(ndim=2)
```
Let's go through some examples.
@@ -124,7 +115,6 @@ func.evaluate(func.create_solution())
#### 2nd way
```python
-
import opfunu
funcs = opfunu.get_functions_by_classname("F12014")
@@ -135,57 +125,91 @@ func.evaluate(func.create_solution())
all_funcs_2014 = opfunu.get_functions_based_classname("2014")
print(all_funcs_2014)
-
```
-For more usage examples please look at [examples](/examples) folder.
+### How to draw 2D, 3D
+
+Two ways if you want to draw functions that available in Opfunu.
+
+```python
+from opfunu.cec_based import F12010
+f0 = F12010()
+# Visualize opfunu function using method in object
+f0.plot_2d(selected_dims=(2, 3), n_points=300, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="Contour map of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="2d-f12010", exts=(".png", ".pdf"), verbose=True)
-# Get helps (questions, problems)
+f0.plot_3d(selected_dims=(1, 6), n_points=500, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="3D visualization of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="3d-f12010", exts=(".png", ".pdf"), verbose=True)
-* Official source code repo: https://github.com/thieu1995/opfunu
-* Official document: https://opfunu.readthedocs.io/
-* Download releases: https://pypi.org/project/opfunu/
-* Issue tracker: https://github.com/thieu1995/opfunu/issues
-* Notable changes log: https://github.com/thieu1995/opfunu/blob/master/ChangeLog.md
-* Examples with different version: https://github.com/thieu1995/opfunu/blob/master/examples.md
-* Official chat group: https://t.me/+fRVCJGuGJg1mNDg1
+## Visualize opfunu function using utility function
+from opfunu import draw_2d, draw_3d
-* This project also related to our another projects which are optimization and machine learning. Check it here:
- * https://github.com/thieu1995/metaheuristics
- * https://github.com/thieu1995/mealpy
- * https://github.com/thieu1995/mafese
- * https://github.com/thieu1995/pfevaluator
- * https://github.com/thieu1995/MetaCluster
- * https://github.com/thieu1995/enoppy
- * https://github.com/thieu1995/permetrics
- * https://github.com/aiir-team
+draw_2d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
+draw_3d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
+```
+
+
+
+
+ F1-2010 CEC 2D
+ |
+
+
+ F1-2010 CEC 3D
+ |
+
+
-## Cite Us
-If you are using opfunu in your project, we would appreciate citations:
+### How to draw Latex
-```code
-@software{thieu_nguyen_2020_3711682,
- author = {Nguyen Van Thieu},
- title = {Opfunu: An Open-source Python Library for Optimization Benchmark Functions},
- year = 2020,
- publisher = {Zenodo},
- doi = {10.5281/zenodo.3620960},
- url = {https://doi.org/10.5281/zenodo.3620960.}
-}
-```
+Two ways if you want to draw latex equation.
+```python
+from opfunu.cec_based import F12010
+from opfunu.name_based import Ackley02
+from opfunu.utils.visualize import draw_latex
-## References
+f0 = F12010()
+f1 = Ackley02()
-```code
-1. http://benchmarkfcns.xyz/fcns
-2. https://en.wikipedia.org/wiki/Test_functions_for_optimization
-3. https://www.cs.unm.edu/~neal.holts/dga/benchmarkFunction/
-4. http://www.sfu.ca/~ssurjano/optimization.html
-5. A Literature Survey of Benchmark Functions For Global Optimization Problems (2013)
-6. Problem Definitions and Evaluation Criteria for the CEC 2014 Special Session and Competition on Single Objective Real-Parameter Numerical Optimization
+## Plot using function inside the object
+f0.plot_latex(f0.latex_formula, figsize=(8, 3), dpi=500, title="Latex equation", exts=(".png", ".pdf"), verbose=True)
+f1.plot_latex(f1.latex_formula_global_optimum, figsize=(8, 3), dpi=500, title="Global optimum", verbose=True)
+
+## Plot using module
+draw_latex(f0.latex_formula_bounds, title="Boundary for Function")
+draw_latex(f1.latex_formula_dimension, title=None)
```
+
+
+
+For more usage examples please look at [examples](/examples) folder.
+
+
+
+# Contributing
+
+There are lots of ways how you can contribute to Permetrics's development, and you are welcome to join in! For example,
+you can report problems or make feature requests on the [issues](/issues) pages. To facilitate contributions,
+please check for the guidelines in the [CONTRIBUTING.md](/CONTRIBUTING.md) file.
+
+
+# Official channels
+
+* [Official source code repository](https://github.com/thieu1995/opfunu)
+* [Official document](https://opfunu.readthedocs.io/)
+* [Download releases](https://pypi.org/project/opfunu/)
+* [Issue tracker](https://github.com/thieu1995/opfunu/issues)
+* [Notable changes log](/ChangeLog.md)
+* [Official discussion group](https://t.me/+fRVCJGuGJg1mNDg1)
+
+
+---
+
+Developed by: [Thieu](mailto:nguyenthieu2102@gmail.com?Subject=Opfunu_QUESTIONS) @ 2023
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 67983b8..2982f14 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -29,7 +29,7 @@
author = 'Thieu'
# The full version, including alpha/beta/rc tags
-release = '1.0.3'
+release = '1.0.4'
# -- General configuration ---------------------------------------------------
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 96cbe8e..c4d5288 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -6,7 +6,7 @@
Welcome to OPFUNU's documentation!
==================================
-.. image:: https://img.shields.io/badge/release-1.0.2-yellow.svg
+.. image:: https://img.shields.io/badge/release-1.0.4-yellow.svg
:target: https://github.com/thieu1995/opfunu/releases
.. image:: https://img.shields.io/pypi/wheel/gensim.svg
@@ -74,7 +74,9 @@ traditional functions with different dimensions are implemented.
:caption: Introduction:
pages/quick_start.rst
- pages/notes.rst
+ pages/integrated.rst
+ pages/visualization.rst
+ pages/categories.rst
.. toctree::
diff --git a/docs/source/pages/notes.rst b/docs/source/pages/categories.rst
similarity index 99%
rename from docs/source/pages/notes.rst
rename to docs/source/pages/categories.rst
index 799c3c1..51477d4 100644
--- a/docs/source/pages/notes.rst
+++ b/docs/source/pages/categories.rst
@@ -1,10 +1,7 @@
-Notes
-=====
+Function Categories
+===================
-Categories
-----------
-
In general, unconstrained problems can be classified into two categories: test functions and real-world problems::
1. Test functions are artificial problems, and can be used to evaluate the behavior of an algorithm in sometimes diverse and difficult situations.
diff --git a/docs/source/pages/integrated.rst b/docs/source/pages/integrated.rst
new file mode 100644
index 0000000..4d64a9f
--- /dev/null
+++ b/docs/source/pages/integrated.rst
@@ -0,0 +1,77 @@
+Collaborative Libraries
+=======================
+
+In this section, we will guide you how to integrate our library into other Optimization frameworks.
+
+
+Mealpy Library
+--------------
+
+For example::
+
+ from opfunu.cec_based import cec2017
+ f3 = cec2017.F32017(ndim=30)
+
+ from mealpy import GA, FloatVar
+
+ problem = {
+ "obj_func": f3.evaluate,
+ "bounds": FloatVar(lb=f3.lb, ub=f3.ub),
+ "minmax": "min",
+ }
+ model = GA.BaseGA(epoch=100, pop_size=50)
+ gbest = model.solve(problem_dict1)
+ print(f"Solution: {gbest.solution}, Fit: {gbest.target.fitness}")
+
+
+
+ScikitOpt Library
+-----------------
+
+For example::
+
+ from opfunu.cec_based import cec2015
+ f10 = cec2015.F102015(ndim=30)
+
+ from sko.DE import DE
+
+ de = DE(func=f10.evaluate, lb=f10.lb, ub=f10.ub,
+ size_pop=50, max_iter=800)
+ best_x, best_y = de.run()
+ print(f"best_x: {best_x}, best_y: {best_y}")
+
+
+
+Opytimizer Library
+------------------
+
+For example::
+
+ from opfunu.cec_based import cec2022
+ f5 = cec2022.F52022(ndim=30)
+
+ from opytimizer import Opytimizer
+ from opytimizer.core import Function
+ from opytimizer.optimizers.swarm import PSO
+ from opytimizer.spaces import SearchSpace
+
+ space = SearchSpace(n_agents=20, n_variables=f5.ndim,
+ lower_bound=f5.lb, upper_bound=f5.ub)
+ optimizer = PSO()
+ function = Function(f5.evaluate)
+
+ opt = Opytimizer(space, optimizer, function)
+ opt.start(n_iterations=1000)
+
+
+
+.. toctree::
+ :maxdepth: 4
+
+
+.. toctree::
+ :maxdepth: 4
+
+
+.. toctree::
+ :maxdepth: 4
diff --git a/docs/source/pages/quick_start.rst b/docs/source/pages/quick_start.rst
index cd0ba12..b85a198 100644
--- a/docs/source/pages/quick_start.rst
+++ b/docs/source/pages/quick_start.rst
@@ -8,7 +8,7 @@ Installation
Install the `current PyPI release `_::
- $ pip install opfunu==1.0.3
+ $ pip install opfunu==1.0.4
Or install the development version from GitHub::
@@ -46,7 +46,6 @@ Current Structure::
z_func.py
utils
operator.py
- validator.py
visualize.py
__init__.py
benchmark.py
diff --git a/docs/source/pages/support.rst b/docs/source/pages/support.rst
index 8f75bcf..18cbccc 100644
--- a/docs/source/pages/support.rst
+++ b/docs/source/pages/support.rst
@@ -6,6 +6,15 @@ If you are using opfunu in your project, we would appreciate citations:
::
+ @article{Van_Thieu_2024_Opfunu,
+ author = {Van Thieu, Nguyen},
+ title = {Opfunu: An Open-source Python Library for Optimization Benchmark Functions},
+ doi = {10.5334/jors.508},
+ journal = {Journal of Open Research Software},
+ month = {May},
+ year = {2024}
+ }
+
@software{thieu_nguyen_2020_3711682,
author = {Nguyen Van Thieu},
title = {Opfunu: An Open-source Python Library for Optimization Benchmark Functions},
diff --git a/docs/source/pages/utils.rst b/docs/source/pages/utils.rst
index 3973278..88c1a32 100644
--- a/docs/source/pages/utils.rst
+++ b/docs/source/pages/utils.rst
@@ -1,14 +1,6 @@
opfunu.utils package
====================
-opfunu.utils.encoder module
----------------------------
-
-.. automodule:: opfunu.utils.encoder
- :members:
- :undoc-members:
- :show-inheritance:
-
opfunu.utils.operator module
----------------------------
@@ -17,14 +9,6 @@ opfunu.utils.operator module
:undoc-members:
:show-inheritance:
-opfunu.utils.validator module
------------------------------
-
-.. automodule:: opfunu.utils.validator
- :members:
- :undoc-members:
- :show-inheritance:
-
opfunu.utils.visualize module
-----------------------------
diff --git a/docs/source/pages/visualization.rst b/docs/source/pages/visualization.rst
new file mode 100644
index 0000000..244865b
--- /dev/null
+++ b/docs/source/pages/visualization.rst
@@ -0,0 +1,71 @@
+Visualization
+=============
+
+Inside Function
+---------------
+
+You can use our visualization module to draw our function.
+
+Code::
+
+ from opfunu.cec_based import F12010
+
+ # Visualize opfunu function using method in object
+ f0 = F12010()
+
+ f0.plot_2d(selected_dims=(2, 3), n_points=300, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="Contour map of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="2d-f12010", exts=(".png", ".pdf"), verbose=True)
+
+ f0.plot_3d(selected_dims=(1, 6), n_points=500, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="3D visualization of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="3d-f12010", exts=(".png", ".pdf"), verbose=True)
+
+ ## Visualize opfunu function using utility function
+ from opfunu import draw_2d, draw_3d
+
+ draw_2d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
+ draw_3d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
+
+
+Custom Function
+---------------
+
+You can also use our visualization module to draw your custom function.
+
+Code::
+
+ from opfunu import draw_2d, draw_3d
+
+ ## Define a custom function, for example. I will use mealpy problem as an example
+ from mealpy import Problem, FloatVar
+ import numpy as np
+
+ # Our custom problem class
+ class Squared(Problem):
+ def __init__(self, bounds=None, minmax="min", data=None, **kwargs):
+ self.data = data
+ super().__init__(bounds, minmax, **kwargs)
+
+ def obj_func(self, solution):
+ x = self.decode_solution(solution)["my_var"]
+ return np.sum(x ** 2)
+
+ bound = FloatVar(lb=(-10., )*20, ub=(10., )*20, name="my_var")
+ custom_squared = Squared(bounds=bound, minmax="min", data="Amazing", name="Squared")
+
+ ## Visualize function using utility function
+ draw_2d(custom_squared.obj_func, custom_squared.lb, custom_squared.ub, selected_dims=(2, 3), n_points=300)
+ draw_3d(custom_squared.obj_func, custom_squared.lb, custom_squared.ub, selected_dims=(2, 3), n_points=300)
+
+
+.. toctree::
+ :maxdepth: 4
+
+
+.. toctree::
+ :maxdepth: 4
+
+
+.. toctree::
+ :maxdepth: 4
diff --git a/examples.md b/examples.md
index 596fdc1..eedb02f 100644
--- a/examples.md
+++ b/examples.md
@@ -7,11 +7,11 @@ import opfunu
import numpy as np
# get all the available functions accepting ANY dimension
-any_dim_cec = opfunu.get_cecs(None)
+any_dim_cec = opfunu.get_cec_based_functions(None)
print(any_dim_cec)
# get all the available separable functions accepting 2D
-separable_2d_cec = opfunu.get_cecs(
+separable_2d_cec = opfunu.get_cec_based_functions(
ndim=2, # dimension
separable=True,
)
@@ -75,14 +75,14 @@ print(problem.x_global)
print(problem.is_succeed(problem.x_global))
# # get all the available separable functions accepting 2D
-my_list = opfunu.get_cecs(
+my_list = opfunu.get_cec_based_functions(
ndim=2, # dimension
rotated=True
)
print(my_list) # --> 41
## Get all noise function
-my_list = opfunu.get_cecs(
+my_list = opfunu.get_cec_based_functions(
randomized_term=True
)
print(my_list)
diff --git a/examples/basic_use_cases_benchmark.py b/examples/basic_use_cases_benchmark.py
index d520f84..68b8cc9 100644
--- a/examples/basic_use_cases_benchmark.py
+++ b/examples/basic_use_cases_benchmark.py
@@ -10,11 +10,11 @@
if __name__ == '__main__':
# get all the available functions accepting ANY dimension
- any_dim_functions = opfunu.get_functions(None)
+ any_dim_functions = opfunu.get_name_based_functions(None)
print(any_dim_functions)
# get all the available differentiable functions accepting 2D
- differentiable_2d_functions = opfunu.get_functions(
+ differentiable_2d_functions = opfunu.get_name_based_functions(
ndim=2, # dimension
differentiable=True,
)
diff --git a/examples/basic_use_cases_cec.py b/examples/basic_use_cases_cec.py
index 84f38ff..52d8b2b 100644
--- a/examples/basic_use_cases_cec.py
+++ b/examples/basic_use_cases_cec.py
@@ -10,11 +10,11 @@
if __name__ == '__main__':
# # get all the available functions accepting ANY dimension
- # any_dim_cec = opfunu.get_cecs(None)
+ # any_dim_cec = opfunu.get_cec_based_functions(None)
# print(any_dim_cec)
#
# # get all the available separable functions accepting 2D
- # separable_2d_cec = opfunu.get_cecs(
+ # separable_2d_cec = opfunu.get_cec_based_functions(
# ndim=2, # dimension
# separable=True,
# )
@@ -77,14 +77,14 @@
print(problem.is_succeed(problem.x_global))
# # get all the available separable functions accepting 2D
- my_list = opfunu.get_cecs(
+ my_list = opfunu.get_cec_based_functions(
ndim=2, # dimension
rotated=True
)
print(my_list) # --> 41
## Get all noise function
- my_list = opfunu.get_cecs(
+ my_list = opfunu.get_cec_based_functions(
randomized_term=True
)
print(my_list)
diff --git a/examples/example_with_mealpy.py b/examples/example_with_mealpy.py
index 605eb71..0bdf813 100644
--- a/examples/example_with_mealpy.py
+++ b/examples/example_with_mealpy.py
@@ -4,6 +4,8 @@
# Github: https://github.com/thieu1995 %
# --------------------------------------------------%
+## Examples with Mealpy <= 2.5.4
+
from mealpy.bio_based import SMA
from opfunu.name_based import Ackley02
@@ -20,10 +22,27 @@
}
## Run the algorithm
-model = SMA.BaseSMA(epoch=100, pop_size=50, pr=0.03)
+model = SMA.OriginalSMA(epoch=100, pop_size=50, pr=0.03)
best_position, best_fitness = model.solve(problem_dict1)
print(f"Best solution: {best_position}, Best fitness: {best_fitness}")
print(ackey.n_fe)
print(ackey.f_global)
print(ackey.x_global)
+
+
+## Examples with Mealpy >= 3.0.0
+
+from opfunu.cec_based import cec2017
+f3 = cec2017.F32017(ndim=30)
+
+from mealpy import GA, FloatVar
+
+problem = {
+ "obj_func": f3.evaluate,
+ "bounds": FloatVar(lb=f3.lb, ub=f3.ub),
+ "minmax": "min",
+}
+model = GA.BaseGA(epoch=100, pop_size=50)
+gbest = model.solve(problem_dict1)
+print(f"Solution: {gbest.solution}, Fit: {gbest.target.fitness}")
diff --git a/examples/visualize/custom_function.py b/examples/visualize/custom_function.py
new file mode 100644
index 0000000..392f7df
--- /dev/null
+++ b/examples/visualize/custom_function.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Created by "Thieu" at 17:03, 24/05/2024 ----------%
+# Email: nguyenthieu2102@gmail.com %
+# Github: https://github.com/thieu1995 %
+# --------------------------------------------------%
+
+from opfunu import draw_2d, draw_3d
+
+## Define a custom function, for example. I will use mealpy problem as an example
+from mealpy import Problem, FloatVar
+import numpy as np
+
+# Our custom problem class
+class Squared(Problem):
+ def __init__(self, bounds=None, minmax="min", data=None, **kwargs):
+ self.data = data
+ super().__init__(bounds, minmax, **kwargs)
+
+ def obj_func(self, solution):
+ x = self.decode_solution(solution)["my_var"]
+ return np.sum(x ** 2)
+
+bound = FloatVar(lb=(-10., )*20, ub=(10., )*20, name="my_var")
+custom_squared = Squared(bounds=bound, minmax="min", data="Amazing", name="Squared")
+
+## Visualize function using utility function
+draw_2d(custom_squared.obj_func, custom_squared.lb, custom_squared.ub, selected_dims=(2, 3), n_points=300)
+draw_3d(custom_squared.obj_func, custom_squared.lb, custom_squared.ub, selected_dims=(2, 3), n_points=300)
diff --git a/examples/visualize/inside_function.py b/examples/visualize/inside_function.py
new file mode 100644
index 0000000..24909f7
--- /dev/null
+++ b/examples/visualize/inside_function.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# Created by "Thieu" at 16:55, 24/05/2024 ----------%
+# Email: nguyenthieu2102@gmail.com %
+# Github: https://github.com/thieu1995 %
+# --------------------------------------------------%
+
+from opfunu.cec_based import F12010
+
+# Visualize opfunu function using method in object
+f0 = F12010()
+
+f0.plot_2d(selected_dims=(2, 3), n_points=300, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="Contour map of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="2d-f12010", exts=(".png", ".pdf"), verbose=True)
+
+f0.plot_3d(selected_dims=(1, 6), n_points=500, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None, title="3D visualization of the F1 CEC 2010 function",
+ x_label=None, y_label=None, figsize=(10, 8), filename="3d-f12010", exts=(".png", ".pdf"), verbose=True)
+
+## Visualize opfunu function using utility function
+from opfunu import draw_2d, draw_3d
+
+draw_2d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
+draw_3d(f0.evaluate, f0.lb, f0.ub, selected_dims=(2, 3), n_points=300)
diff --git a/examples/visualize/plot_latex.py b/examples/visualize/plot_latex.py
new file mode 100644
index 0000000..1310680
--- /dev/null
+++ b/examples/visualize/plot_latex.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# Created by "Thieu" at 21:17, 04/06/2024 ----------%
+# Email: nguyenthieu2102@gmail.com %
+# Github: https://github.com/thieu1995 %
+# --------------------------------------------------%
+
+from opfunu.cec_based import F12010
+from opfunu.name_based import Ackley02
+from opfunu.utils.visualize import draw_latex
+
+# Visualize opfunu function using method in object
+f0 = F12010()
+f1 = Ackley02()
+
+## Plot using function inside the object
+f0.plot_latex(f0.latex_formula, title="Latex equation")
+f1.plot_latex(f1.latex_formula_global_optimum, title="Global optimum")
+
+## Plot using module
+draw_latex(f0.latex_formula_bounds, title="Boundary for Function")
+draw_latex(f1.latex_formula_dimension, title=None)
diff --git a/opfunu/__init__.py b/opfunu/__init__.py
index 90a5c88..4c418fa 100644
--- a/opfunu/__init__.py
+++ b/opfunu/__init__.py
@@ -21,19 +21,18 @@
# >>> print(f1.get_paras()) # Print the parameters of function if has
# >>>
# >>> Plot 2d or plot 3d contours
-# >>> Warning ! Only working on 2d functions objects !
-# >>> Warning !! change n_space to reduce the computing time
+# >>> Warning !! change n_points to reduce the computing time
# >>>
# >>> import opfunu
# >>> f2 = opfunu.cec_based.F22005(ndim=2)
-# >>> opfunu.plot_2d(f22005, n_space=1000, ax=None)
-# >>> opfunu.plot_3d(f22005, n_space=1000, ax=None)
+# >>> f2.plot_2d(selected_dims=(2, 3), n_points=300)
+# >>> f2.plot_3d(selected_dims=(1, 4), n_points=300)
-__version__ = "1.0.3"
+__version__ = "1.0.4"
import inspect
import re
-from .utils import *
+from .utils.visualize import draw_2d, draw_3d, draw_latex
from . import name_based
from . import cec_based
@@ -47,13 +46,13 @@ def get_functions_by_classname(name=None):
"""
Parameters
----------
- name : Classname of the function
+ name : The exact classname of the function (no difference among lowercase, uppercase, mix)
Returns
-------
List of the functions, but all the classname are different, so the result is list of 1 function or list of empty
"""
- functions = [cls for classname, cls in ALL_DATABASE if (classname not in EXCLUDES and (classname == name or classname.lower() == name))]
+ functions = [cls for classname, cls in ALL_DATABASE if (classname not in EXCLUDES and (classname.lower() == name.lower()))]
return functions
@@ -61,13 +60,13 @@ def get_functions_based_classname(name=None):
"""
Parameters
----------
- name : Name that is a substring of classname
+ name : The substring of classname of the function
Returns
-------
List of the functions
"""
- functions = [cls for classname, cls in ALL_DATABASE if (classname not in EXCLUDES and re.search(name, classname))]
+ functions = [cls for classname, cls in ALL_DATABASE if (classname not in EXCLUDES and re.search(name.lower(), classname.lower()))]
return functions
@@ -75,7 +74,7 @@ def get_functions_by_ndim(ndim=None):
"""
Parameters
----------
- ndim : Number of dimensions that function supported
+ ndim : The exact number of dimensions that function has and not able to change
Returns
-------
@@ -91,7 +90,7 @@ def get_functions_based_ndim(ndim=None):
"""
Parameters
----------
- ndim : Number of dimensions that function has as default value
+ ndim : Number of dimensions that function supported
Returns
-------
@@ -99,19 +98,19 @@ def get_functions_based_ndim(ndim=None):
"""
functions = [cls for classname, cls in ALL_DATABASE if classname not in EXCLUDES]
if type(ndim) is int and ndim > 1:
- return list(filter(lambda f: ndim in f().dim_supported, functions))
+ return list(filter(lambda f: (f().dim_default == ndim or f().dim_changeable == True), functions))
return functions
-def get_all_named_functions():
+def get_all_name_based_functions():
return [cls for classname, cls in FUNC_DATABASE if classname not in EXCLUDES]
-def get_all_cec_functions():
+def get_all_cec_based_functions():
return [cls for classname, cls in CEC_DATABASE if classname not in EXCLUDES]
-def get_functions(ndim, continuous=None, linear=None, convex=None, unimodal=None, separable=None,
+def get_name_based_functions(ndim, continuous=None, linear=None, convex=None, unimodal=None, separable=None,
differentiable=None, scalable=None, randomized_term=None, parametric=None, modality=None):
functions = [cls for classname, cls in FUNC_DATABASE if classname not in EXCLUDES]
functions = list(filter(lambda f: f().is_ndim_compatible(ndim), functions))
@@ -129,7 +128,7 @@ def get_functions(ndim, continuous=None, linear=None, convex=None, unimodal=None
return functions
-def get_cecs(ndim=None, continuous=None, linear=None, convex=None, unimodal=None, separable=None, differentiable=None,
+def get_cec_based_functions(ndim=None, continuous=None, linear=None, convex=None, unimodal=None, separable=None, differentiable=None,
scalable=None, randomized_term=None, parametric=True, shifted=True, rotated=None , modality=None):
functions = [cls for classname, cls in CEC_DATABASE if classname not in EXCLUDES]
functions = list(filter(lambda f: f().is_ndim_compatible(ndim), functions))
diff --git a/opfunu/benchmark.py b/opfunu/benchmark.py
index 0113afb..ee39e13 100644
--- a/opfunu/benchmark.py
+++ b/opfunu/benchmark.py
@@ -5,6 +5,7 @@
# --------------------------------------------------%
import numpy as np
+from opfunu.utils.visualize import draw_2d, draw_3d, draw_latex
class Benchmark:
@@ -52,6 +53,7 @@ class Benchmark:
parametric = True
modality = True # Number of ambiguous peaks, unknown # peaks
+
# n_basins = 1
# n_valleys = 1
@@ -60,6 +62,7 @@ def __init__(self):
self._ndim = None
self.dim_changeable = False
self.dim_default = 2
+ self.dim_supported = []
self.f_global = None
self.x_global = None
self.n_fe = 0
@@ -249,3 +252,124 @@ def create_solution(self) -> np.ndarray:
The random solution
"""
return np.random.uniform(self.lb, self.ub)
+
+ def plot_latex(self, latex, title="Latex equation", figsize=(8, 3), dpi=500, filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw latex equation.
+
+ Parameters
+ ----------
+ latex : equation
+ Your latex equation, you can test on the website: https://latex.codecogs.com/
+ title : str
+ Title for the figure
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ dpi : int, default=500
+ The dot per inches (DPI) - indicate the number of dots per inch.
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ draw_latex(latex, title=title, figsize=figsize, dpi=dpi, filename=filename, exts=exts, verbose=verbose)
+
+ def plot_2d(self, selected_dims=None, n_points=500, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7, fixed_strategy="mean", fixed_values=None,
+ title="Contour map of the function", x_label=None, y_label=None, figsize=(10, 8), filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw 2D contour of the function.
+
+ Parameters
+ ----------
+ selected_dims : list, tuple, np.ndarray
+ The selected dimensions you want to draw.
+ If your function has only 2 dimensions, it will select (1, 2) automatically.
+ n_points : int
+ The number of points that will be used to draw the contour
+ ct_cmap : str
+ The cmap of matplotlib.pyplot.contourf function (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contourf.html)
+ ct_levels : int
+ The levels parameter of contourf function
+ ct_alpha : float
+ The alpha parameter of contourf function
+ fixed_strategy : str
+ The selected strategy to set values for other dimensions.
+ When your function has > 2 dimensions, you need to set a fixed value for other dimensions to be able to calculate value.
+ List of available strategy: ["min", "max", "mean', "values", "zero"]
+ + min: Set the other dimensions by its lower bound
+ + max: Set the other dimensions by its upper bound
+ + mean: Set the other dimensions by it average value (lower bound + upper bound) / 2
+ + zero: Set the other dimensions by 0
+ + values: Set the other dimensions by your passed values through the parameter: `fixed_values`.
+
+ fixed_values : list, tuple, np.ndarray
+ Fixed values for all dimensions (length should be the same as lower bound), the selected dimensions will be replaced in the drawing process.
+ title : str
+ Title for the figure
+ x_label : str
+ Set the x label
+ y_label : str
+ Set the y label
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ draw_2d(self.evaluate, self.lb, self.ub, selected_dims=selected_dims, n_points=n_points,
+ ct_cmap=ct_cmap, ct_levels=ct_levels, ct_alpha=ct_alpha, fixed_strategy=fixed_strategy, fixed_values=fixed_values,
+ title=title, x_label=x_label, y_label=y_label, figsize=figsize, filename=filename, exts=exts, verbose=verbose)
+
+ def plot_3d(self, selected_dims=None, n_points=500, ct_cmap="viridis", ct_levels=30, ct_alpha=0.7, fixed_strategy="mean", fixed_values=None,
+ title="3D visualization of the function", x_label=None, y_label=None, figsize=(10, 8), filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw 3D of the function.
+
+ Parameters
+ ----------
+ selected_dims : list, tuple, np.ndarray
+ The selected dimensions you want to draw.
+ If your function has only 2 dimensions, it will select (1, 2) automatically.
+ n_points : int
+ The number of points that will be used to draw the contour
+ ct_cmap : str
+ The cmap of matplotlib.pyplot.contourf function (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contourf.html)
+ ct_levels : int
+ The levels parameter of contourf function
+ ct_alpha : float
+ The alpha parameter of contourf function
+ fixed_strategy : str
+ The selected strategy to set values for other dimensions.
+ When your function has > 2 dimensions, you need to set a fixed value for other dimensions to be able to calculate value.
+ List of available strategy: ["min", "max", "mean', "values", "zero"]
+ + min: Set the other dimensions by its lower bound
+ + max: Set the other dimensions by its upper bound
+ + mean: Set the other dimensions by it average value (lower bound + upper bound) / 2
+ + zero: Set the other dimensions by 0
+ + values: Set the other dimensions by your passed values through the parameter: `fixed_values`.
+
+ fixed_values : list, tuple, np.ndarray
+ Fixed values for all dimensions (length should be the same as lower bound), the selected dimensions will be replaced in the drawing process.
+ title : str
+ Title for the figure
+ x_label : str
+ Set the x label
+ y_label : str
+ Set the y label
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ draw_3d(self.evaluate, self.lb, self.ub, selected_dims=selected_dims, n_points=n_points,
+ ct_cmap=ct_cmap, ct_levels=ct_levels, ct_alpha=ct_alpha, fixed_strategy=fixed_strategy, fixed_values=fixed_values,
+ title=title, x_label=x_label, y_label=y_label, figsize=figsize, filename=filename, exts=exts, verbose=verbose)
diff --git a/opfunu/cec_based/cec.py b/opfunu/cec_based/cec.py
index 84651e9..b81dcc5 100644
--- a/opfunu/cec_based/cec.py
+++ b/opfunu/cec_based/cec.py
@@ -204,10 +204,10 @@ def check_ndim_and_bounds(self, ndim=None, dim_max=None, bounds=None, default_bo
if self.dim_changeable:
if type(ndim) is int and ndim > 1:
if dim_max is None or ndim <= dim_max:
- # Check if ndim in supported dimensions
- if self.dim_supported is not None and ndim not in self.dim_supported:
- raise ValueError(f'{self.__class__.__name__} ndim not in supported dimensions '
- f'{self.dim_supported}')
+ # # Check if ndim in supported dimensions
+ # if self.dim_supported is not None and ndim not in self.dim_supported:
+ # raise ValueError(f'{self.__class__.__name__} ndim not in supported dimensions '
+ # f'{self.dim_supported}')
self._ndim = int(ndim)
self._bounds = np.array([default_bounds[0] for _ in range(self._ndim)])
else:
diff --git a/opfunu/cec_based/cec2017.py b/opfunu/cec_based/cec2017.py
index c5f8114..fa35410 100644
--- a/opfunu/cec_based/cec2017.py
+++ b/opfunu/cec_based/cec2017.py
@@ -321,7 +321,7 @@ def __init__(self, ndim=None, bounds=None, f_shift="shift_data_10", f_matrix="M_
self.f_global = f_bias
self.x_global = self.f_shift
self.n_funcs = 3
- self.p = np.array([0.2, 0.2, 0.2])
+ self.p = np.array([0.2, 0.4, 0.4])
self.n1 = int(np.ceil(self.p[0] * self.ndim))
self.n2 = int(np.ceil(self.p[1] * self.ndim)) + self.n1
self.idx1, self.idx2, self.idx3 = self.f_shuffle[:self.n1], self.f_shuffle[self.n1:self.n2], self.f_shuffle[self.n2:self.ndim]
@@ -544,7 +544,7 @@ class F172017(F102017):
def __init__(self, ndim=None, bounds=None, f_shift="shift_data_17", f_matrix="M_17_D", f_shuffle="shuffle_data_17_D", f_bias=1700.):
super().__init__(ndim, bounds, f_shift, f_matrix, f_shuffle, f_bias)
self.n_funcs = 5
- self.p = np.array([0.1, 0.2, 0.2, 0.2, 0.3])
+ self.p = np.array([0.2, 0.2, 0.2, 0.2, 0.2])
self.n1 = int(np.ceil(self.p[0] * self.ndim))
self.n2 = int(np.ceil(self.p[1] * self.ndim)) + self.n1
self.n3 = int(np.ceil(self.p[2] * self.ndim)) + self.n2
diff --git a/opfunu/dimension_based/__init__.py b/opfunu/dimension_based/__init__.py
deleted file mode 100644
index 48b12e0..0000000
--- a/opfunu/dimension_based/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-# ------------------------------------------------------------------------------------------------------%
-# Created by "Thieu Nguyen" at 11:23, 16/03/2020 %
-# %
-# Email: nguyenthieu2102@gmail.com %
-# Homepage: https://www.researchgate.net/profile/Thieu_Nguyen6 %
-# Github: https://github.com/thieu1995 %
-#-------------------------------------------------------------------------------------------------------%
-
diff --git a/opfunu/dimension_based/benchmark2d.py b/opfunu/dimension_based/benchmark2d.py
deleted file mode 100644
index 9cb11eb..0000000
--- a/opfunu/dimension_based/benchmark2d.py
+++ /dev/null
@@ -1,431 +0,0 @@
-#!/usr/bin/env python #
-# ------------------------------------------------------------------------------------------------------#
-# Created by "Thieu Nguyen" at 02:54, 06/12/2019 #
-# #
-# Email: nguyenthieu2102@gmail.com #
-# Homepage: https://www.researchgate.net/profile/Thieu_Nguyen6 #
-# Github: https://github.com/thieu1995 #
-#-------------------------------------------------------------------------------------------------------#
-
-import numpy as np
-
-class Functions:
- """
- This class of functions is belongs to 2-dimensional space
- """
-
- def _ackley_n2__(self, solution=None):
- """
- Class: unimodal, convex, differentiable, non-separable
- Global: one global minimum fx = -200, at [0, 0]
-
- @param solution: A numpy array include 2 items like: [10, 22]
- """
- n = len(solution)
- assert (n == 2, 'Ackley N. 2 function is only defined on a 2D space.')
- return -200*np.exp(-0.2*np.sqrt(np.sum(solution**2)))
-
-
- def _ackley_n3__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable
- Global: one global minimum fx = −195.629028238419, at [±0.682584587365898,−0.36075325513719]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/ackleyn3fcn.html
-
- @param solution: A numpy array include 2 items like: [10, 22]
- """
- d = len(solution)
- assert (d == 2, 'Ackley N. 3 function is only defined on a 2D space.')
- return -200*np.exp(-0.2*np.sqrt(np.sum(solution**2))) + 5*np.exp(np.cos(3*solution[0]) + np.sin(3*solution[1]))
-
-
- def _adjiman__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable
- Global: if x in [-1, 2], y in [-1, 1] cube => global min fx = -2.02181, at [0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/adjimanfcn.html
-
- @param solution: A numpy array include 2 items like: [10, 22]
- """
- d = len(solution)
- assert (d == 2, 'Adjiman function is only defined on a 2D space.')
- return np.cos(solution[0]) * np.sin(solution[1]) - solution[0] / (solution[1]**2 + 1)
-
- def _bartels_conn__(self, solution=None):
- """
- Class: multimodal, non-convex, non-differentiable, non-separable
- Global: one global minimum fx = 1, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/bartelsconnfcn.html
-
- @param solution: A numpy array include 2 items like: [10, 22]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bartels conn function is only defined on a 2D space.')
- return np.abs(solution[0]**2 + solution[1]**2 + solution[0] * solution[1]) + np.abs(np.sin(solution[0])) + \
- np.abs(np.cos(solution[1]))
-
- def _beale__(self, solution=None):
- """
- Class: multimodal, non-convex, continuous
- Global: one global minimum fx = 0, at [3, 0.5]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/bealefcn.html
-
- @param solution: A numpy array include 2 items in range: [-4.5, 4.5], [-4.5, 4.5]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Beale function is only defined on a 2D space.')
- return (1.5-solution[0]+solution[0]*solution[1])**2 + (2.25-solution[0]+solution[0]*solution[1]**2)**2 +\
- (2.625-solution[0]+solution[0]*solution[1]**3)**2
-
- def _bird__(self, solution=None):
- """
- Class: multimodal, non-convex, non-separable, differentiable
- Global: 2 global minimum fx= -106.764537, at ( 4.70104 , 3.15294 ) and ( − 1.58214 , − 3.13024 ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/birdfcn.html
-
- @param solution: A numpy array include 2 items in range: [-2pi, 2pi], [-2pi, 2pi]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bird function is only defined on a 2D space.')
- return np.sin(solution[0])*np.exp((1 - np.cos(solution[1]))**2) + \
- np.cos(solution[1]) * np.exp( (1-np.sin(solution[0]))**2 ) + (solution[0] - solution[1])**2
-
- def _bohachevskyn_n1__(self, solution=None):
- """
- Class: unimodal, convex, continuous
- Global: global minimum fx= 0, at ( 0, 0 )
- Link: http://benchmarkfcns.xyz/benchmarkfcns/bohachevskyn1fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100], [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bohachevskyn N.1 function is only defined on a 2D space.')
- return solution[0]**2 + 2*solution[1]**2 - 0.3*np.cos(3*solution[0]*np.pi) - 0.4*np.cos(4*solution[1]*np.pi) + 0.7
-
-
- def _bohachevskyn_n2__(self, solution=None):
- """
- Class: multi-modal, non-convex, non-separable, differentiable
- Global: global minimum fx= 0, at ( 0, 0 )
- Link: http://benchmarkfcns.xyz/benchmarkfcns/bohachevskyn2fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100], [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bohachevskyn N.2 function is only defined on a 2D space.')
- return solution[0] ** 2 + 2 * solution[1] ** 2 - 0.3 * np.cos(3 * solution[0] * np.pi) * np.cos(4 * solution[1] * np.pi) + 0.3
-
-
- def _booth__(self, solution=None):
- """
- Class: unimodal, convex, non-separable, differentiable, continuous
- Global: one global minimum fx= 0, at ( 1, 3 )
- Link: http://benchmarkfcns.xyz/benchmarkfcns/boothfcn.html
-
- @param solution: A numpy array include 2 items in range: [-10, 10], [-10, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Brooth function is only defined on a 2D space.')
- return (solution[0]+2*solution[1]-7)**2 + (2*solution[0]+solution[1]-5)**2
-
-
- def _brent__(self, solution=None):
- """
- Class: unimodal, convex, non-separable, differentiable
- Global: one global minimum fx= e^(-200), at ( -10 -10 )
- Link: http://benchmarkfcns.xyz/benchmarkfcns/brentfcn.html
-
- @param solution: A numpy array include 2 items in range: [-20, 0], [-20, 0]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Brent function is only defined on a 2D space.')
- return (solution[0]+10)**2 + (solution[1]+10)**2 + np.exp(-solution[0]**2-solution[1]**2)
-
-
- def _bukin_n6__(self, solution=None):
- """
- Class: multimodal, convex, non-separable, non-differentiable, continuous
- Global: one global minimum fx= 0, at ( -10, 1)
- Link: http://benchmarkfcns.xyz/benchmarkfcns/bukinn6fcn.html
-
- @param solution: A numpy array include 2 items in range: [-15, -5], [-3, 3]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bukin N.6 function is only defined on a 2D space.')
- return 100*np.sqrt(np.abs(solution[1] - 0.01*solution[0]**2)) + 0.01*np.abs(solution[0]+10)
-
-
- def _cross_in_tray__(self, solution=None):
- """
- Class: multimodal, non-convex, non-separable, non-differentiable, continuous
- Global: 4 global minimum fx= -2.06261218, at (±1.349406685353340,±1.349406608602084)
- Link: http://benchmarkfcns.xyz/benchmarkfcns/crossintrayfcn.html
-
- @param solution: A numpy array include 2 items in range: [-10, 10], [-10, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Bukin N.6 function is only defined on a 2D space.')
- t1 = np.exp( np.abs(100 - np.sqrt(np.sum(solution**2))/np.pi ) )
- t2 = np.sin(solution[0]) * np.cos(solution[1])
- return -0.0001*(np.abs(t1*t2) + 1)**0.1
-
-
- def _deckkers_aarts__(self, solution=None):
- """
- Class: multimodal, non-convex, non-separable, differentiable, continuous
- Global: 1 global minimum fx = −24771.09375, at ( 0 , ± 15 ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/deckkersaartsfcn.html
-
- @param solution: A numpy array include 2 items in range: [-20, 20], [-20, 20]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Deckkers Aarts function is only defined on a 2D space.')
- t1 = solution[0]**2
- t2 = solution[1]**2
- return 10**5*t1 + t2 - (t1 + t2)**2 + 10**(-5) * (t1 + t2)**4
-
-
- def _drop_wave__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous
- Global: 1 global minimum fx = −1 at ( 0 , 0 ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/dropwavefcn.html
-
- @param solution: A numpy array include 2 items in range: [-5.2, 5.2], [-5.2, 5.2]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Drop wave function is only defined on a 2D space.')
- return -(1+np.cos(12*np.sqrt(np.sum(solution*2)))) / (0.5 * np.sum(solution**2) + 2)
-
-
- def _easom__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, separable
- Global: 1 global minimum fx = −1 at ( pi, pi ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/easomfcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100], [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Easom function is only defined on a 2D space.')
- return -np.cos(solution[0])*np.cos(solution[1])*np.exp(-(solution[0] - np.pi)**2 - (solution[1] - np.pi)**2)
-
-
- def _egg_crate__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, separable
- Global: global minimum fx = 0 at ( 0, 0 ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/eggcratefcn.html
-
- @param solution: A numpy array include 2 items in range: [-5, 5]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Egg Crate function is only defined on a 2D space.')
- return np.sum(solution**2) + 25 * (np.sin(solution[0])**2 + np.sin(solution[1])**2)
-
-
- def _goldstein_price__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, non-separable
- Global: global minimum fx = 3 at ( 0, -1 ) .
- Link: http://benchmarkfcns.xyz/benchmarkfcns/goldsteinpricefcn.html
-
- @param solution: A numpy array include 2 items in range: [-2, 2]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Goldstein price function is only defined on a 2D space.')
- t1 = 18 - 32*solution[0] + 12*solution[0]**2 + 4*solution[1] - 36*solution[0]*solution[1] + 27*solution[1]**2
- t2 = 19 - 14*solution[0]+3*solution[0]**2 - 14*solution[1] + 6*solution[0]*solution[1] + 3*solution[1]**2
- t3 = (np.sum(solution) + 1)**2
- return (1+t3*t2) * (30 + (2*solution[0]-3*solution[1])**2 * t1)
-
-
- def _himmelblau__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous
- Global: 4 global optima, fx = 0 at (3, 2), (-2.85118, 3.283186), (−3.779310,−3.283186), (3.584458,−1.848126)
-
- Link: http://benchmarkfcns.xyz/benchmarkfcns/himmelblaufcn.html
-
- @param solution: A numpy array include 2 items in range: [-6, 6]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Himmelblau function is only defined on a 2D space.')
- return (solution[0]**2+solution[1]-11)**2 + (solution[0] + solution[1]**2 - 7)**2
-
-
- def _holder_table__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, non-differentiable, non-separable
- Global: 4 global optima, fx = -19.2085 at (±8.05502,±9.66459)
-
- Link: http://benchmarkfcns.xyz/benchmarkfcns/holdertablefcn.html
-
- @param solution: A numpy array include 2 items in range: [-10, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Holder Table function is only defined on a 2D space.')
- return -np.abs(np.sin(solution[0])*np.cos(solution[1])*np.abs(1 - np.sqrt(np.sum(solution**2))/np.pi))
-
-
- def _keane__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, non-separable
- Global: 2 global optima, fx = 0.673667521146855 at (1.393249070031784,0), (0,1.393249070031784)
-
- Link: http://benchmarkfcns.xyz/benchmarkfcns/kealefcn.html
-
- @param solution: A numpy array include 2 items in range: [0, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Keane function is only defined on a 2D space.')
- return -np.sin(solution[0]-solution[1])**2 * np.sin(solution[0] + solution[1])**2 / np.sqrt(np.sum(solution**2))
-
-
- def _leon__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [0, 10]
-
- Link: http://benchmarkfcns.xyz/benchmarkfcns/leonfcn.html
-
- @param solution: A numpy array include 2 items in range: [0, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Leon function is only defined on a 2D space.')
- return 100*(solution[1]-solution[0]**3)**2 + (1-solution[0])**2
-
-
- def _levi_n13__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [1, 1]
-
- Link: http://benchmarkfcns.xyz/benchmarkfcns/levin13fcn.html
-
- @param solution: A numpy array include 2 items in range: [-10, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Levi N.13 function is only defined on a 2D space.')
- return np.sin(3*solution[0]*np.pi)**2 + (solution[0]-1)**2*(1+np.sin(3*solution[1]**np.pi)**2) +\
- (solution[1]-1)**2*(1 + np.sin(2*solution[1]*np.pi)**2)
-
-
- def _matyas__(self, solution=None):
- """
- Class: uni-modal, convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/matyasfcn.html
-
- @param solution: A numpy array include 2 items in range: [-10, 10]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Matyas function is only defined on a 2D space.')
- return 0.26*np.sum(solution**2) - 0.48*solution[0]*solution[1]
-
-
- def _mc_cormick__(self, solution=None):
- """
- Class: multi-modal, convex, continuous, differentiable, non-scalable
- Global: 1 global optima, fx = -1.9133 at [-0.547, -1.547]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/mccormickfcn.html
-
- @param solution: A numpy array include 2 items in range: [-1.5, 4], [-3, 3]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Mc Cormick function is only defined on a 2D space.')
- return np.sin(solution[0]+solution[1]) + (solution[0] - solution[1])**2 - 1.5*solution[0] + 2.5*solution[1] + 1
-
-
- def _schaffer_n1__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schaffern1fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Scheffer N.1 function is only defined on a 2D space.')
- return 0.5 + (np.sin(np.sum(solution**2)**2)**2 - 0.5) / (1 + 0.001*np.sum(solution**2))**2
-
-
- def _schaffer_n2__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schaffern2fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Scheffer N.2 function is only defined on a 2D space.')
- return 0.5 + (np.sin(solution[0]**2 - solution[1]**2)**2 - 0.5) / (1 + 0.001*np.sum(solution**2))**2
-
-
- def _schaffer_n3__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0.00156685 at [0, 1.253115]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schaffern3fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Scheffer N.3 function is only defined on a 2D space.')
- return 0.5 + (np.sin(np.cos(np.abs( solution[0]**2 - solution[1]**2 ))) - 0.5) / (1 + 0.001*np.sum(solution**2))**2
-
-
- def _schaffer_n4__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0.292579 at [0, 1.253115]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schaffern4fcn.html
-
- @param solution: A numpy array include 2 items in range: [-100, 100]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Scheffer N.4 function is only defined on a 2D space.')
- return 0.5 + (np.cos(np.sin(np.abs( solution[0]**2 - solution[1]**2 ))) - 0.5) / (1 + 0.001*np.sum(solution**2))**2
-
-
- def _three_hump_camel__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global optima, fx = 0 at [0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/threehumpcamelfcn.html
-
- @param solution: A numpy array include 2 items in range: [-5, 5]
- @return: fx
- """
- d = len(solution)
- assert (d == 2, 'Scheffer N.3 function is only defined on a 2D space.')
- return 2*solution[0]**2 - 1.05*solution[0]**4 + solution[0]**6/6 + solution[0]*solution[1] + solution[1]**2
-
-
-
diff --git a/opfunu/dimension_based/benchmark3d.py b/opfunu/dimension_based/benchmark3d.py
deleted file mode 100644
index 61f2099..0000000
--- a/opfunu/dimension_based/benchmark3d.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python #
-# ------------------------------------------------------------------------------------------------------#
-# Created by "Thieu Nguyen" at 02:52, 07/12/2019 #
-# #
-# Email: nguyenthieu2102@gmail.com #
-# Homepage: https://www.researchgate.net/profile/Thieu_Nguyen6 #
-# Github: https://github.com/thieu1995 #
-#-------------------------------------------------------------------------------------------------------#
-
-
-import numpy as np
-
-class Functions:
- """
- This class of functions is belongs to 3-dimensional space
- """
-
- def _wolfe__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous, differentiable, non-separable
- Global: 1 global minimum fx = 0, [0, 0, 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/wolfefcn.html
-
- @param solution: A numpy array include 3 items like: [0.2, 0.22, 0.5], limited range: [0, 2]
- """
- n = len(solution)
- assert (n == 3, 'Wolfe function is only defined on a 3D space.')
- return 4/3 * (solution[0]**2 + solution[1]**2 - solution[0]*solution[1])**0.75 + solution[2]
diff --git a/opfunu/dimension_based/benchmarknd.py b/opfunu/dimension_based/benchmarknd.py
deleted file mode 100644
index 5313746..0000000
--- a/opfunu/dimension_based/benchmarknd.py
+++ /dev/null
@@ -1,470 +0,0 @@
-#!/usr/bin/env python #
-# ------------------------------------------------------------------------------------------------------#
-# Created by "Thieu Nguyen" at 17:44, 06/12/2019 #
-# #
-# Email: nguyenthieu2102@gmail.com #
-# Homepage: https://www.researchgate.net/profile/Thieu_Nguyen6 #
-# Github: https://github.com/thieu1995 #
-#-------------------------------------------------------------------------------------------------------#
-
-import numpy as np
-
-class Functions:
- """
- This class of functions is belongs to n-dimensional space
- """
-
- def _ackley__(self, solution=None, a=20, b=0.2, c=2 * np.pi):
- """
- Class: multimodal, continuous, non-convex, differentiable, n-dimensional space.
- Global: one global minimum fx = 0, at [0, 0,...0]
-
- @param solution: A numpy array like: [1, 2, 10, 4, ...]
- @return: fx
- """
- result1 = np.sum(solution ** 2)
- result2 = np.sum(np.cos(c * solution))
- lin = 1 / len(solution)
- return -a * np.exp(-b * np.sqrt(lin * result1)) - np.exp(lin * result2) + a + np.exp(1)
-
-
- def _ackley_n4__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, n-dimensional space.
- Global: on 2-d space, 1 global min fx = -4.590101633799122, at [−1.51, −0.755]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/ackleyn4fcn.html
-
- @param solution: A numpy array include 2 items like: [-35, 35, -35, ...]
- """
- d = len(solution)
- score = 0.0
- for i in range(0, d-1):
- score += ( np.exp(-0.2*np.sqrt(solution[i]**2 + solution[i+1]**2)) + 3*(np.cos(2*solution[i]) + np.sin(2*solution[i+1])) )
- return score
-
-
- def _alpine_n1__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, n-dimensional space.
- Global: one global minimum fx = 0, at [0, 0,...0]
-
- @param solution: A numpy array like: [1, 2, 10, 4, ...]
- @return: fx
- """
- return np.sum(np.abs(solution*np.sin(solution) + 0.1 * solution))
-
-
- def _alpine_n2__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, n-dimensional space.
- Global: one global minimum fx = 2.808^n, at [7.917, ..., 7.917]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/alpinen2fcn.html
-
- @param solution: A numpy array like: [1, 2, 10, 4, ...]
- @return: fx
- """
- return np.prod(np.sqrt(solution)*np.sin(solution))
-
-
- def _brown__(self, solution=None):
- """
- Class: uni-modal, convex, differentiable, non-separable
- Global: one global minimum fx = 0 at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/brownfcn.html
-
- @param solution: A numpy array with x_i in [-1, 4]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d-1):
- result += (solution[i]**2)**(solution[i+1]**2+1) + (solution[i+1]**2)**(solution[i]**2+1)
- return result
-
-
- def _exponential__(self, solution=None):
- """
- Class: uni-modal, convex, differentiable, non-separable, continuous
- Global: one global minimum fx = 0, at [0,...,0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/exponentialfcn.html
-
- @param solution: A numpy array with x_i in [-1, 1]
- @return: fx
- """
- return -np.exp(0-.5*np.sum(solution**2))
-
-
- def _griewank__(self, solution=None):
- """
- Class: uni-modal, non-convex, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/griewankfcn.html
-
- @param solution: A numpy array with x_i in [-600, 600]
- @return: fx
- """
- d = len(solution)
- result = 1 + np.sum(solution**2) / 4000
- prod = 1.0
- for i in range(0, d):
- prod *= np.cos(solution[i]/np.sqrt(i+1))
- return result - prod
-
-
- def _happy_cat__(self, solution=None, alpha=1.0/8):
- """
- Class: multimodal, non-convex, differentiable, non-separable, parametric
- Global: one global minimum fx = 0, at [-1, ..., -1]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/happycatfcn.html
-
- @param solution: A numpy array with x_i in [-2, 2]
- @return: fx
- """
-
- return ((np.sum(solution**2) - len(solution))**2)**alpha + (0.5*np.sum(solution**2)+np.sum(solution))/len(solution) + 0.5
-
-
- def _periodic__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, continuous
- Global: one global minimum fx = 0.9, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/periodicfcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- return 1 + np.sum(np.sin(solution)**2) - 0.1*np.exp(np.sum(solution**2))
-
-
- def _powell_sum__(self, solution=None):
- """
- Class: uni-modal, convex, non-differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/powellsumfcn.html
-
- @param solution: A numpy array with x_i in [-1, 1]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- result += np.abs(solution[i])**(i+2)
- return result
-
-
- def _qing__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, continuous
- Global: one global minimum fx = 0, at (±√i,…,±√i)
- Link: http://benchmarkfcns.xyz/benchmarkfcns/qingfcn.html
-
- @param solution: A numpy array with x_i in [-500, 500]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- result += (solution[i]**2 - i - 1)**2
- return result
-
-
- def _quartic__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, separable, continuous, random
- Global: one global minimum fx = 0 + random, at (0, ...,0)
- Link: http://benchmarkfcns.xyz/benchmarkfcns/quarticfcn.html
-
- @param solution: A numpy array with x_i in [-1.28, 1.28]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- result+= (i+1)*solution[i]**4
- return result+np.random.uniform(0, 1)
-
-
- def _rastrigin__(self, solution=None):
- """
- Class: multimodal, convex, differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/rastriginfcn.html
-
- @param solution: A numpy array with x_in in [-5.12, 5.12]
- @return: fx
- """
- return 10*len(solution) + np.sum(solution**2-10*np.cos(2*solution*np.pi))
-
-
- def _ridge__(self, solution=None, d=2, alpha=0.5):
- """
- Class: uni-model, non-convex, differentiable, non-separable
- Global:
- Link: http://benchmarkfcns.xyz/benchmarkfcns/ridgefcn.html
-
- @param solution: A numpy array with x_i in [-5, 5]
- @return: fx
- """
- t1 = solution[1:]
- return solution[0] + d*np.sum(t1**2)**alpha
-
-
- def _rosenbrock__(self, solution=None, a=1, b=100):
- """
- Class: multimodal, non-convex, differentiable, non-separable, continuous
- Global: 1 global optima, fx = 0, x = [1, ..., 1]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/rosenbrockfcn.html
-
- @param solution: A numpy array with x_i in [-5, 10]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d-1):
- result += b*(solution[i+1] - solution[i]**2)**2 + (a-solution[i])**2
- return result
-
-
- def _salomon__(self, solution=None):
- """
- Class: multimodal, non-convex, differentiable, non-separable, continuous
- Global: 1 global optima, fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/salomonfcn.html
-
- @param solution: A numpy array with x_i in [-100, 100]
- @return: fx
- """
- return 1 - np.cos(2*np.pi*np.sqrt(np.sum(solution**2))) + 0.1*np.sqrt(np.sum(solution**2))
-
-
- def _schwefel_2_20__(self, solution=None):
- """
- Class: uni-modal, convex, non-differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schwefel220fcn.html
-
- @param solution: A numpy array with x_i in [-100, 100]
- @return: fx
- """
- return np.sum(np.abs(solution))
-
-
- def _schwefel_2_21__(self, solution=None):
- """
- Class: uni-modal, convex, non-differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schwefel221fcn.html
-
- @param solution: A numpy array with x_i in [-100, 100]
- @return: fx
- """
- return np.max(np.abs(solution))
-
-
- def _schwefel_2_22__(self, solution=None):
- """
- Class: uni-modal, convex, non-differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schwefel222fcn.html
-
- @param solution: A numpy array with x_i in [-100, 100]
- @return: fx
- """
- return np.sum(np.abs(solution)) + np.prod(np.abs(solution))
-
-
- def _schwefel_2_23__(self, solution=None):
- """
- Class: uni-modal, convex, differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schwefel221fcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- return np.sum(solution**10)
-
-
- def _schwefel__(self, solution=None):
- """
- Class: multi-modal, non-convex, non-differentiable, non-separable, continuous
- Global: one global minimum fx = 0, at [420.9687, ..., 420.9687]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/schwefelfcn.html
-
- @param solution: A numpy array with x_i in [-500, 500]
- @return: fx
- """
- return 418.9829*len(solution) - np.sum(solution*np.sin(np.sqrt(np.abs(solution))))
-
-
- def _shubert_3__(self, solution=None):
- """
- Class: multi-modal, non-convex, differentiable, separable, continuous
- Global: one global minimum fx = -29.6733337
- Link: http://benchmarkfcns.xyz/benchmarkfcns/shubert3fcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- for j in range(1, 6):
- result+= j*np.sin((j+1)*solution[i] + j)
- return result
-
- def _shubert_4__(self, solution=None):
- """
- Class: multi-modal, non-convex, differentiable, separable, continuous
- Global: one global minimum fx = -25.740858
- Link: http://benchmarkfcns.xyz/benchmarkfcns/shubert4fcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- for j in range(1, 6):
- result += j * np.cos((j + 1) * solution[i] + j)
- return result
-
-
- def _shubert__(self, solution=None):
- """
- Class: multi-modal, non-convex, differentiable, non-separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/shubertfcn.html
-
- @param solution: A numpy array with x_i in [-100, 100]
- @return: fx
- """
- d = len(solution)
- prod = 1.0
- for i in range(0, d):
- result = 0
- for j in range(1, 6):
- result += np.cos((j + 1) * solution[i] + j)
- prod *= result
- return prod
-
-
- def _sphere__(self, solution=None):
- """
- Class: uni-modal, convex, differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/spherefcn.html
-
- @param solution: A numpy array with x_i in [-5.12, 5.12]
- @return: fx
- """
- return np.sum(solution**2)
-
-
- def _styblinski__(self, solution=None):
- """
- Class: multi-modal, non-convex, continuous
- Global: one global minimum fx = -39.16599 * d , at [-2.903534, ..., -2.903534]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/styblinskitankfcn.html
-
- @param solution: A numpy array with x_i in [-5, 5]
- @return: fx
- """
- return 0.5*np.sum(solution**4 - 16*solution**2 + 5*solution)
-
-
- def _sum_squres__(self, solution=None):
- """
- Class: uni-modal, convex, differentiable, separable, continuous
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/sumsquaresfcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- d = len(solution)
- result = 0.0
- for i in range(0, d):
- result = (i+1)*solution[i]**2
- return result
-
-
- def _xin_she_yang__(self, solution=None):
- """
- Class: multi-modal, non-convex, non-differentiable, separable, random
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/xinsheyangn1fcn.html
-
- @param solution: A numpy array with x_i in [-5, 5]
- @return: fx
- """
- d = len(solution)
- result = 0
- for i in range(0, d):
- result += np.random.uniform(0, 1) * np.abs(solution[i])**(i+1)
- return result
-
-
- def _xin_she_yang_n2__(self, solution=None):
- """
- Class: multi-modal, non-convex, non-differentiable, non-separable
- Global: one global minimum fx = 0, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/xinsheyangn2fcn.html
-
- @param solution: A numpy array with x_i in [-2pi, 2pi]
- @return: fx
- """
- return np.sum(np.abs(solution))*np.exp(-np.sum(np.sin(solution**2)))
-
-
- def _xin_she_yang_n3__(self, solution=None, m=5, beta=15):
- """
- Class: uni-modal, non-convex, differentiable, non-separable, parametric
- Global: one global minimum fx = -1, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/xinsheyangn3fcn.html
-
- @param solution: A numpy array with x_i in [-2pi, 2pi]
- @return: fx
- """
- t1 = np.exp(-np.sum( np.power(solution/beta, 2*m)))
- t2 = -2*np.exp(-np.sum(solution**2))
- t3 = np.prod(np.cos(solution)**2)
- return t1 + t2*t3
-
-
- def _xin_she_yang_n4__(self, solution=None):
- """
- Class: multi-modal, non-convex, non-differentiable, non-separable
- Global: one global minimum fx = -1, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/xinsheyangn4fcn.html
-
- @param solution: A numpy array with x_i in [-10, 10]
- @return: fx
- """
- t1 = np.sum(np.sin(solution)**2)
- t2 = -np.exp(-np.sum(solution**2))
- t3 = -np.exp(np.sum(np.sin(np.sqrt(np.abs(solution)))**2))
- return (t1 + t2) * t3
-
-
- def _zakharov__(self, solution=None):
- """
- Class: uni-modal, convex, continuous
- Global: one global minimum fx = -1, at [0, ..., 0]
- Link: http://benchmarkfcns.xyz/benchmarkfcns/zakharov.html
-
- @param solution: A numpy array with x_i in [-5, 10]
- @return: fx
- """
- t1 = np.sum(solution**2)
- t2 = 0
- d = len(solution)
- for i in range(0, d):
- t2 += 0.5*(i+1)*solution[i]
- return t1 + t2**2 + t2**4
-
-
-
-
-
-
diff --git a/opfunu/name_based/l_func.py b/opfunu/name_based/l_func.py
index 82e4d2b..d9e760b 100644
--- a/opfunu/name_based/l_func.py
+++ b/opfunu/name_based/l_func.py
@@ -107,8 +107,7 @@ class LennardJones(Benchmark):
def __init__(self, ndim=None, bounds=None):
super().__init__()
- if ndim not in range(6, 61):
- raise ValueError("LennardJones dimensions must be in (6, 60)")
+ self.dim_supported = list(range(6, 61))
self.dim_changeable = True
self.dim_default = 6
self.check_ndim_and_bounds(ndim, bounds, np.array([[-4., 4.] for _ in range(self.dim_default)]))
@@ -121,6 +120,8 @@ def __init__(self, ndim=None, bounds=None):
self.x_global = np.zeros(self.ndim)
def evaluate(self, x, *args):
+ if self.ndim not in self.dim_supported:
+ raise ValueError(f"{self.__class__.__name__} problem is only supported ndim in {self.dim_supported}!")
self.check_solution(x)
self.n_fe += 1
k = int(self.ndim / 3)
diff --git a/opfunu/utils/__init__.py b/opfunu/utils/__init__.py
index 8acc67e..849d0cc 100644
--- a/opfunu/utils/__init__.py
+++ b/opfunu/utils/__init__.py
@@ -3,5 +3,3 @@
# Email: nguyenthieu2102@gmail.com %
# Github: https://github.com/thieu1995 %
# --------------------------------------------------%
-
-from .visualize import *
diff --git a/opfunu/utils/encoder.py b/opfunu/utils/encoder.py
deleted file mode 100644
index 6d175e0..0000000
--- a/opfunu/utils/encoder.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# Created by "Thieu" at 13:58, 09/05/2023 ----------%
-# Email: nguyenthieu2102@gmail.com %
-# Github: https://github.com/thieu1995 %
-# --------------------------------------------------%
-
-import numpy as np
-
-
-class LabelEncoder:
- """
- Encode categorical features as integer labels.
- """
-
- def __init__(self):
- self.unique_labels = None
- self.label_to_index = {}
-
- def fit(self, y):
- """
- Fit label encoder to a given set of labels.
-
- Parameters
- ----------
- y : array-like
- Labels to encode.
- """
- self.unique_labels = np.unique(y)
- self.label_to_index = {label: i for i, label in enumerate(self.unique_labels)}
-
- def transform(self, y):
- """
- Transform labels to encoded integer labels.
-
- Parameters
- ----------
- y : array-like
- Labels to encode.
-
- Returns
- -------
- encoded_labels : array-like
- Encoded integer labels.
- """
- if self.unique_labels is None:
- raise ValueError("Label encoder has not been fit yet.")
- return np.array([self.label_to_index[label] for label in y])
-
- def fit_transform(self, y):
- """
- Fit label encoder and return encoded labels.
-
- Parameters
- ----------
- y : array-like of shape (n_samples,)
- Target values.
-
- Returns
- -------
- y : array-like of shape (n_samples,)
- Encoded labels.
- """
- self.fit(y)
- return self.transform(y)
-
- def inverse_transform(self, y):
- """
- Transform integer labels to original labels.
-
- Parameters
- ----------
- y : array-like
- Encoded integer labels.
-
- Returns
- -------
- original_labels : array-like
- Original labels.
- """
- if self.unique_labels is None:
- raise ValueError("Label encoder has not been fit yet.")
- return np.array([self.unique_labels[i] if i in self.label_to_index.values() else "unknown" for i in y])
diff --git a/opfunu/utils/operator.py b/opfunu/utils/operator.py
index 9480d2b..f087f02 100644
--- a/opfunu/utils/operator.py
+++ b/opfunu/utils/operator.py
@@ -240,13 +240,19 @@ def gz_func(x):
def katsuura_func(x):
+ # TODO: New function failed to pass 5 test cases.
+ # powers_of_two = 2 ** np.arange(1, 34)
+ # reciprocals_of_two = 1 / powers_of_two
+ # for idx in range(0, ndim):
+ # temp = np.sum(np.abs(powers_of_two * x[idx] - np.round(powers_of_two * x[idx])) * reciprocals_of_two)
+ # result *= (1 + (idx + 1) * temp) ** (10.0 / ndim ** 1.2)
+ # return (result - 1) * 10 / ndim ** 2
+
x = np.array(x).ravel()
ndim = len(x)
result = 1.0
- powers_of_two = 2 ** np.arange(1, 34)
- reciprocals_of_two = 1 / powers_of_two
for idx in range(0, ndim):
- temp = np.sum(np.abs(powers_of_two * x[idx] - np.round(powers_of_two * x[idx])) * reciprocals_of_two)
+ temp = np.sum([np.abs(2 ** j * x[idx] - np.round(2 ** j * x[idx])) / 2 ** j for j in range(1, 33)])
result *= (1 + (idx + 1) * temp) ** (10.0 / ndim ** 1.2)
return (result - 1) * 10 / ndim ** 2
diff --git a/opfunu/utils/validator.py b/opfunu/utils/validator.py
deleted file mode 100644
index 6d36c75..0000000
--- a/opfunu/utils/validator.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-# Created by "Thieu" at 21:39, 29/06/2022 ----------%
-# Email: nguyenthieu2102@gmail.com %
-# Github: https://github.com/thieu1995 %
-# --------------------------------------------------%
-
-import operator
-import numpy as np
-
-
-def is_in_bound(value, bound):
- ops = None
- if type(bound) is tuple:
- ops = operator.lt
- elif type(bound) is list:
- ops = operator.le
- if bound[0] == float("-inf") and bound[1] == float("inf"):
- return True
- elif bound[0] == float("-inf") and ops(value, bound[1]):
- return True
- elif ops(bound[0], value) and bound[1] == float("inf"):
- return True
- elif ops(bound[0], value) and ops(value, bound[1]):
- return True
- return False
-
-
-def is_str_in_list(value: str, my_list: list):
- if type(value) == str and my_list is not None:
- return True if value in my_list else False
- return False
-
-
-def check_int(name: str, value: int, bound=None):
- if type(value) in [int, float]:
- if bound is None:
- return int(value)
- elif is_in_bound(value, bound):
- return int(value)
- bound = "" if bound is None else f"and value should be in range: {bound}"
- raise ValueError(f"'{name}' is an integer {bound}.")
-
-
-def check_float(name: str, value: int, bound=None):
- if type(value) in [int, float]:
- if bound is None:
- return float(value)
- elif is_in_bound(value, bound):
- return float(value)
- bound = "" if bound is None else f"and value should be in range: {bound}"
- raise ValueError(f"'{name}' is a float {bound}.")
-
-
-def check_str(name: str, value: str, bound=None):
- if type(value) is str:
- if bound is None or is_str_in_list(value, bound):
- return value
- bound = "" if bound is None else f"and value should be one of this: {bound}"
- raise ValueError(f"'{name}' is a string {bound}.")
-
-
-def check_bool(name: str, value: bool, bound=(True, False)):
- if type(value) is bool:
- if value in bound:
- return value
- bound = "" if bound is None else f"and value should be one of this: {bound}"
- raise ValueError(f"'{name}' is a boolean {bound}.")
-
-
-def check_tuple_int(name: str, values: tuple, bounds=None):
- if type(values) in [tuple, list] and len(values) > 1:
- value_flag = [type(item) == int for item in values]
- if np.all(value_flag):
- if bounds is not None and len(bounds) == len(values):
- value_flag = [is_in_bound(item, bound) for item, bound in zip(values, bounds)]
- if np.all(value_flag):
- return values
- else:
- return values
- bounds = "" if bounds is None else f"and values should be in range: {bounds}"
- raise ValueError(f"'{name}' are integer {bounds}.")
-
-
-def check_tuple_float(name: str, values: tuple, bounds=None):
- if type(values) in [tuple, list] and len(values) > 1:
- value_flag = [type(item) in [int, float] for item in values]
- if np.all(value_flag):
- if bounds is not None and len(bounds) == len(values):
- value_flag = [is_in_bound(item, bound) for item, bound in zip(values, bounds)]
- if np.all(value_flag):
- return values
- else:
- return values
- bounds = "" if bounds is None else f"and values should be in range: {bounds}"
- raise ValueError(f"'{name}' are float {bounds}.")
diff --git a/opfunu/utils/visualize.py b/opfunu/utils/visualize.py
index 543995d..54522dd 100644
--- a/opfunu/utils/visualize.py
+++ b/opfunu/utils/visualize.py
@@ -4,80 +4,373 @@
# Github: https://github.com/thieu1995 %
# --------------------------------------------------%
+import re
from io import BytesIO
+from pathlib import Path
import matplotlib.pyplot as plt
+import platform
import numpy as np
import requests
from PIL import Image
from matplotlib import cm
+from matplotlib.ticker import ScalarFormatter, FuncFormatter
+
cmap = [(0, '#2f9599'), (0.45, '#eeeeee'), (1, '#8800ff')]
cmap = cm.colors.LinearSegmentedColormap.from_list('Custom', cmap, N=256)
+SUPPORTED_ARRAY = (list, tuple, np.ndarray)
+
+
+def __clean_filename__(filename):
+ chars_to_remove = ["`", "~", "!", "@", "#", "$", "%", "^", "&", "*", ":", ",", "<", ">", ";", "+", "|"]
+ regular_expression = '[' + re.escape(''.join(chars_to_remove)) + ']'
+
+ temp = filename.encode("ascii", "ignore")
+ fname = temp.decode() # Removed all non-ascii characters
+ fname = re.sub(regular_expression, '', fname) # Removed all special characters
+ fname.replace("_", "-") # Replaced _ by -
+ return fname
+
+
+def __check_filepath__(filename):
+ filename.replace("\\", "/") # For better handling the parent folder
+ if "/" in filename:
+ list_names = filename.split("/")[:-1] # Remove last element because it is filename
+ filepath = "/".join(list_names)
+ Path(filepath).mkdir(parents=True, exist_ok=True)
+ return filename
-def plot_latex_formula(latex):
- base_url = r'https://latex.codecogs.com/png.latex?\dpi{400}'
+def custom_formatter(x, pos):
+ # Define a custom tick formatter function
+ if abs(x) >= 1e4:
+ return '{:.1e}'.format(x)
+ else:
+ return '{:.2f}'.format(x)
+
+
+def draw_latex(latex, title="Latex equation", figsize=(8, 3), dpi=500,
+ filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw latex equation.
+
+ Parameters
+ ----------
+ latex : equation
+ Your latex equation, you can test on the website: https://latex.codecogs.com/
+ title : str
+ Title for the figure
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ dpi : int, default=500
+ The dot per inches (DPI) - indicate the number of dots per inch.
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ base_url = 'https://latex.codecogs.com/png.latex?\dpi{' + str(dpi) + '}'
url = f'{base_url}{latex}'
response = requests.get(url)
img = Image.open(BytesIO(response.content))
+ plt.rcParams.update({'font.size': 14})
+ plt.figure(figsize=figsize, dpi=dpi)
plt.imshow(img)
+ plt.title(title)
plt.axis('off')
- plt.show()
+
+ if filename is not None:
+ filepath = __check_filepath__(__clean_filename__(filename))
+ for idx, ext in enumerate(exts):
+ plt.savefig(f"{filepath}{ext}", bbox_inches='tight')
+ # img.convert('RGB').save(f'{filepath}{ext}')
+ if platform.system() != "Linux" and verbose:
+ plt.show()
+ plt.close()
-def plot_2d(func, n_space=1000, cmap=cmap, XYZ=None, ax=None, show=True):
- X_domain, Y_domain = func.bounds
- if XYZ is None:
- X, Y = np.linspace(*X_domain, n_space), np.linspace(*Y_domain, n_space)
- X, Y = np.meshgrid(X, Y)
- XY = np.array([X, Y])
- Z = np.apply_along_axis(func.evaluate, 0, XY)
+def draw_2d(func, lb=None, ub=None, selected_dims=None, n_points=1000,
+ ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None,
+ title="Contour map of the function", x_label=None, y_label=None,
+ figsize=(10, 8), filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw 2D contour of the function.
+
+ Parameters
+ ----------
+ func : callable
+ The callable function that is used to calculate the value
+ lb : list, tuple, np.ndarray
+ The lower bound of the variables, should be a list, tuple, or numpy array.
+ ub : list, tuple, np.ndarray
+ The upper bound of the variables, should be a list, tuple, or numpy array.
+ selected_dims : list, tuple, np.ndarray
+ The selected dimensions you want to draw.
+ If your function has only 2 dimensions, it will select (1, 2) automatically.
+ n_points : int
+ The number of points that will be used to draw the contour
+ ct_cmap : str
+ The cmap of matplotlib.pyplot.contourf function (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contourf.html)
+ ct_levels : int
+ The levels parameter of contourf function
+ ct_alpha : float
+ The alpha parameter of contourf function
+ fixed_strategy : str
+ The selected strategy to set values for other dimensions.
+ When your function has > 2 dimensions, you need to set a fixed value for other dimensions to be able to calculate value.
+ List of available strategy: ["min", "max", "mean', "values", "zero"]
+ + min: Set the other dimensions by its lower bound
+ + max: Set the other dimensions by its upper bound
+ + mean: Set the other dimensions by it average value (lower bound + upper bound) / 2
+ + zero: Set the other dimensions by 0
+ + values: Set the other dimensions by your passed values through the parameter: `fixed_values`.
+
+ fixed_values : list, tuple, np.ndarray
+ Fixed values for all dimensions (length should be the same as lower bound), the selected dimensions will be replaced in the drawing process.
+ title : str
+ Title for the figure
+ x_label : str
+ Set the x label
+ y_label : str
+ Set the y label
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ if isinstance(lb, SUPPORTED_ARRAY) and isinstance(ub, SUPPORTED_ARRAY):
+ if len(lb) == len(ub):
+ lb = np.array(lb)
+ ub = np.array(ub)
+ else:
+ raise ValueError(f"Length of lb and ub should be equal.")
+ else:
+ raise TypeError(f"Type of lb and ub should be a list, tuple or np.ndarray.")
+ if len(lb) == 2 or selected_dims is None:
+ selected_dims = (1, 2)
+ if isinstance(selected_dims, SUPPORTED_ARRAY) and len(selected_dims) == 2:
+ selected_dims = tuple(selected_dims)
else:
- X, Y, Z = XYZ
-
- # create new ax if None
- if ax is None:
- fig = plt.figure()
- ax = fig.add_subplot(1, 1, 1)
- # add contours and contours lines
- # ax.contour(X, Y, Z, levels=30, linewidths=0.5, colors='#999')
- ax.contourf(X, Y, Z, levels=30, cmap=cmap, alpha=0.7)
-
- # add labels and set equal aspect ratio
- ax.set_xlabel('X')
- ax.set_ylabel('Y')
- ax.set_aspect(aspect='equal')
- if show:
+ raise TypeError(f"selected_dims should be a list of 2 selected dimensions.")
+
+ selected_dims = (min(selected_dims), max(selected_dims))
+ if selected_dims[0] < 1 or selected_dims[1] > len(lb):
+ raise ValueError(f"The selected_dims's values should >= 1 and <= {len(lb)}.")
+ idx_dims = (selected_dims[0] - 1, selected_dims[1] - 1)
+
+ # Generate a grid of points for the d1-th and d2-th dimensions
+ d1 = np.linspace(lb[idx_dims[0]], ub[idx_dims[0]], n_points)
+ d2 = np.linspace(lb[idx_dims[1]], ub[idx_dims[1]], n_points)
+ D1, D2 = np.meshgrid(d1, d2)
+
+ # Fix the other dimensions to zero (or another value within the domain)
+ if fixed_strategy == "mean":
+ mm_values = (lb + ub) / 2
+ elif fixed_strategy == "min":
+ mm_values = lb
+ elif fixed_strategy == "max":
+ mm_values = ub
+ elif fixed_strategy == "values":
+ mm_values = fixed_values
+ else:
+ mm_values = np.zeros(len(lb))
+
+ # Combine the fixed and varying dimensions into a single array
+ solution = np.full((n_points, n_points, len(lb)), np.array(mm_values))
+ solution[:, :, idx_dims[0]] = D1 # d1-th dimension
+ solution[:, :, idx_dims[1]] = D2 # d2-th dimension
+
+ # Compute the function values using vectorized operations
+ Z = np.apply_along_axis(func, axis=-1, arr=solution)
+
+ # Plot the function
+ plt.rcParams.update({'font.size': 14})
+ plt.figure(figsize=figsize)
+
+ cont = plt.contourf(D1, D2, Z, levels=ct_levels, cmap=ct_cmap, alpha=ct_alpha)
+ cbar = plt.colorbar(cont)
+ cbar.set_label('Function Value')
+ # cbar.formatter = ScalarFormatter()
+ # cbar.formatter.set_scientific(True)
+ # cbar.formatter.set_powerlimits((-2, 2))
+ # cbar.update_ticks()
+
+ cbar.formatter = FuncFormatter(custom_formatter)
+ cbar.update_ticks()
+
+ plt.title(title)
+ if x_label is None:
+ x_label = f'Dimension X{selected_dims[0]}'
+ if y_label is None:
+ y_label = f'Dimension X{selected_dims[1]}'
+ plt.xlabel(x_label)
+ plt.ylabel(y_label)
+
+ if filename is not None:
+ filepath = __check_filepath__(__clean_filename__(filename))
+ for idx, ext in enumerate(exts):
+ plt.savefig(f"{filepath}{ext}", bbox_inches='tight')
+ if platform.system() != "Linux" and verbose:
plt.show()
+ plt.close()
-def plot_3d(func, n_space=1000, cmap=cmap, XYZ=None, ax=None, show=True):
- X_domain, Y_domain = func.bounds
- if XYZ is None:
- X, Y = np.linspace(*X_domain, n_space), np.linspace(*Y_domain, n_space)
- X, Y = np.meshgrid(X, Y)
- XY = np.array([X, Y])
- Z = np.apply_along_axis(func.evaluate, 0, XY)
+def draw_3d(func, lb=None, ub=None, selected_dims=None, n_points=1000,
+ ct_cmap="viridis", ct_levels=30, ct_alpha=0.7,
+ fixed_strategy="mean", fixed_values=None,
+ title="3D visualization of the function", x_label=None, y_label=None,
+ figsize=(10, 8), filename=None, exts=(".png", ".pdf"), verbose=True):
+ """
+ Draw 3D of the function.
+
+ Parameters
+ ----------
+ func : callable
+ The callable function that is used to calculate the value
+ lb : list, tuple, np.ndarray
+ The lower bound of the variables, should be a list, tuple, or numpy array.
+ ub : list, tuple, np.ndarray
+ The upper bound of the variables, should be a list, tuple, or numpy array.
+ selected_dims : list, tuple, np.ndarray
+ The selected dimensions you want to draw.
+ If your function has only 2 dimensions, it will select (1, 2) automatically.
+ n_points : int
+ The number of points that will be used to draw the contour
+ ct_cmap : str
+ The cmap of matplotlib.pyplot.contourf function (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contourf.html)
+ ct_levels : int
+ The levels parameter of contourf function
+ ct_alpha : float
+ The alpha parameter of contourf function
+ fixed_strategy : str
+ The selected strategy to set values for other dimensions.
+ When your function has > 2 dimensions, you need to set a fixed value for other dimensions to be able to calculate value.
+ List of available strategy: ["min", "max", "mean', "values", "zero"]
+ + min: Set the other dimensions by its lower bound
+ + max: Set the other dimensions by its upper bound
+ + mean: Set the other dimensions by it average value (lower bound + upper bound) / 2
+ + zero: Set the other dimensions by 0
+ + values: Set the other dimensions by your passed values through the parameter: `fixed_values`.
+
+ fixed_values : list, tuple, np.ndarray
+ Fixed values for all dimensions (length should be the same as lower bound), the selected dimensions will be replaced in the drawing process.
+ title : str
+ Title for the figure
+ x_label : str
+ Set the x label
+ y_label : str
+ Set the y label
+ figsize : tuple, default=(10, 8)
+ The figure size with format of tuple (width, height)
+ filename : str, default = None
+ Set the file name, If None, the file will not be saved
+ exts : list, tuple, np.ndarray
+ The list of extensions to save file, for example: (".png", ".pdf", ".jpg")
+ verbose : bool
+ Show the figure or not. It will not show on linux system.
+ """
+ if isinstance(lb, SUPPORTED_ARRAY) and isinstance(ub, SUPPORTED_ARRAY):
+ if len(lb) == len(ub):
+ lb = np.array(lb)
+ ub = np.array(ub)
+ else:
+ raise ValueError(f"Length of lb and ub should be equal.")
+ else:
+ raise TypeError(f"Type of lb and ub should be a list, tuple or np.ndarray.")
+ if len(lb) == 2 or selected_dims is None:
+ selected_dims = (1, 2)
+ if isinstance(selected_dims, SUPPORTED_ARRAY) and len(selected_dims) == 2:
+ selected_dims = tuple(selected_dims)
else:
- X, Y, Z = XYZ
-
- # create new ax if None
- if ax is None:
- fig = plt.figure()
- ax = fig.add_subplot(1, 1, 1, projection='3d')
-
- # Plot the surface.
- ax.plot_surface(X, Y, Z, cmap=cmap, linewidth=0, antialiased=True, alpha=0.7)
- ax.contour(X, Y, Z, zdir='z', levels=30, offset=np.min(Z), cmap=cmap)
-
- ax.xaxis.pane.fill = False
- ax.yaxis.pane.fill = False
- ax.zaxis.pane.fill = False
- ax.set_xlabel('X')
- ax.set_ylabel('Y')
- ax.xaxis.set_tick_params(labelsize=8)
- ax.yaxis.set_tick_params(labelsize=8)
- ax.zaxis.set_tick_params(labelsize=8)
- if show:
+ raise TypeError(f"selected_dims should be a list of 2 selected dimensions.")
+
+ selected_dims = (min(selected_dims), max(selected_dims))
+ if selected_dims[0] < 1 or selected_dims[1] > len(lb):
+ raise ValueError(f"The selected_dims's values should >= 1 and <= {len(lb)}.")
+ idx_dims = (selected_dims[0] - 1, selected_dims[1] - 1)
+
+ # Generate a grid of points for the d1-th and d2-th dimensions
+ d1 = np.linspace(lb[idx_dims[0]], ub[idx_dims[0]], n_points)
+ d2 = np.linspace(lb[idx_dims[1]], ub[idx_dims[1]], n_points)
+ D1, D2 = np.meshgrid(d1, d2)
+
+ # Fix the other dimensions to zero (or another value within the domain)
+ if fixed_strategy == "mean":
+ mm_values = (lb + ub) / 2
+ elif fixed_strategy == "min":
+ mm_values = lb
+ elif fixed_strategy == "max":
+ mm_values = ub
+ elif fixed_strategy == "values":
+ mm_values = fixed_values
+ else:
+ mm_values = np.zeros(len(lb))
+
+ # Combine the fixed and varying dimensions into a single array
+ solution = np.full((n_points, n_points, len(lb)), np.array(mm_values))
+ solution[:, :, idx_dims[0]] = D1 # d1-th dimension
+ solution[:, :, idx_dims[1]] = D2 # d2-th dimension
+
+ # Compute the function values using vectorized operations
+ Z = np.apply_along_axis(func, axis=-1, arr=solution)
+
+ # Plot the function
+ plt.rcParams.update({'font.size': 14})
+
+ # Create a 3D plot
+ fig = plt.figure(figsize=figsize)
+ ax = fig.add_subplot(111, projection='3d')
+
+ # Plot the surface
+ surf = ax.plot_surface(D1, D2, Z, cmap=ct_cmap, edgecolor='none', alpha=ct_alpha)
+
+ # Add contours
+ ax.contour(D1, D2, Z, zdir='z', offset=np.min(Z), cmap=ct_cmap, levels=ct_levels)
+
+ # Add a color bar which maps values to colors
+ cbar_ax = fig.add_axes([0.825, 0.175, 0.05, 0.55])
+ cbar = fig.colorbar(surf, cax=cbar_ax, label='Function Value', shrink=0.5, aspect=5,)
+ # cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=5, label='Function Value')
+ cbar.formatter = ScalarFormatter()
+ cbar.formatter.set_scientific(True)
+ cbar.formatter.set_powerlimits((-2, 2))
+ cbar.update_ticks()
+
+ # Apply the custom tick formatter to the color bar
+ cbar_ax.yaxis.set_major_formatter(FuncFormatter(custom_formatter))
+
+ if x_label is None:
+ x_label = f'Dimension X{selected_dims[0]}'
+ if y_label is None:
+ y_label = f'Dimension X{selected_dims[1]}'
+ # Set plot title and labels with increased padding
+ ax.set_title(title)
+ ax.set_xlabel(x_label, labelpad=10)
+ ax.set_ylabel(y_label, labelpad=10)
+ ax.set_zlabel("Function Value", labelpad=16)
+
+ # Set the elevation and azimuth angles to adjust the viewing angle
+ ax.view_init(elev=20, azim=-120)
+
+ # Use scientific notation for large tick values
+ formatter = ScalarFormatter()
+ formatter.set_scientific(True)
+ formatter.set_powerlimits((-2, 2))
+ # Apply the custom tick formatter to the z-axis
+ ax.zaxis.set_major_formatter(FuncFormatter(custom_formatter))
+
+ if filename is not None:
+ filepath = __check_filepath__(__clean_filename__(filename))
+ for idx, ext in enumerate(exts):
+ plt.savefig(f"{filepath}{ext}", bbox_inches='tight')
+ if platform.system() != "Linux" and verbose:
plt.show()
+ plt.close()
diff --git a/tests/cec_based/test_cec2013.py b/tests/cec_based/test_cec2013.py
index a07360d..a27d397 100644
--- a/tests/cec_based/test_cec2013.py
+++ b/tests/cec_based/test_cec2013.py
@@ -403,7 +403,7 @@ def test_F282013_results():
def test_all_optimal_results():
ndim = 30
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2013' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(ndim=ndim)
diff --git a/tests/cec_based/test_cec2014.py b/tests/cec_based/test_cec2014.py
index 1e7de3a..d43f982 100644
--- a/tests/cec_based/test_cec2014.py
+++ b/tests/cec_based/test_cec2014.py
@@ -430,7 +430,7 @@ def test_F302014_results():
def test_all_optimal_results():
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2014' and x.__name__ not in known_failing]
for function in all_functions:
problem = function()
diff --git a/tests/cec_based/test_cec2015.py b/tests/cec_based/test_cec2015.py
index 1dc45f7..7a9d853 100644
--- a/tests/cec_based/test_cec2015.py
+++ b/tests/cec_based/test_cec2015.py
@@ -220,7 +220,7 @@ def test_F152015_results():
def test_all_optimal_results():
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2015' and x.__name__ not in known_failing]
for function in all_functions:
problem = function()
diff --git a/tests/cec_based/test_cec2017.py b/tests/cec_based/test_cec2017.py
index f59c939..d960cb9 100644
--- a/tests/cec_based/test_cec2017.py
+++ b/tests/cec_based/test_cec2017.py
@@ -417,7 +417,7 @@ def test_F292017_results():
def test_all_optimal_results():
ndim = 30
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2017' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(ndim=ndim)
diff --git a/tests/cec_based/test_cec2019.py b/tests/cec_based/test_cec2019.py
index ec276c3..926e856 100644
--- a/tests/cec_based/test_cec2019.py
+++ b/tests/cec_based/test_cec2019.py
@@ -150,7 +150,7 @@ def test_F102019_results():
def test_all_optimal_results():
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2019' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(10)
diff --git a/tests/cec_based/test_cec2020.py b/tests/cec_based/test_cec2020.py
index 0a87dc0..3f5da66 100644
--- a/tests/cec_based/test_cec2020.py
+++ b/tests/cec_based/test_cec2020.py
@@ -151,7 +151,7 @@ def test_F102020_results():
def test_all_optimal_results():
ndim = 30
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2020' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(ndim=ndim)
diff --git a/tests/cec_based/test_cec2021.py b/tests/cec_based/test_cec2021.py
index ccf0b40..6c1d985 100644
--- a/tests/cec_based/test_cec2021.py
+++ b/tests/cec_based/test_cec2021.py
@@ -151,7 +151,7 @@ def test_F102021_results():
def test_all_optimal_results():
ndim = 10
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2021' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(ndim=ndim)
diff --git a/tests/cec_based/test_cec2022.py b/tests/cec_based/test_cec2022.py
index dcb094c..8d2606a 100644
--- a/tests/cec_based/test_cec2022.py
+++ b/tests/cec_based/test_cec2022.py
@@ -179,7 +179,7 @@ def test_F122022_results():
def test_all_optimal_results():
ndim = 10
known_failing = []
- all_functions = [x for x in opfunu.get_all_cec_functions()
+ all_functions = [x for x in opfunu.get_all_cec_based_functions()
if x.__name__[-4:] == '2022' and x.__name__ not in known_failing]
for function in all_functions:
problem = function(ndim=ndim)
diff --git a/tests/cec_based/test_cec_based.py b/tests/cec_based/test_cec_based.py
index a825875..4704820 100644
--- a/tests/cec_based/test_cec_based.py
+++ b/tests/cec_based/test_cec_based.py
@@ -4,11 +4,11 @@
# --------------------------------------------------%
import numpy as np
-from opfunu import get_all_cec_functions
+from opfunu import get_all_cec_based_functions
def test_whenNdimNone_thenDefaultNdimUsed():
- allFunctions = get_all_cec_functions()
+ allFunctions = get_all_cec_based_functions()
for f in allFunctions:
f_default = f()
assert f_default.ndim == f_default.dim_default, f'{f.__name__} failed to have ndim == dim_default'
@@ -16,7 +16,7 @@ def test_whenNdimNone_thenDefaultNdimUsed():
def test_whenEvaulateDefaultNdim_thenHasResult():
known_failing = []
- all_functions = [x for x in get_all_cec_functions() if x.__name__ not in known_failing]
+ all_functions = [x for x in get_all_cec_based_functions() if x.__name__ not in known_failing]
failing = []
for f in all_functions:
f_default = f()
@@ -33,7 +33,7 @@ def test_whenEvaulateDefaultNdim_thenHasResult():
def test_whenEvaulateWith_x_global_then_f_global():
# The following are broken or have incorrect or unknown correct , values.
known_failing = ['F72008']
- all_functions = [x for x in get_all_cec_functions() if x.__name__ not in known_failing]
+ all_functions = [x for x in get_all_cec_based_functions() if x.__name__ not in known_failing]
failing = []
for f in all_functions:
f_default = f()