Exemple #1
0
def left_ortho_complement(matrix):
    
    # commented out for performance
    #assert has_left_ortho_complement(matrix), "There is no leftorthocomplement!"

    v = custom_simplify( st.nullspaceMatrix(matrix.T).T )
    assert is_zero_matrix(v*matrix), "Leftorthocomplement is not correct."
    return v
Exemple #2
0
def left_ortho_complement(matrix):

    # commented out for performance
    #assert has_left_ortho_complement(matrix), "There is no leftorthocomplement!"

    v = custom_simplify(st.nullspaceMatrix(matrix.T).T)
    assert is_zero_matrix(v * matrix), "Leftorthocomplement is not correct."
    return v
Exemple #3
0
def right_ortho_complement(matrix):
    assert has_right_ortho_complement(matrix), "There is no rightorthocomplement!"

    if roc=="conv":
        v = custom_simplify( st.nullspaceMatrix(matrix) )
        assert is_zero_matrix(matrix*v), "Leftorthocomplement is not correct."
        return v
    else:
        return alternative_right_ortho_complement(matrix)
Exemple #4
0
def right_ortho_complement(matrix):
    assert has_right_ortho_complement(
        matrix), "There is no rightorthocomplement!"

    if roc == "conv":
        v = custom_simplify(st.nullspaceMatrix(matrix))
        assert is_zero_matrix(matrix *
                              v), "Leftorthocomplement is not correct."
        return v
    else:
        return alternative_right_ortho_complement(matrix)
Exemple #5
0
def unimod_inv(M,
               s=None,
               t=None,
               time_dep_symbs=[],
               simplify_nsm=True,
               max_deg=None):
    """ Assumes that M(s) is an unimodular polynomial matrix and calculates its inverse
    which is again unimodular

    :param M:               Matrix to be inverted
    :param s:               Derivative Symbol
    :param time_dep_symbs:  sequence of time dependent symbols
    :param max_deg:       maximum polynomial degree w.r.t. s of the ansatz

    :return: Minv
    """

    assert isinstance(M, sp.MatrixBase)
    assert M.is_square

    n = M.shape[0]

    degree_m = nc_degree(M, s)

    if max_deg is None:
        # upper bound according to
        # Levine 2011, On necessary and sufficient conditions for differential flatness, p. 73

        max_deg = (n - 1) * degree_m

    assert int(max_deg) == max_deg
    assert max_deg >= 0

    C = M * 0
    free_params = []

    for i in range(max_deg + 1):
        prefix = 'c{0}_'.format(i)
        c_part = st.symbMatrix(n, n, prefix, commutative=False)
        C += nc_mul(c_part, s**i)
        free_params.extend(list(c_part))

    P = nc_mul(C, M) - sp.eye(n)

    P2 = right_shift_all(P, s, t, time_dep_symbs).reshape(n * n, 1)

    deg_P = nc_degree(P2, s)

    part_eqns = []
    for i in range(deg_P + 1):
        # omit the highest order (because it behaves like in the commutative case)
        res = P2.diff(s, i).subs(s, 0)  #/sp.factorial(i)
        part_eqns.append(res)

    eqns = st.row_stack(*part_eqns)  # equations for all degrees of s

    # now non-commutativity is inferring
    eqns2, st_c_nc = make_all_symbols_commutative(eqns)
    free_params_c, st_c_nc_free_params = make_all_symbols_commutative(
        free_params)

    # find out which of the equations are (in)homogeneous
    eqns2_0 = eqns2.subs(st.zip0(free_params_c))
    assert eqns2_0.atoms() in ({0, -1}, {-1}, set())
    inhom_idcs = st.np.where(st.to_np(eqns2_0) != 0)[0]
    hom_idcs = st.np.where(st.to_np(eqns2_0) == 0)[0]

    eqns_hom = sp.Matrix(st.np.array(eqns2)[hom_idcs])
    eqns_inh = sp.Matrix(st.np.array(eqns2)[inhom_idcs])

    assert len(eqns_inh) == n

    # find a solution for the homogeneous equations
    # if this is not possible, M was not unimodular
    Jh = eqns_hom.jacobian(free_params_c).expand()

    nsm = st.nullspaceMatrix(Jh, simplify=simplify_nsm, sort_rows=True)

    na = nsm.shape[1]
    if na < n:
        msg = 'Could not determine sufficiently large nullspace. '\
        'Either M is not unimodular or the expressions are to complicated.'
        # TODO: decide which of the two cases occurs, via substitution of
        # random numbers and singular value decomposition
        # (or application of st.generic_rank)
        raise ValueError(msg)

    # parameterize the inhomogenous equations with the solution of the homogeneous equations
    # new free parameters:
    aa = st.symb_vector('_a1:{0}'.format(na + 1))
    nsm_a = nsm * aa

    eqns_inh2 = eqns_inh.subs(lzip(free_params_c, nsm_a))

    # now solve the remaining equations

    # solve the linear system
    Jinh = eqns_inh2.jacobian(aa)
    rhs_inh = -eqns_inh2.subs(st.zip0(aa))
    assert rhs_inh == sp.ones(n, 1)

    sol_vect = Jinh.solve(rhs_inh)
    sol = lzip(aa, sol_vect)

    # get the values for all free_params (now they are not free anymore)
    free_params_sol_c = nsm_a.subs(sol)

    # replace the commutative symbols with the original non_commutative symbols (of M)
    free_params_sol = free_params_sol_c.subs(st_c_nc)

    Minv = C.subs(lzip(free_params, free_params_sol))

    return Minv
