StateSpace.zero() now supports MIMO systems · python-control/python-control@f66315d
@@ -54,8 +54,7 @@
5454import math
5555import numpy as np
5656from 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
5958from numpy.random import rand, randn
6059from numpy.linalg import solve, eigvals, matrix_rank
6160from numpy.linalg.linalg import LinAlgError
@@ -516,17 +515,29 @@ def pole(self):
516515def zero(self):
517516"""Compute the zeros of a state space system."""
518517519-if self.inputs > 1 or self.outputs > 1:
520-raise NotImplementedError("StateSpace.zeros is currently \
521-implemented only for SISO systems.")
518+if self.A.shape[0] != self.A.shape[1]:
519+raise NotImplementedError("StateSpace.zero only supports systems "
520+"with square A matrices.")
521+522+# This implements the QZ algorithm for finding transmission zeros from
523+# https://dspace.mit.edu/bitstream/handle/1721.1/841/P-0802-06587335.pdf.
524+# The QZ algorithm solves the generalized eigenvalue problem: given
525+# `L = [A, B; C, D]` and `M = [I_nxn 0]`, find all finite λ for which
526+# there exist nontrivial solutions of the equation `Lz - λMz`.
527+#
528+# The generalized eigenvalue problem is only solvable if its arguments
529+# are square matrices.
530+L = concatenate((concatenate((self.A, self.B), axis=1),
531+concatenate((self.C, self.D), axis=1)), axis=0)
532+M = pad(eye(self.A.shape[0]), ((0, self.C.shape[0]),
533+ (0, self.B.shape[1])), "constant")
522534523-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)
535+if self.states:
536+return np.array([x for x in sp.linalg.eigvals(L, M,
537+overwrite_a=True)
538+if not isinf(x)])
539+else:
540+return np.array([])
530541531542# Feedback around a state space system
532543def feedback(self, other=1, sign=-1):