Skip to content

Commit aa106ba

Browse files
committed
remove use_numpy_matrix
1 parent 7d4bb96 commit aa106ba

8 files changed

Lines changed: 43 additions & 156 deletions

File tree

control/config.py

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
__all__ = ['defaults', 'set_defaults', 'reset_defaults',
1616
'use_matlab_defaults', 'use_fbs_defaults',
17-
'use_legacy_defaults', 'use_numpy_matrix']
17+
'use_legacy_defaults']
1818

1919
# Package level default values
2020
_control_defaults = {
@@ -211,7 +211,6 @@ def use_matlab_defaults():
211211
212212
"""
213213
set_defaults('freqplot', dB=True, deg=True, Hz=False, grid=True)
214-
set_defaults('statesp', use_numpy_matrix=True)
215214

216215

217216
# Set defaults to match FBS (Astrom and Murray)
@@ -233,41 +232,6 @@ def use_fbs_defaults():
233232
set_defaults('nyquist', mirror_style='--')
234233

235234

236-
# Decide whether to use numpy.matrix for state space operations
237-
def use_numpy_matrix(flag=True, warn=True):
238-
"""Turn on/off use of Numpy `matrix` class for state space operations.
239-
240-
Parameters
241-
----------
242-
flag : bool
243-
If flag is `True` (default), use the deprecated Numpy
244-
`matrix` class to represent matrices in the `~control.StateSpace`
245-
class and functions. If flat is `False`, then matrices are
246-
represented by a 2D `ndarray` object.
247-
248-
warn : bool
249-
If flag is `True` (default), issue a warning when turning on the use
250-
of the Numpy `matrix` class. Set `warn` to false to omit display of
251-
the warning message.
252-
253-
Notes
254-
-----
255-
Prior to release 0.9.x, the default type for 2D arrays is the Numpy
256-
`matrix` class. Starting in release 0.9.0, the default type for state
257-
space operations is a 2D array.
258-
259-
Examples
260-
--------
261-
>>> ct.use_numpy_matrix(True, False)
262-
>>> # do some legacy calculations using np.matrix
263-
264-
"""
265-
if flag and warn:
266-
warnings.warn("Return type numpy.matrix is deprecated.",
267-
stacklevel=2, category=DeprecationWarning)
268-
set_defaults('statesp', use_numpy_matrix=flag)
269-
270-
271235
def use_legacy_defaults(version):
272236
""" Sets the defaults to whatever they were in a given release.
273237
@@ -331,7 +295,7 @@ def use_legacy_defaults(version):
331295
# Version 0.9.0:
332296
if major == 0 and minor < 9:
333297
# switched to 'array' as default for state space objects
334-
set_defaults('statesp', use_numpy_matrix=True)
298+
warnings.warn("NumPy matrix class no longer supported")
335299

336300
# switched to 0 (=continuous) as default timestep
337301
set_defaults('control', default_dt=None)

control/mateqn.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,9 @@ def lyap(A, Q, C=None, E=None, method=None):
126126
127127
Returns
128128
-------
129-
X : 2D array (or matrix)
129+
X : 2D array
130130
Solution to the Lyapunov or Sylvester equation
131131
132-
Notes
133-
-----
134-
The return type for 2D arrays depends on the default class set for
135-
state space operations. See :func:`~control.use_numpy_matrix`.
136-
137132
"""
138133
# Decide what method to use
139134
method = _slycot_or_scipy(method)
@@ -260,11 +255,6 @@ def dlyap(A, Q, C=None, E=None, method=None):
260255
X : 2D array (or matrix)
261256
Solution to the Lyapunov or Sylvester equation
262257
263-
Notes
264-
-----
265-
The return type for 2D arrays depends on the default class set for
266-
state space operations. See :func:`~control.use_numpy_matrix`.
267-
268258
"""
269259
# Decide what method to use
270260
method = _slycot_or_scipy(method)
@@ -395,11 +385,6 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
395385
G : 2D array (or matrix)
396386
Gain matrix
397387
398-
Notes
399-
-----
400-
The return type for 2D arrays depends on the default class set for
401-
state space operations. See :func:`~control.use_numpy_matrix`.
402-
403388
"""
404389
# Decide what method to use
405390
method = _slycot_or_scipy(method)
@@ -554,11 +539,6 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
554539
G : 2D array (or matrix)
555540
Gain matrix
556541
557-
Notes
558-
-----
559-
The return type for 2D arrays depends on the default class set for
560-
state space operations. See :func:`~control.use_numpy_matrix`.
561-
562542
"""
563543
# Decide what method to use
564544
method = _slycot_or_scipy(method)

control/statefbk.py

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ def place(A, B, p):
110110
The algorithm will not place poles at the same location more
111111
than rank(B) times.
112112
113-
The return type for 2D arrays depends on the default class set for
114-
state space operations. See :func:`~control.use_numpy_matrix`.
115-
116113
References
117114
----------
118115
.. [1] A.L. Tits and Y. Yang, "Globally convergent algorithms for robust
@@ -193,11 +190,6 @@ def place_varga(A, B, p, dtime=False, alpha=None):
193190
[1] Varga A. "A Schur method for pole assignment." IEEE Trans. Automatic
194191
Control, Vol. AC-26, pp. 517-519, 1981.
195192
196-
Notes
197-
-----
198-
The return type for 2D arrays depends on the default class set for
199-
state space operations. See :func:`~control.use_numpy_matrix`.
200-
201193
Examples
202194
--------
203195
>>> A = [[-1, -1], [0, 1]]
@@ -279,10 +271,6 @@ def acker(A, B, poles):
279271
K : 2D array (or matrix)
280272
Gains such that A - B K has given eigenvalues
281273
282-
Notes
283-
-----
284-
The return type for 2D arrays depends on the default class set for
285-
state space operations. See :func:`~control.use_numpy_matrix`.
286274
"""
287275
# Convert the inputs to matrices
288276
a = _ssmatrix(A)
@@ -366,13 +354,10 @@ def lqr(*args, **kwargs):
366354
367355
Notes
368356
-----
369-
1. If the first argument is an LTI object, then this object will be used
370-
to define the dynamics and input matrices. Furthermore, if the LTI
371-
object corresponds to a discrete time system, the ``dlqr()`` function
372-
will be called.
373-
374-
2. The return type for 2D arrays depends on the default class set for
375-
state space operations. See :func:`~control.use_numpy_matrix`.
357+
If the first argument is an LTI object, then this object will be used
358+
to define the dynamics and input matrices. Furthermore, if the LTI
359+
object corresponds to a discrete time system, the ``dlqr()`` function
360+
will be called.
376361
377362
Examples
378363
--------
@@ -514,11 +499,6 @@ def dlqr(*args, **kwargs):
514499
--------
515500
lqr, lqe, dlqe
516501
517-
Notes
518-
-----
519-
The return type for 2D arrays depends on the default class set for
520-
state space operations. See :func:`~control.use_numpy_matrix`.
521-
522502
Examples
523503
--------
524504
>>> K, S, E = dlqr(dsys, Q, R, [N]) # doctest: +SKIP
@@ -971,11 +951,6 @@ def ctrb(A, B):
971951
C : 2D array (or matrix)
972952
Controllability matrix
973953
974-
Notes
975-
-----
976-
The return type for 2D arrays depends on the default class set for
977-
state space operations. See :func:`~control.use_numpy_matrix`.
978-
979954
Examples
980955
--------
981956
>>> G = ct.tf2ss([1], [1, 2, 3])
@@ -1010,11 +985,6 @@ def obsv(A, C):
1010985
O : 2D array (or matrix)
1011986
Observability matrix
1012987
1013-
Notes
1014-
-----
1015-
The return type for 2D arrays depends on the default class set for
1016-
state space operations. See :func:`~control.use_numpy_matrix`.
1017-
1018988
Examples
1019989
--------
1020990
>>> G = ct.tf2ss([1], [1, 2, 3])
@@ -1063,11 +1033,6 @@ def gram(sys, type):
10631033
if slycot routine sb03md cannot be found
10641034
if slycot routine sb03od cannot be found
10651035
1066-
Notes
1067-
-----
1068-
The return type for 2D arrays depends on the default class set for
1069-
state space operations. See :func:`~control.use_numpy_matrix`.
1070-
10711036
Examples
10721037
--------
10731038
>>> G = ct.rss(4)

control/statesp.py

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777

7878
# Define module default parameter values
7979
_statesp_defaults = {
80-
'statesp.use_numpy_matrix': False, # False is default in 0.9.0 and above
8180
'statesp.remove_useless_states': False,
8281
'statesp.latex_num_format': '.3g',
8382
'statesp.latex_repr_type': 'partitioned',
@@ -104,11 +103,8 @@ def _ssmatrix(data, axis=1):
104103
arr : 2D array, with shape (0, 0) if a is empty
105104
106105
"""
107-
# Convert the data into an array or matrix, as configured
108-
if config.defaults['statesp.use_numpy_matrix']:
109-
arr = np.matrix(data, dtype=float)
110-
else:
111-
arr = np.array(data, dtype=float)
106+
# Convert the data into an array
107+
arr = np.array(data, dtype=float)
112108
ndim = arr.ndim
113109
shape = arr.shape
114110

@@ -202,12 +198,7 @@ class StateSpace(LTI):
202198
-----
203199
The main data members in the ``StateSpace`` class are the A, B, C, and D
204200
matrices. The class also keeps track of the number of states (i.e.,
205-
the size of A). The data format used to store state space matrices is
206-
set using the value of `config.defaults['use_numpy_matrix']`. If True
207-
(default), the state space elements are stored as `numpy.matrix` objects;
208-
otherwise they are `numpy.ndarray` objects. The
209-
:func:`~control.use_numpy_matrix` function can be used to set the storage
210-
type.
201+
the size of A).
211202
212203
A discrete time system is created by specifying a nonzero 'timebase', dt
213204
when the system is constructed:
@@ -355,10 +346,8 @@ def __init__(self, *args, init_namedio=True, **kwargs):
355346
elif kwargs:
356347
raise TypeError("unrecognized keyword(s): ", str(kwargs))
357348