Exemple #6
0
        #~ [    0,      0,               0,               0,                     1,            -1,     1, -1,     0,     0,             0,             0],
        #~ [W2*x9, W3*x10, W1*x11 - W2*x11, W1*x12 - W3*x12, Rd*W1 + Rl*W2 - Rl*W3, Rl*W2 + Rl*W3, Rd*W1,  0, W2*x1, W3*x2, W1*x3 - W2*x3, W1*x4 - W3*x4]])

P00 = F_eq.jacobian(xx)
#~ P00 = sp.Matrix([
        #~ [      x9,         0,                  -x11,                     0,  Rl,   Rl,    0,    0,       x1,        0,                 -x3,                   0],
        #~ [       0,       x10,                     0,                  -x12, -Rl,   Rl,    0,    0,        0,       x2,                   0,                 -x4],
        #~ [       0,         0,                     0,                     0, -x9,    0,    0,    0,      -x5,        0,                   0,                   0],
        #~ [       0,         0,                     0,                     0,   0, -x10,    0,    0,        0,      -x6,                   0,                   0],
        #~ [       0,         0,                     0,                     0,   0,    0, -x11,    0,        0,        0,                 -x7,                   0],
        #~ [       0,         0,                     0,                     0,   0,    0,    0, -x12,        0,        0,                   0,                 -x8],
        #~ [       0,         0,                     0,                     0,   0,    0,    0,    0,        0,        0,                   0,                   0],
        #~ [       0,         0,                     0,                     0,   0,    0,    0,    0,        0,        0,                   0,                   0],
        #~ [W2*xdot9, W3*xdot10, W1*xdot11 - W2*xdot11, W1*xdot12 - W3*xdot12,   0,    0,    0,    0, W2*xdot1, W3*xdot2, W1*xdot3 - W2*xdot3, W1*xdot4 - W3*xdot4]])

P10_roc = st.nullspaceMatrix(P10)
#~ P10_roc = sp.Matrix([
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [     0,             0,             0],
        #~ [-W3*x2, x3*(-W1 + W2), x4*(-W1 + W3)],
        #~ [ W2*x1,             0,             0],
        #~ [     0,         W2*x1,             0],
        #~ [     0,             0,         W2*x1]])

