예제 #1
0
def qrm3(X, maxiter=15000, debug=False):
    """
    First compute similar matrix in Hessenberg form, then compute the
    Eigenvalues and Eigenvectors using the QR-Method.

    Parameters:
        - X: square numpy ndarray.
    Returns:
        - Eigenvalues of A.
        - Eigenvectors of A.
    """
    n, m = X.shape
    assert n == m

    # First stage: transform to upper Hessenberg-matrix.
    T = lin.hessenberg(X)

    conv = False
    k = 0

    # Second stage: perform QR-transformations.
    while (not conv) and (k < maxiter):
        k += 1
        Q, R = helpers.qr_factorize(T - T[n - 1, n - 1] * np.eye(n))
        T = R.dot(Q) + T[n - 1, n - 1] * np.eye(n)

        conv = np.alltrue(np.isclose(np.tril(T, k=-1), np.zeros((n, n))))

    if not conv:
        warnings.warn("Convergence was not reached. Consider raising maxiter.")
    if debug:
        return k
    Evals = T.diagonal()
    order = np.abs(Evals).argsort()[::-1]
    return Evals[order], Q[order, :]
예제 #2
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Parameters:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal S_i
            block is 1x1 or 2x2.

    Returns:
        ((n,) ndarray): The eigenvalues of A.
    """
    n=np.shape(A)[0]
    S=la.hessenberg(A)
    for k in range(N):
        Q,R=la.qr(S)
        S=R@Q
    eigs=[]
    i=0
    while i<n:
        if S[i,i] == S[-1,-1] or np.abs(S[i+1,i])<tol:
            eigs.append(S[i,i])
        elif np.shape(S[i]) == (2,2):
            sqrt=cmath.sqrt((S[i,i][0,0]+S[i,i][1,1])**2-4*(S[i,i][0,0]*S[i,i][1,1]-(S[i,i][1,0]*S[i,i][0,1])))/(2*S[i,i][0,0])
            eigs.append((S[i,i][0,0]+S[i,i][1,1])/(2*S[i,i][0,0])+sqrt)
            eigs.append((S[i,i][0,0]+S[i,i][1,1])/(2*S[i,i][0,0])-sqrt)
            i=i+1
        i=i+1
    return eigs
예제 #3
0
def QR_algorithm(A, niter, tol):
    """Return the eigenvalues of A using the QR algorithm."""
    A = la.hessenberg(A)
    m, n = A.shape
    eigen_vals = []
    for x in xrange(0, niter):
        Q, R = la.qr(A)
        A_new = np.dot(R, Q)
        A = A_new

    x = 0
    while x < m:
        if x == m - 1:
            eigen_vals.append(A[x][x])
            break
        elif abs(A[x + 1][x]) < tol:
            eigen_vals.append(A[x][x])
        else:
            a = A[x][x]
            b = A[x][x + 1]
            c = A[x + 1][x]
            d = A[x + 1][x + 1]
            t = a + d
            d = a * d - b * c
            eigen_vals.append(t / 2.0 + scimath.sqrt(t**2 / (4 - d)))
            eigen_vals.append(t / 2.0 - scimath.sqrt(t**2 / (4 - d)))
            x += 1

        x += 1

    return eigen_vals
예제 #4
0
def eig(A, normal = False, iter = 100):
	'''Finds eigenvalues of an nxn array A. If A is normal, QRalg.eig 
	may also return eigenvectors.
	
	Parameters
	----------
	A :  nxn array
	     May be real or complex
	normal : bool, optional
		     Set to True if A is normal and you want to calculate
		     the eigenvectors.
	iter : positive integer, optional
			
	Returns
	-------
	v : 1xn array of eigenvectors, may be real or complex
	Q : (only returned if normal = True) 
		nxn array whose columns are eigenvectors, s.t. A*Q = Q*diag(v)
		real if A is real, complex if A is complex
	
	For more on the QR algorithm, see Eigenvalue Solvers lab.
	'''
	def getSchurEig(A):
		#Find the eigenvalues of a Schur form matrix. These are the 
		#elements on the main diagonal, except where there's a 2x2 
		#block on the main diagonal. Then we have to find the 
		#eigenvalues of that block.
		D = sp.diag(A).astype(complex)
		#Find all the 2x2 blocks:
		LD = sp.diag(A,-1)
		index = sp.nonzero(abs(LD)>.01)[0] #is this a good tolerance?
		#Find the eigenvalues of those blocks:
		a = 1
		b = -D[index]-D[index+1]
		c = D[index]*D[index+1] - A[index,index+1]*LD[index]
		discr = sp.sqrt(b**2-4*a*c)
		#Fill in vector D with those eigenvalues
		D[index] = (-b + discr)/(2*a)
		D[index+1] = (-b - discr)/(2*a)
		return D

	n,n = A.shape
	I = sp.eye(n)
	A,Q = hessenberg(A,True)
	if normal == False:
		for i in sp.arange(iter):
			s = A[n-1,n-1].copy()
			Qi,R = la.qr(A-s*I)
			A = sp.dot(R,Qi) + s*I
		v = getSchurEig(A)
		return v
	
	elif normal == True:
		for i in sp.arange(iter):
			s = A[n-1,n-1].copy()
			Qi,R = la.qr(A-s*I)
			A = sp.dot(R,Qi) + s*I
			Q = sp.dot(Q,Qi)
		v = sp.diag(A)
		return v,Q
예제 #5
0
파일: test_decomp.py 프로젝트: minrk/scipy
 def test_simple_complex(self):
     a = [[-149, -50,-154],
          [ 537, 180j, 546],
          [ -27j,  -9, -25]]
     h,q = hessenberg(a,calc_q=1)
     h1 = dot(transp(conj(q)),dot(a,q))
     assert_array_almost_equal(h1,h)
예제 #6
0
파일: solutions.py 프로젝트: tkchris93/ACME
def QR_algorithm(A,niter,tol):
    """Return the eigenvalues of A using the QR algorithm."""
    H = la.hessenberg(A)
    for i in xrange(niter):
        Q,R = la.qr(H)
        H = np.dot(R,Q)
    S = H
    print S
    eigenvalues = []
    i = 0
    while i < S.shape[0]:
        if i == S.shape[0]-1:
            eigenvalues.append(S[i,i])
        elif abs(S[i+1,i]) < tol:
            eigenvalues.append(S[i,i])
        else:
            a = S[i,i]
            b = S[i,i+1]
            c = S[i+1,i]
            d = S[i+1,i+1]
            B = -1*(a+d)
            C = a*d-b*c
            eigen_plus = (-B + sm.sqrt(B**2 - 4*C))/2.
            eigen_minus = (-B - sm.sqrt(B**2 - 4*C))/2.
            
            eigenvalues.append(eigen_plus)
            eigenvalues.append(eigen_minus)
            i+=1
        i+=1
    return eigenvalues
예제 #7
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Parameters:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal S_i
            block is 1x1 or 2x2.

    Returns:
        ((n,) ndarray): The eigenvalues of A.
    """

    m, n = A.shape  #initialize m,n
    S = la.hessenberg(A)  #Put A in upper Hessenberg form
    for k in range(N):
        Q, R = la.qr(S)  #Get QR decomposition of A
        S = R.dot(Q)  #Recombine R[k] and Q[k] into A[k+1]
    eigenvalues = []  #initialize empty list of eigenvalues
    i = 0
    while i < n:
        if i == n - 1 or abs(S[i + 1][i] < tol):
            eigenvalues.append(S[i][i])
        else:  #use quadratic formula to get two eigenvalues
            b = -1 * (S[i, i] + S[i + 1, i + 1])
            c = (S[i, i] * S[i + 1, i + 1] - S[i, i + 1] * S[i + 1, i])
            eigenvalues.append((-1 * b + cmath.sqrt(b**2 - 4 * c)) / 2)
            eigenvalues.append((-1 * b - cmath.sqrt(b**2 - 4 * c)) / 2)
            i += 1
        i += 1  #move to the next S[i]
    return np.array(eigenvalues)  #return array of eigenvalues
