Routh-Hurwitz Table

sympy.physics.control.routh_table.negative_real_part_conditions(
polynomial,
var,
/,
*,
domain=None,
)[source]

Returns a list of conditions for a polynomial to have all its roots with negative real parts.

Note: This method assumes that the leading coefficient is non-zero. In the opposite case, additional verification is required.

Parameters:

polynomial : Expr, Number

The polynomial whose roots are to be analyzed.

var : Symbol, None, optional

The symbol representing the variable in the polynomial.

domain : None, Domain, optional

The domain in which the polynomial is defined.

Returns:

list[StrictGreaterThan | Boolean]

A list of conditions that must be satisfied for the polynomial to have all its roots with negative real parts.

Examples

>>> from sympy.physics.control import negative_real_part_conditions
>>> from sympy import symbols
>>> s = symbols('s')
>>> p1 = (s+1)*(s+2)*(s+2.5)
>>> negative_real_part_conditions(p1, s)
[True, True, True]
>>> k = symbols('k')
>>> p2 = (s+1)*(s+k)
>>> negative_real_part_conditions(p2, s)
[k + 1 > 0, k*(k + 1)**3 > 0]
>>> a = symbols('a', negative = True)
>>> p3 = (s+1)*(s+a)
>>> negative_real_part_conditions(p3, s)
[a + 1 > 0, a*(a + 1)**3 > 0]
class sympy.physics.control.routh_table.RouthHurwitz(polynomial, var)[source]

A class for creating a Routh-Hurwitz table from a given polynomial. It handles special cases with methods discussed in [R748].

Note: When at least a row of the table is zero, the property zero_row_case is set to True.

Parameters:

polynomial : Expr, Number

The polynomial whose Routh-Hurwitz table is to be created.

var : Symbol

The symbol representing the variable in the polynomial.

infinitesimal_element : None, Symbol, optional

The symbol representing the infinitesimal element for the first column zero case. If not provided, a default symbol epsilon will be used.

Explanation

In mathematics, the Routh-Hurwitz table is used to determine the number of roots of a polynomial that have positive or negative real parts.

It’s crucial in the control system theory because it can be used to retrieve necessary and sufficient conditions for the stability of a linear time-invariant control system.

Once the table is constructed, the stability of the system can be assessed by counting the number of sign changes in the first column. Each sign change corresponds to a root with a positive real part, whereas each preservation of sign corresponds to a root with a negative real part.

There are two special cases to consider during the construction of the table:

  1. First Column Zero Case: If a zero appears in the first column of a row (while the row is not entirely zero), the Extended Routh’s Table is constructed [R749] and every information of these rows is stored in zero_col_infos.

  2. Full Row Zero Case: If an entire row becomes zero, we can substitute the row with the coefficients of the derivative of an auxiliary polynomial. The auxiliary polynomial is constructed using the row immediately above the zero row [R750]. For instance, consider the following example:

    \[\begin{split}\begin{matrix}3\\2\\1\end{matrix}\begin{bmatrix}b_3&b_1\\ b_2&b_0\\ 0&0\end{bmatrix}\end{split}\]

    The auxiliary polynomial will be: \(a(s) = b_2 s^2 + b_0\) The characteristic is that, if \(p(s)\) is the polynomial we are analyzing, \(p(s)=a(s)\cdot other(s)\) and the roots of \(a(s)\) are symmetric about the origin in the s-plane, so when we fall in this case, we should note that there could be poles with only imaginary part or poles with negative and positive real parts.

The table is constructed for a polynomial of the form \(p(s) = b_n s^n + b_{n-1} s^{n-1} + \ldots + b_1 s + b_0\) and the table has \(n+1\) rows and the following structure:

\[\begin{split}\begin{bmatrix}b_n&b_{n-2}&b_{n-4}&\cdots\\ b_{n-1}&b_{n-3}&b_{n-5}&\cdots\\ c_{1}&c_2&c_3&\cdots\\ d_{1}&d_2&d_3&\cdots\\ \vdots&\vdots&\vdots&\ddots\end{bmatrix}\end{split}\]

In this table, the elements in the subsequent rows are computed using the formulas: \(c_i = \frac{b_{n-1}\cdot b_{n-2i}-b_n\cdot b_{n-(2i+1)}}{b_{n-1}}\)

\(d_i = \frac{c_1 \cdot b_{n-(2i+1)}-b_{n-1}\cdot c_{i+1}}{c_1}\)

Examples

>>> from sympy import symbols
>>> from sympy.physics.control import RouthHurwitz
>>> b1, b2, b3, b4 = symbols('b_1 b_2 b_3 b_4')
>>> s = symbols("s")

Here is a generic example of how to use the RouthHurwitz class:

>>> p = b1*s**3 + b2*s**2 + b3*s + b4
>>> RouthHurwitz(p, s)
Matrix([
[                     b_1, b_3],
[                     b_2, b_4],
[(-b_1*b_4 + b_2*b_3)/b_2,   0],
[                     b_4,   0]])
>>> RouthHurwitz(p, s)[:, 0]
Matrix([
[                     b_1],
[                     b_2],
[(-b_1*b_4 + b_2*b_3)/b_2],
[                     b_4]])

Here you can see how the table appears in the first column zero case:

>>> p1 = s**4 + s**3 + 3*s**2 + 3*s + 3
>>> RouthHurwitz(p1, s)
Matrix([
[ 1, 3, 3],
[ 1, 3, 0],
[-3, 3, 0],
[ 4, 0, 0],
[ 3, 0, 0]])
>>> RouthHurwitz(p1, s).zero_col_infos
[(2, 1)]
>>> RouthHurwitz(p1, s).zero_row_case
False

Here you can see how the table appears in the full row zero case (poles with only imaginary part):

>>> p2 = s**6 + 2*s**5 + 8*s**4 + 12*s**3 + 20*s**2 + 16*s + 16
>>> RouthHurwitz(p2, s)
Matrix([
[  1,  8, 20, 16],
[  2, 12, 16,  0],
[  2, 12, 16,  0],
[  8, 24,  0,  0],
[  6, 16,  0,  0],
[8/3,  0,  0,  0],
[ 16,  0,  0,  0]])
>>> RouthHurwitz(p2, s).zero_row_case
True
>>> RouthHurwitz(p2, s).auxiliary_polynomials
[Poly(2*s**4 + 12*s**2 + 16, s, domain='ZZ')]

References

property auxiliary_polynomials

If zero_row_case is True, returns a list of auxiliary polynomials associated with the Full Row Zero Case. Otherwise, return None.

It is used to handle the Full Row Zero Case during the construction of the Routh-Hurwitz table.

property zero_col_infos

Return a list of tuple.

  • The first element of the tuple represents the index of a row in which the First Column Zero Case occurs.

  • The second element of the tuple represents the index of the first column different from 0 before the Extended Routh’s Table construction.

property zero_row_case

Return True if during the building of the table the Full Row Zero Case (see the explanation section) has been encountered, else False.