Skip to content

Commit ce77e6b

Browse files
committed
clean up terminology and checks for "static" systems
1 parent 8cdc09a commit ce77e6b

File tree

5 files changed

+40
-26
lines changed

5 files changed

+40
-26
lines changed

control/iosys.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,6 @@ def issiso(self):
757757
"""Check to see if a system is single input, single output."""
758758
return self.ninputs == 1 and self.noutputs == 1
759759

760-
def _isstatic(self):
761-
"""Check to see if a system is a static system (no states)"""
762-
return self.nstates == 0
763-
764760

765761
# Test to see if a system is SISO
766762
def issiso(sys, strict=False):

control/nlsys.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def __call__(sys, u, params=None, squeeze=None):
181181
182182
"""
183183
# Make sure the call makes sense
184-
if not sys._isstatic():
184+
if sys.nstates != 0:
185185
raise TypeError(
186186
"function evaluation is only supported for static "
187187
"input/output systems")
@@ -199,7 +199,7 @@ def __call__(sys, u, params=None, squeeze=None):
199199
def __mul__(self, other):
200200
"""Multiply two input/output systems (series interconnection)"""
201201
# Convert 'other' to an I/O system if needed
202-
other = _convert_static_iosystem(other)
202+
other = _convert_to_iosystem(other)
203203
if not isinstance(other, InputOutputSystem):
204204
return NotImplemented
205205

@@ -231,7 +231,7 @@ def __mul__(self, other):
231231
def __rmul__(self, other):
232232
"""Pre-multiply an input/output systems by a scalar/matrix"""
233233
# Convert other to an I/O system if needed
234-
other = _convert_static_iosystem(other)
234+
other = _convert_to_iosystem(other)
235235
if not isinstance(other, InputOutputSystem):
236236
return NotImplemented
237237

@@ -263,7 +263,7 @@ def __rmul__(self, other):
263263
def __add__(self, other):
264264
"""Add two input/output systems (parallel interconnection)"""
265265
# Convert other to an I/O system if needed
266-
other = _convert_static_iosystem(other)
266+
other = _convert_to_iosystem(other)
267267
if not isinstance(other, InputOutputSystem):
268268
return NotImplemented
269269

@@ -284,7 +284,7 @@ def __add__(self, other):
284284
def __radd__(self, other):
285285
"""Parallel addition of input/output system to a compatible object."""
286286
# Convert other to an I/O system if needed
287-
other = _convert_static_iosystem(other)
287+
other = _convert_to_iosystem(other)
288288
if not isinstance(other, InputOutputSystem):
289289
return NotImplemented
290290

@@ -305,7 +305,7 @@ def __radd__(self, other):
305305
def __sub__(self, other):
306306
"""Subtract two input/output systems (parallel interconnection)"""
307307
# Convert other to an I/O system if needed
308-
other = _convert_static_iosystem(other)
308+
other = _convert_to_iosystem(other)
309309
if not isinstance(other, InputOutputSystem):
310310
return NotImplemented
311311

@@ -329,7 +329,7 @@ def __sub__(self, other):
329329
def __rsub__(self, other):
330330
"""Parallel subtraction of I/O system to a compatible object."""
331331
# Convert other to an I/O system if needed
332-
other = _convert_static_iosystem(other)
332+
other = _convert_to_iosystem(other)
333333
if not isinstance(other, InputOutputSystem):
334334
return NotImplemented
335335
return other - self
@@ -355,6 +355,10 @@ def __truediv__(self, other):
355355
else:
356356
return NotImplemented
357357

358+
# Determine if a system is static (memoryless)
359+
def _isstatic(self):
360+
return self.nstates == 0
361+
358362
def _update_params(self, params):
359363
# Update the current parameter values
360364
self._current_params = self.params.copy()
@@ -484,7 +488,7 @@ def feedback(self, other=1, sign=-1, params=None):
484488
485489
"""
486490
# Convert sys2 to an I/O system if needed
487-
other = _convert_static_iosystem(other)
491+
other = _convert_to_iosystem(other)
488492

489493
# Make sure systems can be interconnected
490494
if self.noutputs != other.ninputs or other.noutputs != self.ninputs:
@@ -932,6 +936,7 @@ def _out(self, t, x, u):
932936
# Make the full set of subsystem outputs to system output
933937
return self.output_map @ ylist
934938

939+
# Find steady state (static) inputs and outputs
935940
def _compute_static_io(self, t, x, u):
936941
# Figure out the total number of inputs and outputs
937942
(ninputs, noutputs) = self.connect_map.shape
@@ -1711,8 +1716,8 @@ def ufun(t):
17111716
dt = (t - T[idx-1]) / (T[idx] - T[idx-1])
17121717
return U[..., idx-1] * (1. - dt) + U[..., idx] * dt
17131718