358-
# Reset shapes (may not be needed once np.matrix support is removed)
349+
# Reset shape if system is static
359350
if self._isstatic():
360-
# static gain
361-
# matrix's default "empty" shape is 1x0
362351
A.shape = (0, 0)
363352
B.shape = (0, self.ninputs)
364353
C.shape = (self.noutputs, 0)
@@ -927,18 +916,17 @@ def horner(self, x, warn_infinite=True):
927916
x_arr = np.atleast_1d(x).astype(complex, copy=False)
928917

929918
# return fast on systems with 0 or 1 state
930-
if not config.defaults['statesp.use_numpy_matrix']:
931-
if self.nstates == 0:
932-
return self.D[:, :, np.newaxis] \
933-
* np.ones_like(x_arr, dtype=complex)
934-
if self.nstates == 1:
935-
with np.errstate(divide='ignore', invalid='ignore'):
936-
out = self.C[:, :, np.newaxis] \
937-
/ (x_arr - self.A[0, 0]) \
938-
* self.B[:, :, np.newaxis] \
939-
+ self.D[:, :, np.newaxis]
940-
out[np.isnan(out)] = complex(np.inf, np.nan)
941-
return out
919+
if self.nstates == 0:
920+
return self.D[:, :, np.newaxis] \
921+
* np.ones_like(x_arr, dtype=complex)
922+
elif self.nstates == 1:
923+
with np.errstate(divide='ignore', invalid='ignore'):
924+
out = self.C[:, :, np.newaxis] \
925+
/ (x_arr - self.A[0, 0]) \
926+
* self.B[:, :, np.newaxis] \
927+
+ self.D[:, :, np.newaxis]
928+
out[np.isnan(out)] = complex(np.inf, np.nan)
929+
return out
942930

