Unintended behavior of type checking in svd_compute and compute_rank
klapo opened this issue · comments
Describe the bug
For the BOPDMD module (possibly others) when setting svd_rank=0
the resulting proj_basis
is the wrong size. This is caused by the line rank = np.sum(s > tau)
(in both rdmd.compute_rank
and utils.compute_svd
) which returns an numpy.int64
type instead of an int
data type. As a result in the bopdmd.fit()
function, theutils.compute_svd
check for svd_rank >= 1 and isinstance(svd_rank, int)
should be True
but is False
. As a result, compute_svd
falls back to the else statement and returns the length of the time dimension and overriding the optimally computed svd_rank
.
A solution is to change the logical check to: svd_rank >= 1 and isinstance(svd_rank, (int, np.integer))
in both the rdmd.compute_rank
and utils.compute_svd
functions.
To Reproduce
I use the example from Tutorials 2 and 14:
import numpy as np
from pydmd.bopdmd import BOPDMD
import pydmd
x1 = np.linspace(-3, 3, 80)
x2 = np.linspace(-3, 3, 80)
x1grid, x2grid = np.meshgrid(x1, x2)
# Set the random seed for reproducibility
seed = 1
# The noise amplitude matches the noise amplitude in tutorial 2.
sigma = 0.4
time_forecast = np.arange(6 + 0.4, 18 + 0.4, 0.4)
time = np.arange(0, 6 + 0.4, 0.4)
num_time_samples = len(time)
true_eigenvalues = (-.115 - 1j) * np.pi / 2
spatial_modes = 2 / np.cosh(x1grid) / np.cosh(x2grid)
data_clean = spatial_modes[:, :, np.newaxis] * np.exp(true_eigenvalues * time)
snapshots_1d = data_clean.reshape(x1grid.shape[0] * x1grid.shape[1], num_time_samples)
optdmd = BOPDMD(svd_rank=0, use_proj=True)
optdmd.fit(snapshots_1d, time);
print('Actual shape of the projected basis:')
print(optdmd.proj_basis.shape)
print('Expected shape of the projected basis:')
print(pydmd.utils.compute_svd(snapshots_1d, svd_rank=0)[0].shape)
Expected behavior
The shape should have been (6400, 4).
Additional context
I will open a pull request fixing the issue.