Skip to content

Commit

Permalink
argmin_testfunctions version 0.2.0 and argmin-testfunctions-py versio…
Browse files Browse the repository at this point in the history
…n 0.0.1
  • Loading branch information
stefan-k committed Feb 16, 2024
1 parent aa03c61 commit 06b9ce1
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 28 deletions.
34 changes: 17 additions & 17 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
branches:
- main
tags:
- '*'
- 'argmin-testfunctions-py-v*'
pull_request:
workflow_dispatch:

Expand Down Expand Up @@ -105,19 +105,19 @@ jobs:
name: wheels
path: dist

# release:
# name: Release
# runs-on: ubuntu-latest
# if: "startsWith(github.ref, 'refs/tags/')"
# needs: [linux, windows, macos, sdist]
# steps:
# - uses: actions/download-artifact@v3
# with:
# name: wheels
# - name: Publish to PyPI
# uses: PyO3/maturin-action@v1
# env:
# MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
# with:
# command: upload
# args: --non-interactive --skip-existing *
release:
name: Release
runs-on: ubuntu-latest
if: "startsWith(github.ref, 'refs/tags/argmin-testfunctions-py-v')"
needs: [linux, windows, macos, sdist]
steps:
- uses: actions/download-artifact@v3
with:
name: wheels
- name: Publish to PyPI
uses: PyO3/maturin-action@v1
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --non-interactive --skip-existing *
44 changes: 37 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,38 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (since argmin version 0.6.0),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (since argmin version 0.5.0).

## argmin [argmin unreleased]
## [argmin unreleased]

## argmin-math [argmin-math unreleased]
## [argmin-math unreleased]

## argmin [argmin v0.9.0] 2024-01-06
## [argmin-testfunctions-py v0.0.1] 2024-02-16

* The first version of a Python wrapper around `argmin_testfunctions` was released.
* The fact that this is still experimental is expressed with the version number 0.0.1. Eventually this module's version may end up in lockstep with `argmin_testfunctions`' version number.

## [argmin_testfunctions v0.2.0] 2024-02-16

All work of this release was done by @stefan-k.

### Added

* Added derivative and Hessian calculation to all test functions.
* Tested all derivatives and Hessian against finite differences (with `finitediff`) on multiple positions with `proptest`.
* Added const generics versions for the derivatives and Hessians of multi dimensional test functions to avoid allocations.
* Those test functions which operate on a fixed number of parameters now take a fixed length array as input instead of a slice.

### Fixed

* Bugs in the Levy test function were fixed.

### Changed

* Rust edition 2021
* Repository was moved into argmin monorepo
* `rosenbrock` now only takes the parameters as input. For setting the additional optional parameters `a` and `b` one can use `rosenbrock_ab`
* All `rosenbrock_2d*` functions were removed.

## [argmin v0.9.0] 2024-01-06

### Added

