Skip to content

Commit

Permalink
Add optimiser.name() to optimisers, updt. plotting across examples, c…
Browse files Browse the repository at this point in the history
…hange plot_convergence() to plot mininum cost trace, merge develop
  • Loading branch information
BradyPlanden committed Nov 23, 2023
2 parents bef09c9 + 5225cfc commit e0cd5b5
Show file tree
Hide file tree
Showing 21 changed files with 547 additions and 144 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# [Unreleased](https://github.com/pybop-team/PyBOP)

## Features
- [#114](https://github.com/pybop-team/PyBOP/issues/114) Adds standard plotting class `pybop.StandardPlot()` via plotly backend
- [#114](https://github.com/pybop-team/PyBOP/issues/114) Adds `quick_plot()`, `plot_convergence()`, and `plot_cost2d()` methods
- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds standard plotting class `pybop.StandardPlot()` via plotly backend
- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds `quick_plot()`, `plot_convergence()`, and `plot_cost2d()` methods
- [#116](https://github.com/pybop-team/PyBOP/issues/116) - Adds PSO, SNES, XNES, ADAM, and IPropMin optimisers to PintsOptimisers() class

## Bug Fixes

Expand Down
22 changes: 17 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,29 @@ def pytest_addoption(parser):
parser.addoption(
"--unit", action="store_true", default=False, help="run unit tests"
)
parser.addoption(
"--examples", action="store_true", default=False, help="run examples tests"
)


def pytest_configure(config):
config.addinivalue_line("markers", "unit: mark test as a unit test")
config.addinivalue_line("markers", "examples: mark test as an example")


def pytest_collection_modifyitems(config, items):
def skip_marker(marker_name, reason):
skip = pytest.mark.skip(reason=reason)
for item in items:
if marker_name in item.keywords:
item.add_marker(skip)

if config.getoption("--unit"):
# --unit given in cli: do not skip unit tests
skip_marker("examples", "need --examples option to run")
return
skip_unit = pytest.mark.skip(reason="need --unit option to run")
for item in items:
if "unit" in item.keywords:
item.add_marker(skip_unit)

if config.getoption("--examples"):
skip_marker("unit", "need --unit option to run")
return

skip_marker("unit", "need --unit option to run")
4 changes: 2 additions & 2 deletions examples/scripts/CMAES.py → examples/scripts/spm_CMAES.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPMe(parameter_set=parameter_set)
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

# Fitting parameters
parameters = [
Expand All @@ -20,7 +20,7 @@
]

# Generate data
sigma = 0.01
sigma = 0.001
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
CorruptValues = values["Terminal voltage [V]"].data + np.random.normal(
Expand Down
54 changes: 54 additions & 0 deletions examples/scripts/spm_IRPropMin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pybop
import numpy as np

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

# Fitting parameters
parameters = [
pybop.Parameter(
"Negative electrode active material volume fraction",
prior=pybop.Gaussian(0.7, 0.05),
bounds=[0.6, 0.9],
),
pybop.Parameter(
"Positive electrode active material volume fraction",
prior=pybop.Gaussian(0.58, 0.05),
bounds=[0.5, 0.8],
),
]

sigma = 0.001
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
CorruptValues = values["Terminal voltage [V]"].data + np.random.normal(
0, sigma, len(t_eval)
)

dataset = [
pybop.Dataset("Time [s]", t_eval),
pybop.Dataset("Current function [A]", values["Current [A]"].data),
pybop.Dataset("Terminal voltage [V]", CorruptValues),
]

# Generate problem, cost function, and optimisation class
problem = pybop.Problem(model, parameters, dataset)
cost = pybop.SumSquaredError(problem)
optim = pybop.Optimisation(cost, optimiser=pybop.IRPropMin)
optim.set_max_iterations(100)

x, final_cost = optim.run()
print("Estimated parameters:", x)

# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
54 changes: 54 additions & 0 deletions examples/scripts/spm_SNES.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pybop
import numpy as np

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

# Fitting parameters
parameters = [
pybop.Parameter(
"Negative electrode active material volume fraction",
prior=pybop.Gaussian(0.7, 0.05),
bounds=[0.6, 0.9],
),
pybop.Parameter(
"Positive electrode active material volume fraction",
prior=pybop.Gaussian(0.58, 0.05),
bounds=[0.5, 0.8],
),
]

sigma = 0.001
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
CorruptValues = values["Terminal voltage [V]"].data + np.random.normal(
0, sigma, len(t_eval)
)

dataset = [
pybop.Dataset("Time [s]", t_eval),
pybop.Dataset("Current function [A]", values["Current [A]"].data),
pybop.Dataset("Terminal voltage [V]", CorruptValues),
]

# Generate problem, cost function, and optimisation class
problem = pybop.Problem(model, parameters, dataset)
cost = pybop.SumSquaredError(problem)
optim = pybop.Optimisation(cost, optimiser=pybop.SNES)
optim.set_max_iterations(100)

x, final_cost = optim.run()
print("Estimated parameters:", x)

# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
54 changes: 54 additions & 0 deletions examples/scripts/spm_XNES.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pybop
import numpy as np

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

# Fitting parameters
parameters = [
pybop.Parameter(
"Negative electrode active material volume fraction",
prior=pybop.Gaussian(0.7, 0.05),
bounds=[0.6, 0.9],
),
pybop.Parameter(
"Positive electrode active material volume fraction",
prior=pybop.Gaussian(0.58, 0.05),
bounds=[0.5, 0.8],
),
]

sigma = 0.001
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
CorruptValues = values["Terminal voltage [V]"].data + np.random.normal(
0, sigma, len(t_eval)
)

dataset = [
pybop.Dataset("Time [s]", t_eval),
pybop.Dataset("Current function [A]", values["Current [A]"].data),
pybop.Dataset("Terminal voltage [V]", CorruptValues),
]

# Generate problem, cost function, and optimisation class
problem = pybop.Problem(model, parameters, dataset)
cost = pybop.SumSquaredError(problem)
optim = pybop.Optimisation(cost, optimiser=pybop.XNES)
optim.set_max_iterations(100)

x, final_cost = optim.run()
print("Estimated parameters:", x)

# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
57 changes: 57 additions & 0 deletions examples/scripts/spm_adam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pybop
import numpy as np

# Parameter set and model definition
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPMe(parameter_set=parameter_set)

# Fitting parameters
parameters = [
pybop.Parameter(
"Negative electrode active material volume fraction",
prior=pybop.Gaussian(0.7, 0.05),
bounds=[0.6, 0.9],
),
pybop.Parameter(
"Positive electrode active material volume fraction",
prior=pybop.Gaussian(0.58, 0.05),
bounds=[0.5, 0.8],
),
]

# Generate data
sigma = 0.001
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
corrupt_values = values["Terminal voltage [V]"].data + np.random.normal(
0, sigma, len(t_eval)
)

# Dataset definition
dataset = [
pybop.Dataset("Time [s]", t_eval),
pybop.Dataset("Current function [A]", values["Current [A]"].data),
pybop.Dataset("Terminal voltage [V]", corrupt_values),
]

# Generate problem, cost function, and optimisation class
problem = pybop.Problem(model, parameters, dataset)
cost = pybop.SumSquaredError(problem)
optim = pybop.Optimisation(cost, optimiser=pybop.Adam)
optim.set_max_iterations(100)

# Run optimisation
x, final_cost = optim.run()
print("Estimated parameters:", x)

# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
24 changes: 11 additions & 13 deletions examples/scripts/spm_descent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Parameter set and model definition
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
Expand Down Expand Up @@ -46,15 +45,14 @@
x, final_cost = optim.run()
print("Estimated parameters:", x)

# Show the generated data
simulated_values = problem.evaluate(x)

plt.figure(dpi=100)
plt.xlabel("Time", fontsize=12)
plt.ylabel("Values", fontsize=12)
plt.plot(t_eval, corrupt_values, label="Measured")
plt.fill_between(t_eval, simulated_values - sigma, simulated_values + sigma, alpha=0.2)
plt.plot(t_eval, simulated_values, label="Simulated")
plt.legend(bbox_to_anchor=(0.6, 1), loc="upper left", fontsize=12)
plt.tick_params(axis="both", labelsize=12)
plt.show()
# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
28 changes: 14 additions & 14 deletions examples/scripts/spm_nlopt.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pybop
import pandas as pd
import matplotlib.pyplot as plt

# Form dataset
Measurements = pd.read_csv("examples/scripts/Chen_example.csv", comment="#").to_numpy()
Expand Down Expand Up @@ -36,18 +35,19 @@
cost = pybop.RootMeanSquaredError(problem)

# Build the optimisation problem
parameterisation = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize)
optim = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize)

# Run the optimisation problem
x, final_cost = parameterisation.run()

# Show the generated data
simulated_values = problem.evaluate(x)

plt.figure()
plt.xlabel("Time")
plt.ylabel("Values")
plt.plot(dataset[0].data, dataset[2].data, label="Measured")
plt.plot(dataset[0].data, simulated_values, label="Simulated")
plt.legend(bbox_to_anchor=(0.6, 1), loc="upper left", fontsize=12)
plt.show()
x, final_cost = optim.run()

# Plot the timeseries output
pybop.quick_plot(x, cost, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the cost landscape
pybop.plot_cost2d(cost, steps=15)

# Plot the cost landscape with optimisation path
pybop.plot_cost2d(cost, optim=optim, steps=15)
Loading

0 comments on commit e0cd5b5

Please sign in to comment.