예제 #8
0
def QR_Wilkinson(A):
    eig = []
    A = linalg.hessenberg(A)
    QR_steps = 0
    for i in range(A.shape[0], 0, -1):
        k = 0
        while ((abs(A[i - 2, i - 1]) > epsilon *
                (abs(A[i - 2, i - 1] + A[i - 1, i - 1])))):
            k = k + 1
            if k > 1000:
                print("Endless")
                break
            A_u = A[i - 2:i, i - 2:i]
            ew, ev = np.linalg.eig(A_u)

            if (abs(ew[0] - A_u[1, 1]) > abs(ew[1] - A_u[1, 1])):
                k = ew[1]
            else:
                k = ew[0]
            A = A - np.identity(A.shape[0]) * k
            Q, R = np.linalg.qr(A)
            QR_steps = QR_steps + 1
            A = R @ Q + np.identity(A.shape[0]) * k
        eig.append(A[i - 1, i - 1])

    return eig, QR_steps
예제 #9
0
def eig(A, normal = False, iter = 100):
	'''Finds eigenvalues of an nxn array A. If A is normal, QRalg.eig 
	may also return eigenvectors.
	
	Parameters
	----------
	A :  nxn array
	     May be real or complex
	normal : bool, optional
		     Set to True if A is normal and you want to calculate
		     the eigenvectors.
	iter : positive integer, optional
			
	Returns
	-------
	v : 1xn array of eigenvectors, may be real or complex
	Q : (only returned if normal = True) 
		nxn array whose columns are eigenvectors, s.t. A*Q = Q*diag(v)
		real if A is real, complex if A is complex
	
	For more on the QR algorithm, see Eigenvalue Solvers lab.
	'''
	def getSchurEig(A):
		#Find the eigenvalues of a Schur form matrix. These are the 
		#elements on the main diagonal, except where there's a 2x2 
		#block on the main diagonal. Then we have to find the 
		#eigenvalues of that block.
		D = sp.diag(A).astype(complex)
		#Find all the 2x2 blocks:
		LD = sp.diag(A,-1)
		index = sp.nonzero(abs(LD)>.01)[0] #is this a good tolerance?
		#Find the eigenvalues of those blocks:
		a = 1
		b = -D[index]-D[index+1]
		c = D[index]*D[index+1] - A[index,index+1]*LD[index]
		discr = sp.sqrt(b**2-4*a*c)
		#Fill in vector D with those eigenvalues
		D[index] = (-b + discr)/(2*a)
		D[index+1] = (-b - discr)/(2*a)
		return D

	n,n = A.shape
	I = sp.eye(n)
	A,Q = hessenberg(A,True)
	if normal == False:
		for i in sp.arange(iter):
			s = A[n-1,n-1].copy()
			Qi,R = la.qr(A-s*I)
			A = sp.dot(R,Qi) + s*I
		v = getSchurEig(A)
		return v
	
	elif normal == True:
		for i in sp.arange(iter):
			s = A[n-1,n-1].copy()
			Qi,R = la.qr(A-s*I)
			A = sp.dot(R,Qi) + s*I
			Q = sp.dot(Q,Qi)
		v = sp.diag(A)
		return v,Q
