Zugriff auf Matrizen. Anhängen von Elementen. Punktweise Operatoren. Vektoren und Matrizen in MATLAB II Matrixzugriff Wir wollen nun unsere Einführung in die Arbeit mit Vektoren und Matrizen in MATLAB fortführen. Matrizen und Vektoren werden in MATLAB nicht nur im Sinne linearer Gleichungssysteme verwendet, sondern dienen auch als Speicher für beliebige Informationen. Daher existiert eine Vielzahl von Funktionen um Vektoren und Matrizen zu manipulieren, von denen wir hier einige ansprechen wollen. Aufgabe 1. Um beliebige n m-matrizen zu erzeugen gibt es die Befehle zeros, eye und ones. Informieren Sie sich über help darüber, wie diese Befehle benutzt werden. Der Zugriff auf einzelne Elemente einer n m-matrix (a ij ) erfolgt in MATLAB über runde Klammern: Um auf den Eintrag a ij zuzugreifen, 1 i n, 1 j m, verwenden wir A(i,j): >> [8 1 6; 3 5 7; 4 9 2] 8 1 6 3 5 7 4 9 2 >> A(2,3) 7 Geben wir statt Zeile und Spalte nur eine Zahl an, so wird die Matrix als Element von K nm (statt K n m ) interpretiert. Die Spalten werden dabei untereinander geschrieben interpretiert, A(i,j) entspricht daher dem Element A(i+(j-1)*n). 1
>> A(3) 4 >> A(4) 1 Wir können statt der Zahlen als Indizes auch Vektoren v {1,..., n} k, w {1,..., m} l angeben. Zurückgegeben wird dann die Matrix à Kk l mit Einträgen (ã i,j ) := (a vi,v j ). Da jeder Skalar gleichzeitig auch als Vektor der Länge 1 interpretiert werden kann, fällt diese Definition im Fall von k, l = 1 mit dem normalen Zugriff auf ein Element zusammen. >> A(2, [2, 3]) 5 7 >> A([1, 3], [2, 3]) 1 6 9 2 Aufgabe 2. Sei A R 3 3 definiert durch 1 3 4 A := 5 0 2. 1 3 0 Lösen Sie die folgenden Aufgaben mit Hilfe von Zugriffsoperatoren: a) Geben Sie das Element a 2,3 mit A(i,j) und A(k) aus. b) Geben Sie die erste Zeile von A aus. c) Geben Sie die linke, obere 2 2-Untermatrix von A aus. d) Definieren Sie B als A mit Zeilen 1 und 2 vertauscht. Tipp: MATLAB interpretiert die Matrix als einen Vektor. Beim Zugriff auf eine Matrix A K n m können 1:n und 1:m jeweils auch mit einem einfachen Doppelpunkt : abgekürzt werden. MATLAB kennt die Dimension der Matrix und ersetzt in diesem Fall den Doppelpunkt durch den richtigen Vektor. 2
>> A(2,:) 3 5 7 >> A(:,3) 6 7 2 All die bisher kennengelernten Ausdrücke können wir auch benutzen, um Matrizen zu ändern. Wir können sowohl einzelne Einträge, als auch ganze Spalten, Zeilen oder allgemein beliebige Untermatrizen ändern: >> A(2,3) = 0 8 1 6 3 5 0 4 9 2 Man beachte, dass der Wert des Eintrags bei einer Zuweisung zu einer Variablen kopiert wird und daher späteres Ändern dieser Kopie keine Auswirkung mehr auf die Matrix hat: >> x = A(2,3) x = 0 >> x = 4 x = 4 >> A 8 1 6 3 5 0 4 9 2 Aufgabe 3. Erstellen Sie eine 8 8-Matrix in MATLAB, bei der im Schachbrettmuster Nullen und Einsen angeordnet sind. Gehen Sie dabei wie folgt vor: a) Erzeugen Sie Ihre Matrix mit zeros und ersetzen Sie durch for-schleifen die Nullen an den entsprechenden Stellen durch Einsen. b) Lösen Sie das Problem nun ohne Schleifen, aber trotzdem in wenigen Schritten, in dem Sie ganze Teilmatrizen durch ones ersetzen. 3
Erweitern von Vektoren und Matrizen In einigen Situationen ist es sinnvoll, Vektoren um Einträge zu erweitern, bzw. eine Matrix durch das Anhängen einer Spalte oder einer Zeile in ihrer Dimension zu verändern. Ein Beispiel ist ein Vektor fib_n der Dimension n, in dem die ersten n Glieder der Fibonacci-Folge gespeichert werden. Will man nun alle Elemente der Folge bis zum (n+1)-ten Glied berechnen, also den Vektor fib_(n+1), so ist es sinnvoller, diesen um ein Element zu erweitern, statt alle Elemente der Folge erneut zu berechnen. Dies kann man mit der folgenden Syntax tun: >> fib_3 = [1 1 2] fib_3 = 1 1 2 >> fib_4 = [ fib_3 3] fib_4 = 1 1 2 3 Man beachte dabei, dass beide Vektoren als Zeilenvektoren konstruiert sind. Einen Zeilenvektor zu einem Spaltenvektor zu ergänzen funktioniert nicht und führt zu einem Dimensionsfehler. >> fib_3 = [1 1 2] fib_3 = 1 1 2 >> fib_4 = [ fib_3; 3] Error using vertcat CAT arguments dimensions are not consistent. Bei Matrizen ergeben sich zum Teil ähnliche Situationen wie bei unserem Fibonacci Beispiel. Man nehme an wir wollen für zwei aufeinanderfolgende Dimensionen n und n + 1 die zugehörigen Hilbertmatrizen H_n und H_n+1 aufstellen. Statt die Einträge der Matrix H_n+1 alle neu zu berechnen, nutzen wir die bereits berechneten Einträge der Matrix H_n. Dazu müssen wir die Matrix H_n um eine Spalte der länge n und eine Zeile der Länge n + 1 ergänzen. H_2 = 1.0000 0.5000 0.5000 0.3333 >> s_3 = [1/3; 1/4] 4
s_3 = 0.3333 0.2500 >> z_3 = [1/3 1/4 1/5] z_3 = 0.3333 0.2500 0.2000 >> h_3 = [ H_2 s_3; z_3] H_3 = 1.0000 0.5000 0.3333 0.5000 0.3333 0.2500 0.3333 0.2500 0.2000 Geschwindigkeitsprobleme beim Anhängen Wenn wir Elemente an eine Matrix / einen Vektor anhängen, wird intern eine komplett neue Matrix der richtigen Größe erzeugt und die Einträge des alten Objekts in diese neue Matrix kopiert 1. Dieses Kopieren ist langsam und sollte wenn möglich vermieden werden. Oftmals ist dies möglich, da meist nicht die Größe der Matrix / des Vektors am Anfang unbekannt ist, sondern die Einträge. Wir reservieren daher zu Beginn genug Speicherplatz und arbeiten dann mit Untermatrizen / -vektoren über die oben vorgestellte Syntax. Das folgende Beispiel soll das Problem demonstrieren. In diesem werden abermals die ersten 10 Glieder der Fibonacci-Folge berechnet. v = [1 1]; for i=3:10 v = [ v v(i-1)+ v(i -2)]; end Sofern Sie diesen Programmcode in eine Skriptdatei schreiben, wird MAT- LAB das v in der for-schleife mit rot unterschlängeln. Wenn Sie dann mit dem Mauszeiger auf das v zeigen, gibt MATLAB Ihnen den folgenden 1 Erklärung: Matrizen werden vom Computer als zusammenhängede Blöcke von Zahlen gespeichert, deren Größe beim Anlegen der Matrix festgelegt wird. All die Daten, mit denen der Computer arbeitet, werden so nacheinander im Arbeitsspeicher gespeichert. Nach dem Anlegen der Matrix ist daher nicht mehr garantiert, dass links und rechts Platz für die Einträge unserer größeren Matrix frei ist. Daher muss woanders ein größerer, zusammenhänger Block reserviet und die Einträge der alten Matrix kopiert werden. 5
Hinweis: The variable v appears to change size on every loop iteration. Consider Preallocating for speed. MATLAB reserviert für die Variable v am Anfang nur den Speicherplatz für zwei double-werte. Im ersten Schritt der Schleife wird die Länge des Vektors dann auf Dimension drei geändert. MATLAB reserviert in diesem Moment komplett neuen Speicher für drei double-werte und kopiert die vorhergehenden zwei. Dies wird in jedem Schritt wiederholt. Wir wissen, dass wir ingesamt Speicher für 10 Einträge brauchen, daher erzeugen wir direkt am Anfang den Speicher für alle Einträge und lassen diese auf 0 solange, bis unsere Schleife an der Stelle ankommt. Ein effizientes Programm sähe daher wie folgt aus: v = zeros (10,1); v(1) = 1; v(2) = 1; for i=3:10 v(i) = v(i-1)+ v(i-2); end Elementweise Operationen Außer den bekannten Rechenoperatioren *, / und kennt MATLAB die elementweisen Operatoren.*,./ und., bei denen dem Rechenzeichen ein Punkt vorangestellt wird. Die elementweisen Operatoren können nur verwendet werden, wenn die Dimensionen der verknüpften Matrizen übereinstimmen oder eine von ihnen ein Skalar ist. >> [1 2 3; 4 5 6] 1 2 3 4 5 6 >> B = [2 4 3; 2 1 1] B = 2 4 3 2 1 1 >> A.^B 1 16 27 16 5 6 6
Falls eine der Größen ein Skalar ist, wird die skalare Operation auf alle Elemente der Matrix angewendet. Das Ergebnis hat dann die Dimension der Matrix. >> A.^2 1 4 9 16 25 36 >> 2.^ A 2 4 8 16 32 64 Aufgabe 4. a) Berechnen Sie n n für alle natürlichen Zahlen von 3 bis 9. b) Berechnen Sie für einen beliebigen Vektor a K 4 das elementweise Quadrat und das euklidische Skalarprodukt. Alle bekannten mathematischen Funktionen können auch elementweise angewendet werden, in dem man als Argument für die Funktion einen Vektor angibt. Das Ergebnis ist dann ein Vektor mit den Funktionsauswertungen: >> a = 0:pi/4:pi a = 0 0.7854 1.5708 2.3562 3.1416 >> b = sin(a) b = 0 0.7071 1.0000 0.7071 0.0000 Das Kronecker-Tensorprodukt Um Blockmatrizen wie für die erste Übungsaufgabe von Blatt 2 zu erstellen, können wir das Kroneckerprodukt von Matrizen verwenden. Das Kronecker-Tensorprodukt ist ein Multiplikationsoperator zwischen zwei Matrizen beliebiger Dimension, der als Ergebnis eine größere Matrix erzeugt, die alle möglichen Produkte aus den Einträgen der beiden Ausgangsmatrizen enthält. Für unsere Anwendung zum Aufstellen der Modellmatrix ist es sinnvoll, sich dieses Produkt als Blockmatrix vorzustellen: Das Kronecker- Produkt von zwei Matrizen (a ij ) n,m i,j=1 Rn m und B R k l ist eine Blockmatrix C R nk ml mit den Blöcken c ij = (a ij B) n,m 7 i,j=1.
In MATLAB ist das Kronecker-Tensorprodukt als kron(, )-Funktion verfügbar: 1 2 3 4 >> B = eye(2,2) B = 1 0 0 1 >> kron(a,b) 1 0 2 0 0 1 0 2 3 0 4 0 0 3 0 4 Aufgabe 5. Benutzen Sie kron(), um möglichst einfach die folgende Matrix zu erstellen: 1 2 0 0 1 2 C = 3 4 0 0 3 4 0 0 4 8 0 0 0 0 12 16 0 0 Aufgabe 6. Lösen Sie Aufgabe 1 vom zweiten Übungsblatt mit Hilfe der folgenden Schritte: a) Erstellen Sie eine Funktion, welche die Matrix B m erzeugt. Benutzen Sie hierfür die Funktionen diag() und ones(). Bauen Sie die Matrix Schritt-für-Schritt auf und addieren Sie Ihre Teilergebnisse. b) Erweitern Sie Ihre Funktion, so dass die Matrix A m vom Übungsblatt erzeugt wird, in dem Sie zunächst mit Hilfe von kron() eine Blockdiagonalmatrix mit Blöcken B m erzeugen. c) Ergänzen Sie A m aus der letzten Teilaufgabe durch die Nebendiagonal- Blöcke. Wenden Sie dafür wieder kron() auf eine Matrix an, welche Sie mit diag() und ones() konstruiert haben. 8