943931
try:
944932
out = self.slycot_laub(x_arr)

control/stochsys.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,10 @@ def lqe(*args, **kwargs):
101101
102102
Notes
103103
-----
104-
1. If the first argument is an LTI object, then this object will be used
105-
to define the dynamics, noise and output matrices. Furthermore, if
106-
the LTI object corresponds to a discrete time system, the ``dlqe()``
107-
function will be called.
108-
109-
2. The return type for 2D arrays depends on the default class set for
110-
state space operations. See :func:`~control.use_numpy_matrix`.
104+
If the first argument is an LTI object, then this object will be used
105+
to define the dynamics, noise and output matrices. Furthermore, if the
106+
LTI object corresponds to a discrete time system, the ``dlqe()``
107+
function will be called.
111108
112109
Examples
113110
--------
@@ -236,11 +233,6 @@ def dlqe(*args, **kwargs):
236233
E : 1D array
237234
Eigenvalues of estimator poles eig(A - L C)
238235
239-
Notes
240-
-----
241-
The return type for 2D arrays depends on the default class set for
242-
state space operations. See :func:`~control.use_numpy_matrix`.
243-
244236
Examples
245237
--------
246238
>>> L, P, E = dlqe(A, G, C, QN, RN) # doctest: +SKIP

control/tests/config_test.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,13 @@ def test_reset_defaults(self):
242242
assert ct.config.defaults['freqplot.feature_periphery_decades'] == 1.0
243243

