Repository: sympy/sympy
File: sympy/physics/control/routh_table.py (Python)

Code before:
from sympy.core.relational import Unequality

__all__ = ['RouthHurwitz', 'negative_real_root_conditions']

def negative_real_root_conditions(polynomial, var):
    """
    Returns the conditions for a polynomial to have all its roots with
    negative real parts.

    Examples
    ========

    >>> from sympy.physics.control import negative_real_root_conditions
    >>> from sympy import symbols
    >>> s = symbols('s')
    >>> p1 = (s+1)*(s+2)*(s+2.5)
    >>> negative_real_root_conditions(p1, s)
    [[True], [False]]
    >>> k = symbols('k')
    >>> p2 = (s+1)*(s+k)
    >>> negative_real_root_conditions(p2, s)
    [[k + 1 > 0, k > 0], [False]]
    >>> a = symbols('a', negative = True)
    >>> p3 = (s+1)*(s+a)
    >>> negative_real_root_conditions(p3, s)
    [[a + 1 > 0, False], [False]]

    """
    table = RouthHurwitz(polynomial, var)

    if table.zero_row_case:
        # There is a pole with a real part equal to zero or
        # a pole with a positive real part.
        return [[False], [False]]

    num_conditions = [true, true]
    var_conditions: list[list] = [[], []]

    _add_zero_col_conds(var_conditions, table)

    for eq in table[:, 0]:
        if eq.is_number:
            num_conditions[0] &= eq > 0
            num_conditions[1] &= eq < 0

        else:
            var_conditions[0].append(eq > 0)
            var_conditions[1].append(eq < 0)

        if Or(num_conditions[0], num_conditions[1]) is false:
            return [[False], [False]]

Review comment (suggestion):
Can you add document about how to interpret this result?
I think that the result had changed and I'm not sure about the meaning of this array by 
`Returns the conditions for a polynomial to have all its roots with negative real parts.`

Code after:
__all__ = ['RouthHurwitz', 'negative_real_part_conditions']

def negative_real_part_conditions(polynomial, var, /, *, domain=None):
    """
    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]

    """
    p: Poly = Poly(polynomial, var, domain = domain)

    _, p = p.clear_denoms(convert=True)

    coeffs = p.all_coeffs()