Programmierung zum Balancierten Abschneiden

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
NoraVYK
User
Beiträge: 2
Registriert: Dienstag 22. Februar 2022, 07:51

Hallo,

ich versuche über Python die Modellordnungsreduktion durch das Balancierte Abschneiden zu programmieren. Ich bin noch am Anfag meiner Programmierkünste. Meinen bisherigen Code habe ich hier eingefügt, wobei für mich relevant die letzten drei Abschnitte sind (ab "Cholesky Faktoren R und S bestimmen").

Code: Alles auswählen

import numpy as np

A = np.array([[1,3], [-1,-2]])
B = np.array([[1], [0]])
C = np.array([[0,1]])

#print("A=", A, "B=", B, "C=", C)

'''Grammsche Matrizen erstellen 
1. Gleichung: AP+PA(transponiert+BB(transponiert)=0
 Zeit-kontinouirliche Lyaponov Gleichung nutzen um Gramian Matrix P zu errechnen
Die Gleichung in die Form AP+PA(transponiert)=B_rechts bringen; das B_rechts bezieht sich auf die Umselltung der 1. Gleichung '''
from scipy import linalg
B_rechts = -np.dot(B,np.transpose(B))
P = linalg.solve_continuous_lyapunov(A, B_rechts)
#print(P)
#print(np.allclose(A.dot(P) + P.dot(A.T), B_rechts)) #ermöglicht das Prüfen, ob Dimension der Matrizen übereinstimmt

'''2. Gleichung: A(tranposniert)Q+QA+C(transponiert)C=0
    Infinite observability Gramian Gleichung um Q zu ermitteln
    In die Form AQ+QA(transponiert)=C bringen um die linalg.solve_continuous_lyapunov Funktion zu nutzen. Dafür wird A1 geschaffen und C1 um auf der richtigen Seite der Gleichung und der richtigen Transformation zu sein '''

A1 = np.transpose(A)
C1 = -np.dot(np.transpose(C), C)
Q = linalg.solve_continuous_lyapunov(A1, C1)
#print(Q)
#print(np.allclose(A1.dot(Q) + Q.dot(A1.T), C1))

'''Eigenwerte und Eigenvektoren bestimmen'''
P_Eigen = linalg.eigh(P)
Q_Eigen = linalg.eigh(Q)
#print(P_Eigen, Q_Eigen)
#Eigenwertatrix erstellen
P_Eigenvalues = P_Eigen[1]
Q_Eigenvalues = Q_Eigen[1]
#print(P_Eigenvalues, Q_Eigenvalues)

'''Cholesky Faktoren R und S bestimmen
    P=RR(transponiert) und Q=SS(transponiert)'''
R = np.linalg.cholesky(P)   #R bestimmen
RR_transponiert = (np.dot(R, R.T.conj()))    #Verifizieren, dass RR(transponiert)=P ist

print("RR_T ist gleich", RR_transponiert)
print("P ist gleich", P)

print(np.array_equal(RR_transponiert, P))
print(RR_transponiert==P)

Die Ausgabe von RR_transponiert und P ergibt den selben werd. Beim vergleichen der Matrizen jedoch kommt bei einem Matrixeintrag die Meldung "false". Die Ausgabe des Codes ist nachfolgend aufgeführt.

Code: Alles auswählen

RR_T ist gleich [[ 2.5 -1. ]
 [-1.   0.5]]
P ist gleich [[ 2.5 -1. ]
 [-1.   0.5]]
False
[[ True  True]
 [False  True]]

Process finished with exit code 0

Wieso wird ein Wert als False angegeben, wobei die Ausgabe beider Matrizen identisch ist?
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du wirst da Rundungsfehler haben, die subtil sind, und nicht durch die Darstellung auftauchen. Das ist ein systematisches Problem beim Rechnen mit Fliesskommazahlen. Wenn du das Ergebnis wirklich brauchst (statt nur zur Verifikation für dich), dann hilft vielleicht https://numpy.org/doc/stable/reference/ ... close.html - wenn du die Parameter passend einstellst.
NoraVYK
User
Beiträge: 2
Registriert: Dienstag 22. Februar 2022, 07:51

__deets__ hat geschrieben: Dienstag 22. Februar 2022, 09:12 Du wirst da Rundungsfehler haben, die subtil sind, und nicht durch die Darstellung auftauchen. Das ist ein systematisches Problem beim Rechnen mit Fliesskommazahlen. Wenn du das Ergebnis wirklich brauchst (statt nur zur Verifikation für dich), dann hilft vielleicht https://numpy.org/doc/stable/reference/ ... close.html - wenn du die Parameter passend einstellst.
Vielen Dank für diese schnelle und informative Rückemldung! Da der Vergleich nur für mich relevant ist, hilft es mir weiter.
Antworten