예제 #10
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Parameters:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal S_i
            block is 1x1 or 2x2.

    Returns:
        ((n,) ndarray): The eigenvalues of A.
    """
    m, n = A.shape
    S = la.hessenberg(A)
    for k in range(N):
        Q, R = la.qr(S)
        S = R @ Q
    eigs = []
    i = 0
    while i < n:
        if i == n - 1 or abs(S[i + 1][i]) < tol:
            eigs.append(S[i][i])
        else:
            a = S[i][i]
            b = S[i][i + 1]
            c = S[i + 1][i]
            d = S[i + 1][i + 1]
            e1 = ((a + d) + cmath.sqrt((a + d)**2 - 4 * (a * d - b * c))) / 2
            e2 = ((a + d) - cmath.sqrt((a + d)**2 - 4 * (a * d - b * c))) / 2
            eigs.append(e1)
            eigs.append(e2)
            i += 1
        i += 1
    return eigs
예제 #11
0
 def test_simple(self):
     a = [[-149, -50, -154], [537, 180, 546], [-27, -9, -25]]
     h1 = [[-149.0000, 42.2037, -156.3165],
           [-537.6783, 152.5511, -554.9272], [0, 0.0728, 2.4489]]
     h, q = hessenberg(a, calc_q=1)
     assert_array_almost_equal(dot(transp(q), dot(a, q)), h)
     assert_array_almost_equal(h, h1, decimal=4)
예제 #12
0
 def test_random_complex(self):
     n = 20
     for k in range(2):
         a = random([n,n])+1j*random([n,n])
         h,q = hessenberg(a,calc_q=1)
         h1 = dot(transp(conj(q)),dot(a,q))
         assert_array_almost_equal(h1,h)
예제 #13
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Parameters:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal S_i
            block is 1x1 or 2x2.

    Returns:
        ((n,) ndarray): The eigenvalues of A.
    """
    m, n = A.shape
    S = la.hessenberg(A)
    for k in range(N):
        Q, R = la.qr(S)
        S = R @ Q
    eigs = []
    i = 0
    while i < n:
        if i == len(S) - 1 or S[i + 1][i] < tol:
            eigs.append(S[i][i])
        else:
            b = -(S[i][i] + S[i + 1][i + 1])
            c = la.det(S[i:i + 2, i:i + 2])
            eigs.append((-b + cmath.sqrt(b**2 - 4 * c)) / 2)
            eigs.append((-b - cmath.sqrt(b**2 - 4 * c)) / 2)
            i = i + 1
        i = i + 1

    return eigs
예제 #14
0
 def test_simple_complex(self):
     a = [[-149, -50,-154],
          [ 537, 180j, 546],
          [ -27j,  -9, -25]]
     h,q = hessenberg(a,calc_q=1)
     h1 = dot(transp(conj(q)),dot(a,q))
     assert_array_almost_equal(h1,h)
예제 #15
0
    def importModel(self):
        """
        Import open-loop SISO model (.jac file)
        include simplified ameloadj code that doesn't look into other auxiliary files (e.g. .la)
        """

        # turn off inputs
        self.inputList.clear()
        self.outputList.clear()
        self.resList.clear()
        self.tLinList.clear()
        self.inputList.setEnabled(False)
        self.outputList.setEnabled(False)
        self.resList.setEnabled(False)
        self.tLinList.setEnabled(False)

        # file selection widget
        cwd = os.path.dirname(self.filename)
        dlg = QtWidgets.QFileDialog(self, 'Select .jac file of open-loop, SISO model',
                                    cwd, '*.jac*')
        dlg.exec_()
        file = dlg.selectedFiles()
        if len(file) == 0:
            # loading canceled, back to start
            self.initUI()
            return
        else:
            # load file (using simplified version of ameloadj to restrict parsing to .jac file only)
            try:
                A, B, C, D = ameloadjlight(file[0])
                B = B[0]
                D = D[0]
                A = np.matrix(A)
                B = np.matrix(B)
                C = np.matrix(C)
                D = np.matrix(D)
                # Use Hessenberg decomposition to improve computation robustness for large systems

                H, Q = hessenberg(A, calc_q=True)
                H = np.matrix(H)
                Q = np.matrix(Q)
                ol = signal.lti(H, Q.H * B, C * Q, D)
                # ol = signal.lti(A, B, C, D)

                # save and plot
                self.OL = ol
                self.matchIO = 1
                self.light.setLight(2)
                self.resList.addItem(os.path.basename(file[0]))
                self.message.setText("File imported successfully")

                # move to next step with checkPlant
                self.checkPlant()

            except:
                # show error message and return
                errorDlg = ErrorDlg(4, os.path.basename(file[0]))
                errorDlg.exec_()
                self.initUI()
                return
예제 #16
0
 def test_simple2(self):
     a = [[1, 2, 3, 4, 5, 6, 7], [0, 2, 3, 4, 6, 7,
                                  2], [0, 2, 2, 3, 0, 3, 2],
          [0, 0, 2, 8, 0, 0, 2], [0, 3, 1, 2, 0, 1, 2],
          [0, 1, 2, 3, 0, 1, 0], [0, 0, 0, 0, 0, 1, 2]]
     h, q = hessenberg(a, calc_q=1)
     assert_array_almost_equal(dot(transp(q), dot(a, q)), h)
예제 #17
0
 def test_random_complex(self):
     n = 20
     for k in range(2):
         a = random([n, n]) + 1j * random([n, n])
         h, q = hessenberg(a, calc_q=1)
         h1 = dot(transp(conj(q)), dot(a, q))
         assert_array_almost_equal(h1, h)
