Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates for numpy 2 compatibility #372

Merged
merged 4 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading