Skip to content

Commit 6d19e4a

Browse files
committed
Updated docs for optimiser and CMA-ES. Added proper exception for CMA-ES not supporting 1-d. Closes #1695. Closes #1693. #Closes #1504. Closes #1524.
1 parent 9843b64 commit 6d19e4a

File tree

4 files changed

+60
-14
lines changed

4 files changed

+60
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
1010
- [#1505](https://github.com/pints-team/pints/pull/1505) Added notes to `ErrorMeasure` and `LogPDF` to say parameters must be real and continuous.
1111
- [#1499](https://github.com/pints-team/pints/pull/1499) Added a log-uniform prior class.
1212
### Changed
13+
- [#1698](https://github.com/pints-team/pints/pull/1698) CMA-ES now raises a more informative exception when an unsupported 1-d optimisation is attempted.
1314
- [#1503](https://github.com/pints-team/pints/pull/1503) Stopped showing time units in controller logs, because the units change depending on the output type (see #1467).
1415
### Deprecated
1516
### Removed
@@ -18,6 +19,7 @@ All notable changes to this project will be documented in this file.
1819
- [#1505](https://github.com/pints-team/pints/pull/1505) Fixed issues with toy problems that accept invalid inputs.
1920

2021

22+
2123
## [0.5.0] - 2023-07-27
2224

2325
### Added

pints/_optimisers/__init__.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,23 @@ class Optimiser(pints.Loggable, pints.TunableMethod):
3434
Parameters
3535
----------
3636
x0
37-
A starting point for searches in the parameter space. This value may be
38-
used directly (for example as the initial position of a particle in
37+
A starting point for searches in the parameter space. This must be a
38+
1-dimensional vector, and its length will determine the dimensionality
39+
of the search space. The initial position ``x0`` may may be used
40+
directly (for example as the initial position of a particle in
3941
:class:`PSO`) or indirectly (for example as the center of a
4042
distribution in :class:`XNES`).
4143
sigma0
4244
An optional initial standard deviation around ``x0``. Can be specified
4345
either as a scalar value (one standard deviation for all coordinates)
4446
or as an array with one entry per dimension. Not all methods will use
45-
this information.
47+
this information, and some methods will only use part of the provided
48+
information (e.g. ``CMA-ES`` will only use the smallest value in
49+
``sigma0``). If no value for ``sigma0`` is provided, a guess will be
50+
made. If a :meth:`range<Boundaries.range>` can be obtained from
51+
provided boundaries, then 1/6th of this range will be used. If not, the
52+
value will be set as ``abs(x0[i]) / 3`` for any ``i`` where
53+
``x0[i] != 0`` or as ``1`` where ``x0[i] == 0``.
4654
boundaries
4755
An optional set of boundaries on the parameter space.
4856
@@ -340,17 +348,14 @@ class OptimisationController(object):
340348
An :class:`pints.ErrorMeasure` or a :class:`pints.LogPDF` that
341349
evaluates points in the parameter space.
342350
x0
343-
The starting point for searches in the parameter space. This value may
344-
be used directly (for example as the initial position of a particle in
345-
:class:`PSO`) or indirectly (for example as the center of a
346-
distribution in :class:`XNES`).
351+
The starting point for searches in the parameter space. For details,
352+
see :class:`Optimiser`.
347353
sigma0
348-
An optional initial standard deviation around ``x0``. Can be specified
349-
either as a scalar value (one standard deviation for all coordinates)
350-
or as an array with one entry per dimension. Not all methods will use
351-
this information.
354+
An optional initial standard deviation around ``x0``. For details, see
355+
:class:`Optimiser`.
352356
boundaries
353-
An optional set of boundaries on the parameter space.
357+
An optional set of boundaries on the parameter space. For details, see
358+
:class:`Optimiser`.
354359
transformation
355360
An optional :class:`pints.Transformation` to allow the optimiser to
356361
search in a transformed parameter space. If used, points shown or
@@ -359,6 +364,7 @@ class OptimisationController(object):
359364
method
360365
The class of :class:`pints.Optimiser` to use for the optimisation.
361366
If no method is specified, :class:`CMAES` is used.
367+
362368
"""
363369

364370
def __init__(

pints/_optimisers/_cmaes.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@ class CMAES(pints.PopulationBasedOptimiser):
1818
CMA-ES stands for Covariance Matrix Adaptation Evolution Strategy, and is
1919
designed for non-linear derivative-free optimization problems.
2020
21+
To initialise, set an initial position ``x0``, an initial covariance
22+
``sigma0``, and optionally a set of :class:`pints.Boundaries`.
23+
24+
CMA-ES is designed for multivariate optimisation, so ``x0`` should have a
25+
dimension of 2 or greater.
26+
27+
The initial covariance ``sigma0`` should be a scalar (one standard
28+
deviation for all parameters), but for compatibility with other optimisers
29+
an array is also accepted: in this case the smallest value in ``sigma0``
30+
will be used. If no ``sigma0`` is given a guess will be made based on the
31+
boundaries (if provided) or ``x0``, see :meth:`Optimiser` for details. The
32+
method's authors suggest choosing ``sigma0`` such that the optimum is
33+
expected to be within ``3 * sigma0`` from the initial position ``x0``.
34+
35+
:class:`Rectangular boundaries<pints.RectangularBoundaries>` are supported
36+
by the ``cma`` module natively. Other boundary shapes are also supported
37+
but will be handled by ``PINTS`` (which will pass ``nan`` to ``cma`` for
38+
any point requested outside of the boundaries).
39+
2140
Extends :class:`PopulationBasedOptimiser`.
2241
2342
References
@@ -38,6 +57,11 @@ class CMAES(pints.PopulationBasedOptimiser):
3857
def __init__(self, x0, sigma0=None, boundaries=None):
3958
super(CMAES, self).__init__(x0, sigma0, boundaries)
4059

60+
# 1-D is not supported
61+
if len(x0) < 2:
62+
raise ValueError(
63+
'1-dimensional optimisation is not supported by CMA-ES.')
64+
4165
# Set initial state
4266
self._running = False
4367
self._ready_for_tell = False

pints/tests/test_opt_cmaes.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
# copyright notice and full license details.
88
#
99
import unittest
10+
import warnings
11+
1012
import numpy as np
1113

1214
import pints
@@ -124,8 +126,15 @@ def test_ask_tell(self):
124126
self.assertEqual(opt.f_guessed(), np.inf)
125127

126128
# Test deprecated xbest and fbest
127-
self.assertEqual(list(opt.xbest()), list(x))
128-
self.assertEqual(opt.fbest(), np.inf)
129+
with warnings.catch_warnings(record=True) as w:
130+
warnings.simplefilter('always')
131+
self.assertEqual(list(opt.xbest()), list(x))
132+
self.assertEqual(len(w), 1)
133+
self.assertIn('xbest` is deprecated', str(w[-1].message))
134+
with warnings.catch_warnings(record=True) as w:
135+
self.assertEqual(opt.fbest(), np.inf)
136+
self.assertEqual(len(w), 1)
137+
self.assertIn('fbest` is deprecated', str(w[-1].message))
129138

130139
# Tell before ask
131140
self.assertRaisesRegex(
@@ -154,6 +163,11 @@ def test_name(self):
154163
opt = method(np.array([0, 1.01]))
155164
self.assertIn('CMA-ES', opt.name())
156165

166+
def test_one_dimensional(self):
167+
# Tests 1-d is not supported
168+
self.assertRaisesRegex(
169+
ValueError, '1-dimensional optimisation is', pints.CMAES, [1])
170+
157171

158172
if __name__ == '__main__':
159173
print('Add -v for more debug output')

0 commit comments

Comments
 (0)