Skip to content

Commit

Permalink
Adds maximum iterations functionality to scipyminimize, nloptoptimize…
Browse files Browse the repository at this point in the history
…, baseoptimise, restore test_spm_optimisers assertions
  • Loading branch information
BradyPlanden committed Dec 8, 2023
1 parent 6ef4f0d commit 097bc51
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 12 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Features

- [#131](https://github.com/pybop-team/PyBOP/issues/131) - Adds `SciPyDifferentialEvolution` optimiser
- [#131](https://github.com/pybop-team/PyBOP/issues/131) - Adds `SciPyDifferentialEvolution` optimiser, adds functionality for user-selectable maximum iteration limit to `SciPyMinimize`, `NLoptOptimize`, and `BaseOptimiser` classes.
- [#107](https://github.com/pybop-team/PyBOP/issues/107) - Adds Equivalent Circuit Model (ECM) with examples, Import/Export parameter methods `ParameterSet.import_parameter` and `ParameterSet.export_parameters`, updates default FittingProblem.signal definition to `"Voltage [V]"`, and testing infrastructure
- [#127](https://github.com/pybop-team/PyBOP/issues/127) - Adds Windows and macOS runners to the `test_on_push` action
- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds standard plotting class `pybop.StandardPlot()` via plotly backend
Expand Down
1 change: 1 addition & 0 deletions pybop/optimisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def _run_pybop(self):
cost_function=self.cost,
x0=self.x0,
bounds=self.bounds,
maxiter=self._max_iterations,
)
self.log = self.optimiser.log

Expand Down
3 changes: 2 additions & 1 deletion pybop/optimisers/base_optimiser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ class BaseOptimiser:
def __init__(self):
pass

def optimise(self, cost_function, x0=None, bounds=None):
def optimise(self, cost_function, x0=None, bounds=None, maxiter=None):
"""
Optimisiation method to be overloaded by child classes.
"""
self.cost_function = cost_function
self.x0 = x0
self.bounds = bounds
self.maxiter = maxiter

# Run optimisation
result = self._runoptimise(self.cost_function, x0=self.x0, bounds=self.bounds)
Expand Down
7 changes: 6 additions & 1 deletion pybop/optimisers/nlopt_optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ class NLoptOptimize(BaseOptimiser):
Wrapper class for the NLOpt optimiser class. Extends the BaseOptimiser class.
"""

def __init__(self, n_param, xtol=None, method=None):
def __init__(self, n_param, xtol=None, method=None, maxiter=None):
super().__init__()
self.n_param = n_param
self.maxiter = maxiter

if method is not None:
self.optim = nlopt.opt(method, self.n_param)
Expand Down Expand Up @@ -46,6 +47,10 @@ def cost_wrapper(x, grad):
self.optim.set_lower_bounds(bounds["lower"])
self.optim.set_upper_bounds(bounds["upper"])

# Set max iterations
if self.maxiter is not None:
self.optim.set_maxeval(self.maxiter)

# Run the optimser
x = self.optim.optimize(x0)

Expand Down
14 changes: 12 additions & 2 deletions pybop/optimisers/scipy_optimisers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ class SciPyMinimize(BaseOptimiser):
Wrapper class for the SciPy optimisation class. Extends the BaseOptimiser class.
"""

def __init__(self, method=None, bounds=None):
def __init__(self, method=None, bounds=None, maxiter=None):
super().__init__()
self.method = method
self.bounds = bounds
self.maxiter = maxiter
if self.maxiter is not None:
self.options = {"maxiter": self.maxiter}
else:
self.options = {}

if self.method is None:
self.method = "COBYLA" # "L-BFGS-B"
Expand Down Expand Up @@ -40,7 +45,12 @@ def callback(x):
)

output = minimize(
cost_function, x0, method=self.method, bounds=bounds, callback=callback
cost_function,
x0,
method=self.method,
bounds=bounds,
options=self.options,
callback=callback,
)

# Get performance statistics
Expand Down
9 changes: 2 additions & 7 deletions tests/unit/test_parameterisations.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,8 @@ def test_spm_optimisers(self, spm_cost, x0):
x, final_cost = parameterisation.run()

# Assertions
# Note: SciPyMinimize has a different tolerance due to the local optimisation algorithms
if optimiser in [pybop.SciPyMinimize]:
np.testing.assert_allclose(final_cost, 0, atol=1e-2)
np.testing.assert_allclose(x, x0, atol=2e-1)
else:
np.testing.assert_allclose(final_cost, 0, atol=1e-2)
np.testing.assert_allclose(x, x0, atol=1e-1)
np.testing.assert_allclose(final_cost, 0, atol=1e-2)
np.testing.assert_allclose(x, x0, atol=1e-1)

@pytest.mark.parametrize("init_soc", [0.3, 0.7])
@pytest.mark.unit
Expand Down

0 comments on commit 097bc51

Please sign in to comment.