1717__all__ = ['canonical_form' , 'reachable_form' , 'observable_form' , 'modal_form' ,
1818 'similarity_transform' , 'bdschur' ]
1919
20+
2021def canonical_form (xsys , form = 'reachable' ):
2122 """Convert a system into canonical form
2223
@@ -41,16 +42,16 @@ def canonical_form(xsys, form='reachable'):
4142 --------
4243 >>> Gs = ct.tf2ss([1], [1, 3, 2])
4344 >>> Gc, T = ct.canonical_form(Gs) # default reachable
44- >>> Gc.B
45+ >>> Gc.B.round()
4546 array([[1.],
4647 [0.]])
4748
4849 >>> Gc, T = ct.canonical_form(Gs, 'observable')
49- >>> Gc.C
50+ >>> Gc.C.round()
5051 array([[1., 0.]])
5152
5253 >>> Gc, T = ct.canonical_form(Gs, 'modal')
53- >>> Gc.A
54+ >>> Gc.A.round() # doctest: +SKIP
5455 array([[-2., 0.],
5556 [ 0., -1.]])
5657
@@ -88,9 +89,9 @@ def reachable_form(xsys):
8889 --------
8990 >>> Gs = ct.tf2ss([1], [1, 3, 2])
9091 >>> Gc, T = ct.reachable_form(Gs) # default reachable
91- >>> Gc.B # doctest: +SKIP
92- matrix ([[1.],
93- [0.]])
92+ >>> Gc.B.round()
93+ array ([[1.],
94+ [0.]])
9495
9596 """
9697 # Check to make sure we have a SISO system
@@ -151,8 +152,8 @@ def observable_form(xsys):
151152 --------
152153 >>> Gs = ct.tf2ss([1], [1, 3, 2])
153154 >>> Gc, T = ct.observable_form(Gs)
154- >>> Gc.C # doctest: +SKIP
155- matrix ([[1., 0.]])
155+ >>> Gc.C.round()
156+ array ([[1., 0.]])
156157
157158 """
158159 # Check to make sure we have a SISO system
@@ -216,15 +217,15 @@ def similarity_transform(xsys, T, timescale=1, inverse=False):
216217 Examples
217218 --------
218219 >>> Gs = ct.tf2ss([1], [1, 3, 2])
219- >>> Gs.A # doctest: +SKIP
220- matrix ([[-3., -2.],
221- [ 1., 0.]])
220+ >>> Gs.A.round()
221+ array ([[-3., -2.],
222+ [ 1., 0.]])
222223
223- >>> T = np.array([[0,1],[1,0]])
224+ >>> T = np.array([[0, 1], [1, 0]])
224225 >>> Gt = ct.similarity_transform(Gs, T)
225- >>> Gt.A # doctest: +SKIP
226- matrix ([[ 0., 1.],
227- [-2., -3.]])
226+ >>> Gt.A.round()
227+ array ([[ 0., 1.],
228+ [-2., -3.]])
228229
229230 """
230231 # Create a new system, starting with a copy of the old one
@@ -293,7 +294,8 @@ def _bdschur_condmax_search(aschur, tschur, condmax):
293294
294295 Iterates mb03rd with different pmax values until:
295296 - result is non-defective;
296- - or condition number of similarity transform is unchanging despite large pmax;
297+ - or condition number of similarity transform is unchanging
298+ despite large pmax;
297299 - or condition number of similarity transform is close to condmax.
298300
299301 Parameters
@@ -332,22 +334,25 @@ def _bdschur_condmax_search(aschur, tschur, condmax):
332334
333335 # get lower bound; try condmax ** 0.5 first
334336 pmaxlower = condmax ** 0.5
335- amodal , tmodal , blksizes , eigvals = mb03rd (aschur .shape [0 ], aschur , tschur , pmax = pmaxlower )
337+ amodal , tmodal , blksizes , eigvals = mb03rd (
338+ aschur .shape [0 ], aschur , tschur , pmax = pmaxlower )
336339 if np .linalg .cond (tmodal ) <= condmax :
337340 reslower = amodal , tmodal , blksizes , eigvals
338341 else :
339342 pmaxlower = 1.0
340- amodal , tmodal , blksizes , eigvals = mb03rd (aschur .shape [0 ], aschur , tschur , pmax = pmaxlower )
343+ amodal , tmodal , blksizes , eigvals = mb03rd (
344+ aschur .shape [0 ], aschur , tschur , pmax = pmaxlower )
341345 cond = np .linalg .cond (tmodal )
342346 if cond > condmax :
343- msg = ' minimum cond={ } > condmax={ }; try increasing condmax' . format ( cond , condmax )
347+ msg = f" minimum { cond = } > { condmax = } ; try increasing condmax"
344348 raise RuntimeError (msg )
345349
346350 pmax = pmaxlower
347351
348352 # phase 1: search for upper bound on pmax
349353 for i in range (50 ):
350- amodal , tmodal , blksizes , eigvals = mb03rd (aschur .shape [0 ], aschur , tschur , pmax = pmax )
354+ amodal , tmodal , blksizes , eigvals = mb03rd (
355+ aschur .shape [0 ], aschur , tschur , pmax = pmax )
351356 cond = np .linalg .cond (tmodal )
352357 if cond < condmax :
353358 pmaxlower = pmax
@@ -368,7 +373,8 @@ def _bdschur_condmax_search(aschur, tschur, condmax):
368373 # phase 2: bisection search
369374 for i in range (50 ):
370375 pmax = (pmaxlower * pmaxupper ) ** 0.5
371- amodal , tmodal , blksizes , eigvals = mb03rd (aschur .shape [0 ], aschur , tschur , pmax = pmax )
376+ amodal , tmodal , blksizes , eigvals = mb03rd (
377+ aschur .shape [0 ], aschur , tschur , pmax = pmax )
372378 cond = np .linalg .cond (tmodal )
373379
374380 if cond < condmax :
@@ -440,7 +446,8 @@ def bdschur(a, condmax=None, sort=None):
440446 return a .copy (), np .eye (a .shape [1 ], a .shape [0 ]), np .array ([])
441447
442448 aschur , tschur = schur (a )
443- amodal , tmodal , blksizes , eigvals = _bdschur_condmax_search (aschur , tschur , condmax )
449+ amodal , tmodal , blksizes , eigvals = _bdschur_condmax_search (
450+ aschur , tschur , condmax )
444451
445452 if sort in ('continuous' , 'discrete' ):
446453
@@ -484,9 +491,11 @@ def modal_form(xsys, condmax=None, sort=False):
484491 xsys : StateSpace object
485492 System to be transformed, with state `x`
486493 condmax : None or float, optional
487- An upper bound on individual transformations. If None, use `bdschur` default.
494+ An upper bound on individual transformations. If None, use
495+ `bdschur` default.
488496 sort : bool, optional
489- If False (default), Schur blocks will not be sorted. See `bdschur` for sort order.
497+ If False (default), Schur blocks will not be sorted. See `bdschur`
498+ for sort order.
490499
491500 Returns
492501 -------
@@ -499,9 +508,9 @@ def modal_form(xsys, condmax=None, sort=False):
499508 --------
500509 >>> Gs = ct.tf2ss([1], [1, 3, 2])
501510 >>> Gc, T = ct.modal_form(Gs) # default reachable
502- >>> Gc.A # doctest: +SKIP
503- matrix ([[-2., 0.],
504- [ 0., -1.]])
511+ >>> Gc.A.round() # doctest: +SKIP
512+ array ([[-2., 0.],
513+ [ 0., -1.]])
505514
506515 """
507516
0 commit comments