예제 #18
0
def QR_algorithm(A, niter, tol):
    """Return the eigenvalues of A using the QR algorithm."""
    A = la.hessenberg(A).astype(float)
    eigenvalues = []
    n = 0
    for i in xrange(1, niter):
        Q, R = la.qr(A)
        A = np.dot(np.dot(la.inv(Q), A), Q)
    while n < np.shape(A)[1]:
        if n == np.shape(A)[1] - 1:
            eigenvalues.append(A[n][n])
        elif abs(A[n + 1][n]) < tol:
            eigenvalues.append(A[n][n])
        else:
            two_two = A[n:n + 2, n:n + 2]
            a = 1
            b = -1 * (two_two[0][0] + two_two[1][1])
            c = la.det(two_two)
            x = (-b + (scimath.sqrt(b**2 - 4 * a * c))) / 2
            x2 = (-b - (scimath.sqrt(b**2 - 4 * a * c))) / 2
            eigenvalues.append(x)
            eigenvalues.append(x2)
            n += 1
        n += 1
    return eigenvalues
예제 #19
0
    def calcOpenLoop(self):
        """
        compute open-loop response from closed-loop in state-space format
        :return:
        """
        # compute open-loop response
        cl = self.CL
        (a, b, c, d) = (cl.A, cl.B, cl.C, cl.D)
        a = np.matrix(a)
        b = np.matrix(b)
        c = np.matrix(c)
        d = np.matrix(d)

        tmp = float(inv(1 - d))
        A = a + b * c * tmp
        B = b + b * d * tmp
        C = c * tmp
        D = d * tmp

        # Use Hessenberg decomposition to improve computation robustness for large systems
        H, Q = hessenberg(A, calc_q=True)
        H = np.matrix(H)
        Q = np.matrix(Q)
        ol = signal.lti(H, Q.H * B, C * Q, D)
        # ol = signal.lti(A, B, C, D)

        # save
        self.OL = ol

        # move to next step with checkPlant
        self.checkPlant()
