Skip to content

Commit 43d695d

Browse files
fix: shape predictions correct in presence of controls
1 parent 9a62fa8 commit 43d695d

1 file changed

Lines changed: 20 additions & 7 deletions

File tree

pysindy/_core.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def predict(self, x, u=None):
117117
" not used when the model was fit"
118118
)
119119
u = None
120+
input_shapes = [xi.shape for xi in x]
120121
if u is not None:
121122
u = validate_control_variables(x, u)
122123
x = [np.concatenate((xi, ui), axis=xi.ax_coord) for xi, ui in zip(x, u)]
@@ -125,7 +126,7 @@ def predict(self, x, u=None):
125126
x_feat = [SampleConcatter().fit_transform([xi]) for xi in x_feat]
126127

127128
result = [self.optimizer.predict(xi) for xi in x_feat]
128-
result = [np.reshape(pred, xi.shape) for pred, xi in zip(result, x)]
129+
result = [np.reshape(pred, shp) for pred, shp in zip(result, input_shapes)]
129130

130131
# Kept for backwards compatibility.
131132
if not multiple_trajectories:
@@ -393,22 +394,27 @@ def fit(
393394
_validate_inputs(x, t, x_dot, u)
394395

395396
if x_dot is None:
396-
x, x_dot = self._process_trajectories(x, t, x_dot)
397+
x_smooth, x_dot = self._process_trajectories(x, t, x_dot)
398+
else:
399+
x_smooth = x
397400

398401
if u is None:
399402
self.n_control_features_ = 0
400403
else:
401-
u = validate_control_variables(x, u)
404+
u = validate_control_variables(x_smooth, u)
402405
self.n_control_features_ = cast(int, u[0].n_coord)
403406

404-
x = [np.concatenate((xi, ui), axis=xi.ax_coord) for xi, ui in zip(x, u)]
407+
x_smooth = [
408+
np.concatenate((xi, ui), axis=xi.ax_coord)
409+
for xi, ui in zip(x_smooth, u)
410+
]
405411

406412
self.feature_names_ = feature_names
407413

408414
x_dot = concat_sample_axis(x_dot)
409-
x = self.feature_library.fit_transform(x)
410-
x = SampleConcatter().fit_transform(x)
411-
self.optimizer.fit(x, x_dot)
415+
f_of_x = self.feature_library.fit_transform(x_smooth)
416+
features = SampleConcatter().fit_transform(f_of_x)
417+
self.optimizer.fit(features, x_dot)
412418
self._fit_shape()
413419

414420
return self
@@ -499,6 +505,10 @@ def score(self, x, t, x_dot=None, u=None, metric=r2_score, **metric_kws):
499505

500506
x_dot_predict = self.predict(x, u)
501507

508+
x_dot_predict = [
509+
AxesArray(arr, axes=xi.axes) for arr, xi in zip(x_dot_predict, x)
510+
]
511+
502512
if x_dot is None:
503513
x, x_dot = self._process_trajectories(x, t, x_dot)
504514

@@ -998,6 +1008,9 @@ def score(self, x, t, u=None, x_next=None, metric=r2_score, **metric_kws):
9981008
_validate_inputs(x, t, x_next, u)
9991009

10001010
x_next_predict = self.predict(x, u)
1011+
x_next_predict = [
1012+
AxesArray(arr, axes=xi.axes) for arr, xi in zip(x_next_predict, x)
1013+
]
10011014

10021015
if x_next is None:
10031016
x_next_predict = [xd[:-1] for xd in x_next_predict]

0 commit comments

Comments
 (0)