Skip to content

Commit

Permalink
Merge pull request #372 from pybop-team/367-numpy-updates
Browse files Browse the repository at this point in the history
Updates for numpy 2 compatibility
  • Loading branch information
BradyPlanden committed Jun 24, 2024
2 parents 71f3e43 + e637110 commit 4fe242c
Show file tree
Hide file tree
Showing 21 changed files with 40 additions and 38 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

## Bug Fixes


- [#372](https://github.com/pybop-team/PyBOP/pull/372) - Converts `np.array` to `np.asarray` for Numpy v2.0 support.
- [#165](https://github.com/pybop-team/PyBOP/issues/165) - Stores the attempted and best parameter values and the best cost for each iteration in the log attribute of the optimiser and updates the associated plots.
- [#354](https://github.com/pybop-team/PyBOP/issues/354) - Fixes the calculation of the gradient in the `RootMeanSquaredError` cost.
- [#347](https://github.com/pybop-team/PyBOP/issues/347) - Resets options between MSMR tests to cope with a bug in PyBaMM v23.9 which is fixed in PyBaMM v24.1.
Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/multi_model_identification.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3958,7 +3958,7 @@
}
],
"source": [
"bounds = np.array([[5.5e-05, 8e-05], [7.5e-05, 9e-05]])\n",
"bounds = np.asarray([[5.5e-05, 8e-05], [7.5e-05, 9e-05]])\n",
"for optim in optims:\n",
" pybop.plot2d(optim, bounds=bounds, steps=10, title=optim.cost.problem.model.name)"
]
Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/multi_optimiser_identification.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@
],
"source": [
"# Plot the cost landscape with optimisation path and updated bounds\n",
"bounds = np.array([[0.5, 0.8], [0.55, 0.8]])\n",
"bounds = np.asarray([[0.5, 0.8], [0.55, 0.8]])\n",
"for optim in optims:\n",
" pybop.plot2d(optim, bounds=bounds, steps=10, title=optim.name())"
]
Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/optimiser_calibration.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@
],
"source": [
"# Plot the cost landscape with optimisation path and updated bounds\n",
"bounds = np.array([[0.6, 0.9], [0.5, 0.8]])\n",
"bounds = np.asarray([[0.6, 0.9], [0.5, 0.8]])\n",
"for optim, sigma in zip(optims, sigmas):\n",
" pybop.plot2d(optim, bounds=bounds, steps=10, title=f\"Sigma: {sigma}\")"
]
Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/spm_AdamW.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@
"# Plot the cost landscape\n",
"pybop.plot2d(cost, steps=15)\n",
"# Plot the cost landscape with optimisation path and updated bounds\n",
"bounds = np.array([[0.6, 0.9], [0.5, 0.8]])\n",
"bounds = np.asarray([[0.6, 0.9], [0.5, 0.8]])\n",
"pybop.plot2d(optim, bounds=bounds, steps=15);"
]
},
Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/ecm_CMAES.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,5 @@
pybop.plot2d(cost, steps=15)

# Plot the cost landscape with optimisation path and updated bounds
bounds = np.array([[1e-4, 1e-2], [1e-5, 1e-2]])
bounds = np.asarray([[1e-4, 1e-2], [1e-5, 1e-2]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_AdamW.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ def noise(sigma):
pybop.plot_parameters(optim)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.5, 0.8], [0.4, 0.7]])
bounds = np.asarray([[0.5, 0.8], [0.4, 0.7]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_IRPropMin.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
pybop.plot_parameters(optim)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.5, 0.8], [0.4, 0.7]])
bounds = np.asarray([[0.5, 0.8], [0.4, 0.7]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_MAP.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@
pybop.plot2d(cost, steps=15)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.55, 0.77], [0.48, 0.68]])
bounds = np.asarray([[0.55, 0.77], [0.48, 0.68]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_MLE.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@
pybop.plot2d(likelihood, steps=15)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.55, 0.77], [0.48, 0.68]])
bounds = np.asarray([[0.55, 0.77], [0.48, 0.68]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_NelderMead.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ def noise(sigma):
pybop.plot_parameters(optim)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.5, 0.8], [0.4, 0.7]])
bounds = np.asarray([[0.5, 0.8], [0.4, 0.7]])
pybop.plot2d(optim, bounds=bounds, steps=15)
2 changes: 1 addition & 1 deletion examples/scripts/spm_descent.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@
pybop.plot_parameters(optim)

# Plot the cost landscape with optimisation path
bounds = np.array([[0.5, 0.8], [0.4, 0.7]])
bounds = np.asarray([[0.5, 0.8], [0.4, 0.7]])
pybop.plot2d(optim, bounds=bounds, steps=15)
10 changes: 5 additions & 5 deletions pybop/costs/_likelihoods.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def set_sigma(self, sigma):
)

if not isinstance(sigma, np.ndarray):
sigma = np.array(sigma)
sigma = np.asarray(sigma)

if not np.issubdtype(sigma.dtype, np.number):
raise ValueError("Sigma must contain only numeric values")
Expand All @@ -74,7 +74,7 @@ def _evaluate(self, x, grad=None):
if len(y.get(key, [])) != len(self._target.get(key, [])):
return -np.float64(np.inf) # prediction doesn't match target

e = np.array(
e = np.asarray(
[
np.sum(
self._offset
Expand Down Expand Up @@ -102,7 +102,7 @@ def _evaluateS1(self, x, grad=None):
dl = self._dl * np.ones(self.n_parameters)
return -likelihood, -dl

r = np.array([self._target[signal] - y[signal] for signal in self.signal])
r = np.asarray([self._target[signal] - y[signal] for signal in self.signal])
likelihood = self._evaluate(x)
dl = np.sum((self.sigma2 * np.sum((r * dy.T), axis=2)), axis=1)
return likelihood, dl
Expand Down Expand Up @@ -148,7 +148,7 @@ def _evaluate(self, x, grad=None):
if len(y.get(key, [])) != len(self._target.get(key, [])):
return -np.float64(np.inf) # prediction doesn't match target

e = np.array(
e = np.asarray(
[
np.sum(
self._logpi
Expand Down Expand Up @@ -181,7 +181,7 @@ def _evaluateS1(self, x, grad=None):
dl = self._dl * np.ones(self.n_parameters)
return -likelihood, -dl

r = np.array([self._target[signal] - y[signal] for signal in self.signal])
r = np.asarray([self._target[signal] - y[signal] for signal in self.signal])
likelihood = self._evaluate(x)
dl = sigma ** (-2.0) * np.sum((r * dy.T), axis=2)
dsigma = -self.n_time_data / sigma + sigma**-(3.0) * np.sum(r**2, axis=1)
Expand Down
8 changes: 4 additions & 4 deletions pybop/costs/fitting_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _evaluate(self, x, grad=None):
if len(prediction.get(key, [])) != len(self._target.get(key, [])):
return np.float64(np.inf) # prediction doesn't match target

e = np.array(
e = np.asarray(
[
np.sqrt(np.mean((prediction[signal] - self._target[signal]) ** 2))
for signal in self.signal
Expand Down Expand Up @@ -87,7 +87,7 @@ def _evaluateS1(self, x):
de = self._de * np.ones(self.n_parameters)
return e, de

r = np.array([y[signal] - self._target[signal] for signal in self.signal])
r = np.asarray([y[signal] - self._target[signal] for signal in self.signal])
e = np.sqrt(np.mean(r**2, axis=1))
de = np.mean((r * dy.T), axis=2) / (e + np.finfo(float).eps)

Expand Down Expand Up @@ -159,7 +159,7 @@ def _evaluate(self, x, grad=None):
if len(prediction.get(key, [])) != len(self._target.get(key, [])):
return np.float64(np.inf) # prediction doesn't match target

e = np.array(
e = np.asarray(
[
np.sum(((prediction[signal] - self._target[signal]) ** 2))
for signal in self.signal
Expand Down Expand Up @@ -197,7 +197,7 @@ def _evaluateS1(self, x):
de = self._de * np.ones(self.n_parameters)
return e, de

r = np.array([y[signal] - self._target[signal] for signal in self.signal])
r = np.asarray([y[signal] - self._target[signal] for signal in self.signal])
e = np.sum(np.sum(r**2, axis=0), axis=0)
de = 2 * np.sum(np.sum((r * dy.T), axis=2), axis=1)

Expand Down
4 changes: 2 additions & 2 deletions pybop/models/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def reinit(
if x is None:
x = self._built_model.y0

sol = pybamm.Solution([np.array([t])], [x], self._built_model, inputs)
sol = pybamm.Solution([np.asarray([t])], [x], self._built_model, inputs)

return TimeSeriesState(sol=sol, inputs=inputs, t=t)

Expand All @@ -303,7 +303,7 @@ def get_state(self, inputs: Inputs, t: float, x: np.ndarray) -> TimeSeriesState:
if self._built_model is None:
raise ValueError("Model must be built before calling get_state")

sol = pybamm.Solution([np.array([t])], [x], self._built_model, inputs)
sol = pybamm.Solution([np.asarray([t])], [x], self._built_model, inputs)

return TimeSeriesState(sol=sol, inputs=inputs, t=t)

Expand Down
2 changes: 1 addition & 1 deletion pybop/observers/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def get_current_covariance(self) -> Covariance:

def get_measure(self, x: TimeSeriesState) -> np.ndarray:
measures = [x.sol[s].data[-1] for s in self._signal]
return np.array([[m] for m in measures])
return np.asarray([[m] for m in measures])

def get_current_time(self) -> float:
"""
Expand Down
8 changes: 4 additions & 4 deletions pybop/observers/unscented_kalman.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def observe(self, time: float, value: np.ndarray) -> float:
if value is None:
raise ValueError("Measurement must be provided.")
elif isinstance(value, np.floating):
value = np.array([value])
value = np.asarray([value])

dt = time - self.get_current_time()
if dt < 0:
Expand Down Expand Up @@ -201,7 +201,7 @@ def __init__(
zero_cols = np.logical_and(np.all(P0 == 0, axis=1), np.all(Rp == 0, axis=1))
zeros = np.logical_and(zero_rows, zero_cols)
ones = np.logical_not(zeros)
states = np.array(range(len(x0)))[ones]
states = np.asarray(range(len(x0)))[ones]
bool_mask = np.ix_(ones, ones)

S_filtered = linalg.cholesky(P0[ones, :][:, ones])
Expand Down Expand Up @@ -276,11 +276,11 @@ def gen_sigma_points(

# Define the weights of the sigma points
w_m0 = sigma / (L + sigma)
w_m = np.array([w_m0] + [1 / (2 * (L + sigma))] * (2 * L))
w_m = np.asarray([w_m0] + [1 / (2 * (L + sigma))] * (2 * L))

# Define the weights of the covariance of the sigma points
w_c0 = w_m0 + (1 - alpha**2 + beta)
w_c = np.array([w_c0] + [1 / (2 * (L + sigma))] * (2 * L))
w_c = np.asarray([w_c0] + [1 / (2 * (L + sigma))] * (2 * L))

return (points, w_m, w_c)

Expand Down
12 changes: 7 additions & 5 deletions pybop/plotting/plot2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,19 @@ def plot2d(
# Populate cost matrix
for i, xi in enumerate(x):
for j, yj in enumerate(y):
costs[j, i] = cost(np.array([xi, yj]))
costs[j, i] = cost(np.asarray([xi, yj]))

if gradient:
grad_parameter_costs = []

# Determine the number of gradient outputs from cost.evaluateS1
num_gradients = len(cost.evaluateS1(np.array([x[0], y[0]]))[1])
num_gradients = len(cost.evaluateS1(np.asarray([x[0], y[0]]))[1])

# Create an array to hold each gradient output & populate
grads = [np.zeros((len(y), len(x))) for _ in range(num_gradients)]
for i, xi in enumerate(x):
for j, yj in enumerate(y):
(*current_grads,) = cost.evaluateS1(np.array([xi, yj]))[1]
(*current_grads,) = cost.evaluateS1(np.asarray([xi, yj]))[1]
for k, grad_output in enumerate(current_grads):
grads[k][j, i] = grad_output

Expand All @@ -103,7 +103,7 @@ def plot2d(
flat_costs = costs.flatten()

# Append the optimisation trace to the data
parameter_log = np.array(optim.log["x_best"])
parameter_log = np.asarray(optim.log["x_best"])
flat_x = np.concatenate((flat_x, parameter_log[:, 0]))
flat_y = np.concatenate((flat_y, parameter_log[:, 1]))
flat_costs = np.concatenate((flat_costs, optim.log["cost"]))
Expand Down Expand Up @@ -140,7 +140,9 @@ def plot2d(

if plot_optim:
# Plot the optimisation trace
optim_trace = np.array([item for sublist in optim.log["x"] for item in sublist])
optim_trace = np.asarray(
[item for sublist in optim.log["x"] for item in sublist]
)
optim_trace = optim_trace.reshape(-1, 2)
fig.add_trace(
go.Scatter(
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_optimisation_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TestOptimisation:

@pytest.fixture(autouse=True)
def setup(self):
self.ground_truth = np.array([0.55, 0.55]) + np.random.normal(
self.ground_truth = np.asarray([0.55, 0.55]) + np.random.normal(
loc=0.0, scale=0.05, size=2
)

Expand Down
6 changes: 3 additions & 3 deletions tests/integration/test_spm_parameterisations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Test_SPM_Parameterisation:

@pytest.fixture(autouse=True)
def setup(self):
self.ground_truth = np.array([0.55, 0.55]) + np.random.normal(
self.ground_truth = np.asarray([0.55, 0.55]) + np.random.normal(
loc=0.0, scale=0.05, size=2
)

Expand Down Expand Up @@ -160,7 +160,7 @@ def spm_two_signal_cost(self, parameters, model, cost_class):
[
pybop.SciPyDifferentialEvolution,
pybop.IRPropMin,
pybop.CMAES,
pybop.XNES,
],
)
@pytest.mark.integration
Expand Down Expand Up @@ -218,7 +218,7 @@ def test_model_misparameterisation(self, parameters, model, init_soc):
cost = pybop.RootMeanSquaredError(problem)

# Select optimiser
optimiser = pybop.CMAES
optimiser = pybop.XNES

# Build the optimisation problem
optim = optimiser(cost=cost)
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_thevenin_parameterisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TestTheveninParameterisation:

@pytest.fixture(autouse=True)
def setup(self):
self.ground_truth = np.array([0.05, 0.05]) + np.random.normal(
self.ground_truth = np.asarray([0.05, 0.05]) + np.random.normal(
loc=0.0, scale=0.01, size=2
)

Expand Down

0 comments on commit 4fe242c

Please sign in to comment.