예제 #20
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Inputs:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal block
            is 1x1 or 2x2.

    Returns:
        ((n, ) ndarray): The eigenvalues of A.
    """
    """EQUATION 8.7 should have (a+d) instead of ad"""
    m, n = A.shape
    S = la.hessenberg(A)
    for k in xrange(N):
        Q, R = la.qr(S, mode="economic")
        S = R.dot(Q)
    eigs = []
    i = 0
    while i < n:
        if i == n - 1 or np.abs(S[i + 1, i]) < tol:
            eigs.append(S[i, i])
        else:
            a = S[i, i]
            b = S[i, i + 1]
            c = S[i + 1, i]
            d = S[i + 1, i + 1]
            evalue1 = (a + d + sqrt((a + d)**2 - 4 * (a * d - b * c))) / 2
            evalue2 = (a + d - sqrt((a + d)**2 - 4 * (a * d - b * c))) / 2
            eigs.append(evalue1)
            eigs.append(evalue2)
            i += 1  #If s is 2x2 want to skip entire thing
        i += 1
    return eigs
예제 #21
0
 def _construct_hessenberg(self, cutoff):
     """
         Performs the tridiagonalization up to 'cutoff' diagonal elements without computing the transformation matrix
     """
     T = hessenberg(self.A)
     diag = np.diag(T)[:cutoff]
     offdiag = np.diag(T, k=-1)[:cutoff - 1]
     return diag, offdiag
예제 #22
0
 def test(self):
     matrix = mnaMat("2. 0 2 3; 1 4 2 3; 2 5  6 3; 4 5 4 8")
     oH = sc.hessenberg(matrix)
     H = QRAlgorithm.HessenbergReduction(matrix)
     oVa, _ = np.linalg.eig(matrix)
     Va, _ = np.linalg.eig(H)
     assertAbsEqualMatrix(np.sort(oVa), np.sort(Va))
     assertEqualMatrix(H, oH)
예제 #23
0
 def test(self):
     matrix = mnaMat("2. 0 2 3; 1 4 2 3; 2 5 6 3; 4 5 4 8")
     oH = sc.hessenberg(matrix)
     H, U = QRAlgorithm.HessenbergReductionWithReflector(matrix)
     oVa, oVe = np.linalg.eig(matrix)
     Va, Ve = np.linalg.eig(H)
     assertAbsEqualMatrix(H, oH)
     assertAbsEqualMatrix(np.sort(oVa), np.sort(Va))
     assertAbsEqualMatrix(oVe, U.dot(Ve))
예제 #24
0
def main():
    a = np.asmatrix(la.hilbert(4))
    h = tridiag(a)
    h_std = la.hessenberg(a)
    print("Solution:")
    print(h)
    print('\n')
    print("Standard Solution:")
    print(h_std)
예제 #25
0
 def _construct_hessenberg_with_trafo(self, cutoff):
     """
         Performs the tridiagonalization up to 'cutoff' diagonal elements, while also
         computing the transformation matrix
     """
     T, Q = hessenberg(self.A, calc_q=True)
     diag = np.diag(T)[:cutoff]
     offdiag = np.diag(T, k=-1)[:cutoff - 1]
     return diag, offdiag, Q[:, :cutoff]
예제 #26
0
 def test_simple2(self):
     a = [[1,2,3,4,5,6,7],
          [0,2,3,4,6,7,2],
          [0,2,2,3,0,3,2],
          [0,0,2,8,0,0,2],
          [0,3,1,2,0,1,2],
          [0,1,2,3,0,1,0],
          [0,0,0,0,0,1,2]]
     h,q = hessenberg(a,calc_q=1)
     assert_array_almost_equal(dot(transp(q),dot(a,q)),h)
예제 #27
0
 def test_simple(self):
     a = [[-149, -50,-154],
          [ 537, 180, 546],
          [ -27,  -9, -25]]
     h1 = [[-149.0000,42.2037,-156.3165],
           [-537.6783,152.5511,-554.9272],
           [0,0.0728, 2.4489]]
     h,q = hessenberg(a,calc_q=1)
     assert_array_almost_equal(dot(transp(q),dot(a,q)),h)
     assert_array_almost_equal(h,h1,decimal=4)
예제 #28
0
 def test(self):
     random = np.random
     random.seed(_random_seed)
     size = random.randint(10, 50)
     matrix = random.rand(size, size)
     oH = sc.hessenberg(matrix)
     H = QRAlgorithm.HessenbergReduction(matrix)
     oVa, _ = np.linalg.eig(matrix)
     Va, _ = np.linalg.eig(H)
     assertEqualMatrix(H, oH)
     assertAbsEqualMatrix(np.sort(oVa), np.sort(Va))
예제 #29
0
 def test(self):
     random = np.random
     random.seed(_random_seed)
     size = random.randint(10, 50)
     matrix = random.rand(size, size)
     oH = sc.hessenberg(matrix)
     H, U = QRAlgorithm.HessenbergReductionWithReflector(matrix)
     oVa, oVe = np.linalg.eig(matrix)
     Va, Ve = np.linalg.eig(H)
     assertAbsEqualMatrix(np.sort(oVa), np.sort(Va))
     assertAbsEqualMatrix(H, oH)
     assertAbsEqualMatrix(oVe, U.dot(Ve))
예제 #30
0
def qr_algor(A, N, tol):

    m, n = A.shape
    S = la.hessenberg(A)

    for k in range(N):
        Q, R = la.qr(S)

        S = R @ Q

    eigs = []
    i = 0
예제 #31
0
def discrete_lyapunov(A, Q=None):
    """
    Solve the equation :math:`A^T X A + X = -Q`.
    default Q is set to I

    :param A: system matrix
    :type A: np.ndarray | np.matrix | List[List]
    :param Q: matrix
    :type Q: np.ndarray | np.matrix

    :return: the matrix X if there is a solution
    :rtype: np.ndarray | None
    """
    A = np.array(A)
    n = A.shape[0]
    if Q is None:
        Q = np.eye(n)

    # matrix size is not greater than 2 x 2, use _mini_dlyap directly
    if n < 3:
        return _mini_dlyap(A.T, A, Q)

    X = np.zeros(A.shape)
    h, q = hessenberg(A, True)
    t, z, *_ = schur(h)
    w = q @ z
    Q = w.T @ Q @ w

    partition = _partition_mat(t)
    for row in partition:
        for p in row:
            # =====================================================
            # add previous result into Q
            # e.g.
            # X11 is already known, then solve X12.
            # A11^T * X11 * A12 + A11^T * X12 * A22 - X12 = -Q
            #
            # let Q' = Q + A11^T * X11 * A12, get the new equation
            # A11^T * X12 * A22 - X12 = -Q'
            # =====================================================
            Q[p] += _prev_r(X, t)[p]

            i, j = p
            X[p] = _mini_dlyap(t[i, i], t[j, j], Q[p])
    X = w @ X @ w.T

    if config['use_numpy_matrix']:
        return np.mat(X)
    else:
        return X
예제 #32
0
def ss2bode(A, B, C, D, fmin=0.01, fmax=100, tol=1.0e-9, N=200):
    '''
    Compute gain and phase for Bode plot from state space representation of a SISO model
    tol = threshold for assuming zero gain
    :return: freqHz, gaindB, phasedeg (Inf and NaN values are excluded)

    Note: might return empty lists if frequency response is all NaN (poor conditioning). To be
    improved with matrix balancing and Scipy 0.19
    '''

    # TO DO: implement balancing for large systems (not available in scipy 0.13.1, see linalg.matrix_balancing)
    H, Q = hessenberg(A, calc_q=True)
    H = np.matrix(H)
    Q = np.matrix(Q)

    # define frequency range for plot
    n1 = np.log10(fmin)
    n2 = np.log10(fmax)

    freqHz = np.logspace(n1, n2, N)
    p = 2 * np.pi * freqHz * 1j
    gaindB = np.zeros(N)
    phasedeg = np.zeros(N)
    n = len(A)
    for i in range(0, len(p)):
        # h = C * linalg.inv(p[i] * np.eye(n) - A) * B + D                      # method 1: limited robustness for n>>1
        # h = D - (C * Q) * linalg.inv(H - p[i] * np.eye(n)) * (Q.T * B)        # method 2: much better
        x = solve(H - p[i] * np.eye(n), Q.T * B)  # method 3: same as 2??
        h = D - (C * Q) * x
        if np.abs(h)[0][0] < tol or np.isnan(h[0][0]):
            gaindB[i] = -np.inf
            phasedeg[i] = 0.
        else:
            gaindB[i] = 20 * np.log10(np.abs(h)[0][0])
            phasedeg[i] = np.angle(h, deg=True)[0][0]
    phasedeg = np.unwrap(phasedeg * np.pi / 180, discont=np.pi) * 180 / np.pi

    # restrict output to non-NaN data that would make other function fail
    i = np.nonzero(np.isfinite(gaindB))
    gaindB = gaindB[i]
    phasedeg = phasedeg[i]
    freqHz = freqHz[i]
    i = np.nonzero(np.isfinite(phasedeg))
    gaindB = gaindB[i]
    phasedeg = phasedeg[i]
    freqHz = freqHz[i]

    return freqHz, gaindB, phasedeg
예제 #33
0
def qrm2():
    """
    Create generator for transformed matrices after applying the QR-Method.

    Yields:
        - T: 2D-numpy array. Similar matrix to X.
    """
    # First stage: transform to upper Hessenberg-matrix.
    T = lin.hessenberg(X)

    k = 0
    # Second stage: perform QR-transformations.
    while k < 5000:
        k += 1
        Q, R = np.linalg.qr(T)
        T = R.dot(Q)
        yield T
예제 #34
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Parameters:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal S_i
            block is 1x1 or 2x2.

    Returns:
        ((n,) ndarray): The eigenvalues of A.
    """

    m, n = np.shape(A)
    #put A in upper Hessenberg form
    S = la.hessenberg(A)
    for k in range(N):
        #get the QR decomposition of Ak
        Q, R = la.qr(S)
        #Recombine Rk and Qk into Ak+1
        S = R @ Q

    #initialize an empty list of eigenvalues
    eigs = []
    i = 0
    while i < n:
        if i == n - 1 or S[i + 1, i] < tol:
            eigs.append(S[i, i])
        else:
            eig1 = ((S[i, i] + S[i + 1, i + 1]) + cmath.sqrt(
                (S[i, i] + S[i + 1, i + 1])**2 - 4 *
                (S[i, i] * S[i + 1, i + 1] - S[i, i + 1] * S[i + 1, i]))) / 2
            eig2 = ((S[i, i] + S[i + 1, i + 1]) - cmath.sqrt(
                (S[i, i] + S[i + 1, i + 1])**2 - 4 *
                (S[i, i] * S[i + 1, i + 1] - S[i, i + 1] * S[i + 1, i]))) / 2
            eigs.append(eig1)
            eigs.append(eig2)
            i += 1
        #move to next Si
        i += 1

    return eigs