# statt P10_rpinv nehme ich jetzt S mit einheitsvektoren sodass
def unimod_inv(M, s=None, t=None, time_dep_symbs=[], simplify_nsm=True, max_deg=None):
    """ Assumes that M(s) is an unimodular polynomial matrix and calculates its inverse
    which is again unimodular

    :param M:               Matrix to be inverted
    :param s:               Derivative Symbol
    :param time_dep_symbs:  sequence of time dependent symbols
    :param max_deg:       maximum polynomial degree w.r.t. s of the ansatz

    :return: Minv
    """

    assert isinstance(M, sp.MatrixBase)
    assert M.is_square

    n = M.shape[0]

    degree_m = nc_degree(M, s)

    if max_deg is None:
        # upper bound according to
        # Levine 2011, On necessary and sufficient conditions for differential flatness, p. 73

        max_deg = (n - 1)*degree_m

    assert int(max_deg) == max_deg
    assert max_deg >= 0

    C = M*0
    free_params = []

    for i in range(max_deg+1):
        prefix = 'c{0}_'.format(i)
        c_part = st.symbMatrix(n, n, prefix, commutative=False)
        C += nc_mul(c_part, s**i)
        free_params.extend(list(c_part))

    P = nc_mul(C, M) - sp.eye(n)

    P2 = right_shift_all(P, s, t, time_dep_symbs).reshape(n*n, 1)

    deg_P = nc_degree(P2, s)

    part_eqns = []
    for i in range(deg_P + 1):
        # omit the highest order (because it behaves like in the commutative case)
        res = P2.diff(s, i).subs(s, 0)#/sp.factorial(i)
        part_eqns.append(res)

    eqns = st.row_stack(*part_eqns)  # equations for all degrees of s

    # now non-commutativity is inferring
    eqns2, st_c_nc = make_all_symbols_commutative(eqns)
    free_params_c, st_c_nc_free_params = make_all_symbols_commutative(free_params)

    # find out which of the equations are (in)homogeneous
    eqns2_0 = eqns2.subs(st.zip0(free_params_c))
    assert eqns2_0.atoms() in ({0, -1}, {-1}, set())
    inhom_idcs = st.np.where(st.to_np(eqns2_0) != 0)[0]
    hom_idcs = st.np.where(st.to_np(eqns2_0) == 0)[0]

    eqns_hom = sp.Matrix(st.np.array(eqns2)[hom_idcs])
    eqns_inh = sp.Matrix(st.np.array(eqns2)[inhom_idcs])

    assert len(eqns_inh) == n

    # find a solution for the homogeneous equations
    # if this is not possible, M was not unimodular
    Jh = eqns_hom.jacobian(free_params_c).expand()

    nsm = st.nullspaceMatrix(Jh, simplify=simplify_nsm, sort_rows=True)

    na = nsm.shape[1]
    if na < n:
        msg = 'Could not determine sufficiently large nullspace. '\
        'Either M is not unimodular or the expressions are to complicated.'
        # TODO: decide which of the two cases occurs, via substitution of
        # random numbers and singular value decomposition
        # (or application of st.generic_rank)
        raise ValueError(msg)

    # parameterize the inhomogenous equations with the solution of the homogeneous equations
    # new free parameters:
    aa = st.symb_vector('_a1:{0}'.format(na+1))
    nsm_a = nsm*aa

    eqns_inh2 = eqns_inh.subs(lzip(free_params_c, nsm_a))

    # now solve the remaining equations

    # solve the linear system
    Jinh = eqns_inh2.jacobian(aa)
    rhs_inh = -eqns_inh2.subs(st.zip0(aa))
    assert rhs_inh == sp.ones(n, 1)
    
    sol_vect = Jinh.solve(rhs_inh)
    sol = lzip(aa, sol_vect)

    # get the values for all free_params (now they are not free anymore)
    free_params_sol_c = nsm_a.subs(sol)

    # replace the commutative symbols with the original non_commutative symbols (of M)
    free_params_sol = free_params_sol_c.subs(st_c_nc)

    Minv = C.subs(lzip(free_params, free_params_sol))

    return Minv