-
Notifications
You must be signed in to change notification settings - Fork 438
Prepare for removal of dependency on numpy.matrix class #292
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
Conversation
One overall comment: If control functions, methods, and attributes now return numpy arrays instead of numpy matrices, this change could break lots of code in the wild. If a user gets these matrix outputs and then operates on them with operations that assume a matrix type (e.g. overloaded |
Co-Authored-By: murrayrm <murray@cds.caltech.edu>
@moorepants Good point. Most of these changes are internal and so shouldn't affect any user outputs. But I'll go through and check to see whether the output of any function actually changed pre/post PR. The only think that might have changed are some of the functions that return matrices (eg, Gramians). Note also that the |
I checked through the code. Most functions that return matrices were already returning ndarrays (typically via a call to
Thoughts on the best approach to handling this? We could:
We could also allow a |
Updated the code so that all functions that used to return an ndarray of subtype Once we are OK with the code changing (perhaps in the next major or minor release), we can change the code to return |
Merged changes from current version of master (including implementing updated @billtubbs FYI. Perhaps worth waiting until this PR is merged before making any more changes to |
StateSpaceMatrix should probably have an Putting The code for turning Matlab-style matrix strings into nd.arrays is in numpy.matrixlib.defmatrix._convert_from_string -- it's not all that long or complicated, one could copy it if necessary. Less importantly, if we didn't have to support Python 2.7 this refactoring could have used |
Thanks for the comments @roryyorke. Responses (no actions yet):
|
np.matrix inherits most numeric dunder methods from np.ndarray, except prefixes = ['','r','i']
bases = ['add','sub','mul','matmul','truediv','floordiv','mod','divmod','pow','lshift','rshift','and','or','xor']
makemeth = lambda p, b: '__' + p + b + '__'
# there's no such thing as __idivmod__; otherwise all exist
methods = [makemeth(p,b) for p,b in itertools.product(prefixes, bases) if hasattr(np.ndarray, makemeth(p,b))]
matonly = [m for m in methods if getattr(np.matrix, m) is not getattr(np.ndarray, m)]
print(matonly)
# output: ['__mul__', '__pow__', '__rmul__', '__rpow__', '__imul__', '__ipow__'] |
Committed a new set of changes to address the issues raised by @roryyorke. Most recent updates:
In a future release, we can change the defaults in I decided not to copy the string processing code from |
In looking through the code just now, I see what we have some inconsistencies in how we return matrix objects. In some place we are returning On the one hand, it seems useful to have functions that return a gain matrix sending back something that can be used like the
(note that this won't actually work in the current code, tthough if you used On the other hand, at some point we should probably just bite the bullet and use Any thoughts? |
Will this work?
Using |
Yes, that will work (though not in python 2.7, of course). |
This PR prepares for removal the dependency of the control package on the
numpy.matrix
class, which is planned for deprecation at some point in the future. To handle this, a number of changes have been made:A new
StateSpaceMatrix
class, derived fromnumpy.ndarray
, was created that is used to store the A, B, C, D matrices for aStateSpace
system. This class maintains elements as a 2D matrix, soB[:,1]
returns a column matrix (shape = (n, 1)). As anndarray
, this expression would normally return a 1D array. TheStateSpaceMatrix
class also overrides the*
and^
operators to give matrix multiplication and matrix powers (same asnumpy.matlab
does). This gives better compatibility with (user) code that was using those constructs to operate directly on matrices associated with a system. A new unit test file for the class is also included. There is also a functionssmatrix()
that can be used to create aStateSpaceMatrix
object (similar to the use ofnumpy.array
to create annumpy.ndarray
object).Functions that used to return
numpy.matrix
objects now return a user-configurable type, set using theuse_numpy_matrix
orset_ss_matrix_type
functions. By default the return type is currentlynumpy.matrix
(for backward compatibility), but callinguse_numpy_matrix(False)
changes the return type toStateSpaceMatrix
. Usingset_ss_matrix_type
, it is possible to use other subclasses derived fromnumpy.ndarray
(includingndarray
itself). AUserWarning
is issued whenevernumpy.matrix
is set or used as the output type.The code in the package as been updated to remove unneeded dependencies on the
numpy.matrix
class. This mainly involved changingnumpy.matrix
tonumpy.array
, but in some cases some additional changes were needed because of the differences between matrices and numpy. With the exception of extracting elements of submatrices, the main package code does not explicitly use the functionality of theStateSpaceMatrix
class, so the main use of this class is to provide some backward compatibility for user code that users*
and^
operators (which is fairly common in my own code).All unit test code (in
control/tests
) has been scrubbed of unnecessary dependence on thenumpy.matrix
class (except for testing that warning messages are generated and a few other checks for backward compatibility).I did some PEP8 cleaning on
statesp.py
since there were lots of changes in this file already.The changes were tested with the old unit test files, the new unit test files, and all examples and everything continues to work across all of those variants.
Net impact of this PR is that all
numpy.matrix
deprecation warnings can be removed by callinguse_numpy_matrix(False)
, addressing issue #233. This behavior can be made the default in a future release or whennumpy.matrix
goes away.There are two situations in which the
numpy.matrix
deprecation warning can still appear:For backward compatibility, I set things up so that if you pass the
StateSpaceMatrix
constructor a string then it will callnumpy.matrix
. This allows all old examples to work without change (but does generate a warning message).It's possible that if a user creates a
numpy.matrix
object to one of the python-control functions that it could end up generating a copy and that could trigger a warning message. I figure that is the user's fault -:).(Note: this description was updated on 8 Jun 2019 to reflect the changes made in response to comments and responses below.)