예제 #35
0
def qrm3():
    """
    First compute similar matrix in Hessenberg form, then compute the
    Eigenvalues and Eigenvectors using the accelerated QR-Method.

    Yields:
        * T - 2D numpy array of current iteration step.
    """
    # First stage: transform to upper Hessenberg-matrix.
    T = lin.hessenberg(X)
    k = 0
    n, _ = X.shape

    # Second stage: perform QR-transformations.
    while k < 5000:
        k += 1
        Q, R = np.linalg.qr(T - T[n-1, n-1] * np.eye(n))
        T = R.dot(Q) + T[n-1, n-1] * np.eye(n)

        yield T
예제 #36
0
    def calcClosedLoop(self):
        """
        load inputs from linearization and make closed-loop transfer function
        """
        # load selected .jac file
        res = self.resList.currentText()
        tlin = self.tLinList.currentText()
        for i in range(0, len(self.jacFiles)):
            if self.jacRes[i] == res and self.jacTlin[i] == tlin:
                file = self.jacFiles[i]

        data = self.window()
        dir = os.path.dirname(data.appObject.execDir().decode('utf-8'))
        [A, B, C, D, x, u, y, t, xvals] = ameloadjNoprint(dir, file)
        B = B[0]
        D = D[0]
        A = np.matrix(A)
        B = np.matrix(B)
        C = np.matrix(C)
        D = np.matrix(D)

        # retrieve selected input and output
        tu = self.inputList.currentText()
        iu = u.index(tu)
        ty = self.outputList.currentText()
        iy = y.index(ty)

        # reshape to SISO model from selected input and output
        B = B[:, iu]
        C = C[iy, :]
        D = np.matrix(D[iy, iu])

        # Use Hessenberg decomposition to improve computation robustness for large systems
        H, Q = hessenberg(A, calc_q=True)
        H = np.matrix(H)
        Q = np.matrix(Q)
        cl = signal.lti(H, Q.H * B, C * Q, D)

        # go to next step
        self.CL = cl
        self.calcOpenLoop()
예제 #37
0
def qr_algorithm(A, N=50, tol=1e-12):
    """Compute the eigenvalues of A via the QR algorithm.

    Inputs:
        A ((n,n) ndarray): A square matrix.
        N (int): The number of iterations to run the QR algorithm.
        tol (float): The threshold value for determining if a diagonal block
            is 1x1 or 2x2.

    Returns:
        ((n, ) ndarray): The eigenvalues of A.
    """
    m,n = A.shape
    S = la.hessenberg(A)

    # TODO: introduce shifts.

    for i in xrange(N):
        Q,R = la.qr(S)
        S = np.dot(R,Q)

    eigs = []
    i = 0

    # Get the eigenvalues of each S_i.
    while i < n:
        if i == n-1:                # 1 x 1 block (final diagonal entry).
            eigs.append(S[i,i])
        elif abs(S[i+1,i]) < tol:   # 1 x 1 block.
            eigs.append(S[i,i])
        else:                       # 2 x 2 block.
            a, b, c, d = S[i:i+2,i:i+2].ravel()
            # Use the quadratic formula.
            B = -1*(a+d)
            C = a*d-b*c
            D = sqrt(B**2 - 4*C)
            eigs += [(-B + D)/2., (-B - D)/2.]
            i += 1
        i += 1
    return np.sort(eigs)
