def derv(self, y, t): ''' Returns derivative of the state space at a given time-instant ''' mu = get_mu(y, self.oldBasis, self.V, linP, redOrder, count) U = get_U(mu, self.UlinP) #print mu self.oldBasis = U #linPRed = obliqueprojection( U , V , list( linP ), fullD = True ) #yNew = obliqueprojection( U , V , y , fullD = True) temp = 0 sub1 = { state[str(input_list[k])]: (get_input_signals(t))[k] for k in range(len(input_list)) } inputM = numpy.concatenate( (Sym2NumArray(inputm.evalf(subs=sub1)), numpy.matrix(([1.0]))), 0) #print inputM weight = self.weights(y, mu) mutemp = 0 for Mu in range(count): temp = 0 for wei in range(count): temp = temp + weight[wei] * ( (numpy.dot(self.JacRed[Mu][wei], y.reshape( redOrder, 1))).reshape(redOrder, 1) + (numpy.dot(self.BRed[Mu][wei], inputM))) mutemp = mutemp + mu[Mu] * numpy.array(temp) return ((nD(numpy.linalg.inv(nD(U.T, self.V)), mutemp)).reshape(1, redOrder))[0]
def get_STPWL_weights_Bound(self, mu): '''Calculates the numerical bound on the Weighing functions''' P = [ scipy.linalg.solve_sylvester( (Matrix[linpt].linPJac).T, (Matrix[linpt].linPJac), -numpy.eye(order)) for linpt in range(count) ] Phat = [nD(nD((self.V).T, P[linpt]), self.V) for linpt in range(count)] MaxTerm = [] MinTerm = [] wStar = [] for m in range(count): rowSpan = range(count) rowSpan.remove(m) singluarValues = numpy.array([(numpy.array([ max( numpy.linalg.svd(nD(Phat[m], self.JacRed[k][i]), compute_uv=False)) for i in rowSpan ])).sum() for k in range(count)]) MaxTerm.append(numpy.dot(numpy.array(mu), singluarValues)) MinTerm.append(mu[m] * min( numpy.linalg.svd(nD(Phat[m], self.JacRed[m][m]), compute_uv=False))) wStar.append(MaxTerm[m] / (MaxTerm[m] + MinTerm[m])) #print MinTerm [ m ] return wStar
def get_MOR_Jac( Matrix , B ,linP, count): ''' Returns the order reduced Jacobian and new B ''' Ulinp = get_U_linp( Matrix ) V = get_redBasis( 2 , order , redOrder ) linPJac_Red = [ [ nD( nD((Ulinp[k]).T, Matrix[ i ].linPJac ) , V )for i in range( count ) ] for k in range( count ) ] Bnew = [ numpy.concatenate(( B[ linpt ] , Matrix[ linpt ].linPVal - (numpy.dot( Matrix[ i ].linPJac, linP[ i ] )).reshape( order ,1 ) ),1 ) for linpt in range( count ) ] BRed = [ [ nD( ( Ulinp[ k ] ).T, Bnew[ i ] ) for i in range( count ) ] for k in range( count ) ] return linPJac_Red , BRed
def get_U_linp(Matrix): ''' Assumes stable system and returns a stable rowspace for MOR using lyapunov stability criterion. Builds lyapunov function using -I ''' V = get_redBasis(2, order, redOrder) P = [ scipy.linalg.solve_sylvester( (Matrix[linpt].linPJac).T, (Matrix[linpt].linPJac), -numpy.eye(order)) if max(numpy.array(numpy.linalg.eigvals(Matrix[linpt].linPJac))) < 0 else numpy.eye(order, order) for linpt in range(count) ] U = [(nD(numpy.linalg.inv(nD(nD(V.T, P[linpt]), V)), nD(V.T, P[linpt]))).T for linpt in range(count)] return U
def get_STPWL_weights_Bound( self, mu ): '''Calculates the numerical bound on the Weighing functions''' P = [ scipy.linalg.solve_sylvester( ( Matrix[ linpt ].linPJac ).T , ( Matrix[ linpt ].linPJac ) , -numpy.eye( order ) ) for linpt in range( count ) ] Phat = [ nD( nD( (self.V).T, P[ linpt ] ) , self.V ) for linpt in range( count ) ] MaxTerm = [] MinTerm = [] wStar = [] for m in range( count ): rowSpan = range( count ) rowSpan.remove( m ) singluarValues = numpy.array( [ ( numpy.array( [ max( numpy.linalg.svd( nD( Phat[ m ] , self.JacRed[ k ] [ i ] ) , compute_uv= False ) ) for i in rowSpan ]) ).sum() for k in range( count ) ] ) MaxTerm.append( numpy.dot ( numpy.array( mu ) , singluarValues ) ) MinTerm.append( mu[ m ] * min ( numpy.linalg.svd( nD( Phat[ m ] , self.JacRed[ m ][ m ] ) , compute_uv=False ) ) ) wStar.append( MaxTerm[ m ] / ( MaxTerm[ m ] + MinTerm[ m ] ) ) #print MinTerm [ m ] return wStar
def get_MOR_Jac(Matrix, B, linP, count): ''' Returns the order reduced Jacobian and new B ''' Ulinp = get_U_linp(Matrix) V = get_redBasis(2, order, redOrder) linPJac_Red = [[ nD(nD((Ulinp[k]).T, Matrix[i].linPJac), V) for i in range(count) ] for k in range(count)] Bnew = [ numpy.concatenate( (B[linpt], Matrix[linpt].linPVal - (numpy.dot(Matrix[i].linPJac, linP[i])).reshape(order, 1)), 1) for linpt in range(count) ] BRed = [[nD((Ulinp[k]).T, Bnew[i]) for i in range(count)] for k in range(count)] return linPJac_Red, BRed
def obliqueprojection(rowspace, columnspace, points, fullD=False): ''' Returns the result of the oblique projection with a given rowspace and columnpsace of the projection. The input can be a single vector or a list of vectors. The result is returned in lower dimension unless full dimension is asked for''' proj = nD(numpy.linalg.inv(nD(rowspace.T, columnspace)), rowspace.T) if (type(points) == list): if not fullD: return [nD(proj, point) for point in points] else: return [nD(columnspace, nD(proj, point)) for point in points] else: if not fullD: return nD(proj, points) else: return nD(columnspace, nD(proj, points))
def obliqueprojection( rowspace, columnspace, points, fullD = False): ''' Returns the result of the oblique projection with a given rowspace and columnpsace of the projection. The input can be a single vector or a list of vectors. The result is returned in lower dimension unless full dimension is asked for''' proj = nD( numpy.linalg.inv( nD( rowspace.T , columnspace ) ) , rowspace.T ) if ( type( points ) == list ) : if not fullD: return [ nD( proj , point ) for point in points ] else : return [ nD( columnspace, nD( proj , point ) ) for point in points ] else: if not fullD: return nD( proj , points ) else : return nD( columnspace, nD(proj , points ) )
def controlability( B, A ): ''' Returns the controllability matrix and also checks its rank returns False : if rank deficient True : if full rank ''' start = [ B ] order = (shape( A ))[ 0 ] for i in range( order -1 ): start.append( nD( A, start[ -1 ] ) ) cont = nC( start,1 ) if ( matrix_rank( cont ) < order ): return cont, False else : return cont, True
def derv(self, y , t ): ''' Returns derivative of the state space at a given time-instant ''' mu = get_mu(y ,self.oldBasis, self.V , linP ,redOrder , count ) U = get_U( mu , self.UlinP ) #print mu self.oldBasis = U #linPRed = obliqueprojection( U , V , list( linP ), fullD = True ) #yNew = obliqueprojection( U , V , y , fullD = True) temp = 0 sub1 = { state[ str( input_list[ k ] ) ] : (get_input_signals( t ))[ k ] for k in range( len( input_list ) ) } inputM = numpy.concatenate( (Sym2NumArray( inputm.evalf( subs = sub1) ) , numpy.matrix( ([ 1.0 ]) ) ) , 0) #print inputM weight = self.weights( y, mu ) mutemp = 0 for Mu in range( count ): temp = 0 for wei in range(count): temp = temp + weight[ wei ] * ( (numpy.dot( self.JacRed[ Mu ] [ wei ] , y.reshape( redOrder , 1 ) )).reshape( redOrder ,1 ) + (numpy.dot( self.BRed[ Mu ][ wei ], inputM ) ) ) mutemp = mutemp + mu[ Mu ] * numpy.array( temp ) return ( ( nD( numpy.linalg.inv( nD( U.T , self.V ) ) , mutemp ) ).reshape( 1, redOrder ) ) [ 0 ]
def controlability(B, A): ''' Returns the controllability matrix and also checks its rank returns False : if rank deficient True : if full rank ''' start = [B] order = (shape(A))[0] for i in range(order - 1): start.append(nD(A, start[-1])) cont = nC(start, 1) if (matrix_rank(cont) < order): return cont, False else: return cont, True
def observability( C , A ): ''' Checks for the observability of the system. Returns: Observability matrix True : if full rank False : if rank deficient ''' start = [ C ] order = (shape( A ))[ 0 ] for i in range( order - 1 ) : start.append( nD( start[ -1 ], A ) ) obs = nC( start , 0 ) if( matrix_rank( obs) < order ) : return obs, False else: return obs, True
def observability(C, A): ''' Checks for the observability of the system. Returns: Observability matrix True : if full rank False : if rank deficient ''' start = [C] order = (shape(A))[0] for i in range(order - 1): start.append(nD(start[-1], A)) obs = nC(start, 0) if (matrix_rank(obs) < order): return obs, False else: return obs, True
def KBasisContObs( check_A, check_B, check_C ): ''' This produces the Kalman Basis needed for a kalman decomposition of the system, which is used for a minimal realization of the state space Using a different algorithm than the one previously mentioned. This algorithm checks for controllability and then moves over to observability ''' check_cont , bool_cont = controlability( check_B , check_A ) check_obs, bool_obs = observability( check_C, check_A ) range_cont = columspace( check_cont ) null_obs = nullspace( check_obs ) if bool_obs and bool_cont: print " Minimal realization already" return numpy.eye( max( shape( check_A ) ) ), max( shape( check_A ) ) , max( shape( check_A ) ),max( shape( check_A ) ),max( shape( check_A ) ) else: Cont_A, Cont_B , Cont_C , Cont_col = ContSpace( check_A, check_B, check_C,False) #print Cont_A, Cont_B , Cont_C # Stage I : Checking for Controllablity #------------------------------------- C = matrix_rank( range_cont ) ACont,BCont, CCont = Cont_A[ :C , :C] , Cont_B[ :C , : ],Cont_C[ : , :C ] AUncont, BUncont, CUncont = Cont_A[ C: , C: ] ,Cont_B[ C: , : ], Cont_C[ :, C: ] # print AUncont, BUncont, CUncont # Stage II : checking for Observability #------------------------------------- # Stage II ( a ) : Checking for Observablity of Controllable states #-------------------------------------------------------------------- check_obs , bool_obs = observability ( CCont, ACont ) ObsACont, ObsBCont, ObsCCont , ObsCont_row = ObsSpace( ACont, BCont , CCont ,False ) # Observable from Controllable #print ObsACont, ObsBCont, ObsCCont O = matrix_rank( check_obs ) AObsCont,BObsCont, CObsCont = ObsACont[ :O , :O],ObsBCont[ :O , : ] , ObsCCont[ : , :O ] # Stage II ( b ) : Checking for Observability of Uncontrollable states #--------------------------------------------------------------------- check_obs , bool_obs = observability ( CUncont, AUncont ) ObsAUncont, ObsBUncont, ObsCUncont , ObsUncont_row = ObsSpace( AUncont, BUncont , CUncont ,False ) # Observable from Uncontrollable # print ObsAUncont, ObsBUncont, ObsCUncont O = matrix_rank( check_obs ) AObsUncont, BOBsUncont, CObsUncont = ObsAUncont[ :O , :O] ,ObsBUncont[ :O , : ] , ObsCUncont[ : , :O ] # Stage III : Putting it all together, finding the basis of transformation #--------------------------------------------------------------------------- Z1 = numpy.matrix( numpy.zeros( ( shape( nI(ObsCont_row) ) [ 0 ] , shape( nI(ObsUncont_row) ) [ 1 ]) ) ) Z2 = numpy.matrix( numpy.zeros( ( shape( nI(ObsUncont_row) ) [ 0 ] , shape( nI(ObsCont_row) ) [ 1 ]) ) ) PO = nC( ( nC( (nI(ObsCont_row),Z1) ,1 ) , nC( (Z2,nI(ObsUncont_row)) ,1 ) ),0 ) Kbasis = nD( PO , nI(Cont_col) ) # Truncate output : AObsCont, BObsCont, CObsCont return Kbasis.I , max( shape( AObsCont ) ) , max( shape(BObsCont) ), max( shape( CObsCont ) )
def get_U_linp( Matrix ): ''' Assumes stable system and returns a stable rowspace for MOR using lyapunov stability criterion. Builds lyapunov function using -I ''' V = get_redBasis( 2 , order , redOrder ) P = [ scipy.linalg.solve_sylvester( ( Matrix[ linpt ].linPJac ).T , ( Matrix[ linpt ].linPJac ) , -numpy.eye( order ) ) if max( numpy.array ( numpy.linalg.eigvals( Matrix[ linpt ].linPJac) ) ) < 0 else numpy.eye( order ,order ) for linpt in range( count ) ] U = [ ( nD( numpy.linalg.inv(nD( nD( V.T, P[ linpt ] ) , V ) ) , nD( V.T , P[ linpt ] ) ) ).T for linpt in range( count ) ] return U
def KBasisContObs(check_A, check_B, check_C): ''' This produces the Kalman Basis needed for a kalman decomposition of the system, which is used for a minimal realization of the state space Using a different algorithm than the one previously mentioned. This algorithm checks for controllability and then moves over to observability ''' check_cont, bool_cont = controlability(check_B, check_A) check_obs, bool_obs = observability(check_C, check_A) range_cont = columspace(check_cont) null_obs = nullspace(check_obs) if bool_obs and bool_cont: print " Minimal realization already" return numpy.eye(max(shape(check_A))), max(shape(check_A)), max( shape(check_A)), max(shape(check_A)), max(shape(check_A)) else: Cont_A, Cont_B, Cont_C, Cont_col = ContSpace(check_A, check_B, check_C, False) #print Cont_A, Cont_B , Cont_C # Stage I : Checking for Controllablity #------------------------------------- C = matrix_rank(range_cont) ACont, BCont, CCont = Cont_A[:C, :C], Cont_B[:C, :], Cont_C[:, :C] AUncont, BUncont, CUncont = Cont_A[C:, C:], Cont_B[C:, :], Cont_C[:, C:] # print AUncont, BUncont, CUncont # Stage II : checking for Observability #------------------------------------- # Stage II ( a ) : Checking for Observablity of Controllable states #-------------------------------------------------------------------- check_obs, bool_obs = observability(CCont, ACont) ObsACont, ObsBCont, ObsCCont, ObsCont_row = ObsSpace( ACont, BCont, CCont, False) # Observable from Controllable #print ObsACont, ObsBCont, ObsCCont O = matrix_rank(check_obs) AObsCont, BObsCont, CObsCont = ObsACont[:O, : O], ObsBCont[:O, :], ObsCCont[:, : O] # Stage II ( b ) : Checking for Observability of Uncontrollable states #--------------------------------------------------------------------- check_obs, bool_obs = observability(CUncont, AUncont) ObsAUncont, ObsBUncont, ObsCUncont, ObsUncont_row = ObsSpace( AUncont, BUncont, CUncont, False) # Observable from Uncontrollable # print ObsAUncont, ObsBUncont, ObsCUncont O = matrix_rank(check_obs) AObsUncont, BOBsUncont, CObsUncont = ObsAUncont[:O, : O], ObsBUncont[: O, :], ObsCUncont[:, : O] # Stage III : Putting it all together, finding the basis of transformation #--------------------------------------------------------------------------- Z1 = numpy.matrix( numpy.zeros((shape(nI(ObsCont_row))[0], shape(nI(ObsUncont_row))[1]))) Z2 = numpy.matrix( numpy.zeros((shape(nI(ObsUncont_row))[0], shape(nI(ObsCont_row))[1]))) PO = nC((nC((nI(ObsCont_row), Z1), 1), nC((Z2, nI(ObsUncont_row)), 1)), 0) Kbasis = nD(PO, nI(Cont_col)) # Truncate output : AObsCont, BObsCont, CObsCont return Kbasis.I, max(shape(AObsCont)), max(shape(BObsCont)), max( shape(CObsCont))