244244
def test_legacy_defaults(self):
245-
with pytest.deprecated_call():
245+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
246246
ct.use_legacy_defaults('0.8.3')
247-
assert(isinstance(ct.ss(0, 0, 0, 1).D, np.matrix))
248-
ct.reset_defaults()
249-
assert isinstance(ct.ss(0, 0, 0, 1).D, np.ndarray)
250-
assert not isinstance(ct.ss(0, 0, 0, 1).D, np.matrix)
247+
ct.reset_defaults()
251248

252-
ct.use_legacy_defaults('0.8.4')
253-
assert ct.config.defaults['forced_response.return_x'] is True
249+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
250+
ct.use_legacy_defaults('0.8.4')
251+
assert ct.config.defaults['forced_response.return_x'] is True
254252

255253
ct.use_legacy_defaults('0.9.0')
256254
assert isinstance(ct.ss(0, 0, 0, 1).D, np.ndarray)

control/tests/iosys_test.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,10 @@ def test_linearize_named_signals(self, kincar):
252252
assert linearized_newnames.find_output('y') is None
253253

254254
# Test legacy version as well
255-
ct.use_legacy_defaults('0.8.4')
256-
ct.config.use_numpy_matrix(False) # np.matrix deprecated
257-
linearized = kincar.linearize([0, 0, 0], [0, 0], copy_names=True)
258-
assert linearized.name == kincar.name + '_linearized'
255+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
256+
ct.use_legacy_defaults('0.8.4')
257+
linearized = kincar.linearize([0, 0, 0], [0, 0], copy_names=True)
258+
assert linearized.name == kincar.name + '_linearized'
259259

260260
def test_connect(self, tsys):
261261
# Define a couple of (linear) systems to interconnection
@@ -1059,8 +1059,8 @@ def test_sys_naming_convention(self, tsys):
10591059
"""Enforce generic system names 'sys[i]' to be present when systems are
10601060
created without explicit names."""
10611061

1062-
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
1063-
ct.config.use_numpy_matrix(False) # np.matrix deprecated
1062+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
1063+
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
10641064

10651065
# Create a system with a known ID
10661066
ct.namedio.NamedIOSystem._idCounter = 0
@@ -1127,8 +1127,8 @@ def test_signals_naming_convention_0_8_4(self, tsys):
11271127
output: 'y[i]'
11281128
"""
11291129

1130-
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
1131-
ct.config.use_numpy_matrix(False) # np.matrix deprecated
1130+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
1131+
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
11321132

11331133
# Create a system with a known ID
11341134
ct.namedio.NamedIOSystem._idCounter = 0
@@ -1433,8 +1433,8 @@ def test_duplicates(self, tsys):
14331433
ios_series = nlios * nlios
14341434

14351435
# Nonduplicate objects
1436-
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
1437-
ct.config.use_numpy_matrix(False) # np.matrix deprecated
1436+
with pytest.warns(UserWarning, match="NumPy matrix class no longer"):
1437+
ct.config.use_legacy_defaults('0.8.4') # changed delims in 0.9.0
14381438
nlios1 = nlios.copy()
14391439
nlios2 = nlios.copy()
14401440
with pytest.warns(UserWarning, match="duplicate name"):

0 commit comments

Comments
 (0)