Expand All @@ -31,7 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Updated gnuplot to 0.0.39 (@stefan-k, #364)
* Switched to resolver = 2 for entire workspace (@stefan-k, #372)

## argmin [argmin v0.8.1] 2023-02-20
## [argmin v0.8.1] 2023-02-20

### Added

Expand All @@ -49,7 +76,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Updated slog-term to 2.9 (@stefan-k)
* Updated slog-json to 2.6 (@stefan-k)

## argmin [argmin v0.8.0] 2023-01-28
## [argmin v0.8.0] 2023-01-28

### Added

Expand All @@ -71,7 +98,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* The check whether the target cost is reached is now based on the current best cost function value rather than the current cost function value (@relf)


## argmin-math [argmin-math v0.3.0] 2023-01-28
## [argmin-math v0.3.0] 2023-01-28

### Added

Expand Down Expand Up @@ -263,8 +290,11 @@ This is a rather large release with many (breaking) changes.

For older versions please see the Git history.

[argmin unreleased]: https://github.com/argmin-rs/argmin/compare/argmin-v0.8.1...HEAD
[argmin unreleased]: https://github.com/argmin-rs/argmin/compare/argmin-v0.9.0...HEAD
[argmin-math unreleased]: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.3.0...HEAD
[argmin_testfunctions unreleased]: https://github.com/argmin-rs/argmin/compare/argmin-v0.9.0...HEAD
[argmin-testfunctions-py v0.0.1]: https://github.com/argmin-rs/argmin/compare/argmin-v0.9.0...argmin-testfunctions-py-v0.0.1
[argmin_testfunctions v0.2.0]: https://github.com/argmin-rs/argmin/compare/argmin-v0.9.0...argmin_testfunctions-v0.2.0
[argmin v0.9.0]: https://github.com/argmin-rs/argmin/compare/argmin-v0.8.1...argmin-v0.9.0
[argmin v0.8.1]: https://github.com/argmin-rs/argmin/compare/argmin-v0.8.0...argmin-v0.8.1
[argmin v0.8.0]: https://github.com/argmin-rs/argmin/compare/argmin-v0.7.0...argmin-v0.8.0
Expand Down
2 changes: 1 addition & 1 deletion crates/argmin-testfunctions/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "argmin_testfunctions"
version = "0.1.1"
version = "0.2.0"
authors = ["Stefan Kroboth <stefan.kroboth@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
Expand Down
2 changes: 1 addition & 1 deletion crates/argmin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"], optional = true }
[dev-dependencies]
approx = "0.5.0"
finitediff = { version = "0.1.4", features = ["ndarray"] }
argmin_testfunctions = { version = "0.1.1", path = "../argmin-testfunctions" }
argmin_testfunctions = { version = "0.2.0", path = "../argmin-testfunctions" }
ndarray = { version = "0.15", features = ["serde-1"] }
ndarray-linalg = { version = "0.16", features = ["intel-mkl-static"] }
argmin-math = { path = "../argmin-math", version = "0.3", features = ["vec"] }
Expand Down
177 changes: 177 additions & 0 deletions media/website/content/blog/argmin_testfunctions-v0.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
+++
title = "argmin_testfunctions 0.2.0 and argmin-testfunctions-py v0.0.1 released"
description = ""
date = 2024-02-16T00:00:00+00:00
updated = 2024-02-16T00:00:00+00:00
draft = false
template = "blog/page.html"

[taxonomies]
authors = ["Stefan Kroboth"]

[extra]
+++

<b>argmin</b> is a Rust library which offers a range of numerical optimization methods and is a framework for
developing optimization algorithms. Details about the design and features of argmin can be found on
[the website](https://argmin-rs.org),
in the [book](https://argmin-rs.org/book),
on [Github](https://github.com/argmin-rs/argmin),
on [crates.io](https://crates.io/crates/argmin) and
on [lib.rs](https://lib.rs/crates/argmin).

<b>argmin_testfunctions</b> is one of the Rust libraries in the argmin ecosystem and provides a wide range of
test functions for optimization problems (not just for argmin). For many years it has been sitting around in its repo without
getting much attention.
I decided to change that by pulling the code into the argmin monorepo, updating it to the current Rust edition
and started implementing new features. The main addition is the calculation of the derivatives and Hessians
for all cost functions.

As input, the functions now take parameters either as `&[T]`, `&[T; 2]`, or `&[T; N]` where `N` is a const generic and
`T: Float` (`f64` and `f32`).
Functions which only accept two dimensional input accept `&[T; 2]` and return `T` (test function), `[T; 2]` (derivative), or `[[T; 2]; 2]`
(Hessian).
An example for this is the Himmelblau test function:

```rust
use argmin_testfunctions::{himmelblau, himmelblau_derivative, himmelblau_hessian};

let p: [f64; 2] = [0.1, 0.2];

let c: f64 = himmelblau(&p);
let d: [f64; 2] = himmelblau_derivative(&p);
let h: [[f64; 2]; 2] = himmelblau_hessian(&p);
```

Functions which accept an arbitrary number of parameters come in two forms. One variant accepts `&[T]` and returns
`T` (test function), `Vec<T>` (derivative), or `Vec<Vec<T>>` (Hessian), for instance:

```rust
use argmin_testfunctions::{rosenbrock, rosenbrock_derivative, rosenbrock_hessian};

let p = [0.1, 0.2, 0.3];

let c: f64 = rosenbrock(&p);
let d: Vec<f64> = rosenbrock_derivative(&p);
let h: Vec<Vec<f64>> = rosenbrock_hessian(&p);
```

This obviously allocates `Vec`s and as such isn't the most efficient. If the number of parameters are known
at compile-time, one can use the const generics version of the functions which take `&[T; N]` and return
`[T; N]` (derivative) or `[[T; N]; N]` (Hessian):

```rust
use argmin_testfunctions::{
rosenbrock, rosenbrock_derivative_const, rosenbrock_hessian_const
};

let p: [f64; 3] = [0.1, 0.2, 0.3];

let c: f64 = rosenbrock(&p);
let d: [f64; 3] = rosenbrock_derivative_const(&p);
let h: [[f64; 3]; 3] = rosenbrock_hessian_const(&p);
```

This does not allocate and hence is generally faster.
The Rosenbrock test function also has additional optional parameters `a` and `b` which can be adjusted to one's needs:

```rust
use argmin_testfunctions::{
rosenbrock_ab, rosenbrock_ab_derivative, rosenbrock_ab_derivative_const,
rosenbrock_ab_hessian, rosenbrock_ab_hessian_const
};

let p = [0.1, 0.2, 0.3];
let a = 5.0;
let b = 200.0;

let c: f64 = rosenbrock_ab(&p, a, b);
let d: Vec<f64> = rosenbrock_ab_derivative(&p, a, b);
let h: Vec<Vec<f64>> = rosenbrock_ab_hessian(&p, a, b);

// There are also const generics versions
let d: [f64; 3] = rosenbrock_ab_derivative_const(&p, a, b);
let h: [[f64; 3]; 3] = rosenbrock_ab_hessian_const(&p, a, b);
```

Similar functions exist for `ackley` (`ackley_abc`) and `rastrigin` (`rastrigin_a`).


## Python interface

The new Python module `argmin-testfunctions-py` makes the library availably in Python as well.
It offers the same functions, apart from the const generics versions, which are missing.
Optional parameters such as `a` and `b` of the Rosenbrock test function are optional
arguments in Python:

```python
from argmin_testfunctions_py import *

c = rosenbrock([0.1, 0.2, 0.3, 0.4], a = 5.0, b = 200.0)
g = rosenbrock_derivative([0.1, 0.2, 0.3, 0.4], a = 5.0, b = 200.0)
h = rosenbrock_hessian([0.1, 0.2, 0.3, 0.4], a = 5.0, b = 200.0)

# When omitted, they will default to a = 1.0 and b = 100.0
c = rosenbrock([0.1, 0.2, 0.3, 0.4])
g = rosenbrock_derivative([0.1, 0.2, 0.3, 0.4])
h = rosenbrock_hessian([0.1, 0.2, 0.3, 0.4])
```

This module is still a bit experimental, which is expressed with the version number 0.0.1.
Eventually the version of the Python module may end up in lockstep with `argmin_testfunctions`' version number.

It can be found on [PyPI](https://pypi.org/project/argmin-testfunctions-py/) and installed via
`pip install argmin-testfunctions-py`.


## Tests and Benchmarks

All test functions are tested against known points and the derivative and Hessian calculations
are tested against finite differences (using [finitediff](https://crates.io/crates/finitediff)).
Multiple parameter vectors are evaluated using [proptest](https://crates.io/crates/proptest).
As usual, tests can be executed with `cargo test`.

The benchmarks now use [criterion.rs](https://crates.io/crates/criterion). `cargo bench` will benchmark all
functions and produce a report in `target/criterion/report/index.html`.


## Contributing

This library's usefulness is directly proportional to the number of test functions it provides.
Therefore all contributions to this library are highly welcome. Interested people should have a look
at [this issue](https://github.com/argmin-rs/argmin/issues/450) which provides inspiration for what
to implement as well as a couple of hints on how to implement it such that it best fits into the library.

While I believe that most implementations are quite efficient, I am sure that there are some which could
be improved. If anyone wants to get the last bit of performance out of this, feel free to open a PR.

Ideally this library would also print the formulas in the docs
[as actual formulas](https://github.com/argmin-rs/argmin/issues/418) and having
[visualizations of the test functions](https://github.com/argmin-rs/argmin/issues/451) in the docs wouldn't hurt either.

## Conclusion

With this release the `argmin_testfunctions` crate finally got derivative and Hessian calculations for
all test functions.
Thanks to `argmin-testfunctions-py` the functionality is now also available in Python.
Hopefully this crate will be of use to some. If you find bugs or have suggestions or feedback, feel free to get
in touch, either via Github or the Discord.

Details on the individual test functions can be found in the documentation, either for the
[latest release](https://docs.rs/argmin_testfunctions) or
[the current main branch](https://argmin-rs.github.io/argmin/argmin_testfunctions/index.html).


## Discord server

If you're interested you're invited to join the [Discord](https://discord.gg/fYB8AwxxMW)!


<br>
<script async defer src="https://buttons.github.io/buttons.js"></script>
<p align="center">
<a class="github-button" href="https://github.com/argmin-rs/argmin" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star argmin-rs/argmin on GitHub">Star</a>
<a class="github-button" href="https://github.com/argmin-rs/argmin/subscription" data-icon="octicon-eye" data-size="large" data-show-count="true" aria-label="Watch argmin-rs/argmin on GitHub">Watch</a>
<a class="github-button" href="https://github.com/argmin-rs/argmin/fork" data-icon="octicon-repo-forked" data-size="large" data-show-count="true" aria-label="Fork argmin-rs/argmin on GitHub">Fork</a>
<a class="github-button" href="https://github.com/sponsors/stefan-k" data-icon="octicon-heart" data-size="large" aria-label="Sponsor @stefan-k on GitHub">Sponsor</a>
</p>
4 changes: 2 additions & 2 deletions python/argmin-testfunctions-py/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "argmin-testfunctions-py"
version = "0.1.1"
version = "0.0.1"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["Stefan Kroboth <stefan.kroboth@gmail.com>"]
Expand All @@ -18,6 +18,6 @@ name = "argmin_testfunctions_py"
crate-type = ["cdylib"]

[dependencies]
argmin_testfunctions = { version = "0.1.1", path = "../../crates/argmin-testfunctions" }
argmin_testfunctions = { version = "0.2.0", path = "../../crates/argmin-testfunctions" }
paste = "1"
pyo3 = "0.20"
3 changes: 3 additions & 0 deletions python/argmin-testfunctions-py/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
</p>

<p align="center">
<a href="https://pypi.org/project/argmin-testfunctions-py/">
<img alt="PyPI" src="https://img.shields.io/pypi/v/argmin-testfunctions-py?style=flat-square">
</a>
<a href="https://github.com/argmin-rs/argmin/actions"
><img
src="https://img.shields.io/github/actions/workflow/status/argmin-rs/argmin/python.yml?branch=main&label=argmin CI&style=flat-square"
Expand Down

0 comments on commit 06b9ce1

Please sign in to comment.