MATLAB - Eine Einführung - TUM
MATLAB - Eine Einführung - TUM
MATLAB - Eine Einführung - TUM
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
<strong>MATLAB</strong> - <strong>Eine</strong> <strong>Einführung</strong><br />
Christian Kufner Harald Schmid Konstantin Schorp Bettina Tögel<br />
Matthias Vestner Konstantin Pieper Lorenz Pfeifroth Stefan Jerg<br />
Boris von Loesch<br />
16. April 2009
Vorwort<br />
Das vorliegende Skript gibt dem Leser eine <strong>Einführung</strong> in den Umgang mit <strong>MATLAB</strong>. Die Bedienung<br />
von <strong>MATLAB</strong> und die Themen Visualisierung und lineare Algebra mit <strong>MATLAB</strong> werden erklärt. Auf<br />
weiterführende Funktionen <strong>MATLAB</strong> wie Toolboxen und das Einbinden von Java- und C-Programmen<br />
wird eingegangen.<br />
Dieses Handbuch ist besonders für Studenten der Mathematik geeignet, die im Studium <strong>MATLAB</strong><br />
benötigen. Grundkenntnisse der linearen Algebra werden vorausgesetzt, jedoch sind keine Programmierkenntnisse<br />
notwendig. Dieses Skript ist im Internet unter<br />
http://www.fs.tum.de/fsmpi/kurse/matlab/matlabeinfuehrung.pdf<br />
verfügbar. Sie erreichen den verantwortlichen Mitarbeiter der TU München unter der Email-Adresse<br />
brandenb@ma.tum.de.<br />
Zweite Auflage Dieses Skript wurde für den Ferienkurs „<strong>MATLAB</strong> Grundlagen“ im Wintersemester<br />
07/08 überarbeitet und um die Abschnitte „Eigenwerte“ 5.5, „Ein- und Ausgabe“ 7 und „Troubleshooting“<br />
erweitert. Die Webadresse des Kurses ist<br />
http://ferienkurse.ma.tum.de/twiki/bin/view/Allgemein/WS0708/Matlab.<br />
Dritte Auflage Dieses Skript wurde für den Ferienkurs „<strong>MATLAB</strong> Grundlagen“ im Sommersemester<br />
08 überarbeitet. Die Webadresses des Kurses ist<br />
http://ferienkurse.ma.tum.de/twiki/bin/view/Ferienkurse/SS08/MatLabG<br />
Vierte Auflage Für die vierte Auflage wurden weite Teile des Skriptes stark verändert. Ein Einstiegsbeispiel<br />
(Kapitel 1) soll den Leser mit den besonderen Fähigkeiten von <strong>MATLAB</strong> vertraut machen.<br />
Kapitel 2 ist komplett umgearbeitet worden, zusätzlich wurde das Skript um einen Index ergänzt. Diese<br />
<strong>Einführung</strong> wurde für die Ferienkurse <strong>MATLAB</strong> im SS09 verwendet.<br />
http://www.ma.tum.de/Ferienkurse/WiSe0809/MatLabC<br />
1
Inhaltsverzeichnis<br />
0.1 Bezug von <strong>MATLAB</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
0.2 Alternativen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
0.3 Hinweise zur Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
0.3.1 Komplexe Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
1 Motivation 7<br />
1.1 Interpolation durch kubischen Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
1.2 Implementierung in <strong>MATLAB</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
1.3 Visualisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
1.4 Erweiterung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
1.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
2 Vektoren und Matrizen 11<br />
2.1 Matrizen erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
2.1.1 Spezielle Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />
2.1.2 Doppelpunkt Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
2.2 Indizierung und Doppelpunktnotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
2.3 Operatoren und Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
2.3.1 Rechenoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />
2.3.2 Basisfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />
2.3.3 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
2.4 Matrizen manipulieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
3 Operatoren und Flusskontrolle 23<br />
3.1 Relationale Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
3.2 Logische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
3.2.1 Indizierung mit logischen Feldern . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />
3.3 Flusskontrolle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26<br />
4 M-Dateien 30<br />
4.1 Skriptdateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.2 Funktionsdateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />
4.3 M-Dateien bearbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />
4.4 Mit M-Dateien und der Pfadvariable von <strong>MATLAB</strong> arbeiten . . . . . . . . . . . . . . . . 32<br />
4.5 Dualität von Befehl und Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />
5 Lineare Algebra mit <strong>MATLAB</strong> 34<br />
5.1 Norm und Kondition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34<br />
5.2 Lineare Gleichungssysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.2.1 A n × n Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.2.2 A m × n Matrix mit m > n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.2.3 A m × n Matrix mit m < n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.3 Inverse, Pseudoinverse und Determinante . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.4 Zerlegungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
5.4.1 LR-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
5.4.2 Cholesky-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
5.4.3 QR-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.4.4 Singulärwertzerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
2
5.5 Eigenwertpropleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.5.1 Eigenwerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.6 Matrixfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />
6 Eigene Funktionen 39<br />
6.1 Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
6.2 Subfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40<br />
6.3 Globale Variablen und Rekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40<br />
7 Ein- und Ausgabe 42<br />
7.1 Direkte Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />
7.2 Bildschirmausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43<br />
7.3 Speichern und Laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43<br />
7.4 Indirekte Eingabe und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44<br />
8 Optimierung von M-Files 46<br />
8.1 Vektorisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46<br />
8.2 Preallokierung von Speicher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />
9 Tipps und Tricks 48<br />
9.1 Leere Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />
9.2 ∞ und −∞ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />
10 Grafiken mit <strong>MATLAB</strong> erstellen 50<br />
10.1 Grafiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
10.2 2-dimensionale Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
10.3 Mehrere Plots in einem Fenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
10.4 3-dimensionale Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />
10.4.1 Animationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58<br />
10.5 Diagramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59<br />
10.5.1 Balkendiagramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59<br />
10.5.2 Tortendiagramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />
11 Troubleshooting 61<br />
11.1 Errors und Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61<br />
11.2 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61<br />
12 Weiterführende <strong>MATLAB</strong>-Funktionen 62<br />
12.1 Toolkits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
12.1.1 Symbolic Math Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
12.1.2 Image Processing Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
12.2 Der <strong>MATLAB</strong> C-Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
12.3 Andere Programmiersprachen mit <strong>MATLAB</strong> verwenden . . . . . . . . . . . . . . . . . . . 64<br />
12.3.1 Fortran und C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64<br />
12.3.2 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65<br />
12.4 GUIs programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65<br />
12.4.1 GUI Kommandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65<br />
12.4.2 GUIDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66<br />
3
Einleitung<br />
<strong>MATLAB</strong> ist eine mächtige Anwendung für Mathematiker und Ingenieure, die von der Firma The Mathworks<br />
entwickelt und vertrieben wird. Vielfältigste Funktionen zur Lösung numerischer Probleme, der<br />
Visualisierung von Daten und die Erweiterbarkeit des Basispakets über Toolboxen machen <strong>MATLAB</strong> zu<br />
einem guten Werkzeug für Studenten der Mathematik, die sich im Rahmen ihres Studiums auch mit dem<br />
Lösen numerischer Probleme beschäftigen.<br />
<strong>MATLAB</strong> enthält eine komfortable IDE (integrated development environment) die den Programmierer<br />
bei seiner Arbeit unterstützt. In ihr sind sind unter anderem enthalten<br />
• eine interaktive Codeeingabe,<br />
• eine ausführliche Hilfe,<br />
• ein Quellcode Editor mit Syntax Highlighting,<br />
• ein Debugger um Programme schrittweise durchlaufen zu lassen,<br />
• ein Profiler zum Erkennen von Geschwindigkeitsengpässsen.<br />
Im Gegensatz zu anderen Programmiersprachen wie C, Fortran oder Java muss <strong>MATLAB</strong> Code vor der<br />
Ausführung nicht kompiliert werden, sondern wird direkt interpretiert 1 . Auch müssen Variablen vor ihrer<br />
ersten Verwendung nicht deklariert werden. Deshalb ist <strong>MATLAB</strong> in die Kategorie der Skriptsprachen,<br />
wie z.B. Python, Tcl oder Perl, einzuordnen.<br />
Das Besondere an <strong>MATLAB</strong> ist die Verwendung von mehrdimensionalen Feldern (auch mit komplexen<br />
Zahlen) wie Vektoren und Matrizen als Standardtypen und eine umfangreiche mathematische Bibliothek.<br />
Damit ist es möglich, Algorithmen in einer mathematischen Syntax unter Verwendung von Standardkomponenten<br />
wie z.B. einer LR-Zerlegung schnell zu implementieren (Prototyping). Der Vorwurf, dass<br />
Programme in <strong>MATLAB</strong> im Vergleich zu Fortran oder C viel langsamer sind, ist im Allgemeinen nicht<br />
berechtigt, wenn man bei der Programmierung gewisse Prinzipien befolgt. Dies liegt daran, dass MAT-<br />
LAB intern sehr schnelle Routinen z.B. für das Matrix-Vektor-Produkt oder die Fouriertransformation<br />
verwendet; wie andere Numerikpakete verwendet <strong>MATLAB</strong> für die Lineare Algebra die BLAS und LA-<br />
PACK Bibliotheken.<br />
Diese <strong>Einführung</strong> soll einen Einblick in den Aufbau und die grundlegenden Funktionen von <strong>MATLAB</strong><br />
geben. Weiterführende Informationen findet man in der umfangreichen eingebauten Hilfe, in den vielen<br />
<strong>MATLAB</strong> Bücher und natürlich auch im Internet.<br />
0.1 Bezug von <strong>MATLAB</strong><br />
Als Student gibt es die Möglichkeit kostengünstig eine Studentenversion zu erwerben, die allerdings nur<br />
während und für das Studium verwendet werden darf. Weiterhin ist auf allen Computer der Rechnerhalle<br />
<strong>MATLAB</strong> verfügbar.<br />
0.2 Alternativen<br />
Neben <strong>MATLAB</strong> gibt es eine Reihe Programmpakete, die -zumindest was die grundlegenden Funktionen<br />
angeht- sehr ähnlich sind. <strong>Eine</strong> nicht repräsentative Liste frei verfügbarer Pakete:<br />
1 Seit <strong>MATLAB</strong> R6.5 wird der Code während der Ausführung durch einen Just-In-Time Kompilierer übersetzt um eine<br />
höhere Performance im Vergleich zur direkten Ausführung zu erhalten<br />
4
Octave ist ein Open-Source Clone von <strong>MATLAB</strong> der für viele Betriebssysteme verfügbar ist. Alle Beispiele<br />
aus diesem Skript (bis auf das Kapitel Grafik) sollten ohne Änderung auch in Octave funktionieren.<br />
http://www.gnu.org/software/octave/<br />
SciLab <strong>Eine</strong> freie <strong>MATLAB</strong> Alternative die am INRIA 2 entwickelt wurde. Der Syntax ist nicht kompatibel<br />
zu <strong>MATLAB</strong>, allerdings recht ähnlich; im Paket enthalten ist ein <strong>MATLAB</strong> zu SciLab<br />
Konverter.<br />
http://www.scilab.org/<br />
Python+NumPy+SciPy NumPy und SciPy erweitern die Skriptsprache Python um einen flexiblen<br />
Array-Typ und eine umfangreiche mathematische Bibliothek. Die Syntax ist verschieden zu MAT-<br />
LAB. Diese Kombination erfreut sich in letzter Zeit größerer Beliebtheit. Ein besonderer Vorteil<br />
dieses Paketes ist die Möglichkeit, sehr einfach andere Numerikcodes wie z.B. PETSc oder Trilinos<br />
direkt in Python zu verwenden.<br />
http://www.scipy.org<br />
0.3 Hinweise zur Eingabe<br />
Wie C oder Java unterscheidet <strong>MATLAB</strong> zwischen Groß- und Kleinschreibung. So kann der Befehl<br />
sin(pi/2) richtig interpretiert werden, die Eingabe von Sin(pi/2) gibt jedoch eine Fehlermeldung zurück:<br />
??? Undefined function or method ’Sin’ for input arguments of type ’double’.<br />
Methodennamen werden in <strong>MATLAB</strong> grundsätzlich klein geschrieben und als Programmierer sollte<br />
man sich an diese Konvention halten.<br />
In den ersten Kapiteln werden wir die Beispiele direkt in die interaktive Codeeingabe eintippen.<br />
Das Ergebnis eines Befehls wird standardmäßig direkt ausgegeben. Dies kann unterdrückt werden durch<br />
Abschließen des Befehls mit einem Semikolon. Wird das Ergebnis eines Befehls nicht in einer Variable<br />
gespeichert, wird es automatisch in die Variable ans geschrieben.<br />
>> sin(pi/2)<br />
ans =<br />
1<br />
>> sin(pi/4);<br />
>> ans<br />
ans =<br />
0.7071<br />
Mehrere Befehle können durch Komma (mit Ausgabe des Ergebnisses) oder Semikolon (ohne Ausgabe<br />
des Ergebnisses) getrennt in eine Zeile geschrieben werden. Hierbei wird nur das letzte Resultat in ans<br />
gespeichert.<br />
>> cos(0); cos(pi/4), cos(pi/2)<br />
ans =<br />
0.7071<br />
ans =<br />
6.1232e-17<br />
0.3.1 Komplexe Zahlen<br />
<strong>MATLAB</strong> interpretiert eine Zahl standardmäßig als Gleitpunktzahl mit doppelter Genauigkeit 3 . Komplexe<br />
Zahlen werden durch<br />
2 Institut national de recherche en informatique et en automatique<br />
3 Im Gegensatz zu vielen anderen Programmiersprachen ist 1/2 also wirklich 0.5.<br />
5
+i<br />
eingegeben, z.B. 2+0.5i. Aus diesem Grund sollte die imaginäre Einheit i nicht durch eine Variable<br />
überschrieben werden, da es sonst Probleme mit komplexen Zahlen geben kann.<br />
<strong>MATLAB</strong> verwendet automatisch komplexe Zahlen wenn dies nötig ist. So wird z.B. √ −1 richtig als<br />
komplexe Zahl interpretiert. In vielen anderen Programmiersprachen würde dieser Aufruf eine Fehlermeldung<br />
erzeugen.<br />
6
Kapitel 1<br />
Motivation<br />
Bevor wir uns die Funktionen von <strong>MATLAB</strong> im Detail anschauen, wollen wir an einem kurzen Beispiel<br />
die schnelle und effiziente Umsetzung eines Algorithmus in <strong>MATLAB</strong> demonstrieren. Wie werden hier<br />
die Vorzüge gegenüber klassischen Programmiersprachen feststellen.<br />
1.1 Interpolation durch kubischen Splines<br />
Bei der Interpolation ist eine stetige Funktion S : R → R gesucht, die eine gegebene Menge von Knotenpunkten<br />
(xi, yi) ∈ R×R, i = 0, . . . , n mit xi < xj, i < j interpoliert, d.h. S(xi) = yi für i = 0, . . . , n. Häufig<br />
benötigt man, dass die Funktion S mindestens zweimal stetig differenzierbar ist, dann bieten sich kubische<br />
Splines zur Interpolation an. Ein kubischer Spline ist eine C 2 ([x0, xn]) Funktion, die eingeschränkt<br />
auf ein Intervall [xi, xi+1], i = 0, . . . , n − 1 ein Polynom 3. Grades ist. Diese Aufgabe ist nur dann eindeutig<br />
lösbar, wenn man noch zusätzliche Informationen am Rand vorgibt. Dafür gibt es mehrere Varianten,<br />
eine davon ist, dass die zweiten Ableitungen in den Randpunkten verschwinden (S ′′ (x0) = 0 = S ′′ (xn)).<br />
In diesem Fall nennt man den Spline natürlichen Spline.<br />
<strong>Eine</strong> Möglichkeit einen natürlichen Spline zu berechnen, ist die Momentenmethode. Wir wollen in diesem<br />
Rahmen nicht auf deren Herleitung eingehen sondern verweisen auf [1]. Als Momente Mi bezeichnet<br />
man die zweiten Ableitungen an den Stützstellen xi, also Mi = S ′′ (xi). Hat man sie berechnet, kann man<br />
die Koeffizienten des Polynoms<br />
Pi(x) = αi + βi(x − xi) + γi(x − xi) 2 + δi(x − xi) 3<br />
auf dem Intervall [xi, xi+1] direkt angeben (hi+1 = xi+1 − xi):<br />
αi = yi<br />
βi = yi+1 − yi<br />
hi+1<br />
γi = Mi<br />
2<br />
δi = Mi+1 − Mi<br />
6hi+1<br />
− 2Mi + Mi+1<br />
hi+1<br />
6<br />
Die Momente sind Lösung des linearen Gleichungssystems<br />
⎛<br />
2<br />
⎜µ1<br />
⎜<br />
⎝<br />
λ0<br />
2<br />
µ2<br />
λ1<br />
2<br />
. ..<br />
λ2<br />
. ..<br />
µn−1<br />
. ..<br />
2<br />
⎞<br />
⎛<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎝<br />
λn−1⎠<br />
2<br />
µn<br />
7<br />
M0<br />
M1<br />
.<br />
Mn−1<br />
Mn<br />
⎞<br />
⎛<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ = ⎜<br />
⎟ ⎜<br />
⎠ ⎝<br />
d0<br />
d1<br />
.<br />
dn−1<br />
dn<br />
⎞<br />
⎟<br />
⎠<br />
(1.1)
mit (j = 1, . . . , n − 1)<br />
hj<br />
λj =<br />
hj + hj−1<br />
µj = 1 − λj<br />
6<br />
dj =<br />
hj + hj−1<br />
Für den natürlichen Spline setzt man noch<br />
yj+1 − yj<br />
hj<br />
λ0 = d0 = dn = µn = 0. 1<br />
1.2 Implementierung in <strong>MATLAB</strong><br />
− yj<br />
<br />
− yj−1<br />
.<br />
hj−1<br />
In diesem Abschnitt werden uns ein kurzes <strong>MATLAB</strong> Skript ansehen, welches die Koeffizienten der<br />
Polynome die den kubischen Spline beschreiben ausrechnet. Da dies nur eine kurze Motivation für die<br />
Verwendung von <strong>MATLAB</strong> sein soll, werden wir die Implementierung nicht in voller Ausführlichkeit<br />
besprechen. Die genaue Funktionsweise sollte mit Hilfe der späteren Ausführungen verständlich werden.<br />
Die Funktion kspline bekommt als Eingabeparameter ein Vektor x mit den Stützstellen und ein<br />
Vektor y mit den zu interpolierenden Werten. Zurückgegeben wird eine (n − 1) × 4-Matrix, in deren i-ter<br />
Zeile die Koeffizienten des kubischen Polynoms des Intervalls [xi, xi+1] stehen.<br />
1 function [ P ] = k s p l i n e ( x , y )<br />
2 n = length ( x ) ;<br />
3 j j = 1 : n−1; j = 2 : n−1;<br />
4 h = [ x ( j j +1)−x ( j j ) ] ;<br />
5 lambda = [ 0 , h ( j +1)./( h ( j )+h ( j + 1 ) ) ] ;<br />
6 mu = [1−lambda ( j ) , 0 ] ;<br />
7 d = [ 0 , ( 6 . / ( h ( j )+h ( j + 1 ) ) ) . ∗ ( ( y ( j +1)−y ( j ) ) . / h ( j +1) . . .<br />
8 − ( y ( j )−y ( j −1))./ h ( j ) ) , 0 ] ;<br />
9 A = 2∗eye ( n ) + diag ( lambda , 1) + diag (mu, −1);<br />
10 M = (A \ d ’ ) ’ ;<br />
11 alpha = y ( j j ) ; gamma = M( j j ) / 2 ;<br />
12 beta = ( y ( j j +1)−y ( j j ) ) . / h ( j j +1) − h ( j j +1).∗(2∗M( j j )+M( j j +1))/6;<br />
13 d e l t a = (M( j j +1)−M( j j ) ) . / ( 6 ∗ h ( j j +1));<br />
14 P = [ alpha ’ , beta ’ , gamma’ , delta ’ ] ;<br />
15 end<br />
In der ersten Zeile des Skripts speichern wir die Anzahl der Punkte in der Variable n und erzeugen<br />
Vektoren jj und j in dem die Zahlen von 1 bzw. 2 bis n − 1 stehen. Dann berechnen wir die Länge<br />
der Intervalle [xi, xi+1] und speichern diese in h. Auf dieselbe Weise berechnen wir die λi, µi und di. Die<br />
Einträge λ0, µn, d0 und dn werden hierbei explizit auf Null gesetzt. Man sieht, wie sich die Formeln aus<br />
dem vorherigen Abschnitt nahezu eins zu eins im <strong>MATLAB</strong> Code wiederfinden.<br />
In Zeile 9 erzeugen wir die Matrix aus (1.1) indem wir auf eine mit zwei multiplizierte Einheitsmatrix<br />
die Vektoren lambda und mu auf die Nebendiagonalen addieren.<br />
Der Aufruf M = (A \ d’)’; löst nun das Gleichungssystem (1.1). Der hierbei verwendete Backslash-<br />
Operator wählt automatisch das Verfahren welches das Gleichungssystem möglichst effizient löst, z.B.<br />
eine Cholesky-Zerlegung bei einer symmetrisch positiv definiten Matrix. Da Vektoren in <strong>MATLAB</strong> standardmäßig<br />
Zeilenvektoren sind, müssen wir die rechte Seite d mit ’ transponieren und die Lösung auf die<br />
selbe Weise zurück in einen Zeilenvektor transformieren. Alternativ hätten wir auch den Slash-Operator<br />
verwenden können, um das zweimalige Transponieren zu vermeiden: M = d / A;.<br />
Nachdem die Momente bestimmt sind, berechnen die letzten Zeilen der Funktion die Koeffizienten<br />
des Polynoms und schreiben sie in die (n − 1) × 4-Matrix P. Damit ist alles berechnet.<br />
An diesem Beispiel kann man gut erkennen, wie effektiv der gegebene Algorithmus implementiert<br />
wurde. Wir sind komplett ohne Kontrollstrukturen wie z.B. Schleifen ausgekommen. Zusätzlich lässt sich<br />
der Programmcode sehr gut lesen und ist gut verständlich.<br />
1 Mit dieser Wahl folgt sofort M0 = S ′′ (x0) = Mn = S ′′ (xn) = 0<br />
8
Das folgende Beispiel demonstriert die Verwendung der Methode um einen kubischen Spline zu berechnen,<br />
der die Wurzelfunktion im Intervall [0, 1] interpoliert:<br />
>> x=0:0.1:1;<br />
>> y=sqrt(x);<br />
>> P=kspline(x,y)<br />
P =<br />
0 3.4008 3.5780 -59.6338<br />
0.3162 2.2081 -14.3121 53.2933<br />
0.4472 0.9445 1.6759 -10.7011<br />
0.5477 0.9587 -1.5345 4.2121<br />
0.6325 0.7781 -0.2708 -0.4530<br />
0.7071 0.7104 -0.4067 0.5202<br />
0.7746 0.6446 -0.2507 0.1069<br />
0.8367 0.5977 -0.2186 0.1827<br />
0.8944 0.5595 -0.1638 -0.0523<br />
0.9487 0.5236 -0.1795 0.7479<br />
Das Intervall wird in äquidistante Stücke der Länge 0.1 unterteilt und dann die Werte der Wurzelfunktion<br />
an den Intervallgrenzen in y gespeichert. Mit diesen Informationen füttern wir unsere Routine kspline,<br />
die uns das gewünschte Ergebnis zurückliefert.<br />
1.3 Visualisierung<br />
Im letzten Abschnitt haben wir die Koeffizienten der Polynome des kubischen Splines berechnet. <strong>Eine</strong><br />
weitere Stärke von <strong>MATLAB</strong> ist die Visualisierung. Deshalb wollen wir uns im folgenden noch eine weitere<br />
Funktion ansehen, die den Spline auf den Bildschirm plottet.<br />
1 function p l o t S p l i n e ( x , P )<br />
2 hold on ;<br />
3 g = 1 0 ;<br />
4 for i =1: length ( x)−1<br />
5 X = ( x ( i ) : ( x ( i +1)−x ( i ) ) / g : x ( i +1))−x ( i ) ;<br />
6 Y = P( i , : ) ∗ [ ones ( 1 , length (X) ) ; X; X. ^ 2 ; X. ^ 3 ] ;<br />
7 plot (X+x ( i ) ,Y) ;<br />
8 end<br />
9 hold o f f ;<br />
10 end<br />
Die Routine zeichnet die Funktion intervallweise, dazu verwenden wir eine for Schleife. Jedes Intervall<br />
verschieben wir in den Ursprung und unterteilen es in g=10 Teile auf denen wir das Polynom auswerten<br />
wollen. Die Koordinaten der Punkte speichern wir in X. Mit dem Befehl<br />
Y= P(i,:)*[ones(1,length(X)); X; X.^2; X.^3];<br />
berechnen wir das Skalarprodukt der i-ten Zeile der Matrix P mit dem Vektor der aus den Faktoren<br />
(x − xi) k , k = 0, . . . , 3 besteht für jede Stelle x aus X.<br />
Das eigentliche Plotten übernimmt der plot Befehl welcher in seiner einfachsten Version Vektoren mit<br />
x− und y−Koordinaten der Punkte erwartet. Diese werden automatische mit Geradenstücken verbunden.<br />
Normalerweise überschreibt <strong>MATLAB</strong> mit jedem plot Befehl die alte Graphik. Dies kann unterbunden<br />
werden durch die Angabe von hold on;.<br />
Der folgende Aufruf plottet den kubischen Spline und die Funktion sqrt(x) im Intervall [0, 1]:<br />
>> x=0:0.1:1;<br />
>> y=sqrt(x);<br />
>> xx=0:0.01:1;<br />
>> plotSpline(x, kspline(x,y)); hold on; plot(xx, sqrt(xx), ’r’);<br />
Abbildung 1.3 zeigt das Ergebniss.<br />
9
1.4 Erweiterung<br />
Abbildung 1.1: Kubischer Spline der Wurzelfunktion<br />
<strong>Eine</strong> weitere Qualität von <strong>MATLAB</strong> ist die einfache Möglichkeit vorhandene Algorithmen zu ersetzen.<br />
Wir wollen dies an der Funktion kspline vorführen.<br />
Bei Beispielen mit wenig Knotenpunkten arbeitet kspline recht schnell, wird die Zahl der Knotenpunkte<br />
jedoch groß, wird die Funktion überproportional langsamer, auch der Speicherbedarf steigt stark<br />
an. Die Erklärung hierfür ist, dass die Zeit für das Lösen des größer werdenden Gleichungssystems (1.1)<br />
n Zeit (1000 Ausführungen) Speicher Zeit (A dünn) Speicher (A dünn)<br />
100 0.79sec 93kB 0.87sec 17kB<br />
200 2.57sec 342kB 1.33sec 34kB<br />
400 32.00sec 1309kB 2.44sec 68kB<br />
800 138.00sec 5118kB 4.85sec 137kB<br />
1600 570.00sec 20237kB 9.64sec 275kB<br />
Tabelle 1.1: Laufzeiten von kspline<br />
nicht proportional mit der Anzahl der Unbekannten wächst. Die Matrix ist jedoch nur dünn besetzt (fast<br />
alle Einträge sind Null) und hat eine sehr einfache Struktur (Tridiagonal). Diese Tatsache wollen wir im<br />
Folgenden ausnutzen.<br />
<strong>MATLAB</strong> unterstützt dünnbesetzte Matrizen, hierbei werden im wesentlichen nur die Einträge gespeichert,<br />
die von Null verschieden sind. Zusätzlich erkennt der Gleichungssystemlöser die Bandstruktur der<br />
Matrix und verwendet effiziente Algorithmen um das System zu lösen. Das einzige was wir machen müssen<br />
um diese Funktionen zu verwenden ist die Matrix A dünn besetzt zu erzeugen, alles andere übernimmt<br />
<strong>MATLAB</strong> für uns. Dies können wir machen, in dem wir z.B. die Zeile 9 durch die folgende ersetzen:<br />
A = 2*speye(n) + spdiags([[lambda, 0]’, [mu, 0]’], [1, -1], n, n);<br />
Die neue Version berechnet die Lösung der Interpolationsaufgabe in optimaler Komplexität: Bei Verdoppelung<br />
der Punkte verdoppelt sich auch die Zeit (und Speicherbedarf) zum Berechnen des Splines (s.<br />
Tabelle 1.1).<br />
1.5 Zusammenfassung<br />
Wir haben in diesem Kapitel gesehen wie man einen Algorithmus mit wenigen Zeilen (25) in <strong>MATLAB</strong><br />
implementiert und sich das Ergebnis grafisch darstellen lassen kann.<br />
Zusätzlich konnten wir durch Ändern nur einer Zeile einen nicht optimale Methode in eine mit linearer<br />
Laufzeit umwandeln. <strong>MATLAB</strong> übernimmt die komplette Arbeit und verwendet automatischen einen<br />
optimalen Algorithmus um das Gleichungssystem zu lösen.<br />
10
Kapitel 2<br />
Vektoren und Matrizen<br />
Wie schon in der Einleitung erwähnt, ist der Umgang mit Feldern eine Besonderheit von <strong>MATLAB</strong>.<br />
Ein Verständnis dieser ist essentiell für die effektive Verwendung von <strong>MATLAB</strong>. Da aus mathematischer<br />
Sicht insbesondere Vektoren und Matrizen interessant sind, werden wir uns in dieser <strong>Einführung</strong> auf diese<br />
beschränken. Die Behandlung höherdimensionaler Felder erfolgt in vielen Fällen analog.<br />
2.1 Matrizen erzeugen<br />
Matrizen können auf mehrere Arten erzeugt werden. Viele Typen von Matrizen können direkt über eine<br />
<strong>MATLAB</strong> Funktion generiert werden. Die Nullmatrix, die Einheitsmatrix und Einsmatrizen können über<br />
die Funktionen zeros, eye und ones erzeugt werden. Alle haben die gleiche Syntax. Zum Beispiel erzeugt<br />
zeros(m,n) oder zeros([m,n]) eine m×n Nullmatrix, während zeros(n) eine n×n Nullmatrix erzeugt.<br />
>> zeros(2)<br />
ans =<br />
0 0<br />
0 0<br />
>> ones(2,3)<br />
ans =<br />
1 1 1<br />
1 1 1<br />
>> eye(3,2)<br />
ans =<br />
1 0<br />
0 1<br />
0 0<br />
Zwei andere Matrizen erzeugende Funktionen sind rand und randn, die Matrizen mit Pseudozufallszahlen<br />
als Einträgen generieren. Die Syntax ist die gleiche wie bei eye. Die Funktion rand erzeugt eine<br />
Matrix mit Zahlen aus der Gleichverteilung über dem Einheitsintervall [0, 1]. 1 randn erzeugt eine Matrix<br />
deren Einträge standardnormalverteilt sind. Ohne Argumente geben beide Funktionen eine einzelne<br />
Zufallszahl zurück.<br />
>> rand<br />
ans =<br />
0.9501<br />
1 Für diese Verteilung ist der Anteil der Zahlen aus einem Intervall [a, b] mit 0 < a < b < 1 stets b − a.<br />
11
and(3)<br />
ans =<br />
0.2311 0.8913 0.0185<br />
0.6068 0.7621 0.8214<br />
0.4860 0.4565 0.2835<br />
Bei Experimenten mit Zufallszahlen ist es oft wichtig, die gleichen Zufallszahlen erneut zu erzeugen.<br />
Die Zahlen, die von rand (bzw. randn) erzeugt werden hängen vom Zählerstand des Generators ab.<br />
Dieser Zähler kann über den Befehl rand(’state’,j) (bzw. randn(’state’,j)) gesetzt werden, mit<br />
einer nicht-negativen ganzen Zahl j. j=0 ist der Anfangszustand des Generators (diesen Zustand hat<br />
der Generator, wenn <strong>MATLAB</strong> startet). Möchte man nicht bei jedem Start von <strong>MATLAB</strong> dieselben<br />
Zufallszahlen zu bekommen, sollte der Generator durch den Befehl rand(’state’,sum(100*clock)) auf<br />
einen von der Zeit abhängigen Zustand gesetzt werden. Die Periode von rand und randn, also die Anzahl<br />
Terme die erzeugt werden, bevor sich Teilfolgen wiederholen, übersteigt 2 1492 ≈ 10 449 .<br />
Mit der Funktion diag können Diagonalmatrizen angelegt werden. Für einen Vektor x erzeugt diag(x)<br />
eine Diagonalmatrix mit der Diagonale x.<br />
>> diag([1 2 3])<br />
ans =<br />
1 0 0<br />
0 2 0<br />
0 0 3<br />
Allgemeiner legt diag(x,k) x auf die k-te Diagonale, wobei k > 0 Diagonalen über der Hauptdiagonalen<br />
beschreibt, und k < 0 die darunter (k = 0 bezeichnet die Hauptdiagonale).<br />
>> diag([1 2],1)<br />
ans =<br />
0 1 0<br />
0 0 2<br />
0 0 0<br />
>> diag([3 4],-2)<br />
ans =<br />
0 0 0 0<br />
0 0 0 0<br />
3 0 0 0<br />
0 4 0 0<br />
Matrizen können explizit über die Klammernotation (square bracket notation) erzeugt werden. Zum<br />
Beispiel kann eine 3x3-Matrix mit den ersten neun Primzahlen mit folgendem Befehl erzeugt werden:<br />
>> A = [2 3 5<br />
7 11 13<br />
17 19 23]<br />
A =<br />
2 3 5<br />
7 11 13<br />
17 19 23<br />
Das Ende einer Zeile kann über ein Semikolon anstatt eines Zeilenumbruchs angegeben werden. Ein<br />
kürzere Variante des letzten Beispiels ist also:<br />
>> A = [2 3 5; 7 11 13; 17 19 23]<br />
12
Innerhalb einer Zeile können einzelne Elemente über ein Leerzeichen oder Komma getrennt werden.<br />
In ersterem Fall sollte beachtet werden, dass bei Angabe von Vorzeichen für die einzelnen Einträge<br />
kein Leerzeichen zwischen Vorzeichen und Element gelassen werden darf. <strong>MATLAB</strong> interpretiert das<br />
Vorzeichen sonst als Plus oder Minus Operator.<br />
>> v = [-1 2 -3 4]<br />
v =<br />
-1 2 -3 4<br />
>> w = [-1,2,-3,4]<br />
w =<br />
-1 2 -3 4<br />
>> x = [-1 2 - 3 4]<br />
x =<br />
-1 -1 4<br />
Häufig sehr praktisch ist das Erzeugen von Matrizen durch Angabe von Blöcken, anstatt der einzelnen<br />
Elemente. Sei z.B. B=[1 2; 3 4]:<br />
>> C = [B zeros(2); ones(2) eye(2)]<br />
C =<br />
1 2 0 0<br />
3 4 0 0<br />
1 1 1 0<br />
1 1 0 1<br />
Blockdiagonalmatrizen können noch einfacher direkt über die Funktion blkdiag erzeugt werden.<br />
>> A = blkdiag(B,ones(2))<br />
A =<br />
1 2 0 0<br />
3 4 0 0<br />
0 0 1 1<br />
0 0 1 1<br />
Für ”getäfelte” Blockmatrizen eignet sich repmat: repmat(A,m,n) erzeugt eine Block-m × n-Matrix, in<br />
der jeder Block eine Kopie von A ist. Wird n weggelassen, wird der Wert standardmäßig auf m gesetzt.<br />
>> B=[1,2;3,4];<br />
>> A = repmat(B,2)<br />
A =<br />
1 2 1 2<br />
3 4 3 4<br />
1 2 1 2<br />
3 4 3 4<br />
2.1.1 Spezielle Matrizen<br />
<strong>MATLAB</strong> verfügt über Funktionen um ganz spezielle Matrizen zu erzeugen. Ein Beispiel hierfür sind die<br />
Hilbertmatrizen, deren Elemente aij den Wert 1/(i + j − 1) haben. Die Matrix wird durch den Befehl<br />
hilb erzeugt, und ihre Inverse (die nur ganzzahlige Komponenten hat!) über invhilb.<br />
Quadratische n × n Matrizen die nur aus den Zahlen 1, . . . , n 2 bestehen, deren Zeilen- und Spaltensummen<br />
und Summe der Einträge der Diagonalen gleich ist nennt man magische Quadrate. Diese können<br />
mit <strong>MATLAB</strong> durch die Funktion magic erzeugt werden.<br />
13
magic(3)<br />
ans =<br />
8 1 6<br />
3 5 7<br />
4 9 2<br />
Über fünfzig weitere spezielle und berühmte Matrizen können mit dem Befehl gallery erzeugt werden,<br />
diese sind teilweise dünn besetzt. Mehr über diese speziellen Matrizen erfährt man in der Hilfe.<br />
2.1.2 Doppelpunkt Operator<br />
Der Doppelpunkt Operator ist einer der wichtigsten Operatoren in <strong>MATLAB</strong> und findet in vielen Fällen<br />
Verwendung. Mit seiner Hilfe können spezielle Zeilenvektoren erzeugt werden, die z.B. bei der Indizierung<br />
in for Schleifen oder beim Plotten verwendet werden. Dabei wird ausgehend von einer Zahl solange eine<br />
Einheit addiert und in dem Vektor gespeichert, bis ein vorgegebenes Ende erreicht oder überschritten<br />
wurde. Die allgemeine Syntax ist<br />
: oder ::.<br />
Ein paar Beispiele sollte die Verwendung deutlich machen:<br />
>> j=1:5<br />
j =<br />
1 2 3 4 5<br />
>> X=1.2:0.2:2<br />
X =<br />
1.2000 1.4000 1.6000 1.8000 2.0000<br />
>> X=1:-0.3:0<br />
X =<br />
1.0000 0.7000 0.4000 0.1000<br />
Dem Doppelpunkt Operator verwandt ist die Funktion linspace, die als Eingabe neben Start und<br />
Ende die Anzahl der zu erzeugenden Punkte verlangt anstatt des Abstandes. linspace(a,b,n) erzeugt<br />
n Punkte gleichen Abstands zwischen a und b. Der Standardwert für n ist 100.<br />
>> linspace(-1,1,9)<br />
ans =<br />
Columns 1 through 6<br />
-1.0000 -0.7500 -0.5000 -0.2500 0 0.2500<br />
Columns 7 through 9<br />
0.5000 0.7500 1.0000<br />
2.2 Indizierung und Doppelpunktnotation<br />
Die Indizierung von Feldern erfolgt in <strong>MATLAB</strong> durch runde Klammern und startet wie bei Fortran<br />
beim Index 1. Bei Matrizen steht der erste Index für die Zeilen-, der zweite für die Spaltennummer des<br />
Elements.<br />
>> A=rand(2,2)<br />
14
A =<br />
0.6557 0.8491<br />
0.0357 0.9340<br />
>> A(1,1)<br />
ans =<br />
0.6557<br />
>> A(2,1)<br />
ans =<br />
0.0357<br />
Es gibt bei <strong>MATLAB</strong> keine nicht positiven Indices, der Versuch wird durch eine Fehlermeldung bestraft:<br />
>> A(0,0)<br />
??? Attempted to access A(0,0); index must be a positive integer or logical.<br />
Ein Vorteil von <strong>MATLAB</strong> gegenüber anderen Programmiersprachen ist, dass nicht nur auf die einzelnen<br />
Elemente eines Feldes zugegriffen werden kann, sondern auf beliebige Teilblöcke. Dafür ersetzt<br />
man einfach beim Indizieren die Zahlen durch Vektoren. Sei A eine n × m-Matrix und r und c Vektoren<br />
mit positiven ganzzahligen Elementen kleiner gleich n (bzw. m). Dann ist B=A(r,c) eine Matrix mit<br />
Einträgen bij =A(r(i),c(j)).<br />
>> A=[1,2,3;4,5,6;7,8,9]<br />
A =<br />
1 2 3<br />
4 5 6<br />
7 8 9<br />
>> A([1,2],3)<br />
ans =<br />
3<br />
6<br />
>> A([2,3],[2,3])<br />
ans =<br />
5 6<br />
8 9<br />
Besonders häufig wird in diesen Fällen der Doppelpunktoperator verwendet. Die Teilmatrix bestehend<br />
aus der Schnittmenge der Zeilen p bis q und den Spalten r bis s wird mit A(p:q,r:s) zurückgegeben. Ein<br />
Sonderfall ist ein einzelner Doppelpunkt, dieser wählt sämtliche Zeilen oder Spalten; A(:,j) bezeichnet<br />
also die j-te Spalte, und A(i,:) die i-te Zeile von A. Das Schlüsselwort end steht für den letzten Index in<br />
der angegebenen Dimension; A(end,:) bezeichnet also die letzte Zeile von A.<br />
>> A(1:3,2:end)<br />
ans =<br />
2 3<br />
5 6<br />
8 9<br />
>> A(1,:)<br />
ans =<br />
15
1 2 3<br />
>> A(:,end)<br />
ans =<br />
3<br />
6<br />
9<br />
<strong>MATLAB</strong> speichert alle Felder intern als Spaltenvektor, Matrizen spaltenweise von der ersten zur<br />
letzten Spalte. Auf diese Repräsentation kann durch Angabe nur eines Indizes zugegriffen werden, dies<br />
wird häufig lineares Indizieren genannt.<br />
>> A(:)<br />
ans =<br />
1<br />
4<br />
7<br />
2<br />
5<br />
8<br />
3<br />
6<br />
9<br />
>> A(4)<br />
ans =<br />
2<br />
Wird A(:) auf der linken Seite einer Zuweisung benutzt, so wird damit A gefüllt, unter Beibehaltung<br />
der Struktur von A. Mit dieser Notation ergibt sich eine Möglichkeit auf folgende Weise eine 3×3 - Matrix<br />
der ersten 9 Primzahlen zu erzeugen:<br />
>> A = zeros(3); A(:) = primes(23); A = A’<br />
A =<br />
2 3 5<br />
7 11 13<br />
17 19 23<br />
Die Funktion primes erzeugt einen Vektor von Primzahlen, die kleiner oder gleich dem Eingabeargument<br />
sind. Die Transposition A = A’ ist nötig um die Primzahlen entlang der Zeilen anstatt entlang der<br />
Spalten anzuordnen.<br />
<strong>Eine</strong> weitere Funktion die beim Indizieren hilfreich ist, ist sub2ind. Diese berechnet aus Matrixindizes<br />
lineare Indizes. Hiermit können wir z.B. die Diagonale der obigen Matrix A mit 1 überschreiben.<br />
>> A(sub2ind(size(A), 1:3, 1:3))=1<br />
A =<br />
1 3 5<br />
7 1 13<br />
17 19 1<br />
2.3 Operatoren und Funktionen<br />
Um ein Feld zu transponieren stellt <strong>MATLAB</strong> die Operatoren ’ und .’ zur Verfügung. Die Operatoren<br />
unterscheiden sich, wenn die Einträge des Feldes komplex sind, ’ erzeugt die adjungierte Matrix A ∗ , .’<br />
die Transponierte A T .<br />
16
A=[1+i , 2-i; 1 , 2]<br />
A =<br />
1.0000 + 1.0000i 2.0000 - 1.0000i<br />
1.0000 2.0000<br />
>> A’<br />
ans =<br />
1.0000 - 1.0000i 1.0000<br />
2.0000 + 1.0000i 2.0000<br />
>> A.’<br />
ans =<br />
1.0000 + 1.0000i 1.0000<br />
2.0000 - 1.0000i 2.0000<br />
2.3.1 Rechenoperatoren<br />
<strong>MATLAB</strong> unterstützt das Rechnen mit Vektoren und Matrizen. So können zwei Felder gleicher Dimensionen<br />
einfach durch + addiert und mit - subtrahiert werden:<br />
>> x=1:3;<br />
>> y=2:4;<br />
>> x+y<br />
ans =<br />
3 5 7<br />
>> eye(2)-ones(2)<br />
ans =<br />
0 -1<br />
-1 0<br />
<strong>MATLAB</strong> interpretiert den Multiplikationsoperator * als Matrixprodukt oder als Multiplikation mit<br />
einem Skalar. Bei ersterem muss die Anzahl der Spalten des ersten Arguments gleich der Anzahl der<br />
Zeilen des zweiten Argumentes sein. Daneben gibt es noch den elementweisen Multiplikationsoperator<br />
.*.<br />
>> x=1:3;<br />
>> y=2:4;<br />
>> x*y<br />
??? Error using ==> mtimes<br />
Inner matrix dimensions must agree.<br />
>> x*y’<br />
ans =<br />
20<br />
>> x.*y<br />
ans =<br />
2 6 12<br />
>> A=[1,2,3;4,5,6;7,8,9];<br />
>> A*y<br />
17
ans =<br />
20<br />
47<br />
74<br />
>> 2*A<br />
ans =<br />
2 4 6<br />
8 10 12<br />
14 16 18<br />
Auch das Potenzieren ^ wird im Matrixprodukt Sinn interpretiert, analog zur Multiplikation gibt es auch<br />
die „gepunktete“ Version .^.<br />
Die Division gibt es in zwei Ausführungen: den Slash / und den Backslash \. Beide entsprechem dem<br />
(ggf. approximativen) Lösen eines linearen Gleichungssystems. B/A steht ungefähr für BA −1 , A\B für<br />
A −1 B). Mit diesen Operatoren befassen wir uns ausführlich in Abschnitt 5.2.<br />
>> A=hilb(2);<br />
>> b=[1;2]<br />
b =<br />
1<br />
2<br />
>> A\b<br />
ans =<br />
-8<br />
18<br />
>> invhilb(2)*b<br />
ans =<br />
-8<br />
18<br />
Natürlich gibt es auch wieder das elementweise dividieren ./, dieses muss auch eingesetzt werden, wenn<br />
ein Skalar durch einen Vektor geteilt wird.<br />
>> x=1:3<br />
>> 3/x<br />
??? Error using ==> mrdivide<br />
Matrix dimensions must agree.<br />
>> 3./x<br />
ans =<br />
3.0000 1.5000 1.0000<br />
>> x./x<br />
ans =<br />
1 1 1<br />
2.3.2 Basisfunktionen<br />
Um Eigenschaften wie die Länge oder Dimensionen von Feldern abzufragen gibt es in <strong>MATLAB</strong> eine<br />
Hand voll Funktionen:<br />
18
length Gibt die Länge eines Vektors zurück, bei einer Matrix wird die größere der beiden Dimensionen<br />
zurückgegeben.<br />
size Gibt die Dimensionen einer Matrix zurück.<br />
numel Gibt die Anzahl der Elemente einer Matrix zurück, numel(A)==prod(size(A))==length(A(:))<br />
>> B=[1,2;2,3;4,5]<br />
B =<br />
1 2<br />
2 3<br />
4 5<br />
>> length(B)<br />
ans =<br />
3<br />
>> size(B)<br />
ans =<br />
3 2<br />
>> numel(B)<br />
ans =<br />
6<br />
2.3.3 Funktionen<br />
<strong>MATLAB</strong> verfügt über unzählige Funktionen die Vektoren und Matrizen als Eingabe erwarten. Grundsätzlich<br />
verändert eine Funktion in <strong>MATLAB</strong> kein Eingabeargument. 2 Viele dieser Methoden kann man<br />
einer von drei Gruppen zuordnen:<br />
• Skalare Funktionen<br />
• Vektorfunktionen<br />
• Matrixfunktionen<br />
Skalare Funktionen sind solche, die komponentenweise wirken. Beispiele sind sin, cos, exp und<br />
factorial (Fakultät). Übergibt man diesen Funktionen ein mehrdimensionales Feld, hat die Rückgabe<br />
die gleiche Dimensionen wie das Eingabeargument und die Funktion wurde auf jeden Eintrag des<br />
Feldes angewendet.<br />
>> x=linspace(-pi/2,pi/2,5)<br />
x =<br />
-1.5708 -0.7854 0 0.7854 1.5708<br />
>> sin(x)<br />
ans =<br />
-1.0000 -0.7071 0 0.7071 1.0000<br />
>> A=magic(3);<br />
>> factorial(A)<br />
ans =<br />
2 Eingabeargumente werden als Wert und nicht als Referenz übergeben.<br />
19
40320 1 720<br />
6 120 5040<br />
24 362880 2<br />
Vektorwertige Funktionen operieren auf Vektoren und geben ein Skalar oder einen Vektor zurück.<br />
Beispiele sind max, sum, prod mit skalarem Rückgabewert, diff (Differenz jeweils aufeinander folgender<br />
Elemente), cumsum oder sort geben einen Vektor zurück. Übergibt man diesem Typ von Funktion eine<br />
Matrix, wird die Funktion auf jede Spalte angewendet und die Rückgabe wieder in eine Spalte geschrieben.<br />
>> x=1:4;<br />
>> sum(x)<br />
ans =<br />
10<br />
>> max(x)<br />
ans =<br />
4<br />
>> diff(x)<br />
ans =<br />
1 1 1<br />
>> A=magic(3);<br />
>> sum(A)<br />
ans =<br />
15 15 15<br />
>> cumsum(A)<br />
ans =<br />
8 1 6<br />
11 6 13<br />
15 15 15<br />
Viele vektorwertige Funktionen unterstützen die Übergabe eines zweiten Parameters dim, der die Dimension<br />
(1=Spalten, 2=Zeilen) angibt, über welche die Funktion ausgeführt werden soll. Damit ist es also<br />
z.B. auch einfach möglich die Summe der Zeilen von A zu berechnen:<br />
>> sum(A,2)<br />
ans =<br />
15<br />
15<br />
15<br />
Möchte man diese Funktion nicht auf die Spalten einer Matrix A sondern auf die ganze Matrix -als<br />
Vektor aufgefasst- anwenden, übergibt man A(:) als Eingabeargument (vgl. 2.2).<br />
>> sum(A(:))<br />
ans =<br />
45<br />
Matrixfunktionen erwarten als Eingabe eine Matrix. Beispiele sind norm, chol, triu und tril. Die<br />
letzten beiden Funktionen extrahieren aus einer gegebenen Matrix eine obere, bzw. untere Dreiecksmatritzen.<br />
Allgemein gibt tril(A,k) (bzw. triu(A,k)) die Elemente auf und unter (bzw. ober) der k-ten<br />
Diagonale zurück.<br />
20
A = [2 3 5; 7 11 13; 17 19 23]<br />
A =<br />
2 3 5<br />
7 11 13<br />
17 19 23<br />
>> tril(A)<br />
ans =<br />
2 0 0<br />
7 11 0<br />
17 19 23<br />
>> triu(A,1)<br />
ans =<br />
0 3 5<br />
0 0 13<br />
0 0 0<br />
2.4 Matrizen manipulieren<br />
Es gibt mehrere Befehle für die Manipulation von Matrizen. Die Funktion reshape ändert die Dimensionen<br />
einer Matrix: reshape(A,m,n) erzeugt eine m × n Matrix, deren Elemente spaltenweise aus A<br />
entnommen werden.<br />
>> A = [1 4 9; 16 25 36], B = reshape(A,3,2)<br />
A =<br />
B =<br />
1 4 9<br />
16 25 36<br />
1 25<br />
16 9<br />
4 36<br />
Die Notation [] steht für eine leere 0 × 0-Matrix. Weist man einer Zeile oder Spalte einer Matrix den<br />
Wert [] zu, so wird sie aus der Matrix gelöscht.<br />
>> A=magic(3)<br />
A =<br />
8 1 6<br />
3 5 7<br />
4 9 2<br />
>> A(2,:)=[]<br />
A =<br />
8 1 6<br />
4 9 2<br />
In diesem Beispiel würde der gleiche Effekt durch A = A([1 3],:) erzielt werden. Die leere Matrix<br />
ist auch als Platzhalter in Argumentlisten nützlich.<br />
An einen vorhandenen Vektor können einfach weitere Elemente angehängt werden, indem man einem<br />
Index der größer als die Länge des Vektors ist, einen Wert zuweist. Der Vektor wird daraufhin automatisch<br />
bis zu dem entsprechenden Index verlängert und mit Nullen gefüllt.<br />
21
x=1:3;<br />
>> x(6)=9<br />
x =<br />
1 2 3 0 0 9<br />
Auf dieselbe Weise können neue Zeilen und Spalten an eine Matrix angehängt werden:<br />
>> A=eye(2)<br />
A =<br />
1 0<br />
0 1<br />
>> A(3,:)=[1,1]<br />
A =<br />
1 0<br />
0 1<br />
1 1<br />
>> A(:,3)=2<br />
A =<br />
1 0 2<br />
0 1 2<br />
1 1 2<br />
>> A=eye(2)<br />
A =<br />
1 0<br />
0 1<br />
>> A(3,3)=2<br />
A =<br />
1 0 0<br />
0 1 0<br />
0 0 2<br />
22
Kapitel 3<br />
Operatoren und Flusskontrolle<br />
3.1 Relationale Operatoren<br />
Die relationalen Operatoren von <strong>MATLAB</strong> sind<br />
== gleich<br />
~= ungleich<br />
< weniger als<br />
> größer als<br />
= größer oder gleich<br />
Tabelle 3.1: Die relationalen Operatoren in <strong>MATLAB</strong><br />
Beachten Sie, dass in <strong>MATLAB</strong> ein einzelnes Gleichheitszeichen = eine Zuweisung angibt und nie auf<br />
Gleichheit testet. Vergleiche zwischen Skalaren erzeugen logisch 1 wenn die Relation wahr und logisch<br />
0 wenn sie falsch ist. <strong>MATLAB</strong> verwenden hier intern keine doubles sondern einen anderen Datentyp<br />
(logical), dies sollte aber in den wenigsten Fällen zu Problemen führen.<br />
Vergleiche sind auch zwischen Matrizen gleicher Dimension definiert und zwischen Matrizen und Skalaren,<br />
deren Ergebnis in beiden Fällen eine Matrix mit Nullen und Einsen ist. Für Matrix-Matrix Vergleiche<br />
werden die entsprechenden Paare von Elementen verglichen, während für Matrix-Skalar Vergleiche der<br />
Skalar mit jedem Matrixelement verglichen wird.<br />
>> A = [1 2; 3 4]; B = 2*ones(2);<br />
>> A==B<br />
ans =<br />
0 1<br />
0 0<br />
>> A>2<br />
ans =<br />
0 0<br />
1 1<br />
Um zu testen ob zwei Matrizen A und B gleich sind, kann der Ausdruck isequal(A,B) verwendet<br />
werden. Die Funktion isequal is eine der vielen nützlichen logischen Funktionen, deren Namen mit is<br />
beginnt. Für eine Liste aller dieser Funktionen rufen sie in <strong>MATLAB</strong> doc is auf. Die Funktion isnan<br />
ist besonders wichtig, da der Test x == NaN immer das Ergebnis 0 (falsch) liefert, selbst wenn x = NaN!<br />
(Ein NaN ist gerade so definiert, dass er zu allem ungleich und ungeordnet ist).<br />
3.2 Logische Operatoren<br />
Die logischen Operatoren von <strong>MATLAB</strong> sind<br />
23
& logisches und<br />
| logisches oder<br />
∼ logisches nicht<br />
xor logisches exklusives oder<br />
all wahr wenn alle Elemente eines Vektors von<br />
Null verschieden sind<br />
any wahr wenn wenigstens ein Element eines Vektors<br />
von Null verschieden ist<br />
Tabelle 3.2: Die logischen Operatoren in <strong>MATLAB</strong><br />
Wie die relationalen Operatoren produzieren &,| und ∼ Matrizen von Nullen und Einsen, falls eines<br />
der Argumente eine Matrix ist. Die Funktion all gibt, wenn sie auf einen Vektor angewendet wird, 1<br />
zurück wenn alle Elemente des Vektors verschieden von 0 sind, und 0 sonst. Die any Funktion ist ebenfalls<br />
so definiert, wobei ’irgendeiner’ hier ’alle’ ersetzt. Beispiele:<br />
>> x = [-1 1 1]; y = [1 2 -3];<br />
>> x>0 & y>0<br />
ans =<br />
0 1 0<br />
>> x>0 | y>0<br />
ans =<br />
1 1 1<br />
>> xor(x>0,y>0)<br />
ans =<br />
1 0 1<br />
>> any(x>0)<br />
ans =<br />
1<br />
>> all(x>0)<br />
ans =<br />
0<br />
Beachte, dass xor als Funktion xor(a,b) aufgerufen werden muss. Die Operatoren and, or, not und<br />
die relationalen Operatoren können ebenfalls in funktionaler Form aufgerufen werden, and(a,b) ...(mehr<br />
dazu unter help ops).<br />
Die Funktionen all und any sind Vektorfunktionen (vgl. Abschnitt 2.3.3), deshalb gibt all auf Matrizen<br />
angewandt einen Zeilenvektor zurück der die Ergebnisse von all angewendet auf die Spaltenvektoren<br />
enthält. Mit all(A(:)==B(:)) können die beiden Matrizen A und B auf Gleichheit getestet werden.<br />
3.2.1 Indizierung mit logischen Feldern<br />
Die Rückgabewerte von <strong>MATLAB</strong>s relationalen und logischen Operatoren sind Felder bestehend aus<br />
Nullen und Einsen. Diese sind Beispiele für logische Felder. Sie können auch per Hand erzeugt werden,<br />
indem man den Befehl logical auf ein reelles Feld anwendet. Hierbei werden alle Einträge ungleich 0 zu<br />
logisch 1, alle Einträge gleich 0 zu logisch 0 konvertiert.<br />
>> y=[1 0.2 0 -3 0]<br />
y =<br />
24
1.0000 0.2000 0 -3.0000 0<br />
>> i1 = logical(y)<br />
i1 =<br />
1 1 0 1 0<br />
>> i2 = (y~=0)<br />
i2 =<br />
1 1 0 1 0<br />
Logische Felder können zur Indizierung verwendet werden, hierbei muss das zu indizierende Feld die<br />
gleichen Dimensionen wie das logische Feld haben. Das Ergebnis sind alle Einträge bei denen logisch 1<br />
steht als Spaltenvektor.<br />
>> i3 = [1 1 0 1 0]<br />
i3 =<br />
1 1 0 1 0<br />
>> whos<br />
Name Size Bytes Class<br />
i1 1x5 40 double array (logical)<br />
i2 1x5 40 double array (logical)<br />
i3 1x5 40 double array<br />
y 1x5 40 double array<br />
Grand total is 20 elements using 160 bytes<br />
>> y(i1)<br />
ans =<br />
1.0000 0.2000 -3.0000<br />
>> y(i2)<br />
ans =<br />
1.0000 0.2000 -3.0000<br />
>> isequal(i2,i3)<br />
ans =<br />
1<br />
>> y(i3) ??? Index into matrix is negative or zero. See release<br />
notes on changes to logical indices.<br />
Merke, dass obwohl i2 die gleichen Elemente wie i3 hat (und in <strong>MATLAB</strong> auch als identisch angesehen<br />
wird), nur i2 zur Indizierung verwendet werden kann.<br />
Logische Indizierung wird meistens in Verbindung mit relationalen Operatoren angewandt, z.B. um<br />
die negativen Einträge einer Matrix auf Null zu setzen:<br />
>> A=rand(3)-0.5*ones(3)<br />
A =<br />
0.4649 0.4572 -0.3581<br />
-0.3424 -0.0146 -0.0782<br />
0.4706 0.3003 0.4157<br />
25
A(A> x = [-3 1 0 -inf 0];<br />
>> f=find(x)<br />
f =<br />
1 2 4<br />
Wenn find auf eine Matrix angewendet wird, bezieht sich der Indexvektor auf A als Vektor seiner<br />
Spaltenvektoren (also A(:)), und dieser Vektor kann wiederum verwendet werden, um Elemente in A<br />
anzusprechen. Im folgenden Beispiel benutzen wir find um alle Elemente von A auf 0 zu setzen, die<br />
kleiner sind als die entsprechenden Elemente von B:<br />
>> A=[4 2 16; 12 4 3], B = [12 3 1; 10 -1 7]<br />
A =<br />
B =<br />
4 2 16<br />
12 4 3<br />
12 3 1<br />
10 -1 7<br />
>> f = find(A> A(f) = 0<br />
A =<br />
0 0 16<br />
12 4 0<br />
>> A=[4 2 16; 12 4 3];<br />
>> A(A
if expression<br />
statements<br />
end<br />
statements werden ausgeführt, wenn die Realteile der Elemente von expression alle verschieden von 0<br />
sind. Der folgende Code ersetzt zum Beispiel x und y wenn x größer ist als y:<br />
if x > y<br />
temp = y;<br />
y = x;<br />
x = temp;<br />
end<br />
Folgen auf einen if-Befehl auf der gleichen Zeile weitere Befehle, so müssen diese durch ein Komma<br />
getrennt werden, um das if-Kommando vom nächsten Befehl zu trennen.<br />
>> if x > 0, sqrt(x);end<br />
Befehle die nur ausgeführt werden sollen, wenn expression falsch ist, können nach else eingefügt<br />
werden.<br />
>> e = exp(1);<br />
>> if 2^e > e^2<br />
disp(’2^e is bigger’)<br />
else<br />
disp(’e^2 is bigger’)<br />
end<br />
Schließlich kann mit elseif ein weiterer Test hinzugefügt werden mit (beachte, dass zwischen else<br />
und if kein Leerzeichen stehen darf):<br />
if isnan(x)<br />
disp(’Not a Number’)<br />
elseif isinf(x)<br />
disp(’Plus or minus infinity’)<br />
else<br />
disp(’A ’’regular’’ floating point number’)<br />
end<br />
Bei einer if-Abfrage der Form if Bedingung 1 & Bedingung 2 wird Bedingung 2 nicht ausgewertet,<br />
wenn Bedingung 1 falsch ist (dies wird ”early return” if Auswertung genannt). Dies ist nützlich, wenn<br />
die Auswertung von Bedingung 2 ansonsten einen Fehler produzieren könnte, zum Beispiel durch einen<br />
Index außerhalb des zulässigen Bereichs oder eine nicht definierte Variable.<br />
Die for-Schleife ist einerseits eine der wichtigsten Strukturen in <strong>MATLAB</strong>, andererseits vermeiden<br />
viele Programmierer, die kurzen und schnellen Code produzieren wollen, dessen Verwendung. Die Syntax<br />
lautet:<br />
for variable = ausdruck<br />
statements<br />
end<br />
Normalerweise ist ausdruck ein Vektor der Form i:s:j. Die Befehle werden für jedes Element von<br />
ausdruck ausgeführt, wobei variable dem entsprechenden Element von ausdruck zugeordnet ist. Zum<br />
Beispiel wird die Summe der ersten 25 Elemente der harmonischen Folge 1/i erzeugt durch:<br />
>> s = 0;<br />
>> for i=1:25, s=s+1/i;end,s<br />
s =<br />
3.8160<br />
<strong>Eine</strong> weitere Möglichkeit um ausdruck zu definieren ist, die Klammernotation zu verwenden.<br />
27
for x = [pi/6 pi/4 pi/3], disp([x,sin(x)]), end<br />
0.5236 0.5000<br />
0.7854 0.7071<br />
1.0472 0.8660<br />
Mehrere for-Schleifen können verschachtelt werden. In diesem Fall hilft einrücken, um die Lesbarkeit<br />
des Codes zu erhöhen. Der folgende Code bildet die symmetrische 5x5-Matrix A = (aij) mit aij = i/j<br />
für j >= i:<br />
>> n = 5; A = eye(n);<br />
>> for j=2:n<br />
for i = 1:j-1<br />
A(i,j) = i/j;<br />
A(j,i) = i/j;<br />
end<br />
end<br />
Der ausdruck in der for-Schleife kann eine Matrix sein, in diesem Fall wird variable der Spaltenvektor<br />
zugewiesen, vom Ersten zum Letzten. Zum Beispiel, um x in der Reihenfolge auf jeden Einheitsvektor<br />
zu setzen, kann man for x = eye(n),...,end schreiben.<br />
Die while-Schleife hat die Form<br />
while ausdruck<br />
statements<br />
end<br />
Die Befehle werden ausgeführt, so lange ausdruck wahr ist. Das folgende Beispiel nähert die kleinste<br />
von Null verschiedene Gleitkommazahl an:<br />
>> x=1; while x>0, xmin = x; x = x/2; end, xmin<br />
xmin =<br />
4.9407e-324<br />
<strong>Eine</strong> while-Schleife kann mit dem Befehl break beendet werden, der die Kontrolle an den ersten Befehl<br />
nach dem entsprechenden end zurückgibt. <strong>Eine</strong> unendliche Schleife kann mit while 1, ..., end erzeugt<br />
werden. Dies kann nützlich sein, wenn es ungünstig ist, den Abbruchtest an den Anfang der Schleife zu<br />
setzen. (Merke, dass <strong>MATLAB</strong> im Gegensatz zu manch anderen Sprachen keine ”repeat-until” Schleife<br />
hat.)<br />
Das vorige Beispiel lässt sich damit auch folgendermaßen notieren:<br />
x = 1;<br />
while 1<br />
xmin = x;<br />
x = x/2;<br />
if x == 0, break, end<br />
end<br />
xmin<br />
Der Befehl break kann auch verwendet werden, um eine for-Schleife zu verlassen. In einer verschachtelten<br />
Schleife führt ein break zum Verlassen der Schleife auf der nächsthöheren Ebene. Der Befehl<br />
continue setzt die Ausführung sofort in der nächsten Iteration der for- oder while-Schleife fort, ohne<br />
die verbleibenden Befehle in der Schleife auszuführen.<br />
for i=1:10<br />
if i < 5, continue, end<br />
disp(i)<br />
end<br />
28
In komplexeren Schleifen kann continue verwendet werden um umfangreiche if-Abfragen zu vermeiden.<br />
Zuletzt bleibt noch der Kontrollbefehl switch. Er besteht aus ”switch Ausdruck”, gefolgt von einer<br />
Liste von<br />
”case Ausdruck Befehl”, die optional mit<br />
”otherwise Ausdruck” enden und mit einem end beendet werden. Der Ausdruck bei switch wird<br />
ausgewertet und die Befehle nach dem ersten passenden case Ausdruck werden ausgeführt. Falls keiner<br />
der Fälle passt, werden die Befehle nach otherwise ausgeführt. Das folgende Beispiel wertet die p-Norm<br />
eines Vektors x aus (also norm(x,p)):<br />
switch p<br />
case 1<br />
y = sum(abs(x));<br />
case 2<br />
y = sqrt(x’*x);<br />
case inf<br />
y = max(abs(x));<br />
otherwise<br />
error(’p must be 1, 2 or inf.’)<br />
end<br />
Der Ausdruck nach case kann eine Liste von Werten sein, die in geschweiften Klammern eingeschlossen<br />
ist (ein Cell-Array). In diesem Fall kann der switch-Ausdruck zu jedem Element der Liste passen.<br />
x = input(’Enter a real number: ’); switch x<br />
case {inf,-inf}<br />
disp(’Plus or minus infinity’)<br />
case 0<br />
disp(’Zero’)<br />
otherwise<br />
disp(’Nonzero and finite’)<br />
end<br />
C Programmierer seien darauf hingewiesen, dass das switch-Konstrukt von <strong>MATLAB</strong> sich anders<br />
verhält als das von C: Sobald ein <strong>MATLAB</strong> case Ausdruck zur Variable passt und die Befehle ausgeführt<br />
wurden, wird die Kontrolle an den ersten Befehl nach dem switch-Block übergeben, ohne dass weitere<br />
break Befehle nötig sind.<br />
29
Kapitel 4<br />
M-Dateien<br />
Viele nützliche Berechnungen lassen sich über die Kommandozeile von <strong>MATLAB</strong> durchführen. Nichtsdestotrotz<br />
wird man früher oder später M-Dateien schreiben müssen. Diese sind das Pendant zu Programmen,<br />
Funktionen, Subroutinen und Prozeduren in anderen Programmiersprachen. Fügt man eine Folge<br />
von Befehlen zu einer M-Datei zusammen, ergeben sich vielfältige Möglichkeiten, wie etwa<br />
• an einem Algorithmus herumzuexperimentieren indem man eine Datei bearbeitet, anstatt eine lange<br />
Liste von Befehlen wieder und wieder zu tippen<br />
• einen dauerhaften Beleg für ein numerisches Experiment schaffen<br />
• nützliche Funktionen aufzubauen die zu einem späteren Zeitpunkt erneut verwendet werden können<br />
• M-Dateien mit anderen Kollegen austauschen<br />
Im Internet findet man eine Vielzahl nützlicher M-Dateien, die von Benutzern geschrieben wurden.<br />
<strong>Eine</strong> M-Datei ist eine Textdatei mit der Dateiendung .m, die <strong>MATLAB</strong> Befehle enthält. Es gibt zwei<br />
Arten:<br />
• Skriptdateien (oder Kommandodateien) haben keine Ein- oder Ausgabeargumente und operieren<br />
auf Variablen im Workspace.<br />
• Funktionsdateien enthalten eine function Definitionszeile und akzeptieren Eingabeargumente<br />
und geben Ausgabeargumente zurück, und ihre internen Variable sind lokal auf die Funktion beschränkt<br />
(sofern sie nicht als global deklariert wurden).<br />
4.1 Skriptdateien<br />
Ein Skript erlaubt es, eine Folge von Befehlen die wiederholt verwendet werden sollen oder in Zukunft<br />
noch gebraucht werden. Ein Beispiel für ein Skript ist folgender „Sinus random plotter“:<br />
%randSin<br />
%Plottet die Sinusfunktion nur ausgewertet an n+2 zufälligen Stellen<br />
n=10;<br />
x=sort([0,rand(1,n)*2*pi,2*pi]);<br />
y=sin(x);<br />
plot(x,y);<br />
Die ersten beiden Zeilen des Skripts beginnen mit dem % Symbol und sind daher Kommentare.<br />
Sobald <strong>MATLAB</strong> auf ein % trifft ignoriert es den Rest der Zeile. Dies erlaubt das Einfügen von Text,<br />
der das Skript für Menschen leichter verständlich macht. Angenommen dieses Skript wurde unter dem<br />
Namen randSin.m gespeichert, dann ist die Eingabe von randSin an der Kommandozeile gleichwertig<br />
zur Eingabe der einzelnen Zeilen des Skripts.<br />
30
4.2 Funktionsdateien<br />
Selbst geschriebene Funktionsdateien erweitern den Umfang von <strong>MATLAB</strong>. Sie werden auf die gleiche<br />
Weise verwendet wie die bereits existierenden <strong>MATLAB</strong> Funktionen wie sin, eye, size usw.<br />
Hier ist ein Beispiel für eine Funktionsdatei:<br />
function y = maxentry(A)<br />
%MAXENTRY Largest absolute value of matrix entries.<br />
% MAXENTRY(A) is the maximum of the absolute values<br />
% of the entries of A.<br />
y = max(abs(A(:)));<br />
Dieses Beispiel präsentiert mehrere Features. Die erste Zeile fängt mit dem Schlüsselwort function an,<br />
gefolgt vom Ausgabeargument y, und dem Gleichheitszeichen. Rechts von = kommt der Funktionsname<br />
maxentry, gefolgt vom Eingabeargument A in Klammern. (Im Allgemeinen kann es beliebig viele Einund<br />
Ausgabeargumente geben.) Der Funktionsname muss der gleiche sein wie der Name der M-Datei, die<br />
die Funktion enthält - in diesem Fall muss die Datei maxentry heißen.<br />
Die zweite Zeile der Funktionsdatei heißt H1-Zeile (help 1). Sie sollte eine Kommentarzeile sein: <strong>Eine</strong><br />
Zeile die mit einem %-Zeichen beginnt und danach ohne Leerzeichen dem Funktionsname in Großbuchstaben<br />
– gefolgt von einem oder mehr Leerzeichen und dann einer kurzen Beschreibung. Die Beschreibung<br />
sollte mit einem Großbuchstaben anfangen und mit einem Punkt enden und dabei auf die Worte „der“,<br />
„die“, „das“ und „ein“, „eine“ verzichten. Alle Kommandozeilen – beginnend mit der ersten bis zur ersten<br />
Nichtkommentarzeile (in der Regel eine Leerzeile, um die Lesbarkeit des Codes zu erhöhen) – werden<br />
beim Aufruf von help function_name angezeigt. Darum sollten diese Zeilen die Funktion und ihre Argumente<br />
beschreiben. Funktionenname und -argumente groß zu schreiben ist eine allgemein akzeptierte<br />
Konvention. Im Falle von maxentry sieht die Ausgabe folgendermaßen aus<br />
>> help maxentry<br />
MAXENTRY Largest absolute value of matrix entries.<br />
MAXENTRY(A) is the maximum of the absolute values<br />
of the entries of A.<br />
An dieser Stelle sei noch einmal mit Nachdruck darauf hingewiesen, dass es sich lohnt, alle Funktionsdateien<br />
auf diese Art und Weise zu dokumentieren. Oft ist es nützlich, in Kommentaren anzugeben,<br />
wann die Funktion zuerst geschrieben wurde, und ob Veränderungen hinzugefügt wurden.<br />
Der Befehl help funktioniert auf ähnliche Art und Weise mit Skriptdateien, er zeigt die Anfangsfolge<br />
an Kommentaren an.<br />
Die Funktion maxentry wird wie jede andere <strong>MATLAB</strong> Funktion aufgerufen:<br />
>> maxentry(1:10)<br />
ans =<br />
10<br />
>> maxentry(magic(4))<br />
ans =<br />
16<br />
4.3 M-Dateien bearbeiten<br />
Es gibt zwei Möglichkeiten, M-Dateien zu bearbeiten. Jeder beliebige ASCII-Editor kann verwendet<br />
werden (benutzt man ein Textverarbeitungsprogramm, so ist sicherzustellen, dass das Programm die<br />
Datei auch wieder im ASCII-Format speichert). Oder man benutzt den internen Editor/Debugger von<br />
<strong>MATLAB</strong>. Dieser Editor verfügt über Funktionen, die das Bearbeiten von M-Dateien unterstützen. Zum<br />
Beispiel werden Schleifen und if-Abfragen automatisch eingerückt, es gibt mehrfarbiges Syntax Highlighting,<br />
und einen automatischen Vergleich von Klammern und Doppelpunkten. Diese und andere Features<br />
können im Menü Tools-Optionen deaktiviert oder modifiziert werden.<br />
31
4.4 Mit M-Dateien und der Pfadvariable von <strong>MATLAB</strong> arbeiten<br />
Viele <strong>MATLAB</strong>-Funktionen sind M-Dateien die auf der Festplatte gespeichert werden, während andere in<br />
den <strong>MATLAB</strong>-Interpreter integriert sind. Der <strong>MATLAB</strong> Suchpfad ist eine Liste von Ordnern, die angibt,<br />
wo <strong>MATLAB</strong> nach M-Dateien sucht. <strong>Eine</strong> M-Datei ist nur dann verfügbar, wenn sie sich im Suchpfad<br />
befindet. Geben Sie path ein, um den aktuellen Suchpfad angezeigt zu bekommen. Die Pfadvariable kann<br />
über path gesetzt werden, und über addpath können Befehle hinzugefügt werden. <strong>Eine</strong> weitere Möglichkeit<br />
zur Bearbeitung des Suchpfads ist der Pfad-Browser, der über Datei-Pfad Einstellen oder die Eingabe<br />
von pathtool aufgerufen wird.<br />
Der Suchpfad kann mit mehreren Befehlen durchsucht werden. Der Befehl what listet alle <strong>MATLAB</strong><br />
Dateien im aktuellen Verzeichnis auf;<br />
what verzeichnisname listet alle <strong>MATLAB</strong>-Dateien im Ordner<br />
verzeichnisname im Pfad. Der Befehl lookfor keyword durchsucht den Pfad nach M-Dateien, die<br />
keyword in ihrer H1 Zeile enthalten (die erste Zeile des Hilfetextes). Um alle Kommentarzeilen, die bei<br />
Eingabe von help angezeigt werden, zu durchsuchen, kann man lookfor mit dem Parameter -all aufrufen:<br />
lookfor keyword -all<br />
Manche <strong>MATLAB</strong>-Funktionen benutzen Kommentarzeilen nach dem ersten Block von Kommentaren,<br />
um weitere Informationen zu liefern, wie etwa bibliographische Angaben (zum Beispiel fminsearch).<br />
Auf diese Information kann über type zugegriffen werden. Sie wird beim Aufruf von help nicht angezeigt.<br />
Die Eingabe von which foo zeigt den Pfad der Funktion foo an, oder gibt an, dass die Funktion builtin<br />
ist, oder nicht vorhanden. Diese Funktion ist nützlich falls man wissen möchte, in welchem Ordner<br />
sich eine bestimmte Funktion befindet. Falls mehr als eine Funktion mit dem Namen foo im Suchpfad<br />
existiert, zeigt which foo -all alle Funktionen an.<br />
Ein Skript, welches sich nicht auf dem Suchpfad befindet kann über den Befehl run gefolgt vom<br />
vollständigen Pfad des Skriptes aufgerufen werden. <strong>Eine</strong> M-Datei foo.m kann über type foo oder type<br />
foo.m am Bildschirm ausgegeben werden. (Falls es eine ASCII-Datei mit dem Namen foo gibt, so würde<br />
der erste Befehl foo ausgeben anstatt foo.m) Folgt type auf den Befehl more on, so wird die Datei<br />
seitenweise angezeigt (more off schaltet die seitenweise Darstellung wieder aus).<br />
Erstellt man eine neue M-Datei, sollte man vermeiden, einen Namen zu wählen, der im Suchpfad<br />
bereits vorhanden ist. Dies kann man mit Hilfe der Befehle which, type, help oder exist überprüfen.<br />
Der Befehl exist(’name’) überprüft, ob name eine Variable im Workspace, eine Datei (mit mehreren<br />
möglichen Endungen, unter Anderem .m) im Suchpfad, oder ein Ordner ist. Das Ergebnis 0 bedeutet,<br />
dass keine Übereinstimmungen gefunden wurden, währen die Zahlen 1-7 bedeuten, dass es welche gibt.<br />
Für die Bedeutung der Zahlen siehe help exist.<br />
Wird eine Funktion, die sich im Suchpfad befindet, zum ersten Mal aufgerufen, wird sie in den Speicher<br />
geladen. <strong>MATLAB</strong> kann im Allgemeinen feststellen, ob eine Funktionsdatei sich geändert hat, und<br />
kompiliert sie automatisch erneut, wenn sie aufgerufen wird. Um die Funktion fun aus dem Speicher zu<br />
löschen, benutzt man den Befehl clear fun. clear functions löscht alle Funktionen.<br />
4.5 Dualität von Befehl und Funktion<br />
Normalerweise werden vom Benutzer geschriebene Funktionen so aufgerufen: der Funktionenname gefolgt<br />
von einer Liste von Argumenten in Klammern. Doch manche <strong>MATLAB</strong>-internen Funktionen, wie zum<br />
Beispiel type und what, die im vorhergehenden Abschnitt behandelt wurden, werden normalerweise so<br />
aufgerufen, dass die Argumente vom Funktionennamen durch ein Leerzeichen getrennt werden. Diese ist<br />
keine Inkonsistenz von <strong>MATLAB</strong> sondern ein Beispiel für die Gleichheit von Befehl und Funktion.<br />
function comfun(x,y,z)<br />
%COMFUN Illustrative function with three string arguments.<br />
disp(x), disp(y), disp(z)<br />
32
Die Funktion comfun kann mit den Stringargumenten in Klammern (funktionale Form) oder mit den<br />
Stringargumenten getrennt durch Leerzeichen aufgerufen werden (Befehlsform):<br />
>> comfun(’ab’,’cd’,’ef’)<br />
ab<br />
cd<br />
ef<br />
>> comfun ab cd ef<br />
ab<br />
cd<br />
ef<br />
Die beiden Funktionsaufrufe sind gleichwertig. Andere Beispiele für die Dualität von Befehl und<br />
Funktion sind<br />
format long, format(’long’)<br />
disp(’Hello’), disp Hello<br />
diary mydiary, diary(’mydiary’)<br />
warning off, warning(’off’)<br />
Beachte, dass die Befehlsform nur dann verwendet werden sollte, wenn die Eingabeparameter der<br />
Funktion Strings sind.<br />
33
Kapitel 5<br />
Lineare Algebra mit <strong>MATLAB</strong><br />
5.1 Norm und Kondition<br />
Die Norm eines Vektors oder einer Matrix kann mit dem Befehl norm berechnet werden.<br />
Befehl:<br />
norm(A,p)<br />
wobei A eine m x n Matrix und p=1,2,inf oder fro ist.<br />
p Bedeutung<br />
1 1-Norm, d.h. max. Spaltensumme<br />
2 Spektralnorm, max. Singulärwert, (default)<br />
inf Maximumsnorm, d.h. max. Zeilensumme<br />
fro Frobeniusnorm, definiert als m<br />
i=1<br />
m<br />
i=1 ai,j<br />
Für höherdimensionale Matrizen sind Normberechnung für p = 2 relativ aufwendig und kostenintensiv<br />
– daher werden oft Abschätzungen verwendet.<br />
normest(A,tol)<br />
Mit Hilfe von normest wird die 2-Norm von A bis auf die durch tol gegebene Genauigkeit berechnet.<br />
Defaultwert für tol=1e-16.<br />
Oft werden lineare Gleichungssystem auf das Verhalten von Störungen untersucht (so genannten<br />
Stabilitätsanalyse). Ein Indikator hierfür ist die Kondition einer Matrix A, definiert als<br />
κp(A) = Ap · A −1 p<br />
Je nachdem ob κ groß bzw. klein ist, ist das System schlecht oder gut konditioniert.<br />
Befehl:<br />
cond(A,p)<br />
p ist wie für norm definiert.<br />
Anmerkung:<br />
Normalerweise wird die Kondition nur für quadratische, nicht singuläre Matrizen berechnet. Für p = 2<br />
kann auch die Kondition von rechteckigen Matrizen berechnet werden, wobei dann A ( − 1) durch die<br />
Pseudoinverse (genauer die Moore-Penrose-Inverse) ersetzt wird.<br />
Auch für die Kondition existieren Abschätzungsfunktionen, wie condest und rcond:<br />
[c,v]=condest(A)<br />
c Skalar<br />
v Vektor<br />
mit:<br />
und A · v1 = A1∗v1<br />
c<br />
Befehl:<br />
c ≤ κ1(A)<br />
34
cond(A)<br />
wobei für A singulär rcond(A)=0.<br />
5.2 Lineare Gleichungssysteme<br />
1<br />
(A) ≈ rcond(A)<br />
κ 1<br />
Ein lineares Gleichungssystem sieht grundsätzlich folgendermaßen aus:<br />
Ax = b<br />
mit einer Matrix A und einem Vektor b. Gesucht wird ein Vektor x der das System löst.<br />
5.2.1 A n × n Matrix<br />
Falls A eine quadratische, nicht singuläre Matrix ist, existiert eine eindeutige Lösung. In <strong>MATLAB</strong> wird<br />
diese wie folgt mit Hilfe des ’\’ berechnet.<br />
5.2.2 A m × n Matrix mit m > n<br />
x=A \ b<br />
Wenn A eine rechteckige Matrix ist, die mehr Zeilen als Spalten hat, spricht man von einem überbestimmten<br />
System, da mehr Bedingungen (Zeilen) als Unbekannte (Spalten) vorhanden sind. <strong>Eine</strong> eindeutige<br />
Lösung, so dass Ax = b, ist im Allgemeinen nicht möglich. Es kann allerdings eine Minimallösung angegeben<br />
werden, so dass A ∗ x − b2 = min! ist. (vgl. Numerik 1. „Lineare Ausgleichsrechnung“)<br />
In diesem Fall wird durch den ’\’ Operator das lineare Ausgleichsproblem gelöst, mit Hilfe der „least<br />
square solution“. Ist man nur an den nicht negativen Lösungen interessiert, ist der Befehl lsqnonneg zu<br />
empfehlen.<br />
x=lsqnonneg(A,b)<br />
wobei x nur Einträge größer, gleich Null enthält.<br />
5.2.3 A m × n Matrix mit m < n<br />
Falls A eine Matrix mit weniger Zeilen als Spalten ist, so ist das LGS unterbestimmt und es existieren<br />
entweder keine oder unendlich viele Lösungen. Falls das System unendlich viele Lösungen besitzt, gibt<br />
’A\b’ eine Lösung aus, die k nichtnull Elemente besitzt, wobei k der Rang der Matrix A ist. Sollte das<br />
System keine Lösungen haben gibt ’A\b’ eine Minimallösung aus, wie bei oben genannten überbestimmten<br />
Systemen.<br />
Falls man mehrere Gleichungssysteme, mit der selben Matrix A aber mit verschiedenen Seiten b (1) , . . . , b (n)<br />
auf einmal lösen möchte, geschieht das am einfachsten dadurch, dass man die b (i) s als Spalten einer Matrix<br />
B anordnet und den ’\’ Operator mit dieser Matrix aufruft. Das Ergebnis ist ein Matrix X mit<br />
x (1) , . . . x (n) als Spalten, die das jeweilige System zu gegebenem b (i) lösen.<br />
5.3 Inverse, Pseudoinverse und Determinante<br />
In manchen Fällen – nicht oft, aber hin und wieder, vor allem in Hausaufgaben – muss man die Inverse<br />
einer Matrix berechnen. In <strong>MATLAB</strong> geht das mit Hilfe des inv Befehls:<br />
X=inv(A)<br />
mit A ∗ X = X ∗ A = I, wobei A eine nicht singuläre, quadratische n × n Matrix sein muss.<br />
<strong>Eine</strong> Matrix A ist singulär, falls die Determinante von A = 0 ist. Befehl:<br />
det(A)<br />
35
mit A einer n × n Matrix. Für gewisse Zwecke, z.B. zur Lösung eines least squares Problem ist die<br />
so genannte Pseudoinverse einer Matrix A von Interesse. Die Pseudoinverse X von A erfüllt folgende<br />
Bedingungen:<br />
Befehl:<br />
pinv(A)<br />
XAX = X<br />
AXA = A<br />
(XA) T = XA<br />
(AX) T = AX<br />
wobei A hier nun auch eine rechteckige m × n Matrix sein kann.<br />
5.4 Zerlegungen<br />
Oben wurde bereits erwähnt, dass der ’\’ Operator lineare Gleichungssysteme löst, bzw. Näherungslösungen<br />
dazu angibt. <strong>MATLAB</strong> verwendet dazu geeignete Algorithmen, die sich je nach Matrix unterscheiden<br />
können.<br />
<strong>MATLAB</strong> unterstützt aber auch das Zerlegen von Matrizen mit speziellen Zerlegungen, z.B. die LRoder<br />
Cholesky-Zerlegung.<br />
5.4.1 LR-Zerlegung<br />
Befehl:<br />
[L,R]=lu(A) \\ [L,R,P]=lu(A)<br />
L untere Dreiecksmatrix mit 1 auf der Hauptdiagonale<br />
R obere Dreiecksmatrix<br />
wobei A eine quadratische n × n Matrix ist.<br />
Nicht jede Matrix A kann auf diese Weise zerlegt werden, es existieren Matrizen bei denen ’Pivoting’<br />
notwendig ist. Hierbei gibt der lu Befehl eine zusätzliche Permutationsmatrix P aus, sodass gilt: P ∗ A =<br />
L ∗ R. Wird P bei der Rückgabe von lu nicht aufgefangen so wird L = P T · L.<br />
Mit Hilfe der Zerlegung kann ein lineares Gleichungssystem dann wie folgt gelöst werden:<br />
[L,R]=lu(A);<br />
x=R\(L \ b);<br />
5.4.2 Cholesky-Zerlegung<br />
Falls A eine symmetrische, positiv definite (s.p.d.) Matrix ist, d.h. sie genügt:<br />
1. A T = A<br />
2. ∀x : x T Ax ≥ 0<br />
existiert, die Cholesky Zerlegung von A in eine obere Dreiecksmatrix R, so dass gilt:<br />
A = R T · R<br />
Anmerkung:<br />
In vielen Lehrbüchern wird die Cholesky-Zerlegung mit unteren Dreicksmatrizen L beschrieben. Beide<br />
Formulierungen sind äquivalent, da für L = R T gilt:<br />
Befehl:<br />
R=chol(A)<br />
[R,p]=chol(A)<br />
A = L · L T<br />
wobei A eine quadratische n × n Matrix ist. Falls A nicht positiv definit ist, ist p eine ganze Zahl größer<br />
0, andernfalls gleich 0.<br />
36
5.4.3 QR-Zerlegung<br />
Die oben genannten Zerlegungen sind jeweils nur für quadratische Matrizen geeignet. Die QR-Zerlegung<br />
jedoch arbeitet auch auf rechteckigen m x n Matrizen A , wobei A in eine orthogonale m x m Matrix Q<br />
und eine obere m x n Dreiecksmatrix R zerlegt wird.<br />
[Q,R]=qr(A) \\ [Q,R]=qr(A,0) \\ [Q,R,P]=qr(A)<br />
Falls m>n ist und die Variante qr(A,0) benutzt wird, ist Q eine spaltenorthogonale m × n und R<br />
eine n × n Matrix. Falls das Pivoting genutzt wird ([Q,R,P]=qr(A)) gilt: AP = QR wobei dann die<br />
Diagonalelemente von R dem Betrag nach, abfallend geordnet sind.<br />
Die QR-Zerlegung findet z.B. in der linearen Ausgleichsrechnung oder bei der Konstruktion von Orthonormalbasen<br />
Verwendung.<br />
5.4.4 Singulärwertzerlegung<br />
Ähnlich den Eigenwerten, charakterisieren die so genannten Singulärwerte unterschiedliche Eigenschaften<br />
einer Matrix. Jedoch sind für Eigenwerte quadratische Matrizen notwendig, die Singulärwertzerlegung<br />
hingegen arbeitet auch mit rechteckigen m × n Matrizen A. Es gilt:<br />
A = U · Σ · V<br />
mit U m × m und V n × n unitären Matrizen Σ m × n diagonal Matrix mit σi (Singulärwerte) auf der<br />
Hauptdiagonalen, wobei gilt:<br />
Befehl:<br />
[U,S,V]=svd(A)<br />
σ1 ≥ σ2 ≥ · · · ≥ σ min(m,n)<br />
Anmerkung:<br />
Mit Hilfe der Singulärwertzerlegung ist es möglich, verschiedene Dinge über die Matrix A auszusagen.<br />
So ist zum Beispiel die Anzahl der σi ungleich Null der Rang der Matrix A. Auch ist eine Orthonormalbasis<br />
des durch die Spalten von A aufgespannten Raumes in der Singulärwertzerlegung enthalten. Es sind die<br />
ersten k Spalten der Matrix U, wobei k der Rang von A ist.<br />
5.5 Eigenwertpropleme<br />
5.5.1 Eigenwerte<br />
Sei A eine quadratische n×n Matrix. Dann ist λ ∈ C ein Eigenwert von A, wenn es einen vom Nullvektor<br />
verschiedenen Vektor x gibt mit der Eigenschaft Ax = λx. Um diese Eigenwerte auszurechnen, berechnet<br />
man normalerweise das charakteristische Polynom p = det(Iλ − A). Somit gilt:<br />
p = pnλ n + · · · + p1λ + p0<br />
Die Koeffizienten pn, · · · , p0 des charakteristischen Polynoms erhält man mit dem Befehl poly(A).<br />
Die Eigenwerte bekommt man mittels e=eig(A). e ist ein Spaltenvektor der Länge n mit den Eigenwerten.<br />
Mehrfache Eigenwerte (algebraische Vielfachheit) werden stehen auch mehrfach in e. Mit [V,D]=eig(A)<br />
bekommt man eine n × n Diagonalmatrix D, die die Eigenwerte enthält, und eine n × n Matrix V, deren<br />
Spaltenvektoren, wenn möglich, eine Basis aus Eigenvektoren bilden, so dass V −1 AV = D.<br />
Falls man nicht n linear unabhängige Eigenvektoren erhält, ist die Matrix V nicht regulär. Dies verdeutlichen<br />
wir mit dem folgenden Beispiel:<br />
>> A=[2 -1;1 0]<br />
A =<br />
2 -1<br />
1 0<br />
>> [V,D]=eig(A)<br />
37
V =<br />
D =<br />
0.7071 0.7071<br />
0.7071 0.7071<br />
1 0<br />
0 1<br />
Wie man an diesem Beispiel auch sieht, normiert <strong>MATLAB</strong> die Eigenvektoren immer bzgl. der 2-Norm.<br />
Falls A eine hermitesche Matrix ist, d.h. A = A T , gibt es nur reelle Eigenwerte und eine Orthonormalbasis<br />
aus Eigenvektoren. So eine Basis ist in V gespeichert.<br />
>> [V,D]=eig([2 -1;-1 1])<br />
V =<br />
-0.5257 -0.8507<br />
-0.8507 0.5257<br />
D =<br />
0.3820 0<br />
0 2.6180<br />
Um die Kondition der Berechnung der einzelnen Eigenwerte zu berechnen, ist der Befehl [V,D,s]=condeig(A)<br />
implementiert. Die i-te Stelle im Vektor s entspricht der Kondition des i-ten Eigenwert.<br />
>> [V,D,s]=condeig([2 0.9;200 5]);<br />
>> [diag(D)’;s’]<br />
ans =<br />
-10.0000 17.0000<br />
7.4416 7.4416<br />
Wenn man eine sehr große quadratische Matrix A hat und sich nur für die 6 größten Eigenwerte<br />
interessiert, kann man sich durch eigs(A) eine Approximation an diese Eigenwerte anzeigen lassen. Für<br />
weitere Informationen help eigs.<br />
5.6 Matrixfunktionen<br />
Zum Lösen gewöhnlicher Differentialgleichungen wird oft die Exponentialfunktion mit einer Matrix als<br />
Argument benötigt. Diese ist auch wie folgt definiert:<br />
Von <strong>MATLAB</strong> wird dies direkt unterstützt:<br />
expm(A)<br />
exp(A) =<br />
wobei A eine quadratische n × n Matrix ist<br />
Anmerkung: Im Gegensatz zu der Funktion expm operiert exp nur auf den einzelnen Komponenten<br />
der Matrix A!<br />
Weiterhin sind in <strong>MATLAB</strong> folgenden Matrixfunktionen definiert:<br />
∞<br />
i=1<br />
• logm: Der Logarithmus einer Matrix als Umkehrfunktion der Exponentialfunktion, d.h. logm(expm(A))=A<br />
• sqrtm: Quadratwurzel aus A, d.h. B=sqtrm(A) mit B · B = A<br />
• funm: Mit Hilfe von funm können Funktionen als Argument Matrizen übergeben werden. Zum Beispiel<br />
funm(A,@sin) berechnet den Sinus der Matrix A.<br />
38<br />
A i<br />
i
Kapitel 6<br />
Eigene Funktionen<br />
<strong>Eine</strong> eigene Funktion steht sobald sie etwas komplexer wird in einer m-Datei. Der grundlegende Aufbau<br />
ist in Abschnitt 4.2 besprochen worden.<br />
Daneben ist es bei kurzen Funktionen oft praktisch, diese direkt zu definieren ohne eine neue Datei<br />
anlegen zu müssen. Dies funktioniert mit dem Befehl inline.<br />
>> f=inline(’exp(a+log(x))/42’,’x’,’a’)<br />
f =<br />
>> f(1,2)<br />
Inline function:<br />
f(x,a) = exp(a+log(x))/42<br />
ans =<br />
0.1759<br />
Erzeugt eine Funktion, die mit z.B.f(x, a) ausgewertet werden kann. Die Abfolge hinter der Funktionsvorschrift<br />
definiert die Reihenfolge der Argumente beim Funktionsaufruf.<br />
Meistens geht man bei der Entwicklung von Funktionen von einem einfachen, meistens eindimensionalen<br />
Beispiel aus und versucht an Hand von diesem zu einer vektorwertigen Funktion zu gelangen. Dies<br />
geschieht in Matlab mit Hilfe des vectorize Befehls.<br />
vectorize(FUNKTION)<br />
Der Befehl erzeugt aus einer gegebenen Funktion eine neue, die auf komponentenweise auf den Elementen<br />
von Vektoren bzw. Matrizen operiert.<br />
6.1 Referenzen<br />
Wie im vorhergehende Kapitel besprochen wurde, können mit Hilfe von funm Funktionen mit Matrizen<br />
als Argument ausgewertet werden. Hierzu wird eine so genannte Referenz auf eine Funktion übergeben.<br />
Diese Referenz ist nichts anderes als ein Verweis auf eine Funktion, die dann im Laufe des Aufrufs von<br />
funm mit feval ausgewertet wird.<br />
feval(@Funktionsname,x1,...,xn)<br />
@Funktionsname erzeugt den Verweis auf die Funktionen x1, . . . , xn sind die Argumente die an „Funktionsname“<br />
zur Auswertung übergeben werden sollen.<br />
In neueren Matlabversionen ist es möglich. <strong>Eine</strong>r Referenz direkt die Argument zu übergeben, dies<br />
sollte allerdings aus Gründen der Abwärtskompatibilität zu älteren Matlabversionen unterlassen werden.<br />
Beispiel:<br />
• neuere Matlabversion :<br />
func_handle=@test_function; func_handle(4)<br />
erzeugt eine Funktionsreferenz auf test_function und wertet dann die Referenz an der Stelle 4<br />
aus.<br />
39
• ältere Matlabversionen > diffd(@sin, 0.5)<br />
ans =<br />
0.8776<br />
>> cos(0.5)<br />
ans =<br />
0.8776<br />
6.2 Subfunktionen<br />
Zu einem ’sauberen’ Programmierstil gehört, dass man sich wiederholende Operationen ausgliedert in so<br />
genannte Subfunktionen. Da diese in der Regel nur im Kontext des entsprechenden M-Files Sinn machen,<br />
werden sie einfach an die Hauptfunktion angefügt. Sie werden wie jede andere Funktion definiert durch:<br />
function [RÜCKGABEWERTE]=FUNKTIONSNAME (EINGABEPARAMETER)<br />
Sie sind jedoch nur sichtbar für alle anderen Unterroutinen und die Hauptfunktion.<br />
function y=hauptfunktion(x)<br />
% Hier wird etwas gemacht, wozu man immer wieder die Wurzel<br />
% aus u+u^2 durch pi braucht. Der Aufruf erfolgt mit subfunktion(u).<br />
function t=subfunktion(u)<br />
t=sqrt(u+u^2)/pi;<br />
6.3 Globale Variablen und Rekursion<br />
Oft stellt sich das Problem, dass man Konstanten oder Verweise, in allen Funktionen zur Verfügung haben<br />
muss. Anstatt diese nun von Funktion zu Funktion immer und immer wieder zu übergeben werden sie<br />
als ’global’ deklariert.<br />
Falls man nun in all seinen Funktionen auf den Wert der Variable GLOB_VAR zugreifen will, deklariert<br />
man sie im Command Window mit ’global GLOB_VAR und verweist beim schreiben seiner Funktionen mit<br />
’global GLOB_VAR’ darauf dass die verwendete Variable schon vorhanden ist. Allerdings ist auch Vorsicht<br />
geboten beim Umgang mit globalen Variablen, da sie nicht schreibgeschützt sind, d.h. es ist möglich ihren<br />
Wert in Funktionen zu verändern.<br />
Rekursion bezeichnet einen Aufruf einer Funktion durch sich selbst. Am besten erklärt sich das an<br />
Hand eines Beispiels. Die Fakultät einer natürlichen Zahl n ist definert durch:<br />
n! = 1 · 2 · 3 · · · (n − 1) · n<br />
In Matlab mit Hilfe der Rekursion führt das zu folgendem:<br />
40
function ret_val=fak(n)<br />
if (n
Kapitel 7<br />
Ein- und Ausgabe<br />
Im letzten Kapitel haben wir gelernt wie man eigene Funktionen korrekt in <strong>MATLAB</strong> schreibt – aber<br />
diese konnten weder Daten einlesen noch Daten ausgeben. Dieses Manko wollen wir in diesem Kapitel<br />
beseitigen, da insbesondere viele Funktion direkte Eingaben vom Benutzer erwarten.<br />
7.1 Direkte Eingabe<br />
Direkte Eingabe heißt, dass der Nutzer des Programmes aufgefordert wird, Daten einzugeben.<br />
x=input(’Beschriftungstext’)<br />
x=input(’Beschriftungstext’,’s’)<br />
Wird die Funktion mit nur einem Parameter aufgerufen erwartet <strong>MATLAB</strong> die Eingabe im <strong>MATLAB</strong>-<br />
Syntax:<br />
>> x=input(’Bitte Zahl eingeben: ’);<br />
Bitte Zahl eingeben: sin(0.5)<br />
>> x<br />
x =<br />
0.4794<br />
Mittels eines zweiten Parameters ’s’ kann man <strong>MATLAB</strong> anweisen, die Eingabe immer als Text zu<br />
interpretieren.<br />
>> x=input(’Bitte Zahl eingeben: ’,’s’);<br />
Bitte Zahl eingeben: sin(0.5)<br />
>> x<br />
x =<br />
sin(0.5)<br />
Zur Abfrage von Koordinaten in einer graphischen Oberfläche wird die Funktion ginput verwendet.<br />
[x,y] = ginput(n)<br />
x x Koordinaten relativ zu dem geklickten Fenster<br />
y y Koordinaten relativ zu dem geklickten Fenster<br />
n Anzahl der Klicks die abgefangen werden sollen<br />
Im Vektor x werden folglich die x-Koordinaten der nächsten n Mausklicks gespeichert. Für den Vektor<br />
y gilt das Entsprechende. Diese Art der Eingabe ist besonders bei einem schon bestehenden Plot sinnvoll.<br />
Um zwischen zwei Befehlen n Sekunden zu warten, gibt es den <strong>MATLAB</strong>-Befehl pause(n). Dies wird<br />
üblicherweise bei Anzeigen von verschiedenen Plots angewandt.<br />
42
7.2 Bildschirmausgabe<br />
Einfache Ausgaben können über den Befehl disp erfolgen:<br />
disp(’Zeichenfolge’)<br />
disp(a)<br />
Bei Ausgabe einer Zeichenfolge muss disp verwendet werden, bei Aufruf von disp mit einer Variablen<br />
als Argument wird der Inhalt der Variablen formatiert ausgegeben (formatiert wie am interaktiven<br />
Prompt). Für komplexere und formatierte Ausgaben kann man den Befehl fprintf verwenden:<br />
fprintf(’FORMATSTRING’,Wert)<br />
FORMATSTRING Ein Formatierungsstring der Form %a.b(e/f)\n.<br />
a Anzahl der Stellen vor dem Komma<br />
b Anzahl der Stellen hinter dem Komma<br />
e/f Exponential oder Gleitkommadarstellung<br />
\n Nach Ausgabe eine neue Zeile beginnen.<br />
Wert Werte die ausgegeben werden sollen.<br />
Ein Minus hinter dem % Zeichen erzwingt eine linksbündige Ausgabe:<br />
fprintf(’%-3.5f\n%3.5f\n’, 9, 103)<br />
9.00000<br />
103.00000<br />
Für die Ausgabe von mehreren Werten müssen diese in dem Formatstring gekennzeichnet werden. Es<br />
können auch Beschriftungen eingefügt werden z.B.:<br />
fprintf(’Skalarprodukt von [1 1] und [1 2]: %3.5f\n’,[1,1]*[1;2])<br />
Skalarprodukt von [1 1] und [1 2]: 3.00000<br />
Des weiteren ist es möglich, auch komplette Matrizen zeilenweise ausgeben zu lassen:<br />
A=[1 2 3; 4 5 6; 7 8 9];<br />
fprintf(’a1=%g, a2=%g, a3=%g\n’, A);<br />
a1=1, a2=4, a3=7<br />
a1=2, a2=5, a3=8<br />
a1=3, a2=6, a3=9<br />
Um ’, % und \ in einem Formatstring auszugeben, müssen ’’, \% und \\ verwendet werden. Für die<br />
kombinierte Ausgabe von Zahlen und Zeichenketten ist es auch möglich, die beiden zu verbinden, indem<br />
man die Zahlen in Strings umwandelt mit Hilfe von num2str bzw. int2str:<br />
disp([’a’, num2str(4)])<br />
a4<br />
7.3 Speichern und Laden<br />
<strong>MATLAB</strong> unterstützt das einfache Speichern und Laden von Variablen. Mit dem Befehl save können<br />
Variablen in Dateien geschrieben werden.<br />
>> A=magic(10);<br />
>> B=magic(3);<br />
>> save ’magic’ A B<br />
Die von <strong>MATLAB</strong> geschriebenen Dateien enden auf ’.mat’ und sind in einem binären Format, welches<br />
-je nach <strong>MATLAB</strong> Version- auch komprimiert ist. Gibt man dem save Befehl nur einen Dateinamen als<br />
Argument, wird der komplette Workspace in der Datei gespeichert.<br />
Um gespeicherte Variablen zu laden gibt es den load Befehl. Er hat die gleiche Syntax wie das<br />
save Kommando. Um sich den Inhalt einer ’.mat’ Datei anzuzeigen kann man den Befehl whos -file<br />
verwenden.<br />
43
whos -file ’magic’<br />
Name Size Bytes Class Attributes<br />
A 10x10 800 double<br />
B 3x3 72 double<br />
>> clear A B<br />
>> B<br />
??? Undefined function or variable ’B’.<br />
>> load ’magic’ B<br />
>> B<br />
B =<br />
8 1 6<br />
3 5 7<br />
4 9 2<br />
Im obigen Beispiel haben wir mit dem clear Befehl die Variablen aus dem Workspace gelöscht.<br />
7.4 Indirekte Eingabe und Ausgabe<br />
Indirekte Eingabe und Ausgabe heißt, dass man aus einer *.txt-Datei Daten einliest bzw. in diese Datei<br />
Daten, die z.B. eine Funktion geliefert hat, reinschreibt.<br />
Zuerst muss man Matlab sagen, in welcher Datei es nach Daten suchen oder Daten schreiben soll.<br />
Dies wird durch den Befehl fid=fopen(’myoutput.txt’,’r/w’) erledigt, wobei r für das Einlesen steht<br />
bzw. w für das Eingeben von Daten. Mit fprintf kann man dann Daten in myoutput.txt schreiben.<br />
>> fid=fopen(’myoutput.txt’,’w’);<br />
>> a=[1 2 3 4];<br />
>> for i=1:4<br />
fprintf(fid,’Das %g. Element des Vektors a: %g\n’,i,a(i));<br />
end<br />
>> fclose(fid)<br />
Nun enthält myoutput.txt erwartungsgemäß folgendes:<br />
Das 1. Element des Vektors a: 1<br />
Das 2. Element des Vektors a: 2<br />
Das 3. Element des Vektors a: 3<br />
Das 4. Element des Vektors a: 4<br />
Diese Datei kann folgendermaßen eingelesen werden:<br />
>> fid=fopen(’myoutput.txt’,’r’);<br />
>> X=fscanf(fid,’Das %g Element des Vektors a: %g\n’)<br />
X =<br />
1<br />
1<br />
2<br />
2<br />
3<br />
3<br />
4<br />
4<br />
>> fclose(fid);<br />
44
scanf funktioniert also folgendermaßen: Überspringe ’Das ; lese irgendeine floating point Zahl (%g) ein,<br />
überspringe wieder Element des Vektors a: und lese die zweite floating point Zahl ein. Schreibe alle<br />
Zahlen der Reihe nach in den Vektor X.<br />
Mit reshape formt man X in eine Matrix um:<br />
>> X=reshape(X,2,4)<br />
X =<br />
1 2 3 4<br />
1 2 3 4<br />
Wenn man nur eine Matrix mit lauter reelen Zahlen einlesen will, macht man dies folgendermaßen.<br />
In Matrix.txt steht z.B.<br />
1 4 6 7<br />
7 9 10 11<br />
99 1 5 6<br />
1 103 4 89<br />
Nun muss man nur die Dimensionen der Matrix fscanf bekannt machen.<br />
>> fid=fopen(’Matrix.txt’,’r’);<br />
>> X=fscanf(fid,’%g’,[4,4]);<br />
>> X=X’<br />
X =<br />
1 4 6 7<br />
7 9 10 11<br />
99 1 5 6<br />
1 103 4 89<br />
>> fclose(fid)<br />
Außerdem können Dateien, die nur Zahlen erhalten, einfacher mit fread und fwrite bearbeitet werden.<br />
Informieren Sie sich dazu in der Hilfe.<br />
45
Kapitel 8<br />
Optimierung von M-Files<br />
Bei großen Problemen ist es sinnvoll und notwendig, Algorithmen effizient zu implementieren. Durch<br />
die Beachtung einiger Regeln kann man enorme Zeitgewinne erreichen (vor allem in älteren <strong>MATLAB</strong>-<br />
Versionen ohne JIT-Compiler).<br />
8.1 Vektorisierung<br />
In <strong>MATLAB</strong> sind Matrix- und Vektoroperationen annähernd optimal implementiert. Deshalb sollte man<br />
so oft wie möglich auf sie zurückgreifen, insbesondere for-Schleifen sollten möglichst ersetzt werden. Dazu<br />
ein Beispiel:<br />
>> n = 5e5; x = randn(n,1);<br />
>> tic, s = 0; for i=1:n, s = s+x(i)^2; end, toc<br />
elapsed time is 1.532000 seconds<br />
>> tic t=sum(x.^2); toc<br />
elapsed time is 0.046000 seconds<br />
>>s-t<br />
ans = 0<br />
>> 0.046/1.532<br />
ans = 0.0300<br />
Offensichtlich wird in beiden Fällen die Summe der Quadrate der Elemente von x berechnet, beide<br />
Male mit dem selben Ergebnis. Der Zeitgewinn ist allerdings phänomenal: Durch die vektorielle Implementierung<br />
benötigt man lediglich 3% der Zeit der intuitiven Version mittels einer for-Schleife. 1<br />
Weitere Beispiele:<br />
• Berechnung der Fakultät:<br />
>> n=1e7;<br />
>> p1=1; for i=1:n, p=p*i; end %9.625 sec<br />
>> p2=prod(1:n) %0.531 sec<br />
• Ersetzen zweier Zeilen einer Matrix durch Linearkombinationen:<br />
⎛<br />
⎜<br />
⎝<br />
←− A1 −→<br />
.<br />
←− Aj −→<br />
.<br />
.<br />
←− Ak −→<br />
.<br />
⎞ ⎛<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ↩→ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎠ ⎝<br />
←− A1 −→<br />
.<br />
←− c ∗ Aj − s ∗ Ak −→<br />
.<br />
.<br />
←− s ∗ Aj + c ∗ Ak −→<br />
.<br />
←− An −→<br />
←− An −→<br />
1 Dieses Missverhältnis ist in aktuelleren <strong>MATLAB</strong> Versionen nicht mehr so drastisch, trotzdem hat man häufig noch<br />
einen Unterschied vom Faktor 4.<br />
46<br />
⎞<br />
⎟<br />
⎠
temp = A(j,:);<br />
>> A(j,:) = c*A(j,:) - s*A(k,:);<br />
>> A(k,:) = s*temp + c*A(k,:);<br />
>> A([j k],:) = [c -s;s c]*A([j k],:);<br />
8.2 Preallokierung von Speicher<br />
<strong>Eine</strong> bequeme Eigenschaft von <strong>MATLAB</strong> besteht darin, dass Arrays (Vektoren) vor ihrer Benutzung<br />
nicht deklariert werden müssen, und man sich ins Besondere die Festlegung auf eine Größe (Höchstzahl<br />
der Elemente) spart. Werden an ein vorhandenes Array neue Elemente angehängt, wird die Dimension<br />
automatisch angepasst. Dafür muss immer neuer Speicher belegt werden – in Extremfällen kann dieses<br />
Vorgehen deshalb zu Ineffizienz führen:<br />
>> clear;<br />
>> n=1e4;<br />
>> tic, x(1:2) = 1; for i=3:n, x(i)=0.25*x(i-1)^2-x(i-2); end, toc<br />
elapsed time is 5.547000 sec<br />
>> clear<br />
>> n=1e4<br />
>> tic, x=ones(n,1); for i=3:n, x(i)=0.25*x(i-1)^2-x(i-2); end, toc<br />
elapsed time is 0.062000 sec<br />
Es ist zu erkennen, dass die arithmetischen Operationen im Vergleich zur Speicher-Allokierung einen<br />
verschwindend geringen Anteil an der Rechenzeit haben.<br />
47
Kapitel 9<br />
Tipps und Tricks<br />
9.1 Leere Arrays<br />
Wir haben die Möglichkeik Arrays der Dimensionen (4,0), (0,7) oder auch (0,0) zu erzeugen, im Folgenden<br />
„leere Arrays“ genannt. Die Regeln für Operationen mit leeren Arrays werden aus denen für „normale“<br />
Arrays hergeleitet. So zum Beispiel bei der Matrix-Multiplikation:<br />
>> k = 5; A = ones(2,k); B = ones(k,3); A*B<br />
ans=<br />
5 5 5<br />
5 5 5<br />
>> k = 0; A = ones(2,k); B = ones(k,3); A*B<br />
ans=<br />
0 0 0<br />
0 0 0<br />
Und wofür das Ganze? Es unterstützt uns bei unserem Vorhaben, for-Schleifen zu vermeiden – wie<br />
das folgende Beispiel zeigt:<br />
for i=j-1:-1:1<br />
s=0;<br />
for k=i+1:j-1<br />
s=s+R(i,k)*R(k,j);<br />
end<br />
end<br />
for i=j-1:-1:1<br />
s=R(i,i+1:j-1)*R(i+1:j-1,j);<br />
end<br />
Im Fall i=j-1 wird R(i,i+1:j-1) zu einer 1 × 0 - Matrix, R(i+1:j-1,j) zu einer 0 × 1 - Matrix und wir<br />
erhalten als Produkt das die 1 × 1-Matrix.<br />
9.2 ∞ und −∞<br />
Über den Nutzen von ∞ und −∞ im Zusammenhang mit der Achsenbeschriftung bei plots wird unten<br />
noch etwas gesagt. Ein weiteres Gebiet, an dem uns damit geholfen wird, sind die p-Normen. Möchte<br />
man nämlich die zu p gehörige q-Norm berechnen, so dass p −1 + q −1 = 1 gilt, muss man sich um die<br />
Spezialfälle p = 1 (⇒ q = ∞) bzw. p=∞ keine Gedanken machen, sondern kann ruhigen Gewissens<br />
q=1/(1-1/p) berechnen:<br />
>> x=1:10; p=1;<br />
>> norm(x,p)<br />
ans = 55<br />
48
norm(x,1/(1-1/p)<br />
ans = 10;<br />
49
Kapitel 10<br />
Grafiken mit <strong>MATLAB</strong> erstellen<br />
10.1 Grafiken<br />
In <strong>MATLAB</strong> ist es relativ leicht verschiedenste Arten von Grafiken zu erzeugen. Das Erscheinungsbild<br />
kann sehr individuell gestaltet werden. Beispielsweise kann man Farben, Achsenskalierungen und Beschriftungen<br />
den eigenen Vorstellungen anpassen. Grundsätzlich bestehen zur Modifikation von Grafiken<br />
zwei Möglichkeiten, einerseits direkt über die Kommandozeile oder alternativ interaktiv mit der Maus in<br />
der vorhandenen Grafik. Wir werden uns auf die erste Variante beschränken, aber es ist durchaus ratsam,<br />
auch mal mit den „fertigen“ Grafiken rumzuspielen.<br />
10.2 2-dimensionale Plots<br />
Die einfachste Variante zweidimensionale Plots zu erzeugen, besteht darin zwei Vektoren mit gleichen<br />
Dimensionen zu koppeln. Hat man zwei solcher Vektoren (x und y) gegeben, werden mit dem Befehl<br />
plot(x,y) die jeweiligen x(i) und y(i) als zusammengehörig erkannt und ein dementsprechender Plot<br />
erzeugt.<br />
Beispiel:<br />
>> x = [1.5 2.2 3.1 4.6 5.7 6.3 9.4];<br />
>> y = [2.3 3.9 4.3 7.2 4.5 3.8 1.1];<br />
>> plot(x,y)<br />
Mit zusätzlichen Angaben kann man das Aussehen modifizieren. Ein allgemeinerer Aufruf der Funktion<br />
plot hat die Form plot(x,y,String ), wobei sich der String aus bis zu drei Angaben (Farbe, Knoten,<br />
Linienart) zusammensetzt. Die möglichen Eingaben können Tabellen 10.1 entnommen werden:<br />
50
Farbe<br />
r Red<br />
g Green<br />
b Blue<br />
c Cyan<br />
m Magenta<br />
y Yellow<br />
k Black<br />
w White<br />
Marker<br />
◦ Kreis<br />
∗ Stern<br />
. Punkt<br />
+ Plus<br />
x Kreuz<br />
s Quadrat<br />
d Diamant<br />
^ Dreieck nach oben<br />
v Dreieck nach unten<br />
> Dreieck nach rechts<br />
< Dreieck nach links<br />
p Fünfpunktestern<br />
h Sechspunktestern<br />
Linienart<br />
- durchgezogene Linie<br />
– gestrichelte Linie<br />
: gepunktete Linie<br />
-. gepunktet und gestrichelte Linie<br />
Tabelle 10.1: Parameter für das Aussehen eines Plots<br />
Ein typischer Aufruf hätte die Form plot(x,y,’mx:’), das gleiche Resultat erhält man auch mit<br />
plot(x,y,’m:x’), woran man sieht, dass die Reihenfolge der Angabe irrelevant ist.<br />
Es ist auch möglich mehr als einen Graphen in das Koordinatensystem zu legen:<br />
>> x = [1.5 2.2 3.1 4.6 5.7 6.3 9.4];<br />
>> y = [2.3 3.9 4.3 7.2 4.5 3.8 1.1];<br />
>> a = 1:.1:10;<br />
>> b = 1./a;<br />
>> plot(x,y,’rp--’,a,b,’mx:)<br />
51
Es werden allerdings nicht nur Vektoren als „Datenquellen“ akzeptiert, sondern auch Matrizen.<br />
Wenn x ein m-dimensionaler Vektor und Y eine m x n Matrix ist, bewirkt plot(x,Y) das gleiche wie<br />
plot(x,Y(:1),x,Y(:2),...,x,Y(:,n)). Wenn zusätzlich X auch eine m x n Matrix ist, kann man mit<br />
plot(X,Y) die jeweils korrespondierenden Spalten der beiden Matrizen zu einem Graph verbinden, es<br />
handelt sich also um eine verkürzte Schreibweise von plot(X(:1),Y(:1),...,X(:,n),Y(:,n). Nun stellt<br />
sich die Frage, was passiert, wenn die Einträge in den beteiligten Vektoren und Matrizen nicht reellwertig<br />
sondern komplex sind. In diesem Fall wird der imaginäre Teil ignoriert. Allerdings gibt es eine Ausnahme<br />
- übergibt man plot als einziges Argument eine komplexe Matrix Z, erhält man das identische Resultat<br />
wie mit dem Kommando plot(real(Z),imag(Z)). plot können weitere Attribute übergeben werden,<br />
beispielsweise LineWidth:<br />
>> x = [1.5 2.2 3.1 4.6 5.7 6.3 9.4];<br />
>> y = [2.3 3.9 4.3 7.2 4.5 3.8 1.1];<br />
>> plot(x,y,’LineWidth’,2)<br />
Das Resultat sieht folgendermaßen aus:<br />
Für manche Anwendungen ist es sinnvoller, die Achsen logarithmisch zu skalieren. Dazu verwendet<br />
man statt plot eine der folgenden Anweisungen:<br />
• semilogx(x,y), die x-Achse wird logarithmisch skaliert<br />
• semilogy(x,y), die y-Achse wird logarithmisch skaliert<br />
52
• loglog(x,y), beide Achsen werden logarithmisch skaliert<br />
Beispiel:<br />
Wir wollen den Fehler bei der quadratischen Taylor-Approximation bei kleinen Zahlen visualisieren<br />
und zeigen, dass er sich proportional zu h3 verhält. Dazu betrachten wir |1 + h + h2 − exp(h)| und zum<br />
2<br />
Vergleich h3 jeweils ausgewertet für h = 10−4 , 10−3 , 10−2 , 10−1 , 1 und mit logarithmischer Skalierung:<br />
>> h = 10.^[0:-1:-4];<br />
>> taylor = abs((1+h+h.^2/2)-exp(h));<br />
>> loglog(h,taylor)<br />
>> hold on<br />
>> xlabel(’h’)<br />
>> ylabel(’absoluter Fehler’)<br />
>> title(’Fehler in quadratischer Taylor-Entwicklung’)<br />
>> plot(h,h.^3,’--’)<br />
Das Ergebnis bestätigt unsere Theorie:<br />
Neben loglog haben wir noch einige weitere neue Befehle benutzt, die allerdings mit Ausnahme von<br />
hold on selbsterklärend sein sollten. hold on sorgt dafür, dass beim Plotten von weiteren Funktionen<br />
die bisherigen erhalten bleiben und nicht - wie standardmaßig eingestellt bzw. bei hold off - zunächst<br />
das figure-Fenster „geleert“ und erst dann der neue Plot eingefügt wird. Das ist in unserem Beispiel<br />
durchaus sinnvoll, da wir so überprüfen können, ob die beiden Geraden tatsächlich annähernd parallel<br />
sind. Trotzdem ist es komisch, dass <strong>MATLAB</strong> grundsätzlich in das figure-Fenster mit der Nummer 1<br />
zeichnet. Das muss doch auch anders gehen?! Tut es auch! Mit dem Befehl figure wird ein neues figure-<br />
Fenster geöffnet, mit figure(n) kann man ein beliebiges figure-Fenster aktivieren, so dass sich alle<br />
folgenden (Grafik-) Befehle auf dieses beziehen.<br />
Viele Eigenschaften der Achsen können mit dem axis-Kommando beeinflusst werden. Mögliche Einstellungen<br />
sind:<br />
• axis [xmin xmax ymin ymax]<br />
• axis auto<br />
• axis equal<br />
• axis off<br />
• axis square<br />
• axis tight<br />
53
Für den Fall, dass man nur die Grenzen einer Achse festlegen möchte, stehen die Befehle xlim([xmin,xmax])<br />
und ylim([ymin,ymax]) zur Verfügung. Sollte man sich an einem Ende des Intervalls nicht festlegen wollen<br />
oder können, sorgt die Angabe von -inf bzw. inf dafür, dass sich <strong>MATLAB</strong> darum kümmert. Warum<br />
es an manchen Stellen sinnvoll ist, die Achseneinstellungen selbst vorzunehmen, zeigt folgendes Beispiel:<br />
Wir betrachten die Funktion<br />
Achsen, dann greifen wir manuell ein.<br />
>> x = linspace(0,3,500);<br />
>> plot(x,1./(x-1).^2+3./(x-2).^2)<br />
>> grid on<br />
>> ylim([0 50])<br />
1<br />
(x−1) 2 + 3<br />
(x−2) 2 , zunächst übernimmt <strong>MATLAB</strong> selbst die Begrenzung der<br />
Weiter oben haben wir ja schon gesehen, wie man seinem Plot einen Titel verpasst, doch man kann<br />
auch Text an einer beliebigen Stelle einfügen und sogar einer automatisch erstellten Legende kann<br />
man sich bedienen. Um Text einzufügen, reicht der Befehl text(x,y,’string), wobei (x, y) die Koordinate<br />
festlegt, an der der Text beginnen soll. Zum Einfügen der Legende lautet das Kommando<br />
legend(’string1’, ... ,’stringn’, Position), die Reihenfolge und die Anzahl der übergebenen<br />
Strings sollte mit der im plot- bzw loglog- Befehl übereinstimmen. Mögliche Werte für Position:<br />
• -1: rechts des Plots<br />
• 0: <strong>MATLAB</strong> entscheidet<br />
54
• 1: rechts oben<br />
• 2: links oben<br />
• 3: links unten<br />
• 4: rechts unten<br />
Es ist möglich (und teilweise auch notwendig) in Strings TEX-Code zu benutzen. Um zum Beispiel<br />
folgenden Text am Punkt (−0.6, 0.7) in einer Grafik einzufügen: (n + 1)Pn+1(x) = (2n + 1)xPn(x) −<br />
nPn−1(x) schreibt man idealerweise:<br />
>> text(-.6,.7,’(n+1)P_{n+1}(x)=(2n+1)xP_n(x)-nP_{n-1}(x)’)<br />
10.3 Mehrere Plots in einem Fenster<br />
Der Befehl subplot(m,n,p) teilt das figure-Fenster in m Zeilen und n Spalten auf. p ist ein Skalar und<br />
bezeichnet das aktive Feld.<br />
>> subplot(2,2,1), fplot(’exp(sqrt(x)*(sin(12*x))’,[0 2*pi])<br />
>> subplot(2,2,2), fplot(’sin(round(x))’,[0 10], ’--’)<br />
>> subplot(2,2,3), fplot(’cos(30*x)/x’,[0.01 1 -15 20], ’-.’)<br />
>> subplot(2,2,4), fplot(’[sin(x), cos(2*x),1/(1+x)’,[0 5*pi -1.5 1.5])<br />
Hier haben wir eine neue Funktion genutzt: fplot. <strong>MATLAB</strong> wertet dabei die Funktion an „genug“<br />
Stellen aus, um einen realitätsnahen Graph zu erhalten. Natürlich können auch fplot weitere Parameter<br />
übergeben werden. Mehr dazu findet man - wie zu jeder anderen Funktion auch - unter doc fplot. Auch<br />
eine unregelmäßige Aufteilung des figure-Feldes ist möglich:<br />
>> x = linspace(0,15,100);<br />
>> subplot(2,2,1), plot(x,sin(x))<br />
>> subplot(2,2,2), plot(x,round(x))<br />
>> subplot(2,2,3:4), plot(x, sin(round(x)))<br />
55
10.4 3-dimensionale Plots<br />
Analog zum Befehl plot im zweidimensionalen existiert auch der Befehl plot3 zum Plotten von Kurven<br />
in 3-D. Im Grunde funktioniert er genauso.<br />
>> t = -5:.005:5;<br />
>> x = (1+t.^2).*sin(20*t);<br />
>> y = (1+t.^2).*cos(20*t);<br />
>> z = t;<br />
>> plot3(x,y,z)<br />
>> grid on<br />
plot3 ist zwar ganz nett, kann aber nur zur Visualisierung von Kurven f : R → R 3 genutzt werden,<br />
nicht aber von Funktionen g : R 2 → R, anschaulich gesprochen werden ausschließlich Linien und nie<br />
Flächen dargestellt.<br />
<strong>Eine</strong>n ersten Ausweg aus diesem Dilemma bietet der Befehl ezcontour, der für eine Funktion f :<br />
[xmin, xmax] × [ymin, ymax] → R eine Höhenkarte erzeugt, indem man ezcontour(’f’,[xmin xmax<br />
ymin ymax]); ausführt.<br />
Ähnliches liefert auch die Funktion contour, ihr müssen allerdings zwei Vektoren x und y, sowie eine<br />
Matrix Z = (zi,j) mit zi,j = f(xi, yi) übergeben werden:<br />
56
subplot(211)<br />
>> ezcontour(’sin(3*y-x^2+1)+cos(2*y^2-2*x)’,[-2 2 -1 1]);<br />
>> x = -2:.01:2; y = -1:.01:1;<br />
>> [X,Y] = meshgrid(x,y);<br />
>> Z = sin(3*Y-X.^2+1)+cos(2*Y.^2-2*X);<br />
>> subplot(212)<br />
>> contour(x,y,Z,20)<br />
Um Z zu berechnen haben wir uns hier komponentenweisen Operationen auf Matrizen bedient. Es ist<br />
leicht einzusehen, dass x und y dazu in zwei Matrizen X und Y konvertiert werden müssen, deren Zeilen<br />
bzw. Spalten Kopien der Ursprungsvektoren sind. Genau das erreichen wir durch den Befehl meshgrid<br />
in der vierten Zeile. Beispielsweise liefert [X,Y]=meshgrid(1:4,5:7) die beiden Matrizen<br />
X =<br />
Y =<br />
1 2 3 4<br />
1 2 3 4<br />
1 2 3 4<br />
5 5 5 5<br />
6 6 6 6<br />
7 7 7 7<br />
Natürlich können contour auch mehr als drei Argumente übergeben werden, so dass zum Beispiel die<br />
Anzahl der unterschiedlichen Höhen beeinflusst werden kann. Für Einzelheiten in der Hilfe nachschauen,<br />
bei der Gelegenheit auch mal clabel nachschlagen.<br />
Die Befehle mesh und meshc erwarten als Eingabe die gleichen Datentypen wie contour, sie liefern<br />
uns endlich dreidimensionale Plots, wie wir sie uns vorstellen, meshc legt in die x-y-Ebene zusätzlich eine<br />
Höhenkarte.<br />
>> x = 0:.1:pi; y = 0:.1:pi;<br />
>> [X,Y] = meshgrid(x,y);<br />
>> Z = sin(Y.^2+X)-cos(Y-X.^2);<br />
>> subplot(221)<br />
>> mesh(Z)<br />
>> subplot(222)<br />
>> meshc(Z)<br />
>> subplot(223)<br />
>> mesh(x,y,Z)<br />
57
axis([0 pi 0 pi -5 5])<br />
>> subplot(224)<br />
>> mesh(Z)<br />
hidden off<br />
Es fällt auf, dass nur netzartige Strukturen entstanden sind. Ausgefüllt bekommt man die Graphen<br />
durch die Befehle surf bzw. surfc. Ein ähnliches Resultat liefert auch waterfall.<br />
>> Z = membrane; FS = ’FontSize’;<br />
>> subplot(221), surf(Z), title(’\bf{surf}’,FS,14)<br />
>> subplot(222), surfc(Z), title(’\bf{surfc}’,FS,14), colorbar<br />
>> subplot(223), surf(Z), shading flat<br />
>> title(’\bf{surf} shading flat’,FS,14)<br />
>> subplot(224), waterfall(Z), title(’\bf{waterfall}’,FS,14)<br />
10.4.1 Animationen<br />
Es gibt zwei Möglichkeiten, animierte Plots zu erzeugen.<br />
• Durch Erzeugen einer Sequenz von figures, die gespeichert und in Form eines Films abgespielt wird:<br />
58
Z = peaks; surf(Z)<br />
>> axis tight<br />
>> set(gca,’nextplot’,’replacechildren’)<br />
>> for j = 1:11<br />
>> surf(cos(2*pi*(j-1)/10).*Z,Z)<br />
>> F(j) = getframe;<br />
>> end<br />
>> movie(F)<br />
• Durch Manipulation der Objektattributte XData, YData und ZData, beispielsweise durch Aufruf<br />
der Funktion comet oder comet3:<br />
>> x = linspace(-2,2,500);<br />
>> y = exp(x).*sin(1./x);<br />
>> comet(x,y)<br />
>> t = -pi:pi/500:pi;<br />
>> comet3(sin(5*t),cos(3*t),t)<br />
10.5 Diagramme<br />
10.5.1 Balkendiagramme<br />
Zum Erzeugen von Balkendiagrammen stehen uns im zweidimensionalen die Funktionen bar und barh,<br />
im dreidimensionalen die Funktionen bar3 und barh3 zur Verfügung, das ’h’ steht dabei für horizontal,<br />
wir erhalten also waagerechte Balken. Balkendiagramme aggieren auf Matrizen. Deshalb erzeugen wir<br />
uns zunächst eine Beispiel-Matrix, die uns durch dieses Kapitel begleitet:<br />
>> Y = [7 6 5; 6 8 1; 4 5 9; 2 3 4; 9 7 2];<br />
<strong>MATLAB</strong> gruppiert jeweils die Elemente einer Zeile<br />
>> subplot(2,2,1), bar(Y)<br />
Durch zusätzliche Übergabe eines Vektors x kann man die Beschriftung der x-Achse ändern.<br />
>> x = 0:5:20;<br />
>> subplot(2,2,2), bar(x,Y)<br />
Bisher wurde das Attribut grouped verschwiegen, eigentlich müsste der Aufruf bar(x,Y,’grouped’)<br />
heißen, allerdings wird grouped als Standard angenommen. Die Alternative dazu lautet stacked.<br />
>> subplot(2,2,3), bar(Y,’stacked’)<br />
>> subplot(2,2,4), barh(Y)<br />
Im Dreidimensionalen funktionieren diese Befehle natürlich auch.<br />
59
10.5.2 Tortendiagramme<br />
Tortendiagramme werden mit pie bzw. pie3 erzeugt und erwarten als Parameter einen Vektor. Es besteht<br />
die Möglichkeit einige Tortenteile „herauszutrennen“ bzw. die Torte alternativ zu beschriften:<br />
>> x = [1.5 3.4 4.2];<br />
>> subplot(2,2,1), pie(x)<br />
>> subplot(2,2,2), pie(x,[0,0,1])<br />
>> subplot(2,2,3), pie(x,{’aaa’,’bbb’,’ccc’})<br />
>> subplot(2,2,1), pie3(x,[0,1,0])<br />
60
Kapitel 11<br />
Troubleshooting<br />
11.1 Errors und Warnings<br />
Es ist bestimmt schon jedem ein Tipp- oder Programmierfehler unterlaufen, der von <strong>MATLAB</strong> durch<br />
einen Error quittiert wird:<br />
>> mod(3,sqrt(-2))<br />
??? Error using ==> mod<br />
Arguments must be real.<br />
Zusätzlich zum Wort Error besteht die Fehlermeldung aus einem erläuternden Text - wie aussagekräftig<br />
auch immer der sein mag...<br />
Auf jeden Fall ist es auch möglich sich selbst solche Fehlermeldungen ausgeben zu lassen, das folgende<br />
Beispiel sollte selbserklärend sein:<br />
if ~isreal(arg2), error(’Arguments must be real.’), end<br />
Die Funktion warning zeigt, wie error, sein Argument an, stoppt die Ausführung des Programms aber<br />
nicht. Warum dann nicht einfach disp benutzen? Das hat vor allem zwei Gründe - zum einen kann man<br />
mit warning(’off’), die Warnmeldungen einfach unterdrücken, zum anderen ist es auch möglich alle<br />
aufgetretenen Fehler in einer Variable zu speichern: warns=warning.<br />
11.2 Debugging<br />
Die einfachste Möglichkeit, sich wichtige Zwischenergebnisse bei der Berechnung anzeigen zu lassen, besteht<br />
darin, die gewünschte Variable ohne Semikolon in den Code zu schreiben.<br />
Ein mächtiges Werkzeug von <strong>MATLAB</strong> ist aber auch der so genannte Keyboard-Modus. Er kann an<br />
einer bestimmten Stelle durch die Eingabe von keyboard oder alternativ mit zum Beispiel dbstop at<br />
5 in fak aufgerufen werden. Auf diese Art und Weise lässt sich auch die nützliche Version dbstop if<br />
error implementieren.<br />
Im Keyboard-Modus steht eine Kommandozeile zur Verfüegung, so dass man sowohl Werte von Variablen<br />
abfragen als auch verändern kann.<br />
61
Kapitel 12<br />
Weiterführende<br />
<strong>MATLAB</strong>-Funktionen<br />
Im abschließenden Kapitel sollen noch kurz einige, der vielen weiteren Möglichkeiten mit <strong>MATLAB</strong><br />
zu programmieren vorgestellt werden. Dies erfolgt beispielhaft an einigen interessanten Toolkits, der<br />
Möglichkeit GUIs zu erstellen und <strong>MATLAB</strong> mit anderen Programmiersprachen zu kombinieren.<br />
12.1 Toolkits<br />
Die Funktionalität von <strong>MATLAB</strong> wurde von einigen Toolboxen erweitert.Um herauszufinden, ob eine<br />
Toolbox bereits installiert ist, schaut man die Liste durch, die <strong>MATLAB</strong> nach dem Kommando ver<br />
ausgibt. Wenn der Name der gewünschten Toolbox enthalten ist, so ist diese auch vorhanden.<br />
Es gibt eine Vielzahl solcher Toolboxen z.B. zur Optimierung, für Neuronale Netzwerke, Splines,Partielle<br />
Differentialgleichungen oder für Wavelets. <strong>Eine</strong> aktuelle Liste solcher Toolboxen findet sich unter<br />
http://www.mathworks.com/products/product_listing/index.html<br />
wo es auch entsprechende Dokumentationen gibt. Außerdem gibt es noch eine Vielzahl von Toolboxen,<br />
die von Privatpersonen oder Organisationen zur Verfügung gestellt werden. Diese haben meist sehr<br />
spezielle Zielsetzungen (z.B. INTLAB, Hidden Markow Modell Toolbox, Bioelectromagnetism Toolbox).<br />
Wir werden uns nun mit einer kleinen Auswahl beschäftigen.<br />
12.1.1 Symbolic Math Toolbox<br />
Um auch symbolische Rechnungen (wie im Maple) in <strong>MATLAB</strong> zu machen, benötig man die Symbolic<br />
Math Toolbox. Diese basiert auf MAPLE und liefert einen Teil der dort vorhandenen Funktionen in<br />
<strong>MATLAB</strong>-Syntax mit. Um symbolische Variablen einzuführen, verwendet man den Befehl sym oder syms:<br />
>> b = sym(sqrt(2))<br />
>> syms x y n a<br />
>> f = sin(x*y)/(x*y)<br />
Um diese Variablen wieder in numerische umzuwandeln, verwendet man vpa und um die Genauigkeit<br />
festzulegen digits:<br />
>> digits(25)<br />
>> vpa(b)<br />
Außerdem kann man den symbolischen Variablen auch Werte zuweisen:<br />
>> solve(a*x^2+b*x+c)<br />
>> subs(y,{a,b,c},{1,-1,-1})<br />
Differential- und Integralrechnung<br />
Nachdem man eine Funktion f mit symbolischen Variablen erzeugt hat, kann man diese nun auch ableiten<br />
mit diffoder integrieren mit int:<br />
62
diff(f)<br />
>> int(f)<br />
Außerdem lassen sich auch Grenzwerte symbolisch berechnen mit limit:<br />
>> limit((1 + x/n)^n,n,inf)}<br />
Vereinfachung<br />
Um die Ausgabe leichter lesbar zu machen gibt es das pretty- Kommando:<br />
>> pretty(f)<br />
Um Ausdrücke zu vereinfachen, kann man entweder simplify oder simple verwenden, wobei simple<br />
den Ausdruck sucht, der am kürzesten ist:<br />
>> simplify((1/a^3+6/a^2+12/a+8)^(1/3))<br />
>> simple((1/a^3+6/a^2+12/a+8)^(1/3))<br />
Gleichungssysteme lösen<br />
Desweiteren kann man auch Gleichungen mit solve und Differentialgleichungen mit dsolve lösen:<br />
>> solve(’cos(n*x)+sin(x)=1’)<br />
>> dsolve(’Dy=1+y^2’)<br />
12.1.2 Image Processing Toolbox<br />
Die Image Processing Toolbox bietet die Möglichkeit auf Bilder zuzugreifen, sie zu verändern und zu<br />
speichern.<br />
Lesen und Schreiben von Bildern<br />
Dazu lädt man zuerst ein Bild mit dem Befehl imread. Dieser unterstützt unter anderm die Formate<br />
JPEG, TIFF, GIF, BMP oder PNG. Mit imwrite kann man Bilder speichern. Der Befehl imfinfo gibt<br />
Informationen:<br />
>> A = imread(’test.jpg’);<br />
>> imwrite(A,’test2.jpg’);<br />
>> imfinfo(’test.jpg’)<br />
Anzeigen und Bearbeiten von Bildern<br />
Das Bild kann man sich mit dem Befehl imshow anzeigen lassen:<br />
>> imshow(A)<br />
Den Kontrast eines Graustufenbildes kann man mit dem Befehl imadjust verbessern. Mit dem Befehl<br />
imfilter kann man beliebige Filter auf ein Bild anwenden. <strong>Eine</strong> Auswahl solcher Filter stellt fspecial<br />
zur Verfügung.<br />
>> imadjust(A)<br />
>> h=fspecial(’sobel’)<br />
>> imfilter(A,h)<br />
12.2 Der <strong>MATLAB</strong> C-Compiler<br />
Mit dem <strong>MATLAB</strong> Compiler kann man auch Standalone Anwendungen erstellen oder C-, C++ Shared<br />
Libraries. Dazu muss auf dem System erstmal die <strong>MATLAB</strong> Component Runtime installiert sein. (im<br />
63
<strong>MATLAB</strong>-Verzeichnis unter root\toolbox\compiler\deploy\win32). Anschließend muss man den Compiler<br />
konfigurieren. Dazu ruft man in <strong>MATLAB</strong> mbuild -setup auf und wählt dort das Verzeichnis, in<br />
dem der C-Compiler liegt. Danach kann man mit mcc die eigenen m-Dateien kompilieren. Wenn man eine<br />
Standalone Anwendung erstellen möchte verwendet man:<br />
>> mcc -m eigenefun.m<br />
Für ein C Shared Library:<br />
>> mcc -l eigenefun.m<br />
Für ein C++ Shared Library:<br />
>> mcc -l eigenefun.m -W cpplib -T link:lib<br />
Um die so erzeugte Anwendung oder Bibliothek weiterzugeben, muss man natürlich die compilierte<br />
Datei weitergeben, außerdem die eigenefun.ctf und das <strong>MATLAB</strong> Component Runtime (unter Windows<br />
MCRInstaller.exe, unter Linux MCRInstaller.zip). Nun kann man auf jedem System über die Kommandozeile<br />
das Programm starten, dabei werden die evtl. vorhandenen Parameter einfach nach einem<br />
Leerzeichen angehängt.<br />
12.3 Andere Programmiersprachen mit <strong>MATLAB</strong> verwenden<br />
<strong>MATLAB</strong> ist sehr nützlich für mathematische Programmierung, bietet aber auch die Möglichkeit andere<br />
Programmiersprachen zu nutzen. So kann man z.B. bereits bestehende Programme in C oder Fortran<br />
einbinden oder Java-Klassen nutzen.<br />
12.3.1 Fortran und C<br />
Viele mathematische Programme sind in FORTRAN oder C geschrieben sind und man kann sie auch in<br />
MATAB nutzen, indem man sie etwas ändert und compiliert. Daher testen wir zuerst, ob unser Systm<br />
dafür passend konfigueriert ist. Dazu kompieren wir yprime.c ins aus \extern\examples\mex Arbeitsverzeichnis.<br />
Nun rufen wir mex auf:<br />
>> mex yprime.c<br />
Kann man nun yprime wie eine normale M-Funktion verwenden, funktioniert alles. >> yprime(1,1:4)<br />
Ansonsten sollte man mit mex -setup sicherstellen, dass ein geeigneter Compiler ausgewählt ist.<br />
Ebenso verfährt man mit Fortran-Programmen. Beim Aufruf des Compilers mex kann man auch noch<br />
eine Optionsdatei<br />
(z.B. aus \bin\win32\mexopts) mitgeben:<br />
>> mex yprime.c -f lccopts.bat<br />
Solche Optionsdateien kann man auch selbst erstellen, wenn man zum Beispiel einen nicht supporteten<br />
Compiler verwenden will, oder mehr Einfluss auf den Compilationsprozess nehmen will.<br />
Um ein C bzw. Fortran-Programm <strong>MATLAB</strong> kompatibel anzupassen, benötigt man eine Gatewayroutine.<br />
Außerdem muss im C-Header auch # include „mex.h“ stehen. Die Gatewayroutine stellt die<br />
Schnittstelle zwischen <strong>MATLAB</strong> und C dar:<br />
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const<br />
mxArray*prhs[] )}<br />
nlhs gibt die Anzahl der Ausgabeparameter,nrhs sie Anzahl der Eingabeparameter an. Die Parameter<br />
plhs und prhs enthalten die Pointer auf die entsprechenden Eingabe-/Ausgabevektoren. Danach<br />
kommt C Code, der die Eingaben prüft und die Datenstrukturen (natürlich <strong>MATLAB</strong> kompatibel, z.B.<br />
mxArray) für die Ausgabe anlegt. Die eigentliche C Routine ist meist eine eigene Funktion, die von hier<br />
aus aufgerufen wird und deren Ergebnis dann durch die Gatewayroutine an <strong>MATLAB</strong> zurückgegeben<br />
wird.<br />
Ruft man nun die Funktion in Matlab auf, findet <strong>MATLAB</strong> die MEX-Datei vor M-Dateien mit<br />
gleichem Namen. Dies kann man sich für die <strong>MATLAB</strong> Hilfe zunutze machen. Da die MEX-Datei keine<br />
für <strong>MATLAB</strong> lesbare Hilfe hat, sucht <strong>MATLAB</strong> weiter und gibt die Hilfe einer gleichnamigen M-Datei<br />
aus, falls vorhanden.<br />
Auch Fortran benötigt eine Gatewayroutine, die der in C sehr ähnlich sieht:<br />
subroutine mexFunction(nlhs, plhs, nrhs, prhs)<br />
64
integer plhs(*), prhs(*)<br />
integer nlhs, nrhs,<br />
die anschließend die Eingaben prüft, den Ausgabevektor initialisiert und die eigentliche Funktion aufruft.<br />
Außerdem kann man auch Matlab Routinen in C oder Fortran verwenden. Dazu läuft eine seperate<br />
<strong>MATLAB</strong> Engine, die das C bzw. Fortran Programm ansteuern kann. Dazu muss engine.h eingebunden<br />
sein. Mit engOpen(“\0“) startet man die <strong>MATLAB</strong>-Engine. Man erhält dabei einen Pointer auf die Engine.<br />
Nun kann man Matlab kompatible Variablen deklarieren und mit engPutVariable an Matlab geben.<br />
Die Auswertung eines Ausdrucks erfolt mit engEvalString. Wenn man alle Auswertungen ausgeführt<br />
hat, gibt man den Speicher wieder frei und schließt die <strong>MATLAB</strong> Engine mit engClose, z.B.:<br />
Engine *ep;<br />
ep = engOpen("’\0"’); T = mxCreateDoubleMatrix(1, 10, mxREAL);<br />
engPutVariable(ep, "’T"’, T);<br />
engEvalString(ep,"’D=.5.*(-9.8).*T.^2;"’);<br />
mxDestroyArray(result);<br />
engClose(ep);<br />
Matlab in Fortran einzubinden funktioniert analog.<br />
12.3.2 Java<br />
<strong>MATLAB</strong> liefert außerdem bei seiner Installation eine JVM (Java Virtual Machine) mit und bietet die<br />
Möglichkeit auf Java-Objekte zuzugreifen. Dabei kann man den Pfad entweder statisch in der classpath.txt<br />
(unter \toolbox\local) oder dynamisch mit javaaddpath C:\Java einbinden. Wenn man jar-Archives einbinden<br />
will, muss man ihren vollständigen Pfad inklusiv ihrem Namen angeben, bei normalen Javaklassen<br />
reicht der Pfad zu einem Elternverzeichnis um alle Klassen darin in <strong>MATLAB</strong> verfügbar zu machen. Nun<br />
kann man wie man es aus Java gewohnt ist, mit dem Konstruktor Instanzen einer Java-Klasse erzeugen<br />
und bearbeiten: >> frame = java.awt.Frame(’Frame A’);<br />
>> frame.setSize(100,60);<br />
>> frame.setVisible(true);<br />
Mittels Java-Klassen kann man zum Beispiel Daten aus dem Internet holen:<br />
>> url = java.net.URL(’http://www.fs.tum.de/FSMPI/Kurse/Matlab/test.html’)<br />
>> is = openStream(url);<br />
>> isr = java.io.InputStreamReader(is);<br />
>> br = java.io.BufferedReader(isr);<br />
>> for k = 1:85<br />
s = readLine(br);<br />
end<br />
>> s = readLine(br);<br />
>> disp(s)<br />
12.4 GUIs programmieren<br />
Mit dem <strong>MATLAB</strong> Compiler haben wir eine Möglichkeit kennengelernt, Standalone Anwendungen zu<br />
erstellen, allerdings ist die Parameter-Übergabe wenig intuitiv. Daher ist es sinnvoll für solche Anwendungen<br />
eine GUI zu erstellen. <strong>MATLAB</strong> bietet dazu direkt Funktionen an oder ein graphisches Tool, mit<br />
dem man die Steuerelemente anordnen kann.<br />
12.4.1 GUI Kommandos<br />
Um Steuerelemente direkt zu programmieren, kann man das Kommando uicontrol verwenden. Dem<br />
Kommando werden verschiedene Werte mitgegeben, z.B. gibt ’Style’ an, was für ein Element man möchte<br />
(z.B. checkbox, edit, listbox, popupmenu pushbutton, radiobutton, slider, text). Man kann zum Beipiel<br />
65
einer figure einen Button zum Schließen des Fensters mitgeben:<br />
>> fh = figure(’NumberTitle’,’off’,’Name’,’GUI’);<br />
>> ah = axes(’Position’,[0.1 0.1 0.65 0.85]);<br />
>> membrane;<br />
>> ph = uicontrol(fh, ’Style’, ’pushbutton’, ’String’, ’Ende’, ’Units’, ’normalized’,<br />
’Position’, [0.8 0.08 0.18 0.12], ’ToolTipString’,’Schließt das Fenster’,’Callback’,<br />
’close(gcbf)’);<br />
12.4.2 GUIDE<br />
Guide ist ein graphisches Interface um GUIs zu erzeugen. Um es zu starten tippt man den Befehl guide.<br />
Nun kann man auf einem leeren GUI die Komponenten per Drag’n’Drop anordnen. Und mit dem Property<br />
Manager Eigenschaften zuordnen (z.B. Farbe, Text, Closefunction). Wenn man die fertige GUI<br />
gespeichert hat, findet man eine .fig und .m Datei desselben Namens. Bis jetzt haben wir nur eine Gui,<br />
die aber noch keine Funktionalität besitzt, wenn wir sie starten. Wenn wir die .m-Datei editieren, weisen<br />
wir nun die entsprechenden Funktionen zu. In der generierten M-Datei findet sich am Anfang eine Initialisierung,<br />
die man nicht änern sollte. Anschließend kommt die eigene Opening Function. Hier schreiben<br />
wir alle Funktionen hinein, die nur einmal und zwar beim Öffnen der Gui erledigt werden sollen (z.B.<br />
Beispielplot). Mit setappdata stellen wir dann die gebrechneten Daten der GUI zur Verfügung. Die Output<br />
Funktion verwenden wir, wenn wir Werte z.B. an eine weitere GUI weitergeben möchten (so muss<br />
man sie nicht öffentlich deklarieren). In der Callback Funktion implementieren wir die Funktionalität der<br />
einzelnen Elemente, z.B. Auslesen eines Wertes von einem Slider (hObject ist das Handle des Sliders):<br />
>> f = get(hObject,’Value’);<br />
66
Literaturverzeichnis<br />
[1] Stoer: Numerische Mathematik 1. Springer-Verlag, Berlin Heidelberg, New-York<br />
67
Index<br />
[], 21<br />
function, 31<br />
charakteristisches Polynom, 37<br />
Cholesky-Zerlegung, 36<br />
Debugging, 61<br />
Determinante, 35<br />
Eingabe, 42<br />
Funktionen<br />
addpath, 32<br />
all, 24<br />
and, 24<br />
any, 24<br />
axis, 53<br />
bar3, 59<br />
barh3, 59<br />
barh, 59<br />
bar, 59<br />
blkdiag, 13<br />
break, 28<br />
case, 29<br />
chol, 20<br />
clabel, 57<br />
clear, 32, 44<br />
comet3, 59<br />
comet, 59<br />
condest, 34<br />
continue, 28, 29<br />
contour, 56, 57<br />
cos, 19<br />
cumsum, 20<br />
dbstop, 61<br />
diag, 12<br />
diff, 20, 62<br />
digits, 62<br />
disp, 43, 61<br />
doc, 55<br />
dsolve, 63<br />
eigs, 38<br />
elseif, 27<br />
else, 27<br />
error, 61<br />
exist, 32<br />
expm, 38<br />
exp, 19, 38<br />
eye, 11<br />
ezcontour, 56<br />
68<br />
factorial, 19<br />
feval, 39<br />
figure, 53, 66<br />
find, 26<br />
fminsearch, 32<br />
for, 9, 14, 26–28, 46, 48<br />
fplot, 55<br />
fprintf, 43, 44<br />
fread, 45<br />
fscanf, 45<br />
fspecial, 63<br />
funm, 38, 39<br />
fwrite, 45<br />
gallery, 14<br />
ginput, 42<br />
global, 40<br />
guide, 66<br />
help, 31, 32<br />
hilb, 13<br />
hold, 53<br />
if, 26, 27, 29<br />
imadjust, 63<br />
imfilter, 63<br />
imfinfo, 63<br />
imread, 63<br />
imshow, 63<br />
imwrite, 63<br />
inline, 39<br />
int2str, 43<br />
int, 62<br />
invhilb, 13<br />
inv, 35<br />
isequal, 23<br />
isnan, 23<br />
keyboard, 61<br />
legend, 54<br />
length, 19<br />
limit, 63<br />
linspace, 14<br />
load, 43<br />
logical, 24<br />
loglog, 53<br />
logm, 38<br />
lookfor, 32<br />
lsqnonneg, 35<br />
lu, 36<br />
magic, 13<br />
max, 20<br />
meshc, 57
meshgrid, 57<br />
mesh, 57<br />
more, 32<br />
normest, 34<br />
norm, 20, 34<br />
not, 24<br />
num2str, 43<br />
numel, 19<br />
ones, 11<br />
or, 24<br />
pathtool, 32<br />
path, 32<br />
pause, 42<br />
pie3, 60<br />
pie, 60<br />
plot3, 56<br />
plot, 9, 50–52, 56<br />
poly, 37<br />
pretty, 63<br />
primes, 16<br />
prod, 20<br />
qr, 37<br />
randn, 11, 12<br />
rand, 11, 12<br />
rcond, 34<br />
repmat, 13<br />
reshape, 21, 45<br />
run, 32<br />
save, 43<br />
scanf, 45<br />
semilogx, 52<br />
semilogy, 52<br />
simple, 63<br />
simplify, 63<br />
sin, 19<br />
size, 19<br />
solve, 63<br />
sort, 20<br />
sqrtm, 38<br />
sub2ind, 16<br />
subplot, 55<br />
sum, 20<br />
surfc, 58<br />
surf, 58<br />
switch, 26, 29<br />
syms, 62<br />
sym, 62<br />
text, 54<br />
tril, 20<br />
triu, 20<br />
type, 32<br />
uicontrol, 65<br />
vectorize, 39<br />
ver, 62<br />
vpa, 62<br />
warning, 61<br />
waterfall, 58<br />
what, 32<br />
69<br />
which, 32<br />
while, 26, 28<br />
whos , 43<br />
xlim, 54<br />
xor, 24<br />
ylim, 54<br />
zeros, 11<br />
eig, 37<br />
hilb, 18<br />
hold, 9<br />
input, 42<br />
invhilb, 18<br />
spdiags, 10<br />
speye, 10<br />
subplot, 59, 60<br />
condeig, 38<br />
fopen, 44<br />
lu, 36<br />
norm, 34<br />
pinv, 36<br />
globale Variablen, 40<br />
GUI, 65<br />
GUIDE, 66<br />
Hilbertmatrix, 13<br />
Inverse, 35<br />
Keyboard-Modus, 61<br />
Komplexe Zahlen, 5<br />
Kondition, 34<br />
kubische Splines, 7<br />
leere Felder, 48<br />
lineare Gleichungssysteme, 35<br />
logical, 23<br />
logische Felder, 24<br />
LR-Zerlegung, 36<br />
magische Quadrate, 13<br />
Matrix, 11<br />
Moore-Penrose-Inverse, 34<br />
natürlicher Spline, 7<br />
Norm, 34<br />
NumPy, 5<br />
Octave, 5<br />
Operatoren, 23<br />
\, 35<br />
=, 23<br />
:, 14<br />
’, 16<br />
*, 17<br />
+, 17
-, 17<br />
.’, 16<br />
.*, 17<br />
:, 15<br />
=, 23<br />
Pseudoinverse, 36<br />
Python, 5<br />
QR-Zerlegung, 37<br />
Rekursion, 40<br />
SciLab, 5<br />
SciPy, 5<br />
symbolisches rechnen, 62<br />
Tortendiagramme, 60<br />
transponieren, 16<br />
Variablen<br />
ans, 5<br />
Vektor, 11<br />
Workspace, 43<br />
70