1714-
# Check to make sure this is not a static function
1715-
if sys._isstatic():
1719+
# Check to make sure see if this is a static function
1720+
if sys.nstates == 0:
17161721
# Make sure the user gave a time vector for evaluation (or 'T')
17171722
if t_eval is None:
17181723
# User overrode t_eval with None, but didn't give us the times...
@@ -2924,8 +2929,8 @@ def _process_vector_argument(arg, name, size):
29242929
return val, nelem
29252930

29262931

2927-
# Utility function to create an I/O system from a static gain
2928-
def _convert_static_iosystem(sys):
2932+
# Utility function to create an I/O system (from number or array)
2933+
def _convert_to_iosystem(sys):
29292934
# If we were given an I/O system, do nothing
29302935
if isinstance(sys, InputOutputSystem):
29312936
return sys

control/statesp.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ def __init__(self, *args, **kwargs):
229229
self.C = C
230230
self.D = D
231231

232+
# Determine if the system is static (memoryless)
233+
static = (A.size == 0)
234+
232235
#
233236
# Process keyword arguments
234237
#
@@ -242,7 +245,7 @@ def __init__(self, *args, **kwargs):
242245
{'inputs': B.shape[1], 'outputs': C.shape[0],
243246
'states': A.shape[0]}
244247
name, inputs, outputs, states, dt = _process_iosys_keywords(
245-
kwargs, defaults, static=(A.size == 0))
248+
kwargs, defaults, static=static)
246249

247250
# Create updfcn and outfcn
248251
updfcn = lambda t, x, u, params: \
@@ -257,7 +260,7 @@ def __init__(self, *args, **kwargs):
257260
states=states, dt=dt, **kwargs)
258261

259262
# Reset shapes if the system is static
260-
if self._isstatic():
263+
if static:
261264
A.shape = (0, 0)
262265
B.shape = (0, self.ninputs)
263266
C.shape = (self.noutputs, 0)

control/xferfcn.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,22 @@ def __init__(self, *args, **kwargs):
219219
raise ValueError("display_format must be 'poly' or 'zpk',"
220220
" got '%s'" % self.display_format)
221221

222-
# Determine if the transfer function is static (needed for dt)
222+
#
223+
# Determine if the transfer function is static (memoryless)
224+
#
225+
# True if and only if all of the numerator and denominator
226+
# polynomials of the (MIMO) transfer function are zeroth order.
227+
#
223228
static = True
224229
for arr in [num, den]:
230+
# Iterate using refs_OK since num and den are ndarrays of ndarrays
225231
for poly_ in np.nditer(arr, flags=['refs_ok']):
226232
if poly_.item().size > 1:
227233
static = False
228234
break
229235
if not static:
230236
break
231-
self._static = static
237+
self._static = static # retain for later usage
232238

233239
defaults = args[0] if len(args) == 1 else \
234240
{'inputs': num.shape[1], 'outputs': num.shape[0]}
@@ -1284,12 +1290,9 @@ def dcgain(self, warn_infinite=False):
12841290
"""
12851291
return self._dcgain(warn_infinite)
12861292

1293+
# Determine if a system is static (memoryless)
12871294
def _isstatic(self):
1288-
"""returns True if and only if all of the numerator and denominator
1289-
polynomials of the (possibly MIMO) transfer function are zeroth order,
1290-
that is, if the system has no dynamics. """
1291-
# Check done at initialization
1292-
return self._static
1295+
return self._static # Check done at initialization
12931296

12941297
# Attributes for differentiation and delay
12951298
#

doc/nlsys.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ Discrete time systems are also supported and have dynamics of the form
2323
x[t+1] &= f(t, x[t], u[t], \theta), \\
2424
y[t] &= h(t, x[t], u[t], \theta).
2525
26+
A nonlinear input/output model is said to be "static" if the output
27+
:math:`y(t)` at any given time :math:`t` depends only on the input
28+
:math:`u(t)` at that same time :math:`t` and not on past or future
29+
values of :math:`u`.
30+
2631

2732
.. _sec-nonlinear-models:
2833

@@ -47,7 +52,9 @@ dynamics of the system can be in continuous or discrete time (use the
4752
The output function `outfcn` is used to specify the outputs of the
4853
system and has the same calling signature as `updfcn`. If it is not
4954
specified, then the output of the system is set equal to the system
50-
state. Otherwise, it should return an array of shape (p,).
55+
state. Otherwise, it should return an array of shape (p,). If a
56+
input/output system is static, the state `x` should still be passed to
57+
the output function, but the state is ignored.
5158

5259
Note that the number of states, inputs, and outputs should generally
5360
be explicitly specified, although some operations can infer the

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy