def mk_in_space_conditions(space,var_vector): # print "mk_in_space_conditions" # print space # print var_vector basis_matrix = space.matrix().transpose().apply_map(lambda x:QQbar(x).radical_expression()) vec_len,coeff_count = basis_matrix.dimensions() coeffs = MX.mk_symbol_vector(coeff_count,'c'); # print "mk_in_space_condition:", coeff_count, coeffs, vec_len # print basis_matrix #for i in range(coeff_count): # assume(coeffs[0][i],'rational') if coeff_count == 0: # if the space is empty return ([0 != 0],coeffs.list(),var_vector.list()) lhs1 = MX.linear_combination_of(coeffs,basis_matrix).list() lhs2 = var_vector.list() # print "lhs2",lhs2 # print "lhs1",lhs1 conds=map(lambda tup: tup[0] - tup[1] == 0,zip(lhs1,lhs2)) return (conds,coeffs.list(),var_vector.list())
def termination_check(matrix_A,matrix_B_s,matrix_B_w,show_time): t=take_time.TakeTime() mA = matrix_A mB_s = matrix_B_s mB_w = matrix_B_w zvec = MX.mk_symbol_vector(mA.dimensions()[0],"z").transpose() t.print_tdiff("0",show_time) ######################################################### # 1. compute JNF (mD,mP) = mA.jordan_form(QQbar,transformation=true) mPi = mP.inverse() t.print_tdiff("1",show_time) ######################################################### # 2. find factors porresponding to entries in A in BPDQ sB_dims=mB_s.dimensions() wB_dims=mB_w.dimensions() A_dims=mA.dimensions() sB=MX.mk_symbol_matrix(sB_dims[0],sB_dims[1],"bs") wB=MX.mk_symbol_matrix(wB_dims[0],wB_dims[1],"bw") P=MX.mk_symbol_matrix(A_dims[0],A_dims[1],"p") D=MX.mk_symbol_matrix(A_dims[0],A_dims[1],"a") # entries of this matrix must be sorted first when expanding # to make the algorithm work. Hence it is called "a" Q=MX.mk_symbol_matrix(A_dims[0],A_dims[1],"q") sBPDQ=matrix([]) if sB.dimensions()[0] > 0: sBPDQ=(sB*P*D*Q).expand() # .expand() is the same as .apply_map(expand) wBPDQ=matrix([]) if wB.dimensions()[0] > 0: wBPDQ=(wB*P*D*Q).expand() # a matrix entry now has the form (apdq + apdq + apdq + ...), where each # a,p,d,q corresponds to one entry of the original matrices. # # split into operators and operands soBPDQ=map(lambda r: map (lambda c: formula_to_operands(c),r), MX.matrix_to_list(sBPDQ)) woBPDQ=map(lambda r: map (lambda c: formula_to_operands(c),r), MX.matrix_to_list(wBPDQ)) # Now we have a list representation of our matrix where each entry is split # into a tuple (operator,list of arguments). # Here we want to replace the symbolic values of matrix A by some abstract # representation of the Jordan matrix D to the power of some natural number soBPdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(D),MX.abstract_jordan_matrix_power(mD),soBPDQ) woBPdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(D),MX.abstract_jordan_matrix_power(mD),woBPDQ) # combine parts by same absolute eigenvalues and direction for every entry. # an entry. snBPdQ=MX.map_lmatrix(group_entry_summands_by_eigenvalue,soBPdQ) wnBPdQ=MX.map_lmatrix(group_entry_summands_by_eigenvalue,woBPdQ) # Entries now have the form (abs(a_0)(dir(a_0)pdq+dir(a_1)pdq+...) # + abs(a_2)(dir(a_2)pdq+dir(a_3)pdq+...) + ...). # Next the variables b p q are replaced by their values. snbPdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(sB),MX.matrix_to_list(mB_s),snBPdQ) snbpdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(P),MX.matrix_to_list(mP),snbPdQ) snbpdq=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(Q),MX.matrix_to_list(mPi),snbpdQ) wnbPdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(wB),MX.matrix_to_list(mB_w),wnBPdQ) wnbpdQ=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(P),MX.matrix_to_list(mP),wnbPdQ) wnbpdq=MX.replace_symbols_in_lmatrix(MX.matrix_to_list(Q),MX.matrix_to_list(mPi),wnbpdQ) t.print_tdiff("2",show_time) ######################################################### # 3. build the index set and abstract conditions ind=sorted(list(set.union(abs_ev_index_set_from_abstract_lmatrix(snbpdq), abs_ev_index_set_from_abstract_lmatrix(wnbpdq)))) s_abs_conds = mk_abstract_conds(snbpdq) w_abs_conds = mk_abstract_conds(wnbpdq) t.print_tdiff("3",show_time) ######################################################### # 4. build index_z function and conditions for each index and constraint index_z_k,index_cond_c_tuples = mk_index_z(s_abs_conds,w_abs_conds,ind,zvec) t.print_tdiff("4",show_time) ######################################################### # 5. build positive eigenspace and constraints for vectors inside of it #pos_eigenspace = positive_eigenspace_of(mA) pos_eigenspace=positive_generalized_eigenspace_of(mA.change_ring(QQbar)) in_space_conds = mk_in_space_conditions(pos_eigenspace,zvec) t.print_tdiff("5",show_time) ######################################################### # 6. collect all variables and coefficients used c_vars=in_space_conds[1] # coefficients v_vars=in_space_conds[2] # variables (from zvec) allvars=in_space_conds[1]+in_space_conds[2] t.print_tdiff("6",show_time) ######################################################### # 7. compute the maxial satisfying index for each of the k constraints max_indices = max_indices_cond(index_cond_c_tuples,zvec,in_space_conds) if max_indices == None: # when no index function can be found (= no nonterminating # susbspace is found = dimension of S_min is zero) t.print_tdiff("7.0",show_time) print "case 0: terminating" return "terminating" t.print_tdiff("7",show_time) ######################################################### # 8. compute S_min S_min_conds=complex_space_conditions(s_abs_conds,w_abs_conds,ind,zvec,index_cond_c_tuples,max_indices,in_space_conds) S_min = SE.solution_to_space(S_min_conds[0][0],c_vars,v_vars) t.print_tdiff("8",show_time) ######################################################### # 9. compute Q_min and R_min algebraic_base_extends = collect_QQ_extends(mD) Q_min=find_Q_min(S_min,algebraic_base_extends) R_min=VectorSpace(SR,Q_min.degree()).subspace_with_basis(Q_min.basis()) t.print_tdiff("9",show_time) ######################################################### # 10. decide termination if S_min.dimension() == Q_min.dimension(): print "case 1: non-terminating" clean_up(allvars) t.print_tdiff("10.1",show_time) return "non-terminating" if Q_min.dimension() == 0: ######################################################### # 10.2 test whether zero vector is non-terminating if terminates_on_zero(mB_s,mB_w): print "case 2: terminating" clean_up(allvars) t.print_tdiff("10.2",show_time) return "terminating" else: print "case 2: non-terminating" clean_up(allvars) t.print_tdiff("10.2",show_time) return "non-terminating" if 0 < Q_min.dimension() < S_min.dimension(): ######################################################### # 10.3 run termination_check onr educed program print "case 3: reduce" rA,valphas,lin_alpha=find_reduction_of_matrix(mA,Q_min) rB_s,rB_w=apply_reduction_on(mB_s, mB_w, valphas,lin_alpha) clean_up(allvars) t.print_tdiff("10.3",show_time) termination_check(rA,rB_s,rB_w)