From 80053e8e674c59e473589ae84f627e05d39343cc Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:02:47 -0600 Subject: [PATCH 1/9] Modernize package definition --- .coveragerc | 28 --------- .flake8 | 4 +- .gitignore | 55 ++++++++++++++++ .isort.cfg | 5 -- .pre-commit-config.yaml | 61 ++++++++---------- MANIFEST.in | 9 --- pyproject.toml | 135 ++++++++++++++++++++++++++++++++++++++-- requirements.txt | 4 -- setup.cfg | 126 ------------------------------------- setup.py | 21 ------- tox.ini | 38 +++++++---- 11 files changed, 239 insertions(+), 247 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .isort.cfg delete mode 100644 MANIFEST.in delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 4a63307..0000000 --- a/.coveragerc +++ /dev/null @@ -1,28 +0,0 @@ -# .coveragerc to control coverage.py -[run] -branch = True -source = benchmarking -# omit = bad_file.py - -[paths] -source = - src/ - */site-packages/ - -[report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about missing debug-only code: - def __repr__ - if self\.debug - - # Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - - # Don't complain if non-runnable code isn't run: - if 0: - if __name__ == .__main__.: diff --git a/.flake8 b/.flake8 index 5cfa070..8d80798 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] # Global ignores -ignore = +ignore = # trailing whitespace W291, # line break before binary operator @@ -9,7 +9,7 @@ ignore = W504 # Per-file ignores -per-file-ignores = +per-file-ignores = # imported but unused __init__.py:F401 diff --git a/.gitignore b/.gitignore index b6e4761..10ce677 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,58 @@ dmypy.json # Pyre type checker .pyre/ + +# Temporary and binary files +*~ +*.py[cod] +*.so +*.cfg +!.isort.cfg +!setup.cfg +*.orig +*.log +*.pot +__pycache__/* +.cache/* +.*.swp +*/.ipynb_checkpoints/* +.DS_Store + +# Project files +.ropeproject +.project +.pydevproject +.settings +.idea +.vscode +tags + +# Package files +*.egg +*.eggs/ +.installed.cfg +*.egg-info + +# Unittest and coverage +htmlcov/* +.coverage +.coverage.* +.tox +junit*.xml +coverage.xml +.pytest_cache/ + +# Build and docs folder/files +**/build/* +**/dist/* +**/sdist/* +docs/source/api/* +docs/source/_rst/* +docs/build/* +cover/* +MANIFEST + +# Per-project virtualenvs +**/venv*/ +**/*conda*/ +.python-version diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index 53079a4..0000000 --- a/.isort.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[settings] -profile = black -known_first_party = benchmarking -multi_line_output = 3 -line_length = 79 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 682d599..8ed430b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,8 @@ -exclude: '^docs/conf.py' +exclude: '^docs/source/conf.py' repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: check-added-large-files @@ -17,51 +17,42 @@ repos: - id: mixed-line-ending args: ['--fix=auto'] # replace 'auto' with 'lf' to enforce Linux/Mac line endings or 'crlf' for Windows -## If you want to automatically "modernize" your Python code: -# - repo: https://github.com/asottile/pyupgrade -# rev: v3.3.1 -# hooks: -# - id: pyupgrade -# args: ['--py37-plus'] - -## If you want to avoid flake8 errors due to unused vars or imports: -# - repo: https://github.com/PyCQA/autoflake -# rev: v2.0.2 -# hooks: -# - id: autoflake -# args: [ -# --in-place, -# --remove-all-unused-imports, -# --remove-unused-variables, -# ] - -- repo: https://github.com/PyCQA/isort - rev: 5.12.0 +- repo: https://github.com/pycqa/isort + rev: 9.0.0b1 hooks: - id: isort - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 26.5.1 hooks: - id: black language_version: python3 -## If like to embrace black styles even in the docs: -# - repo: https://github.com/asottile/blacken-docs -# rev: v1.13.0 -# hooks: -# - id: blacken-docs -# additional_dependencies: [black] +- repo: https://github.com/LilSpazJoekp/docstrfmt + rev: v2.2.0 + hooks: + - id: docstrfmt + language_version: python3 + types_or: [rst] # Options are [python, rst, txt] - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 7.3.0 hooks: - id: flake8 ## You can add flake8 plugins via `additional_dependencies`: # additional_dependencies: [flake8-bugbear] -## Check for misspells in documentation files: -# - repo: https://github.com/codespell-project/codespell -# rev: v2.2.4 -# hooks: -# - id: codespell +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v2.3.0 + hooks: + - id: mypy + args: [--ignore-missing-imports, "--config-file=pyproject.toml"] + # NOTE: Any changes to exclude here need to be made in pyproject.toml, too! + exclude: | + (?x)( + ^setup.py$ | + ^build | + ^venv | + ^docs | + ^tests + ) diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 552fde3..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include setup.py -include MANIFEST.in -include LICENSE -include README.md - -graft tests -graft examples -graft docs -graft src diff --git a/pyproject.toml b/pyproject.toml index 0166480..a32587f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,137 @@ [build-system] -# AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD! -requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=5"] +requires = ["setuptools>=64", "setuptools_scm[toml]>=8"] build-backend = "setuptools.build_meta" +[project] +name = "benchmarking" +description = "A collection of benchmarking functions for optimization algorithms." +authors = [ + { name = "dulithaprasanna", email = "dulithaprasanna@gmail.com" }, + { name = "zachcran", email = "zachcran@iastate.edu" }, +] +maintainers = [{ name = "zachcran", email = "zachcran@iastate.edu" }] +dependencies = ["matplotlib", "numpy"] +dynamic = ["version"] +requires-python = ">=3.9, <4" +license = "MIT" +license-files = ["LICENSE.txt"] +readme = { file = "README.rst", content-type = "text/x-rst" } +keywords = ["benchmarking"] + +classifiers = [ + "Private :: Do Not Upload", + + "Development Status :: 4 - Beta", + "Natural Language :: English", + "Typing :: Typed", + + # Intended audience tags and other information about what this project is + "Intended Audience :: Science/Research", + "Environment :: Console", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Chemistry", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Software Development :: Libraries :: Python Modules", + + # Supported Python versions and operating systems + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3 :: Only", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Operating System :: Microsoft :: Windows :: Windows 10", + "Operating System :: Microsoft :: Windows :: Windows 11", + # Untested, but likely works + # "Operating System :: MacOS :: MacOS X" +] + +[project.urls] +Documentation = "https://RxnRover.github.io/benchmarking" +Source = "https://github.com/RxnRover/benchmarking" +Tracker = "https://github.com/RxnRover/benchmarking/issues" +Download = "https://github.com/RxnRover/benchmarking/archive/refs/heads/main.zip" +Changelog = "https://github.com/RxnRover/benchmarking/releases/latest" + +# Install these optional development dependencies with pip's --group flag while +# in the project root directory. +# Example: pip install --group dev +[dependency-groups] +docs = ["sphinx>=3.2.1", "sphinx_rtd_theme"] +test = [ + "setuptools", + "pytest", + "pytest-cov", + "pytest-xdist", +] +dev = [ + "tox", + "pre-commit", + { include-group = "docs" }, + { include-group = "test" }, +] + [tool.setuptools_scm] -# For smarter version schemes and other configuration options, -# check out https://github.com/pypa/setuptools_scm +# For more options, see https://github.com/pypa/setuptools_scm version_scheme = "no-guess-dev" [tool.black] -line-length = 79 +line-length = 80 + +[tool.docstrfmt] +line_length = 80 + +[tool.isort] +profile = "black" +known_first_party = "benchmarking" +multi_line_output = 3 +line_length = 80 + +[tool.pytest.ini_options] +# Enable log display during test runs with --strict-markers +# See: https://docs.pytest.org/en/latest/how-to/logging.html#live-logs +addopts = "--cov benchmarking --cov-report term-missing --verbose --strict-markers" +norecursedirs = "dist build .tox" +testpaths = ["tests"] +log_cli = true + +# Use pytest markers to select/deselect specific tests +markers = [ + "individual: Marks tests that need to run in an individual pytest run (deselect with '-m \"not individual\"'", +] + +[tool.coverage.run] +branch = true +source = ["benchmarking"] +# omit = bad_file.py + +[tool.coverage.paths] +source = ["src/", "*/site-packages/"] + +[tool.coverage.report] +exclude_lines = [ + # Have to re-enable the standard pragma + "pragma: no cover", + + # Don't complain about missing debug-only code: + "def __repr__", + "if self\\.debug", + + # Don't complain if tests don't hit defensive assertion code: + "raise AssertionError", + "raise NotImplementedError", + + # Don't complain if non-runnable code isn't run: + "if 0:", + "if __name__ == .__main__.:", +] # Regexes for lines to exclude from consideration + +[tool.mypy] +disallow_untyped_defs = true +# Any changes to exclude here need to be made in .pre-commit-config.yaml, too! +# This exclude list doesn't work because of the way pre-commit invokes mypy +exclude = ['^setup.py$', '^build', '^venv', '^docs', '^tests'] + +[[tool.mypy.overrides]] +module = "benchmarking.*" +disallow_incomplete_defs = true diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 3895af8..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ --e . -matplotlib -numpy -tox diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 32d9857..0000000 --- a/setup.cfg +++ /dev/null @@ -1,126 +0,0 @@ -# This file is used to configure your project. -# Read more about the various options under: -# https://setuptools.pypa.io/en/latest/userguide/declarative_config.html -# https://setuptools.pypa.io/en/latest/references/keywords.html - -[metadata] -name = benchmarking -description = A collection of benchmarking functions for optimization algorithms -author = zachcran -author_email = zachcran@gmail.com -license = MIT -license_files = LICENSE.txt -long_description = file: README.rst -long_description_content_type = text/x-rst; charset=UTF-8 -url = https://github.com/RxnRover/benchmarking -# Add here related links, for example: -project_urls = - Documentation = https://RxnRover.github.io/benchmarking - Source = https://github.com/RxnRover/benchmarking/ -# Changelog = https://pyscaffold.org/en/latest/changelog.html -# Tracker = https://github.com/pyscaffold/pyscaffold/issues -# Conda-Forge = https://anaconda.org/conda-forge/pyscaffold -# Download = https://pypi.org/project/PyScaffold/#files -# Twitter = https://twitter.com/PyScaffold - -# Change if running only on Windows, Mac or Linux (comma-separated) -platforms = any - -# Add here all kinds of additional classifiers as defined under -# https://pypi.org/classifiers/ -classifiers = - Development Status :: 4 - Beta - Programming Language :: Python - - -[options] -zip_safe = False -packages = find_namespace: -include_package_data = True -package_dir = - =src - -# Require a min/specific Python version (comma-separated conditions) -# python_requires = >=3.8 - -# Add here dependencies of your project (line-separated), e.g. requests>=2.2,<3.0. -# Version specifiers like >=2.2,<3.0 avoid problems due to API changes in -# new major versions. This works if the required packages follow Semantic Versioning. -# For more information, check out https://semver.org/. -install_requires = - importlib-metadata; python_version<"3.8" - matplotlib - numpy - -[options.packages.find] -where = src -exclude = - tests - -[options.extras_require] -# Add here additional requirements for extra features, to install with: -# `pip install benchmarking[PDF]` like: -# PDF = ReportLab; RXP - -# Add here test requirements (semicolon/line-separated) -testing = - setuptools - pytest - pytest-cov - -[options.entry_points] -# console_scripts = -# analyze_results = benchmarking.apps.main:main -# For example: -# console_scripts = -# fibonacci = benchmarking.skeleton:run -# And any other entry points, for example: -# pyscaffold.cli = -# awesome = pyscaffoldext.awesome.extension:AwesomeExtension - -[tool:pytest] -# Specify command line options as you would do when invoking pytest directly. -# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml -# in order to write a coverage file that can be read by Jenkins. -# CAUTION: --cov flags may prohibit setting breakpoints while debugging. -# Comment those flags to avoid this pytest issue. -addopts = - --cov benchmarking --cov-report term-missing - --verbose -norecursedirs = - dist - build - .tox -testpaths = tests/benchmarking -# Use pytest markers to select/deselect specific tests -# markers = -# slow: mark tests as slow (deselect with '-m "not slow"') -# system: mark end-to-end system tests - -[devpi:upload] -# Options for the devpi: PyPI server and packaging tool -# VCS export must be deactivated since we are using setuptools-scm -no_vcs = 1 -formats = bdist_wheel - -[flake8] -# Some sane defaults for the code style checker flake8 -max_line_length = 80 -extend_ignore = E203, W503, W605 -# ^ Black-compatible -# E203 and W503 have edge cases handled by black -exclude = - .tox - build - dist - .eggs - docs/conf.py - -[pyscaffold] -# PyScaffold's parameters when the project was created. -# This will be used when updating. Do not change! -version = 4.4.1 -package = benchmarking -extensions = - github_actions - pre_commit diff --git a/setup.py b/setup.py deleted file mode 100644 index 3c2d4d6..0000000 --- a/setup.py +++ /dev/null @@ -1,21 +0,0 @@ -""" - Setup file for benchmarking. - Use setup.cfg to configure your project. - - This file was generated with PyScaffold 4.4.1. - PyScaffold helps you to put up the scaffold of your new Python project. - Learn more under: https://pyscaffold.org/ -""" -from setuptools import setup - -if __name__ == "__main__": - try: - setup(use_scm_version={"version_scheme": "no-guess-dev"}) - except: # noqa - print( - "\n\nAn error occurred while building the project, " - "please ensure you have the most updated version of setuptools, " - "setuptools_scm and wheel with:\n" - " pip install -U setuptools setuptools_scm wheel\n\n" - ) - raise diff --git a/tox.ini b/tox.ini index 10ed2e6..343bbfb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ # Tox configuration file # Read more under https://tox.wiki/ -# THIS SCRIPT IS SUPPOSED TO BE AN EXAMPLE. MODIFY IT ACCORDING TO YOUR NEEDS! [tox] minversion = 3.24 @@ -15,8 +14,8 @@ setenv = passenv = HOME SETUPTOOLS_* -extras = - testing +dependency_groups = + test commands = pytest {posargs} @@ -47,31 +46,46 @@ deps = passenv = SETUPTOOLS_* commands = - clean: python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/_build")]' + clean: python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/build")]' clean: python -c 'import pathlib, shutil; [shutil.rmtree(p, True) for p in pathlib.Path("src").glob("*.egg-info")]' build: python -m build {posargs} -# By default, both `sdist` and `wheel` are built. If your sdist is too big or you don't want -# to make it available, consider running: `tox -e build -- --wheel` -[testenv:{docs,doctests,linkcheck}] +[testenv:{docs,doctests,linkcheck,viewdocs}] description = docs: Invoke sphinx-build to build the docs doctests: Invoke sphinx-build to run doctests linkcheck: Check for broken links in the documentation + viewdocs: Build the documentation and starts a local server hosting it passenv = SETUPTOOLS_* setenv = - DOCSDIR = {toxinidir}/docs/source + DOCSDIR = {toxinidir}/docs + SOURCEDIR = {toxinidir}/docs/source BUILDDIR = {toxinidir}/docs/build - docs: BUILD = html + {docs,viewdocs}: BUILD = html doctests: BUILD = doctest linkcheck: BUILD = linkcheck -deps = - -r {toxinidir}/docs/requirements.txt + viewdocs: PORT = 3000 +dependency_groups = + docs commands = - sphinx-build --color -b {env:BUILD} -d "{env:BUILDDIR}/doctrees" "{env:DOCSDIR}" "{env:BUILDDIR}/{env:BUILD}" {posargs} + sphinx-build --color -b {env:BUILD} -d "{env:BUILDDIR}/doctrees" "{env:SOURCEDIR}" "{env:BUILDDIR}/{env:BUILD}" {posargs} + viewdocs: python -m http.server {env:PORT} --directory "{env:BUILDDIR}/{env:BUILD}" +[testenv:{docformat}] +description = + docformat: Invoke docstrfmt to format the documentation +passenv = + SETUPTOOLS_* +setenv = + DOCSDIR = {toxinidir}/docs + PYPROJECT = {toxinidir}/pyproject.toml +deps = + docstrfmt +commands = + docformat: docstrfmt "{toxinidir}/README.rst" --pyproject-config {env:PYPROJECT} {posargs} + docformat: docstrfmt "{env:DOCSDIR}/source" --pyproject-config {env:PYPROJECT} -e docs/source/api {posargs} [testenv:publish] description = From bec2a8b227bfcd068b29afb7dca8e8697e12a1fc Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:03:45 -0600 Subject: [PATCH 2/9] Update documentation and some formatting/pre-commit --- AUTHORS.rst | 9 +- CONTRIBUTING.rst | 353 -------------------------------------- LICENSE.txt | 22 +-- README.rst | 31 ++++ README.txt | 67 -------- docs/README.rst | 43 ++--- docs/source/authors.rst | 3 + docs/source/changelog.rst | 3 + docs/source/conf.py | 289 +++++++++++++++++++++++++++++-- docs/source/index.rst | 34 ++-- docs/source/license.rst | 7 + docs/source/readme.rst | 3 + 12 files changed, 378 insertions(+), 486 deletions(-) delete mode 100644 CONTRIBUTING.rst create mode 100644 README.rst delete mode 100644 README.txt create mode 100644 docs/source/authors.rst create mode 100644 docs/source/changelog.rst create mode 100644 docs/source/license.rst create mode 100644 docs/source/readme.rst diff --git a/AUTHORS.rst b/AUTHORS.rst index 9d1f600..db8ab9d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,5 +1,6 @@ -============ -Contributors -============ +############## + Contributors +############## -* Zachery Crandall (@zachcran) +- dulithaprasanna +- zachcran diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 833dca6..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,353 +0,0 @@ -.. todo:: THIS IS SUPPOSED TO BE AN EXAMPLE. MODIFY IT ACCORDING TO YOUR NEEDS! - - The document assumes you are using a source repository service that promotes a - contribution model similar to `GitHub's fork and pull request workflow`_. - While this is true for the majority of services (like GitHub, GitLab, - BitBucket), it might not be the case for private repositories (e.g., when - using Gerrit). - - Also notice that the code examples might refer to GitHub URLs or the text - might use GitHub specific terminology (e.g., *Pull Request* instead of *Merge - Request*). - - Please make sure to check the document having these assumptions in mind - and update things accordingly. - -.. todo:: Provide the correct links/replacements at the bottom of the document. - -.. todo:: You might want to have a look on `PyScaffold's contributor's guide`_, - - especially if your project is open source. The text should be very similar to - this template, but there are a few extra contents that you might decide to - also include, like mentioning labels of your issue tracker or automated - releases. - - -============ -Contributing -============ - -Welcome to ``benchmarking`` contributor's guide. - -This document focuses on getting any potential contributor familiarized -with the development processes, but `other kinds of contributions`_ are also -appreciated. - -If you are new to using git_ or have never collaborated in a project previously, -please have a look at `contribution-guide.org`_. Other resources are also -listed in the excellent `guide created by FreeCodeCamp`_ [#contrib1]_. - -Please notice, all users and contributors are expected to be **open, -considerate, reasonable, and respectful**. When in doubt, `Python Software -Foundation's Code of Conduct`_ is a good reference in terms of behavior -guidelines. - - -Issue Reports -============= - -If you experience bugs or general issues with ``benchmarking``, please have a look -on the `issue tracker`_. If you don't see anything useful there, please feel -free to fire an issue report. - -.. tip:: - Please don't forget to include the closed issues in your search. - Sometimes a solution was already reported, and the problem is considered - **solved**. - -New issue reports should include information about your programming environment -(e.g., operating system, Python version) and steps to reproduce the problem. -Please try also to simplify the reproduction steps to a very minimal example -that still illustrates the problem you are facing. By removing other factors, -you help us to identify the root cause of the issue. - - -Documentation Improvements -========================== - -You can help improve ``benchmarking`` docs by making them more readable and coherent, or -by adding missing information and correcting mistakes. - -``benchmarking`` documentation uses Sphinx_ as its main documentation compiler. -This means that the docs are kept in the same repository as the project code, and -that any documentation update is done in the same way was a code contribution. - -.. todo:: Don't forget to mention which markup language you are using. - - e.g., reStructuredText_ or CommonMark_ with MyST_ extensions. - -.. todo:: If your project is hosted on GitHub, you can also mention the following tip: - - .. tip:: - Please notice that the `GitHub web interface`_ provides a quick way of - propose changes in ``benchmarking``'s files. While this mechanism can - be tricky for normal code contributions, it works perfectly fine for - contributing to the docs, and can be quite handy. - - If you are interested in trying this method out, please navigate to - the ``docs`` folder in the source repository_, find which file you - would like to propose changes and click in the little pencil icon at the - top, to open `GitHub's code editor`_. Once you finish editing the file, - please write a message in the form at the bottom of the page describing - which changes have you made and what are the motivations behind them and - submit your proposal. - -When working on documentation changes in your local machine, you can -compile them using |tox|_:: - - tox -e docs - -and use Python's built-in web server for a preview in your web browser -(``http://localhost:8000``):: - - python3 -m http.server --directory 'docs/_build/html' - - -Code Contributions -================== - -.. todo:: Please include a reference or explanation about the internals of the project. - - An architecture description, design principles or at least a summary of the - main concepts will make it easy for potential contributors to get started - quickly. - -Submit an issue ---------------- - -Before you work on any non-trivial code contribution it's best to first create -a report in the `issue tracker`_ to start a discussion on the subject. -This often provides additional considerations and avoids unnecessary work. - -Create an environment ---------------------- - -Before you start coding, we recommend creating an isolated `virtual -environment`_ to avoid any problems with your installed Python packages. -This can easily be done via either |virtualenv|_:: - - virtualenv - source /bin/activate - -or Miniconda_:: - - conda create -n benchmarking python=3 six virtualenv pytest pytest-cov - conda activate benchmarking - -Clone the repository --------------------- - -#. Create an user account on |the repository service| if you do not already have one. -#. Fork the project repository_: click on the *Fork* button near the top of the - page. This creates a copy of the code under your account on |the repository service|. -#. Clone this copy to your local disk:: - - git clone git@github.com:YourLogin/benchmarking.git - cd benchmarking - -#. You should run:: - - pip install -U pip setuptools -e . - - to be able to import the package under development in the Python REPL. - - .. todo:: if you are not using pre-commit, please remove the following item: - -#. Install |pre-commit|_:: - - pip install pre-commit - pre-commit install - - ``benchmarking`` comes with a lot of hooks configured to automatically help the - developer to check the code being written. - -Implement your changes ----------------------- - -#. Create a branch to hold your changes:: - - git checkout -b my-feature - - and start making changes. Never work on the main branch! - -#. Start your work on this branch. Don't forget to add docstrings_ to new - functions, modules and classes, especially if they are part of public APIs. - -#. Add yourself to the list of contributors in ``AUTHORS.rst``. - -#. When you’re done editing, do:: - - git add - git commit - - to record your changes in git_. - - .. todo:: if you are not using pre-commit, please remove the following item: - - Please make sure to see the validation messages from |pre-commit|_ and fix - any eventual issues. - This should automatically use flake8_/black_ to check/fix the code style - in a way that is compatible with the project. - - .. important:: Don't forget to add unit tests and documentation in case your - contribution adds an additional feature and is not just a bugfix. - - Moreover, writing a `descriptive commit message`_ is highly recommended. - In case of doubt, you can check the commit history with:: - - git log --graph --decorate --pretty=oneline --abbrev-commit --all - - to look for recurring communication patterns. - -#. Please check that your changes don't break any unit tests with:: - - tox - - (after having installed |tox|_ with ``pip install tox`` or ``pipx``). - - You can also use |tox|_ to run several other pre-configured tasks in the - repository. Try ``tox -av`` to see a list of the available checks. - -Submit your contribution ------------------------- - -#. If everything works fine, push your local branch to |the repository service| with:: - - git push -u origin my-feature - -#. Go to the web page of your fork and click |contribute button| - to send your changes for review. - - .. todo:: if you are using GitHub, you can uncomment the following paragraph - - Find more detailed information in `creating a PR`_. You might also want to open - the PR as a draft first and mark it as ready for review after the feedbacks - from the continuous integration (CI) system or any required fixes. - - -Troubleshooting ---------------- - -The following tips can be used when facing problems to build or test the -package: - -#. Make sure to fetch all the tags from the upstream repository_. - The command ``git describe --abbrev=0 --tags`` should return the version you - are expecting. If you are trying to run CI scripts in a fork repository, - make sure to push all the tags. - You can also try to remove all the egg files or the complete egg folder, i.e., - ``.eggs``, as well as the ``*.egg-info`` folders in the ``src`` folder or - potentially in the root of your project. - -#. Sometimes |tox|_ misses out when new dependencies are added, especially to - ``setup.cfg`` and ``docs/requirements.txt``. If you find any problems with - missing dependencies when running a command with |tox|_, try to recreate the - ``tox`` environment using the ``-r`` flag. For example, instead of:: - - tox -e docs - - Try running:: - - tox -r -e docs - -#. Make sure to have a reliable |tox|_ installation that uses the correct - Python version (e.g., 3.7+). When in doubt you can run:: - - tox --version - # OR - which tox - - If you have trouble and are seeing weird errors upon running |tox|_, you can - also try to create a dedicated `virtual environment`_ with a |tox|_ binary - freshly installed. For example:: - - virtualenv .venv - source .venv/bin/activate - .venv/bin/pip install tox - .venv/bin/tox -e all - -#. `Pytest can drop you`_ in an interactive session in the case an error occurs. - In order to do that you need to pass a ``--pdb`` option (for example by - running ``tox -- -k --pdb``). - You can also setup breakpoints manually instead of using the ``--pdb`` option. - - -Maintainer tasks -================ - -Releases --------- - -.. todo:: This section assumes you are using PyPI to publicly release your package. - - If instead you are using a different/private package index, please update - the instructions accordingly. - -If you are part of the group of maintainers and have correct user permissions -on PyPI_, the following steps can be used to release a new version for -``benchmarking``: - -#. Make sure all unit tests are successful. -#. Tag the current commit on the main branch with a release tag, e.g., ``v1.2.3``. -#. Push the new tag to the upstream repository_, e.g., ``git push upstream v1.2.3`` -#. Clean up the ``dist`` and ``build`` folders with ``tox -e clean`` - (or ``rm -rf dist build``) - to avoid confusion with old builds and Sphinx docs. -#. Run ``tox -e build`` and check that the files in ``dist`` have - the correct version (no ``.dirty`` or git_ hash) according to the git_ tag. - Also check the sizes of the distributions, if they are too big (e.g., > - 500KB), unwanted clutter may have been accidentally included. -#. Run ``tox -e publish -- --repository pypi`` and check that everything was - uploaded to PyPI_ correctly. - - - -.. [#contrib1] Even though, these resources focus on open source projects and - communities, the general ideas behind collaborating with other developers - to collectively create software are general and can be applied to all sorts - of environments, including private companies and proprietary code bases. - - -.. <-- start --> -.. todo:: Please review and change the following definitions: - -.. |the repository service| replace:: GitHub -.. |contribute button| replace:: "Create pull request" - -.. _repository: https://github.com//benchmarking -.. _issue tracker: https://github.com//benchmarking/issues -.. <-- end --> - - -.. |virtualenv| replace:: ``virtualenv`` -.. |pre-commit| replace:: ``pre-commit`` -.. |tox| replace:: ``tox`` - - -.. _black: https://pypi.org/project/black/ -.. _CommonMark: https://commonmark.org/ -.. _contribution-guide.org: https://www.contribution-guide.org/ -.. _creating a PR: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request -.. _descriptive commit message: https://chris.beams.io/posts/git-commit -.. _docstrings: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html -.. _first-contributions tutorial: https://github.com/firstcontributions/first-contributions -.. _flake8: https://flake8.pycqa.org/en/stable/ -.. _git: https://git-scm.com -.. _GitHub's fork and pull request workflow: https://guides.github.com/activities/forking/ -.. _guide created by FreeCodeCamp: https://github.com/FreeCodeCamp/how-to-contribute-to-open-source -.. _Miniconda: https://docs.conda.io/en/latest/miniconda.html -.. _MyST: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html -.. _other kinds of contributions: https://opensource.guide/how-to-contribute -.. _pre-commit: https://pre-commit.com/ -.. _PyPI: https://pypi.org/ -.. _PyScaffold's contributor's guide: https://pyscaffold.org/en/stable/contributing.html -.. _Pytest can drop you: https://docs.pytest.org/en/stable/how-to/failures.html#using-python-library-pdb-with-pytest -.. _Python Software Foundation's Code of Conduct: https://www.python.org/psf/conduct/ -.. _reStructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/ -.. _Sphinx: https://www.sphinx-doc.org/en/master/ -.. _tox: https://tox.wiki/en/stable/ -.. _virtual environment: https://realpython.com/python-virtual-environments-a-primer/ -.. _virtualenv: https://virtualenv.pypa.io/en/stable/ - -.. _GitHub web interface: https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files -.. _GitHub's code editor: https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files diff --git a/LICENSE.txt b/LICENSE.txt index a8a3107..ad53fc6 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,9 @@ -The MIT License (MIT) +Copyright 2023, 2026, Iowa State University -Copyright (c) 2023 zachcran +This material was produced under U.S. Government contract DE-AC02-07CH11358 for Ames National Laboratory, which is operated by Iowa State University for the U.S. Department of Energy. The Government is granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable worldwide license in this material to reproduce, prepare derivative works, and perform publicly and display publicly. The U.S. Government has rights to use, reproduce, and distribute this software. If software is modified to produce derivative works, such modified software should be clearly marked, so as not to confuse it with the version available from The Ames Laboratory. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. NEITHER THE GOVERNMENT, AMES NATIONAL LABORATORY, NOR IOWA STATE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..911a313 --- /dev/null +++ b/README.rst @@ -0,0 +1,31 @@ +.. image:: https://img.shields.io/badge/Documentation-grey + :alt: Documentation link + :target: https://rxnrover.github.io/benchmarking/ + +.. image:: https://img.shields.io/badge/-PyScaffold-005CA0?logo=pyscaffold + :alt: Project generated with PyScaffold + :target: https://pyscaffold.org/ + +############## + benchmarking +############## + + Add a short description here! + +A longer description of your project goes here... + +******************************* + Making Changes & Contributing +******************************* + +This project uses pre-commit_, please make sure to install it before making any +changes: + +.. code-block:: bash + + # After cloning the repository + pip install pre-commit + cd cyrxnopt_analyzer + pre-commit install + +.. _pre-commit: https://pre-commit.com/ diff --git a/README.txt b/README.txt deleted file mode 100644 index b6a087e..0000000 --- a/README.txt +++ /dev/null @@ -1,67 +0,0 @@ -.. These are examples of badges you might want to add to your README: - please update the URLs accordingly - - .. image:: https://api.cirrus-ci.com/github//benchmarking.svg?branch=main - :alt: Built Status - :target: https://cirrus-ci.com/github//benchmarking - .. image:: https://readthedocs.org/projects/benchmarking/badge/?version=latest - :alt: ReadTheDocs - :target: https://benchmarking.readthedocs.io/en/stable/ - .. image:: https://img.shields.io/coveralls/github//benchmarking/main.svg - :alt: Coveralls - :target: https://coveralls.io/r//benchmarking - .. image:: https://img.shields.io/pypi/v/benchmarking.svg - :alt: PyPI-Server - :target: https://pypi.org/project/benchmarking/ - .. image:: https://img.shields.io/conda/vn/conda-forge/benchmarking.svg - :alt: Conda-Forge - :target: https://anaconda.org/conda-forge/benchmarking - .. image:: https://pepy.tech/badge/benchmarking/month - :alt: Monthly Downloads - :target: https://pepy.tech/project/benchmarking - .. image:: https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Twitter - :alt: Twitter - :target: https://twitter.com/benchmarking - -.. image:: https://img.shields.io/badge/-PyScaffold-005CA0?logo=pyscaffold - :alt: Project generated with PyScaffold - :target: https://pyscaffold.org/ - -| - -============ -benchmarking -============ - - - Add a short description here! - - -A longer description of your project goes here... - - -.. _pyscaffold-notes: - -Making Changes & Contributing -============================= - -This project uses `pre-commit`_, please make sure to install it before making any -changes:: - - pip install pre-commit - cd benchmarking - pre-commit install - -It is a good idea to update the hooks to the latest version:: - - pre-commit autoupdate - -Don't forget to tell your contributors to also install and use pre-commit. - -.. _pre-commit: https://pre-commit.com/ - -Note -==== - -This project has been set up using PyScaffold 4.4.1. For details and usage -information on PyScaffold see https://pyscaffold.org/. diff --git a/docs/README.rst b/docs/README.rst index 9e7ebc9..460dedb 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -1,16 +1,18 @@ -Building the Documentation -########################## +############################ + Building the Documentation +############################ -Using tox -********* +*********** + Using tox +*********** -The `tox` tools allows for a one-line solution to building documentation -(two lines if you count installing `tox`). +The `tox` tools allows for a one-line solution to building documentation (two +lines if you count installing `tox`). -0. If you are not in a virtual environment, it is highly recommended to create - and activate one before doing any work in Python. +- If you are not in a virtual environment, it is highly recommended to create + and activate one before doing any work in Python. - .. code-block:: bash + .. code-block:: bash # Create the virtual environment in the "venv" directory python -m venv venv @@ -18,29 +20,30 @@ The `tox` tools allows for a one-line solution to building documentation # Activate the virtual environment source venv/bin/activate -1. Install `tox` using `pip` +- Install `tox` using `pip` - .. code-block:: bash + .. code-block:: bash pip install tox -2. Build the documentation +- Build the documentation - .. code-block:: bash + .. code-block:: bash tox -e docs -Viewing the Documentation -************************* +*************************** + Viewing the Documentation +*************************** -Once the documentation is built, you can view it in a web browser by opening -the various HTML files under `docs/build/html`, or host the website locally -on your system using Python by navigating into `docs/build/html` and running -the following command in a terminal: +Once the documentation is built, you can view it in a web browser by opening the +various HTML files under `docs/build/html`, or host the website locally on your +system using Python by navigating into `docs/build/html` and running the +following command in a terminal: .. code-block:: - python -m http.server + python -m http.server If the command succeeded, you can visit `http://0.0.0.0:8000` in a web browser to view the documentation website. diff --git a/docs/source/authors.rst b/docs/source/authors.rst new file mode 100644 index 0000000..0181789 --- /dev/null +++ b/docs/source/authors.rst @@ -0,0 +1,3 @@ +.. _authors: + +.. include:: ../../AUTHORS.rst diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst new file mode 100644 index 0000000..227f9ca --- /dev/null +++ b/docs/source/changelog.rst @@ -0,0 +1,3 @@ +.. _changes: + +.. include:: ../../CHANGELOG.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index 882afcd..95840a5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,26 +1,293 @@ -# Configuration file for the Sphinx documentation builder. +# This file is execfile()d with the current directory set to its containing dir. # -# For the full list of built-in configuration values, see the documentation: +# This file only contains a selection of the most common options. For a full +# list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +# +# All configuration values have a default; values that are commented out +# serve to show the default. -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import os +import shutil +import sys -project = "Benchmarking" -copyright = "2023, zachcran" -author = "zachcran" +# -- Path setup -------------------------------------------------------------- + +__location__ = os.path.dirname(__file__) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.join(__location__, "../../src")) + +# -- Run sphinx-apidoc ------------------------------------------------------- +# This hack is necessary since RTD does not issue `sphinx-apidoc` before running +# `sphinx-build -b html . _build/html`. See Issue: +# https://github.com/readthedocs/readthedocs.org/issues/1139 +# DON'T FORGET: Check the box "Install your project inside a virtualenv using +# setup.py install" in the RTD Advanced Settings. +# Additionally it helps us to avoid running apidoc manually + +try: # for Sphinx >= 1.7 + from sphinx.ext import apidoc +except ImportError: + from sphinx import apidoc + +output_dir = os.path.join(__location__, "api") +module_dir = os.path.join(__location__, "../../src/benchmarking") +try: + shutil.rmtree(output_dir) +except FileNotFoundError: + pass + +try: + import sphinx + + cmd_line = ( + f"sphinx-apidoc --implicit-namespaces -f -o {output_dir} {module_dir}" + ) + + args = cmd_line.split(" ") + if tuple(sphinx.__version__.split(".")) >= ("1", "7"): + # This is a rudimentary parse_version to avoid external dependencies + args = args[1:] + + apidoc.main(args) +except Exception as e: + print("Running `sphinx-apidoc` failed!\n{}".format(e)) # -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -extensions = [] +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.autosummary", + "sphinx.ext.viewcode", + "sphinx.ext.coverage", + "sphinx.ext.doctest", + "sphinx.ext.ifconfig", + "sphinx.ext.mathjax", + "sphinx.ext.napoleon", +] +# Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] -exclude_patterns = [] + +# The suffix of source filenames. +source_suffix = ".rst" + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "Benchmarking" +copyright = "2023, 2026 Iowa State University" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# version: The short X.Y version. +# release: The full version, including alpha/beta/rc tags. +# If you don’t need the separation provided between version and release, +# just set them both to the same value. +try: + from benchmarking import __version__ as version +except ImportError: + version = "" + +if not version or version.lower() == "unknown": + version = os.getenv( + "READTHEDOCS_VERSION", "unknown" + ) # automatically set by RTD + +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".venv"] + +# The reST default role (used for this markup: `text`) to use for all documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If this is True, todo emits a warning for each TODO entries. The default is False. +todo_emit_warnings = True # -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# html_theme_options = {"sidebar_width": "300px", "page_width": "1200px"} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = "" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = "benchmarking-doc" + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ("letterpaper" or "a4paper"). + # "papersize": "letterpaper", + # The font size ("10pt", "11pt" or "12pt"). + # "pointsize": "10pt", + # Additional stuff for the LaTeX preamble. + # "preamble": "", +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ( + "index", + "user_guide.tex", + "benchmarking Documentation", + "zachcran", + "manual", + ) +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = "" + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + +# -- External mapping -------------------------------------------------------- +python_version = ".".join(map(str, sys.version_info[0:2])) +intersphinx_mapping = { + "sphinx": ("https://www.sphinx-doc.org/en/master", None), + "python": ("https://docs.python.org/" + python_version, None), + "matplotlib": ("https://matplotlib.org", None), + "numpy": ("https://numpy.org/doc/stable", None), + "sklearn": ("https://scikit-learn.org/stable", None), + "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), + "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), + "setuptools": ("https://setuptools.pypa.io/en/stable/", None), + "pyscaffold": ("https://pyscaffold.org/en/stable", None), +} + +print(f"loading configurations for {project} {version} ...", file=sys.stderr) diff --git a/docs/source/index.rst b/docs/source/index.rst index da920c4..266254c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,20 +1,26 @@ -.. Benchmarking documentation master file, created by - sphinx-quickstart on Wed Jun 28 12:52:31 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +##################################### + Benchmarking Function Documentation +##################################### -Welcome to Benchmarking's documentation! -======================================== +This is the documentation of **benchmarking**. -.. toctree:: - :maxdepth: 2 - :caption: Contents: +********** + Contents +********** +.. toctree:: + :maxdepth: 1 + Overview + License + Authors + Changelog + Module Reference -Indices and tables -================== +******************** + Indices and tables +******************** -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` +- :ref:`genindex` +- :ref:`modindex` +- :ref:`search` diff --git a/docs/source/license.rst b/docs/source/license.rst new file mode 100644 index 0000000..3d78c66 --- /dev/null +++ b/docs/source/license.rst @@ -0,0 +1,7 @@ +.. _license: + +######### + License +######### + +.. include:: ../../LICENSE.txt diff --git a/docs/source/readme.rst b/docs/source/readme.rst new file mode 100644 index 0000000..d97f1cf --- /dev/null +++ b/docs/source/readme.rst @@ -0,0 +1,3 @@ +.. _readme: + +.. include:: ../../README.rst From 8dc8fa36071216bb290f6f160d1ec6d25604956d Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:04:19 -0600 Subject: [PATCH 3/9] Fix incorrectly escaped characters, add math formatting, and fix other formatting/linting issues --- src/benchmarking/evaluate.py | 8 ++- .../functions/BenchmarkingFunction.py | 59 +++++++++++-------- src/benchmarking/functions/Optimum.py | 4 +- src/benchmarking/functions/beale.py | 11 ++-- src/benchmarking/functions/booth.py | 7 ++- src/benchmarking/functions/branin.py | 7 ++- src/benchmarking/functions/bukin_n6.py | 9 ++- src/benchmarking/functions/eggholder.py | 11 ++-- src/benchmarking/functions/goldstein_price.py | 13 ++-- src/benchmarking/functions/hartmann.py | 23 ++++++-- src/benchmarking/functions/himmelblau.py | 7 ++- src/benchmarking/functions/holder_table.py | 11 ++-- src/benchmarking/functions/matyas.py | 7 ++- src/benchmarking/functions/rosenbrock.py | 7 ++- src/benchmarking/functions/schwefel.py | 9 ++- src/benchmarking/functions/shekel.py | 18 ++++-- src/benchmarking/functions/shubert.py | 9 ++- src/benchmarking/functions/six_hump_camel.py | 9 ++- src/benchmarking/functions/sphere.py | 9 ++- src/benchmarking/functions/styblinski_tang.py | 7 ++- .../functions/three_hump_camel.py | 9 ++- src/benchmarking/utilities/apply_noise.py | 14 +++-- src/benchmarking/utilities/generate_box.py | 4 +- 23 files changed, 180 insertions(+), 92 deletions(-) diff --git a/src/benchmarking/evaluate.py b/src/benchmarking/evaluate.py index be6513b..a077504 100644 --- a/src/benchmarking/evaluate.py +++ b/src/benchmarking/evaluate.py @@ -1,3 +1,5 @@ +from typing import Any + from benchmarking.functions.beale import Beale from benchmarking.functions.booth import Booth from benchmarking.functions.branin import Branin @@ -18,7 +20,7 @@ from benchmarking.functions.three_hump_camel import ThreeHumpCamel -def evaluate(function_name: str, *args, **kwargs): # pragma: no cover +def evaluate(function_name: str, *args: Any, **kwargs: Any) -> float: """Helper function to evaluate different benchmarking functions given the function name. This helps to not have to put this large if-elif statement everywhere that multiple functions are possible. @@ -26,9 +28,9 @@ def evaluate(function_name: str, *args, **kwargs): # pragma: no cover :param function_name: Name of the function to use. This must exactly match the actual function name. :type function_name: str - :param \*args: Positional arguments to be passed to the benchmarking + :param *args: Positional arguments to be passed to the benchmarking function. - :param \*\*kwargs: Keyword arguments to be passed to the benchmarking + :param **kwargs: Keyword arguments to be passed to the benchmarking function. :raises ValueError: Invalid function name was provided. diff --git a/src/benchmarking/functions/BenchmarkingFunction.py b/src/benchmarking/functions/BenchmarkingFunction.py index b61424f..2580678 100644 --- a/src/benchmarking/functions/BenchmarkingFunction.py +++ b/src/benchmarking/functions/BenchmarkingFunction.py @@ -1,43 +1,52 @@ from abc import ABC -from typing import List +from typing import Any, Callable, List, Optional from benchmarking.functions.Optimum import Optimum class BenchmarkingFunction(ABC): - def __init__(self): - self._minima = [] - self._global_minima = [] - self._maxima = [] - self._global_maxima = [] - self._bounds = [] - self._function = None + def __init__(self) -> None: + self._minima: List[Optimum] = [] + self._global_minima: List[Optimum] = [] + self._maxima: List[Optimum] = [] + self._global_maxima: List[Optimum] = [] + self._bounds: List[List[float]] = [] + self._function: Optional[Callable] = None def __call__(self, xs: List[float]) -> float: + if self._function is None: + raise RuntimeError( + "Function was not set the benchmarking function." + ) + return self._function(xs) - def set_function(self, foo): + def set_function(self, foo: Callable) -> None: self._function = foo - def add_minimum(self, inputs, outputs, local=False): + def add_minimum( + self, inputs: List[float], outputs: float, local: bool = False + ) -> None: minimum = Optimum(inputs, outputs) self._minima.append(minimum) if not local: self._global_minima.append(minimum) - def add_maximum(self, inputs, outputs, local=False): + def add_maximum( + self, inputs: List[float], outputs: float, local: bool = False + ) -> None: maximum = Optimum(inputs, outputs) self._maxima.append(maximum) if not local: self._global_maxima.append(maximum) - def add_bound(self, bound): + def add_bound(self, bound: List[float]) -> None: self._bounds.append(bound) @property - def min(self): + def min(self) -> Optional[float]: """Get the value of the global minimum. Returns 'None' if there are no minima listed for the function. """ @@ -48,7 +57,7 @@ def min(self): return self.global_minima[0].value @property - def max(self): + def max(self) -> Optional[float]: """Get the value of the global maximum. Returns 'None' if there are no maxima listed for the function. """ @@ -59,55 +68,55 @@ def max(self): return self.global_maxima[0].value @property - def global_minima(self): + def global_minima(self) -> List[Optimum]: """List of global minima.""" return self._global_minima @property - def minima(self): + def minima(self) -> List[Optimum]: """List of all minima.""" return self._minima @property - def global_maxima(self): + def global_maxima(self) -> List[Optimum]: """List of global maxima.""" return self._global_maxima @property - def maxima(self): + def maxima(self) -> List[Optimum]: """List of all maxima.""" return self._maxima @property - def global_extrema(self): + def global_extrema(self) -> List[Optimum]: """List of global extrema.""" return self.global_minima + self.global_maxima @property - def extrema(self): + def extrema(self) -> List[Optimum]: """List of all extrema.""" return self.minima + self.maxima @property - def nmin(self): + def nmin(self) -> int: """Number of global minima.""" return len(self.global_minima) @property - def nmax(self): + def nmax(self) -> int: """Number of global maxima.""" return len(self.global_maxima) @property - def bounds(self): + def bounds(self) -> List[List[float]]: """Suggested boundaries to use.""" return self._bounds @property - def metadata(self): + def metadata(self) -> dict: """Dictionary containing metadata about benchmarking function.""" - metadata = {} + metadata: dict[str, Any] = {} metadata["all_minima_count"] = len(self.minima) metadata["all_minima_values"] = [f.value for f in self.minima] diff --git a/src/benchmarking/functions/Optimum.py b/src/benchmarking/functions/Optimum.py index 56a7f0b..eff72b8 100644 --- a/src/benchmarking/functions/Optimum.py +++ b/src/benchmarking/functions/Optimum.py @@ -2,11 +2,11 @@ class Optimum: - def __init__(self, coordinates, value): + def __init__(self, coordinates: List[float], value: float) -> None: self._coordinates = coordinates self._value = value - def __str__(self): + def __str__(self) -> str: msg = "{}: {}".format(self.coordinates, self.value) return msg diff --git a/src/benchmarking/functions/beale.py b/src/benchmarking/functions/beale.py index bf21c1e..c68e67d 100644 --- a/src/benchmarking/functions/beale.py +++ b/src/benchmarking/functions/beale.py @@ -4,7 +4,7 @@ class Beale(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(beale) @@ -21,11 +21,14 @@ def beale(xs: List[float]) -> float: Beale function from https://www.sfu.ca/~ssurjano/beale.html. - Input domain: 2D square x_i = [-4.5, 4.5] for all i = 1, 2. + Input domain: 2D square :math:`x_i = [-4.5, 4.5]` for all i = 1, 2. Function in LaTeX format: - f(x) = (1.5 - x_1 + x_1 x_2)^2 + (2.25 - x_1 + x_1 x_2^2)^2 + - (2.625 - x_1 + x_1 x_2^3)^2 + + .. math:: + + f(x) = (1.5 - x_1 + x_1 x_2)^2 + (2.25 - x_1 + x_1 x_2^2)^2 + + (2.625 - x_1 + x_1 x_2^3)^2 :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/booth.py b/src/benchmarking/functions/booth.py index df3d7a3..f8e7f59 100644 --- a/src/benchmarking/functions/booth.py +++ b/src/benchmarking/functions/booth.py @@ -4,7 +4,7 @@ class Booth(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(booth) @@ -24,7 +24,10 @@ def booth(xs: List[float]) -> float: Input domain: 2D square with bounds [-10, 10]. Function in LaTeX format: - f(x) = (x_1 + 2x_2 - 7)^2 + (2x_1 + x_2 - 5)^2 + + .. math:: + + f(x) = (x_1 + 2x_2 - 7)^2 + (2x_1 + x_2 - 5)^2 :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/branin.py b/src/benchmarking/functions/branin.py index 33ad47f..fb0d896 100755 --- a/src/benchmarking/functions/branin.py +++ b/src/benchmarking/functions/branin.py @@ -6,7 +6,7 @@ class Branin(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(branin) @@ -37,7 +37,10 @@ def branin( from https://www.sfu.ca/~ssurjano/branin.html. Function in LaTeX format: - f(x) = a(x_2 - bx_1^2 + cx_1 - r)^2 + s(1-t)cos(x_1) + s + + .. math:: + + f(x) = a(x_2 - bx_1^2 + cx_1 - r)^2 + s(1-t)cos(x_1) + s :param xs: Input 'x' values. :type xs: List[float] diff --git a/src/benchmarking/functions/bukin_n6.py b/src/benchmarking/functions/bukin_n6.py index 5b7b32e..d5224c1 100644 --- a/src/benchmarking/functions/bukin_n6.py +++ b/src/benchmarking/functions/bukin_n6.py @@ -5,7 +5,7 @@ class BukinN6(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(bukin_n6) @@ -22,10 +22,13 @@ def bukin_n6(xs: List[float]) -> float: Sixth Bukin function from https://www.sfu.ca/~ssurjano/bukin6.html. - Input domain: 2D rectangle x_1 = [-15, -5], x_2 = [-3, 3]. + Input domain: 2D rectangle :math:`x_1 = [-15, -5], x_2 = [-3, 3]`. Function in LaTeX format: - f(x) = 100 \sqrt{|x_2 - 0.01 x_1^2|} + 0.01 |x_1 + 10| + + .. math:: + + f(x) = 100 \\sqrt{|x_2 - 0.01 x_1^2|} + 0.01 |x_1 + 10| :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/eggholder.py b/src/benchmarking/functions/eggholder.py index 30d4926..e8584f3 100644 --- a/src/benchmarking/functions/eggholder.py +++ b/src/benchmarking/functions/eggholder.py @@ -5,7 +5,7 @@ class Eggholder(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(eggholder) @@ -22,11 +22,14 @@ def eggholder(xs: List[float]) -> float: Eggholder function from https://www.sfu.ca/~ssurjano/egg.html. - Input domain: 2D square x_i = [-512, 512] for all i = 1, 2. + Input domain: 2D square :math:`x_i = [-512, 512]` for all i = 1, 2. Function in LaTeX format: - f(x) = -(x_2 + 47) \sin{(\sqrt{|x_2 + \dfrac{x_1}{2} + 47|})} - - x_1 \sin{(\sqrt{|x_1 - (x_2 + 47)|})} + + .. math:: + + f(x) = -(x_2 + 47) \\sin{(\\sqrt{|x_2 + \\dfrac{x_1}{2} + 47|})} - + x_1 \\sin{(\\sqrt{|x_1 - (x_2 + 47)|})} :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/goldstein_price.py b/src/benchmarking/functions/goldstein_price.py index b661945..e90eeaf 100755 --- a/src/benchmarking/functions/goldstein_price.py +++ b/src/benchmarking/functions/goldstein_price.py @@ -4,7 +4,7 @@ class GoldsteinPrice(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(goldstein_price) @@ -22,10 +22,13 @@ def goldstein_price(xs: List[float]) -> float: Goldstein-Price function from https://www.sfu.ca/~ssurjano/goldpr.html. Function in LaTeX format: - f(x) = [1 + (x_1 + x_2 + 1)^2 - (19 - 14 x_1 + 3 x_1^2 - 14 x_2 + 6 x_1 x_2 + 3 x_2^2)] - \times [30 + (2 x_1 - 3 x_2)^2 - (18 - 32 x_1 + 12 x_1^2 + 48 x_2 - 36 x_1 x_2 + 27 x_2^2)] + + .. math:: + + f(x) = [1 + (x_1 + x_2 + 1)^2 + (19 - 14 x_1 + 3 x_1^2 - 14 x_2 + 6 x_1 x_2 + 3 x_2^2)] + \\times [30 + (2 x_1 - 3 x_2)^2 + (18 - 32 x_1 + 12 x_1^2 + 48 x_2 - 36 x_1 x_2 + 27 x_2^2)] :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/hartmann.py b/src/benchmarking/functions/hartmann.py index 2780ff8..3a40e26 100755 --- a/src/benchmarking/functions/hartmann.py +++ b/src/benchmarking/functions/hartmann.py @@ -13,7 +13,7 @@ class Hartmann3D(BenchmarkingFunction): Source: https://www.sfu.ca/~ssurjano/hart3.html """ - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(hartmann) @@ -28,6 +28,11 @@ def __call__( self, xs: List[float], ) -> float: + if self._function is None: + raise RuntimeError( + "Function was not set the benchmarking function." + ) + alpha = np.array([1.0, 1.2, 3.0, 3.2]) A = np.array( @@ -52,7 +57,7 @@ class Hartmann6D(BenchmarkingFunction): Source: https://www.sfu.ca/~ssurjano/hart6.html """ - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(hartmann) @@ -70,6 +75,11 @@ def __call__( self, xs: List[float], ) -> float: + if self._function is None: + raise RuntimeError( + "Function was not set the benchmarking function." + ) + alpha = np.array([1.0, 1.2, 3.0, 3.2]) A = np.array( @@ -103,12 +113,15 @@ def hartmann( supports 3 or 6 dimensions, and dimensions are inferred by the length of the ``xs`` parameter list. - Hartmann nD function with (by default) values of \alpha, A, and P + Hartmann nD function with (by default) values of :math:`\\alpha`, A, and P from https://www.sfu.ca/~ssurjano/hart3.html. Function in LaTeX format: - f(x) = -\sum_{i=1}^{4} \alpha_i - \exp{\bigg(-\sum_{j=1}^n A_{ij}(x_j - P_{ij})^2\bigg)} + + .. math:: + + f(x) = -\\sum_{i=1}^{4} \\alpha_i + \\exp{\\bigg(-\\sum_{j=1}^n A_{ij}(x_j - P_{ij})^2\\bigg)} :param xs: Input parameters :type xs: List[float] diff --git a/src/benchmarking/functions/himmelblau.py b/src/benchmarking/functions/himmelblau.py index 40ceae6..dfbcf01 100644 --- a/src/benchmarking/functions/himmelblau.py +++ b/src/benchmarking/functions/himmelblau.py @@ -4,7 +4,7 @@ class Himmelblau(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(himmelblau) @@ -42,7 +42,10 @@ def himmelblau(xs: List[float]) -> float: Input domain: Unknown. Function in LaTeX format: - f(x) = (x_1^2 + x_2 - 11)^2 + (x_1 + x_2^2 - 7)^2 + + .. math:: + + f(x) = (x_1^2 + x_2 - 11)^2 + (x_1 + x_2^2 - 7)^2 :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/holder_table.py b/src/benchmarking/functions/holder_table.py index 0bfab5d..e5a76d0 100644 --- a/src/benchmarking/functions/holder_table.py +++ b/src/benchmarking/functions/holder_table.py @@ -5,7 +5,7 @@ class HolderTable(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(holder_table) @@ -29,11 +29,14 @@ def holder_table(xs: List[float]) -> float: Holder Table function from https://www.sfu.ca/~ssurjano/holder.html. - Input domain: 2D square x_i = [-10, 10] for all i = 1, 2. + Input domain: 2D square :math:`x_i = [-10, 10]` for all i = 1, 2. Function in LaTeX format: - f(x) = -|\sin{(x_1)} \cos{(x_2)} - \exp{(|1 - \frac{\sqrt{x_1^2 + x_2^2}}{\pi}|)}| + + .. math:: + + f(x) = -|\\sin{(x_1)} \\cos{(x_2)} + \\exp{(|1 - \\frac{\\sqrt{x_1^2 + x_2^2}}{\\pi}|)}| :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/matyas.py b/src/benchmarking/functions/matyas.py index 1a1d79b..ec13fbc 100644 --- a/src/benchmarking/functions/matyas.py +++ b/src/benchmarking/functions/matyas.py @@ -4,7 +4,7 @@ class Matyas(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(matyas) @@ -24,7 +24,10 @@ def matyas(xs: List[float]) -> float: Input domain: 2D square with bounds [-10, 10]. Function in LaTeX format: - f(x) = 0.26 (x_1^2 + x_2^2) - 0.48 x_1 x_2 + + .. math:: + + f(x) = 0.26 (x_1^2 + x_2^2) - 0.48 x_1 x_2 :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/rosenbrock.py b/src/benchmarking/functions/rosenbrock.py index 5282e40..5d23195 100755 --- a/src/benchmarking/functions/rosenbrock.py +++ b/src/benchmarking/functions/rosenbrock.py @@ -23,7 +23,10 @@ def rosenbrock(xs: List[float]) -> float: Rosenbrock nD function from https://www.sfu.ca/~ssurjano/rosen.html. Function in LaTeX format: - f(x) = \sum_{i=1}^{d-1} [100(x_{i+1} - x_i^2)^2 + (x_i - 1)^2] + + .. math:: + + f(x) = \\sum_{i=1}^{d-1} [100(x_{i+1} - x_i^2)^2 + (x_i - 1)^2] :param xs: List of input parameters :type xs: List[float] @@ -33,7 +36,7 @@ def rosenbrock(xs: List[float]) -> float: dimension_count = len(xs) - sum = 0 + sum = 0.0 for i in range(dimension_count - 1): term_1 = 100 * (xs[i + 1] - xs[i] ** 2) ** 2 term_2 = (xs[i] - 1) ** 2 diff --git a/src/benchmarking/functions/schwefel.py b/src/benchmarking/functions/schwefel.py index c23a1ff..26df7b2 100644 --- a/src/benchmarking/functions/schwefel.py +++ b/src/benchmarking/functions/schwefel.py @@ -22,10 +22,13 @@ def schwefel(xs: List[float]) -> float: Schwefel function from https://www.sfu.ca/~ssurjano/schwef.html. - Input domain: Hypercube x_i = [-500, 500], for all i=1, ..., d. + Input domain: Hypercube :math:`x_i = [-500, 500]`, for all i=1, ..., d. Function in LaTeX format: - f(x) = 418.9829 d - \sum_{i = 1}^d x_i \sin{(\sqrt{|x_i|})} + + .. math:: + + f(x) = 418.9829 d - \\sum_{i = 1}^d x_i \\sin{(\\sqrt{|x_i|})} :param xs: Parameter list :type xs: List[float] @@ -36,7 +39,7 @@ def schwefel(xs: List[float]) -> float: term_1 = 418.9829 * len(xs) - term_2 = 0 + term_2 = 0.0 for x in xs: term_2 += x * math.sin(math.sqrt(abs(x))) diff --git a/src/benchmarking/functions/shekel.py b/src/benchmarking/functions/shekel.py index cde74cf..d93f9f3 100755 --- a/src/benchmarking/functions/shekel.py +++ b/src/benchmarking/functions/shekel.py @@ -33,6 +33,11 @@ def __init__(self, m: int = 5): self.add_bound([0, 10]) def __call__(self, xs: List[float]) -> float: + if self._function is None: + raise RuntimeError( + "Function was not set the benchmarking function." + ) + return self._function(xs, m=self.m) @@ -51,12 +56,16 @@ def shekel( ) -> float: """Shekel 4D optimization test function. - Shekel 4D function with (by default) values of \beta and C + Shekel 4D function with (by default) values of :math:`\\beta` and C from https://www.sfu.ca/~ssurjano/shekel.html. Does not support m > 10 without a new C provided. Function in LaTeX format: - f(x) = -\sum_{i=1}^m \bigg(\sum_{j=1}^4(x_j - C_{ji})^2 + \beta_i\bigg)^-1 + + .. math:: + + f(x) = -\\sum_{i=1}^m + \\bigg(\\sum_{j=1}^4(x_j - C_{ji})^2 + \\beta_i\\bigg)^{-1} :param xs: List of input parameters :type xs: List[float] @@ -71,14 +80,15 @@ def shekel( :param beta: 'beta' list, defaults to [ 0.1, 0.2, 0.2, 0.4, 0.4, 0.6, 0.3, 0.7, 0.5, 0.5 ] :type beta: List[float], optional + :return: Result of calculation :rtype: float """ - outer_sum = 0 + outer_sum = 0.0 for i in range(m): - inner_sum = 0 + inner_sum = 0.0 for j in range(4): inner_sum += (xs[j] - C[j][i]) ** 2 diff --git a/src/benchmarking/functions/shubert.py b/src/benchmarking/functions/shubert.py index fe320c3..54dd54b 100755 --- a/src/benchmarking/functions/shubert.py +++ b/src/benchmarking/functions/shubert.py @@ -11,7 +11,7 @@ class Shubert(BenchmarkingFunction): Source: https://www.sfu.ca/~ssurjano/shubert.html """ - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(shubert) @@ -31,8 +31,11 @@ def shubert(xs: List[float]) -> float: Shubert function from https://www.sfu.ca/~ssurjano/shubert.html. Function in LaTeX format: - f(x) = \big(\sum_{i=5}^5 i cos((i + 1)x_1 + i)\big) \times - \big(\sum_{i=5}^5 i cos((i + 1)x_2 + i)\big) + + .. math:: + + f(x) = \\big(\\sum_{i=5}^5 i cos((i + 1)x_1 + i)\\big) \\times + \\big(\\sum_{i=5}^5 i cos((i + 1)x_2 + i)\\big) :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/six_hump_camel.py b/src/benchmarking/functions/six_hump_camel.py index 4742a53..3ee9f08 100755 --- a/src/benchmarking/functions/six_hump_camel.py +++ b/src/benchmarking/functions/six_hump_camel.py @@ -4,7 +4,7 @@ class SixHumpCamel(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(six_hump_camel) @@ -23,8 +23,11 @@ def six_hump_camel(xs: List[float]) -> float: Six-hump camel function from https://www.sfu.ca/~ssurjano/camel6.html. Function in LaTeX format: - f(x) = (4 - 2.1 x_1^2 + \frac{x_1^4}{3}) x_1^2 + x_1 x_2 + - (-4 + 4 x_2^2) x_2^2 + + .. math:: + + f(x) = (4 - 2.1 x_1^2 + \\frac{x_1^4}{3}) x_1^2 + x_1 x_2 + + (-4 + 4 x_2^2) x_2^2 :param xs: Parameter list :type xs: float diff --git a/src/benchmarking/functions/sphere.py b/src/benchmarking/functions/sphere.py index 91185fc..24d56a9 100644 --- a/src/benchmarking/functions/sphere.py +++ b/src/benchmarking/functions/sphere.py @@ -21,10 +21,13 @@ def sphere(xs: List[float]) -> float: Sphere function from https://www.sfu.ca/~ssurjano/spheref.html. - Input domain: Hypercube x_i = [-5.12, 5.12] for all i=1, ..., d. + Input domain: Hypercube :math:`x_i = [-5.12, 5.12]` for all i=1, ..., d. Function in LaTeX format: - f(x) = \sum_{i=1}^d x_i^2 + + .. math:: + + f(x) = \\sum_{i=1}^d x_i^2 :param xs: Parameter list :type xs: List[float] @@ -33,7 +36,7 @@ def sphere(xs: List[float]) -> float: :rtype: float """ - result = 0 + result = 0.0 for x in xs: result += x**2 diff --git a/src/benchmarking/functions/styblinski_tang.py b/src/benchmarking/functions/styblinski_tang.py index f86c18a..1ac6903 100644 --- a/src/benchmarking/functions/styblinski_tang.py +++ b/src/benchmarking/functions/styblinski_tang.py @@ -22,10 +22,13 @@ def styblinski_tang(xs: List[float]) -> float: Styblinski-Tang function from https://www.sfu.ca/~ssurjano/stybtang.html. - Input domain: Hypercube x_i = [-5, 5] for all i=1, ..., d. + Input domain: Hypercube :math:`x_i = [-5, 5]` for all i=1, ..., d. Function in LaTeX format: - f(x) = \dfrac{1}{2} \sum_{i = 1}^d (x_i^4 - 16 x_i^2 + 5 x_i) + + .. math:: + + f(x) = \\dfrac{1}{2} \\sum_{i = 1}^d (x_i^4 - 16 x_i^2 + 5 x_i) :param xs: Parameter list :type xs: List[float] diff --git a/src/benchmarking/functions/three_hump_camel.py b/src/benchmarking/functions/three_hump_camel.py index ec75742..8d92094 100755 --- a/src/benchmarking/functions/three_hump_camel.py +++ b/src/benchmarking/functions/three_hump_camel.py @@ -4,7 +4,7 @@ class ThreeHumpCamel(BenchmarkingFunction): - def __init__(self): + def __init__(self) -> None: super().__init__() self.set_function(three_hump_camel) @@ -21,10 +21,13 @@ def three_hump_camel(xs: List[float]) -> float: Three-hump camel function from https://www.sfu.ca/~ssurjano/camel3.html. - Input domain: 2D square x_i = [-5, 5] for all i = 1, 2. + Input domain: 2D square :math:`x_i = [-5, 5]` for all i = 1, 2. Function in LaTeX format: - f(x) = 2 x_1^2 - 1.05 x_1^4 + \dfrac{x_1^6}{6} + x_1 x_2 + x_2^2 + + .. math:: + + f(x) = 2 x_1^2 - 1.05 x_1^4 + \\dfrac{x_1^6}{6} + x_1 x_2 + x_2^2 :param xs: Parameter list :type xs: float diff --git a/src/benchmarking/utilities/apply_noise.py b/src/benchmarking/utilities/apply_noise.py index 8a5f9dc..8840eef 100755 --- a/src/benchmarking/utilities/apply_noise.py +++ b/src/benchmarking/utilities/apply_noise.py @@ -1,16 +1,20 @@ import numpy as np -def apply_noise(value, sigma, mean=0, variance=1): +def apply_noise( + value: float, sigma: float, mean: float = 0, variance: float = 1 +) -> float: """Apply noise to the given function values. - Applies noise of the form \sigma * N to the function value as + Applies noise of the form :math:`\\sigma * N` to the function value as - f_bar(x) = f(x) + \sigma * N + .. math:: + + f_bar(x) = f(x) + \\sigma * N where N is a normally distributed random variable with (by default) - mean = 0 and variance = 1. \sigma refers to the degree of - perturbation of the value with \sigma = 0 representing the + mean = 0 and variance = 1. :math:`\\sigma` refers to the degree of + perturbation of the value with :math:`\\sigma = 0` representing the unperturbed problem. """ diff --git a/src/benchmarking/utilities/generate_box.py b/src/benchmarking/utilities/generate_box.py index 0d6c837..a2e266d 100755 --- a/src/benchmarking/utilities/generate_box.py +++ b/src/benchmarking/utilities/generate_box.py @@ -1,7 +1,9 @@ import numpy as np -def generate_box(bounds, numPoints): +def generate_box( + bounds: list[list[float]], numPoints: int +) -> list[np.typing.ndarray]: """Generate a box with the given bounds. Bounds must be given as a Python 2D list of shape n x 2, where n From 848065524d510abaed2705729d927623a688d16b Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:13:34 -0600 Subject: [PATCH 4/9] Add gh pages workflow action --- .github/workflows/gh_pages.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/gh_pages.yml diff --git a/.github/workflows/gh_pages.yml b/.github/workflows/gh_pages.yml new file mode 100644 index 0000000..1dfbe9d --- /dev/null +++ b/.github/workflows/gh_pages.yml @@ -0,0 +1,11 @@ +name: GitHub Pages Documentation Generation + +on: + push: + branches: + - main + pull_request: # Run in every PR + +jobs: + gh_pages_generation: + uses: RxnRover/.github/.github/workflows/gh_pages_sphinx_main.yml@main From a1f51b8b0fcbb21f998e99f474df08796a76b34c Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:14:14 -0600 Subject: [PATCH 5/9] Add changelog --- CHANGELOG.rst | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 CHANGELOG.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..23765bf --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,54 @@ +########### + Changelog +########### + +All notable changes to this project will be documented in this file. + +The format is based on `Keep a Changelog +`_, and this project adheres to `Semantic +Versioning `_. + +************* + Unreleased_ +************* + +- None yet + +********************* + 0.6.0_ - 2026-07-28 +********************* + +Changed +======= + +- Math formatting in docstrings updated +- Project structure consolidated and modernized + +********************* + 0.5.0_ - 2023-10-23 +********************* + +Added +===== + +- Helper function was added to easily fetch the new function metadata + +Changed +======= + +- Refactored the benchmarking functions into classes that make more information + about the function available to the user + +.. Reference links + +.. _0.5.0: https://github.com/RxnRover/cyrxnopt_server/releases/tag/v0.5.0 + +.. _0.6.0: https://github.com/RxnRover/cyrxnopt_server/releases/tag/v0.5.0...v0.6.0 + +.. _dulithaprasanna: https://github.com/dulithaprasanna + +.. _semver: https://semver.org + +.. _unreleased: https://github.com/RxnRover/cyrxnopt_server/compare/v0.6.0...HEAD + +.. _zachcran: https://github.com/zachcran From fb964e03b915aa081696865304732780d3226f14 Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:19:32 -0600 Subject: [PATCH 6/9] Fix escaping characters again --- src/benchmarking/evaluate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/benchmarking/evaluate.py b/src/benchmarking/evaluate.py index a077504..200db7a 100644 --- a/src/benchmarking/evaluate.py +++ b/src/benchmarking/evaluate.py @@ -28,9 +28,9 @@ def evaluate(function_name: str, *args: Any, **kwargs: Any) -> float: :param function_name: Name of the function to use. This must exactly match the actual function name. :type function_name: str - :param *args: Positional arguments to be passed to the benchmarking + :param \\*args: Positional arguments to be passed to the benchmarking function. - :param **kwargs: Keyword arguments to be passed to the benchmarking + :param \\*\\*kwargs: Keyword arguments to be passed to the benchmarking function. :raises ValueError: Invalid function name was provided. From f7b253df3e43a3567e0f7dd070a0efd9b06f3055 Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:19:47 -0600 Subject: [PATCH 7/9] Keep empty '_static' directory --- docs/source/_static/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/source/_static/.gitignore diff --git a/docs/source/_static/.gitignore b/docs/source/_static/.gitignore new file mode 100644 index 0000000..3c96363 --- /dev/null +++ b/docs/source/_static/.gitignore @@ -0,0 +1 @@ +# Empty directory From 09079ef90051a7dd9f6a80bfe11e257aa9cee4cc Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:24:25 -0600 Subject: [PATCH 8/9] fix indentation errors on docstring --- src/benchmarking/functions/shekel.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/benchmarking/functions/shekel.py b/src/benchmarking/functions/shekel.py index d93f9f3..51d3063 100755 --- a/src/benchmarking/functions/shekel.py +++ b/src/benchmarking/functions/shekel.py @@ -71,14 +71,22 @@ def shekel( :type xs: List[float] :param m: 'm' parameter, defaults to 10 :type m: int, optional - :param C: 'C' array, defaults to - np.array( [[4.0, 1.0, 8.0, 6.0, 3.0, 2.0, 5.0, 8.0, 6.0, 7.0], - [4.0, 1.0, 8.0, 6.0, 7.0, 9.0, 3.0, 1.0, 2.0, 3.6], - [4.0, 1.0, 8.0, 6.0, 3.0, 2.0, 5.0, 8.0, 6.0, 7.0], - [4.0, 1.0, 8.0, 6.0, 7.0, 9.0, 3.0, 1.0, 2.0, 3.6]]) + :param C: 'C' array, defaults to: + + .. code-block:: python + + np.array([[4.0, 1.0, 8.0, 6.0, 3.0, 2.0, 5.0, 8.0, 6.0, 7.0], + [4.0, 1.0, 8.0, 6.0, 7.0, 9.0, 3.0, 1.0, 2.0, 3.6], + [4.0, 1.0, 8.0, 6.0, 3.0, 2.0, 5.0, 8.0, 6.0, 7.0], + [4.0, 1.0, 8.0, 6.0, 7.0, 9.0, 3.0, 1.0, 2.0, 3.6]]) + :type C: np.ndarray, optional :param beta: 'beta' list, defaults to - [ 0.1, 0.2, 0.2, 0.4, 0.4, 0.6, 0.3, 0.7, 0.5, 0.5 ] + + .. code-block:: python + + [ 0.1, 0.2, 0.2, 0.4, 0.4, 0.6, 0.3, 0.7, 0.5, 0.5 ] + :type beta: List[float], optional :return: Result of calculation From 655b2680d4d2a16ae44275dae7c5c8fe758e355e Mon Sep 17 00:00:00 2001 From: zachcran <15938371+zachcran@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:40:02 -0600 Subject: [PATCH 9/9] Update README to provide general information, installation, and usage; also explicitly discuss the intent to grow this repository past the first 10 functions --- README.rst | 77 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 911a313..79ea3ca 100644 --- a/README.rst +++ b/README.rst @@ -6,13 +6,78 @@ :alt: Project generated with PyScaffold :target: https://pyscaffold.org/ -############## - benchmarking -############## +######################## + benchmarking functions +######################## - Add a short description here! + A collection of benchmarking functions for use with optimization algorithms. -A longer description of your project goes here... +This package provides a collection of standard test functions used to benchmark +the performance of optimization algorithms. Each function exposes its callable +form along with metadata such as its known global (and, where applicable, local) +minima/maxima and suggested input bounds, making it easy to score an optimizer's +results against ground truth. + +The original 10 functions (Branin, Goldstein-Price, Hartmann 3D, Hartmann 6D, +Rosenbrock, Shekel 5, Shekel 7, Shekel 10, Shubert, and Six-Hump Camel) match +the set used to benchmark the CyRxnOpt optimizer and are the same functions used +in the SNOBFIT paper for its own benchmarking. + +This repository is intended to grow beyond that original set of 10 test +problems. It currently also includes Beale, Booth, Bukin N.6, Eggholder, +Himmelblau, Holder Table, Matyas, Schwefel, Sphere, Styblinski-Tang, and +Three-Hump Camel, with more functions expected to be added over time. + +************** + Installation +************** + +Clone the repository and install it with pip: + +.. code-block:: bash + + git clone https://github.com/RxnRover/benchmarking.git + cd benchmarking + pip install . + +******* + Usage +******* + +Each benchmarking function is implemented as a class that can be called directly +with a list of input coordinates. For example, to evaluate the Branin function +and inspect its metadata: + +.. code-block:: python + + from benchmarking.functions.branin import Branin + + branin = Branin() + + # Evaluate the function at a point. + result = branin([-3.14, 12.275]) + + # Metadata about the function: known minima/maxima, bounds, etc. + print(branin.metadata) + + # Convenience accessors are also available. + print(branin.min) # value of the global minimum + print(branin.bounds) # suggested input bounds + +Functions can also be looked up by name, which is useful when the specific +function to benchmark against is chosen dynamically (e.g. from a config file or +command-line argument): + +.. code-block:: python + + from benchmarking.evaluate import evaluate + from benchmarking.function_data import function_data + + result = evaluate("branin", [-3.14, 12.275]) + metadata = function_data("branin") + +The full list of valid function names is available in +``benchmarking.function_ids.function_ids``. ******************************* Making Changes & Contributing @@ -25,7 +90,7 @@ changes: # After cloning the repository pip install pre-commit - cd cyrxnopt_analyzer + cd benchmarking pre-commit install .. _pre-commit: https://pre-commit.com/