|
54 | 54 | import math |
55 | 55 | import numpy as np |
56 | 56 | from numpy import all, angle, any, array, asarray, concatenate, cos, delete, \ |
57 | | - dot, empty, exp, eye, matrix, ones, poly, poly1d, roots, shape, sin, \ |
58 | | - zeros, squeeze |
| 57 | + dot, empty, exp, eye, isinf, matrix, ones, pad, shape, sin, zeros, squeeze |
59 | 58 | from numpy.random import rand, randn |
60 | 59 | from numpy.linalg import solve, eigvals, matrix_rank |
61 | 60 | from numpy.linalg.linalg import LinAlgError |
@@ -516,17 +515,22 @@ def pole(self): |
516 | 515 | def zero(self): |
517 | 516 | """Compute the zeros of a state space system.""" |
518 | 517 |
|
519 | | - if self.inputs > 1 or self.outputs > 1: |
520 | | - raise NotImplementedError("StateSpace.zeros is currently \ |
521 | | -implemented only for SISO systems.") |
| 518 | + # This implements the QZ algorithm for finding transmission zeros from |
| 519 | + # https://dspace.mit.edu/bitstream/handle/1721.1/841/P-0802-06587335.pdf. |
| 520 | + # The QZ algorithm solves the generalized eigenvalue problem: given |
| 521 | + # `L = [A, B; C, D]` and `M = [I_nxn 0]`, find all finite λ for which |
| 522 | + # there exist nontrivial solutions of the equation `Lz - λMz`. |
| 523 | + L = concatenate((concatenate((self.A, self.B), axis=1), |
| 524 | + concatenate((self.C, self.D), axis=1)), axis=0) |
| 525 | + M = pad(eye(self.A.shape[0]), ((0, self.C.shape[0]), |
| 526 | + (0, self.B.shape[1])), "constant") |
522 | 527 |
|
523 | | - den = poly1d(poly(self.A)) |
524 | | - # Compute the numerator based on zeros |
525 | | - #! TODO: This is currently limited to SISO systems |
526 | | - num = poly1d(poly(self.A - dot(self.B, self.C)) + ((self.D[0, 0] - 1) * |
527 | | - den)) |
528 | | - |
529 | | - return roots(num) |
| 528 | + if self.states: |
| 529 | + return np.array([x for x in sp.linalg.eigvals(L, M, |
| 530 | + overwrite_a=True) |
| 531 | + if not isinf(x)]) |
| 532 | + else: |
| 533 | + return np.array([]) |
530 | 534 |
|
531 | 535 | # Feedback around a state space system |
532 | 536 | def feedback(self, other=1, sign=-1): |
|
0 commit comments