Example #1
0
def _check_non_simple(coeffs):
    r"""Checks that a polynomial has no non-simple roots.

    Does so by computing the companion matrix :math:`A` of :math:`f'`
    and then evaluating the rank of :math:`B = f(A)`. If :math:`B` is not
    full rank, then :math:`f` and :math:`f'` have a shared factor.

    See: https://dx.doi.org/10.1016/0024-3795(70)90023-6

    .. note::

       This assumes that :math:`f \neq 0`.

    Args:
        coeffs (numpy.ndarray): ``d + 1``-array of coefficients in monomial /
            power basis.

    Raises:
        NotImplementedError: If the polynomial has non-simple roots.
    """
    coeffs = _strip_leading_zeros(coeffs)
    num_coeffs, = coeffs.shape
    if num_coeffs < 3:
        return

    deriv_poly = polynomial.polyder(coeffs)

    companion = polynomial.polycompanion(deriv_poly)
    # NOTE: `polycompanion()` returns a C-contiguous array.
    companion = companion.T
    # Use Horner's method to evaluate f(companion)
    num_companion, _ = companion.shape
    id_mat = _helpers.eye(num_companion)
    evaluated = coeffs[-1] * id_mat
    for index in six.moves.xrange(num_coeffs - 2, -1, -1):
        coeff = coeffs[index]
        evaluated = (_helpers.matrix_product(evaluated, companion) +
                     coeff * id_mat)

    if num_companion == 1:
        # NOTE: This relies on the fact that coeffs is normalized.
        if np.abs(evaluated[0, 0]) > _NON_SIMPLE_THRESHOLD:
            rank = 1
        else:
            rank = 0
    else:
        rank = np.linalg.matrix_rank(evaluated)
    if rank < num_companion:
        raise NotImplementedError(_NON_SIMPLE_ERR, coeffs)
Example #2
0
def tf2ss(sys_):
    """
    Convert transfer function model to state space model.

    :param sys_: the system
    :type sys_: TransferFunction

    :return: corresponded transfer function model
    :rtype: StateSpace
    """
    try:
        nump = np.poly1d(sys_.num)
        denp = np.poly1d(sys_.den)
    except AttributeError as e:
        raise TypeError(f'TransferFunction expected got {type(sys_)}') from e

    if not sys_.is_siso:
        raise ValueError('tf2ss only for siso system right now.')

    dt = sys_.dt
    if denp[denp.order] != 1:
        nump /= denp[denp.order]
        denp /= denp[denp.order]
    q, r = nump / denp
    num = r.coeffs
    bn = q.coeffs
    den = denp.coeffs
    D = np.atleast_2d(bn)

    if sys_.is_gain:
        A = np.array([[0]])
        B = np.array([[0]])
        C = np.array([[0]])
    else:
        # generate matrix A
        n = den.shape[0] - 1
        A = polycompanion(den[::-1]).T

        B = np.zeros((n, 1))
        B[-1] = 1

        C = np.zeros((1, n))
        C[0, 0:num.shape[0]] = num[::-1]

    return StateSpace(A, B, C, D, dt=dt)
Example #3
0
def _mi_place(A, B, poles):
    n = A.shape[0]
    p = B.shape[1]
    T = ctrb_trans_mat(A, B)
    Ac = T @ A @ inv(T)
    Bc = T @ B

    Ac_tilde = polycompanion(np.flip(np.poly(poles))).T

    r = -1
    indices = ctrb_indices(A, B)
    Ar = np.empty((indices.shape[0], n))
    Br = np.empty((p, p))
    Ar_tilde = np.empty(Ar.shape)
    for i, mu in enumerate(indices):
        r += mu
        Ar[i] = Ac[r]
        Br[i] = Bc[r]
        Ar_tilde[i] = Ac_tilde[r]

    K = inv(Br) @ (Ar - Ar_tilde)
    return K @ T
Example #4
0
 def test_linear_root(self):
     assert_(poly.polycompanion([1, 2])[0, 0] == -.5)
Example #5
0
 def test_dimensions(self):
     for i in range(1, 5):
         coef = [0]*i + [1]
         assert_(poly.polycompanion(coef).shape == (i, i))
Example #6
0
 def test_linear_root(self):
     assert_(poly.polycompanion([1, 2])[0, 0] == -.5)
Example #7
0
 def test_dimensions(self):
     for i in range(1, 5):
         coef = [0] * i + [1]
         assert_(poly.polycompanion(coef).shape == (i, i))
Example #8
0
def companion_from_eig(eigvals):
    """
    Find companion matrix for given eigenvalue sequence.
    """
    from numpy.polynomial.polynomial import polyfromroots, polycompanion
    return polycompanion(polyfromroots(eigvals)).real