예제 #38
0
def qr_solver(A, niter=1000, tol=1e-3):
    '''
    Calculate the eigenvalues of a matrix A using QR iteration.
    Inputs:
        A -- real square matrix
        niter -- number of QR iterations to run
        tol -- real number. All real numbers with magnitude below we treat as 0
    Returns:
        eigs -- list of real or complex numbers, the eigenvalues of A.
    Note: this code is far from optimized, but considering that the algorithm itself is
          inherently limited in robustness, any extra optimization short of chaning the
          algorithm seems wasted effort.
    '''
    # first calculate the upper hessenberg form of A
    H = la.hessenberg(A)
    
    # perform the QR iterations
    for i in xrange(niter):
        Q, R = la.qr(H)
        H = R.dot(Q)
        
    # populate the list of eigenvalues
    eigs = []
    i = 0
    while i < H.shape[0]:
        if i == H.shape[0]-1: #if we are at the last diagonal entry, must be eigenvalue
            eigs.append(H[i,i])
            i += 1
        elif abs(H[i+1,i]) < tol: #if subdiagonal zero, diagonal must be e'value 
            eigs.append(H[i,i])
            i += 1
        else: #subdiagonal nonzero, so find complex e'values of 2x2 block
            a, b, c, d = H[i:i+2,i:i+2].flatten()
            T = a + d
            D = a*d - b*c
            eigs.append(T/2 + math.sqrt(abs(T**2/4 - D))*1j)
            eigs.append(T/2 - math.sqrt(abs(T**2/4 - D))*1j)
            i += 2
    return eigs
예제 #39
0
def hessenberg_realization(G, compute_T=False, form='c', invert=False,
                           output='system'):
    """
    A state transformation is applied in order to get the following form where
    A is a Hessenberg matrix and B (or C if 'form' is set to 'o' ) is row/col
    compressed ::

                                [x x x x x|x x]
                                [x x x x x|0 x]
                                [0 x x x x|0 0]
                                [0 0 x x x|0 0]
                                [0 0 0 x x|0 0]
                                [---------|---]
                                [x x x x x|x x]
                                [x x x x x|x x]

    Parameters
    ----------
    G : State, Transfer, 3-tuple
        A system representation or the A, B, C matrix triplet of a  State
        realization. Static Gain models are returned unchanged.
    compute_T : bool, optional
        If set to True, the array that would bring the system into the desired
        form will also be returned. Default is False.
    form : str, optional
        The switch for selecting between observability and controllability
        Hessenberg forms. Valid entries are ``c`` and ``o``.
    invert : bool, optional
        Select which side the B or C matrix will be compressed. For example,
        the default case returns the B matrix with (if any) zero rows at the
        bottom. invert option flips this choice either in B or C matrices
        depending on the "form" switch.
    output : str, optional
        In case only the resulting matrices and not a system representation is
        needed, this keyword can be used with the value ``'matrices'``. The
        default is ``'system'``. If 3-tuple is given and 'output' is still
        'system' then the feedthrough matrix is taken to be 0.

    Returns
    -------
    Gh : State, tuple
        A realization or the matrices are returned depending on the 'output'
        keyword.
    T : ndarray
        If 'compute_T' is set to True, the array for the state transformation
        is returned.

    """
    if isinstance(G, tuple):
        a, b, c = G
        a, b, c, *_ = State.validate_arguments(a, b, c, zeros((c.shape[0],
                                                               b.shape[1])))
        in_is_sys = False
    else:
        _check_for_state_or_transfer(G)
        in_is_sys = True
        if isinstance(G, Transfer):
            a, b, c, _ = transfer_to_state(G, output='matrices')
        else:
            a, b, c = G.a, G.b, G.c

    if form == 'o':
        a, b, c = a.T, c.T, b.T

    qq, bh = qr(b)
    ab, cb = qq.T @ a @ qq, c @ qq
    ah, qh = hessenberg(ab, calc_q=True)
    ch = cb @ qh

    if compute_T:
        T = qq @ qh

    if invert:
        ah, bh, ch = fliplr(flipud(ah)), flipud(bh), fliplr(ch)
        if compute_T:
                T = flipud(T)

    if form == 'o':
        ah, bh, ch = ah.T, ch.T, bh.T

    if output == 'system':
        if in_is_sys:
            Gh = State(ah, bh, ch, dt=G.SamplingPeriod)
        else:
            Gh = State(ah, bh, ch)
        if compute_T:
            return Gh, T
        else:
            return Gh
    else:
        if compute_T:
            return ah, bh, ch, T
        else:
            return ah, bh, ch
