dynamicslab / pysindy

A package for the sparse identification of nonlinear dynamical systems from data
https://pysindy.readthedocs.io/en/latest/
Other
1.42k stars 310 forks source link

[BUG] Generalized library in `1_feature_overview/example.ipynb` #403

Closed georgemilosh closed 1 year ago

georgemilosh commented 1 year ago

The issue with running the notebook ./pysindy/examples/1_feature_overview/example.ipynb when trying Generlized library

Reproducing code example:

import warnings
from contextlib import contextmanager
from copy import copy
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import solve_ivp
from scipy.linalg import LinAlgWarning
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import Lasso

import pysindy as ps
from pysindy.utils import enzyme
from pysindy.utils import lorenz
from pysindy.utils import lorenz_control

if __name__ != "testing":
    t_end_train = 10
    t_end_test = 15
else:
    t_end_train = 0.04
    t_end_test = 0.04

data = (Path() / "../data").resolve()

@contextmanager
def ignore_specific_warnings():
    filters = copy(warnings.filters)
    warnings.filterwarnings("ignore", category=ConvergenceWarning)
    warnings.filterwarnings("ignore", category=LinAlgWarning)
    warnings.filterwarnings("ignore", category=UserWarning)
    yield
    warnings.filters = filters

if __name__ == "testing":
    import sys
    import os

    sys.stdout = open(os.devnull, "w")
# %%
# Seed the random number generators for reproducibility
np.random.seed(100)

integrator_keywords = {}
integrator_keywords["rtol"] = 1e-12
integrator_keywords["method"] = "LSODA"
integrator_keywords["atol"] = 1e-12

dt = 0.002

t_train = np.arange(0, t_end_train, dt)
x0_train = [-8, 8, 27]
t_train_span = (t_train[0], t_train[-1])
x_train = solve_ivp(
    lorenz, t_train_span, x0_train, t_eval=t_train, **integrator_keywords
).y.T

# %% [markdown]
# ### Multiple trajectories
# We use the Lorenz equations to evolve multiple different initial conditions forward in time, passing all the trajectories into a single `SINDy` object. Note that `x_train_multi` is a list of 2D numpy arrays.

# %%
# Initialize two libraries
poly_library = ps.PolynomialLibrary(include_bias=False)
fourier_library = ps.FourierLibrary()

# Initialize the default inputs, but
# don't use the x0 input for generating the Fourier library
inputs_per_library = [(0, 1, 2), (1, 2)]

# Tensor all the polynomial and Fourier library terms together
tensor_array = [[1, 1]]

# Initialize this generalized library, all the work hidden from the user!
generalized_library = ps.GeneralizedLibrary(
    [poly_library, fourier_library],
    tensor_array=tensor_array,
    exclude_libraries=[1],
    inputs_per_library=inputs_per_library,
)

# Fit the model and print the library feature names to check success
model = ps.SINDy(feature_library=generalized_library, feature_names=feature_names)
model.fit(x_train, t=dt)
model.print()
print("Feature names:\n", model.get_feature_names())

Error message:

Traceback (most recent call last):
  File "/net/nfs/ssd1/gmiloshe/pysindy/examples/1_feature_overview/test.py", line 79, in <module>
    generalized_library = ps.GeneralizedLibrary(
  File "/net/nfs/ssd1/miniconda3/envs/pysindy-dev/lib/python3.10/site-packages/pysindy/feature_library/generalized_library.py", line 124, in __init__
    if inputs_per_library.ndim != 2:
AttributeError: 'list' object has no attribute 'ndim'

PySINDy/Python version information:

1.7.5 3.10.12 | packaged by conda-forge | (main, Jun 23 2023, 22:40:32) [GCC 12.3.0]

Jacob-Stevens-Haas commented 1 year ago

Same as #402. For 1.7.5 documentation, see the stable readthedocs or the docstrings from the package you have installed.

The inputs_per_library argument was changed in #362 as was discussed in #306.

Also, FWIW, if you want to browse the repo at an older point, you can click on "releases" on the right hand side of the main pysindy github page. This will have the examples as they existed during that release cycle.