def fourseven(iter_stack): # load matrices Ai = iter_stack.A Bi = iter_stack.B P1i_roc = iter_stack.P1_roc P1i_rpinv = iter_stack.P1_rpinv K2 = roc_hint("B", iter_stack.i, Bi) if mode=="manual" else al.right_ortho_complement(Bi) K1 = al.regular_completion(K2) K = st.concat_cols(K1, K2) assert al.is_regular_matrix(K), "K is not a regular matrix." Bi_tilde = al.custom_simplify(Bi*K1) # unit matrix if myStack.calc_G: Bi_tilde_lpinv = al.left_pseudo_inverse(Bi_tilde) else: Bi_tilde_lpinv = None P1i_tilde_roc = al.custom_simplify( P1i_roc*K1 ) Zi = al.custom_simplify( P1i_roc*K2 ) Zi_lpinv = al.Zi_left_pinv_with_restrictions(P1i_rpinv, P1i_tilde_roc, Zi) assert al.is_unit_matrix( Zi_lpinv*Zi ), "Zi_lpinv seems to be wrong." # store iter_stack.store_special_case_matrices( Zi, Zi_lpinv, Bi_tilde, Bi_tilde_lpinv, P1i_tilde_roc ) return Bi_tilde
def Zi_left_pinv_with_restrictions(P1i_rpinv, P1i_tilde_roc, Zi): """ Given a matrix Zi, this function calculates a matrix such that: Zi_left_pinv * Zi = I Zi_left_pinv * P1i_tilde_roc = 0 Zi_left_pinv * P1i_rpinv = 0 """ assert check_row_compatibility(P1i_rpinv, P1i_tilde_roc, Zi),\ "Matrices do not match in row dimension." C = st.concat_cols(P1i_rpinv, P1i_tilde_roc, Zi) assert is_regular_matrix(C), "C is not a regular matrix" C_det = C.berkowitz_det() C_inv = C.adjugate()/C_det C_inv = custom_simplify(C_inv) m, n = Zi.shape Zi_left_pinv = sp.Matrix([]) for i in xrange(m-n,m): Zi_left_pinv = st.concat_rows(Zi_left_pinv,C_inv.row(i)) o, p = Zi_left_pinv.shape assert o==n and p==m, "There must have been a problem with the\ computation of Zi_left_pinv" assert is_unit_matrix(Zi_left_pinv*Zi), "Zi_left_pinv is wrong" assert is_zero_matrix(Zi_left_pinv*P1i_tilde_roc), "Zi_left_pinv is wrong" assert is_zero_matrix(Zi_left_pinv*P1i_rpinv), "Zi_left_pinv is wrong" return Zi_left_pinv
def Zi_left_pinv_with_restrictions(P1i_rpinv, P1i_tilde_roc, Zi): """ Given a matrix Zi, this function calculates a matrix such that: Zi_left_pinv * Zi = I Zi_left_pinv * P1i_tilde_roc = 0 Zi_left_pinv * P1i_rpinv = 0 """ assert check_row_compatibility(P1i_rpinv, P1i_tilde_roc, Zi),\ "Matrices do not match in row dimension." C = st.concat_cols(P1i_rpinv, P1i_tilde_roc, Zi) assert is_regular_matrix(C), "C is not a regular matrix" C_det = C.berkowitz_det() C_inv = C.adjugate() / C_det C_inv = custom_simplify(C_inv) m, n = Zi.shape Zi_left_pinv = sp.Matrix([]) for i in range(m - n, m): Zi_left_pinv = st.concat_rows(Zi_left_pinv, C_inv.row(i)) o, p = Zi_left_pinv.shape assert o == n and p == m, "There must have been a problem with the\ computation of Zi_left_pinv" assert is_unit_matrix(Zi_left_pinv * Zi), "Zi_left_pinv is wrong" assert is_zero_matrix(Zi_left_pinv * P1i_tilde_roc), "Zi_left_pinv is wrong" assert is_zero_matrix(Zi_left_pinv * P1i_rpinv), "Zi_left_pinv is wrong" return Zi_left_pinv
def is_linearly_independent(matrix, column_vector): m, n = matrix.shape rank1 = st.rnd_number_rank(matrix) tmp = st.concat_cols(matrix, column_vector) rank2 = st.rnd_number_rank(tmp) assert rank2 >= rank1 return rank2 > rank1
def remove_zero_columns(matrix): """ this function removes zero columns of a matrix """ m, n = matrix.shape M = sp.Matrix([]) for i in xrange(n): if not is_zero_matrix(matrix.col(i)): M = st.concat_cols(M, matrix.col(i)) return M
def remove_zero_columns(matrix): """ this function removes zero columns of a matrix """ m, n = matrix.shape M = sp.Matrix([]) for i in range(n): if not is_zero_matrix(matrix.col(i)): M = st.concat_cols(M, matrix.col(i)) return M
def right_shift_all_in_matrix(self, matrix): # does nct-package provide this already? m,n = matrix.shape matrix_shifted = sp.Matrix([]) t_dep_symbols = [symb for symb in st.atoms(matrix, sp.Symbol) if not symb == s] for i in xrange(n): col = matrix.col(i) col_shifted = sp.Matrix([nct.right_shift_all(expr,s,t, t_dep_symbols) for expr in col]) matrix_shifted = st.concat_cols(matrix_shifted, col_shifted) return matrix_shifted
def right_shift_all_in_matrix(self, matrix): # does nct-package provide this already? m, n = matrix.shape matrix_shifted = sp.Matrix([]) t_dep_symbols = [ symb for symb in st.atoms(matrix, sp.Symbol) if not symb == s ] for i in range(n): col = matrix.col(i) col_shifted = sp.Matrix([ nct.right_shift_all(expr, s, t, t_dep_symbols) for expr in col ]) matrix_shifted = st.concat_cols(matrix_shifted, col_shifted) return matrix_shifted
def calculate_Gi_matrix(self, i): # 1) choose correct matrices for Gi[d/dt] # 2) change symbols to noncommutative symbols, calculate Gi[d/dt] # 3) G[d/dt] = G0[d/dt] * G1[d/dt] * ... * Gi[d/dt] # 4) special case procedure iteration = self._myStack.get_iteration(i) if not iteration.is_special_case: # get matrices P1_rpinv = iteration.P1_rpinv P1_roc = iteration.P1_roc B_lpinv = iteration.B_lpinv A = iteration.A P1_rpinv_nc, P1_roc_nc, B_lpinv_nc, A_nc = self.convert_to_nc_matrices( P1_rpinv, P1_roc, B_lpinv, A) Gi = P1_rpinv_nc - P1_roc_nc * (B_lpinv_nc * s_ + B_lpinv_nc * A_nc) else: # get matrices P1_rpinv = iteration.P1_rpinv P1_tilde_roc = iteration.P1_tilde_roc B_tilde_lpinv = iteration.B_tilde_lpinv A = iteration.A Z = iteration.Z # convert commutative symbols to non commutative P1_rpinv_nc = self.make_symbols_non_commutative(P1_rpinv) P1_tilde_roc_nc = self.make_symbols_non_commutative(P1_tilde_roc) B_tilde_lpinv_nc = self.make_symbols_non_commutative(B_tilde_lpinv) A_nc = self.make_symbols_non_commutative(A) Z_nc = self.make_symbols_non_commutative(Z) Gi = P1_rpinv_nc - P1_tilde_roc_nc * (B_tilde_lpinv_nc * s_ + B_tilde_lpinv_nc * A_nc) Gi = st.concat_cols(Gi, Z_nc) if False: # show_Gi_matrices: pc.print_matrix("G", i, "", Gi) # store iteration.Gi = Gi return Gi
def calculate_Gi_matrix(self, i): # 1) choose correct matrices for Gi[d/dt] # 2) change symbols to noncommutative symbols, calculate Gi[d/dt] # 3) G[d/dt] = G0[d/dt] * G1[d/dt] * ... * Gi[d/dt] # 4) special case procedure iteration = self._myStack.get_iteration(i) if not iteration.is_special_case: # get matrices P1_rpinv = iteration.P1_rpinv P1_roc = iteration.P1_roc B_lpinv = iteration.B_lpinv A = iteration.A P1_rpinv_nc, P1_roc_nc, B_lpinv_nc, A_nc = self.convert_to_nc_matrices(P1_rpinv, P1_roc, B_lpinv, A) Gi = P1_rpinv_nc - P1_roc_nc*( B_lpinv_nc*s_ + B_lpinv_nc*A_nc ) else: # get matrices P1_rpinv = iteration.P1_rpinv P1_tilde_roc = iteration.P1_tilde_roc B_tilde_lpinv = iteration.B_tilde_lpinv A = iteration.A Z = iteration.Z # convert commutative symbols to non commutative P1_rpinv_nc = self.make_symbols_non_commutative(P1_rpinv) P1_tilde_roc_nc = self.make_symbols_non_commutative(P1_tilde_roc) B_tilde_lpinv_nc = self.make_symbols_non_commutative(B_tilde_lpinv) A_nc = self.make_symbols_non_commutative(A) Z_nc = self.make_symbols_non_commutative(Z) Gi = P1_rpinv_nc - P1_tilde_roc_nc*( B_tilde_lpinv_nc*s_ + B_tilde_lpinv_nc*A_nc ) Gi = st.concat_cols(Gi, Z_nc) if False: # show_Gi_matrices: pc.print_matrix("G", i, "", Gi) # store iteration.Gi = Gi return Gi
def fourseven(iter_stack): # load matrices Ai = iter_stack.A Bi = iter_stack.B P1i_roc = iter_stack.P1_roc P1i_rpinv = iter_stack.P1_rpinv K2 = roc_hint("B", iter_stack.i, Bi) if mode == "manual" else al.right_ortho_complement(Bi) K1 = al.regular_completion(K2) K = st.concat_cols(K1, K2) assert al.is_regular_matrix(K), "K is not a regular matrix." Bi_tilde = al.custom_simplify(Bi * K1) # unit matrix if myStack.calc_G: Bi_tilde_lpinv = al.left_pseudo_inverse(Bi_tilde) else: Bi_tilde_lpinv = None P1i_tilde_roc = al.custom_simplify(P1i_roc * K1) Zi = al.custom_simplify(P1i_roc * K2) Zi_lpinv = al.Zi_left_pinv_with_restrictions(P1i_rpinv, P1i_tilde_roc, Zi) assert al.is_unit_matrix(Zi_lpinv * Zi), "Zi_lpinv seems to be wrong." # store iter_stack.store_special_case_matrices(Zi, Zi_lpinv, Bi_tilde, Bi_tilde_lpinv, P1i_tilde_roc) return Bi_tilde
def reshape_matrix_columns(P): m0, n0 = P.shape # pick m0 of the simplest lin. independent columns of P: P_new = remove_zero_columns(P) m1, n1 = P_new.shape list_of_cols = matrix_to_vectorlist(P_new) # sort by "complexity" if pinv_optimization=="free_symbols": cols_sorted_by_atoms = sorted( list_of_cols, key=lambda x: x.free_symbols, reverse=False) elif pinv_optimization=="count_ops": cols_sorted_by_atoms = sorted( list_of_cols, key=lambda x: nr_of_ops(x), reverse=False) elif pinv_optimization=="none": cols_sorted_by_atoms = list_of_cols # sort by number of zero entries colvecs_sorted = sorted( cols_sorted_by_atoms, key=lambda x: count_zero_entries(x), reverse=True) # pick m suitable column vectors and add to new matrix A: ---------- A = colvecs_sorted[0] for j in xrange(len(colvecs_sorted)-1): column = colvecs_sorted[j+1] if is_linearly_independent(A,column): A = st.concat_cols(A,column) if st.rnd_number_rank(A)==m1: break assert A.is_square # calculate transformation matrix R: ------------------------------- #R_tilde = sp.Matrix([]) used_cols = [] R = sp.Matrix([]) for k in xrange(m1): new_column_index = k old_column_index = get_column_index_of_matrix(P,A.col(k)) used_cols.append(old_column_index) tmp = sp.zeros(n0,1) tmp[old_column_index] = 1 #R_tilde = st.concat_cols(R_tilde,tmp) R = st.concat_cols(R,tmp) #R=R_tilde # remainder columns of R matrix #m2,n2 = R_tilde.shape m2,n2 = R.shape for l in xrange(n0): if l not in used_cols: R_col = sp.zeros(n0,1) R_col[l] = 1 R = st.concat_cols(R,R_col) m3, n3 = A.shape r2 = st.rnd_number_rank(A) assert m3==r2, "A problem occured in reshaping the matrix." # calculate B matrix: ---------------------------------------------- B = sp.Matrix([]) tmp = P*R for i in xrange(n0-m0): B = st.concat_cols(B,tmp.col(m0+i)) assert is_zero_matrix( (P*R) - st.concat_cols(A,B)), "A problem occured in reshaping the matrix." return A, B, R
def gen_leqs_for_acc_llmd(self, parameter_values=None): """ Create a callable function which returns A, bnum of the linear eqn-system A*ww = bnum, where ww := (ttheta_dd, llmnd). :return: None, set self.leqs_acc_lmd_func """ if self.leqs_acc_lmd_func is not None and self.acc_of_lmd_func is not None: return if parameter_values is None: parameter_values = [] ntt = self.ntt nll = self.nll self.generate_constraints_funcs() # also respect those values, which have been passed to the constructor parameter_values = list(self.parameter_values) + list(parameter_values) # we use mod.eqns here because we do not want ydot-vars inside eqns = st.concat_rows(self.mod.eqns.subs(parameter_values), self.constraints_dd) ww = st.concat_rows(self.mod.ttdd, self.mod.llmd) A = eqns.jacobian(ww) b = -eqns.subz0(ww) # rhs of the leqs Ab = st.concat_cols(A, b) fvars = st.concat_rows(self.mod.tt, self.mod.ttd, self.mod.tau) actual_symbs = Ab.atoms(sp.Symbol) expected_symbs = set(fvars) unexpected_symbs = actual_symbs.difference(expected_symbs) if unexpected_symbs: msg = "Equations can only converted to numerical func if all parameters are passed for substitution. " \ "Unexpected symbols: {}".format(unexpected_symbs) raise ValueError(msg) A_fnc = st.expr_to_func(fvars, A, keep_shape=True) b_fnc = st.expr_to_func(fvars, b) nargs = len(fvars) # noinspection PyShadowingNames def leqs_acc_lmd_func(*args): """ Calculate the matrices of the linear equation system for ttheta and llmd. Assume args = (ttheta, theta_d, ttau) :param args: :return: """ assert len(args) == nargs Anum = A_fnc(*args) bnum = b_fnc(*args) # theese arrays can now be passed to a linear equation solver return Anum, bnum self.leqs_acc_lmd_func = leqs_acc_lmd_func def acc_of_lmd_func(*args): """ Calculate ttheta in dependency of args= (yy, ttau) = ((ttheta, ttheta_d, llmd), ttau) :param args: :return: """ ttheta = args[:ntt] ttheta_d = args[ntt:2 * ntt] llmd = args[2 * ntt:2 * ntt + nll] ttau = args[2 * ntt + nll:] args1 = np.concatenate((ttheta, ttheta_d, ttau)) Anum = A_fnc(*args1) A1 = Anum[:ntt, :ntt] A2 = Anum[:ntt, ntt:] b1 = b_fnc(*args1)[:ntt] ttheta_dd_res = np.linalg.solve(A1, b1 - np.dot(A2, llmd)) return ttheta_dd_res self.acc_of_lmd_func = acc_of_lmd_func
def reshape_matrix_columns(P): m0, n0 = P.shape # pick m0 of the simplest lin. independent columns of P: P_new = remove_zero_columns(P) m1, n1 = P_new.shape list_of_cols = matrix_to_vectorlist(P_new) # sort by "complexity" if pinv_optimization == "free_symbols": cols_sorted_by_atoms = sorted(list_of_cols, key=lambda x: x.free_symbols, reverse=False) elif pinv_optimization == "count_ops": cols_sorted_by_atoms = sorted(list_of_cols, key=lambda x: nr_of_ops(x), reverse=False) elif pinv_optimization == "none": cols_sorted_by_atoms = list_of_cols # sort by number of zero entries colvecs_sorted = sorted(cols_sorted_by_atoms, key=lambda x: count_zero_entries(x), reverse=True) # pick m suitable column vectors and add to new matrix A: ---------- A = colvecs_sorted[0] for j in range(len(colvecs_sorted) - 1): column = colvecs_sorted[j + 1] if is_linearly_independent(A, column): A = st.concat_cols(A, column) if st.rnd_number_rank(A) == m1: break assert A.is_square # calculate transformation matrix R: ------------------------------- #R_tilde = sp.Matrix([]) used_cols = [] R = sp.Matrix([]) for k in range(m1): new_column_index = k old_column_index = get_column_index_of_matrix(P, A.col(k)) used_cols.append(old_column_index) tmp = sp.zeros(n0, 1) tmp[old_column_index] = 1 #R_tilde = st.concat_cols(R_tilde,tmp) R = st.concat_cols(R, tmp) #R=R_tilde # remainder columns of R matrix #m2,n2 = R_tilde.shape m2, n2 = R.shape for l in range(n0): if l not in used_cols: R_col = sp.zeros(n0, 1) R_col[l] = 1 R = st.concat_cols(R, R_col) m3, n3 = A.shape r2 = st.rnd_number_rank(A) assert m3 == r2, "A problem occured in reshaping the matrix." # calculate B matrix: ---------------------------------------------- B = sp.Matrix([]) tmp = P * R for i in range(n0 - m0): B = st.concat_cols(B, tmp.col(m0 + i)) assert is_zero_matrix( (P * R) - st.concat_cols(A, B)), "A problem occured in reshaping the matrix." return A, B, R