예제 #40
0
    def get(self, Wt, full=False):
        r'''Get Arnoldi relation for a deflation subspace choice.

        :param Wt: the coefficients :math:`\tilde{W}` of the deflation vectors
          in the basis :math:`[V_n,U]` with ``Wt.shape == (n+d, k)``, i.e., the
          deflation vectors are :math:`W=[V_n,U]\tilde{W}`. Must fulfill
          :math:`\tilde{W}^*\tilde{W}=I_k`.
        :param full: (optional) should the full Arnoldi
          basis and the full perturbation be returned? Defaults to ``False``.

        :return:

          * ``Hh``: the Hessenberg matrix with ``Hh.shape == (n+d-k, n+d-k)``.
          * ``Rh``: the perturbation core matrix with
            ``Rh.shape == (l, n+d-k)``.
          * ``q_norm``: norm :math:`\|q\|_2`.
          * ``vdiff_norm``: the norm of the difference of the initial vectors
            :math:`\tilde{v}-\hat{v}`.
          * ``PWAW_norm``: norm of the projection
            :math:`P_{\mathcal{W}^\perp,A\mathcal{W}}`.
          * ``Vh``: (if ``full == True``) the Arnoldi basis with ``Vh.shape ==
            (N, n+d-k)``.
          * ``F``: (if ``full == True``) the perturbation matrix
            :math:`F=-Z\hat{R}\hat{V}_n^* - \hat{V}_n\hat{R}^*Z^*`.
        '''
        n = self.n
        n_ = self.n_
        d = self.d
        k = Wt.shape[1]

        # get orthonormal basis of Wt and Wt^\perp
        if k > 0:
            Wto, _ = scipy.linalg.qr(Wt)
            Wt = Wto[:, :k]
            Wto = Wto[:, k:]
        else:
            Wto = numpy.eye(Wt.shape[0])

        deflated_solver = self._deflated_solver

        Pt = utils.Projection(self.L.dot(Wt), self.J.T.conj().dot(Wt)) \
            .operator_complement()
        if d > 0:
            qt = Pt*(numpy.r_[[[deflated_solver.MMlr0_norm]],
                              numpy.zeros((self.n_-1, 1)),
                              numpy.linalg.solve(deflated_solver.E,
                                                 deflated_solver.UMlr)])
        else:
            qt = Pt*(numpy.r_[[[deflated_solver.MMlr0_norm]],
                              numpy.zeros((self.n_-1, 1))])
        q = Wto.T.conj().dot(self.J.dot(qt))

        # TODO: q seems to suffer from round-off errors and thus the first
        #       vector in the computed basis may differ from the exact
        #       projected one more than on the level of unit round-off.

        # rotate closest vector in [V_n,U] to first column
        Q = utils.House(q)
        q_norm = Q.xnorm

        # Arnoldify
        WtoQ = Q.apply(Wto.T.conj()).T.conj()

        from scipy.linalg import hessenberg
        Hh, T = hessenberg(
            Q.apply(Wto.T.conj().dot(self.J).dot(Pt*(self.L.dot(WtoQ)))),
            calc_q=True)

        QT = Q.apply(T)

        # construct residual
        Rh = self.N.dot(Pt*self.L.dot(Wto.dot(QT)))

        # norm of difference between initial vectors
        vdiff = self.N.dot(qt)
        vdiff_norm = 0 if vdiff.size == 0 else numpy.linalg.norm(vdiff, 2)

        # compute norm of projection P_{W^\perp,AW}
        if k > 0:
            # compute coefficients of orthonormalized AW in the basis [V,Z]
            Y = numpy.bmat([[numpy.eye(n_), deflated_solver.B_],
                            [numpy.zeros((d, n_)), deflated_solver.E],
                            [numpy.zeros((self.R12.shape[0], n_)), self.R12]])
            YL_Q, _ = scipy.linalg.qr(Y.dot(self.L.dot(Wt)), mode='economic')

            # compute <W,X> where X is an orthonormal basis of AW
            WX = Wt.T.conj().dot(numpy.r_[YL_Q[:n, :],
                                          YL_Q[n_:n_+d, :]])
            PWAW_norm = 1./numpy.min(scipy.linalg.svdvals(WX))
        else:
            PWAW_norm = 1.

        if full:
            Vh = numpy.c_[deflated_solver.V[:, :n],
                          deflated_solver.projection.U].dot(Wto.dot(QT))
            ip_Minv_B = deflated_solver.linear_system.get_ip_Minv_B()

            def _apply_F(x):
                '''Application of the perturbation.'''
                return -(self.Z.dot(Rh.dot(utils.inner(Vh, x,
                                                       ip_B=ip_Minv_B)))
                         + Vh.dot(Rh.T.conj().dot(utils.inner(self.Z, x,
                                                              ip_B=ip_Minv_B)))
                         )
            F = utils.LinearOperator((Vh.shape[0], Vh.shape[0]),
                                     dtype=deflated_solver.dtype,
                                     dot=_apply_F
                                     )
            return Hh, Rh, q_norm, vdiff_norm, PWAW_norm, Vh, F
        return Hh, Rh, q_norm, vdiff_norm, PWAW_norm
예제 #41
0
파일: QR.py 프로젝트: philzook58/badgergame
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import scipy.linalg as linalg

a = np.array([
    [2,-1,0 ],
    [-1,2,-1],
    [0,-1,2 ]])

print linalg.eigvals(a)


H,Q = linalg.hessenberg(a, calc_q=True)
print H
print Q
a = H

N = 50
result = np.zeros(N)

for i in range(N):
    Q,R = linalg.qr(a)
    #print "Q" + str(i) + ":"
    #print  Q
    #print "R" + str(i) + ":"
    #print R
    result[i]= R[0,0]
    a = np.dot(R,Q)
예제 #42
0
 def test_random(self):
     n = 20
     for k in range(2):
         a = random([n,n])
         h,q = hessenberg(a,calc_q=1)
         assert_array_almost_equal(dot(transp(q),dot(a,q)),h)
예제 #43
0
    leftcounts = totcounts - rightcounts
    print leftcounts, rightcounts , "\n"
    #print "leftcount: ", leftcounts, " rightcount: ", rightcounts, "\n\n"
    if not rightcounts == 0:
        findeig(A, (a+b)/2, b, rightcounts)
    if not leftcounts == 0:
        findeig(A, a, (a+b)/2, leftcounts)

def findeigs(A, a = 0, b = 0):
    if a-b == 0:
        b = A.shape[0]
        a = -b
    totcounter = counteiginterval(A, a, b)
    findeig(A,a,b,500)
n = 500
a, b = 0, 1
eigs = []
   
A = random.rand(n, n)
A = (A + A.T)/2
A = sla.hessenberg(A)

findeigs(A)
nbrfound = eigs.__len__()
shouldfound = sla.eig(A)[0].__len__()

print sort(eigs)
print sort(sla.eig(A)[0]*-1)*-1
print "Found: ",nbrfound, " Exists: ", shouldfound