GeezerVison is showing github.com — Scalar / Array mismatches in iosys not compatible with NumPy 1.24 · Issue #853 · python-control/python-control
Scalar / Array mismatches in iosys not compatible with NumPy 1.24 #853DescriptionDiscussed in #852
Originally posted by codeFighter2022 January 26, 2023
Hi,
First of all, thanks a lot for this amazing toolbox!
I think, I found a bug, or a suggestion for improvement, when running the prey example:
https://python-control.readthedocs.io/en/0.9.3.post2/iosys.html#example
When I run the code of the prey example, in particular the linearization,
lin_predprey = ct.linearize(io_predprey, xeq, 0)
I get the following error
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.
After analyzing the code, I think the origin of the error is that in predprey_rhs() dH is of type numpy arrary, while dL is not.
I think others ones are much deeper in the code than me. That is why I post this topic instead of a pull request.
Maybe a type check with dummy input/output data already solves these kind of issues when initializing the constructor. I think such a feature could save people some time.
Best,
codeFighter2022
Python: 3.810
Control: 0.9.3.post2
I installed the toolbox via pip
Activitybnavigator commented on Jan 26, 2023 ContributorAuthor More actions When executing the example:
In [4]: eqpt = ct.find_eqpt(io_predprey, X0, 0)
...: xeq = eqpt[0] # choose the nonzero equilibrium point
...: lin_predprey = ct.linearize(io_predprey, xeq, 0)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[4], line 3
1 eqpt = ct.find_eqpt(io_predprey, X0, 0)
2 xeq = eqpt[0] # choose the nonzero equilibrium point
----> 3 lin_predprey = ct.linearize(io_predprey, xeq, 0)
File /usr/lib/python3.10/site-packages/control/iosys.py:2252, in linearize(sys, xeq, ueq, t, params, **kw)
2250 if not isinstance(sys, InputOutputSystem):
2251 raise TypeError("Can only linearize InputOutputSystem types")
-> 2252 return sys.linearize(xeq, ueq, t=t, params=params, **kw)
File /usr/lib/python3.10/site-packages/control/iosys.py:580, in InputOutputSystem.linearize(self, x0, u0, t, params, eps, name, copy_names, **kwargs)
578 du = np.zeros((ninputs,))
579 du[i] = eps
--> 580 B[:, i] = (self._rhs(t, x0, u0 + du) - F0) / eps
581 D[:, i] = (self._out(t, x0, u0 + du) - H0) / eps
583 # Create the state space system
File /usr/lib/python3.10/site-packages/control/iosys.py:866, in NonlinearIOSystem._rhs(self, t, x, u)
863 def _rhs(self, t, x, u):
864 xdot = self.updfcn(t, x, u, self._current_params) \
865 if self.updfcn is not None else []
--> 866 return np.array(xdot).reshape((-1,))
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.changed the title [-]Avoid ragged shapes in linearize()[/-] [+]Avoid ragged shapes in linearize() / iosys[/+] on Jan 26, 2023bnavigator commented on Jan 26, 2023 ContributorAuthor More actions This would fix the error:
def predprey_rhs(t, x, u, params):
# Parameter setup
a = params.get('a', 3.2)
b = params.get('b', 0.6)
c = params.get('c', 50.)
d = params.get('d', 0.56)
k = params.get('k', 125)
r = params.get('r', 1.6)
# Map the states into local variable names
H = x[0]
L = x[1]
# Compute the control action (only allow addition of food)
u_0 = u[0] if u[0] > 0 else 0
# Compute the discrete updates
dH = (r + u_0) * H * (1 - H/k) - (a * H * L)/(c + H)
dL = b * (a * H * L)/(c + H) - d * L
return np.array([dH, dL])
Documentation says, that the update function's u must be an array. As well as the ueq for linearize:
|
def linearize(sys, xeq, ueq=None, t=0, params=None, **kw): |
|
"""Linearize an input/output system at a given state and input. |
|
|
|
This function computes the linearization of an input/output system at a |
|
given state and input value and returns a :class:`~control.StateSpace` |
|
object. The evaluation point need not be an equilibrium point. |
|
|
|
Parameters |
|
---------- |
|
sys : InputOutputSystem |
|
The system to be linearized |
|
xeq : array |
|
The state at which the linearization will be evaluated (does not need |
|
to be an equilibrium state). |
|
ueq : array |
|
The input at which the linearization will be evaluated (does not need |
|
to correspond to an equlibrium state). |
Strictly speaking, the zero us from the example would not be allowed:
eqpt = ct.find_eqpt(io_predprey, X0, 0)
xeq = eqpt[0] # choose the nonzero equilibrium point
lin_predprey = ct.linearize(io_predprey, xeq, 0)
But we have this:
|
# Convert x0, u0 to arrays, if needed |
|
if np.isscalar(x0): |
|
x0 = np.ones((nstates,)) * x0 |
|
if np.isscalar(u0): |
|
u0 = np.ones((ninputs,)) * u0 |
changed the title [-]Avoid ragged shapes in linearize() / iosys[/-] [+]Scalar / Array mismatches in iosys not compatible with NumPy 1.24[/+] on Jan 26, 2023bnavigator commented on Jan 26, 2023 ContributorAuthor More actions The test suite has a different predprey model:
|
def predprey(t, x, u, params={}): |
|
"""Predator prey dynamics""" |
|
r = params.get('r', 2) |
|
d = params.get('d', 0.7) |
|
b = params.get('b', 0.3) |
|
k = params.get('k', 10) |
|
a = params.get('a', 8) |
|
c = params.get('c', 4) |
|
|
|
# Dynamics for the system |
|
dx0 = r * x[0] * (1 - x[0]/k) - a * x[1] * x[0]/(c + x[0]) |
|
dx1 = b * a * x[1] * x[0] / (c + x[0]) - d * x[1] |
|
|
|
return np.array([dx0, dx1]) |
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|