diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1a0741f49..9a9e2d8e2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -6,11 +6,11 @@ on:
branches: [ master, development ]
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
- build-source:
+ source-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -24,15 +24,12 @@ jobs:
run: python -m pip install --upgrade -r scripts/requirements.txt
- name: Fabricate COCO
run: python scripts/fabricate
- - name: Configure unit test
+ - name: Run core unit tests
working-directory: ${{github.workspace}}/code-experiments/test/unit-test/
- run: cmake -B build .
- - name: Build unit test
- working-directory: ${{github.workspace}}/code-experiments/test/unit-test/
- run: cmake --build build
- - name: Run unit test
- working-directory: ${{github.workspace}}/code-experiments/test/unit-test/
- run: ctest --test-dir build
+ run: |
+ cmake -B build .
+ cmake --build build
+ ctest --test-dir build
- name: Build cocoex Python package
run: python -m build -s -o dist code-experiments/build/python
- name: Build cocopp Python package
@@ -62,7 +59,7 @@ jobs:
with:
name: dist-rust
path: dist/cocoex-rust-*.zip
- - name: Archive cocoex Python source package
+ - name: Archive cocoex and cocopp Python source package
uses: actions/upload-artifact@v3
with:
name: dist-python-sdist
@@ -70,44 +67,124 @@ jobs:
dist/cocoex*.tar.gz
dist/cocopp*.tar.gz
- build-python-wheels:
- needs: build-source
+ python-wheels-build-cocopp:
+ needs: source-build
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ${{github.workspace}}
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
+ - name: Download Python source package
+ uses: actions/download-artifact@v3
+ with:
+ name: dist-python-sdist
+ - name: Build cocopp wheel
+ shell: bash
+ run: python -m pip wheel -w dist/ cocopp-*.tar.gz
+ - name: Archive Python wheels
+ uses: actions/upload-artifact@v3
+ with:
+ name: dist-python-wheels
+ path: dist/cocopp*.whl
+
+ python-wheels-build-cocoex:
+ needs: source-build
+ # This strategy is taken straight from the numpy wheels.yaml CI job
+ #
+ # Since we depend on numpy, there's no reason to try and build a binary cocoex wheel
+ # on platform that don't have a compiled numpy available.
strategy:
+ # Ensure that a wheel builder finishes even if another fails
+ fail-fast: false
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
- version: ["3.8", "3.9", "3.10", "3.11"]
- runs-on: ${{matrix.os}}
+ buildplat:
+ - [ubuntu-20.04, manylinux_x86_64]
+ - [ubuntu-20.04, musllinux_x86_64]
+ - [macos-12, macosx_x86_64]
+ - [windows-2019, win_amd64]
+ - [windows-2019, win32]
+ python: ["cp39", "cp310", "cp311", "cp312", "pp39"]
+ exclude:
+ # Don't build PyPy 32-bit windows
+ - buildplat: [windows-2019, win32]
+ python: "pp39"
+ - buildplat: [ ubuntu-20.04, musllinux_x86_64 ]
+ python: "pp39"
+ runs-on: ${{ matrix.buildplat[0] }}
defaults:
run:
working-directory: ${{github.workspace}}
steps:
- - uses: actions/setup-python@v4
+ - name: Setup MSVC (32-bit)
+ if: ${{ matrix.buildplat[1] == 'win32' }}
+ uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1
with:
- python-version: ${{matrix.version}}
+ architecture: 'x86'
+ - name: Setup Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
- name: Download Python source package
uses: actions/download-artifact@v3
with:
name: dist-python-sdist
- - name: Setup Python
- run: python -m pip install --upgrade pip wheel
+ - name: Install cibuildwheel
+ run: python -m pip install cibuildwheel==2.16.2
- name: Build cocoex wheel
shell: bash
- run: python -m pip wheel -w dist/ cocoex-*.tar.gz
- - name: Build cocopp wheel
- shell: bash
- run: python -m pip wheel -w dist/ cocopp-*.tar.gz
- - name: Archive Python package
+ run: python -m cibuildwheel --output-dir dist/ cocoex-*.tar.gz
+ env:
+ CIBW_PRERELEASE_PYTHONS: True
+ CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }}
+ - name: Archive Python wheels
uses: actions/upload-artifact@v3
with:
name: dist-python-wheels
- path: dist/*.whl
+ path: dist/cocoex*.whl
- test-python-wheels:
- needs: build-python-wheels
+ python-wheels-test:
+ needs: python-wheels-build-cocoex
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
- version: ["3.8", "3.9", "3.10", "3.11"]
+ version: ["3.9", "3.10", "3.11", "3.12"]
+ runs-on: ${{matrix.os}}
+ defaults:
+ run:
+ working-directory: ${{github.workspace}}
+ steps:
+ - uses: actions/download-artifact@v3
+ with:
+ name: dist-python-sdist
+ path: dist
+ - uses: actions/download-artifact@v3
+ with:
+ name: dist-python-wheels
+ path: wheels
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{matrix.version}}
+ - name: Setup Python
+ run: python -m pip install --upgrade pip wheel
+ - name: Install cocoex
+ run: python -m pip install --find-links wheels/ cocoex
+ - name: Run cocoex test
+ shell: bash
+ run: |
+ tar xf dist/cocoex-*.tar.gz --strip-components=1
+ python -m pip install pytest pytest-cov
+ pytest --cov=cocoex test/
+
+ python-wheels-example:
+ needs: [python-wheels-build-cocoex, python-wheels-build-cocopp]
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ version: ["3.9", "3.10", "3.11", "3.12"]
runs-on: ${{matrix.os}}
defaults:
run:
@@ -124,14 +201,61 @@ jobs:
- name: Setup Python
run: python -m pip install --upgrade pip wheel
- name: Install cocoex and cocopp
- run: pip install --find-links wheels cocoex cocopp
+ run: python -m pip install --find-links wheels/ cocoex cocopp
- name: Install scipy for example experiment
- run: pip install scipy
+ run: python -m pip install scipy
- name: Run example experiment
run: python code-experiments/build/python/example/example_experiment2.py
+
+ python-lint:
+ needs: source-build
+ runs-on: "ubuntu-latest"
+ steps:
+ - uses: actions/download-artifact@v3
+ with:
+ name: dist-python-sdist
+ path: dist
+ - uses: actions/setup-python@v4
+ with:
+ python-version: "3.11"
+ - name: Setup Python
+ run: python -m pip install --upgrade pip wheel
+ - name: Lint with Ruff
+ shell: bash
+ continue-on-error: true
+ run: |
+ pip install ruff
+ tar xf dist/cocoex-*.tar.gz --strip-components=1
+ ruff --output-format=github .
- test-c:
- needs: build-source
+ cocopp-example:
+ needs: python-wheels-build-cocopp
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ version: ["3.9", "3.10", "3.11", "3.12"]
+ runs-on: ${{matrix.os}}
+ defaults:
+ run:
+ working-directory: ${{github.workspace}}
+ steps:
+ - uses: actions/download-artifact@v3
+ with:
+ name: dist-python-wheels
+ path: wheels
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{matrix.version}}
+ - name: Setup Python
+ run: python -m pip install --upgrade pip wheel
+ - name: Run BBOB postprocessing example
+ shell: bash
+ run: |
+ python -m pip install wheels/cocopp*.whl
+ python -m cocopp -v AMALGAM\! BIPOP-CMA-ES\!
+
+ c-test:
+ needs: source-build
strategy:
matrix:
# FIXME: Currently fails on windows because of path issues.
@@ -159,14 +283,20 @@ jobs:
if: failure()
uses: actions/upload-artifact@v3
with:
- name: test-c-${{matrix.os}}
+ name: c-test-${{matrix.os}}
path: |
**/build/
- test-java:
- needs: build-source
- # FIXME: Should also test on windows and macos
- runs-on: ubuntu-latest
+ java-example:
+ needs: source-build
+ strategy:
+ matrix:
+ # FIXME: Currently fails on windows because of path issues.
+ #
+ # Debug and add `windows-latest` back to list at some point.
+ os: [ubuntu-latest, macos-latest]
+ java: [11, 17, 21]
+ runs-on: ${{matrix.os}}
defaults:
run:
working-directory: ${{github.workspace}}
@@ -175,6 +305,11 @@ jobs:
uses: actions/download-artifact@v3
with:
name: dist-java
+ - name: Setup java
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'temurin'
+ java-version: ${{ matrix.java }}
- name: Unpack
run: unzip cocoex-java-*.zip
- name: Build
@@ -186,11 +321,11 @@ jobs:
- name: Archive Java example experiment results
uses: actions/upload-artifact@v3
with:
- name: exdata-java
+ name: java-example-${{matrix.os}}
path: cocoex-java/exdata/*
- test-octave:
- needs: build-source
+ octave-example:
+ needs: source-build
# FIXME: Should also test on windows and macos
runs-on: ubuntu-latest
defaults:
@@ -214,13 +349,16 @@ jobs:
- name: Archive Octave example experiment results
uses: actions/upload-artifact@v3
with:
- name: exdata-octave
+ name: octave-example
path: cocoex-octave/exdata/*
- test-rust:
- needs: build-source
- # FIXME: Should also test on windows and macos
- runs-on: ubuntu-latest
+ rust-test:
+ if: false # Disabled since we don't have any tests yes
+ needs: source-build
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{matrix.os}}
defaults:
run:
working-directory: ${{github.workspace}}
@@ -237,12 +375,32 @@ jobs:
- name: Test
working-directory: ${{github.workspace}}/cocoex-rust/
run: cargo test -r
- - name: Experiment
+
+ rust-example:
+ needs: source-build
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{matrix.os}}
+ defaults:
+ run:
+ working-directory: ${{github.workspace}}
+ steps:
+ - name: Download Rust source package
+ uses: actions/download-artifact@v3
+ with:
+ name: dist-rust
+ - name: Unpack
+ run: unzip cocoex-rust-*.zip
+ - name: Build
+ working-directory: ${{github.workspace}}/cocoex-rust/
+ run: cargo build -r
+ - name: Example Experiment
working-directory: ${{github.workspace}}/cocoex-rust/
- run: ./target/release/examples/example-experiment
+ run: cargo run --example example-experiment
- name: Archive Rust example experiment results
uses: actions/upload-artifact@v3
with:
- name: exdata-rust
+ name: rust-example-${{matrix.os}}
path: cocoex-rust/exdata/*
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 28b4ad308..2fe04c06a 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -17,7 +17,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
- python-version: "3.7"
+ python-version: "3.8"
cache: "pip"
- name: Setup Python
run: python -m pip install --upgrade -r scripts/requirements.txt
@@ -40,7 +40,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
- python-version: "3.7"
+ python-version: "3.8"
cache: "pip"
- name: Setup Python
run: python -m pip install --upgrade -r scripts/requirements.txt
@@ -65,7 +65,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
- python-version: "3.7"
+ python-version: "3.8"
cache: "pip"
- name: Setup Python
run: python -m pip install --upgrade -r scripts/requirements.txt
diff --git a/.gitignore b/.gitignore
index bfb5ae1de..bb395257a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,13 +29,14 @@ code-experiments/build/python/build/
code-experiments/build/python/dist/
code-experiments/build/python/src/cocoex/_version.py
code-experiments/build/python/src/cocoex/interface.c
+code-experiments/build/python/src/cocoex/function.c
code-experiments/build/rust/Cargo.lock
code-experiments/build/rust/Cargo.toml
code-experiments/build/rust/coco-sys/Cargo.toml
code-experiments/build/rust/coco-sys/vendor/
code-experiments/build/rust/target/
code-experiments/examples/*/coco.[ch]
-code-experiments/src/coco_version.h
+code-experiments/src/coco_version.c
code-experiments/test/**/coco.[ch]
code-experiments/test/unit-test/build/
code-experiments/test/unit-test/exdata/
diff --git a/README.md b/README.md
index fe4f58948..50da489a5 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,6 @@ Languages currently available to connect a solver to the benchmarks are
- `Python`
- `Rust`
-Code for others might be available in branched code.
Contributions to link further languages (including a better
example in `C++`) are more than welcome.
@@ -41,62 +40,46 @@ For more general information:
# Requirements
-1. For a machine running experiments
- - A `C` compiler, such as gcc
- - Python >=3.7 with `setuptools` installed
- - optional: `git`
-2. For a machine displaying data by running the post-processing
- - Python 3 with `numpy`, `scipy`, `matplotlib`, and `six` installed.
- We recommend installing the [Anaconda Python library](https://www.continuum.io/downloads)
-For Ubuntu 16.04+, all the requirements can be installed using the following command:
+The requirements vary depending on the lanuage used to run the experiments
-```
-apt-get install build-essential python-dev python-numpy python-matplotlib \
- python-scipy python-six python-setuptools
-```
+## Running experiments
+
+Depending on the language you use to implement your algorithm, the required dependencies differ.
-For macOS, the `C` compiler comes with installing the Xcode command line tools like
+* **C**: We provide cross-platform build files for both [CMake](https://cmake.org/) and [meson](https://mesonbuild.com/).
+ Additionally you will need to bring a C compiler.
+* **Java**: You need a C compiler and any Java Development Kit (JDK), such that `javac` and `javah` are accessible (i.e. in the system path). Again we provide a [CMake](https://cmake.org) based build but it should be relatively straight forward to build the interface with any other build tool.
+* **MATLAB**: You need at least MATLAB 2008, for details, see [here](./code-experiments/build/matlab/README.md)
+* **Python**: We support Python 3.8 and newer. You can install the latest `cocoex` package from [PyPI](https://pypi.org/project/cocoex/) using pip by running `pip install cocoex`.
+ We have prebuilt binaries for Windows, Linux and MacOS. If there are no binaries for your platform, you will need a C compiler to install the package from PyPI.
+* **Octave**: Octave 4.0.0 or later. On operating systems other than Windows, earlier versions might work.
+ Under Linux the package `liboctave-dev` might be necessary.
+* **Rust**: We provide the `coco-rs` crate on [crates.io](https://crates.io/crates/coco-rs). Just run `cargo add coco-rs@0.7.0` to add it to your Rust based experiment.
+
+### Additional hints
+
+#### MacOS
+
+For macOS, the C compiler comes with installing the Xcode command line tools like
```
-xcode-select install
+xcode-select --install
```
-### Windows Specifics
+#### Windows
Under Windows, two alternative compile toolchains can be used:
-1. [Cygwin](https://www.cygwin.com/) which comes with gcc and make, available in 32- and 64-bit versions.
-2. MinGW's gcc (http://www.mingw.org/ for 32-bit or https://mingw-w64.org for 64-bit machines). Make sure to update the Windows path to MinGW's make.exe and rename/link the gcc.exe to cc.exe.
+1. [Cygwin](https://www.cygwin.com/) which comes with gcc and make, available in 32- and 64-bit versions.
+1. MinGW's gcc (http://www.mingw.org/ for 32-bit or https://mingw-w64.org for 64-bit machines). Make sure to update the Windows path to MinGW's make.exe and rename/link the gcc.exe to cc.exe.
-For using `git` under Windows (optional), we recommend installing [TortoiseGit](https://tortoisegit.org/).
+## Analysing results
-### Programming Language Specifics
-_Additional_ requirements for running an algorithm in a specific language.
+To analyse and a compare the results, we provide a separate Python package named [`cocopp`](https://pypi.org/project/cocopp/) that can be installed from PyPI.
+The package will automatically install all required dependencies.
-* **C**: `make`, such as GNU make (when using [GNU make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm), make sure that your ``CC`` environment variable is set to `gcc` by potentially typing `set CC=gcc` if you see an error).
-* **Java**: `gcc` and any Java Development Kit (JDK), such that `javac` and `javah` are accessible
- (i.e. in the system path).
-* **Rust**: For details, take a look at the [Rust Readme](./code-experiments/build/rust/README.md)
-* **MATLAB**: at least MATLAB 2008, for details, see [here](./code-experiments/build/matlab/README.md)
-* **Python on Windows with MinGW**: Python 2.7 and the Microsoft compiler package for Python 2.7
- containing VC9, available [here](https://www.microsoft.com/en-us/download/details.aspx?id=44266).
- These are necessary to build the C extensions for the Python `cocoex` module for Windows.
- The package contains 32-bit and 64-bit compilers and the Windows SDK headers.
-* **Python on Linux**: `python-dev` must be installed to compile/install the `cocoex` module.
-* **Octave**: Octave 4.0.0 or later. On operating systems other than Windows, earlier versions might work.
- Under Linux the package `liboctave-dev` might be necessary.
-
-### Guaranties (None)
-We tested the framework on Mac OSX, Ubuntu linux, Fedora linux, and Windows (XP,
-7, 10) in various combinations of 32-bit and 64-bit compilers, python versions
-etc. Naturally, we cannot guarantee that the framework runs on any combination
-of operating system and software installed. In case you experience some incompatibilies,
-check out the [_Known Issues / Trouble Shooting_ Section](#Known-Issues) below.
-Otherwise we will be happy if you can document them in detail on the
-[issue tracker](https://github.com/numbbo/coco/issues).
-
-Getting Started
+# Getting Started
---------------
0. Check out the [_Requirements_](#Requirements) above.
@@ -108,6 +91,7 @@ Getting Started
As long as no experiments are meant to be run, the next points 2.-6. can be skipped and continue with points 7. and 8. below.
+1. If you want to run
1. **Download** the COCO framework code from github,
- either by clicking the [Download ZIP button](https://github.com/numbbo/coco/archive/master.zip)
@@ -165,7 +149,7 @@ Getting Started
respectively). Output is automatically generated in the
specified data `result_folder`. By now, more suites might be available, see below.
-6. **Postprocess** the data from the results folder by
+6. **Postprocess** the data from the results folder by
typing
```sh
@@ -335,215 +319,7 @@ our issue tracker at https://github.com/numbbo/coco/issues.
* howtos contains a few text files with generic howtos.
-Known Issues / Trouble-Shooting
--------------------------------
-### Java
-#### `javah` call fails
-If you see something like this when running `python do.py run-java` or `build-java`
-under Linux
-```
-COPY code-experiments/src/coco.h -> code-experiments/build/java/coco.h
-WRITE code-experiments/build/java/REVISION
-WRITE code-experiments/build/java/VERSION
-RUN javac CocoJNI.java in code-experiments/build/java
-RUN javah CocoJNI in code-experiments/build/java
-Traceback (most recent call last):
- File "do.py", line 590, in
- main(sys.argv[1:])
- File "do.py", line 563, in main
- elif cmd == 'build-java': build_java()
- File "do.py", line 437, in build_java
- env = os.environ, universal_newlines = True)
- File "/..../code-experiments/tools/cocoutils.py", line 34, in check_output
- raise error
-subprocess.CalledProcessError: Command '['locate', 'jni.h']' returned non-zero exit status 1
-```
-it means `javah` is either not installed (see above) or cannot be found in the system
-path, see [this](http://stackoverflow.com/questions/13526701/javah-missing-after-jdk-install-linux)
-and possibly [this](https://github.com/numbbo/coco/issues/416) for a solution.
-
-### Matlab
-
-#### Path to matlab
-If you see something like this when running `python do.py build-matlab`
-```
-AML ['code-experiments/src/coco_generics.c', 'code-experiments/src/coco_random.c', 'code-experiments/src/coco_suite.c', 'code-experiments/src/coco_suites.c', 'code-experiments/src/coco_observer.c', 'code-experiments/src/coco_runtime_c.c'] -> code-experiments/build/matlab/coco.c
-COPY code-experiments/src/coco.h -> code-experiments/build/matlab/coco.h
-COPY code-experiments/src/best_values_hyp.txt -> code-experiments/build/matlab/best_values_hyp.txt
-WRITE code-experiments/build/matlab/REVISION
-WRITE code-experiments/build/matlab/VERSION
-RUN matlab -nodisplay -nosplash -r setup, exit in code-experiments/build/matlab
-Traceback (most recent call last):
- File "do.py", line 447, in
- main(sys.argv[1:])
- File "do.py", line 429, in main
- elif cmd == 'build-matlab': build_matlab()
- File "do.py", line 278, in build_matlab
- run('code-experiments/build/matlab', ['matlab', '-nodisplay', '-nosplash', '-r', 'setup, exit'])
- File "/Users/auger/workviasvn/newcoco/numbbo/code-experiments/tools/cocoutils.py", line 68, in run
- universal_newlines=True)
- File "//anaconda/lib/python2.7/subprocess.py", line 566, in check_output
- process = Popen(stdout=PIPE, *popenargs, **kwargs)
- File "//anaconda/lib/python2.7/subprocess.py", line 710, in __init__
- errread, errwrite)
- File "//anaconda/lib/python2.7/subprocess.py", line 1335, in _execute_child
- raise child_exception
-OSError: [Errno 2] No such file or directory
-```
-it might be because your system does not know the `matlab` command. To fix this,
-you should edit the file `/etc/paths` and add the path to the `matlab` bin file
-(Linux/Mac) or add the path to the folder where the `matlab.exe` lies to your
-Windows path. For instance, the `etc/paths` should look like something like this
-```
-/usr/local/bin
-/usr/bin
-/bin
-/usr/sbin
-/sbin
-/Applications/MATLAB_R2012a.app/bin/
-```
-
-#### SMS-EMOA example does not compile under Mac
-With the more complex SMS-EMOA example, the problem is related to the compilation
-of the external C++ hypervolume calculation in `hv.cpp`.
-
-A fix for this issue consists in adding to the files `hv.cpp` and `paretofront.c`
-```
-#define char16_t UINT16_T
-```
-just before the line:
-```
-#include "mex.h"
-```
-
-#### Access to mex files denied
-If it happens that you get some `Access is denied` errors during
-`python do.py build-matlab` or `python do.py run-matlab` like this one
-```
-C:\Users\dimo\Desktop\numbbo-brockho>python do.py run-matlab
-Traceback (most recent call last):
- File "do.py", line 649, in
- main(sys.argv[1:])
- File "do.py", line 630, in main
- elif cmd == 'run-matlab': run_matlab()
- File "do.py", line 312, in run_matlab
- os.remove( filename )
-WindowsError: [Error 5] Access is denied: 'code-experiments/build/matlab\\cocoEv
-aluateFunction.mexw32'
-```
-a reason can be that a previously opened Matlab window still has some
-file handles open. Simply close all Matlab windows (and all running Matlab
-processes if there is any) before to run the `do.py` command again.
-
-
-### Octave
-
-#### `octave-dev` under Linux
-When running
-```
- python do.py run-octave
-```
-or
-```
- python do.py build-octave
-```
-and seeing something like
-```
- [...]
- compiling cocoCall.c...error: mkoctfile: please install the Debian package "liboctave-dev" to get the mkoctfile command
-```
-then, unsurprisingly, installing `liboctave-dev` like
-```
- sudo apt-get install liboctave-dev
-```
-should do the job.
-
-
-### Python
-
-#### `setuptools` is not installed
-If you see something like this
-```
-$ python do.py run-python # or build-python
-[...]
-PYTHON setup.py install --user in code-experiments/build/python
-ERROR: return value=1
-Traceback (most recent call last):
- File "setup.py", line 8, in
- import setuptools
-ImportError: No module named setuptools
-
-Traceback (most recent call last):
- File "do.py", line 562, in
- main(sys.argv[1:])
- File "do.py", line 539, in main
- elif cmd == 'build-python': build_python()
- File "do.py", line 203, in build_python
- python('code-experiments/build/python', ['setup.py', 'install', '--user'])
- File "/vol2/twagner/numbbo/code-experiments/tools/cocoutils.py", line 92, in python
- universal_newlines=True)
- File "/usr/local/lib/python2.7/subprocess.py", line 575, in check_output
- raise CalledProcessError(retcode, cmd, output=output)
-subprocess.CalledProcessError: Command '['/usr/local/bin/python', 'setup.py', 'install', '--user']' returned non-zero exit status 1
-```
-then `setuptools` needs to be installed:
-```
- pip install setuptools
-```
-or `easy_install setuptools` should do the job.
-
-#### Compilation During Install of `cocoex` Fails (under Linux)
-If you see something like this:
-```
-$ python do.py run-python # or build-python
-[...]
-cython/interface.c -o build/temp.linux-i686-2.6/cython/interface.o
-cython/interface.c:4:20: error: Python.h: file not found
-cython/interface.c:6:6: error: #error Python headers needed to compile C extensions, please install development version of Python.
-error: command 'gcc' failed with exit status 1
-```
-or
-```
-$ python do.py run-python # or build-python
-[...]
-cython/interface.c -o build/temp.linux-x86_64-2.7/cython/interface.o
-cython/interface.c:4:20: fatal error: Python.h: No such file or directory
-#include "Python.h"
-^
-compilation terminated.
-error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
-```
-Under Linux
-```
- sudo apt-get install python-dev
-```
-should do the trick.
-
-#### Module Update/Install Does Not Propagate
-We have observed a case where the update of the `cocoex` Python module seemed to have no
-effect. In this case it has been successful to remove all previously installed versions,
-see [here](https://github.com/numbbo/coco/issues/586) for a few more details.
-
-
-#### Installing `cocoex` after migrating macOS to the ARM chipset (M1 or M2)
-Reinstall the Xcode command line tools with
-```
-xcode-select install
-```
-and uninstall previous versions of `cocoex`
-```
-pip uninstall cocoex
-```
-until the message
-```
-WARNING: Skipping cocoex as it is not installed.
-```
-appears. Then
-```
-python do.py run-python
-```
-in the coco home folder should do the job.
-
+# Known Issues / Trouble-Shooting
### Post-Processing
diff --git a/coco.png b/coco.png
index 1e5ef2d9e..41b6d59d0 100644
Binary files a/coco.png and b/coco.png differ
diff --git a/code-experiments/build/python/MANIFEST.in b/code-experiments/build/python/MANIFEST.in
index 103f87e69..2b445f590 100644
--- a/code-experiments/build/python/MANIFEST.in
+++ b/code-experiments/build/python/MANIFEST.in
@@ -1,3 +1,8 @@
-exclude src/cocoex/interface.c
+graft test
include src/cocoex/coco.h
-include test/bbob2009*.txt
+# Don't include Cython generated files.
+exclude src/cocoex/interface.c
+exclude src/cocoex/function.c
+# Build artifacts not meant for source distribution
+global-exclude *.pyc
+global-exclude __pycache__
diff --git a/code-experiments/build/python/pyproject.toml b/code-experiments/build/python/pyproject.toml
index e83d11bcb..d0d6d5f2b 100644
--- a/code-experiments/build/python/pyproject.toml
+++ b/code-experiments/build/python/pyproject.toml
@@ -1,7 +1,7 @@
[build-system]
requires = [
- "setuptools>=61.0",
- "cython ~= 0.29.33",
+ "setuptools >= 67.0",
+ "cython ~= 3.0",
"wheel",
"numpy"
]
@@ -20,17 +20,17 @@ authors = [
]
description = 'Benchmarking framework for all types of black-box optimization algorithms.'
readme = "README.md"
-requires-python = ">=3.7"
+requires-python = ">=3.8"
license = {text = "BSD-3-Clause"}
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
- "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
]
dependencies = [
@@ -42,7 +42,11 @@ dynamic = ["version"]
version = {attr = "cocoex._version.__version__"}
[tool.setuptools.packages.find]
-where = ["src"] # list of folders that contain the packages (["."] by default)
+where = ["src"]
+
+[tool.pytest]
+log_cli = true
+addopts = "--doctest-modules"
[project.urls]
Homepage = "https://github.com/numbbo/coco"
diff --git a/code-experiments/build/python/setup.py b/code-experiments/build/python/setup.py
index 8e00fb6cc..42ac73a7b 100644
--- a/code-experiments/build/python/setup.py
+++ b/code-experiments/build/python/setup.py
@@ -4,6 +4,11 @@
extensions = []
extensions.append(Extension(name="cocoex.interface",
sources=["src/cocoex/coco.c", "src/cocoex/interface.pyx"],
+ define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
+ include_dirs=[np.get_include()]))
+extensions.append(Extension(name="cocoex.function",
+ sources=["src/cocoex/coco.c", "src/cocoex/function.pyx"],
+ define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
include_dirs=[np.get_include()]))
setup(ext_modules=extensions)
diff --git a/code-experiments/build/python/src/cocoex/__init__.py b/code-experiments/build/python/src/cocoex/__init__.py
index 0fcb3ab72..4fc8ff72f 100644
--- a/code-experiments/build/python/src/cocoex/__init__.py
+++ b/code-experiments/build/python/src/cocoex/__init__.py
@@ -15,13 +15,14 @@
A more complete example use case can be found in the `example_experiment.py`
file.
"""
-from . import interface as _interface
-from . import solvers
-from . import utilities
-from . import exceptions
-from .interface import Suite as _Suite
+from . import solvers # noqa: F401
+from . import utilities # noqa: F401
+from . import exceptions # noqa: F401
from .interface import Observer as _Observer
+from .interface import Problem as _Problem
+from .interface import Suite as _Suite
from .interface import known_suite_names
+from .interface import log_level # noqa: F401
from ._version import __version__ # noqa: F401
@@ -413,7 +414,7 @@ def result_folder(self):
return super().result_folder
# this definition is copy-edited from interface, solely to pass docstrings to pydoctor
-class Problem(_interface.Problem):
+class Problem(_Problem):
"""`Problem` instances are usually generated using class `Suite`.
The main feature of a problem instance is that it is callable, returning the
@@ -606,14 +607,3 @@ def info(self):
See also: ``repr(self)``
"""
return str(self)
-
-def log_level(level=None):
- """``log_level(level=None)`` return current log level and
- set new log level if ``level is not None and level``.
-
- :param level: must be 'error' or 'warning' or 'info' or 'debug', listed
- with increasing verbosity, or '' which doesn't change anything.
-
- """
- return _interface.log_level(level)
-
diff --git a/code-experiments/build/python/src/cocoex/function.pyx b/code-experiments/build/python/src/cocoex/function.pyx
new file mode 100644
index 000000000..6c4f735d3
--- /dev/null
+++ b/code-experiments/build/python/src/cocoex/function.pyx
@@ -0,0 +1,147 @@
+# -*- mode: cython -*-
+#cython: language_level=3, boundscheck=False, c_string_type=str, c_string_encoding=ascii
+
+import numpy as np
+cimport numpy as np
+
+from .exceptions import NoSuchProblemException, NoSuchSuiteException
+
+np.import_array()
+
+
+cdef extern from 'coco.h':
+ ctypedef struct coco_problem_t:
+ pass
+
+ char *coco_problem_get_id(coco_problem_t *p)
+ void coco_evaluate_function(coco_problem_t *p, double *x, double *y)
+ void coco_problem_free(coco_problem_t *p)
+
+# IMPORTANT: These functions are *not* declared public in coco.h so we have to
+# explicitly declare it as an external function. Otherwise Cython will *not*
+# add a declaration to the generated source files.
+cdef extern coco_problem_t *coco_get_bbob_problem(size_t function, size_t
+ dimension, size_t instance)
+cdef extern double coco_problem_get_best_value(coco_problem_t *p)
+
+
+cdef class BenchmarkFunction:
+ """A bare benchmark function from one of the available suites.
+
+ Examples
+ --------
+
+ >>> import numpy as np
+
+ Create a 13 dimensional sphere function
+
+ >>> fn = BenchmarkFunction("bbob", 1, 13, 1)
+ >>> fn
+ BenchmarkFunction('bbob', 1, 13, 1)
+
+ We can also get a short mnemonic name for the function
+
+ >>> str(fn)
+ 'bbob_f001_i01_d13'
+
+ And of course evaluate it
+
+ >>> x = np.zeros(fn.dimension)
+ >>> fn(x)
+ 124.61122368000001
+ """
+
+ cdef coco_problem_t *_problem
+ cdef readonly char* suite
+ cdef readonly char* id
+ cdef readonly int function
+ cdef readonly int dimension
+ cdef readonly int instance
+
+ def __init__(self, suite: str, function: int, dimension: int, instance: int):
+ """
+ Create a bare benchmark function from one of the COCO suites.
+
+ Parameters
+ ----------
+ suite
+ Name of benchmark suite ("bbob" only currently)
+
+ function
+ ID of function from suite
+
+ dimension
+ Dimension of instantiated function
+
+ instance
+ Instance ID of instantiated function
+
+
+ Raises
+ ------
+ NoSuchSuiteException
+ If the `suite` is not known or not yet supported
+
+ NoSuchProblemException
+ If no problem with the given `function`, `dimension` and `instance` exists in
+ the given `suite`.
+ """
+ self.suite = suite
+ self.function = function
+ self.dimension = dimension
+ self.instance = instance
+ self._problem = NULL
+ if suite == "bbob":
+ self._problem = coco_get_bbob_problem(function, dimension, instance)
+ if self._problem == NULL:
+ # FIXME: Possibly extend Exception to include dimension and instance?
+ raise NoSuchProblemException(suite, function)
+ else:
+ raise NoSuchSuiteException(suite)
+
+ self.id = coco_problem_get_id(self._problem)
+
+ def __del__(self):
+ if self._problem != NULL:
+ coco_problem_free(self._problem)
+
+ def best_value(self):
+ """Return the best (lowest) possible function value"""
+ return coco_problem_get_best_value(self._problem)
+
+ def __str__(self):
+ return self.id
+
+ def __repr__(self):
+ return f"BenchmarkFunction('{self.suite}', {self.function}, {self.dimension}, {self.instance})"
+
+ def __call__(self, x):
+ cdef double[::1] xi
+ cdef double[:, ::1] X
+ cdef Py_ssize_t N, D, i
+ cdef double[::1] y_view
+ cdef double y
+ if isinstance(x, list):
+ x = np.array(x, dtype=float)
+ if x.ndim == 1:
+ # Evaluate a single parameter
+ xi = np.array(x, dtype=float)
+ coco_evaluate_function(self._problem, &xi[0], &y)
+ return y
+ elif x.ndim == 2:
+ # Evaluate several parameters at once
+ X = x
+ N = X.shape[0]
+ D = X.shape[1]
+ Y = np.zeros(N, dtype=np.float64)
+ y_view = Y
+ for i in range(N):
+ xi = X[i, :]
+ coco_evaluate_function(self._problem, &xi[0], &y)
+ y_view[i] = y
+ return Y
+ else:
+ return None
+
+
+__all__ = ["BenchmarkFunction"]
diff --git a/code-experiments/build/python/src/cocoex/utilities.py b/code-experiments/build/python/src/cocoex/utilities.py
index 204124a49..ff0039450 100644
--- a/code-experiments/build/python/src/cocoex/utilities.py
+++ b/code-experiments/build/python/src/cocoex/utilities.py
@@ -369,12 +369,15 @@ def __init__(self):
self.evals_dimension = 0
self.evals_by_dimension = {}
self.runs_function = 0
+
def print(self, problem, end="", **kwargs):
print(self(problem), end=end, **kwargs)
_sys.stdout.flush()
+
def add_evals(self, evals, runs):
self.evals_dimension += evals
self.runs_function += runs
+
def dimension_done(self):
self.evals_by_dimension[self.d_current] = (_time.time() - self.t0_dimension) / self.evals_dimension
s = '\n %d-D done in %.1e seconds/evaluation' % (self.d_current, self.evals_by_dimension[self.d_current])
@@ -382,10 +385,12 @@ def dimension_done(self):
self.evals_dimension = 0
self.t0_dimension = _time.time()
return s
+
def function_done(self):
s = "(%d)" % self.runs_function + (2 - int(np.log10(self.runs_function))) * ' '
self.runs_function = 0
return s
+
def __call__(self, problem):
"""uses `problem.id` and `problem.dimension` to decide what to print.
"""
@@ -409,6 +414,7 @@ def __call__(self, problem):
self.f_current = f
# print_flush(res)
return res
+
def print_timings(self):
print(" dimension seconds/evaluations")
print(" -----------------------------")
@@ -416,12 +422,13 @@ def print_timings(self):
print(" %3d %.1e " %
(dim, self.evals_by_dimension[dim]))
print(" -----------------------------")
+
@staticmethod
def short_time_stap():
- l = _time.asctime().split()
- d = l[0]
- d = l[1] + l[2]
- h, m, s = l[3].split(':')
+ t = _time.asctime().split()
+ d = t[0]
+ d = t[1] + t[2]
+ h, m, s = t[3].split(':')
return d + ' ' + h + 'h' + m + ':' + s
diff --git a/code-experiments/build/python/test/test_function.py b/code-experiments/build/python/test/test_function.py
new file mode 100644
index 000000000..39c32ca4f
--- /dev/null
+++ b/code-experiments/build/python/test/test_function.py
@@ -0,0 +1,34 @@
+import pytest
+import numpy as np
+
+from cocoex.function import BenchmarkFunction
+from cocoex.exceptions import NoSuchSuiteException
+
+
+def test_bad_suite():
+ with pytest.raises(NoSuchSuiteException):
+ BenchmarkFunction("bad_suite", 1, 1, 1)
+
+
+def test_bbob():
+ for fid in range(1, 25):
+ for dimension in [2, 3, 4, 5, 7, 11, 13, 17, 18, 19, 20, 31, 40]:
+ x0 = np.zeros(dimension)
+ for instance in [0, 1, 10, 100, 1000]:
+ fn = BenchmarkFunction("bbob", fid, dimension, instance)
+ assert str(fn) == f"bbob_f{fid:03d}_i{instance:02d}_d{dimension:02d}"
+ assert fn(x0) >= fn.best_value()
+
+
+def test_list():
+ fn = BenchmarkFunction("bbob", 1, 4, 1)
+ assert fn([1, 2, 3, 4]) >= fn([1.0, 2.0, 3.0, 4.0])
+
+
+def test_multiple_parameters():
+ for n in [1, 2, 10, 100, 200]:
+ fn = BenchmarkFunction("bbob", 1, 4, 1)
+ X = np.random.uniform(-5, 5, size=(n, 4))
+ y = fn(X)
+ assert len(y) == n
+ assert np.all(y >= fn.best_value())
diff --git a/code-experiments/build/python/test/test_regression.py b/code-experiments/build/python/test/test_regression.py
index 49b38be9a..73bafdbc6 100644
--- a/code-experiments/build/python/test/test_regression.py
+++ b/code-experiments/build/python/test/test_regression.py
@@ -1,9 +1,12 @@
+import pytest
import cocoex
+from cocoex.exceptions import NoSuchSuiteException
+
def test_crash_no_dimension():
"""C code crashes when no dimensions remain after filtering.
See #2181"""
- s = cocoex.Suite("bbob", "", "dimensions:4")
- assert len(s) == 0
+ with pytest.raises(NoSuchSuiteException):
+ cocoex.Suite("bbob", "", "dimensions:4")
diff --git a/code-experiments/build/rust/src/lib.rs b/code-experiments/build/rust/src/lib.rs
index 6d383af16..71e2b503f 100644
--- a/code-experiments/build/rust/src/lib.rs
+++ b/code-experiments/build/rust/src/lib.rs
@@ -21,7 +21,7 @@ pub use observer::Observer;
/// COCO’s version.
pub fn version() -> &'static str {
- unsafe { CStr::from_ptr(coco_sys::coco_version.as_ptr()) }
+ unsafe { CStr::from_ptr(coco_sys::coco_version) }
.to_str()
.unwrap()
}
diff --git a/code-experiments/src/coco.h b/code-experiments/src/coco.h
index d903bd3df..7fb7470ec 100644
--- a/code-experiments/src/coco.h
+++ b/code-experiments/src/coco.h
@@ -92,7 +92,15 @@ typedef unsigned __int64 uint64_t;
extern "C" {
#endif
-#include "coco_version.h"
+/**
+* @brief COCO's version.
+*
+* The version number is dervied from the latest tag in the
+* repository plus the number of commits after the tag.
+*/
+/**@{*/
+extern const char *coco_version;
+/**@}*/
/***********************************************************************************************************/
/**
diff --git a/code-experiments/src/coco_platform.h b/code-experiments/src/coco_platform.h
index 8471ef936..897234510 100644
--- a/code-experiments/src/coco_platform.h
+++ b/code-experiments/src/coco_platform.h
@@ -22,7 +22,7 @@
static const char *coco_path_separator = "\\";
#define COCO_PATH_MAX MAX_PATH
#define HAVE_GFA 1
-#elif defined(__gnu_linux__)
+#elif defined(__gnu_linux__) || defined(__linux__)
#include
#include
#include
diff --git a/code-experiments/src/suite_bbob.c b/code-experiments/src/suite_bbob.c
index 35aec8892..7479de859 100644
--- a/code-experiments/src/suite_bbob.c
+++ b/code-experiments/src/suite_bbob.c
@@ -95,7 +95,7 @@ static const char *suite_bbob_get_instances_by_year(const int year) {
*
* Useful for other suites as well (see for example suite_biobj.c).
*/
-static coco_problem_t *coco_get_bbob_problem(const size_t function,
+coco_problem_t *coco_get_bbob_problem(const size_t function,
const size_t dimension,
const size_t instance) {
coco_problem_t *problem = NULL;
diff --git a/code-postprocessing/MANIFEST.in b/code-postprocessing/MANIFEST.in
index 879e9f626..57387a1d4 100644
--- a/code-postprocessing/MANIFEST.in
+++ b/code-postprocessing/MANIFEST.in
@@ -1,3 +1,4 @@
include cocopp/js/*
include cocopp/refalgs/*.tar.gz
include cocopp/bbob-*infos.txt
+include cocopp/*.pickle.gz
diff --git a/code-postprocessing/cocopp/archiving.py b/code-postprocessing/cocopp/archiving.py
index 76c74a5ee..9398231fa 100644
--- a/code-postprocessing/cocopp/archiving.py
+++ b/code-postprocessing/cocopp/archiving.py
@@ -88,7 +88,14 @@
"https://numbbo.github.io/data-archive/data-archive", # new location
]
coco_url = coco_urls[-1] # may be reassigned if it doesn't work out
-cocopp_home = os.path.abspath(os.path.expanduser(os.path.join("~", ".cocopp")))
+
+# cocopp needs a directory where it can cache downloaded datasets.
+#
+# We use `platformdirs` to find the users cache directory in a platform independent way
+# and create a subdirectory within for cocopp.
+
+import platformdirs
+cocopp_home = platformdirs.user_cache_dir("cocopp", ensure_exists=True)
default_archive_location = os.path.join(cocopp_home, 'data-archives')
default_definition_filename = 'coco_archive_definition.txt'
cocopp_home_archives = default_archive_location
diff --git a/code-postprocessing/pyproject.toml b/code-postprocessing/pyproject.toml
index 04b0cd789..639b18f74 100644
--- a/code-postprocessing/pyproject.toml
+++ b/code-postprocessing/pyproject.toml
@@ -34,6 +34,8 @@ classifiers = [
dependencies = [
"matplotlib >=3.5.0",
"numpy >=1.21.0",
+ "setuptools >=61.0", # For pkg_resources
+ "platformdirs >=3.8.1",
]
dynamic = ["version"]
diff --git a/scripts/fabricate b/scripts/fabricate
index c6952ece6..b968582ff 100755
--- a/scripts/fabricate
+++ b/scripts/fabricate
@@ -29,7 +29,8 @@ RUST_DIR = BUILD_DIR / "rust"
CORE_FILES = ['code-experiments/src/coco_random.c',
'code-experiments/src/coco_suite.c',
'code-experiments/src/coco_observer.c',
- 'code-experiments/src/coco_archive.c'
+ 'code-experiments/src/coco_archive.c',
+ 'code-experiments/src/coco_version.c'
]
@@ -186,26 +187,15 @@ def write_version_to_python(filename, version):
fd.write(f'__version__ = version = "{version}"\n')
-def write_version_to_c_header(filename, version,
+def write_version_to_c_file(filename, version,
variable="coco_version",
guard="COCO_VERSION"):
info("version", f"{version} -> {filename}")
with open(ROOT_DIR / filename, "wt") as fd:
- fd.write("/* file generated by do.py\n")
+ fd.write("/* file generated by fabricate.py\n")
fd.write(" * don't change, don't track in version control!\n")
fd.write(" */\n\n")
- fd.write(f"#ifndef {guard}_H\n")
- fd.write(f"#define {guard}_H\n")
- fd.write("/**\n")
- fd.write("* @brief COCO's version.\n")
- fd.write("*\n")
- fd.write("* The version number is dervied from the latest tag in the\n")
- fd.write("* repository plus the number of commits after the tag.\n")
- fd.write("*/\n")
- fd.write("/**@{*/\n")
- fd.write(f'static const char { variable }[{ len(version)+1 }] = "{ version }";\n')
- fd.write("/**@}*/\n")
- fd.write("#endif\n")
+ fd.write(f'const char *{ variable } = "{ version }";\n')
################################################################################
## MAIN
@@ -251,7 +241,7 @@ OCTAVE_DISTFILE = DIST_DIR / f"cocoex-octave-{COCO_VERSION}.zip"
JAVA_DISTFILE = DIST_DIR / f"cocoex-java-{COCO_VERSION}.zip"
RUST_DISTFILE = DIST_DIR / f"cocoex-rust-{COCO_VERSION}.zip"
-write_version_to_c_header("code-experiments/src/coco_version.h", COCO_VERSION)
+write_version_to_c_file("code-experiments/src/coco_version.c", COCO_VERSION)
if not args.skip_c:
write_version_file("code-experiments/build/c/VERSION", COCO_VERSION)