Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3...

466

Transcript of Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3...

Page 1: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

Page 2: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 3: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Rechnen mit Sage

Calcul mathématique avec

SAGE

Page 4: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 5: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Dieses Werk wird unter der Lizenz Creative Commons(https://creativecommons.org/licenses/by-sa/3.0/de/) verteilt.Es kann von der Seite http://sagebook.gforge.inria.fr frei heruntergeladen werden.

Die Autoren des Originals:Alexandre Casamayou Nathan Cohen

Guillaume Connan Thierry Dumont Laurent FousseFrançois Maltey Matthias Meulien Marc MezzarobbaClément Pernet Nicolas M. Thiéry Paul Zimmermann

Aus dem Französischen übertragen,an Sages aktuelle Version 7 angepasst, soweit möglich,

sonst mit einem Hinweis versehenund in LATEX gesetzt von Helmut Büch, Gifhorn

i

Page 6: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 7: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

I. Die Handhabung von Sage 1

1. Erste Schritte 31.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.1. Ein Werkzeug für Mathematiker . . . . . . . . . . . . . . . . . . . . . 31.1.2. Zugang zu Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.1.3. Quellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2. Sage als Taschenrechner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2.1. Erste Rechnungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2.2. Elementare Funktionen und Konstanten . . . . . . . . . . . . . . . . . 111.2.3. Online-Hilfe und automatische Vervollständigung . . . . . . . . . . . . 121.2.4. Python-Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.2.5. Symbolische Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.2.6. Erste Graken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2. Analysis und Algebra 172.1. Symbolische Ausdrücke und Vereinfachungen . . . . . . . . . . . . . . . . . . 17

2.1.1. Symbolische Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . 172.1.2. Umformung von Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . 182.1.3. Gebräuchliche mathematische Funktionen . . . . . . . . . . . . . . . . 202.1.4. Vorgaben für eine symbolische Variable . . . . . . . . . . . . . . . . . 212.1.5. Mögliche Gefahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.2. Gleichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2.1. Explizite Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.2.2. Gleichungen ohne explizite Lösung . . . . . . . . . . . . . . . . . . . . 26

2.3. Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.3.1. Summen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.3.2. Grenzwerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.3.3. Folgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.3.4. Taylor-Reihenentwicklung (*) . . . . . . . . . . . . . . . . . . . . . . . 302.3.5. Reihen (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.3.6. Ableitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3.7. Partielle Ableitungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3.8. Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

2.4. Elementare lineare Algebra (*) . . . . . . . . . . . . . . . . . . . . . . . . . . 352.4.1. Lösung linearer Gleichungssysteme . . . . . . . . . . . . . . . . . . . . 352.4.2. Vektorrechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352.4.3. Matrizenrechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362.4.4. Reduktion einer quadratischen Matrix . . . . . . . . . . . . . . . . . . 38

3. Programmierung und Datenstrukturen 413.1. Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.1.1. Allgemeine Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423.1.2. Aufruf von Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

iii

Page 8: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

3.1.3. Ergänzungen zu Variablen . . . . . . . . . . . . . . . . . . . . . . . . . 433.2. Algorithmik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

3.2.1. Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443.2.2. Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513.2.3. Prozeduren und Funktionen . . . . . . . . . . . . . . . . . . . . . . . . 523.2.4. Beispiel: schnelles Potenzieren . . . . . . . . . . . . . . . . . . . . . . . 553.2.5. Datenein- und -ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . 57

3.3. Listen und zusammengesetzte Strukturen . . . . . . . . . . . . . . . . . . . . 583.3.1. Denition von Listen und Zugri auf die Elemente . . . . . . . . . . . 583.3.2. Globale Operationen auf Listen . . . . . . . . . . . . . . . . . . . . . . 603.3.3. Wichtige Methoden auf Listen . . . . . . . . . . . . . . . . . . . . . . . 643.3.4. Beispiele für Listenbearbeitung . . . . . . . . . . . . . . . . . . . . . . 663.3.5. Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673.3.6. Teilen und Verdoppeln einer Struktur . . . . . . . . . . . . . . . . . . 683.3.7. Veränderbare und nicht veränderbare Daten . . . . . . . . . . . . . . . 703.3.8. Endliche Mengen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703.3.9. Diktionäre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

4. Graphiken 754.1. Kurven in 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.1.1. Graphische Darstellung von Funktionen . . . . . . . . . . . . . . . . . 754.1.2. Kurven in Parameterdarstellung . . . . . . . . . . . . . . . . . . . . . 784.1.3. Kurven in Polarkoordinaten . . . . . . . . . . . . . . . . . . . . . . . . 794.1.4. Durch implizite Gleichungen denierte Kurven . . . . . . . . . . . . . 794.1.5. Die Darstellung von Daten . . . . . . . . . . . . . . . . . . . . . . . . 804.1.6. Zeichnen der Lösung einer Dierentialgleichung . . . . . . . . . . . . . 844.1.7. Evolute einer Kurve . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

4.2. Graphik in 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5. Denitionsmengen für das Rechnen 955.1. Sage ist objektorientiert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

5.1.1. Objekte, Klassen und Methoden . . . . . . . . . . . . . . . . . . . . . 955.1.2. Objekte und Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . 965.1.3. Introspektion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

5.2. Elemente, Vorfahren, Kategorien . . . . . . . . . . . . . . . . . . . . . . . . . 995.2.1. Elemente und Vorfahren . . . . . . . . . . . . . . . . . . . . . . . . . . 995.2.2. Konstruktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1005.2.3. Ergänzung: Kategorien . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.3. Denitionsmengen für das Rechnen und die Darstellung in Normalform . . . . 1025.3.1. Elementare Zahlenarten . . . . . . . . . . . . . . . . . . . . . . . . . . 1035.3.2. Zusammengesetzte Objektklassen . . . . . . . . . . . . . . . . . . . . . 106

5.4. Ausdrücke versus Zahlenarten für das Rechnen . . . . . . . . . . . . . . . . . 1085.4.1. Ausdrücke als Denitionsmenge für das Rechnen . . . . . . . . . . . . 1085.4.2. Beispiele: Polynome und Normalformen . . . . . . . . . . . . . . . . . 1095.4.3. Beispiel: Faktorisierung von Polynomen . . . . . . . . . . . . . . . . . 1105.4.4. Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

iv

Page 9: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

II. Algebra und symbolisches Rechnen 113

6. Endliche Körper und elementare Zahlentheorie 1156.1. Ringe und endliche Körper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

6.1.1. Ring der ganzen Zahlen modulo n . . . . . . . . . . . . . . . . . . . . 1156.1.2. Endliche Körper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1176.1.3. Rationale Rekonstruktion . . . . . . . . . . . . . . . . . . . . . . . . . 1186.1.4. Chinesische Reste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

6.2. Primzahltests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1206.3. Faktorisierung und diskreter Logarithmus . . . . . . . . . . . . . . . . . . . . 1226.4. Anwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

6.4.1. Die Konstante δ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1246.4.2. Berechnung mehrfacher Integrale durch rationale Rekonstruktion . . . 125

7. Polynome 1277.1. Polynomringe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

7.1.1. Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1277.1.2. Erzeugung von Polynomringen . . . . . . . . . . . . . . . . . . . . . . 1287.1.3. Polynome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.2. Euklidsche Arithmetik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1327.2.1. Teilbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1337.2.2. Ideale und Quotientenringe . . . . . . . . . . . . . . . . . . . . . . . . 135

7.3. Faktorisierung und Wurzeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1367.3.1. Faktorisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1367.3.2. Wurzelsuche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1387.3.3. Resultante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1397.3.4. Galoisgruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

7.4. Gebrochen rationale Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . 1427.4.1. Erzeugung und elementare Eigenschaften . . . . . . . . . . . . . . . . 1427.4.2. Zerlegung in einfache Elemente . . . . . . . . . . . . . . . . . . . . . . 1437.4.3. Rationale Rekonstruktion . . . . . . . . . . . . . . . . . . . . . . . . . 143

7.5. Formale Potenzreihen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1477.5.1. Operationen auf abbrechenden Reihen . . . . . . . . . . . . . . . . . . 1477.5.2. Reihenentwicklung von Gleichungslösungen . . . . . . . . . . . . . . . 1497.5.3. Faule Reihen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

7.6. Rechnerinterne Darstellung von Polynomen . . . . . . . . . . . . . . . . . . . 151

8. Lineare Algebra 1558.1. Erstellung und elementare Operationen . . . . . . . . . . . . . . . . . . . . . . 155

8.1.1. Vektorräume, Matrix-Vektorräume . . . . . . . . . . . . . . . . . . . . 1558.1.2. Erzeugung von Matrizen und Vektoren . . . . . . . . . . . . . . . . . . 1578.1.3. Grundlegende Operationen und Matrizen-Arithmetik . . . . . . . . . . 1588.1.4. Grundlegende Operationen mit Matrizen . . . . . . . . . . . . . . . . . 160

8.2. Rechnungen mit Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1608.2.1. Gauÿ-Algorithmus und Treppennormalform . . . . . . . . . . . . . . . 1618.2.2. Lösung von Gleichungssystemen; Bild und Basis des Kerns . . . . . . . 1678.2.3. Eigenwerte, Jordanform und Ähnlichkeitstransformationen . . . . . . . 169

9. Polynomiale Systeme 1799.1. Polynome in mehreren Unbestimmten . . . . . . . . . . . . . . . . . . . . . . 179

9.1.1. Die Ringe A[x1, . . . , , xn] . . . . . . . . . . . . . . . . . . . . . . . . . . 179

v

Page 10: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

9.1.2. Polynome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1819.1.3. Grundlegende Operationen . . . . . . . . . . . . . . . . . . . . . . . . 1829.1.4. Arithmetik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

9.2. Polynomiale und ideale Systeme . . . . . . . . . . . . . . . . . . . . . . . . . . 1849.2.1. Ein erstes Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1849.2.2. Was heiÿt Lösen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1879.2.3. Ideale und Systeme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1889.2.4. Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1939.2.5. Systeme der Dimension null . . . . . . . . . . . . . . . . . . . . . . . . 198

9.3. Gröbnerbasen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2039.3.1. Monomiale Ordnungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 2039.3.2. Division durch eine Familie von Polynomen . . . . . . . . . . . . . . . 2049.3.3. Gröbnerbasen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2059.3.4. Eigenschaften der Gröbnerbasen . . . . . . . . . . . . . . . . . . . . . 2099.3.5. Berechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211

10.Dierentialgleichungen und rekursiv denierte Folgen 21510.1. Dierentialgleichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

10.1.1. Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21510.1.2. Gewöhnliche Dierentialgleichungen 1. Ordnung . . . . . . . . . . . . . 21610.1.3. Gleichungen 2. Odnung . . . . . . . . . . . . . . . . . . . . . . . . . . 22410.1.4. Laplace-Transformation . . . . . . . . . . . . . . . . . . . . . . . . . . 22610.1.5. Lineare Dierentialsysteme . . . . . . . . . . . . . . . . . . . . . . . . 227

10.2. Rekursiv denierte Folgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22910.2.1. Durch un+1 = f(un) denierte Folgen . . . . . . . . . . . . . . . . . . 22910.2.2. Lineare rekursiv denierte Folgen . . . . . . . . . . . . . . . . . . . . . 23110.2.3. Rekursiv denierte Folgen mit zweitem Glied . . . . . . . . . . . . . 232

III. Numerisches Rechnen 235

11.Gleitpunktzahlen 23711.1. Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

11.1.1. Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23711.1.2. Eigenschaften, Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . 23811.1.3. Normalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

11.2. Die Gleitpunktzahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23911.2.1. Welchen Zahlentyp wählen? . . . . . . . . . . . . . . . . . . . . . . . . 241

11.3. Einige Eigenschaften der Gleitpunktzahlen . . . . . . . . . . . . . . . . . . . . 24111.3.1. Mengen voller Löcher . . . . . . . . . . . . . . . . . . . . . . . . . . . 24111.3.2. Das Runden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24211.3.3. Einige Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24211.3.4. Komplexe Gleitpunktzahlen . . . . . . . . . . . . . . . . . . . . . . . . 24711.3.5. Die Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

11.4. Schlussbemerkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

12.Nichtlineare Gleichungen 25112.1. Algebraische Gleichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

12.1.1. Die Methode Polynomial.roots() . . . . . . . . . . . . . . . . . . . . 25112.1.2. Zahlendarstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25212.1.3. Der Gauÿ-d'Alembertsche Fundamentalsatz der Algebra . . . . . . . . 253

vi

Page 11: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

12.1.4. Verteilung der Wurzeln . . . . . . . . . . . . . . . . . . . . . . . . . . . 25312.1.5. Lösung durch Wurzelausdrücke . . . . . . . . . . . . . . . . . . . . . . 25412.1.6. Die Methode Expression.roots() . . . . . . . . . . . . . . . . . . . . 255

12.2. Numerische Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25712.2.1. Lokalisierung der Lösungen algebraischer Gleichungen . . . . . . . . . 25712.2.2. Verfahren der sukzessiven Approximation . . . . . . . . . . . . . . . . 259

13.Numerische lineare Algebra 27313.1. Ungenaues Rechnen in der linearen Algebra . . . . . . . . . . . . . . . . . . . 273

13.1.1. Normen von Matrizen und Kondition . . . . . . . . . . . . . . . . . . . 27413.2. Voll besetzte Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276

13.2.1. Lösung linearer Gleichungssysteme . . . . . . . . . . . . . . . . . . . . 27613.2.2. Direkte Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27713.2.3. Die LU -Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27813.2.4. Die Cholesky-Zerlegung reeller positiv deniter symmetrischer Matrizen 27813.2.5. Die QR-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27913.2.6. Die Singulärwertzerlegung . . . . . . . . . . . . . . . . . . . . . . . . . 27913.2.7. Anwendung auf kleinste Quadrate . . . . . . . . . . . . . . . . . . . . 28013.2.8. Eigenwerte, Eigenvektoren . . . . . . . . . . . . . . . . . . . . . . . . . 28313.2.9. Polynomiale Angleichung: die Rückkehr des Teufels . . . . . . . . . . . 28813.2.10.Implementierung und Leistung . . . . . . . . . . . . . . . . . . . . . . 291

13.3. Dünn besetzte Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29213.3.1. Vorkommen dünn besetzter Matrizen . . . . . . . . . . . . . . . . . . . 29213.3.2. Sage und dünn besetzte Matrizen . . . . . . . . . . . . . . . . . . . . . 29313.3.3. Lösung linearer Systeme . . . . . . . . . . . . . . . . . . . . . . . . . . 29313.3.4. Eigenwerte, Eigenvektoren . . . . . . . . . . . . . . . . . . . . . . . . . 29513.3.5. Gegenstand des Nachdenkens: Lösung von sehr groÿen nicht-linearen

Systemen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

14.Numerische Integration und Dierentialgleichungen 29714.1. Numerische Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

14.1.1. Funktionen für die Integration . . . . . . . . . . . . . . . . . . . . . . . 30314.2. Numerische Lösung gewöhnlicher Dierentialgleichungen . . . . . . . . . . . . 309

14.2.1. Beispiellösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31014.2.2. Verfügbare Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

IV. Kombinatorik 315

15.Abzählende Kombinatorik 31715.1. Erste Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

15.1.1. Poker und Wahrscheinlichkeiten . . . . . . . . . . . . . . . . . . . . . . 31715.1.2. Abzählen von Bäumen durch erzeugende Reihen . . . . . . . . . . . . 320

15.2. Die üblichen abzählbaren Mengen . . . . . . . . . . . . . . . . . . . . . . . . . 32615.2.1. Beispiel: Teilmengen einer Menge . . . . . . . . . . . . . . . . . . . . . 32615.2.2. Partitionen natürlicher Zahlen . . . . . . . . . . . . . . . . . . . . . . . 32715.2.3. Einige andere abzählbare endliche Mengen . . . . . . . . . . . . . . . . 329

15.3. Konstruktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33915.4. Generische Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341

15.4.1. Lexikographische Erzeugung ganzzahliger Listen . . . . . . . . . . . . 34115.4.2. Ganzzahlige Punkte in Polytopen . . . . . . . . . . . . . . . . . . . . . 343

vii

Page 12: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

15.4.3. Arten, zerlegbare kombinatorischer Klassen . . . . . . . . . . . . . . . 34415.4.4. Graphen bis auf Isomorphie . . . . . . . . . . . . . . . . . . . . . . . . 345

16.Graphentheorie 34916.1. Erzeugen eines Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

16.1.1. Beginn bei Null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34916.1.2. Verfügbare Konstruktoren . . . . . . . . . . . . . . . . . . . . . . . . . 35116.1.3. Disjunkte Vereinigungen . . . . . . . . . . . . . . . . . . . . . . . . . . 35316.1.4. Ausgabe von Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . 355

16.2. Methoden der Klasse Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35716.2.1. Modikation der Struktur von Graphen . . . . . . . . . . . . . . . . . 35816.2.2. Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35816.2.3. Traversierung von Graphen und Abstände . . . . . . . . . . . . . . . . 36016.2.4. Fluss, Konnektivität, Paarung (Matching) . . . . . . . . . . . . . . . . 36116.2.5. NP-vollständige Probleme . . . . . . . . . . . . . . . . . . . . . . . . . 36216.2.6. Erkennen und Prüfen von Eigenschaften . . . . . . . . . . . . . . . . . 363

16.3. Graphen in Aktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36516.3.1. Gierige Färbung der Knoten eines Graphen . . . . . . . . . . . . . . . 36516.3.2. Erzeugung von Graphen unter Bedingungen . . . . . . . . . . . . . . . 36716.3.3. Anwendung eines probabilistischen Algorithmus bei der Suche nach ei-

ner groÿen unabhängigen Menge . . . . . . . . . . . . . . . . . . . . . 36816.3.4. Suchen eines induzierten Subgraphen in einem Zufallsgraphen . . . . . 369

16.4. Einige mit Graphen modellierte Probleme . . . . . . . . . . . . . . . . . . . . 37116.4.1. Ein Rätsel aus der Zeitschrift Le Monde 2 . . . . . . . . . . . . . . . 37116.4.2. Die Zuordnung von Aufgaben . . . . . . . . . . . . . . . . . . . . . . . 37216.4.3. Planung eines Turniers . . . . . . . . . . . . . . . . . . . . . . . . . . . 373

17.Lineare Programmierung 37517.1. Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37517.2. Ganzzahlige Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 37617.3. In der Praxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

17.3.1. Die Klasse MixedIntegerLinearProgram . . . . . . . . . . . . . . . . . 37617.3.2. Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37717.3.3. Nicht lösbare oder nicht endende Probleme . . . . . . . . . . . . . . . 378

17.4. Erste Anwendungen auf die Kombinatorik . . . . . . . . . . . . . . . . . . . . 37917.4.1. Das Rucksackproblem . . . . . . . . . . . . . . . . . . . . . . . . . . . 37917.4.2. Paarung (Matching) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38017.4.3. Fluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

17.5. Erzeugung von Bedingungen und Anwendung . . . . . . . . . . . . . . . . . . 382

A. Lösungen der Übungen 387A.1. Erste Schritte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387A.2. Analysis und Algebra mit Sage . . . . . . . . . . . . . . . . . . . . . . . . . . 387A.3. Programmierung und Datenstrukturen . . . . . . . . . . . . . . . . . . . . . . 396A.4. Graphik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396A.5. Denitionsmengen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399A.6. Endliche Körper und elementare Zahlentheorie . . . . . . . . . . . . . . . . . 400A.7. Polynome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405A.8. Lineare Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409A.9. Polynomiale Systeme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411A.10.Dierentialgleichungen und rekursiv denierte Folgen . . . . . . . . . . . . . . 414

viii

Page 13: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

A.11.Flieÿpunktzahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416A.12.Nichtlineare Gleichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419A.13.Numerische lineare Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421A.14.Numerische Integration und Dierentialgleichungen . . . . . . . . . . . . . . . 422A.15.Aufzählende Kombinatorik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424A.16.Graphentheorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429A.17.Lineare Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

B. Bibliographie 433

C. Register 437

ix

Page 14: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

Vorwort zur französischen Ausgabe

Dieses Buch ist für alle diejenigen gedacht, die ein System für mathematische Berechnungen,insbesondere das Programm Sage, ezient nutzen möchten. Diese Systeme bieten eine Füllevon Funktionen und herauszunden, wie ein gegebenes Problem gelöst werden kann, ist nichtimmer einfach. Ein Referenzhandbuch liefert zu jeder Funktion des Systems eine analytischeund detaillierte Beschreibung, doch muss man den Namen der Funktion wissen, die man sucht!Der hier eingenommene Standpunkt ist ergänzend, wir geben mit Betonung der zugrundeliegenden Mathematik eine nach Themen geordnete Übersicht über die Klassen der zu lösendenProbleme und die entsprechenden Algorithmen.

Der erste Teil, der mehr an Sage ausgerichtet ist, zeigt die Handhabung des Systems. DieserTeil sollte allen Studenten wissenschatlich-technischer Fächer (BTS, IUT, Vorbereitungskurse,Bachelor)1 zugänglich sein und in gewissem Umfang auch Schülern der gymnasialen Oberstufe.Die anderen Teile wenden sich an Studenten in höheren Semestern2. Anders als in einemReferenzhandbuch werden die mathematischen Begrie klar formuliert, bevor sie mit Sageumgesetzt werden. Damit ist dieses Buch auch ein Buch über Mathematik.

Zur Illustration dieser Vorgehensweise fällt die Wahl natürlich auf Sage, denn das ist freieSoftware, die jedermann nach Belieben benutzen, verändern und verteilen darf. So wird einSchüler, der auf dem Gymnasium Sage kennen gelernt hat, es auch auf seinem beruichenWege anwenden, als Bachelor, Master oder Doktorand, auf der Ingenieurschule, im Unter-nehmen usw. Sage ist im Vergleich zu konkurrierender Software ein noch junges Programmund trotz seiner vielseitigen Fähigkeiten enthält es noch zahlreiche Fehler. Doch dank seinersehr aktiven Commumity entwickelt sich Sage sehr rasch. Jeder Anwender von Sage kann auftrac.sagemath.org oder über die Liste sage-support einen Fehler melden - und vielleichtsogar dessen Behebung.

Bei der Erstellung dieses Buches hat uns die Version 5.9 vorgelegen. Trotzdem sollten dieBeispiele mit jeder weiteren Version funktionieren, hingegen könnten bestimmte Aussagennicht mehr stimmen, beispielsweise weil Sage zur Auswertung numerischer Integrale Maximaverwendet.

Als ich im Dezember 2009 Alexandre Casamayou, Guillaume Connan, Thierry Dumont, Lau-rent Fousse, François Maltey, Matthias Meulien, Marc Mezzarobba, Clément Pernet und Ni-colas M. Thiéry vorgeschlagen habe, über Sage ein Buch zu schreiben, haben alle trotz er-heblicher Arbeitsbelastung prompt geantwortet, wie auch Nathan Cohen, der sich uns beidiesem Abenteur angeschlossen hat. Ich lege Wert darauf, Ihnen allen zu danken, besondersdafür, dass sie den engen Zeitplan eingehalten haben, den ich vorgegeben hatte, und ganzbesonders Nathan Cohen, Marc Mezzarobba und Nicolas Thiéry für ihr groÿes Engagemantauf der Zielgeraden.

Alle Autoren danken folgenden Personen, die die Vorabversionen dieses Buches gelesen haben:Gaëtan Bisson, Françoise Jung, Hugh Thomas, Anne Vaugon, Sébastien Desreux, PierrickGaudry. Maxime Huet, Jean Thiéry, Muriel Shan Sei Fan, Timothy Walsh, Daniel Duparc,Kévin Rowanet und Kamel Naroun (eine besondere Erwähnung dieser beiden, die Druckfehlergefunden haben, die 17 Korrekturlesungen wiederstanden haben); wie auch Emmanuel Thomé

1Brevet de Technicien Supérieur, Institute Universitaire des Technologie2étudiants au niveau agrégation

x

Page 15: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhaltsverzeichnis

für deine wertvolle Hilfe bei der Realisierung dieses Buches, Sylvain Chevillard, Gaëtan Bissonund Jérémie Detrey für ihre besonnenen typographischen Ratschläge und für die Fehler, diesie gefunden haben. Der Entwurf des Umschags wurde nach einer originellen Idee von AlbaneSaintenoy von Corinne Thiéry realisiert.

Beim Schreiben dieses Buches haben wir viel über Sage gelernt. Wir haben dabei natürlichauch Fehler gefunden, von denen einige schon korrigiert worden sind. Wir hoen, dass diesesBuch auch anderen von Nutzen sein wird, Schülern, Studenten, Lehrern, Ingenieuren, For-schern oder Amateuren! Die Arbeit enthält sicherlich noch zahlreiche Unvollkommenheiten,umgekehrt erwarten wir deshalb vom Leser, dass er uns alle Fehler anzeigt und uns auchKritik und Anregungungen für eine spätere Auage zukommen lässt: danke, dass Sie dafürdie Seite sagebook.gforge.inria.fr benutzen.

Nancy, FrankreichMai 2013 Paul Zimmermann

xi

Page 16: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 17: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Teil I.

Die Handhabung von Sage

1

Page 18: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 19: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

Dieses einführende Kapitel präsentiert die Denkungsart des Mathematikprogramms Sage. Dieanderen Kapitel dieses ersten Teils entwickeln die Grundbegrie von Sage: Ausführung nu-merischer oder symbolischer Rechnungen in der Analysis, Operationen auf Vektoren und Ma-trizen, Schreiben von Programmen, Verarbeitung von Datenlisten, Entwerfen von Grakenusw. Die folgenden Teile dieses Buches vertiefen einige Zweige der Mathematik, bei denen dieInformatik eine hohe Leistungsfähigkeit unter Beweis stellt.

1.1. Das Programm Sage

1.1.1. Ein Werkzeug für Mathematiker

Sage ist eine Software, die mathematische Algorithmen aus vielen Gebieten implementiert.In erster Linie operiert das System auf verschidenen Zahlenarten: den ganzen Zahlen oderden rationalen, mit variabler Präzision auf den numerischen Näherungen der reellen und derkomplexen Zahlen oder auch auf den Elementen der endlichen Körper. Sehr schnell kann sichder Anwender Sages als wissenschatlichem und evtl. graschem Taschenrechner bedienen.

Doch das Rechnen beschränkt sich nicht auf Zahlen. Die Studenten lernen beispielsweise,Systeme inhomogener linearer Gleichungen zu lösen, Ausdrücke, die manchmal Variable ent-halten, auszumultiplizieren, zu vereinfachen und in Faktoren zu zerlegen. Sage ist auch undnicht zuletzt ein System zum symbolischen Rechnen, in der Lage, algebraische Rechnungenauszuführen (Rechnen mit Buchstaben) - und für anspruchsvollere Aufgaben auch auf Po-lynomringen oder Körpern von Quotienten von Polynomen.

In der Analysis1 kennt Sage die gebräuchlichen Funktionen wie Quadratwurzel, Potenz, Lo-garithmus und trigonometrische Funktionen und die damit gebildeten Ausdrücke. Sage leitetab, integriert und berechnet Grenzwerte, vereinfacht Summen, entwickelt Reihen, löst ver-schiedene Typen von Dierentialgleichungen.

Sage führt die in der linearen Algebra auf Vektoren, Matrizen und Vektorräumen üblichenOperationen aus, Sage ermöglicht auch den Umgang mit Wahrscheinlichkeiten, mit Statistikund mit Fragen der Kombinatorik.

So sind die von Sage behandelten Gebiete der Mathematik recht vielfältig, von der Grup-pentheorie bis zur numerischen Analysis. Sage kann die erhaltenen Ergebnisse auch als ebeneoder räumlichelder und als Animationen darstellen.

1In Frankreich ist der Begri Analysis etwas weiter gefasst als in Deutschland, wo nur Dierntial- undIntegralrechnung dazu zählen. In Frankreich gehören auch alle Themen dazu, die Leonhard Euler im erstenBand seiner Introductio in analysin innitorum behandelt hat.

3

Page 20: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

Ziele und Entwicklung von Sage

William Stein, ein Mathematiker aus den USA, Forscher und Hochschullehrer, be-ginnt 2005 mit der Entwicklung von Sage mit dem Ziel, eine Mathematik-Softwarezu schreiben, deren ganzer Code zugänglich und lesbar sein sollte. Das Programmist zunächst auf das Arbeitsgebiet seines Autors zugeschnitten, die Zahlentheorie.Nach und nach formiert sich eine internationale Community von mehreren hundertEntwicklern, die meisten Forscher oder Lehrende. Mit der Zeit erweitert sich dieFunktionalität der Beiträge, um auch andere Gebiete der Mathematik abzudecken,was aus Sage den Software-Generalisten gemacht hat, der es heute ist.

Nicht nur, dass Sage kostenlos herunter geladen und verwendet werden kann, Sageist auch frei. Seine Autoren verzichten auf jede Beschränkung bei der Verteilung,der Installation, ja selbst der Modikation, vorausgestzt, dass die modizierten Ver-sionen ebenfalls frei sind. Wäre Sage ein Buch, könnte das in allen Bibliothekenohne weiteres verliehen oder fotokopiert werden. Diese Erlaubnis harmoniert mitder Verbreitung von Wissen, wie sie durch Forschung und Lehre angestrebt wird.

Die Entwicklung von Sage geht relativ schnell vor sich, denn es bevorzugt die Ein-bindung bereits existierender freier Software. Sage selbst ist in Python geschrieben,einer weithin verwendeten und leicht zu erlernenden Programmiersprache. Dieser Co-de ruft andere bereits existierende Mathematikprogramme auf, die mit Sage geliefertwerden.

Wie fast alle Mathematikprogramme arbeitet auch Sage mit Befehlen, die in einerProgrammiersprache geschrieben sind. Man kann dennoch nicht von einer eigenenSprache Sage reden: es ist Python, das diese Rolle übernimmt, und zwar mit etli-chen syntaktischen Abkürzungen zur Erleichterung der mathematischen Notation.Die vom Anwender eingegebenen Befehle werden durch den Interpreter Python aus-gewertet. Für komplexe oder auch nur sich wiederholende Rechnungen ist es möglich,veritable Programme zu schreiben statt der zeilenweisen Eingabe von Befehlen, undsie sogar, warum nicht, zur Einbindung in Sage vorschlagen.

Abb. 1.1 - Das erste Auftreten des Namens Sage in einem Heft von W. Stein. Ursprünglich war Sage auch

ein Akronym, sobald sich das System aber auf die Gesamtheit der Mathematik erweitert hat, ist allein der

Name Sage geblieben, der im Englischen Salbeia bedeutet.

aEin stilisiertes Bild dieser Heilpanze ziert denn auch den Buchdeckel des französischen Originals.Natürlich kann man sage auch mit weise übersetzen.

4

Page 21: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1. Das Programm Sage

Abb. 1.2 - Ein Arbeitsblatt im Sage-Notebook

Die Verwendung einer und derselben Software zur Behandlung unterschiedlicher Aspekte derMathematik befreit den Mathematiker, welchen Niveaus auch immer, von der Notwendigkeit,Daten zwischen verschiedenen Werkzeugen hin und her zu schieben und vom Erlernen der Syn-tax verschiedener Programmiersprachen. Sage will auf seinen verschiedenen Einsatzgebietenhomogen sein.

1.1.2. Zugang zu Sage

Die im Buch beschriebene Möglichkeit, ein Sage-Notebook auf einem öentlichen Server imInternet einfach durch Aufruf der Seite http.//sagenb.org zu nutzen, existiert seit dem17. April 2015 nicht mehr. Stattdessen wird auf der Seite https://cloud.sagemath.com/ebenfalls kostenlos die viel umfangreichere Sage Cloud angeboten. Deren Benutzung wird hiernicht beschrieben, wir empfehlen stattdessen die Installation von Sage auf Ihrem Rechner, dieim folgenden für Linux-Rechner beschrieben ist. Für andere Betriebssysteme ist das Verfahrenähnlich2, Anleitungen ndet man auf der Sage-Seite.

2Sage ist für die meisten Betriebssysem verfügbar, Linux, Windows, Mac OS X und Solaris.

5

Page 22: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

Abb. 1.3 - Sage von der Konsole

1. Rufen Sie die Seite https://sagemath.org auf und klicken Sie den Download-Buttonan.

2. Wählen Sie einen Lieferanten aus, z.B. die Freie Universität Berlin.

3. Entscheiden Sie sich für eine Rechnerarchitektur, z.B. 64 bit.

4. Laden Sie die für Ihr Betriebssystem passende Sage-Version herunter.

5. Entpacken Sie die heruntergeladene Datei in ein Verzeichnis, z.B. nach ~/bin.

6. Richten Sie für die Dateien, die Sie im weiteren Verlauf erstellen werden, ein Arbeits-verzeichnis ein, z.B. mit mkdir ~/SageWorkSpace.

7. Erstellen Sie in Ihrem persönlichen Verzeichnis eine Textdatei, z.B. mit dem Namensage, die zwei Zeilen enthält:

cd ~/SageWorkSpace~/bin/SageMath/sage

Diese Zeile bewirken erstens den Wechsel in Ihr Arbeitsverzeichnis und zweitens vondort aus den Start von Sage.

6

Page 23: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1. Das Programm Sage

8. Starten Sie nun Sage mit dem Befehl . sage, wobei Sie bitte auf den Punkt und dasfolgende Leerzeichen achten. Sage wird sich nun einrichten und durch den Prompt

sage:

auf der Sage-Konsole seine Bereitschaft anzeigen, Ihre Anweisungen entgegenzunehmen.

Abb. 1.4 - Die Hilfe zu den Notebooks

1.1.3. Quellen

Probieren Sie die Hinweise auf help() und notebook() bitte in aller Ruhe aus. Möglicher-weise gefällt Ihnen die Arbeit mit Sage-Arbeitsblättern (worksheets) besser als mit der Sage-Konsole, doch werden wir im Buch die Notation für die Sage-Konsole verwenden. Eine Ein-weisung in den Umgang mit Sage-Arbeitblättern nden Sie, wenn Sie notebook() aufgerufenhaben und dann den Menupunkt Help anklicken. .

7

Page 24: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

Ob Sie die Sage-Konsole lieber mit weiÿer Schrift auf schwarzem Grund oder mit schwarzerSchrift auf hellem Grund vor sich sehen, ist Geschmackssache3 und einstellbar.

Auf der Seite sagemath.org nden unter dem Button Help/Documentation etliche Links, woSie Informationen zu Sage in verschieden Sprachen - darunter auch in der deutschen - und inverschiedenen Formaten nden können.

1.2. Sage als Taschenrechner

1.2.1. Erste Rechnungen

In diesem Buch stellen wir die Rechnungen mit Sage dar in der Form

sage: 1+12

Die Zeichenkette sage: am Beginn der ersten Zeile ist die Eingabemarke oder der Promptdes Systems. Der Prompt (der in den Arbeitsblättern nicht erscheint), zeigt an, dass Sageeinen Befehl des Anwenders erwartet. Dahinter ist ein Befehl einzugeben, der nach Drückender Taste <Enter> ausgewertet wird. Die folgenden Zeilen enthalten die Antwort des Systems,das ist im allgemeinen das Ergebnis einer Rechnung. Manche Instruktionen erstrecken sichüber mehrere Zeilen (siehe Kapitel 3). Die zusätzlichen Befehlszeilen werden dann durchden Zwischenprompt ....: eingeleitet. Bei der Eingabe eines mehrzeiligen Befehls wirdjede Zeile mit <Enter> abgeschlossen. Auÿerdem muss auf die richtige Einrückung geachtetwerden (Verschiebung der Zeile mit Leerzeichen in Bezug auf die Zeile darüber). Dabei mussder Zwischenprompt am Zeilenanfang stehen bleiben.

In den Arbeitsblättern wird der Befehl direkt in die markierte Rechenzelle eingegeben. DieEingabe wird nach Anklicken von Evaluate unter der Zelle oder nach Eingabe der Tasten-kombination <Shift><Enter> ausgewertet. Die Tastenkombination <Alt><Enter> erzeugt ei-ne neue Zelle unter der aktuellen und bewirkt auÿerdem deren Auswertung Durch Anklickendes Symbols + oberhalb oder unterhalb der aktuellen Zelle kann ebenfalls eine neue Zellegeönet werden.

Sage interpretiert einfache Formeln wie ein wissenschaftlicher Taschenrechner. Die Operaionen+, ∗ usw. haben die übliche Priorität und Klammern die gewohnte Funktion.

3Über Geschmack lässt sich bekanntlich nicht streiten - schon deshalb nicht, weil es nur einen einzigenrichtigen gibt, nämlich meinen.

8

Page 25: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2. Sage als Taschenrechner

Arithmetische Operationendie vier Grundrechenarten a+b, a-b, a*b, a/b

Potenz a^b oder a**bQuadratwurzel sqrt(a)

n-te Wurzel a^(1/n)

Operationen auf ganzen ZahlenGanzzahldivision a // b

Rest, modulo a % bFakultät n! factorial(n)

Binomialkoezient(nk

)binomial(n,k)

Gebrauchliche Funktionen auf R und Cganzzahliger Anteil floor(a)Absolutwert, Modul abs(a)

elementare Funktionen sin, cos, ... (siehe Tabelle 2.2)

Tab. 1.1 - Einige gebräuchliche Funktionen

sage: (1 + 2*(3 + 5))*234

Hier steht das Zeichen ∗ für die Multiplikation und darf nicht weggelassen werden, auch nichtin Ausdrücken wie 2x. Die Potenz wird mit ^ oder mit ∗∗ notiert:

sage: 2^38sage: 2**38

und die Division mit /

sage: 20/610/3

Wir sehen, dass eine exakte Rechnung erfolgt. Das Resultat der Division ist nach der Verein-fachung die rationale Zahl 10/3 und nicht ein Näherungswert wie z.B. 3.33333. Für die Gröÿeeiner ganzen oder einer rationalen Zahl gibt es keine Grenze4:

sage: 2^101024sage: 2^1001267650600228229401496703205376sage: 2^10001071508607186267320948425049060001810561404811705533607443750\3883703510511249361224931983788156958581275946729175531468251\8714528569231404359845775746985748039345677748242309854210746\0506237114187795418215304647498358194126739876755916554394607\7062914571196477686542167660429831652624386837205668069376

4Auÿer der, die mit dem Speicher des Rechners gesetzt ist.

9

Page 26: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

Um eine numerische Näherung zu erhalten, genügt es, eine der Zahlen mit Dezimalpunkt zuschreiben (man kann statt 20.0 auch 20. oder 20.000 sagen).

sage: 20.0/141.42857142857143

Auÿerdem verarbeitet die Funktion numerical_approx das Ergebenis einer exakten Rechnungund macht daraus eine numerische Näherung.

sage: numerical_approx(20/14)1.42857142857143

Es ist möglich, Näherungen mit beliebig groÿer Genauigkeit zu berechnen Vergröÿern wir siebeispielsweise auf 60 Ziern, um die Periode der Dezimalentwicklung einer rationalen Zahl zuerkennen:

sage: numerical_approx(20/14, digits=60)1.42857142857142857142857142857142857142857142857142857142857

Wir kehren zu den Unterschieden zwischen exakter und numerischer Rechnung im Kasten aufSeite 12 zurück.

Die Operatoren // und % ergeben den Quotienten und den Rest der Division zweier ganzerZahlen.

sage: 20 // 63sage: 20 % 62

Es gibt noch viele andere Funktionen auf ganzen Zahlen, von denen wir hier nur die Fakultätoder den Binomialkoezienten erwähnen wollen (siehe Tabelle 1.1).

sage: factorial(100)93326215443944152681699238856266700490715968264381621\46859296389521759999322991560894146397615651828625369\7920827223758251185210916864000000000000000000000000

Hier nun noch eine Möglichkeit der Zerlegung einer ganzen Zahl in Primfaktoren. In Kapitel5 greifen wir dieses Problem wieder auf und dann noch einmal in Kapitel 6.

sage: factor(2^(2^5)+1)641 * 6700417

Fermat hatte vermutet, dass alle Zahlen der Form 22n+1 Primzahlen wären. Das obige Beispielist das kleinste, das Fermats Vermutung widerlegt.

10

Page 27: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2. Sage als Taschenrechner

1.2.2. Elementare Funktionen und Konstanten

Man ndet die gebräuchlichen Funktionen und Konstanten, die auch mit komplexen Zahlenverwendet werden können, in den Tabellen 1.1 und 1.2. Auch da sind die Rechnungen exakt:

Wichtige WerteWahrheitswerte wahr und falsch True, False

imaginäre Einheit I oder iunendlich ∞ infinity oder oo

Gebräuchliche KonstantenKreiszahl π pi

Eulersche Zahl e = exp(1) eEuler-Mascheroni-Konstante γ euler_gamma

Goldener Schnitt ϕ = (1 +√

5)/2 golden_ratioCatalansche Konstante catalan

Tabelle 1.2 - Vordenierte Konstanten

sage: sin(pi)0sage: tan(pi/3)sqrt(3)sage: arctan(1)1/4*piA sage: exp(2*I*pi)1

bzw. endet mit Rückgabe einer Formel statt eines Zahlenwertes:

sage: arccos(sin(pi/3))arccos(1/2*sqrt(3))sage: sqrt(2)sqrt(2)|sage: exp(I*pi/6)e^(1/6*I*pi)

Die Formeln, die man so erhält, sind nicht immer das, was man erwartet hat. Tatsächlicherfolgen nur wenige Vereinfachungen automatisch. Erscheint ein Resultat zu komplex, kannman versuchen, zur Vereinfachung explizit eine Funktion aufzurufen:

sage: simplify(arccos(sin(pi/e)))1/6*pisage: simplify(exp(i*pi/6))1/2*sqrt(3) +,1/2*I

In Abschnitt 2.1 werden wir sehen, wie man die Vereinfachung von Ausdrücken noch bessersteuern kann. Natürlich kann man auch numerische Näherungen der Ergebnisse berechnen(am häugsten mit einer Genauigkeit, die man vorschreibt):

sage: numerical_approx(6*arccos(sin(pi/3)), digits=60)3.14159265358979323846264338327950288419716939937510582097494

11

Page 28: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

sage: numerical_approx(sqrt(2), digits=60)1.41421356237309504880168872420969807856967187537694807317668

Symbolisches Rechnen und numerische Methoden

Ein Computer-Algebra-System (CAS) zum symbolischen Rechnen ist eine Software,deren Zweck die Bearbeitung, die Vereinfachung und die Berechnung mathemati-scher Formeln einzig durch exakte Umformungen ist. Der Terminus symbolisch stehthier als Gegensatz zu numerisch. Er besagt, dass die Rechnungen auf symbolischenAusdrücken stattnden und zwar algebraisch. Im Englischen sagt man computer

algebra oder symbolic computation.Die Taschenrechner verarbeiten ganze Zahlen mit weniger als einem Dutzend Stellenexakt, gröÿere Zahlen werden gerundet, was zu Fehlern führt. So wertet ein Taschen-rechner den folgenden Ausdruck falsch aus und liefert 0 anstatt 1:

(1 + 1050)1050

Solche Fehler sind schwer zu nden, wenn sie durch keine theoretische Untersuchungvorhergesehen - und auch nicht leicht vorhersehbar - bei einer Zwischenrechnung auf-treten. Die Systeme zum symbolischen Rechnen hingegen verschieben diese Grenzenund führen bei den ganzen Zahlen keine Rundungen durch, damit die Rechnungenin ihrem ganzen Verlauf exakt bleiben: sie beantworten die obige Rechnung mit 1.

Die Verfahren zur numerischen Analysis nähern das Integralπ∫0

cos tdt mit einer vor-

gegebenen Genauigkeit an (Trapezregel, Simpson, Gauÿ) um zum Beispiel ein nume-risches Ergebnis zu erhalten, das mehr oder weniger dicht an 0 liegt (beispielsweise10−10), ohne sagen zu können, dass das Resultat exakt die ganze Zahl 0 ist - oderauch, dass es fast 0 ist aber nicht genau 0.

Ein CAS formt das Integralπ∫0

cos tdt durch eine Manipulation der mathematischen

Symbole in die Formel sinπ − sin 0 um, die dann exakt zu 0 − 0 ausgewertet wird.

Diese Methode beweist deshalbπ∫0

cos tdt = 0.

Dennoch haben auch die nur algebraischen Umformumgen ihre Grenzen. Die meistender von einem CAS verarbeiteten Ausdrücke sind Quotienten von Polynomen undein Ausdruck a/a wird automatisch zu 1 vereinfacht. Solche algebraische Rechnungeignet sich nicht zum Lösen von Gleichungen; in diesem Rahmen hat die Gleichungax = a die Lösung x = a/a, was zu x = 1 vereinfacht wird ohne zu bemerken, dassfür a = 0 jede Zahl x Lösung der Gleichung ist.

1.2.3. Online-Hilfe und automatische Vervollständigung

Interaktiv kann man auf das Referenz-Handbuch zugreifen und jede Funktion, jede Konstanteoder jeden Befehl nachschlagen, indem man dahinter ein Fragezeichen schreibt

sage: sin?

Die Seite der Dokumentation (auf englisch) enthält die Beschreibung der Funktion und An-wendungsbeispiele.

12

Page 29: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2. Sage als Taschenrechner

Die Tabulator-Taste <TAB> nach einem Wortanfang zeigt alle Befehle, die so anfangen: arcgefolgt von <TAB> zeigt die Namen sämtlicher Arkus- und Areafunktionen:

sage: arcarc arccosh arccoth arccsch arcsech arcsinh arctan2arccos arccot arccsc arcsec arcsin arctan arctanh

1.2.4. Python-Variablen

Sobald man das Resultat einer Rechnung speichern möchte, kann man es einer Variablen

zuweisen:

sage: y = 1 + 2

um es später weiterzuverwenden:

sage: y3sage: (2 + y) * y15

Zu beachten ist, dass das Resultat nach einer Zuweisung nicht automatisch ausgegeben wird.Oft werden wir auch die folgende Akürzung verwenden:

sage: y = 1 + 2; y3

Das Semikolon ; trennt mehrere Anweisungen auf einer einzigen Zeile. Die Berechnung desErgebnisses erfolgt vor der Zuweisung. Daher kann man dieselbe Variable weiterverwenden:

sage: y = 3 * y + 1; y10sage: y = 3 * y + 1; y31sage: y = 3 * y + 1; y94

Schlieÿlich speichert Sage die Ergebnisse der letzten drei Rechnungen in den Sondervariablen_, __ und ___:

sage: 1 + 12sage: _ + 13sage: __2

Die Variablen, die wir gerade bearbeitet haben, sind Variablen aus der Programmierung inPython, und wir werden das im Unterabschnitt 3.1.3 noch einmal genauer behandeln. Hierwollen wir nur vermerken, dass es empehlenswert ist, weder Funktionen noch in Sage vorde-nierte Konstanten zu überschreiben. Das würde den internen Ablauf von Sage zwar nichtbeeinträchtigen, doch die nachfolgenden Ergebnisse Ihrer Rechnungen oder Iher Programmekönnten unsicher werden.:

13

Page 30: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Erste Schritte

sage: pi = -I/2sage: exp(2*i*pi)e

Zur Wiederherstellung des Ausgangswertes kann ein Befehl verwendet werden wie: So sind dievon Sage behandelten Gebiete der Mathematik recht vielfältig, von der Gruppentheorie bis zurnumerischen Analysis. Sage kann die erhaltenen Ergebnisse auch als ebene oder räumlichelderund als Animationen darstellen.

sage: from sage.all import pi

1.2.5. Symbolische Variablen

Bis jetzt haben wir nur konstante Ausdrücke wie sin(√

2) verarbeitet. Sage ermöglicht auchund vor allem mit Ausdrücken zu rechnen, die Variablen enthalten wie x + y = z oder auchsin(x) + cos(x). Die symbolischen Variablen des Mathematikers, x, y, z, erscheinen in Sagein verschiedenen Ausdrücken, Variablen des Programmierers, denen wir schon im vorigenAbschnitt begegnet sind. Sage unterscheidet sich insbesondere in diesem Punkt von anderenCAS wie Maple oder Maxima.

Die symbolischen Variablen müssen vor ihrer Verwendung explizit deklariert werden5:

sage: z = SR.var('z')sage: 2*z + 32*z + 36

In diesem Beispiel konstruiert der Befehl var('z') eine symbolische Variable mit dem Na-men z. Diese symbolische Variable ist ein Sage-Objekt wie andere auch: sie wird nicht andersbehandelt als komplexere Ausdrücke wie sin(x)+1. Dann wird diese symbolische Variable derVariablen z des Programmiers zugeordnet, was ermöglicht, sich ihrer zur Bildung beliebigkomplexer Ausdrücke zu bedienen.

Wir hätten z auch einer anderen Variablen als z zuordnen können:

sage: y = SR.var('z')sage: 2*y + 32*z + 3

Die systematische Bindung der symbolischen Variablen z an die Variable z ist daher keinebloÿe Konvention, sondern sie wird zur Vermeidung von Verwirrung empfohlen.

Andererseits hat die Variable z mit der symbolischen Variablen z nichts zu tun:

sage: c = 2*y + 3sage: z = 1sage: 2*y + 32*z + 3sage: c2*z + 3

5Tatsächlich ist die symbolische Variable x in Sage vordeniert - das ist aber auch die einzige.6SR steht für Symbolic Ring, siehe dazu auch Kapitel 5.

14

Page 31: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2. Sage als Taschenrechner

Wie weist man einer symbolischen Variablen nun aber einen Wert zu, der in einem Ausdruckerscheint? Man substituiert, wie in

sage: x = SR.var('x')sage: expr = sin(x); exprsin(x)sage: expr(x=1)sin(1)

Ausführlich wird die Substitution in symbolischen Ausdrücken in Kapitel 2 behandelt.

Übung 1. Erläutern Sie Schritt für Schritt, was bei dieser Anweisungsfolge vor sich geht:

u = SR.var('u')u = u+1u = u+1u

Da es ein wenig arbeitsaufwendig ist, auf diese Weise eine groÿe Zahl von symbolischen Va-riablen zu generieren, gibt es eine Kurzform var('x'), die zu x = SR.var('x') äquivalentist. Beispielsweise kann man schreiben

sage: var('a, b, c, x, y')(a, b, c, x, y)sage: a*x + b*y + ca*x + b*y + c

Wird die explizite Variablendeklaration als zu schwerfällig eingeschätzt, kann das Verhaltenvon Maxima oder Maple emuliert werden. Im Moment (Sage 7.6) steht diese Funktionalitätnur im Notebook zur Verfügung. Dort führt nach dem Aufruf von

sage: automatic_names(True)

jeder Gebrauch einer neuen Variablen implizit zur Erzeugung einer symbolischen Variablengleichen Namens und ihre Zuweisung.

sage: 2*bla + 32*bla + 3sage: blabla

1.2.6. Erste Graken

Der Befehl plot ermöglicht auf ganz einfache Weise das Zeichnen des Graphen einer reellenFunktion in einem gegebenen Intervall. Der Befehl plot3d dient zum Zeichnen in drei Dimen-sionen, wie den Graphen einer reellen Funktion von zwei Veränderlichen. Hier die Befehle, mitdenen die Graken in Abb. 1.3 (S. 6) erzeugt wurden:

sage: plot(sin(2*x), x, -pi, pi)sage: plot3d(sin(pi*sqrt(x^2+y^2))/sqrt(x^v2+y^2), (x,-5,5), (y,-5,5))

Die graschen Möglichkeiten von Sage zeigen sich auch an anderen Beispielen. AusführlicheErklärungen folgen im 4. Kapitel.

15

Page 32: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 33: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Dieses Kapitel stellt anhand einfacher Beispiele die Grundfunktionen vor, die in Analysis undAlgebra von Nutzen sind. Schüler und Studenten werden hier Material nden, um Bleistift

und Papier durch Tastatur und Bildschirm zu ersetzen, und damit für das Verstehen vonMathematik vor der gleichen intellektuellen Herausforderung stehen.

Diese Auistung der gebräuchlichsten Befehle für das Rechnen mit Sage will auch für Oberstu-fenschüler zugänglich erscheinen. Mit einem Stern (∗) gekennzeichnet, bilden sie Ergänzungenfür Studenten im ersten Studienjahr. Wegen weiterer Einzelheiten verweisen wir auf die an-deren Kapitel.

2.1. Symbolische Ausdrücke und Vereinfachungen

2.1.1. Symbolische Ausdrücke

Sage ermöglicht alle Arten von Rechnungen zur Analysis mit symbolischen Ausdrücken undZahlen auszuführen, mit symbolischen Variablen, den vier Grundrechenarten und den üblichenFunktionen wie sqrt, exp, log, sin, cos etc. Ein symbolischer Ausdruck kann durch einenBaum dargestellt werden, wie in Abb. 2.1. Es ist wichtig zu verstehen, dass ein symbolischerAusdruck eine Formel ist und kein Wert oder eine mathematische Funktion. So erkennt Sagenicht, dass die folgenden Ausdrücke gleich sind1:

sage: bool(arctan(1+abs(x)) == pi/2 - arctan(1/(1+abs(x))))False

+

^

x 2

3 x

2

x^2 + 3*x + 2

+ +

x 1 x 2

(x + 1)*(x + 2)

Abb. 2.1 - Zwei symbolische Ausdrücke, die dasselbe mathematische Objekt darstellen.

1Der Test auf Gleichheit == ist insofern kein einfacher syntaktischer Vergleich von Formeln: beispielsweisewerden in Sage 7.6 die Ausdrücke arctan(sqrt(2)) und pi/2 - arctan(1/sqrt(2) als gleich betrachtet.Wenn man zwei Ausdrücke mit bool(x==y) vergleicht, versucht Sage zu beweisen, dass ihre Dierenz nullist und gibt True zurück, wenn das gelingt.

17

Page 34: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Dank der in diesem Kapitel vorgestellten Befehle kann der Anwender Ausdrücke umformenund sie in die gewünschte Form bringen.

Die wohl häugste Operation ist das Auswerten eines Ausdrucks, indem einem oder mehrerender darin vorkommenden Parameter ein Wert zugewiesen wird. Das bewirkt die - vielleichtnicht immer ausdrücklich angegebene - Methode subs.

sage: a, x = var('a, x'); y = cos(x+a) * (x+1); y(x + 1)*cos(a + x)sage: y.subs(a=-x); y.subs(x=pi/2, a=pi/3); y.subs(x=0.5, a=2.3)x + 1-1/4*sqrt(3)*(pi + 2)-1.41333351100299sage: y(a=-x); y(x=pi/2, a=pi/3); y(x=0.5, a=2.3)x + 1-1/4*sqrt(3)*(pi + 2)-1.41333351100299

Wie auch in der üblichen Schreibweise x 7→ f(x) muss der Name der ersetzten Variablen an-gegeben werden. Die Substitution mehrerer Variablen geschieht auf analoge Weise, indem alleErsetzungen nacheinander hingeschrieben werden, wie die beiden nächsten Beispiele zeigen:

sage: x, y, z = var('x, y, z') ; q = x*y + y*z + z*xsage: bool(q(x=y, y=z, z=x) == q), bool(q(z=y)(y=x) == 3*x^2)(True, True)

Um einen Unterausdruck zu ersetzen, der komplizierter ist als eine Variable, greift man zurFunktion substitute.

sage: y, z = var('y, z'); f = x^3 + y^2 + zsage: f.substitute(x^3 == y^2, z==1)2*y^2 + 1

2.1.2. Umformung von Ausdrücken

Die einfachsten Ausdrücke mit Variablen sind die Polynome und Quotienten aus zwei Poly-nomen mit einer oder mehreren Variablen. Die Funktionen, die erlauben, sie auf verschiedeneWeise umzuschreiben oder in eine Normalform zu bringen, sind in Tabelle 2.1 aufgeführt. ZumBeispiel dient die Funktion expand dazu, Polynome auszumultiplizieren.

sage: x, y = SR.var('x,y')sage: p = (x+y)*(x+1)^2sage: p2 = p.expand(); p2x^3 + x^2*y + 2*x^2 + 2*x*y + x + y

während die Methode collect die folgenden Terme nach fallenden Potenzen einer gegebenenVariablen umordnet:

sage: p2.collect(x)x^3 + x^2*(y + 2) + x*(2*y + 1) + y

Diese Funktionen werden auch auf Ausdrücke angewendet, die Polynome sind, aber keine mitsymbolischen Variablen sondern mit Unterausdrücken, die komplizierter sind als sin(x):

18

Page 35: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.1. Symbolische Ausdrücke und Vereinfachungen

sage: ((x+y+sin(x))^2.expand().collect(sin(x))2*(x + y)*sin(x) + x^2 + 2*x*y + y^2 + sin(x)^2

Symbolische Funktionen

Sage erlaubt auch die Denition von symbolischen Funktionen zur Verarbeitung einesAusdrucks.sage: f(x) = (2*x + 1)^3; f(-3)-125sage: f.expand()x |--> 8*x^3 + 12*x^2 + 6*x + 1Eine symbolische Funktion ist nichts anderes als ein Ausdruck, den man wie einenBefehl aufrufen kann und bei dem die Reihenfolge der Variablen festgelegt ist. Umeinen symbolischen Ausdruck in eine symbolische Funktion zu verwandeln, benutztman entweder die schon erwähnte Syntax oder die Methode function:sage: y = var('y'); u = sin(x) + x*cos(y)sage: v = u.function(x, y); v(x, y) |--> x*cos(y) + sin(x)sage: w(x, y) = u; w(x, y) |--> x*cos(y) + sin(x)Die symbolischen Funktionen dienen zur Modellierung mathematischer Funktionen.Sie spielen nicht die gleiche Rolle wie die Funktionen (oder Prozeduren) in Python.Das sind Konstruktionen der Programmierung, die wir im 3. Kapitel beschreiben.Der Unterschied zwischen beiden entspricht dem Unterschied zwischen symbolischenVariablen und den in Unterabschnitt 1.2.4 vorgestellten Python-Variablen.Praktisch verwendet man eine symbolische Funktion genauso wie einen Ausdruck,was bei Python-Funktionen nicht der Fall ist, beispielsweise verfügen letztere nichtüber die Methode expand.

Polynom p = zx2 + x2 − (x2 + y2)(ax− 2by) + zy2 + y2

p.expand().collect(x) −ax3 − axy2 + 2byy3 + (2by + z + 1)x2 + y2z + y2

p.collect(x).collect(y) 2bx2y + 2by3 − (ax− z − 1)x2 − (ax− z − 1)y2

p.expand() −ax3 − axy2 + 2bx2y + 2by3 + x2z + y2z + x2 + y2

p.factor() −(x2 + y2)(ax− 2by − 7− 1)p.factor_list [(x2 + y2, 1), (ax− 2by − z − 1, 1), (−1, 1)]

Quotient von Polynomen r =x3 + x2y + 3x2 + 3xy + 2x+ 2y

x3 + 2x2 + xy + 2y

r.simplify_rational()(x+ 1)y + x2 + x

x2 + y

r.factor()(x+ 1)(x+ y)

x2 + y

r.factor().expand()x2

x2 + y+

xy

x2 + y+

x

x2 + y+

y

x2 + y

Quotient von Polynomen r =(x− 1)x

x2 − 7+

y2

x2 − 7+b

a+c

a+

1

x+ 1

r.combine()(x− 1)x+ y2

x2 − 7+b+ c

a+

1

x+ 1

Quotient von Polynomen r =1

(x3 + 1)y2

r.partial_fraction(x) − (x− 2)

3(x2 − x+ 1)y2+

1

3(x+ 1)y3

19

Page 36: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Tab. 2.1 - Polynome und Quotienten von Polynomen2

Was Quotienten von Polynomen angeht, d.h. gebrochen rationale Ausdrücke, so erlaubt dieFunktion combine die Umgruppierung von Termen mit gleichem Nenner, während die Funk-tion partial_fraction die Zerlegung in einfache Elemente in Q bewirkt (Eine genauereBeschreibung dieses Körpers, in dem die Zerlegung in einfache Elemente zu erfolgen hat, wirdman in Abschnitt 7.4 nden.)

Die gebräuchlichsten Darstellungen sind für das Polynom die ausmultiplizierte Form und fürden Quotienten zweier Polynome die gekürzte Form P/Q mit ausmultiplizierten P und Q.Sobald zwei Polynome oder zwei Quotienten von Polynomen in diesen Formen geschriebensind, genügt für die Entscheidung, ob sie gleich sind, der Vergleich ihrer Koezienten: mannennt diese Formen die Normalformen.

2.1.3. Gebräuchliche mathematische Funktionen

In Sage liegen schon die meisten mathematischen Funktionen vor. insbesondere die trigono-metrischen Funktionen, die Logarithmus- und die Exponentialfunktion: In Tab. 2.2 sind siezusammengestellt. Die Vereinfachung dieser Funktionen ist wesentlich. Um einen Aussdruckoder eine symbolische Funktion zu vereinfachen, verfügen wir über die Funktion simplify:

Gebräuchliche mathematische FunktionenExponentialfunktion und Logarithmus exp, log

Logarithmus zur Basis a log(x,a)

trigonometrische Funktionen sin, cos, tan, cot, sec, csc

Arcusfunktionen arcsin, arccos, arctan, arccot

hyperbolische Funktionen sinh, cosh, tanh, coth

Areafunktionen arcsinh, arccosh, arctanh, arccoth

ganzzahliger Anteil usw. floor, ceil, trunc, round

Quadratwurzel und n−te Wurzel sqrt, nth_root

Umformung trigonometricher AusdrückeVereinfachung simplify_trig

Linearisierung reduce_trig

Anti_Linearisierung expand_trig

Tab. 2.2 - Gebräuchliche Funktionen und Vereinfachungen

sage: (x^x/x).simplify()x^(x-1)

Jedoch muss man für feinere Vereinfachungen den Typ der erwarteten Vereinfachung ange-ben:

sage: f = (e^x-1) / (1+e^(x/2)); f.simplify_exp()e^(1/2*x) - 1

Entsprechend nimmt man den Befehl simplify_trig zur Vereinfachung trigonometrischerAusdrücke.

2Die Darstellung der Ausdrücke auf der rechten Seite erhält man in einem Sage-Arbeitsblatt nach Aktivierungvon Typeset.

20

Page 37: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.1. Symbolische Ausdrücke und Vereinfachungen

sage: f = cos(x)^6 + sin(x)^6 + 3*sin(x)^2*cos(x)^2sage: f.simplify_trig()1

Zur Linearisierung (bzw. Anti-Linearisierung) eines trigonometrischen Ausdrucks verwendetman reduce_trig (bzw. expand_trig):

sage: f = cos(x)^6; f.reduce_trig()1/32*cos(6*x) + 3/16*cos(4*x) + 15/32*cos(2*x) + 5/16sage: f = sin(6*x): f.expand_trig()6*cos(x)^5*sin(x) - 20*cos(x)^3*sin(x)^3 + 6*cos(x)*sin(x)^5

Man kann Ausdrücke mit Fakultäten ebenfalls vereinfachen:

sage: n = var('n'); f = factorial(n+1)/factoral(n)n+1

Was die Funktion simplify_rational angeht, so versucht sie, einen Quotienten von Poly-nomen dadurch zu vereinfachen, dass sie seine Glieder ausmultipliziert. Für die Vereinfa-chung von Quadratwurzeln, logarithmischen oder exponentiellen Ausdrücken steht die Funk-tion canonicalize_radical zur Verfügung.

sage: f = sqrt(abs(x)^2); f.canonicalize_radical()xsage: y = var('y')sage: f = log(x*y); f.canonicalize_radical()log(x) + log(y)

Der Befehl simplify_full wendet die Funktionen simplify_factorial, simplify_ trigund simplify_rational an (in dieser Reihenfolge).

Alles, was zur klassischen Palette einer Kurvendiskussion gehört (Berechnung von Ableitun-gen, Asymptoten, Extrema, Nullstellen und Skizze des Graphen), kann mit einem CAS leichtrealisiert werden. Sages wichtigste Operationen die man auf Funktionen anwenden kann, wer-den in Abschnitt 2.3 vorgestellt.

2.1.4. Vorgaben für eine symbolische Variable

Bei der Rechnung mit symbolischen Variablen wird im allgemeinen angenommen, dass siejeden Wert einer reellen oder komplexen Zahl annehmen können. Das führt zu Problemen,wenn ein Parameter eine auf ihren Denitionsbereich beschränkte Gröÿe darstellt (beispiels-weise positiv reell).

Ein typischer Fall ist der Ausdruck√x2. Zur Vereinfachung solcher Ausdrücke bietet die

Funktion assume, mit der die Eigenschaften einer Variablen päzisiert werden können, einegute Lösung. Möchte man diese Vorgabe wieder aufheben, kommt der Befehl forget zumEinsatz:

sage: assume(x>0); bool(sqrt(x^2) == x)Truesage: forget(x>0); bool(sqrt(x^2) == x)False

21

Page 38: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

sage: n = var('n'); assume(n, 'integer'); sage: sin(n*p).simplify()0

2.1.5. Mögliche Gefahren

Sei c ein ganz klein wenig komplizierter Ausdruck:

sage: a = var('a')sage: c = (1+a)^2 - (a^2+2*ab+1)

und versuchen wir, die in x gegebene Gleichung cx = 0 nach x aufzulösen:

Das Problem der Vereinfachung

Die Beispiele in Unterabschnitt 2.5.1 illustrieren die Wichtigkeit der Normalformenund spziell des Tests auf 0, ohne den jede Rechnung, die eine Division enthält, zumGlücksspiel wird.Bestimmte Familien von Ausdrücken, die aussehen wie Polynome, lassen eine Pro-zedur zu, die entscheidet, ob der Nenner 0 ist. Das heiÿt, dass für diese Klassenvon Ausdrücken ein Programm entscheiden kann, ob ein gegebener Ausdruck nullist oder nicht. In vielen Fällen wird diese Entscheidung durch Reduktion auf dieNormalform getroen: der Ausdruck ist null dann und nur dann, wenn wenn seineNormalform 0 ist.Unglücklicherweise können nicht alle Klassen von Ausdrücken eine Normalform bil-den, und für einige Klassen kann man zeigen, dass es keine allgemeine Methode gibt,die in endlicher Zeit feststellt, ob ein Ausdruck null ist. Ein Beispiel einer solchenKlasse ist ein Ausdruck, der aus rationalen Zahlen, π, ln 2 und einer Variablen zu-sammengesetzt ist mit wiederholter Addition, Subraktion, Multiplikation, Exponen-tiation und der Sinusfunktion. Eine wiederholte Anwendung von numerical_approxmit erhöhter Genauigkeit erlaubt häug eine Vermutung, ob ein spezieller Ausdrucknull ist oder nicht; doch es ist bewiesen, dass es nicht möglich ist, ein Programmzu schreiben, das als Argument einen Ausdruck dieser Klasse erhält und das wahreErgebnis zurückgibt, wenn das Argment null ist und andernfalls ein falsches.Bei diesen Klassen stellt sich also das Problem der Vereinfachung mit gröÿter Schär-fe. Ohne Normalform können die Systeme nur eine bestimmte Zahl von Umformun-gen angeben, mit denen der Anwender jonglieren muss, um zu einem Ergebnis zukommen. Um hier klarer zu sehen, muss man die Unterklassen der Ausdrücke iden-tizieren, die Normalformen haben und wissen, welche Funktionen aufzurufen sind,um letztere zu berechnen. Sages Verhalten gegenüber diesen Schwierigkeiten wird inKapitel 5 ausführlicher behandelt.

sage: eq = c*x == 0x == 0

Ein unvorsichtiger Anwender wird versucht sein, diese Gleichung zu vereinfachen, bevor er sielöst:

sage: eq2 = eq/c; eq2x == 0

22

Page 39: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2. Gleichungen

sage: solve(eq2, x)[x == 0]

Glücklicherweise macht Sage diesen Fehler nicht:

sage: solve(eq, x)[x == x]

Hier konnte Sage die Aufgabe korrekt lösen, denn der Koezient c ist ein polynomialer Aus-druck. Daher kann c leicht auf 0 getestet werden. Es reicht hin, c auszumultiplizieren:

sage: expand(c)0

und davon Gebrauch zu machen, dass zwei Polynome mit gleicher ausmultiplizierter Formgleich sind, anders gesagt, dass die ausmultiplierte Form eine Normalform ist.

Im Gegenzug begeht Sage bei einem kaum komplizierteren Ausdruck einen Fehler:

sage: c = cos(a)^2 + sin(a)^2 - 1sage: eq = c*x == 0sage: solve(eq, x)[x == 0]

und das, obwohl die Vereinfachung und der Test auf 0 korrekt sind:

sage: c.simplify_trig()0sage: c.is_zeroTrue

2.2. Gleichungen

Wir wenden uns jetzt den Gleichungen zu und ihrer Lösung; die wichtigsten Funktionen dazusind in Tab. 2.3 zusammengestellt.

Numerische Gleichungensymbolische Lösung solve

Lösunmg (mit Mehrfachwurzeln) roots

numerische Lösung find_root

Vektorgleichungen und FunktionsgleichungenLösung linearer Gleichungen right_solve, left_solve

Lösung von Dierentialgleichungen desolve

Lösung von Rekursionen rsolve

Tab. 2.3 - Lösung von Gleichungen

23

Page 40: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

2.2.1. Explizite Lösung

Wie betrachten folgende Gleichung mit der Unbekannten z und dem Parameter ϕ:

z2 − 2

cosϕz +

5

cos2 ϕ− 4 = 0, mit ϕ ∈

]−π

2,π

2

[.

Wir schreiben

sage: z, phi = var('z, phi')sage: eq = z**2 - 2/cos(phi)*z + 5/cos(phi)**2 - 4 == 0; eqz^2 - 2*z/cos(phi) + 5/cos(phi)^2 - 4 == 0

Mit der Methode lhs (bzw. mit der Methode rhs) kann man die linke Seite der Gleichung(bzw. die rechte) isolieren:

sage: eq.lhs()z**2 - 2/cos(phi)*z + 5/cos(phi)**2 - 4sage: eq.rhs()0

was jedoch nicht erforderlich ist, um sie mit solve zu lösen. In einem Sage-Arbeitsblatt siehtdas so aus:

solve(eq,z) z = −2√

cos (ϕ)2 − 1− 1

cos (ϕ), z =

2√

cos (ϕ)2 − 1 + 1

cos (ϕ)

Sei nun die Gleichung y7 = y zu lösen.

sage: y = var('y'); solve(y^7==y, y)[y == 1/2*I*sqrt(3) + 1/2, y == 1/2*I*sqrt(3) - 1/2, y == -1, y ==-1/2*I*sqrt(3) - 1/2, y == -1/2*I*sqrt(3) + 1/2, y == 1, y == 0]

Die Lösungen können auch in Gestalt eines Objekts vom Typ Diktionär3 zurückgegeben wer-den (siehe Unterabschnitt 3.3.9).

sage: solve(x^2-1, x, solution_dict=True)[x: -1, x: 1]

Der Befehl solve erlaubt ebenfalls das Lösen von Gleichungssystemen:

sage: solve(x+y == 3, 2*x+2*y == 6], x, y)[[x == -r1 + 3, y == r1]]

Bei unbestimmten Systemen wie diesem übernehmen Hilfsvariablen, die mit r1, r2 usw.bezeichnet werden, die Parametrisierung der Lösungsmenge. Kommen als Parameter nur ganzeZahlen in Betracht, werden sie mit z1, z2 usw. angegeben ((hierunter ist es z38, was je nachSage-Version auch anders sein kann).

sage: solve([cos(x)*sin(x) == 1/2, x+y == 0], x, y)[[x == 1/4*pi + pi*z38, y == -1/4*pi - pi*z38]]

3engl. dictionary

24

Page 41: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2. Gleichungen

Schlieÿlich kann man mit der Funktion solve sogar Ungleichungen lösen:

sage: solve(x^2+x-1 > 0, x)[[x < -1/2*sqrt(5) - 1/2], [x > 1/2*sqrt(5) - 1/2]]

Es kommt vor, dass von solve die Lösungen eines Gleichungssystems als Flieÿkommazahlenzurückgegeben werden. Sei beispielsweise das folgende Gleichungssystem im C2 zu lösen:

x2yz = 18,xy3z = 24,xyz3 = 3.

sage: x, y, z = var('x, y, z')sage: solve([x^2*y*z == 18, x*y^3*z == 24,\....: x*y*z^4 == 3], x, y, z)[[x = (-2.76736473308 - 1.71347969911*I), y = (-0.570103503963 +

2.00370597877*I), z = (-0.801684337646 - 0.14986077496*I)],...]

Sage gibt hier 17 angenäherte komplexe Lösungstripel zurück. Wegen symbolischer Lösungenbefrage man das 9. Kapitel.

Um die numerische Lösung einer Gleichung zu erhalten, verwendet man die Funktion find_root,die als Argument eine Funktion einer Veränderlichen oder eine symbolische Gleichung sowiedie Grenzen des Intervalls aufnimmt, in welchem die Lösung gesucht werden soll.

sage: expr = sin(x) + sin(2*x) + sin(3*x)sage: solve(expr, x)[sin(3*x) == -sin(2*x) - sin(x)]

Zu dieser Gleichung ndet Sage keine symbolische Lösung. Nun gibt es zwei Möglichkeiten:entweder greift man zu einer numerischen Lösung

sage: find_root(expr,0.1,pi)2.0943951023931957

oder man formt den Ausdruck vorher um:

sage: f = f = expr.simplify_trig(); f2*(cos(x)^2 + cos(x))*sin(x)sage: solve(f, x)[x == 0, x == 2/3*pi, x == 1/2*pi]

Schlieÿlich kann man mit der Funktion roots die exakten Lösungen samt deren Vielfachheitbekommen. Man kann überdies den Ring angeben, in welchem man die Lösung zu erhaltenwünscht; wählt man RR für R oder CC für C, erhält man die Ergebnisse als Flieÿkomma-zahlen. Das untenstehende Lösungsverfahren ist für die betrachtete Gleichung spezisch, imGegensatz zu find_root, das eine generische Methode verwendet.

Betrachten wir die Gleichung dritten Grades x3 + 2x + 1 = 0. Diese Gleichung hat einenegative Diskriminante und besitzt somit eine reelle Wurzel und zwei komplexe, die man mitder Funktion roots erhalten kann (dargestellt im Sage-Arbeitsblatt):

25

Page 42: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

(x^3+2*x+1).roots(x)[−1

2

(1

18

√59√

3− 1

2

) 13 (i√

3 + 1)− i

√3− 1

3(

118

√59√

3− 12

) 13

, 1

,

−1

2

(1

18

√59√

3− 1

2

) 13 (−i√

3 + 1)− −i

√3− 1

3(

118

√59√

3− 12

) 13

, 1

,

( 1

18

√59√

3− 1

2

) 13

− 2

3(

118

√59√

3− 12

) 13

, 1

]

sage: (x^3+2*x+1).roots(x, ring=RR)[(-0.453397651516404, 1)]sage: (x^3+2*x+1).roots(x, ring=CC)[(-0.453397651516404, 1),(0.226698825758202 - 1.46771150871022*I, 1),(0.226698825758202 + 1.46771150871022*I, 1)]

2.2.2. Gleichungen ohne explizite Lösung

Sobald das Gleichungssystem zu kompliziert wird, ist es in den wenigsten Fällen möglich, eineexakte Lösung zu berechnen.

sage: solve(x^(1/x)==(1/x)^x, x)[(1/x)^x == x^(1/x)]

Andererseits ist das nicht zwangsläug eine Beschränkung, wie man meinen könnte. Tatsäch-lich ist ein Leitmotiv des symbolischen Rechnens, dass man durch Gleichungen denierteObjekte sehr wohl umformen und insbesonerere ihre Eigenschaften berechnen kann, ohne ihreexplizite Lösung zu kennen. Noch besser, die Gleichung, die ein Objekt deniert, ist oft diebeste Beschreibung dieses Objekts. So ist eine Funktion, die durch eine lineare Dierential-gleichung und Anfangsbedingungen deniert ist, vollkommen bestimmt. Die Lösungsmengevon linearen Dierentialgleichungen ist (unter anderem) hinsichtlich Summe und Produkt ab-geschlossen und bildet so eine wichtige Klasse, wo man den Test auf 0 einfach vornehmenkann. Dafür fällt die Lösung, ist sie ihrer Denitionsgleichung beraubt, in eine gröÿere Klasse,wo nur wenig entschieden werden kann:

sage: y = function('y', x)sage: desolve(diff(y,x,x) + x*diff(y,x) + y == 0, y, [0,0,1])-1/2*I*sqrt(2)*sqrt(pi)*erf(1/2*I*sqrt(2)*x)*e^(-1/2*x^2)

Im 14. Kapitel und im Unterabschnitt 15.1.2 greifen wir diese Überlegungen wieder auf.

2.3. Analysis

In diesem Abschnitt stellen wir die in der reellen Analysis laufend gebrauchten Funktionenkurz vor. Wegen weiter fortgeschrittener Anwendungen oder Ergänzungen verweisen wir aufspätere Kapitel, namentlich jene, die die numerische Integration (Kapitel 14), die Lösungnichtlinearer Gleichungen (Kapitel 12) und Dierentialgleichungen (Kapitel 10) behandeln.

26

Page 43: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3. Analysis

2.3.1. Summen

Zur Berechnung symbolischer Summen verwendet man die Funktion sum. Berechnen wir bei-spielsweise die Summe der ersten n natürlichen Zahlen:

sage: k, n = var('k, n')sage: sum(k,k,1,n).factor()1/2*(n + 1)*n

Die Funktion sum erlaubt die Vereinfachung des binomischen Lehrsatzes:

sage: n, k, y = var('n, k, y') # das symbolische x ist voreingestelltsage: sum(binomial(n,k) * x^k * y^(n-k), k, 0, n)(x + y)^n

Hier nun weitere Beispiele, darunter die Summe der Zahl der Elemente einer Teilmenge mitn Elementen:

sage: k, n = var('k, n')sage: sum(binomial(n,k), k, 0, n),\....: sum(k * binomial(n, k), k, 0, n),\....: sum((-1)\^k*binomial(n,k), k, 0, n)(2^n, 2^(n - 1)*n, 0)

Schlieÿlich noch Beispiele für geometrische Summen:

sage: a, q, k, n = var('a, q, k, n')sage: sum(a*q^k, k, 0, n)(a*q^(n + 1) - a)/(q - 1)

Um die entsprechende Reihe zu berechnen, muss präzisiert werden, dass der Quotient q absolutkleiner als 1 ist:

sage: assume(abs(q) < 1)sage: sum(a*q^k, k, 0, infinity)-a/(q - 1)

sage: forget(); assume(q > 1); sum(a*q^k, k, 0, infinity)Traceback (most recent call last):...ValueError: Sum is divergent.

Übung 2 (Rekursive Berechnung der Summe). Zu berechnen ist die Summe der p-ten Poten-zen der ganzen Zahlen von 0 bis n für p = 1, . . . , 4, ohne den Sage-Algorithmus zu verwen-den:

Sn(p) =

n∑k=0

kp.

Zur Berechnung diese Summe kann man folgende Rekursionsgleichung verwenden:

Sn(p) =1

p+ 1

(n+ 1)p+1 −p−1∑j=0

(p− 1

j

)Sn(j)

.

27

Page 44: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Diese Rekursionsformel erweist sich bei der Berechnung der Teleskopsumme∑0≤k≤n

(k + 1)p+1 − kp+1,

als hilfreich, die auf zweierlei Art erfolgen kann.

2.3.2. Grenzwerte

Zur Berechnung eines Grenzwertes verwendet man den Befehl limit oder seinen Alias lim.Zu berechen sind die folgenden Grenzwerte:

(a) limx→8

3√x− 2

3√x+ 19− 3

;

(b) limx→π

4

cos(π4 − x)− tanx

1− sin(π4 + x).

sage: limit((x**(1/3) - 2)/((x+19)**(1/3) - 3), x = 8)9/4sage: f(x) = (cos(pi/4-x)-tan(x))/(1-sin(pi/4+x))sage: limit(f(x), x = pi/4)Infinity

Die letzte Antwort zeigt an, dass einer der Grenzwerte, der rechte oder der linke, unendlich4

ist. Um das Resultat zu präzisieren, untersucht man mit Hilfe der Option dir die Grenzwertevon links (minus) und von rechts (plus):

sage: limit(f(x), x = pi/4, dir='minus')+Infinitysage: limit(f(x), x = pi/4, dir='plus')-Infinity

2.3.3. Folgen

Die bis jetzt behandelten Funktionen erlauben die Untersuchung von Folgen. Als Beispielvergleichen wir das Wachstum einer exponentiellen Folge und einer geometrischen.

Beispiel. Untersuchung einer Folge Wir betrachten die Folge un =n100

100n. Zu berechnen sind

die ersten zehn Terme der Folge. Welche Monotonie weist die Folge auf? Welches ist derGrenzwert der Folge. Für welche n ist un ∈]0, 10−8[?

1. Um den Term der Folge un zu denieren, verwenden wir eine symbolische Funktion. Wirführen die Berchnung der ersten 10 Terme von Hand aus (und warten mit den Schleifenbis zum 3. Kapitel):

sage: u(n) = n^100/100^nsage: u(2.); u(3.); u(4.); u(4.); u(6.); u(7.); u(8.); u(9.); u(10.)

4Statt von einem unendlichen Grenzwert zu sprechen (oft wird auch uneigentlicher Grenzwert gesagt), ist esauch möglich zu sagen, dass ein Grenzwert nicht existiert oder dass ein Wert über alle Grenzen wächst.Schlieÿlich ist ∞ weder Zahl noch Wert, sondern bezeichnet eine Eigenschaft.

28

Page 45: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3. Analysis

1.26765060022823e265.15377520732011e411.60693804425899e521.60693804425899e526.53318623500071e653.23447650962476e702.03703597633449e742.65613988875875e771.00000000000000e80

Daraus könnte man übereilt folgern, dass un gegen unendlich strebt.

Abb. 2.2 - Graph von x 7→ x100/100x

2. Um eine Vorstellung von der Monotonie zu haben, kann man die Funktion zeichnen, mitder wir die Folge un deniert haben (siehe Abb. 2.2).

plot(u(x), x, 1, 40)

Wir vermuten, dass die Folge ab n = 22 abnehmen wird.

sage: v(x) = diff(u(x), x); sol = solve(v(x) == 0, x); sol[x = 100/log(100), x = 0]sage: floor(sol[0].rhs()))21

Die Folge wächst also bis n = 21, um ab n = 22 wieder abzunehmen.

3. Wir berechnen nun den Grenzwert.

sage: limit(u(n), n=infinity)0sage: n0 = find_root(u(n) - 1e-8 == 0, 22, 1000); n0105.07496210187252

29

Page 46: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Die ab n = 22 abnehmende Folge verläuft ab n = 106 im Intervall ]0, 10−8[.

2.3.4. Taylor-Reihenentwicklung (*)

Zur Berechnung einer Taylor-Reihe der Ordnung n an der Stelle x0 verfügt man über dieMethode f(x).series(x==x0, n). Interessiert man sich nur für den regulären Teil der Rei-henentwicklung der Ordnung n, kann man die Funktion taylor(f(x), x, x0, n) verwenden.Bestimmen wir die Reihenentwicklungen folgender Funktionen im Sage-Arbeitsblatt:

a) (1 + arctanx)1x der Ordnung 3 um x0 = 0,

b) ln(2 sinx) der Ordnung 3 um x0 =π

6.

taylor((arctan(x))**(1/x), x, 0, 3)

1

810

(112x3 + 45x2 − 270x+ 810

)e

log(x)x

(ln(2*sin(x)).series(x==pi/6, 3))

(√

3)(−1

6π + x) + (−2)(−1

6π + x)

2

+O(− 1

216(π − 6x)3

)Hat man die Taylor-Reihe mittels series erhalten und möchte den regulären Teil allein haben,verwendet man die Methode truncate:

(ln(2*sin(x)).series(x==pi/6, 3)).truncate()

− 1

18(π − 6x)2 − 1

6

√3(π − 6x)

Mit dem Befehl taylor ist es auch möglich, asymptotische Entwicklungen zu erhalten. Umbespielsweise den Wert der Funktion (x3 +x)

13 − (x3−x)

13 für x→∞ zu berechnen, schreibt

man:

sage: taylor((x^3+x)^(1/3)-(x^3-x)^(1/3), x, infinity, 2)2/3/x

Übung 3 (Eine symbolische Grenzwertberechnung). Sei f aus der Klasse C2 in der Umgebungvon a ∈ R gegeben. Zu berechnen ist

limh→0

1

h3(f(a+ 3h)− 3f(a+ 2h) + 3(a+ h)− f(a).

Verallgemeinerung?

Beispiel (*) (Die Formel von Machin). Zu beweisen ist folgende Gleichung:

π

4= 4 arctan

1

5− arctan

1

239.

Mit Hilfe dieser Formel und der arctan-Entwicklung als Potenzreihe hat der Astronom JohnMachin (1680-1752) im Jahre 1706 π auf 100 Dezimalstellen berechnet. Mit seinem Verfahrenist ein Näherungswert für π herzuleiten.

30

Page 47: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3. Analysis

Funktionen und OperatorenAbleitung diff(f(x), x)

n-te Ableitung diff(f(x), x, n)

Integration integrate(f(x), x)

numerische Integration integral_numerical((f(x), a, b)

symbolische Summe sum(f(i), i, imin, imax)

Grenzwert limit(f(x), x==a)

Taylorpolynom taylor(f(x), x, a, n)

Taylor-Reihenentwicklung f.series(x==a, n)

Graph einer Funktion plot(f(x), x, a, b)

Tab. 2.4 - Zusammenstellung von in der Analysis hilfreichen Funktionen

Zunächst überzeugt man sich, dass 4 arctan 15 und π

4 + arctan 1239 den gleichen Tangenswert

haben.

sage: tan(4*arctan(1/5)).simplify_trig()120/119sage: tan(pi/4+arctan(1/239)).simplify_trig()120/119

Nun liegen die reellen Zahlen 4 arctan 15 und π

4 +arctan 1239 beide im oenen Intervall ]0, π[, sie

sind also gleich. Um einen Näherungswert für π zu erhalten, kann man wie folgt verfahren:

sage: f = arctan(x).series(x, 10); f1*x + (-1/3)*x^3 + 1/5*x^5 + (-1/7)*x^7 + 1/9*x^9 + Order(x^10)sage: (16*f.substitute(x==1/5) - 4*f.substitute(x==1/239)).n(); pi.n()3.141592682404403.14159265358979

Übung 4 (Eine Formel von Gauÿ). Die folgende Formel erfordert in der Ausgabe von Gauÿ'Werken (Werke, ed. Königl. Ges. d. Wiss. Göttingen, vol 2, p. 477-502) immerhin 20 SeitenTabellenrechnung:

π

4= 12 arctan

1

38+ 20 arctan

1

57+ 7 arctan

1

239+ 24 arctan

1

268.

1. Man setze θ = 12 arctan 138 + 20 arctan 1

57 + 7 arctan 1239 + 24 arctan 1

268 .Bestätigung mit Sage, dass tan θ = 1.

2. Zu beweisen ist die Ungleichung ∀x ∈[0, π4

], tanx ≤ π

4x durch Herleitung der Formelvon Gauÿ.

3. Durch Approximation der arctan-Funktion vermittels des Taylor-Polynoms der Ord-nung 21 an der Stelle 0 ist eine neuer Näherungswert für π anzugeben.

2.3.5. Reihen (*)

Die vorstehenden Befehle können auch auf Reihen angewendet werden. Wir geben einigeBeispiele:

Beispiel (Berechnung der Summe der Riemann-Reihe).

k = var('k')sum(1/k^2, k, 1, infty),\

31

Page 48: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

sum(1/k^4, k, 1, infty),\sum(1/k^5, k, 1, infty)(1

6π2, 1

90π4, ζ(5))

Beispiel (Eine Formel von Ramanujan). Mit der Partialsumme der ersten 12 Terme derfolgenden Summe geben wir eine Näherung für π und vergleichen sie mit dem von Sage für πgefundenen Wert.

1

π=

2√

2

9801

+∞∑k=0

(4k)! · (1103 + 26390k)

(k!)4 · 3964k.

sage: s = 2*sqrt(2)/9801*(sum((factorial(4*k))*(1103+26390*k)/..... factorial(k))^4*396^(4*k)) for k in (0..11)))sage: (1/s).n(digits=100)3.141592653589793238462643383279502884197169399375105820974...sage: (pi-1/s).n(digits=100).n()-4.36415445739398e-96

Man sieht, dass die Patialsumme der ersten 12 Terme schon 95 signikante Stellen von πliefert!

Beispiel (Konvergenz einer Reihe). Es ist die Natur folgender Reihe zu untersuchen:∑n≥0

sin(π√

4n2 + 1).

Um eine asymptotische Entwicklung des allgemeinen Gliedes zu erhalten, benutzt man einemit 2π periodische Sinusfunktion, die gegen 0 strebt:

un = sin(π√

4n2 + 1)⇒ sin

[π(√

4n2 + 1− 2n)].

Nun kann man die Funktion taylor auf die neue Gestalt des allgemeinen Terms anwenden

n = var('n'); u = sin(pi*(sqrt(4*n^2+1)-2*n))taylor(u, n, infinity, 3)π

4n− 6π + π2

384n3

Daraus bekommt man un ∼ π4n , was nach den Vergleichs-Regeln für Riemann-Reihen zeigt,

dass die Reihe∑n≥0

un divergiert.

Übung 5 (Asymptotische Entwicklung einer Folge). Es ist unschwer zu zeigen (beispielsweisemit dem Satz über monotone Bijektionen), dass die Gleichung tanx = x für jedes n ∈ Nim Intervall [nπ, nπ + π

2 ] genau eine Lösung xn besitzt. Anzugeben ist eine asymptotischeEntwicklung von xn für +∞ mit der Ordnung 6.

32

Page 49: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3. Analysis

2.3.6. Ableitung

Die Funktion derivative (mit dem Alias diff) ermöglicht die Ableitung eines symbolischenAusdrucks oder einer symbolischen Funktion.

sage: diff(sin(x^2), x)2*x*cos(x^2)sage: function('f', x); function('g', x); diff(f(g(x)), x)f(x)g(x)D[0](f)(g(x))*diff(g(x), x)sage: diff(ln(f(x)), x)diff(f(x), x)/f(x)

2.3.7. Partielle Ableitungen

Der Befehl diff erlaubt auch die Berechnung der n-ten Ableitung oder von partiellen Ablei-tungen.

sage: f(x,y) = x*y + sin(x^2) +e^(-x); derivative(f, x)(x, y) |--> 2*x*cos(x^2) + y - e^(-x)sage: derivative(f, y)(x, y) |--> x

Beispiel. Zu verizieren ist, dass die folgende Funktion harmonisch5 ist:

f(x, y) =1

2ln(x2 + y2) für alle (x, y) 6= (0, 0).

sage: x, y = var('x, y'); f = ln(x^2 + y^2)/2sage: delta = diff(f,x,2) + diff(f,y,2)sage: delta.simplify_full()0

Übung 6 (Ein Gegenbeispiel von Peano zum Satz von Schwarz). Sei f eine Abbildung vonR2 nach R, die deniert ist durch

f(x, y) =

xy x

2−y2x2+y2

, falls (x, y) 6= (0, 0)

0, falls (x, y) = (0, 0)

Gilt ∂1∂2f(0, 0) = ∂2∂1f(0, 0)?

5Eine Funktion heiÿt harmonisch, wenn gilt ∆f = ∂21f + ∂2

2 = 0 mit dem Laplace-Operator ∆.

33

Page 50: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

2.3.8. Integration

Für die Berechnung bestimmter und unbestimmter Integrale verwenden wir die Funktion bzwdie Methode integrate oder deren Alias integral.

sage: sin(x).integral((x, 0, pi/2))1sage: integrate(1/(1+x^2), x)arctan(x)sage: integrate(1/(1+x^2), x, -infinity, infinity)pisage: integrate(exp(-x**2), x, 0, infinity)1/2*sqrt(pi)

sage: integrate(exp(-x), -infinity, infinity)Traceback (most recent call last):...ValueError: Integral is divergent.

Beispiel. Für x ∈ R ist das Integral ϕ(x) =+∞∫0

x cosu

u2 + x2du zu berechnen.

sage: u = var('u'); f = x*cos(u)/(u^2+x^2)sage: assume(x>0); f.integrate(u, 0, inifinity)1/2*pi*e^(-x)sage: forget(); assume(x<0); f.integrate(u, 0, infinity)-1/2*pi*e^x

Somit haben wir: ∀x ∈ R∗, ϕ(x) = π2 · sgn(x) · e−|x|.

Um eine numerische Integration auf einem Intervall zu bewirken, verfügen wir über die Funk-tion integral_numerical, die ein Tupel mit zwei Elementen zurückgibt, dessen erste Kom-ponente ein Näherungswert des Integrals ist und dessen zweite Komponte den Fehler ab-schätzt.

sage: integral_numerical(sin(x)/x, 0, 1)(0.946083070367183, 1.0503632079297087e-14)sage: g = integrate(exp(-x^2), x, 0, infinity)sage: g, g.n()(1/2*sqrt(pi), 0.886226925452758)sage: approx = integral_numerical(exp(-x^2), 0, infinity)sage: approx(0.8862269254527568, 1.714774436012769e-08)sage: approx[0] - g.n()-1.11022302462516e-15

Übung 7 (BBP-Formel). Wir versuchen, die BBP-Formel (Bailey-Borwein-Ploue-Formel)durch eine symbolische Rechnung aufzustellen: diese Formel ermöglicht die Berechnung der n-ten Nachkommastelle von π zur Basis 2 (oder 16), ohne die vorangehenden Ziern zu kennen,und das mit geringem Aufwand an Speicherplatz und Zeit. Für N ∈ N setzen wir

SN =

N∑n=0

(4

8n+ 1− 2

8n+ 4− 1

8n+ 5− 1

8n+ 6

)(1

16

)n.

34

Page 51: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.4. Elementare lineare Algebra (*)

1. Sei die Funktion f : t 7→ 4√

2− 8t3 − 4√

2t4 − 8t5. Für N ∈ N ist das folgende Integralals Funktion von SN auszudrücken:

IN =

1/√

2∫0

f(t)

(N∑n=0

t8n

)dt.

2. Für N ∈ N setze man J =1/√

2∫0

f(t)

1− t8dt. Zu zeigen ist lim

N→+∞SN = J .

3. Beweisen Sie die BBP-Formel:

+∞∑n=0

(4

8n+ 1− 2

8n+ 4− 1

8n+ 5− 1

8n+ 6

)(1

16

)n= π.

Diese bemerkenswerte Formel wurde am 19. September 1995 von Simon Ploue in Zu-sammenarbeit mit David Bailey und Peter Blorwein erhalten. Dank einer aus der BBP-Formel abgeleiteten Gleichung wurde im Jahre 2001 die4.000.000.000.000.000. Stelle von π zur Basis 2 bestimmt.

2.4. Elementare lineare Algebra (*)

In diesem Abschnitt beschreiben wir die grundlegenden Funktionen der lineare Algebra: Ope-rationen auf Vektoren und dann auf Matrizen. Wegen weiterer Details siehe Kapitel 8 übersymbolische Matrizenrechnung und Kapitel 13 über numerische Matrizenrechnung.

2.4.1. Lösung linearer Gleichungssysteme

Zur Lösung eines linearen Systems können wir die Funktion solve nehmen, die uns schonbegegnet ist.

Übung 8 (Polynomiale Näherung für den Sinus). Es ist das Polynom höchstens 5. Grades zubestimmen, das die beste Näherung im Sinne der kleinsten Quadrate im Intervall [−π, π] fürdie Sinusfunktion realisiert:

α5 = min

π∫−π

| sinx− P (x)|2dx|P ∈ R5[x]

.

2.4.2. Vektorrechnung

Die grundlegenden Funktionen für das Rechnen mit Vektoren sind in Tab. 2.5 zusammenge-stellt.

35

Page 52: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

Auf Vektoren gebräuchliche FunktionenDeklaration eines Vektors vector

Vektorprodukt cross_product

Skalarprodukt dot_product

Norm eines Vektors norm

Tabelle 2.5 - Vektorrechnung

Wir können uns dieser Funktionen bei der Behandlung der folgenden Übung bedienen.

Übung 9 (Das Problem von Gauÿ). Wir betrachten einen Satelliten in seiner Umlaufbahnum die Erde, von der wir drei Punkte kennen: A1, A2 und A3. Ausgehend von diesen dreiPunkten möchten wir die Parameter des Orbits dieses Satelliten bestimmen.

Wir bezeichnen mit O den Erdmittelpunkt. Die Punkte O, A1, A2 und A3 liegen oenbar inderselben Ebene, nämlich der Bahnebene des Satelliten. Die Bahn des Satelliten ist eine Ellipseund O einer ihrer Brennpunkte. Wir können ein Koordinatensystem (O,~i,~j), derart wählen,

dass die Ellipsengleichung in Polarkoordinaten in diesem Koordinatensystem r =p

1− e cos θist, wobei e die Exzentrizität der Ellipse bezeichnet und p ihren Parameter. Wir werdenschreiben ~ri = ~OAi und ri = |~ri| für i ∈ 1, 2, 3. Wir betrachten dann die folgenden dreiVektoren, die sich aus der Kenntnis von A1, A2 und A3 ergeben:

~D = ~r1 ∧ ~r2 + ~r2 ∧ ~r3 + ~r3 ∧ ~r1

~S = (r1 − r3) · ~r2 + (r3 − r3) · ~r1 + (r2 − r1) · ~r3

~N = r3 · (~r1 ∧ ~r2) + r1 · (~r2 ∧ ~r3) + r2 · (~r3 ∧ ~r1)

1. Zeigen Sie ~i ∧ ~D = −1e~S und leiten Sie daraus die Exzentrizität der Ellipse her.

2. Zeigen Sie: ~i ist kollinear zum Vektor ~S ∧ ~D.

3. Zeigen Sie ~i ∧ ~N = −pe~S und leiten Sie daraus den Parameter p der Ellipse her.

4. Drücken Sie die groÿe Halbachse a der Ellipse als Funktion des Parameters p und derExzentrizität e aus.

5. Anwendung mit Zahlen: In der erwähnten Ebene in einem rechtwinkligen Koordinaten-system betrachten wir die Punkte

A1

(01

), A2

(22

), A3

(35

), O

(0).

Zu bestimmen sind die Zahlenwerte der charakteristischen Gröÿen der Ellipse mit demBrennpunkt O durch die Punkte A1, A2 und A3.

2.4.3. Matrizenrechnung

Zur Denition einer Matrix verwenden wir den Befehl matrix und legen dabei eventuell auchden Ring (oder den Körper) fest, aus dem die Einträge genommen werden.

sage: A = matrix(QQ, [[1,2],[3,4]]); A[1 2][3 4]

36

Page 53: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.4. Elementare lineare Algebra (*)

Um für die Matrixgleichung Ax = b (bzw. xA = b) eine Lösung zu nden, benutzen wirdie Funktion solve_right bzw. solve_left. Um alle Lösungen einer Matrixgleichung zunden, muss man einer partikulären Lösung die allgemeine Lösung der zugehörigen homogenenGleichung hinzufügen. Für die Lösung einer homogenen Gleichung der Form Ax = 0 (bzw.xA = 0) steht die Funktion right_kernel bzw. left_kernel zur Verfügung, wie das folgendeBeispiel zeigt.

Übung 10 (Basen von Untervektorräumen).

1. Zu bestimmen ist eine Basis des Lösungsraumes des homogenen linearen Gleichungssys-tems mit der Matrix

A =

2 −3 2 −12 336 1 26 −16 6910 −29 −18 −53 322 0 8 −18 84

2. Zu bestimmen ist eine Basis des von den Spalten von A aufgespannten Vektorraums F .

3. F ist durch eine oder mehrere Gleichungen zu charakterisieren.

Übung 11 (Eine Matrixgleichung).

Wir erinnern uns an das Lemma zur Faktorisierung linearer Anwendungen. Seien E,F,G K-Vektorräume endlicher Dimension. Seien weiter u ∈ L(E,F ) und v ∈ L(E,G). Dann sind diefolgenden Aussagen äquivalent:

(i) es existiert w ∈ L(F,G), sodass v = w u ist,

(ii) keru ⊂ ker v.

Wir suchen alle Lösungen für dieses Problem in einem konkreten Fall. Es seien

A =

−2 1 18 1 −54 3 −3

und C =

1 2 −12 −1 −1−5 0 3

.

Zu bestimmen sind alle Lösungen B ∈M3(R) der Gleichung A = BC.

Auf Matrizen gebräuchliche FunktionenDeklaration einer Matrix matrix

Lösung einer Matrixgleichung solve_right, solve_left

Kern von rechtss, Kern von links right_kernel, left_kernel

Reduktion auf Treppennormalform echelon_form

Spaltenvektorraum column_space

Verkettung von Matrizen matrix_block

Reduktion von MatrizenEigenwerte einer Matrix eigenvalues

Eigenvektoren einer Matrix eigenvectors_right

Reduktion auf Jordan-Normalform jordan_form

Minimalpolynom einer Matrix minimal_polynomial

charakteristisches Polynom einer Matrix chrakteristic_polynomial

Tabelle 2.6 - Matrizenrechnung

37

Page 54: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Analysis und Algebra

2.4.4. Reduktion einer quadratischen Matrix

Für die Untersuchung der Eigenschaften einer Matrix stehen uns die in Tab. 2.6 aufgelistetenMethoden zur Verfügung.

Genauer werden diese Methoden in Kapitel 8 behandelt. Hier geben wir uns mit einigenBeispielen für ihre Anwendung zufrieden.

Beispiel. Is die Matrix

2 4 3−4 −6 −33 3 1

diagonalisierbar? Triagonalisierbar?

Wir beginnen mit der Denition der Matrix A auf dem Körper der rationalen Zahlen (QQ =Q). Danach bestimmen wir ihre Eigenschaften.

sage: A = matrix(QQ, [[2,4,3],[-4,-6,-3],[3,3,1]])sage: A.characteristic_polynomial()x^3 + 3*x^2 - 4sage: A.eigenvalues()[1, -2, -2]sage: A.minimal_polynomial().factor()(x - 1) * (x + 2)^2

Das minimale Polynom von A besitzt eine einfache und eine doppelte Wurzel. Daher ist Anicht diagonalisierbar. Hingegen ist das minimale Polynom von A zusammengesetzt. Daherist A triagonalisierbar.

sage: A.eigenvectors_right()[(1, [(1, −1, 1)] , 1) , (−2, [(1, −1, 0)] , 2)]

sage: A.jordan_form(transformation=True) 1 0 0

0 −2 10 0 −2

,

1 1 1−1 −1 0

1 0 −1

Beispiel. Die Matrix A =

(1 −1/2−1/2 −1

)ist zu diagonalisieren. Man kann es mit der

Methode jordan_form versuchen:

sage: A = matrix(QQ, [[1,-1/2],[-1/2,-1]])sage: A.jordan_form()Traceback (click to the left of this block for traceback)...RuntimeError: Some eigenvalue does not exist in Rational Field.

Hier ist eine kleine Schwierigkeit aufgetreten: die Eigenwerte sind nicht rational.

sage: A.minimal_polynomial()

x2 − 5

4

Wir müssen also den Basiskörper wechseln.

sage: R = QQ[sqrt(5)]sage: A = A.change_ring(R)

38

Page 55: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.4. Elementare lineare Algebra (*)

sage: A.jordan_form(transformation=True, subdivide=False)((12sqrt5 0

0 −12sqrt5

),

(1 1

−sqrt5 + 2 sqrt5 + 2

))Das interpretieren wir als((

12

√5 0

0 −12

√5

),

(1 1

−√

5 + 2√

5 + 2

))

Beispiel. Die Matrix A =

2√

6√

2√6 3

√3√

2√

3 1

ist zu diagonalisieren.

Dieses Mal müssen wir mit einer Erweiterung 4. Grades des Körpers Q arbeiten. Man gehtnun vor wie folgt:

sage: K.<sqrt2> = NumberField(x^2 - 2)sage: L.<sqrt3> = K.extension(x^2 - 3)sage: A = matrix(L, [[2, sqrt2*sqrt3, sqrt2], \

[sqrt2*sqrt3, 3, sqrt3], \[sqrt2, sqrt3, 1]])

sage: A.jordan_form(transformation=True) 6 0 0

0 0 0

0 0 0

,

1 1 012sqrt2sqrt3 0 1

12sqrt2 −sqrt2 −sqrt3

oder6 0 0

0 0 00 0 0

,

1 1 0

1

2

√2√

3 0 1

1

2

√2 −

√2 −

√3

.

39

Page 56: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 57: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Wir haben in den vorangegangenen Kapiteln gesehen, wie mathematische Rechnungen mitisolierten Sage-Befehlen zu bewerkstelligen sind, doch das Systen ermächtigt auch zur Pro-grammierung einer Folge von Anweisungen.

Das System Sage zum symbolischen Rechnen ist in der Tat eine Erweiterung der Program-miersprache Python1 und erlaubt, wenn auch mit etlichen Veränderungen der Syntax, dieProgrammiermethoden dieser Sprache auszunutzen.

Die in den vorangegangenen Kapiteln beschriebenen Befehle beweisen, dass es nicht nötigist, die Sprache Python zu kennen, um Sage zu verwenden; dagegen zeigt dieses Kapitel,wie in Sage die elementaren Programmier-Strukturen von Python angewendet werden. Dasbeschränkt sich auf die Grundlagen der Programmierung und kann von Menschen, die Pythonkennen, vielleicht nur überogen werden: die Beispiele sind aus den klassischen Bereichen derMathematik ausgewählt, um dem Leser durch Analogie mit der Programmiersprache, die erkennt, eine rasche Anpassung an Python zu ermöglichen.

Dieses Kapitel stellt die algorithmische Methode der strukturierten Programmierung vor mitSchleifen und Abfragen und stellt im folgenden die Funktionen vor, die auf Listen und anderenzusammengesetzten Datenstrukturen operieren. Das Buch Apprendre à programmer avec Py-

thon von G. Swinnen [Swi09, Swi12] (frei verfügbar) und der Syllabus online von T. Massart[Mas13] bieten eine vertiefte Darstellung der Sprache Python.

Schlüsselwörter der Programmierspache Pythonwhile, for...in, if...elif...else Schleifen und Bedingungen

continue, break vorzeitige Beendigung eines Codeblockstry...except...finally Behandlung und Auslösung von Fehlern

assert einzuhaltende Bedingungpass Befehl ohne Wirkung

def, lambda Denition einer Funktionreturn, yield Rückgabe eines Wertesglobal, del Sichtbarkeit und Löschen einer Variablenand, not, or logische Operatoren

print Textausgabeclass, with objektorientierte Programmierung, Anwendung von Kontext

from...import...as Zugri auf eine Bibliothekexec...in dynamische Auswertung von Code

Tabelle 3.1 - Allgemeine Syntax des Sage-Codes

1Sage verwendet Python 2.7, eine Änderung ist vorerst nicht zu erwarten.

41

Page 58: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

3.1. Syntax

3.1.1. Allgemeine Syntax

Die elementaren Anweisungen werden generell Zeile für Zeile ausgeführt. Python betrachtetdas Zeichen # als Anfang eines Kommentars und ignoriert den Text von hier an bis zumEnde der Zeile. Das Semikolon ; trennt Anweisungen auf derselben Zeile:

sage: 2*3; 3*4; 4*5 # ein Kommentar, 3 Ergebnisse61220

Bei der Eingabe kann sich eine Anweisung über mehrere Zeilen erstrecken. Dann wird diealte Zeile mit einem umgekehrter Schrägstrich \ (backslash) abgeschlossen, bevor die neueZeile erönet wird. Der Wagenrücklauf (carriage return) wird als Leerzeichen betrachtet.

sage: 123 + \....: 345468

Ein Bezeichner - also der Name einer Variablen, einer Funktion usw. - besteht nur aus Buch-staben, Ziern oder dem Unterstrich _, und darf nicht mit einer Zier beginnen (der Nameeiner Datei aber schon). Die Bezeichner sollen sich von Schlüsselwörtern der Programmier-sprache unterscheiden. Die Schlüsselwörter in Tab. 3.1 bilden den Kern von Python 2.7. Eineeinfache Liste der Schlüsselwörter erhält man mit

sage: import keyword; keyword.kwlist['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del','elif', 'else', 'except', 'exec', 'finally', 'for', 'from','global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass','print', 'raise', 'return', 'try', 'while', 'with', 'yield']

Zeichen in Sage mit besonderer Bedeutung und ihre Verwendung, ; Trenner von Argumenten und Anweisungen

: Erönung eines Anweisungsblocks, Raung. Dezimalpunkt, Zugri auf Felder von Objekten= Zuweisung eines Wertes an eine Variable

+ - * / elementare arithmetische Operatoren^ ** Potenz// % Quotient und Rest einer Ganzzahl-Division

+= -= *= /= **= arithmetische Operatoren mit Veränderung einer Variablen== != <> is Tests auf Gleichheit< <= > >= Vergleichsoperatoren

& | ^^ << >> Mengenoperatoren und logische Bit-Operatoren# Kommentar (bis Zeilenende)

[...] Konstruktion einer Liste, Zugri auf ein indiziertes Element(...) Aufruf einer Funktion oder Methode, unveränderliches Tupel

...:... Konstruktion von Diktionären\ Maskierung von Sonderzeichen, lineare Algebra? Zugri auf die Hilfe

_ __ ___ Wiederholung der letzten drei Ergebnisse

Tabelle 3.2 - Allgemeine Syntax des Sage-Codes (Fortsetzung)

42

Page 59: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.1. Syntax

Diesen Schlüsselwörtern sind noch die Konstanten None (Wert leer), etwa äquivalent zuNULL in anderen Programmiersprachen, True und False, sowie zahlreiche, in Python undSage vordenierte Funktionen wie len, cos und integrate hinzuzufügen. Es ist sehr zuempfehlen, diese Bezeichner nicht als Namen für Variablen zu verwenden, weil dann der Zu-gang zu Funktionalitäten des Systems schwierig werden könnte. Der Interpreter akzeptiertnoch mehr Befehle wie quit zum Verlassen der laufenden Sage-Sitzung. Wir werden davonnach und nach weitere kennenlernen.

Bestimmte Zeichen spielen in Sage eine besondere Rolle. Sie sind in Tab. 3.2 aufgelistet.

3.1.2. Aufruf von Funktionen

Die Auswertung einer Funktion verlangt, dass ihr eventuelle Argumente in Klammern überge-ben werden, wie in cos(pi) oder in der Funktion ohne Argument reset(). Hingegen sind dieKlammern für Argumente bei Befehlen überüssig: print(6*7) und print 6*7 leisten dasgleiche2. Der Name einer Funktion ohne Argument oder Klammer stellt die Funktion selbstdar und bewirkt keinerlei Rechnung.

3.1.3. Ergänzungen zu Variablen

Wie wir gesehen haben, erkennt Sage im Gleichheitseichen = die Anweisung, einer Variableneinen Wert zuzuweisen. Zuerst wird die Seite rechts von = ausgewertet, dann wird ihr Wertder Variablen zugewiesen, deren Name links steht. So haben wir

sage: y = 3; y = 3*y + 1; y = 3*y + 1; y31

Die obigen Zuweisungen verändern den Wert der Variablen y ohne einen Zwischenwert aus-zugeben. Der letzte dieser vier Befehle gibt den Wert der Variablen y aus, nachdem alleRechnungen beendet sind.

Der Befehl del x unterbindet Zuweisungen an die Variable x und durch die Funktion ohne Ar-gument reset() werden die Variablen wieder initialiert. Die gleichzeitige, parallele Zuweisungvon Werten an mehrere Variablen ist auch möglich.

sage: a, b = 10, 20 # auch möglich: (a, b) = (10, 20) oder [10, 20]sage: a, b = b, asage: a, b(20, 10)

Die Zuweisung a, b = b, a vertauscht die Werte von a und b und ist äquivalent zum sonstüblichen Vorgehen mit einer Zwischenvariablen:

sage: temp = a: a = b; b = temp

Ein weiteres Beispiel für den Tausch der Werte zweier Variablen ohne Zwischenvariable oderparalle Zweisung, aber mit Summe und Dierenz ist das folgende:

sage: x, y = var('x, y'); a = x; b = ysage: a, b

2In Python 3.x ist print eine Funktion und erwartet seine Argumente in Klammern.

43

Page 60: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

(x, y)sage: a = a + b; b = a - b; a = a - bsage: a, b(y, x)

Die gleichzeitige Zuweisung desselben Wertes an mehrere Variable gelingt mit einer Syntaxder Form a = b = c = 0; die Befehle x += 5 und n += 2 sind äquivalent zu x = x + 5 bzw.zu n = n + 2.

Der Test auf Gleichheit zweier Objekte erfolgt mit dem aus zwei Gleichheitszeichen bestehen-den Operator ==.

sage: 2 + 2 == 2^2, 3*3 == 3^3(True, False)

3.2. Algorithmik

Die strukturierte Programmierung besteht in der Beschreibung eines Programm-Ablaufs alseine endliche Folge von Anweisungen, die eine nach der anderen abgearbeitet werden. DieseAnweisungen können elementar oder zusammengesetzt sein.

- eine elementare Anweisung besteht beispielsweise aus der Zuweisung eines Wertes zu einerVariablen (siehe Unterabschnitt 1.2.4) oder der Ausgabe eines Ergebnisses;

- eine zusammengesetzte Anweisung wie eine Schleife oder eine Bedingung wird aus mehrerenAnweisungen gebildet, die ihrerseits wieder elementar oder zusammengesetzt sein können.

3.2.1. Schleifen

Aufzählungsschleifen. Eine Aufzählungsschleife führt die gleiche Rechnung für alle ganz-zahligen Werte einer Indexfolge k ∈ [a, . . . , b] aus. Das folgende Beispiel3 gibt den Anfang derMultiplikationstabelle mit 7 aus:

sage: for k in [1..5]:....: print 7*k # Block mit einer einzigen Annweisung714212835

Der Doppelpunkt : am Ende der ersten Zeile erönet den Anweisungsblock, welcher derReihe nach mit k = 1, 2, 3, 4, 5 ausgewertet wird. Bei jeder Iteration gibt Sage das Produkt7× k als momentanen Wert des Befehls print aus.

In diesem Beispiel besteht der Block der zu wiederholenden Anweisungen nur aus dem Befehlprint, der gegen das Schlüsselwort for eingerückt ist. Ein Block aus mehreren Anweisungen

3Wird Sage auf einem Terminal ausgeführt, wird ein Block durch Eingabe einer Leerzeile beendet. Das istbei der Arbeit mit Sage in einem Skript oder in einem Notebook nicht erforderlich und wird im folgendenstillschweigend so gehandhabt.

44

Page 61: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

ist daran erkennbar, dass die eingegebenen Anweisungen alle mit der gleichen Einrückunguntereinander stehen.

Die Kennzeichnung des Blocks ist wichtig: die beiden folgenden Programme unterscheidensich nur bei der Einrückung einer Zeile und zeitigen unterschiedliche Ergebnisse:

sage: S = 0 sage: S = 0sage: for k in [1..3]: sage: for k in [1..3]:....: S += k ....: S += ksage: S *= 2 ....: S *= 2sage: S sage: S

Links wird die Anweisung S *= 2 nach der Schleife einmal ausgeführt, während das rechtsbei jeder Iteration geschieht, weswegen die Ergebnisse verschieden sind:

S = (0 + 1 + 2 + 3) · 2 = 12 S = ((((0 + 1) · 2) + 2) · 2 + 3) · 2 = 22

Diese Schleife dient unter anderem zur Berechnung eines Terms einer rekursiven Folge wie amEnde dieses Unterabschnitts gezeigt.

Funktionen für die Iteration der Form ..range für ganze Zahlen a, b, cfor k in [a..b]: ... erzeugt eine Liste von ganzen Sage-Zahlen a ≤ k ≤ b

for k in srange(a, b): ... erzeugt eine Liste von ganzen Sage-Zahlen a ≤ k < bfor k in range(a, b): ... erzeugt eine Liste von ganzen Python-Zahlen (int) a ≤ k < bfor k in xrange(a, b): ... zählt die ganzen Python-Zahlen (int) auf, ohne

die entsprechende Liste explizit zu erzeugenfor k in sxrange(a, b): ... zählt die Sage-Zahlen auf ohne die Liste zu erzeugen[a,a+c..b], [a, b, step=c] die Sage-Zahlen a, a+ c, a+ 2c, . . . , a+ kc ≤ b

..range(b) äquivalent zu ..range(0, b)

..range(a, b, c) mit Schrittweite c statt 1

Tabelle 3.3 - Die verschiedenen Aufzählungsschleifen

Die Syntax einer Aufzählungsschleife ist sehr direkt und kann ohne weiteres für 104 oder 105

Iterationen verwendet werden. Sie eignet sich hingegen nicht für den Aufbau einer Liste allerWerte der Schleifenvariable, bevor die zu iterierenden Anweisungen wiederholt werden, siehat vielmehr den Vorteil, die ganze Zahl des Sage-Typs Integer (siehe Unterabschnitt 5.3.1)zu manipulieren. Mehrere Funktionen ...range erlauben für diese Iterationen die Auswahlaus zwei möglichen Alternativen. Die erste besteht entweder im Anlegen einer Werteliste imSpeicher, bevor die Schleife ausgeführt wird oder in der Bestimmung dieser Werte im Laufeder Zeit. Die andere Alternative arbeitet mit ganzen Sage-Zahlen4 des Typs Integer oder mitganzen Python-Zahlen des Typs int; die beiden Ganzzahl-Typen haben nicht genau dieselbenEigenschaften. Im Zweifel bewahrt die Form [a..b] am sichersten vor Überraschungen.

while-Schleifen. Die andere Familie der Schleifen wird von den while-Schleifen gebildet.Wie auch die Aufzählungsschleife for wertet sie einen Anweisungsblock mehrmals aus. Indesist die Anzahl der Wiederholungen nicht von vornherein festgelegt, sondern hängt von derErfüllung einer Bedingung ab.

4Die Befehle srange, sxrange und [...] operieren auch auf rationalen und Flieÿpunkt-Zahlen: was gibt[pi,pi+4..20]?

45

Page 62: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Wie der Name sagt, wiederholt die Schleife die Anweisungen solange, wie eine Bedingungerfüllt ist. Das folgende Beispiel5 berechnet die Summe der Quadrate der natürlichen Zahlen,solange die Potenz der natürlichen Zahl den Wert 106 nicht überschreitet, also 12 + 22 + . . .+132.

sage: S = 0; k = 0 # Die Summme beginnt mit 0sage: while e^k <= 10^6: # e^13 <= 10^5 < e^14....: S = S + k^2 # addiert die Quadrate k^2....: k = k + 1

sage: S819

Die letzte Anweisung gibt den Wert der Variablen S aus. Es gilt:

S =∑k ∈ Nek ≤ 106

k2 =

13∑k=0

k2 = 819, e13 ≈ 442413 ≤ 106 < e14 ≈ 1202604.

Der obige Anweisungsblock umfasst zwei Zuweisungen, die erste addiert den neuen Term, diezweite geht zum nächsten Index über. Beide Anweisungen sind untereinander angeordnet undinnerhalb der while-Struktur auf die gleiche Weise eingerückt.

Das nächste ist wieder ein typisches Beispiel einer while-Schleife. Die sucht für eine Zahlx ≥ 1 nach dem einzigen Wert n ∈ N sodass gilt 2n−1 ≤ x ≤ 2n, das heiÿt die kleinsteganze Zahl, sodass x < 2n ist. Das untenstehende Programm vergleicht x mit 2n, dessen Wert1, 2, 4, 9 usw. ist. Sie führt diese Rechnung für x = 104 aus:

sage: x = 10^4; u = 1; n= 0 # invariant: u = 2^nsage: while u <= x: n = n + 1; u = 2*u # wobei n += 1; u *= 2sage: n14

Solange, wie die Bedingung 2n ≤ x erfüllt ist, berechnet das Programm die neuen Werte n+1und 2n+1 = 2 ·2n der beiden Variablen n und u und speichert sie anstelle von n und 2n. DieseSchleife endet, sobald die Bedingung nicht mehr erfüllt ist, also bei x > 2n:

x = 104, min n ∈ N|x < 2n = 14, 213 = 8192, 1014 = 16384.

Der Rumpf einer Schleife wird nie ausgeführt, wenn die Bedingung von Anfang an nicht erfülltist.

Einfache Anweisungsblöcke können nach dem Doppelpunkt : auf derselben Zeile eingegebenwerden, ohne einen neuen eingerückten Block zu denieren, der mit der neuen Zeile beginnenwürde.

Beispiele für die Anwendung bei Folgen und Reihen. Die for-Schleife ermöglicht dieeinfache Berechnung eines Terms einer rekursiv denierten Folge. Es sei beispielsweise (un)die durch

u0 = 1, ∀n ∈ N : un+1 =1

1 + u2n

5Die Eingabe einer Leerzeile ist erforderlich, um den Anweisungsblock zu beenden, bevor der Wert von Sabgefragt werden kann.

46

Page 63: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

denierte Folge. Das untenstehende Programm bestimmt eine numerische Näherung von unfür n = 20; die Variable U wird bei jeder Schleifeniteration modiziert, um mit der Rekursi-onsgleichung vom Wert un−1 auf un zu kommen. Die erste Iteration berechnet u1 aus u0 fürn = 1, die zweite macht dasselbe von u1 nach u2 mit n = 2, und die letzte der n Iterationenmodiziert die Variable U , um von un−1 zu un zu gelangen:

sage: U = 1.0 # oder U = 1. oder U = 1.000sage: for n in [1..20]:....: U = 1/(1 + U^2)sage: U0.68236043761105

Dasselbe Programm mit der Ganzzahl U = 1 anstelle der numerischen Approximation U = 1.0in der ersten Zeile führt eine exakte Rechnung auf den rationalen Zahlen aus; das exakte Er-gebnis für u10 ist ein Bruch mit mehr als hundert Ziern, und u20 enthält davon mehrereHunderttausend. Exakte Rechnungen sind interessant, wenn sich Rundungsfehler in den nu-merischen Approximationen anhäufen. Die Rechnung mit Näherungswerten, von Hand odermit dem Rechner, mit Hunderten von Dezimalstellen sind schneller als die mit 500, 1000 odernoch mehr ganzen oder rationalen Zahlen.

Unterbrechung der Ausführung einer Schleife

Die for- und die while-Schleifen wiederholen dieselben Anweisungen mehrmals. DerBefehl break im Inneren einer Schleife beendet diese Schleife vorzeitig, und derBefehl continue springt sofort zur nächsten Iteration. So bewirken diese Befehle dieAuswertung der Bedingung an beliebiger Stelle des Schleifenkörpers.Die vier Beispiele hierunter bestimmen die kleinste natürliche Zahl x, die die Bedin-gung ln(x + 1) ≤ x/10 erfüllt. Das erste bringt eine for-Schleife mit maximal 100Versuchen, die nach der ersten Lösung vorzeitig beendet wird; das zweite stellt dieSuche nach der kleinsten Zahl dar, welche die Bedingung erfüllt und riskiert dabei,nicht zu enden, falls die Bedingung niemals erfüllt wird; das dritte entspricht demersten mit einer komplizierteren Schleifenbedingung, und schlieÿlich besitzt das vier-te Beispiel eine unnötig komplizierte Struktur, die nur den Zweck hat, den Befehlcontinue zu verwenden. In jedem dieser Fälle hat x den Endwert 37.0.

for x in [1.0..100.0]: x = 1.0if log(x+1) <= x/10: break while log(x+1) > x/10:

x = x + 1

x = 1.0 x = 1.0while log(x+1) > x/10 and x < 100: while True:

x = x + 1 log(x+1) > x/10:x = x + 1continue

break

Der Befehl return (der die Ausführung einer Funktion beendet und ihren Wert zu-rückgibt, siehe Unterabschnitt 3.2.3), stellt eine weitere Art des vorzeitigen Abbruchseines Anweisungsblocks dar.

47

Page 64: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Summen und Produkte können in die Form von rekursiv denierten Folgen gebracht werdenund werden auf die gleiche Weise berechnet:

Sn =n∑k=1

(2k)(2k + 1) = 2 · 3 + 4 · 5 + . . .+ (2n)(2n+ 1),

S0 = 0, Sn = Sn−1

Diese Reihe wird auf dieselbe Weise programmiert wie die rekursiv denierten Folgen: dasProgramm bildet die Summen mit 0 beginnend eine nach der anderen, indem es die Termefür k = 1, k = 2 bis k = n addiert:

sage: S = 0; n = 10sage: for k in [1..n]:...: S = S + (2*k)*(2*k+1)sage: S1650

Dieses Beispiel veranschaulicht ein allgemeines Programmierverfahren für eine Summe, dochin diesem einfachen Fall zeitigt die formale Rechnung ein Ergebnis in voller Allgemeinheit:

sage: n, k = var('n k'); res = sum(2*k*(2*k+1), k, 1, n)sage: res, factor(res) # das Resultat wird anschlieÿend faktorisiert(4/3*n^3 + 3*n^2 + 5/3*n, 1/3*(4*n + 5)*(n + 1)*n)

Diese Resultate können auch mit Papier und Bleistift als wohlbekannte Summen erhaltenwerden:

n∑k=1

k =n(n+ 1)

2,

n∑k=1

k2 =n(n+ 1)(2n+ 1)

6,

n∑k=1

2k(2k + 1) = 4∑k=1

nk2 + 2n∑k=1

k =2n(n+ 1)(2n+ 1)

3+ n(n+ 1)

=n(n+ 1)((4n+ 2) + 3)

3=n(n+ 1)(4n+ 5)

3

Beispiele für die Annäherung an Grenzwerte von Folgen. Die for-Schleife ermöglichtdie Berechnung eines gegebenen Terms einer Folge oder einer Reihe, die while-Schleife istdagegen gut geeignet, den Grenzwert einer Folge numerisch anzunähern.

Konvergiert eine Folge (an)n∈N gegen l ∈ R, sind die Terme an für hinreichend groÿes nNachbarn von l. Daher ist es möglich, l durch einen bestimmten Term an anzunähern unddas mathematische Problem besteht darin, den Fehler |l − an| mehr oder weniger leicht zuerhöhen. Diese Erhöhung ist für die benachbarten Folgen (un)n∈N und (vn)n∈N unmittelbar,das heiÿt solche, für die gilt

(un)n∈N nimmt zu,(vn)n∈N nimmt ab,

limn→+∞

vn − un = 0.

In diesem Fall giltbeide Folgen konvergieren gegen den gleichen Grenzwert l,∀p ∈ N : up ≤ lim

n→+∞un = l = lim

n→+∞vn ≤ vp,∣∣∣l − up+vp

2

∣∣∣ ≤ up−vp2 .

48

Page 65: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

Eine mathematische Fingerübung beweist, dass die beiden untenstehenden Folgen benachbartsind und gegen

√ab konvergieren, wenn 0 < a < b ist:

u0 = a, v0 = b > a, un+1 =2unvnun + vn

, vn+1 =un + vn

2.

Der gemeinsame Grenzwert dieser beiden Folgen trägt den Namen arithmetisch-harmonischesMittel, denn das arithmetische Mittel zweier Zahlen a und b ist Mittelwert im üblichen Sinne(a + b)/2 und das harmonische Mittel h ist das Inverse des Mittels der inversen: 1/h =(1/a+ 1/b)/2 = (a+ b)/(2ab). Das folgende Programm bestätigt, dass der Grenzwert für dieZahlenwerte derselbe ist:

sage: U = 2.0; V = 50.0sage: while V-U >= 1.0e-6: # 1-0e-6 bedeutet 1.0*10^-6....: temp = U....: U = 2*U*V/(U + V)....: V = (temp + V)/2sage: U, V(9.99999999989256, 10.0000000001074)

Die Werte von un+1 und vn+1 hängen von un und vn ab: aus diesem Grund lässt die Haupt-schleife dieses Programms eine Zwischenvariable, die hier temp heiÿt, aufrufen, weil die neuenWerte vun+1 und vn+1 von U und V von den zwei vorhergehenden Werten un und vn ab-hängen. Die beiden Blöcke hierunter links denieren dieselben Folgen, während die untenrechts zwei andere Folgen, (u′n)n und (v′n)n, bildet; die parallele Zuweisung vermeidet dieVerwendung einer Zwischenvariablen:

temp = 2*U*V/(U+V) U,V = 2*U*V/(U+V), (U+V)/2 U = 2*U*V/(U+V)V = (U + V)/2 V = (U+V)/2

U = temp (parallele Zuweisung) u′n+1 = 2u′nv′n

u′n+v′n

v′n+1 =u′n+1+v′n

2

Die Reihe Sn =n∑k=0

(−1)kak ist alternierend, da die Reihe (an)n∈N abnimmt und den Grenzwert

0 hat. Zu sagen, dass S alternierend ist, bedeutet, dass die beiden Teilfolgen (S2n)n∈N und(S2n+1)n∈N benachbart sind und denselben Grenzwert l haben. Die Folge (an)n∈N konvergiertdaher auch gegen diesen Grenzwert und hat ihn bei S2p+1 ≤ l = lim

n→+∞Sn ≤ S2p.

Das folgende Programm illustriert dieses Ergebnis für die Folge ak = 1/k3, beginnend mitk = 1 und speichert dazu die aufeinander folgenden Patialsummen S2n und S2n+1 der Reihe,die den Grenzwert einschachteln, in den beiden Variablen U und V :

sage: U = 0.0 # die Summe S0 ist leer, der Wert 0sage: V = -1.0 # S1 = -1/1^3sage: n = 0 # U und V enthalten S(2n) und S(2n+1)sage: while U-V >= 1.0e-6:....: n = n+1 # n += 1 ist äquivalent....: U = V + 1/(2*n)^3 # Übergang von S(2n+1) zu S(2n)....: V = U + 1/(2*n+1)^3 # Übergang von S(2n) zu S(2n+1)sage: V, U(-0.901543155458595, -0.901542184868447)

49

Page 66: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Die Hauptschleife modiziert den Wert von n, um zum nächsten Index überzugehen, solangedie beiden Werte S2n und S2n+1 nicht genügend nahe beieinander liegen. Die beidenn Va-riablen U und V speichern die aufeinander folgenden Terme; der Schleifenrumpf bestimmtbeginnend mit S2n−1 nacheinander S2n und S2n+1, dann wechseln die Zuweisungen zu U undzu V .

Das Programm endet, sobald zwei aufeinander folgenden Terme S2n+1 und S2n, die den Grenz-wert einschachteln, einander nahe genug gekommen sind, der Näherungsfehler (ohne Beach-tung des Rundungsfehlers) beträgt dann 0 ≤ a2n+1 = S2n − S2n+1 ≤ 10−6.

Die Programmierung dieser fünf alternierenden Reihen geht ähnlich:∑n≥2

(−1)n

lnn,∑n≥1

(−1)n

n,∑n≥1

(−1)n

n2,

∑n≥1

(−1)n

n4,∑n≥1

(−1)ne−n lnn =∑n≥1

(−1)n

nn.

Die allgemeinen Terme dieser Reihen tendieren mehr oder weniger schnell gegen 0, und dieAnnäherungen an die Grenzwerte erforden je nach Fall mehr oder weniger Rechnungen.

Die Suche nach den Grenzwerten dieser Reihen mit einer Genauigkeit von 3, 10, 20 oder 100Dezimalstellen besteht in der Lösung folgender Ungleichungen:

1/ lnn ≤ 10−3 ⇐⇒ n ≥ e(103) ≈ 1.97 · 10434

1/n ≤ 10−3 ⇐⇒ n ≥ 103 1/n ≤ 10−10 ⇐⇒ n ≥ 1010

1/n2 ≤ 10−3 ⇐⇒ n ≥√

103 ≈ 32 1/n2 ≤ 10−10 ⇐⇒ n ≥ 105

1/n4 ≤ 10−3 ⇐⇒ n ≥ (103)1/4 ≈ 6 1/n4 ≤ 10−10 ⇐⇒ n ≥ 317e−n lnn ≤ 10−3 ⇐⇒ n ≥ 5 e−n lnn ≤ 10−10 ⇐⇒ n ≥ 30

1/n2 ≤ 10−20 ⇐⇒ n ≥ 1010 1/n2 ≤ 10−100 ⇐⇒ n ≥ 1050

1/n4 ≤ 10−20 ⇐⇒ n ≥ 105 1/n4 ≤ 10−100 ⇐⇒ n ≥ 1025

e−n lnn ≤ 10−20 ⇐⇒ n ≥ 17 e−n lnn ≤ 10−100 ⇐⇒ n ≥ 57

In den einfachsten Fällen bestimmt die Lösung dieser Ungleichungen einen Index n, ab demsich der Wert Sn dem Grenzwert l der Reihe annähern darf, ebenso ist eine for-Schleifemöglich. Im Gegensatz dazu ist eine while-Schleife nötig, sobald sich die algebraische Lösungder Ungleichung in n an ≤ 10−p als unmöglich erweist.

Bestimmte Näherungslösungen für die vorstehenden Grenzwerte erforden zu viele Rechnun-gen, um direkt erhalten zu werden, insbesondere sobald der Index n eine Gröÿenordnung von1010 oder 1012 überschreitet. Ein vertieftes Studium der Mathematik kann zuweilen die Be-stimmung des Grenzwertes oder eine Näherung mit anderen Verfahren ermöglichen, darunterRiemann-Reihen:

limn→+∞

n∑k=1

(−1)k

k3= −3

4ζ(3), mit ζ(p) = lim

n→+∞

n∑k=1

1

kp,

limn→+∞

n∑k=1

(−1)k

k= − ln 2, lim

n→+∞

n∑k=1

(−1)k

k2= −π

2

12,

limn→+∞

n∑k=1

(−1)k

k4= −7π4

6!.

50

Page 67: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

Auÿerdem kann Sage einige solcher Gleichungen und einen Näherungswert von ζ(3) nit 1200Dezimalstellen in wenigen Sekunden mit viel weniger als 10400 Operationen berechnen als beidirekter Anwendung der Denition nötig wären:

sage: k = var('k'); sum((-1)^k/k, k, 1, +oo)-log(2)sage: sum((-1)^k/k^2, k, 1, +oo), sum((-1)^k/k^3, k, 1, +oo)(-1/12*pi^2, -3/4*zeta(3))sage: -3/4*zeta(N(3, digits=1200))-0.901542677369695714049803621133587493073739719255374161344\203666506378654339734817639841905207001443609649368346445539\563868996999004962410332297627905925121090456337212020050039\...019995492652889297069804080151808335908153437310705359919271\798970151406163560328524502424605060519774421390289145054538\901961216359146837813916598064286672255343817703539760170306262

3.2.2. Bedingungen

Weitere wichtige zusammengesetze Anweisungen stellen die Bedingungen dar: welche Anwei-sung ausgeführt wird, hängt vom Wahrheitswert einer Bedingung ab. Die Struktur und zweimögliche Formen dieser Anweisung sind die folgenden:

if <Bedingung>: if <Bedingung>:ein Anweisungsblock ein Anweisungsblock

else: sonst ein anderer Anweisungsblock

Die Syrakuse-Folge (Collatz-Problem) ist mit einer Prüfung auf Parität deniert:

u0 ∈ N∗ un+1 =

un/2 falls un gerade ist,3un + 1 falls un ungerade ist.

Die tschechische Vermutung besagt - seit 2012 bekannt und unbewiesen - dass für jedenAnfangswert u0 ∈ N∗ eine Ordnungszahl n existiert, für die un = 1 wird. Die folgenden Termesind dann 4, 2, 1, 4, 2 usw. Die Berechnung jedes Terms der Folge erfolgt vermittels derPrüfung einer Bedingung. Diese Prüfung wird im Inneren einer while-Schleife angeordnet,die den kleinsten Wert von n ∈ N bestimmt, für den un = 1 wird:

sage: u = 6; n = 0sage: while u != 1: # eine Prüfung mit <> ("ungleich") ist auch möglich....: if u % 2 == 0: # der Operator % ergibt den Rest der Ganzzahldivision....: u = u//2 # //: Quotient der Ganzzahldivision....: else:....: u = 3*u+1....: n = n + 1sage: n8

Die Prüfung, ob un gerade ist, erfolgt durch Vergleich des Restes der Division von un durch2 mit 0. Die Anzahl der ausgeführten Iterationen ist der Wert der Variablen n am Ende des

51

Page 68: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Blocks. Diese Schleife endet, sobald der berechnete Wert von un = 1 ist. Wenn u0 beispiels-weise 6 ist, wird u8 = 1 und 8 = min p ∈ N∗ | up = 1:

p = 0 1 2 3 4 5 6 7 8 9 10 . . .up = 6 3 10 5 16 8 4 2 1 4 2 . . .

Die schrittweise Verikation der korrekten Arbeitsweise dieser Zeilen kann durch einen print-

Spion der Form print(u, n) im Schleifenrumpf geleistet werden,

Der Befehl if erlaubt auÿerdem, Prüfungen mit Hilfe des Wortes elif in den else-Zweig zulegen. Diese beiden Strukturen sind gleichwertig:

if eine Bedingung bed1: if bed1:eine Anweisungsfolge anw1 anw1

else: elif bed2:if eine Bedinging bed2: anw2

eine Anweisungsfolge anw2 elif cond3:else: anw3

if eine Bedingung cond3: else:eine Anweisungsfolge anw3 anwn

else:sonst anwn

Wie bei Schleifen kann eine einfache Anweisung neben dem Doppelpunkt angeordnet werdenund nicht als Block darunter.

3.2.3. Prozeduren und Funktionen

Allgemeine Syntax. Wie andere Programmiersprachen auch erlaubt Sage dem Anwender,Funktionen oder Prozeduren nach Maÿ zu denieren. Der Befehl def, dessen Syntax hierunterzu erkennen ist, erönet die Denition von Prozeduren und Funktionen, d.h. von Unterpro-grammen (die kein Ergebnis zurückgeben bzw. genau dies tun), ohne Argument oder mit einemoder mehreren Argumenten. Das erste Beispiel deklariert die Funktion (x, y) 7→ x2 + y2:

sage: def fct2 (x, y):....: return x^2 + y^2sage: a = var('a')sage: fct2 (a, 2*a)5*a^2

Die Auswertung der Funktion wird durch den Befehl return beendet. Ihr Ergebnis ist hierx2 + y2.

Auf dieselbe Weise wird eine Funktion deniert, die nicht explizit ein Resultat zurückgibt, undbei Abwesenheit der Anweisung return wird der Funktionsrumpf bis zum Ende abgearbeitet.Dann wird der Wert None zurückgegeben.

In der Voreinstellung betrachtet Sage alle Variablen, die in der Funktion auftreten, als lo-kale Variablen. Diese Variablen werden bei jedem Aufruf der Funktion neu erzeugt und am

52

Page 69: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

Ende wieder zerstört. Sie sind unabhängig von anderen Variablen gleichen Namens, die auÿer-halb der Funktion existieren mögen. Globale Variablen werden durch Zuweisungen an lokaleVariablen innerhalb der Funktion nicht verändert:

sage: def versuch(u)....: t = u^2....: return t*(t+1)sage: t = 1; u = 2sage: versuch(3), t, u(90, 1, 2)

Um in einer Funktion eine globale Variable zu verändern, muss man sie mit dem Schlüsselwortglobal explizit deklarieren:

sage: a = b = 1sage: def f(): global a; a = b = 2sage: f(); a, b(2,1)

Das folgende Beispiel wiederholt die Berechnung des arithmetisch-harmonischen Mittels zweierpositiver Zahlen:

sage: def MittAH(u, v):....: u, v = min(u, v), max(u, v)....: while v-u > 2.0e-8:....: u, v = 2*u*v/(u+v), (u+v)/2....: return (u+v)/2

sage: MittAH(1., 2.)1.41421...sage: MittAH # entspricht einer Funktion

<function MittAH at ...>

Die Funktion MittAH erhält die beiden Parameter u und v, die lokal sind und deren An-fangswerte mit dem Aufruf der Funktion bestimmt sind; beispielsweise beginnt MittAH dieAusführung dieser Funktion mit den Werten 1. und 2. der Variablen u und v.

Bei strukturierter Programmierung soll eine Funktion so geschrieben werden, dass der Befehlreturn die letzte Anweisung des Funktionsrumpfes ist. In seinem Inneren plaziert beendet derBefehl return die Ausführung der Funktion und verhindert so die vollständige Ausführungdieses Blocks. Auÿerdem können verschiedene Zweige von if - elif - else - Konstruktio-nen jeweils mit return enden. Die Übertragung des Geistes der Mathematik auf die Informatiklegt nahe, Funktionen zu programmieren, die zu ihren Argumenten jeweils ein Resultat zu-rückgeben und dies nicht etwa durch einen print-Befehl bewerkstelligen. Das ProgrammpaketSage verfügt zudem über eine Vielzahl von Funktionen, beispielsweise exp oder solve, die alleein Ergebnis zurückgeben, eine Zahl zum Beispiel, einen Ausdruck, eine Liste von Lösungenusw.

Iterative und rekursive Verfahren. Eine vom Anwender denierte Funktion ist wie eineFolge von Anweisungen aufgebaut. Eine Funktion heiÿt rekursiv, wenn zu ihrer Auswertungin bestimmten Fällen erforderlich ist, diese Funktion mit verschiedenen Parametern mehrmalsauszuführen. Die Fakultät (n!)n∈N ist ein einfaches Beispiel:

0! = 1, (n+ 1)! = (n+ 1)n! für alle n ∈ N.

53

Page 70: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Die beiden folgenden Funktionen einer natürlichen Zahl liefern dasselbe Ergebnis, aber dieerste arbeitet iterativ und verwendet eine for-Schleife, während die andere die vorstehenderekursive Denition wortwörtlich umsetzt:

sage: def fact1(n):....: res = 1....: for k in [1..n]: res = res*k....: return reset

sage: def fact2(n):....: if n == 0: return 1....: else: return n*fact2(n-1)

Die Fibonacci-Folge ist eine rekursive Folge 2. Ordnung, denn der Wert un+2 hängt eindeutigvon den Werten u und un+1 ab:

u0 = 0, u1 = 1, un+2 = un+1 + un für alle n ∈ N.

Die Funktion fib1 hierunter verwendet bei der Berechnung der Glieder der Fibonaccifolge einiteratives Verfahren und arbeitet mit zwei Variablen U und V, um die beiden vorhergehendenWerte der Folge zwischenzuspeichern, bevor zum nächsten gegangen wird:

sage: def fib1(n):....: if n == 0 or n == 1: return n....: else:....: U = 0....: V = 1 # die Startwerte u0 und u1....: for k in [2..n]:....: W = U + V....: U = V....: V = W....: return Vsage: fib1(8)21

Ab n = 2 verarbeitet die Schleife die Beziehung un = un−1 + un−2. Des weiteren vermeidetdie parallele Zuweisung von U,V = V,U+V statt w = U+V; U = V; V = W die Einführung einerVariablen W und übersetzt die Iteration der rekursiven vektoriellen Folge Xn = (un, un+1) 1.Ordnung, die durch Xn+1 = f(Xn) deniert ist, wenn f(a, b) = (b, a + b) ist. Die iterativenVerfahren sind ezient, doch muss bei ihrer Programmierung die Denition der Folge an dieManipulation der Variablen angepasst werden

Im Gegensatz dazu folgt die rekursive Funktion fib2 der mathematischen Denition dieserFolge viel besser, was ihre Programmierung vereinfacht und das Verständnis verbessert:

sage: def fib2(n):....: if 0 <= n <= 1: return n # für n = 0 oder n = 1....: else: return fib2(n-1) + fib2(n-2)

Das Ergebnis dieser Funktion ist der von der bedingten Anweisung zurückgegebene Wert: 0und 1 für n = 0 bzw. n = 1 und sonst die Summe fib2(n-1)+fib2(n-2). Jeder Zweig desTests endet mit dem Befehl return.

54

Page 71: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

Dieses Verfahren ist zwar weniger ezient, denn viele Rechnungen werden unnötigerweisewiederholt. Zum Beispiel werden für fib2(5) auch fib2(3) und fib2(4) ausgewertet, dieebenso berechnet worden sind. Somit wertet Sage fib2(3) zweimal aus und fib2(2) dreimal.Dieser Prozess endet mit der Auswertung von fib2(1) oder fib2(0) und die Auswertung vonfib2(n) besteht schlieÿlich aus der Addition von un Einsen und un−1 Nullen. Die Gesamtzahlder Additionen ist daher gleich un+1 − 1. Diese Zahl ist von beträchtlicher Gröÿe und wächstsehr schnell. Kein Rechner, und sei er noch so schnell, kann auf diese Weise u100 berechnen.

Auch andere Verfahren sind möglich, beispielsweise mit Zwischenspeicherung dank dem Deko-rator @cached_function oder durch Ausnutzung einer Eigenschaft von Matrixpotenzen: derfolgende Abschnitt zum schnellen Potenzieren zeigt, wie der millionste Term dieser Folge zuberechnen ist.

3.2.4. Beispiel: schnelles Potenzieren

Eine naive Methode zur Berechnung von an besteht darin, in einer for-Schleife n ∈ N Multi-plikationen mit a auszuführen.

sage: a = 2; n = 6; res = 1 # 1 ist das neutrale Elementsage: for k in [1..n]: res = res*asage: res # Der Wert von res ist 2^664

Ganzzahlige Potenzen gibt es in der Mathematik in drei Zusammenhängen: dieser Abschnittuntersucht eine allgemeine Methode der Berechnung einer ganzzahligen Potenz an, die schnel-ler ist als die vorstehende. Die hiernach denierte Folge (un)n∈N veriziert un = an; manbeweist dieses Resultat durch Rekursion mittels dieser Gleichungen a2k = (ak)2 und ak+1 =aak:

un =

1 für n = 0,u2n/2 für gerades n > 0, (3.1)

aun−1 für ungerades n.

Beispielsweise ist für u11:

u11 = au10, u10 = u25, u5 = au4, u4 = u2

2,

u2 = u21, u1 = au0 = a;

und somit:

u2 = a2, u4 = u22 = a4, u5 = aa4 = a5,

u10 = u25 = a10, u11 = aa10 = a11.

Die Berechnung von un lässt nur Terme uk mit k ∈ 0, . . . , n− 1 auftreten und ist deshalbmit einer endlichen Anzahl von Operationen gut beschrieben.

Dieses Beispiel zeigt auÿerdem, dass man den Wert von u11 durch Auswertung der 6 Termeu10, u5, u4, u2, u1 und u0 erhält, was einzig mit 6 Multiplikationen erfolgt. Die Berechnungvon un erfordert zwischen log n/ log 2 und 2 log n/ log 2 Multiplikationen, denn nach einemoder zwei Schritten - jenachdem ob n gerade ist oder ungerade - wird un als Funktion von ukausgedrückt mit k ≤ n/2. Dieses Verfahren ist daher unvergleichlich schneller als die naiveMethode, sobald n groÿ ist; etwa 20 Terme für 104 und keine 104 Produkte:

55

Page 72: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

verarbeitete Indizes: 10000 5000 2500 1250 625 624 312 156 7839 38 19 18 9 8 4 2 1

Allerdings ist dieses Verfahren nicht immer das schnellste; die folgende Rechnung mit b, c, dund f braucht 5 Produkte, um a15 zu berechnen, obwohl das Verfahren mit u, v, w, x und y6 Multiplikationen erfordert ohne die Multiplikation mit 1:

b = a2 c = ab = a3 d = c2 = a6 f = cd = a9 df = a15 : 5 Produkte;

u = a2 v = au = a3 w = v2 = a6 x = aw = a7 y = x2 = a14 ay = a15 : 6 Produkte.

Die rekursive Funktion pot1 berechnet die rekursive Folge (3.1) nur mit den Multiplikationenzur Programmierung des Operators für die Erhebung zur Potenz:

sage: def pot1(a, n):....: if n == 0: return 1....: elif n % 2 == 0: b = pot1(a, n//2); return b*b....: else: return a*pot1(a, n-1)

sage: pot1(2,11) # a für das Resultat 2^112048

Die Anzahl der von dieser Funktion ausgeführten Operationen ist die gleiche wie die von Handberechnete, wenn die schon berechneten Resultate weiterverwendet werden. Wenn anderer-seits die Anweisungen b = pot1(a, n//2); return b*b, die nach der Prüfung von n aufGeradheit ausgeführt werden, durch pot1(a, n//2)*pot1(a, n//2) ersetzt würden, müssteSage weit mehr Rechnungen ausführen, weil wie bei der rekursiven Funktion fib2, welche dieFibonacci-Folge berechnet, etliche Berechnungen unnötigerweise wiederholt werden würden.Es gäbe letzten Endes n Multiplikationen, soviele wie mit dem naiven Verfahren.

Auÿerdem kann der Befehl return pot1(a*a, n//2) auf äquivalente Weise diese beiden An-weisungen ersetzen.

Das folgende Programm führt die gleiche Rechnung iterativ aus:

sage: def pot2(u, k):....: v = 1....: while k != 0:....: if k % 2 == 0: u = u*u; k = k//2....: else: v = v*u; k -= 1....: return v

sage: pot2(2, 10) # a für das Resultat 2^101024

Dass der Wert von pot2(a, n) tatsächlich an ist, wird dadurch bewiesen, dass die Variablenu, v und k bei jedem Schritt durch die Gleichung vuk = an verbunden sind, egal, ob k geradeoder ungerade ist. Im ersten Schritt ist v = 1, u = a und k = n; nach dem letzten Schritt istk = 0, also v = an.

Die aufeinander folgenden Werte von k sind sämtlich ganz und ≥ 0, und sie bilden eine strengfallende Folge. Diese Variable kann nur eine endliche Anzahl von Werten annehmen, bevor sie0 wird und die Schleife endet.

56

Page 73: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2. Algorithmik

Entgegen dem Augenschein - die Funktion pot1 ist rekursiv, die Funktion pot iterativ pro-grammiert - geben beide Funktionen nahezu den gleichen Algorithmus wieder: der einzigeUnterschied ist, dass die erste a2k durch (ak)2 auswertet, die zweite jedoch a2k durch (ak)2,wie die Modikation der Variablen u zeigt.

Dieses Verfahren ist nicht auf ganzzahlige Potenzen von Zahlen durch Multiplikation be-schränkt, sondern wird auf jedes Gesetzt der internen assoziativen Komposition angewendet.Dieses Gesetz muss assoziativ sein, um die üblichen Eigenschaften bei mehrmaliger Multipli-kation zu besitzen. Ersetzte man also die Zahl 1 durch die Einheitsmatrix In, würden beideFunktionen die positiven Potenzen quadratischer Matrizen auswerten. Diese Funktionen ver-deutlichen, wie der Potenz-Operator ^ mittels Multiplikationen ezient zu programmierenist, und sie ähneln dem in Sage implementierten Verfahren.

Beispielsweise ermöglicht eine Matrizenpotenz Terme der Fibonacci-Folge mit Indizes zu er-halten, die noch gröÿer sind als vorhin:

A =

(0 11 1

), Xn =

(unun+1

), AXn = Xn+1, AnX0 = Xn.

Das entsprechende Sage-Programm gibt sich mit zwei Zeilen zufrieden und das gesuchte Re-sultat ist der erste Eintrag des Matrizenproduktes AnX0, was selbst für n = 107 funktioniert;diese beiden Programme sind äquivalent und ihre Ezienz kommt daher, dass Sage eine Me-thode der schnellen Potenzierung verwendet:

sage: def fib3(n):....: A = matrix([[0,1],[1,1]]); X0 = vector([0,1])....: return (A^n*X0)[0]

sage: def fib4(n):....: return (matrix([[0,1],[1,1]])^n*vector([0,1]))[0]

3.2.5. Datenein- und -ausgabe

Die Anweisung print ist der Befehl zur Datenausgabe. Voreingestellt ist die Ausgabe derArgumente eines nach dem anderen und getrennt durch ein Leerzeichen; am Ende des Befehlsmacht Sage automatisch einen Zeilenvorschub:

sage: print 2^2, 3^3, 4^4; print 5^5, 6^64 27 2563125 46656

Ein Komma am Ende des Befehls print unterdrückt den Zeilenvorschub, und die nächsteprint-Anweisung wird auf der selben Zeile fortgesetzt:

sage: for k in [1..10]: print '+', k,+ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10

Es ist möglich, die Resultate ohne Zwischenraum auszugeben, indem sie mit der Funktionstr() in eine Zeichenkette umgewandelt und durch den Verkettungsoperator + verbundenwerden.

sage: print 10, 0.5; print 10+0.5; print 10.0, 510 0.500000000000000

57

Page 74: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

10.500000000000010.0000000000000 5sage: print 10+0, 5; print str(10)+str(0.5)10 5100.500000000000000

Der letzte Abschnitt dieses Kapitels über Listen und andere Datenstrukturen stellt Zeichen-ketten dann ausführlicher vor.

Der Befehl print ermöglicht auch Zahlen zu formatieren, um sie in eine Tabelle zu schreiben.Das folgende Beispiel mit dem Platzhalter %.d und dem Operator % gibt die Tabelle der 4. Po-tenzen eine untereinander aus: sage: for k in [1..6]: print '%2d^4 = %4d' % (k, k^4)1^4 = 12^4 = 163^4 = 814^4 = 2565^4 = 6256^4 = 1296

Der Operator % setzt die Zahlen zu seiner Rechten in die Zeichenkette zu seiner Linken ander durch %2d und %4d markierten Stelle ein. Dabei sorgt zum Beispiel %4d dafür, dass für dieZahl mindestens 4 Stellen reserviert werden, um noch für 6^4 Platz zu haben. Genauso gibtder Platzhalter %.4f in 'pi = %.4f' % n(pi) die Zeichenkette pi = 3.1416 mit vier Stellennach dem Dezimaltrenner aus.

Auf einem Terminal gibt die Funktion raw_input('message') den Text message aus, erwarteteine gültige Eingabe von der Tastatur, die mit einem Zeilenvorschub abgeschlossen wird undgibt die entsprechende Zeichenkette zurück.

3.3. Listen und zusammengesetzte Strukturen

Dieser Abschnitt behandelt die zusammengesetzten Datenstrukturen in Sage: Zeichenketten,Listen - veränderlichen oder unveränderlichen Typs -, Mengen und Diktionäre.

3.3.1. Denition von Listen und Zugri auf die Elemente

Der Begri der Liste ist in der Informatik das n-Tupel der Mathematik und ermöglicht dieAufzählung mathematischer Objekte. Der Begri des Paares - mit (a, b) 6= (ba) - und desn-Tupels präzisiert im Gegensatz zum Begri der Menge die Position jedes Elementes.

Wir denieren eine Liste, indem wir ihre Elemente getrennt durch Kommata in eckige Klam-mern setzen [. . .]. Die Zuweisung des Tripels (10, 20, 30) zur Variablen L wird auf folgendeWeise vorgenommen:

sage: L = [10, 20, 30]sage: L[10, 20, 30]

und die leere Liste, ohne Elemente, wird einfach so deniert:

58

Page 75: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

sage: [] # das ist die leere Liste[]

Die Listenelemente werden durch ganze Zahlen indiziert. Das erste Element hat den Index0, das zweite den Index 1 usw. Der Zugri auf das Element mit dem Index k einer Liste Lerfolgt durch L[k], mathematisch entspricht das der kanonischen Projektion der betrachtetenListe als Element eines kartesischen Produkts auf das Element der Ordnung k. Die Funktionlen gibt die Anzahl der Elemente einer Liste zurück6:

sage: L[1], len(L), len([])(20, 3, 0)

Die Modikation eines Eintrags gelingt auf die gleiche Weise, nämlich durch Zuweisung desentsprechen Eintrags. So verändert der folgende Befehl den mit 2 indizierten dritten Term derListe:

sage: L[2] = 33sage: L[20, 3, 33]

Mit negativen Indizes wird von hinten auf Listenelemente zugegrien, wobei das letzte Elementden Index -1 hat, das vorletzte den Index -2 usw.

sage: L = [11, 22, 33]sage: L[-1], L[-2], L[-3](33,22,11)

Der Befehl L[p:q] extrahiert die Teilliste [L[p], L[p+1], ..., L[q-1]], welche für q ≤ pleer ist. Negative Indizes ermöglichen das Herausziehen der hinteren Listenelemente; schlieÿlichbildet die Angabe L[p:] die Teilliste L[l:len(L)], beginnend beim Index p bis zum Ende,und L[:p]=L[0:p] zählt die Elemente der Liste vom Anfang bis vor das Element mit demIndex q auf:

sage: L = [0, 11, 22, 33, 44, 55]sage: L[2:4]22, 33sage: L[-4:4][22, 33]sage: L[2,-2]22,33 sage: L[:4][0, 11, 22, 33] sage: L[4:][44,55]

Genauso wie der Befehl L[n] = ... ein Element der Liste verändert, ersetzt die ZuweisungL[p:q] 0 ... die Teilliste zwischen den Elementen p (einschlieÿlich) und q (ausschlieÿlich):

sage: L = [0, 11, 22, 33, 44, 55, 66, 77]sage: L[2:6] = [12, 13, 14] # ersetzt [22, 33, 44, 55]

6Der Wert der Funktion len hat den Typ int von Python, der Ausdruck Integer(len(...)) gibt eine ganzeZahl des Typs Integer von Sage zurück.

59

Page 76: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

So unterdrücken L[:1] = [] und L[-1:] jeweils das erste bzw. das letzte Element einer Listeund umgekehrt setzen L[:0] = [a] und L[len(L):] = [a] jeweils ein Element a am Anfangbzw. am Ende der Liste ein. Generell erfüllen die Einträge einer Liste diese Gleichungen:

L = [l0, l1, l2, · · · , ln−1] = [l−n, l1−n, . . . , l−2, l−1] mit n = len(L),lk = lk−n für 0 ≤ k < n, lj = ln+j für −n ≤ j < 0.

Der Operator in testet, ob ein Element in einer Liste vorhanden ist. Sage prüft zwei Listenauf Gleichheit mit == und vergleicht die Elemente eins nach dem anderen. Die beidenTeillisten mit positiven bzw. negativen indizes sind gleich:

sage: L = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]sage: L[3:len(L)-5] == L[3-len(L):-5]Truesage: [5 in L, 6 in L][True, False]

Die obigen Beispiele betreen Listen mit ganzen Zahlen, doch können beliebige Sage-ObjekteElemente von Listen sein, Zahlen, Ausdrücke, andere Listen usw.

3.3.2. Globale Operationen auf Listen

Der Additionsoperator + bewirkt die Verkettung zweier Listen, und der Multiplikations-operator * bewirkt ein ganzzahliges Vielfaches dieser Verkettung:

sage: L = [1, 2, 3]; L + [10, 20, 30][1, 2, 3, 10, 20, 30]sage: 4*[1, 2, 3][1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

Die Verkettung der beiden Teillisten L[:k] und L[k:] bringt die ursprüngliche Liste zurück.Das erklärt, eshalb die linke Grenze mit dem Index p einer Teilliste L[p:q] eingeschlossen ist,die rechte Grenze q aber nicht:

L = L[:k] + L[k:] = [l0.l1, . . . , ln−1]= [l0, l1, l2, . . . , lk−1] + [lk, lk+1, lk+2, . . . , ln−1].

Das folgende Beispiel verdeutlicht diese Eigenschaft:

sage: L = 5*[10, 20, 30]; L[:3] + L[3:] == LTrue

Der aus zwei Punkten zusammengesetzte Operator .. automatisiert die Erstellung ganz-zahliger Listen, ohne ihre Elemente alle einzeln aufzuzählen. Das folgende Beispiel bildet eineListe, die aus Aufzählungen und aus isolierten Elementen besteht:

sage: 1..3, 7, 10..13[1, 2, 3, 7, 10, 11, 12, 13]

Nun wird beschrieben, wie das Bild einer Liste unter einer Funktion erzeugt wird und eineTeilliste einer Liste. Die zugehörigen Funktionen sind map und filter sowie die Konstruktion

60

Page 77: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

[.. for .. x .. in .. ]. In der Mathematik treten oft Listen auf, die aus Bildern unterder Funktion f ihrer Elemente bestehen:

(a0, a1, a2, . . . , an−1) 7→ (f(a0), f(a1), . . . , f(an−1)).

Der Befehl map erzeugt dieses Bild; das folgende Beispiel wendet die trigonometrische Funktioncos auf eine Liste häug gebrauchter Winkel an:

sage: map(cos, [0, pi/6, pi/4, pi/3, pi/2])[1, 1/2*sqrt(3), 1/2*sqrt(2), 1/2, 0]

Es ist auch möglich, eine vom Anwender mit def denierte Funktion zu verwenden oder mitlambda eine Funktion direkt zu deklarieren; der Befehl hierunter ist zum vorhergehendenäquivalent und benutzt die mit t 7→ cos t denierte Funktion:

sage: map(lambda t: cos(t), [0, pi/6, pi/4, pi/3, pi/2])[1, 1/2*sqrt(3), 1/2*sqrt(2), 1/2, 0]

Der Befehl lambda wird gefolgt von einem oder mehreren durch Kommata getrennten Para-metern und kann nach dem Doppelpunkt nur genau einen Ausdruck verarbeiten, der ohnereturn das Ergebnis liefert.

Diese lambda-Funktion kann zudem einen Test ausführen; die folgenden Funktionen sind äqui-valent:

fktTest1 = lambda x: res1 if cond else res2def fktTest2(x):

if cond; return res1else: return res2

Die folgenden drei map-Befehle sind äquivalent, die Hintereinanderausführung der FunktionenM cos geschieht auf mehrere Arten:

sage: map(lambda t: N(cos(t)), [0, pi/6, pi/4, pi/3, pi/2])[1.00000000000000, 0.866025403784439, 0.707106781186548,0.500000000000000, 0.000000000000000]

sage: map(N, map(cos, [0, pi/6, pi/4, pi/3, pi/2]))[1.00000000000000, 0.866025403784439, 0.707106781186548,0.500000000000000, 0.000000000000000]

sage: map(compose(N, cos), [0, pi/6, pi/4, pi/3, pi/2])[1.00000000000000, 0.866025403784439, 0.707106781186548,0.500000000000000, 0.000000000000000]

Der Befehl filter erzeugt eine Teilliste der Elemente, die eine Bedingung erfüllen. DiesesBeispiel wendet den Primzahltest is_prime auf die Zahlen 1, . . . , 55 an:

sage: filter(is_prime, [1..55])[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]

Die Test-Funktion kann auch im Inneren des Befehls filter deniert werden. Das Beispielhierunter bestimmt in erschöpfenden Tests alle vierten Wurzeln von 7 modulo der Primzahl37; diese Gleichung hat die vier Lösungen 3, 18, 19 und 34:

61

Page 78: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

sage: p = 37; filter(lambda n: n^4 % p == 7, [0..p-1])[3, 18, 19, 34]

Auÿerdem bildet der Befehl [.. for ,, x .. in ..] eine Listenraung (Listencomprehen-sion); diese beiden Befehle zählen auf äquivalente Weise die ungeraden Zahlen von 1 bis 31auf:

sage: map(lambda n: 2*n+1, [0..15])[1, 3, 5, 7, 9. 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]sage: [2*n+1 for n in [0..15]][1, 3, 5, 7, 9. 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]

Dieser Befehl ist vom Schleifenbefehl for unabhängig. Die mit for verbundene Bedingung ifführt zu einer Konstruktion, die zur Funktion filter äquivalent ist:

sage: filter(is_prime, [1..55])[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]sage: p for p in [1..55] if is_prime(p)[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]

Die beiden folgenden Beispiele kombinieren die Tests filter und for, um eine Liste vonPrimzahlen zu bestimmen, die zu 1 modulo 4 kongruent sind, dann eine Liste der Quadratevon Primzahlen:

sage: filter(is_prime, [4*n+1 for n in [0..20]])[5, 13, 17, 29, 37, 41, 53, 61, 73]sage: [n^2 for n in [1..20] if is_prime(n)][4, 9, 25, 49, 121, 169, 361]

Im ersten Fall wird der Test is_prime nach der Berechnung von 4n+ 1 ausgeführt, währendim zweiten Fall der Test vor der Berechnung des Quadrats n2 ausgeführt wird.

Die Funktion reduce bearbeitet die Elemente einer Liste assoziativ von links nach rechts.Denieren wir das Gesetz der internen Komposition mit :

x y = 10x+ y, wird ((1 2) 3) 4 = (12 3) 4 = 10 ∗ (10 ∗ (10 ∗ 1 + 2) + 3) + 4 = 1234.

Das erste Argument von reduce ist eine Funktion mit zwei Parametern und das zweite ist dieListe der Argumente:

sage: reduce(lambda x, y: 10*x+y, [1, 2, 3, 4])1234

Ein optionales drittes Argument wird vor das Ergebnis gestellt und dient bei einer leeren Listeals Ergebnis:

sage: reduce(lambda x, y: 10*x+y, [9, 8, 7, 6], 1)[19876]

Es entspricht allgemein dem neutralen Element der jeweiligen Operation. So berechnet dasnächste Beispiel ein Produkt von ungeraden Zahlen:

62

Page 79: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

sage: L = [2*n+1 for n in [0..9]]sage: reduce(lambda x, y: x*y, L, 1)654729075

Sages Funktionen add7 und prod verwenden den Operator reduce direkt zur Berechnung vonSummen und Produkten; das Produkt ist in den drei Beispielen hierunter jeweils das gleiche,und der Befehl mit einer Liste ermöglicht zudem, einen zweiten, optionalen Term als neutralesElement hinzuzufügen, 1 für das Produkt und 0 für die Summe oder eine Einheitsmatrix fürein Matrizenprodukt:

sage: prod([2*n+1 for n in [0..9]], 1) # eine Liste mit for654729075sage: prod(2*n+1 for n in [0..9])654729075sage: prod(n for n in [0..19] if n%2 == 1)654729075

Die Funktion any mit dem Operator or und die Funktion all mit dem Operator and sindgrundsätzlich äquivalent. Allerdings endet die Auswertung, sobald das Resultat True oderFalse eines der Terme dieses Resultat erheischt, ohne die Auswertung der folgenden Termezu beeinussen.

sage: def fkt(x): return 4/x == 2sage: all(fkt(x) for x in [2, 1, 0])False sage: any(fkt(x) for x in [2, 1, 0])True

Hingegen führen die Bildung der Liste [fkt(x) for x in [2, 1, 0]] und der Befehlall([fkt(x) for x in [2, 1, 0]]) zu Fehlern (rational division by zero), denn eswerden alle Terme ausgewertet, auch der letzte mit x = 0.

Das Verschachteln mehrerer for-Befehle ermöglicht die Bildung des kartesischen Produkteszweier Listen oder die Denition einer Liste von Listen. Das folgende Beispiel zeigt, dasswenn wir mehrere Operatoren for in derselben Denition in einer Raung kombinieren, deram weitesten links stehende der äuÿersten Schleife entspricht:

sage: [[x, y] for x in [1..2] for y in [6..8]][[1, 6], [1, 7], [1, 8], [2, 6], [2, 7], [2, 8]]

Die Reihenfolge der Schritte ist daher von derjenigen verschieden, die man durch Verschachtelnmehrerer Denitionen in einer Raung erhält.

sage: [[[x, y] for x in [1..2]] for y in [6..8]][[[1, 6], [2, 6]], [[1, 7], [2, 7]], [[1, 8], [2, 8]]]

Der Befehl map mit mehreren gleichlangen Listen als Argumenten geht in diesen Listen syn-chronisiert vor.

sage: map(lambda x, y: [x, y], [1..3], [6..8])[[1, 6], [2, 7], [3, 8]]

Schlieÿlich erlaubt der Befehl flatten Listen auf einer oder mehreren Ebenenen zu verket-ten:

7Nicht zu verwechseln mit sum, das für eine Summe einen symbolischen Ausdruck sucht.

63

Page 80: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

sage: L = [[1, 2, [3]], [4, [5, 6]], [7, [8, [9]]]]sage: flatten(L, max_level = 1)[1, 2, [3], 4, [5, 6], 7, [8, [9]]]sage: flatten(L, max_level = 2)[1, 2, 3, 4, 5, 6, 7, 8, [9]]sage: flatten(L) # äquivalent zu flatten(L, max_level = 3)[1, 2, 3, 4, 5, 6, 7, 8, 9]

Solche elementaren Manipulationen von Listen erweisen sich in anderen Zweigen von Sage alsnützlich; das folgende Beispiel berechnet Ableitungen von xex; das erste Argument von diffist der abzuleitende Ausdruck, der oder die folgenden entsprechen der Variablen, nach derabgeleitet werden soll, diese Parameter können auch die Liste der Variablen sein, nach denenabgeleitet werden soll:

sage: x = var('x')sage: factor(diff(x*exp(x), [x, x]))(x + 2)*e^xsage: map(lambda n: factor(diff(x*exp(x), n*[x])), [0..6])[x*e^x, (x + 1)*e^x, (x + 2)*e^x, (x + 3)*e^x, (x + 4)*e^x,(x + 5)*e^x, (x + 6)*e^x]sage: [factor(diff(x*exp(x), n*[x])) for n in [0..6]][x*e^x, (x + 1)*e^x, (x + 2)*e^x, (x + 3)*e^x, (x + 4)*e^x,(x + 5)*e^x, (x + 6)*e^x]

Der Befehl diff besitzt mehrere Syntaxen. Die Parameter, die der Funktion f folgen, könnensowohl die Liste der Ableitungsvariablen sein wie auch die Aufzählung dieser Variablen oderder Grad der Ableitung:

sage: diff(f(x), x, x, x), diff(f(x), [x, x, x]), diff(f(x), x, 3)

Wir können auch diff(f(x), 3) für Funktionen nur einer Variablen verwenden. Diese Re-sultate werden durch die Leibnizformel für mehrfache Ableitungen eines Produktes aus zweiTermen unmittelbar bestätigt, wobei die zweiten und höheren Ableitungen nach x null sind:

(xex)(n) =n∑k=0

(n

k

)x(k)(ex)(n−k) = (x+ n)ex.

3.3.3. Wichtige Methoden auf Listen

Die Methode reverse kehrt die Reihenfolge der Elemente einer Liste um, und die Methodesort ordnet die Elemente aufsteigend der Gröÿe nach:

sage: L = [1. 8, 5, 2, 9]: L.reverse(); L[9, 2, 5, 8, 1]sage: L.sort(); L1, 2, 5, 8, 9sage: L.sort(reverse = True); L[9, 8, 5, 2, 1]

Diese beiden Methoden verändern die Liste L, und der alte Wert ist verloren.

64

Page 81: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

Ein erstes optionales Argument bei sort ermöglicht die Auswahl der Ordnungsrelation in derForm einer Funktion Ordre(x, y) mit zwei Parametern. Das Resultat muss vom Typ intvon Python sein; es ist zum Beispiel -1, 0 oder 1, je nachdem ob x ≺ y, x = y oder x y.Die transformierte Liste (x0, x1, . . . , xn−1) erfüllt x0 x1 . . . xn−1.

Die lexikographische Ordnung der beiden Zahlenlisten gleicher Länge ist ähnlich der alphabe-tischen Ordnung und wird durch diese Äquivalenz deniert, wobei ersten Terme vernachlässigtwerden, sobald sie paarweise gleich sind:

P = (p0, p1, . . . , pn−1) ≺textlexQ = (Q0, Q1, . . . , qn−1)

⇐⇒ ∃r ∈ 0, . . . , n− 1 (p0, p1, . . . , pr−1) = (q0, q1, . . . , qr−1) und pr < qr.

Die folgende Funktion vergleicht zwei Listen, die gleich lang sein müssen. Trotz der End-losschleife while True verlassen die Befehle return diese Schleife direkt und beenden dieFunktion. Das Ergebnis ist -1, 0 oder 1 je nachdem, ob P ≺lex Q, P = Q oder P lex Q:

sage: def alpha(P, Q): # len(P) = len(Q) vorausgesetzt....: i = 0....: while True:....: if i == len(P): return int(0)....: elif P[i] < Q[i]: return int(-1)....: elif P[i] > Q[i]: return int(1)....: else: i = i+1sage: alpha([2, 3, 4, 6, 5], [2, 3, 4, 5, 6])1

Der folgende Befehl ordnet eine Liste von gleich langen Listen in lexikographischer Reihenfolge.Diese Funktion entspricht auÿerdem der in Sage für den Vergleich zweier Listen implemen-tierten Ordnung; der Befehl L.sort() ohne optionalen Parameter ist äquivalent:

sage: L = [[2, 2, 5], [2, 3, 4], [3, 2, 4], [3, 3, 3], [1, 1, 2], [1, 2, 7]]sage: L.sort(cmp=alpha); L[[1, 1, 2], [1, 2, 7], [2, 2, 5], [2, 3, 4], [3, 2, 4], [3, 3, 3]]

Die Denition der homogenen lexikographischen Ordnung besteht zunächst im Vergleich derTerme nach ihrem Gewicht vor Anwendung der lexikographischen Ordnung, wobei das Ge-wicht die Summe der Koezienten ist:

P = (p0, p1, . . . , pn−1) ≺lexH Q = (q0, q1, . . . , qn−1)

⇐⇒n−1∑k=0

pk <

n−1∑k=0

qk oder

(n−1∑k=0

pk =

n−1∑k=0

qk und P ≺lex Q

).

Der Code hierunter implementiert diese homogene Ordnung:

sage: def homogLex(P. Q):....: sp = sum(P); sq = sum(Q)....: if sp < sq: return int(-1)....: elif sp > sq: return int(1)....: elde: return alpha(P, Q)

sage: homogLex([2, 3, 4, 6, 4], [2, 3, 4, 5, 6])-1

65

Page 82: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Sages Funktion sorted ist eine Funktion im mathematischen Sinnes des Wortes; sie erhält alserstes Argument eine Liste und gibt, ohne sie zu verändern, als Resultat eine neue, geordneteListe zurück. Im Unterschied dazu ordnet die Methode sort die Liste in place.

Sage bietet noch andere Methoden für Listen, Einfügen eines Elements am Ende der Listeund Abzählen der Anzahl der Wiederholungen eines Elements:

L.append(x) ist äquivalent zu L[len(L):] = [x]L.extend(L1) ist äquivalent zu L[len(L):] = L1L.insert(i, x) ist äquivalent zu L[i:i] = [x]L.cont(x) ist äquivalent zu len(select(lambda t: t == x, L))

Die Befehle L.pop(i) und L.pop() löschen das mit i indizierte Objekt oder das letzte Elementeiner Liste und geben dieses Element zurück; die beiden Funktionen hierunter beschreibenjeweils ihre Wirkungsweise:

def pop1(L, i): def pop2(L):a = L[i] return pop1(L, len(L)-1)L[i:i+1] = []return a

Auÿerdem gibt L.index(x) den Index des ersten Terms zurück, der x gleicht, und L.remove(x)entfernt das erste Element mit dem Wert x aus der Liste. Diese Befehle führen zu einem Feh-ler, wenn x nicht in der Liste vorhanden ist. Schlieÿlich ist der Befehl del L[p:q] äquivalentzu L[p:q] = [], und del L[i] löscht das Element mit dem Index i.

Anders als in zahlreichen anderen Programmiersprachen modizieren diese Funktionen dieListe L, ohne eine neue Liste zu erzeugen.

3.3.4. Beispiele für Listenbearbeitung

Das folgende Beispiel erzeugt die Liste der geraden und die Liste der ungeraden Elementeeiner gegebenen Liste. Diese erste Lösung durchläuft die gegebene Liste zweimal und führtdiese Tests zweimal aus: sage: def fkt1(L):....: return [filter(lambda n: n % 2 == 0, L), filter(lambda n: n % 2 == 1, L)]

sage: fkt1([1..10])[[2, 4, 6, 8, 10], [1. 3, 5, 7, 9]]

Diese zweite Lösung durchläuft die Liste nur einmal und bildet die beiden Ergebnislisten nachund nach:

sage: def fkt2(L):....: res0 = []; res1 = []....: for k in L:....: if k%2 == 0: res0.append(k) # oder res0[len(res0):] = [k]....: else: res1.append(k) # oder res1[len(res1):] = [k]....: return [res0, res1]

Dieses Programm ersetzt die for-Schleife und die Hilfsvariablen durch einen rekursiven Aufrufund einen zusätzlichen Parameter:

66

Page 83: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

sage: def fkt3a(L, res0, res1):....: if L == []: return [res0, res1]....: elif L[0]%2 == 0: return fkt3a(L[1:], res0+[L[0]], res1)....: else: return fkt3a(L[1:], res0, res1+[L[0]])

sage: def fkt3(L): return fkt3a(L, [], [])

Die Parameter res0 und res1 enthalten die ersten schon gefundenen Elemente, und die Pa-rameterliste L verliert ein Element bei jedem rekursiven Aufruf.

Das zweite Beispiel hierunter extrahiert alle wachsenden Folgen einer Zahlenliste. Drei Varia-ble werden verwendet. Die erste, res, speichert die bereits erhaltenen wachsenden Folgen, dieVariable anfang bezeichnet die Position, wo die aktuelle wachsende Folge beginnt, und dieVariable k ist der Schleifenindex:

sage: def teilFolgen(L):....: if L == []: return []....: res = []; anfang = 0; k = 1....: while k < len(L): # 2 aufeinander folgende Elemente definiert....: if L[k-1] > L[k]:....: res.append(L[anfang:k]); anfang = k....: k = k+1....: res.append(L[anfang:k])....: return res

sage: teilFolgen([1, 4, 1, 5])[[1, 4], [1, 5]]sage: teilFolgen([4, 1, 5, 1])[[4], [1,5], [1]]

Der Schleifenrumpf erlaubt den Übergang zum nächten Element der Liste. Ist der Test positiv,dann endet die aktuelle wachsende Teilfolge und es muss zu einer neuen Teilfolge übergegangenwerden, sofern sie nicht durch das folgende Element verlängert wird.

Die Anweisung nach der Schleife fügt dem Endresultat die aktuelle wachsende Teilfolge hinzu,die mindestens ein Element besitzt.

3.3.5. Zeichenketten

Zeichenketten werden in einfache '...' oder doppelte "..." Anführungszeichen eingeschlos-sen. Zeichenketten in einfachen Anführungszeichen können doppelte Anführungszeichen ent-halten und umgekehrt. Zeichenketten können auch von dreifachen Hochkommata '''...'''begrenzt werden, können dann auch mehrere Zeilen umfassen und einfache oder doppelteAnführungszeichen enthalten.

sage: S = 'Dies ist eine Zeichenkette.'

Das Zeichen \ ermöglicht einen Zeilenvorschub mit \n, Anführungszeichen mit \" oder mit\', das TAB-Zeichen ist \t und das ESC-Zeichen ist \\. Die Zeichenketten können auchBuchstaben mit Akzenten enthalten und ganz generell beliebige Unicode-Zeichen.

sage: S = 'Ceci est une chaîne de charactères.'; S'Ceci est une cha\xc3\xaene de charact\xc3\xa8res.'

67

Page 84: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

sage: print SCeci est une chaîne de charactères.

Der Vergleich von Zeichenketten erfolgt zeichenweise anhand des Codes der Zeichen. Die Längeeiner Kette erhält man mit der Funktion len, und die Verkettung wird durch die Operatorender Addition + und der Multiplikation * bewirkt.

Der Zugri auf eine Teilkette von S funktioniert wie bei Listen mit eckigen Klammern S[n],S[p:q], S[p:], S[:q], und das Ergebnis ist eine Zeichenkette. Die Sprache erlaubt aberkeine Veränderung der ursprünglichen Zeichenkette durch eine Zuweisung dieser Form, ausdiesem Grund wird der Typ der Zeichenketten als immutabel bezeichnet.

Die Funktion str wandelt ihr Argument in eine Zeichenkette um. Die Methode split zerlegteine Zeichenkette an den Leerzeichen in eine Liste von Teilketten.

sage: S = 'eins zwei drei vier fünf sechs sieben'; L = S.split(); L['eins', 'zwei', 'drei', 'vier', 'f\xc3\xbcnf', 'sechs', 'sieben']

Die recht vollständige Python-Bibliothek re unterstützt reguläre Ausdrückereguläre Aus-drücke und kann für die Suche nach Teilketten und für die Mustererkennung ebenfalls ver-wendet werden.

3.3.6. Teilen und Verdoppeln einer Struktur

Eine Liste in eckigen Klammer [...] kann durch Zuweisungen zu ihren Elemente, durch dieÄnderung der Anzahl ihrer Elemente oder mit Methoden wie sort oder reverse modiziertwerden.

Die Zuweisung einer vorhandenen Liste zu einer weiteren Variablen verändert die Strukturnicht, beide Listen haben Teil an denselben Daten. Im folgenden Beispiel bleiben die Listen L1und L2 identisch; sie entsprechen zwei Alias-Namen desselben Objektes, und eine Veränderungder einen zeigt sich auch bei der anderen:

sage: L1 = [11, 22, 33]; L2 = L1sage: L1[1] = 222; L2.sort(); L1, L2[11, 33, 222], [11, 33, 222]sage: L1[2:3] = []; L2[0:0] = [6, 7, 8]sage: L1, L2([6, 7, 8, 11, 33], [6, 7, 8, 11, 33])

Im Gegensatz dazu sind die Werte von map, mit L[p:q], filter oder .. for ... if .. er-zeugte Teillisten, Verkettungen mit + und * und Abachungen mit flatten neue Strukturen,sodass von einer Verdoppelung der Daten gesprochen werden kann.

Im vorstehenden Beispiel verändert die Ersetzung von L2 = L1 in der ersten Zeile durcheinen der sechs Befehle hierunter die Ergebnisse komplett, denn die Modikationen einerListe wirken sich auf die andere nicht aus. Beide Strukturen bleiben unabhängig, beide Listensind verschieden, selbst wenn ihre Werte gleich sind. So kopiert die Zuweisung L2 = L1[:]die Liste L1 vom ersten bis zum letzten Eintrag und verdoppelt daher die Struktur von L1:

L1 = [11, 22, 33] L2 = copy(L1) L2 = L1[:]L2 = [] + L1 L2 = L1 + [] L2 = 1*L1

68

Page 85: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

Der Test auf geteilte Strukturen von Sage wird durch den binären Operator is bewirkt; ist dasErgebnis des Tests wahr, dann wirken alle Modikationen auf beide Variablen auf einmal:

sage: L1 = [11, 22, 33]; L2 = L1; L3 = L1[:]sage: L1 is L2, L2 is L1, L1 is L3, L1 == L3[True, True, False, True]

Die Kopieroperationen arbeiten nur auf einer Listenebene. So panzt sich die Änderung imInnern einer Liste von Listen fort trotz der Kopie der ersten Ebene der Struktur:

sage: La = [1, 2, 3]; L1 = [1, La]; L2 = copy(L1)sage: L1[1][0] = 5 # [1, [5, 2, 3]] für L1 und L2sage: [L1 == L2, L1 is L2, L1[1] is L2[1]][True, False, True]

Die folgende Anweisung kopiert die Struktur mit beiden Ebenen:

sage: map(copy, L)

während die Funktion copyRec die Liste mit allen Ebenen rekursiv kopiert:

sage: def copyRec(L):....: if type(L) == list: return map(copyRec, L)....: else: return L

Die inverse lexikographische Ordnung ist als lexikographische Ordnung auf umgekehrt aufge-zählten n-Tupeln dadurch deniert, dass die Reihenfolge für jedes Element umgekehrt wird:

P = (p0, p1, . . . , pn−1) ≺lexInv Q = (q0, q1, . . . , qn−1)

⇐⇒∃r ∈ 0, . . . , n− 1 , (pr+1, . . . , pn−1) = (qr+1, . . . , qn−1) und pr > qr.

Die Programmierung der inversen lexikographischen Ordnung kann mittels der in Unterab-schnitt 3.3.3 denierten Funktion alpha erfolgen, welche die lexikographische Ordnung imple-mentiert. Das Kopieren der Listen P und Q ist erforderlich, um die Inversion durchzuführen,ohne die Daten zu verändern. Genauer gesagt kehrt die Funktion lexInverse die Reihen-folge der n − Tupel mit reverse um und gibt die endgültige Reihenfolge mit dem Ergebnis−(P1 ≺lex Q1) zurück:

sage: def lexInverse(P, Q):....: P1 = copy(P); P1.reverse()....: Q1 = copy(Q); Q1.reverse()....: return -alpha(P1, Q1)

Die Modikationen einer als Argument einer Funktion übergebenen Liste wirken sich globalauf die Liste aus, denn die Funktionen kopieren nicht die Struktur der als Argument überge-benen Listen. So modiziert eine Funktion, die einzig P.reverse() statt P1 = copy(P) undP1.reverse() ausführt, die Liste P ; dieser Eekt, der Nebenwirkung8 genannt wird, ist imallgemeinen unerwünscht.

Die Variable P ist eine lokale Variable der Funktion und unabhängig von anderen globalenVariablen gleichen Namens, doch das hat mit den Modikationen nichts zu tun, die im Innereneiner als Argument übergebenen Liste vorgenommen werden.

8engl. side eect, wird ebenso häug wie falsch mit Seiteneekt übersetzt

69

Page 86: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

Listen - ein Begri, den Python und Sage verwenden - sind in diesen Systemen tatsächlichin der Form dynamischer Tabellen implementiert und haben eine andere Struktur als in Lispoder in OCaml, wo sie durch ein Kopfelement t und eine Schwanzliste Q deniert sind. Derelementare Lispbefehl cons(t,Q) gibt eine Liste mit dem Term t als Kopf zurück, ohne dieListe Q zu verändern; in Python dagegen verändert das Hinzufügen eines Elementes e zueiner Tabelle T durch T.append(e) die Tabelle T . Beide Repräsentationen der Daten habenihre Vorteile, und der Übergang von einer Darstellung zur anderen ist möglich, doch ist dieEzienz der Algorithmen in den beiden Fällen nicht dieselbe.

3.3.7. Veränderbare und nicht veränderbare Daten

Listen erlauben Daten zu strukturieren und zu manipulieren, weil sie veränderbarbar sind.Aus diesem Grund werden diese Strukturen als modizierbar oder mutabel eingestuft.

Python ermöglicht auch die Denition von festen oder immutablen Daten. Die immutableStruktur, die Listen entspricht, sind Tupel, die in runden Klammern (...) geschrieben werdenanstatt in eckigen [...]. Ein Tupel mir einem einzigen Element wird mit einem Komma hinterdiesem Eintrag geschrieben.

sage: S0 = (); S1 = (1, ); S2 = (1, 2)sage: [1 in S1, 1 == (1)][True, True]

Die Operationen des Zugris auf Tupel sind die gleichen wie die für Listen, beispielsweise dieErzegung des Abbildes eines Tupels durch map oder eines Teiltupels durch filter. In allendiesen Fällen ist das Ergebnis eine Liste, und mit for transformieren wir ein Tupel in eineListe.

sage: S1 = (1, 4, 9, 16, 25); [k for k in S1][1, 4, 9, 16, 25]

Der Befehl zip gruppiert mehrere Listen oder Tupel um, genau wie der Befehl map:

sage: L1 = [0..4]; L2 = [5..9]sage: zip(L1, L2)[(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]sage: map(lambda x, y: (x, y), L1, L2)[(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]

3.3.8. Endliche Mengen

Anders als bei Listen kommt es bei Mengen nur darauf an, ob ein Element vorhanden ist odernicht. Weder ist seine Position deniert noch wie oft es vorkommt. Sage kann endliche Mengenmittels der Funktion Set aus Listen erzeugen. Das Ergebnis wird in geschweifte Klammerneingeschlossen:

sage: E = Set([1, 2, 4, 8, 2, 2, 2]); F = Set([7, 5, 3, 1]); E, F(8, 1, 2, 4, 1, 3, 5, 7)

70

Page 87: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

Der Operator des Enthaltensein in testet, ob ein Objekt Element der Menge ist, und Sageerlaubt die Vereinigung zweier Mengen mit + oder |, ermittelt ihre Schnittmenge mit &, ihreDierenz mit − und ihre symmetrische Dierenz mit ^^:

sage: 5 in E, 5 in F, E + F == E F|(False, True, True)sage: E & F, E - F, E ^^ F(1, 8, 2, 4, 2, 3, 4, 5, 7, 8)

Die Funktion len(E) gibt die Kardinalität einer endlichen Menge zurück. Die Operationenmap, filter und for .. if .. nden auf Mengen genauso Anwendung wie für Tupel. DieErgebnisse sind Listen. Der Zugri auf ein Element erfolgt mit E[k]. Die beiden Befehlehierunter bilden jeweils die gleiche Liste von Elementen einer Menge:

sage: [E[k] for k in [0..len(E)-1]], [t for t in E][8, 1, 2, 4], [8, 1, 2, 4]

Die folgende Funktion testet die Inklusion, das Enthaltensein einer Menge E in einer anderenMenge F mittels der Vereinigung:

sage: def inklus(E, F): return E+F == F

Anders als Listen sind Mengen von immutablem Typ und somit nicht modizierbar; auch ihreElemente müssen immutabel sein. Es sind also Mengen von Tupeln und Mengen von Mengenmöglich, wir können aber keine Mengen von Listen bilden:

sage: Set([Set([]), Set([1]), Set([2]), Set([1, 2])])1, 2, , 2, 1sage: Set([(), (1,), (2,), (1, 2)])(1, 2), (2,), (), (1,)

Diese Funktion zählt mit einem rekursiven Verfahren alle Teilmengen einer Menge auf:

sage: def TeilM(EE):....: if EE == Set([]): return Set([EE])....: else: return mitOderOhneElt(EE[0], TeilM(Set(EE[1:])))

sage: def mitOderOhneElt(a, E):....: return Set(map(lambda F: Set([a])+F, E)) + E

sage: TeilM(Set(1, 2, 3))3, 1, 2, , 2, 3, 1, 1, 3, 1, 2, 3, 2

Die Funktion mitOderOhneElt(a, E) nimmt eine Menge E von Teilmengen und bildet eineMenge, die zweimal mehr Elemente hat, die ihrerseits Teilmengen sind und denen das Elementa hinzugefügt ist. Die rekursive Erzeugung beginnt mit der einelementigen Menge E = 0.

71

Page 88: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Programmierung und Datenstrukturen

3.3.9. Diktionäre

Schlieÿlich integriert Python, und damit Sage, den Begri des Diktionärs (Dictionary). Wieein Telefonbuch ordnet ein Diktionär jedem Eintrag einen Wert zu.

Die Einträge eines Diktionärs sind Unveränderliche beliebigen Typs, Zahlen, Zeichenketten,Folgen usw. Die Syntax ist der von Listen vergleichbar, auÿer dass das leere Diktionär dict()als abgekürzt werden kann.

sage: D = ; D['eins'] = 1, D['zwei'] = 2, D['drei'] = 3; D['zehn'] = 10sage: D['zwei'] + D['drei']5

Das vorstehende Beispiel sagt also, wie ein neuer Eintrag in ein Diktionär eingefügt wird, undwie auf ein Feld mit D[...] zugegrien wird.

Der Operator in prüft, ob ein Eintrag in einem Diktionär enthalten ist und die Befehledel D[x] oder D.pop(x) liefern den Eintrag x dieses Diktionärs.

Das folgende Beispiel zeigt, wie ein Diktionär eine Anwendung auf einer endlichen Mengedarstellen kann:

E = a0, a1, a2, a3, a4, a5 , f(a0) = b0, f(a1) = b1, f(a2) = b2f(a3) = b0, f(a4) = b3, f(a5) = b3.

Die Methoden der Diktionäre sind mit denen der anderen aufzählenden Strukturen vergleich-bar. Der untenstehende Code implementiert die vorstehende Funktion und erzeugt die Deniti-onsmenge E und die Bildmenge Im f = f(E) mittels der Methoden keys() und values():

sage: D = 'a0':'b0', 'a1':'b1', 'a2':'b2', 'a3':'b0', 'a4':'b3', 'a5':'b3'sage: E = Set(D.keys()); Imf = Set(D.values())sage: Imf == Set(map(lambda t:D[t], E)) # ist äquivalent True

Der letzte Befehl überträgt die mathematische Denition Im f = f(x)|x ∈ E. Diktionärekönnen auch aus Listen oder Paaren [Schluessel,Wert] durch den folgenden Befehl erzeugtwerden:

dict(['a0','b0'], ['a1','b1'], ...).

Die beiden folgenden Befehle, die auf die Einträge des Diktionärs oder auf das Diktionär selbstangewendet werden, sind mit der Methode D.values() äquivalent:

map(lambda t:D[t], D) map(lambda t:D[t], D.keys())

Der folgende Test auf die Anzahl der Elemente bestimmt mit len(D) die Anzahl der Einträgeim Diktionär, falls die durch D dargestellte Funktion injektiv ist,

sage: def injektiv(D):....: return len(D) == len(Set(D.values()))

Die ersten beiden Befehle hierunter erzeugen das Bild f(F ) und das Urbild f−1(G) der Teil-mengen F und G einer durch das Diktionär D denierten Funktion; die letztere deniert

72

Page 89: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.3. Listen und zusammengesetzte Strukturen

ein Diktionär DR, das der Urbildfunktion f−1 einer als bijektiv vorausgesetzten Funktion fentspricht:

sage: Set([D[t] for t in F])sage: Set([t for t in D if D[t] in G])sage: DR = dict((D[t], t) for t in D)

73

Page 90: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 91: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Die Veranschaulichung von Funktionen zweier oder dreier Veränderlicher oder einer Datenreiheerleichtert das Verständnis mathematischer oder physikalischer Phänomene und ermöglicht,Resultate eektiv zu mutmaÿen. In diesem Kapitel illustrieren wir anhand von Beispielen diegraphischen Fähigkeiten von Sage.

4.1. Kurven in 2D

Eine ebene Kurve kann auf mehrere Arten deniert werden: als Graph einer Funktion einerVeränderlichen, durch ein System parametrisierter Gleichungen, durch eine Gleichung in Po-larkoordinaten oder durch eine implizite Gleichung. Diese vier Fälle stellen wir vor, danachgeben wir einige Beispiele für die Veranschaulichung von Daten.

4.1.1. Graphische Darstellung von Funktionen

Um den Graphen einer symbolischen Funktion oder einer Python-Funktion auf einem Intervall[a, b] zu zeichnen, verfügen wir über zwei Möglichkeiten: plot(f(x),a,b) oderplot(f(x),x,a,b).

sage: plot(x*sin(1/x), x, -2, 2, plot_points=500)

Von den zahlreichen Optionen der Funktion plot nennen wir

• plot_points (voreingestellt 200): Mindestzahl der berechneten Punkte;

• min und max: Grenzen des Intervalls, auf dem die Funktion gezeichnet wird;

• color: Farbe der Zeichnung, ein RGB-Tripel, eine Zeichenkette, z.B. 'blue' oder eineHTML-Farbe (z.B. '#aaff0b';

• detect_poles (voreingestellt False): erlaubt oder verbietet das Einzeichnen einer ver-tikalen Asymptote an den Polstellen einer Funktion;

• alpha: Transparenz des Striches;

• thickness: Strichstärke;

• linestyle: Linienart, punktiert: (':'), strichpunktiert: ('-.') oder durchgezogen('-'), der voreingestellte Wert.

75

Page 92: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Abb. 4.1 - Graph von x 7→ x sin1

x

Um die Zeichnung sichtbar zu machen, können wir das graphische Objekt einer Variablenzuweisen, sagen wir g, und dann die Methode show benutzen, der beispielsweise die minimalenund maximalen Werte der Ordinate übergeben werden können (g.show(ymin=-1,ymax=3))oder auch eine bestimmte Streckung wie (g.show(aspect_ratio=1)) für ein orthonormiertesKoordinatensystem.

Die fertige Zeichnung kann mit dem Befehl save in unterschiedlichen Formaten exportiert wer-den, die durch die Erweiterungen .pdf, .png, .ps, .eps, .svg und .sobj gekennzeichnetsind:

g.save(name.png, aspect_ratio=1, xmin=-1,ymin=3, ymin=-1, ymax=3)

Um eine Graphik mit dem Befehl \includegraphics in ein LATEX-Dokument einzufügen,wird die Erweiterung .eps gewählt (encapsulated PostScript), wenn das Dokument mit latexkompiliert wird, oder die Erweiterung .pdf (die wegen der besseren Auösung der Erweiterung.png vorzuziehen ist), wenn das Dokument mit pdflatex kompiliert wird.

Zeichnen wir nun in dieselbe Graphik die Sinusfunktion und die ersten Polynome der Taylor-entwicklung um den Ursprung:

sage: def p(x, n):....: return (taylor(sin(x), x, 0, n))sage: xmax=15; n=15sage: g=plot(sin(x), x, -xmax, xmax)sage: for d in range(n):....: g += plot(p(x, 2*d + 1), x, -xmax, xmax, \....: color=(1.7*d/(2*n), 1.5*d/(2*n), 1.3*d/(2*n)))sage: g.show(ymin=-2, ymax=2)

Man hätte auch eine Animation erzeugen können, um zu sehen, wie das Taylor-Polynom sichmit der Erhöhung des Grades der Sinuskurve mehr und mehr annähert. Möchte man eineAnimation sehen, genügt dafür die Speicherung als gif-Datei.

76

Page 93: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

Abb. 4.2 - Einige Taylor-Polynome der Sinusfunktion um den Ursprung

sage: a = animate([sin(x), taylor(sin(x), x, 0, 2*k+1)]\....: for k in range(0, 14)], xmin=-14, xmax=14),\| ....: ymin=-3, ymax=3, figsize=[8, 4])sage: a.show(); a.save('~/bin/animation.gif')

Kehren wir zur Funktion plot zurück, um beispielsweise das Phänomen von Gibbs zu beob-achten. Wir zeichnen die Partialsumme der Ordnung 20 der Fourierreihe für die Rechteckkur-ve.

sage: f2(x) = 1; f1(x) = -1sage: f = piecewise([[(-pi,0),f1], [(0,pi),f2]])sage: S = f.fourier_series_partial_sum(20,pi)sage: g = plot(S, x, -8, 8, color='blue')sage: scie(x) = x - 2*pi*floor((x + pi)/(2*pi))sage: g += plot(scie(x)/abs(scie(x)), x, -8, 8, color='red')sage: g

Abb. 4.3 - Zerlegung einer Rechteckfunktion in eine Fourierreihe

Mit obigem Code ist f eine mit Hilfe des Befehls piecewise stückweise denierte Funktion auf[−π;π]. Um die Verlängerung von f auf die mit 2π periodische Funktion zu bewirken, ist es am

77

Page 94: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

einfachsten, dafür einen Ausdruck zu suchen, der für alle reellen Zahlen (im Denitionsbereichvon scie/abs(scie)) deniert ist. Die ersten 20 Terme der Fourierreihe sind

S =1

π

(sin(x) +

sin(3x)

3+

sin(5x)

5+ . . .+

sin(19x)

9

).

4.1.2. Kurven in Parameterdarstellung

Kurven in Parameterdarstellung (x = f(t), y = g(t)) werden mit dem Befehlparametric_plot((f(t), g(t)), (t, a, b)) gezeichnet, wobei [a, b] das Intervall ist, dasder Parameter durchläuft. Stellen wir beispielsweise diese Kurve dar:

x(t) = cos(t) + 12 cos(7t) + 1

3 sin(17t)y(t) = sin(t) + 1

2 sin(7t) + 13 cos(17t)

sage: t = var('t')sage: x = cos(t) + cos(7*t)/2 + sin(17*t)/3sage: y = sin(t) + sin(7*t)/2 + cos(17*t)/3sage: g = parametric_plot((x, y), (t, 0, 2*pi))sage: g.show(aspect_ratio=1)

Abb. 4.4 - Kurve in Parameterdarstellung für x = cos(t) + 12

cos(7t) + 13

sin(17t) und

y = sin(t) + 12

sin(7t) + 13

cos(17t)

78

Page 95: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

4.1.3. Kurven in Polarkoordinaten

Kurven in Polarkoordinaten ρ(θ) werden mit dem Befehl polar_plot(rho(theta),(theta, a, b)) gezeichnet, wobei [a, b] das Intervall ist, das vom Parameter durchlaufenwird.

Stellen wir beispielsweise zwei Rosetten mit der Polargleichung ρ(θ) = 1 + e cosnθ dar mitn = 20/19 und e ∈ 2, 1/3.

sage: t = var('t'); n = 20/19sage: g1 = polar_plot(1+2*cos(n*t),(t,0,n*36*pi),plotpoints=5000)sage: g2 = polar_plot(1+1/3*cos(n*t),(t,0,n*36*pi),plot_points=5000)sage: g1.show(aspect_ratio=1); g2.show(aspect_ratio=1)

Abb. 4.5 - Rosetten der Gleichung ρ(θ) = 1 + e cosnθ

Übung 12. Darzustellen ist eine Familie von Pascalschen Schnecken mit der Polargleichungρ(θ) = a + cos θ, wobei der Parameter a zwischen 0 und 2 mit einer Schrittweite von 0.1 zuvariieren ist.

4.1.4. Durch implizite Gleichungen denierte Kurven

Zur Darstellung einer Kurve, die durch eine implizite Gleichung gegeben ist, verwenden wirdie Funktion implicit_plot(f(x, y), (x, a, b), (y, c, d)); allerdings können wir auchden Befehl complex_plot verwenden, der die Veranschaulichung einer Funktion von zwei Ver-änderlichen mit farbigen Niveaulinien ermöglicht. Wir wollen die durch die implizite GleichungC =

z ∈ C : |cos(z4)| = 1

gegebene Funktion darstellen.

sage: z = var('z')sage: g1 = complex_plot(abs(cos(z^4))-1,....: (-3,3), (-3,3), plot_points=400)sage: f = lambda x, y: (abs((cos(x +I*y)^4)) - 1)sage: g2 = implicit_plot(f, (-3,3), (-3,3), plot_points=400)sage: g1.show(aspect_ratio=1); g2.show(aspect_ratio=1)

79

Page 96: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

4.1.5. Die Darstellung von Daten

Zum Zeichnen eines Säulendiagramms verfügen wir über zwei ganz unterschiedliche Funktio-nen. Zuerst der Befehl bar_chart, der als Argument eine Liste ganzer Zahlen aufnimmt undeinfach senkrechte Säulen zeichnet, deren Höhe durch die Elemente der Liste gegeben ist (inderselben Reihenfolge wie in der Liste). Halten wir fest, dass die Option width gestattet, dieBreite der Säulen festzulegen.

Abb. 4.6 - Durch die Gleichung |cos(z4)| = 1 denierte Funktion

sage: bar_chart([randrange(15) for i in range(20)])sage: bar:chart([x^2 for x in range(1,20)], width=0.2)

Abb. 4.7 - Säulendiagramme

Wenn hingegen für eine Liste von Flieÿkommazahlen das Histogram einer Häugkeitsvertei-lung zu zeichnen ist, verwenden wir die Funktion plot_histogram: die Werte der Liste werdensortiert und in Intervalle eingeteilt (die Anzahl der Intervalle wird durch die Variable binsfestgelegt, deren Gröÿe mit 50 voreingestellt ist). Die Höhe der Säule jedes Intervalls gleichtder entsprechenden Häugkeit.

80

Page 97: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

sage: liste = [10 + floor(10*sin(i)) for i in range(100)]sage: bar_chart(liste)sage: finance.TimeSeries(liste).plot_histogram(bins=20)

(a) gezeichnet mit bar_chart (b) gezeichnet mit plot_histogram

Oft sind die zu untersuchenden statistischen Daten in einem Arbeitsblatt einer Tabellenkal-kulation gespeichert. Das Python-Modul csv ermöglicht dann den Import der Daten aus einercsv-Datei. Nehmen wir beispielsweise an, wir wollen ein Histogramm für die Zensuren von 40Schülern berechnen. Die Punkte (französisches Benotungsystem) verteilen sich folgenderma-ÿen (obere Zeile: erreichte Punkte, untere Zeile: Anzahl der Schüler mit dieser Punktzahl):

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 200 1 0 0 4 0 1 0 8 4 7 5 3 3 0 1 1 1 0 0 1

Die Punkte jedes Schülers werden in die dritte Spalte der Tabellenkalkulation eingetragen.Das Arbeitsblatt wird in der Datei ds01.csv gespeichert, wobei darauf zu achten ist, dassbeim Speichern als csv-Dokument als Trennelemente Kommas ausgewählt werden.

Um die Punkte in dieser Spalte auszulesen, arbeiten wir mit folgenden Anweisungen (dieoberste Zeile enthält normalerweise Text, sodass eventuelle Fehler bei der Umwandlung inZahlen mit der Anweisung try aufgefangen werden müssen):

sage: import csvsage: reader = csv.reader(open("ds01.csv"))sage: noten = []; liste = []sage: for zeile in reader:.....: noten.append(zeile[2]) # die dritte Spalte hat den Index 2....: for i in noten:....: try:....: f = float(i)....: except ValueError:....: pass....: else:....: liste.append(f)sage: finance.TimeSeries(liste).plot_histogram(bins=20)

81

Page 98: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Um eine Liste verbundener Punkte (bzw. eine Punktwolke) zu zeichnen, verwenden wir denBefehl line(p) (bzw. point(p)), wobei p eine Liste von zweielementigen Listen ist, die Ab-szisse und Ordinate der zu zeichnenden Punkte enthalten.

Beispiel (Zufallsbewegung). Ausgehend von einem Startpunkt O verschiebt sich ein Teilchenum den Betrag l in gleichbleibenden Zeitspannen t jedes Mal in eine beliebige Richtung,die von den vorigen Richtungen unabhängig ist. Wir wollen die Spur eines solchen Teilchensbeispielhaft aufzeichnen. Die rote Gerade verbindet Start- und Endpunkt.

sage: from random import *sage: n, l, x, y = 1000, 1, 0, 0; p = [[0,0]]sage: for k in range(n):....: theta = (2*pi*random()).n(digits=5)....: x, y = x + l*cos(theta), y + l*sin(theta)....: p.append([x,y])sage: g1 = line([p[n], [0,0]], color='red', thickness=2)sage: g1 += line(p, thickness=.4); g1.show(aspect_ratio=1)

Abb. 4.8 - Zufallsweg

Beispiel (Gleichverteilte Folgen). Für eine gegebene reelle Folge (un)n∈N∗ konstruieren wirden Polygonzug, dessen aufeinander folgende Ecken die Punkte des Ausdrucks

zN =∑n≤N

e2iπun .

sind. Ist die Folge gleichverteilt modulo 1, entfernt sich die gebrochene Linie nicht zu schnellvom Startpunkt. Wir können dann aus der Spur der gebrochenen Linie die Regelmäÿigkeitder Verteilung der Folge vermuten. Wir wollen den Polygonzug für folgende Fälle zeichnen:

82

Page 99: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

- un = n√

2 und N = 200,

- un = n ln(n) und N = 10000,

- un = E(n ln(n))√

2 und N = 10000 (wobei E den ganzzahligen Anzeil bezeichnet),

- un = pn√

2 und N = 10000 (hier ist pn die n-te Primzahl).

Die Abb. 4.9 erhält man auf folgende Weise (hier für un = n√

2):

sage: length = 200; n = var('n')sage: u = lambda n: n*sqrt(2)sage: z = lambda n: exp(2*I*pi*u(n)).n()sage: vertices = [CC(0, 0)]sage: for n in range(1, length):....: vertices.append(vertices[n-1] + CC(z(n)))sage: line(vertices).show(aspect_ratio=1)

Man bememerkt, dass die Zeichnung Abb. 4.9 (a) besonders regelmäÿig ist. Das ermöglichtuns voherzusehen, dass die Gleichverteilung von n

√2 von deterministischer Natur ist. Bei

der Folge un = n ln(n)√

2 erzeugt die Prüfung der eingegebenen Werte den Eindruck einerwohl eher zufälligen Bildung. Indessen ist die Zeichnung in Abb. 4.9 (b) bemerkenswert gutstrukturiert. Die Zeichnung Abb. 4.9 (c) zeigt die gleiche Struktur wie die zweite. Und endlichlässt die Zeichnung in Abb. 4.9 (d) eine vollkommen andere Struktur der Verteilung modulo1/√

2 der Folge der Primzahlen entstehen: die Spiralen sind verschwunden und das Verhaltenerinnert an die Zeichnung in Abb. 4.8, die wir im Falle einer Folge von Zufallszahlen unbekommen. Es scheint daher, dass die Primzahlen den gesamten Zufall in Beschlag nehmen,mit dem sie ausgestattet sind...

Wegen einer eingehenderen Interpretation der erhaltenen Zeichnungen sei auf das Buch LesNombres Premiers (Que Sais-je) von Gérard Tenenbaum und Michel Mendès-France verwie-sen [TMF00].

Übung 13 (Zeichnung von Gliedern einer rekursiv denierten Folge). Man betrachte dieFolge (un)n∈N mit

u0 = a∀n ∈ N, un+1 = |u2

n − 14 |

.

Stellen Sie das Verhalten der Folge graphisch dar, indem Sie eine Liste mit den Punkten[[u0, 0], [u0, u1], [u1, u1], [u1, u2], [u2, u2], . . .] und a ∈ −0.4, 1.1, 1.3 aufstellen.

83

Page 100: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

(a) Der Fall un = n√

2. (b) Der Fall n ln(n)√

2

(c) Der Fall E(n ln(n))√

2 (d) Der Fall un = pn√

2

Abb. 4.9 - Gleichverteilte Folgen

4.1.6. Zeichnen der Lösung einer Dierentialgleichung

Wir können die vorstehenden Befehle zur Darstellung der Lösung einer Dierentialgleichungoder auch eines System von Dierentialgleichungen kombinieren. Um eine gewöhnliche Die-rentialgleichung symbolisch zu lösen, verwenden wir die Funktion desolve, deren Studium Ge-genstand von Kapitel 10 ist. Um eine Dierentialgleichung symbolisch zu lösen, bietet uns Sagemehrere Werkzeuge an: desolve_rk4 (mit einer Syntax ähnlich wie die Funktion desolve),odeint, (das SciPy verwendet), und schlieÿlich ode_solver, (das die Bibliothek GSL auf-ruft, deren Verwendung in Abschnitt 14.2 behandelt wird). Die Funktionen desolve_rk4 undodeint geben eine Liste von Punkten zurück, die mit dem Befehl line unschwer gezeich-net werden können. Auch wir werden mit ihnen in diesem Abschnitt numerische Lösungenzeichnen.

Beispiel (Ungelöste lineare Dierentialgleichung erster Ordnung). Wir möchten die Integral-kurven der Dierentialgleichung xy′ − 2y = x3 zeichnen.

sage: x = var('x'); y = function('y')sage: DE = x*diff(y(x), x) == 2*y(x) + x^3sage: desolve(DE, [y(x),x])(_C + x)*x^2sage: sol = []sage: for i in srange(-2, 2, 0.2)....: sol.append(desolve(DE, [y, x], ics=[1, i]))....: sol.append(desolve(DE, [y, x], ics=[-1, i]))sage: g = plot(sol, x, -2, 2)sage: y = var('y')sage: g += plot_vector_field((x, 2*y+x^3), (x,-2,2), (y,-1,1))sage: g.show(ymin=-1, ymax=1)

84

Page 101: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

(a) Symbolische Lösung (b) Numerische Lösung

Abb. 4.10 - Zeichnung der Integralkurven von xy′ − 2y = x3.

Zur Verringerung der Rechenzeit ist hier zu empfehlen, die allgemeine Lösung der Gleichungvon Hand zu beschaen und eine Liste partikulärer Lösungen zu erzeugen (wie das in derAuösung von Übung 14 gemacht wird) und nicht mehrmals hintereinander die Dierenti-algleichung mit verschiedenen Anfangswerten zu lösen. Ebenso hätten wir eine numerischeLösung dieser Gleichung berechnen lassen können (mittels der Funktion desolve_rk4), umdaraus die Integralkurven zu zeichnen:

sage: x, y = var('x y'); y = function('y')sage: DE = x*diff(y(x), x) == 2*y(x) + x^3sage: g = Graphics() # Erzeugung einer leeren Graphiksage: for i in srange(-2, 2, 0.2):....: g += line(desolve_rk4(2*y/x + x^2, dvar=y, ivar=x, ics=[1, i],\

step=0.05, end_points=[0,2]))....: g += line(desolve_rk4(2*y/x + x^2, dvar=y, ivar=x, ics=[-1,i],\

step=0.05, end_points=[-2,0]))sage: y = var('y')sage: g += plot_vector_field((x, 2*y+x^3), (x,-2,2), (y,-1,1))sage: g.show(ymin=-1, ymax=1)

Wie man an vorstehendem Beispiel sieht, übernimmt die Funktion desolve_rk4 als Argu-ment eine Dierentialgleichung (oder die rechte Seite der Gleichung in der Form y′ = f(x, y)),den Namen der unbekannten Funktion, die abhängige Variable, die Anfangsbedingung, dieSchrittweite und das Intervall der Lösung. Das optionale Argument output ermöglicht diePräzisierung der Ausgabe: der voreingestellte Wert 'list' gibt eine Liste zurück (was zweck-mäÿig ist, wenn man die Graphiken wie hier überlagern will), 'plot' zeichnet das Bild derLösung und 'slope_field' fügt die Steigungen der Integralkurve hinzu.

Übung 14. Zeichnen Sie die Integralkurven der Gleichung x2y′ − y = 0 für −3 ≤ x ≤ 3 und−5 ≤ y ≤ 5.

Wir geben jetzt ein Beispiel für die Verwendung der Funktion odeint aus demModul SciPy.

Beispiel (Nichtlineare Dierentialgleichung erster Ordnung.) Zeichnen Sie die Integralkurvender Gleichung y′(t) + cos(y(t) · t) = 0.

sage: import scipy; from scipy import integratesage: f = lambda y, t: -cos(y*t)

85

Page 102: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

sage: t = srange(0, 5, 0.1); p = Graphics()sage: for k in srange(0, 10,0.15):....: y = integrate.odeint(f, k, t)....: p += line(zip(t, flatten(y)))sage: t = srange(0, -5, -0.1); q = Graphics()sage: for k in srange(0, 10, 0.15):....: y = integrate.odeint(f, k, t)....: q += line(zip(t, flatten(y)))sage: y = var('y')sage: v = plot_vector_field((1, -cos(x*y)), (x,-5,5), (y,-2,11))sage: g = p + q + v; g.show()

Abb. 4.11 - Zeichnung der Integralkurven von y′(t) + cos(y(t) · t) = 0.

Die Funktion odeint übernimmt als Argument das zweite Glied der Dierentialgleichung (auf-gelöst geschrieben), eine oder mehrere Anfangsbedingungen und auch das Lösungsintervall;sie gibt eine Tabelle des Typs numpy.ndarray zurück, die wir mit dem Befehl flatten1 verein-fachen, wie das in Unterabschnitt 3.3.2 zu sehen war, und die wir mit dem Befehl zip mit derTabelle t zuaammenführen, bevor wir die Näherungslösung zeichnen. Um das Feld der Tan-genten an die Integralkurven hinzuzufügen, verwenden wir den Befehl plot_vector_field.

Beispiel (Räuber-Beute-Modell von Lotka-Volterra.) Wir möchten die graphische Lösung ei-ner Population von Beute und Räubern darstellen, die einem Gleichungssystem von Lotka-Volterra folgt:

du

dt= au− buv

dv

dt= −cv + dbuv

1Wir könnten hier auch die Funktion ravel von NumPy nehmen, welche die Erzeugung eines neuen Objektsvermeidet und daher den Speicherbedarf optimiert.

86

Page 103: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

wobei u die Anzahl der Beutetiere (z.B. Hasen) bezeichnet, v die Anzahl der Räuber (z.B.Füchse). Auÿerdem sind a, b, c, d Parameter, die die Entwicklung der Populationen beschrei-ben: a charakterisiert das natürliche Wachstum der Anzahl der Hasen bei Abwesenheit vonFüchsen, b die Abnahme der Anzahl der Hasen bei Anwesenheit der Räuber, c die Abnahmeder Anzahl der Füchse bei Fehlen der Beutetiere, und d zeigt schlieÿlich an, wieviel Hasenerforderlich sind, damit ein neuer Fuchs erscheint.

sage: import scipy; from scipy import integratesage: a, b, c, d = 1., 0.1, 1.5, 0.75sage: def dX_dt(X, t=0): # meldet das Anwachsen der Populationen....: return [a*X[0] - b*X[0]*X[1], -c*X[1] + d*b*X[0]*X[1]]sage: t = srange(0, 15, 0.01) # Zeitskalasage: X[0] = [10, 5] # Anfangsbedingungen: 10 Hasen und 5 Füchsesage: X = integrate.odeint(dX_dt, X0, t) # numerische Lösungsage: hasen, fuechse = X.T # Abkürzung von X.transpose()sage: p = line(zip(t, hasen), color='red') # Verlauf der Anzahl der Hasensage: p += text("Hasen",(12,37), fontsize=10, color='red')sage: p += line(zip(t, fuechse), color='blue') # dito für die Füchsesage: p += text("Füchse",(12,7), fontsize=10, color='blue')sage: p.axes_labels(["Zeit", "Population"]); p.show(gridlines=True)

Die obigen Anweisungen zeigen die Entwicklung der Anzahl der Hasen und Füchse als Funk-tion der Zeit (Abb. 4.12 links) und die hierunter zeigen das Vektorfeld (Abb. 4.12 rechts):

sage: n = 11; L = srange(6, 18, 12/n); R = srange(3, 9, 6/n)sage: CI = zip(L, R) # Liste der Anfangsbedingungensage: def g(x,y):....: v = vector(dX_dt([x, y])) # zwecks besserer Lesbarkeit..... return v/v.norm() # normieren wir das Vektorfeldsage: x, y = var('x y')sage: q = plot_vector_field(g(x, y), (x, 0, 60), (y, 0, 36))sage: for j in range(n):....: X = integrate.odeint(dX_dt, CI[j], t) # graphische....: q += line(X, color=hue(.8-float(j)/(1.8*n))) # Lösungsage: q.axes_labels(["Hasen","Fuechse"]); q.show()

Abb. 4.12 - Untersuchung Räuber-Beute-eines Systems

87

Page 104: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Übung 15 (Modell Räuber-Beute). Reproduzieren Sie die Graphik links in Abb. 4.12 mitdesolve_system_rk4 anstelle von odeint.

Übung 16 (Ein autonomes Dierentialsystem). Zeichnen Sie die Integralkurven des folgendenDierentialsystems:

x = yy = 0.5y − x− y3

Übung 17 (Strömung um einen Zylinder mit Magnus-Eekt).Wir überlagern einer einfachenStrömung um einen Zylinder mit dem Radius a einen Wirbel mit dem Parameter α, der diezirkulare Geschwindigkeitskomponente verändert. Wir stellen uns in ein Koordinatensystemmit dem Ursprung im Zylinder, und wir arbeiten mit Zylinderkoordinaten in der Ebene z = 0,anders gesagt mit Polarkoordinaten. Die Geschwindigkeitskomponenten sind dann:

vr = v0 cos(θ)

(1− a2

r2

)und vθ = v0 sin(θ)

(1 +

a2

r2

)+ 2

αav0

r.

Die Stromlinien (verschmolzen mit den Trajektorien, denn die Strömung ist stationär) sindparallel zur Geschwindigkeit. Wir suchen einen parametrisierten Ausdruck für die Stromlinien;man muss dazu das Dierentialsystem lösen:

dr

dt= vr und

dt=v0

r.

Wir benutzen dimensionslose Koordinaten, d.h. bezogen auf a, den Zylinderradius, den wirzu a = 1 setzen. Zu zeichen sind die Stromlinien dieser Strömung für α ∈ 0.1, 0.5, 1, 1.25.

Die Nutzung des Magnus-Eekts ist für die Entwicklung von Antriebssystemen vorgeschlagenworden, die aus groÿen senkrecht stehenden rotierenden Zylindern bestehen, die eine Querkrafterzeugen können, wenn der Wind seitlich auf das Schi trit (das war bei dem von AntonFlettner entwickelten Schi Baden-Baden der Fall, die 1926 den Atlantik überquerte).

4.1.7. Evolute einer Kurve

Wir geben nun ein Beispiel für das Zeichnen einer Evolute eines parametrisierten Bogens (wirerinnern uns, dass die Evolute die Hüllkurve der Normalen ist oder, äquivalent dazu, dergeometrische Ort der Krümmungsmittelpunkte der Kurve).

Beispiel (Evolute der Parabel). Wir suchen die Gleichung der Evolute der Parabel P mit derGleichung y = x2/4 und zeichnen in dieselbe Graphik die Parabel P, einige Normalen an Pund ihre Evolute.

Zur Bestimmung eines Systems von parametrischen Gleichungen (x(t), y(t)) der Evolute einerFamilie von Geraden ∆t, die durch kartesische Gleichungen der Form α(t)X + β(t)y = γ(t)deniert sind, drücken wir den Sachverhalt, dass die Gerade ∆t Tangente an die Evolute imPunkt (x(t), y(t)) ist, so aus:

α(t)x(t) + β(t)y(t) = γ(t) (4.1)

α(t)x′(t) + β(t)y′(t) = 0 (4.2)

Wir leiten Gl. (4.1) ab und durch Kombination mit Gl. (4.2) bekommen wir das System:

α(t)x(t) + β(t)y(t) = γ(t)

α(t)x′(t) + β(t)y′(t) = γ′(t) (4.3)

88

Page 105: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1. Kurven in 2D

In unserem Fall hat die Normale N(t) an die Parabel P in M(t, t2/4) als Normalenvektor~v = (1, t/2) (der Tangentenvektor an die Parabel); ihre Gleichung ist daher:(

x− ty − t2/4

)·(

1t/2

)=⇔ x+

t

2y = t+

t3

8,

anders gesagt, (α(t), β(t), γ(t)) = (1, t/2, t3/8). Wir können das obige System nun mit derFunktion solve lösen:

sage: x, y, t = var('x y t')sage: alpha(t) = 1; beta(t) = t/2; gamma(t) = t + t^3/8sage: env = solve([alpha(t)*x + beta(t)*y == gamma(t),\....: diff(alpha(t), t)*x + diff(beta(t), t)*y == \....: diff(gamma(t), t)], [x,y])[[

x = −1

4t3, y =

3

4t2 + 2

]]Daraus ergibt such eine parametrische Darstellung der Hüllkurve der Normalen:

x(t) = −14 t

3

y(t) = 2 + 34 t

2

Nun können wir die geforderte Darstellung ausführen und zeichnen dazu einige Normalen andie Parabel (genauer: wir zeichnen Strecken [M,M + 18~n], worin M(u, u2/4) ein Punkt vonP ist und ~n = (−u/2, 1) ein Normalenvektor an P):

sage: f(x) = x^2/4sage: p = plot(f, -8, 8, rgbcolor=(0.2,0.2,0.4)) # die Parabelsage: for u in srange(0, 8, 0.1): # Normalen an die Parabel....: p += line([[u, f(u)], [-8*u, f(u) + 18]], thickness=.3)....: p += line([[-u, f(u)], [8*u, f(u) + 18]], thickness=.3)sage: p += parametric_plot((env[0][0].rhs(),env[0][1].rhs()),\....: (t, -8, 8), color='red') # Zeichnen der Evolutesage: p.show(xmin=-8, xmax=8, ymin=-1, ymax=12, aspect_ratio=1)

Wie weiter oben erwähnt, ist die Evolute einer Kurve auch der Ort ihrer Krümmungsmit-telpunkte. Mit Hilfe der Funktion circle zeichnen wir einige Schmiegkreise an die Parabel.Wir wissen, der Krümmungsmittelpunkt Ω in einem Kurvenpunkt Mt = (x(t), y(t)) hat dieKoordinaten:

xΩ = x− y′ x′2 + y′2

x′y′′ − x′′y′und yΩ = y + x′

x′2 + y′2

x′y′′ − x′′y′

und der Krümmungsradius in Mt ist:

R =(x′2 + y′2)

32

x′y′′ − x′′y′.

89

Page 106: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Abb. 4.13 - Die Evolute einer Parabel

Art der ZeichnungGraph einer Funktion plot

parametrisierte Kurve parametric_plot

durch eine Polargleichung denierte Kurve polar_plot

durch eine implizite Gleichung denierte Kurve implicit_plot

Höhenlinien einer komplexen Funktion complex_plot

leeres graphisches Objekt Graphics()

Integralkurven einer Dierentialgleichung odeint, desolve_rk4

Stabdiagramm bar_chart

Häugkeitsverteilung einer statistischen Reihe plot_histogramm

Zeichnen eines Kurvenstücks line

Zeichnen einer Punktwolke points

Kreis circle

Polygon polygon

Text text

Tab. 4.1 - Zusammenfassung der graphischen Funktionen in 2D

sage: t = var('t'); p = 2sage: x(t) = t; y(t) = t^2/(2*p); f(t) = [x(t), y(t)]sage: df(t) = [x(t).diff(t), y(t).diff(t)]sage: d2f(t) = [x(t).diff(t, 2), y(t).diff(t, 2)]sage: T(t) = [df(t)[0]/df(t).norm(), df[1](t)/df(t).norm()]sage: R(t) = (df(t).norm())^3/(df(t)[0]*d2f(t)[1]-df(t)[1]*d2f(t)[0])sage: Omega(t) = [f(t)[0] + R(t)*N(t)[0], f(t)[1] + R(t)*N(t)[1]]sage: g = parametric_plot(f(t), (t, -8, 8), color='green', thickness=2)sage: for u in srange(.4, 4, .2):....: g += line([f(t=u), Omega(t=u)], color='red', alpha=.5)....: g += circle(Omega(t=u), R(t=u), color='blue')sage: g.show(aspect_ratio=1, xmin=-12, xmax=7, ymin=-3, ymax=12)

90

Page 107: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.2. Graphik in 3D

Abb. 4.14 - Schmiegkreise an die Parabel

Die Tabelle 4.1 stellt die in diesem Abschnitt verwendeten Funktionen zusammen. Wir führendort auch den Befehl text auf, mit dem wir eine Zeichenkette in eine Graphik einfügen können,wie auch den Befehl polygon, mit dem wir Vielecke zeichnen können.

4.2. Graphik in 3D

Zum Zeichnen von Flächen in drei Dimensionen verfügen wir über den Befehl plot3d(f(x,y),(x,a,b), (y,c,d)). Die erhaltene Fläche wird mit der Voreinstellung dank der AnwendungJmol visualisiert; wir können aber auch den Tachyon 3D Ray Tracer mit Hilfe des optionalenArguments viewer='tachyon' des Befehls show verwenden. Es folgt ein erstes Beispiel fürdie Zeichnung einer parametrisierten Fläche (Abb. 4.15).

sage: u, v = var('u v')sage: h = lambda u,v: u^2 + 2*v^2sage: f = plot3d(h, (u,-1,1), (v,-1,1), aspect_ratio=[1,1,1])sage: f.show(viewer='tachyon')

Abb. 4.15 - Die mit (u, v) 7→ u2 + 2v2 parametrisierte Fläche

91

Page 108: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

Die Visualisierung der Fläche einer Funktion zweier Variablen ermöglicht die Diskussion einersolchen Funktion, wie wir das im nächsten Beispiel sehen werden.

Beispiel (Eine diskontinuierliche Funktion, deren Richtungsableitungen überall existieren).

Zu untersuchen ist die Existenz der Richtungsableitungen in (0, 0) und die Stetigkeit derFunktion f von R2 nach R, die deniert ist durch:

f(x, y) =

x2yx4+y2

für (x, y) 6= (0, 0)

0 für (x, y) = (0, 0)

Für H =

(cos θsin θ

)ist die Funktion ϕ(t) = f(tH) = f(t cos θ.t sin θ) in t = 0 für jeden Wert

von θ dierenzierbar:

sage: f(x, y) = x^2*y/(x^5 + y^2)sage: t, theta = var('t theta')sage: limit(f(t*cos(theta), t*sin(theta))/t, t=0)cos(theta)^2/sin(theta)

Daher lässt f an der Stelle (0, 0) Richtungsableitungen nach beliebigen Vektoren zu. Für einebessere Darstellung der Fläche von f kann man damit beginnen, einige Höhenlinien zu suchen;beispielsweise die zum Wert 1

2 gehörende Höhenlinie:

sage: solve(f(x,y)==1/2,y)[y == x^2]sage: a = var('a'); h = f(x, a*x^2).simplify_rational(); ha/(a^2 + 1)

Entlang der Parabel mit der Gleichung y = ax2, ausgenommen der Ursprung, hat f denkonstanten Wert f(x, ax2) = a

1+a2. Wir zeichnen daraufhin die Funktion h : a 7→ a

1+a2:

sage: plot(h, a, -4, 4)

Abb. 4.16 - Ein vertikaler Schnitt durch die untersuchte Fläche

Die Funktion h erreicht ihr Maximum bei a = 1 und ihr Minimum bei a = −1. Die Beschrän-kung von f auf die Parabel mit der Gleichung y = x2 entspricht dem Kammweg, der sich inder Höhe 1

2 bendet; was die Restriktion von f auf die Parabel mit der Gleichung y = −x2

angeht, so entspricht sie dem Talweg, der sich in der Höhe −12 bendet. Abschlieÿend können

92

Page 109: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.2. Graphik in 3D

wir, so dicht wir an (0, 0) auch sein mögen, Punkte nden, an denen f die Werte 12 bzw. −1

2annimmt. Infolgedessen ist die Funktion im Ursprung nicht stetig.

sage: p = plot3d(f(x,y), (x,-2,2), (y,-2,2), plot_points=[150,150])sage: p.show(viewer='tachyon')

Abb. 4.17 - Die Fläche von f : (x, y) 7→ x2yx4+x2

.

Wir hätten ebensogut horizontale Ebenen zeichnen können, um die Höhenlinien dieser Funk-tion sichtbar zu machen, indem wir diesen Code ausführen:

sage: for i in range(1,4):....: p += plot3d(-0.5 + i/4, (x, -2, 2), (y, -2,2),\....: color=hue(i/10), opacity=.1)sage: p.show(viewer='tachyon')

Von den übrigen Befehlen für 3D-Graphik erwähnen wir implicit_plot3d, der uns erlaubtFlächen zu zeichnen, die durch eine implizite Gleichung der Form f(x, y, z) = 0 deniert sind.Als Beispiel wollen wir die cassinische Fläche zeichnen (Abb. 4.18a), die durch die impliziteGleichung (a2 + x2 + y2)2 = 4a2x2 + z4 deniert ist:

sage: x, y, z = var('x y z'); a = 1sage: h = lambda x, y, z: (a^2+x^2+y^2)^2-4*a^2*x^2-z^4sage: f = implicit_plot3d(h, (x, -3, 3), (y, -3, 3), (z, -2, 2),\....: plot_points=100, adaptative=True)sage: f.show(viewer='tachyon')

Schlieÿlich geben wir noch das Beispiel einer Raumkurve (Abb. 4.18b) mittels des Befehlsline3d:

sage: g1 = line3d([(-10*cos(t)-2*cos(5*t)+15*sin(2*t),\....: -15*cos(2*t)+10*sin(t)-2*sin(5*t),\....: 10*cos(3*t)) for t in srange(0,6.4,.1)], radius=0.5)sage: g1.show(viewer='tachyon')

93

Page 110: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4. Graphiken

(a) Die cassinische Fläche (b) Ein Knoten im Raum

94

Page 111: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

Das Schreiben mathematischer Texte auf Papier oder Tafel erfordert vor allem die Suche nacheinem guten Kompromiss zwischen Flexibilität, Leichtigkeit der Schreibweise und Strenge.Das ist für den tagtäglichen Gebrauch eines Berechnungssystems nicht anders. Sage versuchtdie Wahl des Kompromisses dem Anwender zu überlassen insbesondere dadurch, dass es ihmmehr oder weniger streng erlaubt, den Denitionbereich der Rechnung festzulegen: welches istdie Natur der betrachteten Objekte, zu welcher Menge gehören sie, welche Operationen sindmit ihnen ausführbar?

5.1. Sage ist objektorientiert

Python und Sage machen von der objektorientierten Programmierung intensiven Gebrauch.Auch wenn das für den normalen Gebrauch relativ transparent bleibt, ist es sinnvoll, darüberein Minimum an Wissen zu haben, zumal dies in mathematischen Zusammenhängen ganznatürlich ist.

5.1.1. Objekte, Klassen und Methoden

Die objektorientierte Programmierung beruht auf der Idee, jede physikalische oder abstrakteEntität zu modellieren, die wir in einem Programm durch ein Objekt genanntes Sprachkon-strukt manipulieren möchten. Meistens, und in Python ist das der Fall, ist jedes ObjektInstanz einer Klasse. So ist die rationale Zahl 12/35 modelliert durch ein Objekt, welches eineInstanz der Klasse Rational ist.

sage: o = 12/35sage: print type(o)<type 'sage.rings.rational.Rational'>

Merken wir uns, dass diese Klasse dem Objekt 12/35 zugeordnet ist und nicht der Variableno, die es enthält:

sage: print type(12/35)<type 'sage.rings.rational.Rational'>

Präzisieren wir die Denitionen. Ein Objekt ist ein Teil des Speichers des Rechners, das dieerforderliche Information für die Darstellung der Entität enthält, die vom Objekt modelliertwird. Was die Klasse betrit, so deniert sie zwei Dinge:

1. die Datenstruktur eines Objektes, d.h. wie die Information im Speicherblock organisiertist. Beispielsweise speziziert die Klasse Rational, dass eine rationale Zahl wie 12/35durch zwei ganze Zahlen dargestellt wird: ihren Zähler und ihren Nenner;

95

Page 112: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

2. ihr Verhalten, insbesondere die Operationen auf diesem Objekt: beispielsweise wie manden Zähler einer rationalen Zahl bekommt, wie ihr Absolutwert berechnet wird, wie manzwei rationale Zahlen addiert oder multipliziert. Jede dieser Operationen wird durch eineMethode implementiert (hier durch numer und numerator, abs, __mult__, __add__).

Um eine ganze Zahl zu faktorisieren wird man daher die Methode factormit folgender Syntaxaufrufen1:

sage: o = 720sage: o.factor()2^4 * 3^2 * 5

was man lesen kann als: nimm den Wert von o und wende die Methode factor ohne einweiteres Argument darauf an. Unter der Haube führt Python folgende Rechnung aus:

sage: type(o).factor(o)2^4 * 3^2 * 5

Von links nach rechts: fordere von der Klasse von o (type(o)) die Methode factor die fürdie Faktorisierung geeignete Methode an (type(o).factor) und wende sie auf o an.

Wir bemerken bei dieser Gelegenheit, dass wir eine Methode auf einen Wert anwenden können,ohne ihn an eine Variable zu übergeben:

sage: 720.factor()2^4 * 3^2 * 5

und daher auch Operationen von links nach rechts hintereinander ausführen können:

sage: o = 720/133sage: o.numerator().factor()2^4 * 3^2 * 5

5.1.2. Objekte und Polymorphie

Was geht uns das an? Zunächst sind in Sage alle Operationen polymorph, d.h. sie könnenauf verschiedene Typen angewendet werden. So wenden wir auf welches Objekt auch immer,das wir faktorisieren wollen, dieselbe Schreibweise o.factor() an (oder seine Abkürzungfactor(o)). Die auszuführenden Operationen sind dennoch im Fall einer ganzen Zahl undeines Polynoms nicht die gleichen! Sie unterscheiden sich auÿerdem auch darin, ob das Polynomrationale Koezienten hat oder Koezienten aus einem endlichen Körper. Es ist die Klassedes Objektes, die entscheidet, welche Version von factor letztendlich ausgeführt wird.

1Für die Bequemlichkeit des Anwenders bietet Sage auch eine Funktion factor derart, dass factor(o) eineAbkürzung von o.factor() ist. Das gilt auch für eine groÿe Anzahl häug gebrauchter Funktionen, es istdurchweg möglich, ihre Abkürzungen zu nehmen.

96

Page 113: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.1. Sage ist objektorientiert

Ebenso, und wir übernehmen die normale mathematische Schreibweise, kann das Produktzweier Objekte a und b immer a*b geschrieben werden, auch wenn die in jedem der Fälleverwendeten Algorithmen verschieden2 sind. Hier ein Produkt zweier ganzer Zahlen:

sage: 3*721

hier ein Produkt zweier rationaler Zahlen, das durch Multiplikation der Zähler und der Nennerund anschlieÿendes Kürzen erhalten wird:

sage: (2/3)*(6/5)4/5

und hier ein Produkt zweier komplexer Zahlen, wobei die Beziehung i2 = −1 benutzt wird:

sage: (1 + I)*(1 - I)2

sowie kommutative Produkte zweier symbolischer Ausdrücke:

sage: (x + 1)*(x + 2)(x + 2)*(x + 1)sage: (x + 2)*(x + 1)(x + 2)*(x + 1)

Auÿer der einfachen Schreibweise ermöglicht diese Form der Polymorphie das Schreiben ge-

nerischer , d.h. allgemeingültiger Programme, die auf jedes Objekt anwendbar sind, das dieseOperation zulässt (hier die Multiplikation):

sage: def vierte_potenz(a)....: a = a*a....: a = a*a....: return a

sage: vierte_pozenz(2)16sage: vierte_potent(3/2)81/16sage: vierte_potenz(I)1sage: vierte_potenz(x+1)(x + 1)^4sage: M = matrix([[0, -1], [1, 0]]); M[ 0 -1][ 1 0]sage: vierte_potenz(M)[1 0][0 1]

2Für eine binäre arithmetische Operation wie das Produkt ist das Verfahren zur Auswahl der passendenMethode ein wenig komplizierter als das oben beschriebene. Sie muss nämlich gemischte Operationen wiedie Summe 2 + 3/4 einer ganzen und einer rationalen Zahl managen. Hier wird die 2 vor der Addition ineine rationale Zahl 2/1 konvertiert. Die Regeln für die Entscheidung, welche Operanden umzuwandeln sindund wie, heiÿen Zwangsmodell .

97

Page 114: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

5.1.3. Introspektion

Die Objekte von Python, und damit auch von Sage, haben die Funktionalitäten der Introspek-tion. Das bedeuten, dass wir ein Objekt bei der Ausführung nach seiner Klasse und seinenMethoden befragen können und auch die erhaltenen Informationen mit den üblichen Kon-struktionen der Programmierung manipulieren. So ist die Klasse eines Objektes ihrerseits einPython-Objekt wie (fast) alle anderen, die wir mit type(o) gewinnen können:

sage: t = type(5/1); print t<type 'sage.rings,rational.Rational'>sage: t == type(5)False

Wir sehen hier, dass der Ausdruck 5/1 die rationale Zahl 5 bildet, die ein anderes Objekt istals die ganze Zahl 5.

Es gibt auch Werkzeuge der Introspektion, auf die online zugegrien werden kann, wie hieram Beispiel der Faktorisierung einer ganzen Zahl gezeigt wird:

sage: o = 720sage: o.factor?...Definition: o.factor(algorithm='pari', proof=None, ... )

Docstring:

Return the prime factorization of this integer as a formalFactorization object.

...

Den Code dieser Funktion zeigt

sage: o.factor??...def factor(self, algorithm='pari', proof=None, ...):

...if algorithm not in ['pari', 'kash', 'magma', 'qsieve', 'ecm']:....

Wenn wir dazu die technischen Details durchgehen, erkennen wir, dass Sage einen Groÿteilder Rechnungen an andere Programme delegiert (PARI, kash, Magna).

Ebenso können wir die automatische Vervollständigung nutzen, um zu einem Objekt dieOperationen zu erfragen, die wir mit ihm verwenden können. Hier gibt es viele davon; wirzeigen die, welche mit n beginnen:

sage: o.n<tab>o.n o.next_prime o.nth_rooto.nbits o.next_prime_power o.numeratoro.ndigits o.next_probable_prime o.numerical_approx

Auch hier handelt es sich um eine Form der Introspektion.

98

Page 115: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2. Elemente, Vorfahren, Kategorien

5.2. Elemente, Vorfahren, Kategorien

5.2.1. Elemente und Vorfahren

Im vorigen Abschnitt sind wir dem Begri der Klasse einnes Objektes begegnet. In der Praxisgenügt es zu wissen, dass dieser Begri existiert; selten muss man den Typ eines Objektesexplizit betrachten. Andererseits führt Sage ein Gegenstück zu diesem Begri ein, dem wirund nun widmen werden, dem des Vorfahren eines Objektes.

Zum Beispiel nehmen wir an, wir wollten entscheiden, ob ein Element a invertierbar ist. DieAntwort wird nicht nur vom Element selbst abhängen, sondern auch von der Menge A, deres angehört (wie auch sein potentielles Inverses). Die Zahl 5 ist beispielsweise in der MengeZ der ganzen Zahlen nicht invertierbar, weil ihr Inverses 1/5 keine ganze Zahl ist:

sage: a = 5; a5sage: a.is_unit()False

Vielmehr ist 5 in der Menge der rationalen Zahlen invertierbar:

sage: a = 5/1; a5sage: a.is_unit()True

Sage antwortet auf diese beiden Fragen unterschiedlich, denn wir haben im vorigen Abschnittgesehen, dass die Elemente 5 und 5/1 Instanzen verschiedener Klassen sind.

In einigen CAS wie MuPAD oder Axiom wird die Menge X, zu der x gehört (hier Z oder Q),einfach durch die Klasse von x modelliert. Sage folgt dem Ansatz von Magma und modelliertX durch ein ergänzendes, mit x verbundenes Objekt, seinem Vorfahren:

sage: parent(5)Integer Ringsage: parant(5/1)Rational Field

Wir können diese beiden Mengen auch mit ihren Abkürzungen nden:

sage: ZZInteger Ringsage: QQRational Field

und sie für die einfache Konvertierung eines Elementes von der einen in die andere benutzen,sofern das sinnvoll ist:

sage: QQ(5).parent()Rational Fieldsage: ZZ(5/1).parent()Integer Ringsage: ZZ(1/5)

99

Page 116: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

Traceback (most recent call last)...

TypeError: no conversion of this rational to integer

Allgemein versucht die Syntax P(x), wobei P ein Vorfahr ist, das Objekt x in ein Element von Pzu konvertieren. Für die ganze Zahl 1 ∈ Z, die rationale Zahl 1 ∈ Q, die Gleitpunkt-Näherungder reellen Zahl 1, 0 ∈ R oder die komplexe Zahl 1, 0 + 0, 0i ∈ C gilt:

sage: ZZ(1), QQ(1), RR(1), CC(1)(1, 1, 1.00000000000000, 1.00000000000000)

Übung 18. Welches ist die Klasse des Ringes der ganzen Zahlen Z?

5.2.2. Konstruktionen

Die Vorfahren sind ihrerseits Objekte, mit denen wir Operationen ausführen können. So kön-nen wir das kartesische Produkt Q2 bilden:

sage: cartesian_product([QQ, QQ])The Cartesian product of (Rational Field, Rational Field)

Q zurückgewinnen als Körper der Brüche von Z:

sage: ZZ.fraction_field()Rational Field

den Polynomring in x mit Koezienten aus Z:

sage: ZZ['x']Univariate Polynomial Ring in x over Integer Ring

Durch schrittweises Vorgehen können wir komplexe algebraische Strukturen bilden wie denVektorraum der 3×3-Matrizen mit polynomialen Koezienten aus einem endlichen Körper:

sage: Z5 = GF(5); Z5Finite Field of size 5sage: P = Z5['x']; PUnivariate Polynomial Ring in x over Finite Field of size 5sage: M = MatrixSpace(P, 3, 3); MFull MatrixSpace of 3 by 3 dense matrices over Univariate PolynomialRing in x over Finite Field of size 5

Hier ein Element:

sage: M.random_element()[ x + 4 2*x + 1 3*x^2 + x + 2][3*x^2 + 4*x + 1 x + 2 4*x^2 + 3*x + 2][4*x^2 + 2*x + 2 x^2 + 2*x + 3 3*x^2 + 4*x + 4]

100

Page 117: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2. Elemente, Vorfahren, Kategorien

5.2.3. Ergänzung: Kategorien

Ein Vorfahr hat im allgemeinen selbst keinen Vorfahren, sondern eine Kategorie, die seineEigenschaften angibt:

sage: QQ.category()Category of quotient fields

In der Tat weiÿ Sage, dass Q ein Körper ist:

sage: QQ in FieldsTrue

und somit beispielsweise auch eine additive kommutative Gruppe ist:

sage: QQ in CommutativeAdditiveGroups()True

Daraus folgt, dass Q[x] ein euklidischer Ring ist:

sage: QQ['x'] in EuclideanDomains()True

Alle diese Eigenschaften werden bei strengen und ezienten Rechnungen mit Elementen dieserSysteme verwendet.

101

Page 118: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

Abb. 5.1 - Ein kleiner Ausschnitt aus der Darstellung der Kategorien in Sage

5.3. Denitionsmengen für das Rechnen und die Darstellung in Normalform

Wir gehen nun über zur Betrachtung einiger Vorfahren, die in Sage zu nden sind.

In Abschnitt 2.1 haben wir die Bedeutung der Normalformen für das symbolische Rechnenerkannt, die uns die Entscheidung ermöglichen, ob zwei Objekte bei Vergleich ihrer Darstel-lungen mathematisch gleich sind. Jeder der hiernach aufgeführten grundlegenden Vorfahrenentspricht einer Menge von Zahlen für die Rechnung mit Normalformen, d.h. einer Menge

102

Page 119: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.3. Denitionsmengen für das Rechnen und die Darstellung in Normalform

solcher mathematischer Objekte, die eine Normalform erlauben. Das ermöglicht Sage, dieElemente jedes dieser Vorfahren unzweideutig darzustellen3.

Einige Basistypen von Pythonganze Zahlen in Python int

Gleitpunktzahlen in Python float

Wahrheitswerte (True, False) bool

Zeichenketten str

Denitionsmengen von Zahlenganze Zahlen Z ZZ oder IntegerRing()

rationale Zahlen Q QQ oder RationalField()Gleitpunktzahlen mit der Genauigkeit p Reals(p) oder RealField(p)

komplexe Gleitpunktzahlen mit Genauigkeit p Complexes(p) oder ComplexField(p)

Ringe und endliche KörperRest modulo n Z/nZ Integers(n) oder IntegerModRing(n)endlicher Körper Fq GF(q) oder FiniteField(q)

algebraische Zahlenalgebraische Zahlen Q QQbar oder AlgebraicField()

reelle algebraische Zahlen AA oder AlgebraicRealField()Körper der Zahlen Q[x]/(p) NumberField(p)

Symbolisches Rechnenm× n-Matrizen mit Einträgen aus A MatrixSpace(A, m, n)

Polynome A[x, y] A['x,y'] oder PolynomialRing(A, 'x,y')

Reihen A[[x]] A[['x']] oder PowerSeriesRing(A, 'x')

symbolische Ausdrücke SR

Tab. 5.1 - Die wichtigsten Zahlenarten für Berechnungen und die Vorfahren

5.3.1. Elementare Zahlenarten

Elementare Zahlenarten nennen wir die klassischen Mengen von Konstanten: ganze Zahlen,rationale Zahlen, Gleitpunktzahlen, boolesche Werte, Reste modulo n . . .

Ganze Zahlen. Die ganzen Zahlen werden rechnerintern zur Basis zwei dargestellt und aufdem Bildschirm zur Basis zehn. Wie wir gesehen haben, sind die ganzen Zahlen in Sage vomTyp Integer. Ihr Vorfahr ist der Ring Z:

sage: 5.parent()Integer Ring

Die ganzen Zahlen werden in Normalform dargestellt; die Gleichheit ist daher einfach zuprüfen. Um ganze Zahlen in faktorisierter Form darstellen zu können, verwendet der Befehlfactor eine besondere Klasse:

sage: print type(factor(4))<class'sage.structure.factorization_integer.IntegerFactorization'>

3Die meisten anderen der in Sage verfügbaren Vorfahren entsprechen Denitionsmengen für die Rechnungmit Normalformen, doch ist dies nicht bei allen der Fall. Es kommt auch vor, dass Sage aus Gründen derEzienz die Elemente als Normalformen nur auf besondere Anforderung darstellt.

103

Page 120: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

Die Klasse Integer ist Sage-eigen: in der Voreinstellung verwendet Python ganze Zahlen desTyps int. Generell erfolgt die Konversion des einen in den anderen automatisch, doch kannes notwendig werden, die Konversion explizit vorzuschreiben mit

sage: int(5)5sage: print type(int(5)) <type 'int'>

oder umgekehrt

sage: Integer(5)5sage: print type(Integer(5))<type 'sage.rings.integer.Integer'>

Rationale Zahlen. Die Eigenschaft der Normalform haben auch die rationalen Zahlen, dieElemente von QQ, die immer in Normalform dargetellt werden. So werden durch die Anwei-sung

sage: factorial(99)/factorial(100) -1/50-1/100

Zuerst werden die Fakultäten ausgewertet, dann wird von dem erhaltenen Bruch 1/100 dierationale Zahl 1/50 abgezogen und gekürzt (was hier nicht nötig ist).

Gleitpunktzahlen. Reelle Zahlen können nicht exakt dargestellt werden. Ihre genähertenZahlenwerte werden als Gleitpunktzahlen dargestellt. Sie werden in Kapitel 11 eingehendbehandelt.

In Sage werden Gleitpunktzahlen zur Basis zwei dargestellt. Als eine Folge wird die als 0.1dargestellte Gleitpunktzahl nicht genau gleich 1/10 sein, denn 1/10 kann zur Basis 2 nichtexakt dargestell werden. Jede Gleitpunktzahl hat ihre eigene Genauigkeit. Der Vorfahr derGleitpunktzahlen mit p signikanten Bits wird als Reals(p) geschrieben. Die Gleitpunktzahlmit der voreingestellten Präzision (p = 53) heiÿt auch RR. Wie im Fall der ganzen Zahlenunterscheiden sich die Gleitpunktzahlen in Sage von denen in Python.

Wenn sie in einer Summe oder einem Produkt zusammen mit ganzen oder rationalen Zahlenauftreten, sind Gleitpunktzahlen ansteckend: der gesamte Ausdruck wird dann als Gleit-punktzahl berechnet:

sage: 72/53 - 5/3*2.7-3.14150943396227

Ebenso, wenn das Argument einer Funktion eine Gleitpunktzahl ist, erscheint auch das Er-gebnis als Gleitpunktzahl:

sage: cos(1), cos(1.)(cos(1), 0.540302305868140)

Die Methode numerical_approx (oder ihre Alias n und N) dient zur numerischen Auswertungweiterer Ausdrücke. Ein optionales Argument erlaubt die Präzisierung der bei der Rechnunggebrauchten signikanten Stellen. Als Beispiel π mit 50 signikanten Ziern:

sage: pi.n(digits=50) # Variante: n(pi,digits=50)3.1415926535897932384626433832795028841971693993751

104

Page 121: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.3. Denitionsmengen für das Rechnen und die Darstellung in Normalform

Komplexe Zahlen. Genauso sind die Näherungen von komplexen Zahlen mittels Gleitpunkt-zahlen mit der Genauigkeit p Elemente von Complexes(p), wobei CC die voreingestellte Ge-nauigkeit besitzt. Wir können eine komplexe Zahl bilden und ihr Argument berechnen:

sage: z = CC(1,2); z.arg()1.10714871779409

Komplexe symbolische Ausdrücke

Die imaginäre Einheit i (geschrieben I oder i), die uns in den vorigen Kapitelnschon begegnet ist, ist kein Element von CC, sondern ein symbolischer Ausdruck(siehe Unterabschnitt 5.4.1):sage: I.parent()Symbolic RingWir können damit eine komplexe Gleitpunktzahl schreiben, wenn wir eine expliziteKonversion vorschreiben:sage: I.parent()Symbolic Ringsage: CC(1.+2.*I).parent()Complex Field with 53 bits precisionIn der Welt der symbolischen Ausdrücke ergeben die Methoden real, imag und absden Realteil, den Imaginärteil bzw. die Norm oder auch den Modul einer komplexenZahl:sage: z = 3*exp(I*pi/4)sage: z.real(), z.imag(), z.abs().simplify()(3/2*sqrt(2), 3/2*sqrt(2), 3)

Boolesche Werte. Logische Ausdrücke bilden auch eine Zahlenart in Normalform, doch istdie Klasse der Wahrheitswerte oder booleschen Werte ein Basistyp von Python ohne Vorfahrenin Sage. Die beiden Normalformen sind True und False:

sage: a, b, c = 0, 2, 3True

In Tests und Schleifen werden die zusammengesetzten Bedingungen mit den Operatoren orund and einfach von links nach rechts ausgewertet. Das bedeutet, dass die Auswertung einerzusammengesetzten Bedingung mit or nach dem ersten Teilergebnis True beendet wird, ohnedie rechts noch folgenden Terme zu berücksichtigen; genauso bei and und False. So beschreibtder nächste Test die Teilbarkeit a|b von ganzen Zahlen und führt auch bei a = 0 nicht zu einemFehler:

sage: a = 0; b = 12; (a == 0) and (b == 0) or (a != 0) and (b%a == 0)

Der Operator not hat Vorrang vor and, das wiederum Vorrang vor or hat, und die Tests aufGleichheit haben Vorrang vor allen booleschen Operatoren. Die beiden folgenden Tests sinddeshalb zum vorigen äquivalent:

sage: ((a == 0) and (b == 0)) or ((a != 0) and (b%a == 0))sage: a == 0 and b == 0 or not a == 0 and b%a == 0

Des weiteren gestattet Sage Tests auf Enthaltensein in mehrfachen Intervallen genauso, wiedas in der Mathematik geschieht:

105

Page 122: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

x ≤ y ≤ z wird codiert als x <= y <= zx = y = z 6= t x == y == z != t

In einfachen Fällen werden diese Test unmittelbar ausgeführt; wenn nicht, muss mit demBefehl bool die Auswertung erzwungen werden:

sage: x, y = var('x, y')sage: bool((x-y)*(x+y) == x^2 - y^2)True

Reste modulo n. Bei der Denition einer Kongruenz beginnen wir mit der Bildung ihresVorfahren, des Ringes Z/nZ:

sage: Z4 = IntegerModRing(4); Z4Ring of integers modulo 4sage: m = Z4(7); m3

Wie bei Gleitpunktzahlen wird in Rechnungen mit m automatisch in Zahlen modulo 4 um-gewandelt. So werden im folgenden Beispiel 3 und 1 automatisch in Elemente von Z/nZkonvertiert:

sage: 3*m + 12

Ist p eine Primzahl, können wir Z/pZ als Körper bilden:

sage: Z3 = GF(3); Z3Finite Field of size 3

In beiden Fällen handelt es sich um Zahlenarten in Normalform: die Reduktionen modulo noder p werden bei jeder Erzeugung eines Elementes automatisch ausgeführt. Rechnungen aufendlichen Ringen und Körpern werden in Kapitel 6 ausführlich behandelt.

5.3.2. Zusammengesetzte Objektklassen

Mit wohldenierten Konstanten können Klassen symbolischer Objekte gebildet werden, dieals Variable vorkommen und eine Normalform kennen. Die wichtigsten sind die Matrizen, diePolynome, die gebrochen rationalen Ausdrücke und die abbrechenden Reihen.

Die entsprechenden Vorfahren sind durch die Zahlenart der Koezienten parametrisiert. Sounterscheiden sich beispielsweise Matrizen mit ganzzahligen Einträgen von solchen mit Ein-trägen aus Z/nZ und die zugehörigen Rechenregeln werden automatisch angewendet, ohnedass eine Funktion für die Reduktion modulo n explizit aufgerufen werden müsste.

Teil II dieses Buches ist vor allem diesen Objekten gewidmet.

Matrizen. Die Normalform einer Matrix liegt vor, wenn ihre Einträge ihrerseits in Normal-form sind. Auch wird jede Matrix auf einem Körper oder einem Ring in normaler Darstellungautomatisch in Normalform ausgegeben:

sage: a = matrix(QQ, [[1, 2, 3], [2, 4, 8], [3, 9, 27]])sage: (a^2 + 1)*a^(-1)

106

Page 123: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.3. Denitionsmengen für das Rechnen und die Darstellung in Normalform

[ -5 13/2 7/3][ 7 1 25/3][ 2 19/2 27]

Der Aufruf der Funktion matrix ist eine Abkürzung. Intern bildet Sage den entsprechendenVorfahren, nämlich den Vektorraum der 3 × 3-Matrizen mit Einträgen aus Q (in normalerDarstellung), dann wird der Vorfahr zur Erzeugung der Matrix verwendet:

sage: M = MatrixSpace(QQ,3,3); MFull MatrixSpace of 3 by 3 dense matrices over Rational Fieldsage: a = M[[1, 2, 3], [2, 4, 8], [3, 9, 27]])sage: (a^2 + 1)*a^(-1)[ -5 13/2 7/3][ 7 1 25/3][ 2 19/2 27]

Die Operationen mit symbolischen Matrizen werden in Kapitel 8 beschrieben, die numerischelineare Algebra in Kapitel 13.

Polynome und gebrochen rationale Ausdrücke. Genau wie Matrizen den Typ ihrerEinträge kennen Polynome in Sage den Typ ihrer Koezienten. Ihre Vorfahren sind Poly-nomringe wie Z[x] oder C[x, y, z], die in den Kapiteln 7 und 9 eingehend vorgestellt werden,und die wir erzeugen können mit

sage: P = ZZ['x']; PUnivariate Polynomial Ring in x over Integer Ringsage: F = P.fraction_field(); FFraction Field of Univariate Polynomial Ring in x over Integer Ringsage: p = P(x+1)*P(x); Px^2 + xsage: p + 1/p(x^4 + 2*x^3 + x^2 + 1)/(x^2 + x)sage: parent(p + 1/p)Fraction Field of Univariate Polynomial Ring in x over Integer Ring

Wie wir in Unterabschnitt 5.4.2 sehen werden, gibt es keine ideale Darstellung für Polynomeund gebrochen rationale Ausdrücke. Die Elemente der Polynomringe werden in entwickelterForm dargestellt. Diese Ringe sind daher normal dargestellt, sobald die Koezienten in einerZahlenart ihreseits in Normalform vorliegen.

Diese Polynome unterscheiden sich von polynomialen Ausdrücken, denen wir in Kapitel 2begegnet sind, und deren Koeezienten weder einen wohldenierten Typ haben noch einenVorfahren, der den Typ widerspiegelt. Sie repräsentieren eine Alternative zu den echtenPolynomen, die nützlich sein kann, um Polynome und andere mathematische Ausdrücke zumischen. Wir betonen, dass wenn wir mit diesen Ausdrücken arbeiten, dann anders als beiElementen von Polynomringen, explizit ein Befehl zur Reduktion wie expand erfolgen muss,um sie in Normalform zu bringen.

Reihen. Abbrechende Potenzreihen sind Objekte der Form

a0 + a1x+ a2a2 + · · ·+ anx

n +O(xn+1)

107

Page 124: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

Sie werden beispielsweise für die Darstellung abbrechender Reihenentwicklungen verwendetund ihre Manipulation in Sage wird in Abschnitt 7.5 beschrieben. Der Vorfahr der abbrechen-den Reihen in x mit der Genauigkeit n und Koezienten aus A ist der Ring A[[x]], der mitPowerSeriesRing(A, 'x', n) erzeugt wird. Wie die Polynome haben auch die abbrechendenReihen eine Entsprechung in der Welt der symbolischen Ausdrücke. Der zugehörige Befehl zurReduktion auf die Normalform ist series.

sage: f = cos(x).series(x == 0, 6); 1/f

1

1 + (−12)x2 + 1

24x4 +O (x6)

sage: (1/f).series(x == 0, 6)

1 +1

2x2 +

5

24x4 +O

(x6)

Algebraische Zahlen. Eine algebraische Zahl ist als Wurzel eines Polynoms deniert. So-bald der Grad eines Polynoms 5 oder gröÿer ist, ist es im allgemeinen nicht möglich, dieWurzeln mit Hilfe der Operatoren +,−, ∗, /,√ explizit hinzuschreiben. Jedoch können zahl-reiche Rechnungen mit Wurzeln mit keinen anderen Informationen als dem Polynom selbstsehr wohl ausgeführt werden.

sage: k.<a> = NumberField(x^3 + x + 1); a^3; a^4 + 3*a-a - 1-a^2 + 2*a

Die Manipulation algebraischer Zahlen in Sage wird in diesem Buch nicht detailliert behandelt,einige Beispiele sind jedoch in den Kapiteln 7 und 9 zu nden.

5.4. Ausdrücke versus Zahlenarten für das Rechnen

Es sind also in Sage mehrere Ansätze für die Manipulation von Objekten wie Polynomemöglich. Man kann sie als besondere formale Ausdrücke ansehen, wie wir das in den erstenKapiteln dieses Buches getan haben, man kann aber auch einen speziellen Polynomring ein-führen und mit dessen Elementen rechnen. Zum Abschluss dieses Kapitels beschreiben wirkurz den Vorfahr der symbolischen Ausdrücke, den Bereich SR, sodann erläutern wir anhandeiniger Beispiele wie wichtig es ist, die Denitionsmengen für die Rechnung zu kontrollierenund die Unterschiede zwischen diesen Ansätzen zu beachten.

5.4.1. Ausdrücke als Denitionsmenge für das Rechnen

Die symbolischen Ausdrücke bilden selber eine Denitionsmenge für Rechnungen! In Sage istihr Vorfahr der symbolische Ring :

sage: parent(sin(x))Symbolic Ring

was wir auch erhalten könnten mit

sage: SRSymbolic Ring

108

Page 125: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.4. Ausdrücke versus Zahlenarten für das Rechnen

Die Eigenschaften dieses Ringes sind recht verschwommen; er ist kommutativ:

sage: SR.category()Category of commutative rings

und die Rechenregeln machen im groÿen Ganzen die Annahme, dass die Werte aller symboli-schen Variablen in C liegen.

Die Form der Ausdrücke, die wir in SR manipulieren (polynomiale, rationale und trigono-metrische Ausdrücke), die nicht oensichtlich zu ihrer Klasse oder ihrem Vorfahr gehören,bedarf als Resultat einer Rechnung sehr oft einer manuellen Umformung, zum Beispiel mitexpand, combine, collect und simplify, um in die gewünschte Form gebracht zu werden(siehe Abschnitt 2.1). Für den angemessenen Gebrauch dieser Funktionen müssen wir wissen,welchen Typ der Umformung sie ausführen, auf welche Unterklassen4 von Ausdrücken sieangewendet werden, und welche dieser Unterklassen Denitionsbereiche der Normalform bil-den. Somit kann der blinde Gebrauch der Funktion simplify zu falschen Ergebnissen führen.Varianten von simplify ermöglichen eine zielsichere Vereinfachung.

5.4.2. Beispiele: Polynome und Normalformen

Wir konstruieren den Polynomring Q[x1, x2, x3, x4] in vier Variablen:

sage: R = QQ['x1,x2,x3,x4']; RMultivariate Polynomial Ring in x1, x2, x3, x4 over Rational Fieldsage: x1, x2, x3, x4 = R.gens()

Die Elemente von R werden automatisch in entwickelter Form dargestellt:

sage: x1*(x2 - x3)x1*x2 - x1*x3

was eine Normalform ist, wie wir wissen. Insbesondere ist der Test auf 0 in R unmittelbar:

sage: (x1 + x2)*(x1 - x2) - (x1^2 - x2^2)0

Das ist nicht immer ein Vorteil. Wenn wir beispielsweise die vandermondesche Determinante∏1≤i<j≤n(xi − xj) bilden:

sage: prod((a - b) for (a,b) in Subsets([x1,x2,x3,x4],2))x1^3*x2^2*x3 - x1^2*x2^3*x3 - x1^3*x2*x3^2 + x1*x2^3*x3^2+ x1^2*x2*x3^3 - x1*x2^2*x3^3 - x1^3*x2^2*x4 + x1^2*x2^3*x4+ x1^3*x3^2*x4 - x2^3*x3^2*x4 - x1^2*x3^3*x4 + x2^2*x3^3*x4+ x1^3*x2*x4^2 - x1*x2^3*x4^2 - x1^3*x3*x4^2 + x2^3*x3*x4^2+ x1*x3^3*x4^2 - x2*x3^3*x4^2 - x1^2*x2*x4^3 + x1*x2^2*x4^3+ x1^2*x3*x4^3 - x2^2*x3*x4^3 - x1*x3^2*x4^3 + x2*x3^2*x4^3

bekommen wir 4! = 24 Terme. Dieselbe Konstruktion mit einem Ausdruck verbleibt in derfaktorisierten Form und ist viel kompakter und besser lesbar:

4im Sinne von Familien, nicht von Pythons Objektklassen

109

Page 126: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

sage: x1, x2, x3, x4 = SR.var('x1, x2, x3, x4')sage: prod((a - b) for (a,b) in Subsets([x1,x2,x3,x4],2))(x1 - x2)*(x1 - x3)*(x1 - x4)*(x2 - x3)*(x2 - x4)*(x3 - x4)

Ebenso ermöglicht eine faktorisierte oder teilfaktorisierte Darstellung eine schnellere Berech-nung des ggT. Es wäre jedoch nicht sinnvoll, jedes Polynom automatisch in faktorisierte Formzu bringen, selbst wenn es sich dabei um eine Normalform handelte, denn die Faktorisierungkostet Rechenzeit und macht Additionen kompliziert.

Je nach der gewünschten Rechenart ist die ideale Darstellung eines Elementes nicht immerseine Normalform. Das führt die symbolischen Rechensysteme zu einem Kompromiss mitden Ausdrücken. Etliche grundlegende Vereinfachungen wie das Kürzen von Brüchen oderdie Multiplikation mit null werden hier automatisch ausgeführt; die übrigen Transformatio-nen werden der Entscheidung des Anwenders überlassen, dem dafür spezische Befehle zurVerfügung stehen.

5.4.3. Beispiel: Faktorisierung von Polynomen

Betrachten wir die Faktorisierung des folgenden polynomialen Ausdrucks:

sage: x = var('x')sage: p = 54*x^4 + 36*x^3 - 102*x^2 - 72*x -12sage: factor(p)6*(x^2 - 2)*(3*x + 1)^2

Ist diese Antwort zufriedenstellend? Zwar handelt es sich um eine Faktorisierung von p, dochhängt ihre Optimalität stark vom Kontext ab! Für den Moment betrachtet Sage p als symbo-lischen Ausdruck, der sich als polynomial erweist. Er kann beispielsweise nicht wissen, ob wirp als Produkt von Polynomen mit ganzzahligen Koezienten faktorisieren möchten oder mitrationalen Koezienten.

Um hier die Kontrolle zu übernehmen, werden wir präzisieren, in welcher Menge wir p sehenwollen. Zunächst soll p ein Polynom mit ganzzahligen Koezienten sein. Wir denieren daherden Ring R = Z[x] solcher Polynome:

sage: R = ZZ['x']; RUnivariate Polynomial Ring in x over Integer Ring

Dann konvertieren wir p in diesen Ring:

sage: q = R(p); q54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12

An der Ausgabe sehen wir keinen Unterschied, doch q weiÿ, dass es ein Element von R ist:

sage: parent(q)Univariate Polynomial Ring in x over Integer Ring

Damit ist die Faktorisierung eindeutig:

sage: factor(q)2 * 3 * (3*x + 1)^2 * (x^2 - 2)

Wir verfahren genauso auf dem Körper der rationalen Zahlen:

110

Page 127: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.4. Ausdrücke versus Zahlenarten für das Rechnen

sage: R = QQ['x'], RUnivariate Polynomial Ring in x over Rational Fieldsage: q = R(p); q54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12sage: factor(q)(54) * (x + 1/3)^2 * (x^2 - 2)

In diesem neuen Kontext ist die Faktorisierung wieder eindeutig, doch verschieden von dervorigen.

Suchen wir jetzt eine vollständige Zerlegung auf den komplexen Zahlen mit 16 Bits Genauig-keit:

sage: R = ComplexField(16)['x']; RUnivariate Polynomial Ring in x over Complex Field with 16 bits ofprecisionsage: q = R(p); q54.00*x^4 + 36.00*x^3 - 102.0*x^2 - 72.00*x - 12.00sage: factor(q)(54.00) * (x - 1.414) * (x + 0.3333)^2 * (x + 1.414)

Anders ist es, wenn wir den Körper der rationalen Zahlen ein wenig erweitern; hier fügen wir√2 hinzu.

sage: R = QQ[sqrt(2)]['x']; RUnivariate Polynomial Ring in x over Number Field in sqrt2 with definingpolynomial x^2 - 2sage: q = R(p); q54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12sage: factor(q)(54) * (x - sqrt2) * (x + sqrt2) * (x + 1/3)^2

Wollen wir schlieÿlich sogar, dass die Koezienten modulo 5 sind?

sage: R = GF(5)['x']; RUnivariate Polynomial Ring in x over Finite Field of size 5sage: q = R(p); q4*x^4 + x^3 + 3*x^2 + 3*x + 3sage: factor(q)(4) * (x + 2)^2 * (x^2 + 3)

5.4.4. Zusammenfassung

In den vorstehenden Beispielen haben wir illustriert, wie der Anwender das Niveau der Strengein seinen Rechnungen steuern kann.

Einerseits kann er symbolische Ausdrücke verwenden. Diese Ausdrücke sind Elemente desRinges SR. Sie bieten zahlreiche Methoden (vorgestellt in Kapitel 2), die auf bestimmte Unter-klassen von Ausdrücken wie die polynomialen Ausdrücke angewendet werden. Die Erkenntnis,dass ein Ausdruck zu dieser oder jener Klasse gehört, erlaubt zu wissen, welche Funktionen fürdie Anwendung darauf infrage kommen. Ein Problem, bei dem dieses Wissen wichtig ist, istdie Vereinfachung von Ausdrücken. Wegen dieser Aufgaben wurden die wichtigsten Klassen

111

Page 128: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Denitionsmengen für das Rechnen

der Ausdrücke im CAS deniert, und dieser Ansatz ist es, dem wir im Verlauf dieses Buchessehr oft den Vorzug geben.

Andererseits kann der Anwender einen Vorfahren konstruieren, der die Denitionsbereichefür die Rechnung festlegt. Das ist besonders interessant, wenn dieser Vorfahr in Normalform

ist: das heiÿt, dass zwei Objektelemente genau dann mathematisch gleich sind, wenn sie diegleiche Darstellung haben.

Um es kurz zu sagen, die Flexibilität ist der Hauptvorteil der Ausdrücke: keine explizite Dekla-ration einer Denitionsmenge, die Einführung neuer Variablen und symbolischer Funktionenoder der Wechsel der Denitionsmenge während des Programmablaufs (wenn wir beispielswei-se den Sinus eines polynomialen Ausdrucks nehmen), die Verwendung der gesamten Palettevon Werkzeugen der Analysis (Integration usw.). Die Vorteile der expliziten Deklaration derDenitionsmenge bestehen in den didaktischen Möglichkeiten, einer oftmals gröÿeren Stren-ge5, die automatische Umwandlung in die Normalform (die auch ein Nachteil sein kann!), wieauch die Möglichkeit komplizierterer Konstruktionen, die mit Ausdrücken schwierig wären(Rechnungen auf einem endlichen Körper oder algebraische Erweiterungen von Q in einemnichtkommutativen Ring usw.).

5Sage ist kein zertiziertes CAS

112

Page 129: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Teil II.

Algebra und symbolisches Rechnen

113

Page 130: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 131: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

Die natürlichen Zahlen hat der liebe Gott gemacht.Alles andere ist Menschenwerk.

Leopold Kronecker (1823 - 1891)

Dieses Kapitel beschreibt die Verwendung von Sage in der elementaren Zahlentheorie zurBearbeitung von Objekten auf Ringen oder endlichen Körpern (Abschnitt 6.1), zu Primal-tests (Abschnitt 6.2) oder zur Faktorisierung einer ganzen Zahl (Abschnitt 6.3); schlieÿlichdiskutieren wir einige Anwendungen (Abschnitt 6.4).

6.1. Ringe und endliche Körper

Ringe und endliche Körper sind ein grundlegendes Objekt in der Zahlentheorie und ganz all-gemein beim symbolischen Rechnen. Tatsächlich stammen zahlreiche Algorithmen des sym-bolischen Rechnens vom Rechnen auf endlichen Körpern, dann nutzt man die mit Technikenwie dem Aufstieg von Hensel oder der Rekonstruktion mit chinesischen Resten erhalteneInformation. Erwähnen wir beispielsweise den Algorithmus von Cantor-Zassenhaus zur Fak-torisierung univariater Polynome mit ganzzahligen Koezienten, der mit der Faktorisierungdes gegebenen Polynoms auf einem endlichen Körper beginnt.

6.1.1. Ring der ganzen Zahlen modulo n

In Sage wird der Restklassenring Z/nZ der ganzen Zahlen modulo n mi Hilfe des KonstruktorsIntegerModRing (oder einfacher Integers) deniert. Alle mit diesem Konstruktor erzeugtenObjekte und ihre Ableitungen werden systematisch modulo n reduziert und haben somit einekanonische Form, das heiÿt, dass zwei Variable, die den gleichen Wert modulo n darstellen,auch die gleiche interne Darstellung besitzen. In bestimmten, sehr seltenen Fällen ist es e-zient, die Reduktionen modulo n zu verzögern, beispielsweise wenn wir Matrizen mit solchenKoezienten multiplizieren; man wird dann vorziehen, mit ganzen Zahlen zu arbeiten und dieReduktion modulo n von Hand via a%n vornehmen. Aber Achtung, der Modul n erscheintnicht explizit im ausgegebenen Wert:

sage: a = IntegerModRing(15)(3); b = IntegerModRing(17)(3); a, b(3, 3)sage: a == bFalse

Eine Konsequenz ist, dass wenn wir ganze Zahlen modulo n kopieren, wir die Informationüber n verlieren. Ist eine Variable gegeben, die eine Zahl modulo n enthält, gewinnen wir dieInformation über n mittels der Methoden base_ring oder parent zurück und erhalten denWert von n mit der Methode characteristic.

115

Page 132: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

sage: R = a.base_ring(); RRing of integers modulo 15sage: R.characteristic()15

Die Grundrechenarten Addition, Subraktion, Multiplikation und Division sind für ganze Zah-len modulo n überladen und rufen die entsprechenden Funktionen auf, ebenso werden dieganzen Zahlen automatisch konvertiert, sobald einer der Operanden eine ganze Zahl modulon ist:

sage: a + a, a - 17, a*a + 1, a^3(6, 1, 10, 12)

Was die Inversion 1/a mod n oder die Division b/a mod n betrit, so führt Sage sie aus,wenn das möglich ist, sonst wird ein ZeroDivisionError gemeldet, d.h. wenn a und b einennichttrivialen ggT haben.

sage: 1/(a + 1)4sage: 1/aTraceback (click to the left of this block for traceback)...ZeroDivisionError: Inverse does not exist.

Um den Wert von a zu erhalten - sofern er ganzzahlig ist - ausgehend vom Rest a mod n,können wir die Methode lift nutzen oder auch ZZ:

sage: z = lift(a); y = ZZ(a); print y, type(y), y == z3 <type 'sage.rings.integer.Integer'> True

Die additive Ordnung von a modulo n ist die kleinste ganze Zahl k > 0, sodass ka = 0mod n ist. Es gilt k = n/g mit g = ggT(a, n) und wird durch die Methode additive_orderangegeben (man sieht nebenbei, dass man auch mit Mod oder mod arbeiten kann, um die ganzenZahlen modulo n zu bekommen):

sage: [Mod(x,15).additive_order() for x in range(15)][1, 15, 15, 5, 15, 3, 5, 15, 15, 5, 3, 15, 5, 15, 15]

Die multiplikative Ordnung von a modulo n für a teilerfremd zu n ist die kleinste ganze Zahlk > 0, für die ak = 1 ist. (Wenn a mit n einen gemeinsamen Teiler p hat, dann ist ak mod nein Vielfaches von p für jedes k.) Wenn diese multiplikative Ordnung gleich ϕ(n) ist, nämlichdie multiplikative Gruppe modulo n, sagen wir, dass a ein Generator dieser Gruppe ist. Sogibt es für n = 15 keinen Generator, und die maximale Ordnung ist 4 < 8 = ϕ(15).

sage: [[x, Mod(x,15).multiplicative_order()]....: for x in range(1,15) if gcd(x,15) == 1][[1, 1], [2, 4], [4, 2], [7, 4], [8, 4], [11, 2], [13, 4], [14, 2]]

Hier ein Beispiel mit n = p prim mit dem Generator 3:

sage: p = 10^20+ 39; mod(2,p).multiplicative_order()50000000000000000019sage: mod(3,p).multiplicative_order()100000000000000000038

116

Page 133: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.1. Ringe und endliche Körper

Eine wichtige Operation auf Z/nZ ist die modulare Potenz , die darin besteht, ae mod n zuberechnen. Das Kryptosystem RSA beruht auf dieser Operation. Zur ezienten Berechnungvon ae mod n benötigen die ezientesten Algorithmen Multiplikationen der Ordnung log eoder Quadrate modulo n. Es kommt darauf an, alle Rechnungen systematisch modulo n zureduzieren, anstatt erst ae als ganze Zahl zu berechnen, wie dies das folgende Beispiel zeigt:

sage: n = 3^100000; a = n-1; e = 100sage: timeit('(a^e) % n')5 loops, best of 3: 373 ms per loopsage: timeit('power_mod(a,e,n)')25 loops, best of 3: 6.56 ms per loop

6.1.2. Endliche Körper

Die endlichen Körper1 werden mit dem Konstruktor FiniteField deniert (oder einfachermit GF). Wir können auch den Primzahlkörper GF(p) mit der Primzahl p wie die zusammen-gesetzten Körper mit GF(q) erzeugen. Dabei ist q = pk, p prim und k > 1 ganz. Wie beiden Ringen haben die auf einem solchen Körper generierten Objekte eine kanonische Form,daher erfolgt eine Reduktion bei jeder Operation. Die endlichen Körper haben die gleichenEigenschaften wie die Ringe (Unterabschnitt 6.1.1) und bieten zusätzlich die Möglichkeit, einvon null verschiedenes Element zu invertieren:

sage: R = GF(17); [1/R(x) for x in range(1,17)][1, 9, 6, 13, 7, 3, 5, 15, 2, 12, 14, 10, 4, 11, 8, 16]

Ein Körper Fpk , der kein Primzahlkörper ist, mit p prim und k > 1 ist zum Quotientenringder Polynome von Fp[x] modulo eines unitären und irreduziblen Polynoms f vom Grad kisomorph. In diesem Fall verlangt Sage einen Namen für den Generator des Körpers, also dieVariable x:

sage: R = GF(9,name='x'); RFinite Field in x of size 3^2

Hier wählt Sage das Polynom f automatisch:

sage: R.polynomial()x^2 + 2*x + 2

Die Elemente des Körpers werden nun durch die Polynome ak−1xk−1+. . .+a1x+a0 dargestellt,

wobei die ai Elemente von Fp sind:

sage: Set([r for r in R])0, 1, 2, x, x + 1, x + 2, 2*x, 2*x + 1, 2*x + 2

Wir können Sage auch das irreduzible Polynom f vorschreiben:

sage: Q.<x> = PolynomialRing(GF(3))sage: R2 = GF(9, name='x', modulus=x^2+1); R2Finite Field in x of size 3^2

1In der französischen (und in der deutschen) Literatur werden endliche Körper mit q Elementen üblicherweisemit Fq bezeichnet, während man in der englischsprachigen meistens GF(q) ndet. Wir verwenden hier diefranzösische (und deutsche) Schreibweise für die mathematischen Begrie und die englische im Sage-Code.

117

Page 134: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

Trotzdem ist Vorsicht geboten, denn wenn die beiden oben erzeugten Instanzen R und R2 auchzu F9 isomorph sind, ist der Isomorphismus dennoch nicht nutzbar:

sage: p = R(x+1); R2(p)Traceback (click to the left of this block for traceback)...TypeError: unable to coerce <class 'sage.interfaces.r.R'>

6.1.3. Rationale Rekonstruktion

Das Problem der rationalen Rekonstruktion ist eine hübsche Anwendung des Rechnens mitResten. Ist ein Rest modulo m gegeben, geht es darum, eine kleine rationale Zahl x/y zunden, sodass x/y ≡ a mod m. Wenn wir wissen, dass eine solche kleine rationale Zahlexistiert, dann, anstatt x/y direkt zu berechnen, insofern es rational ist, berechnen wir x/ymodulom, was den Rest a ergibt, dann nden wir x/y wieder durch rationale Rekonstruktion.Dieser zweite Weg ist oft eektiver, denn wir ersetzen rationale Berechnungen - bei denenaufwendige ggT auftreten - durch modulare Berechnungen.

Lemma. Seien a,m ∈ N, mit 0 < a < m. Es existiert höchstens ein Paar teilerfremder ganzerZahlen x, y ∈ Z, sodass x/y ≡ a mod m mit 0 < |x|, y ≤

√m/2.

Ein solches Paar x, y existiert nicht immer, beispielsweise für a = 2 und m = 5. Der Algo-rithmus der rationalen Rekonstruktion basiert auf dem Algorithmus des erweiterten ggT. Dererweiterte ggT von m und a berechnet eine Folge ganzer Zahlen, ai = αim + βia, wobei dieganzen Zahlen ai abnehmen, und die Absolutwerte der Koezienten αi, βi anwachsen. Dahergenügt es aufzuhören, sobald |αi|, |βi| ≤

√m/2 ist, und die Lösung ist dann x/y = αi/βi .

Dieser Algorithmus steht in Sage in Gestalt der Funktion rational_reconstruction zu Ver-fügung. Sie gibt x/y zurück, falls eine solche Lösung existiert und einen Fehler, falls nicht:

sage: rational_reconstruction(411,1000)-13/17sage: rational_reconstruction(409,1000)Traceback (click to the left of this block for traceback)...ArithmeticError: rational reconstruction of 409 (mod 1000) does not exist

Um die rationale Rekonstruktion zu veranschaulichen, betrachten wir die Berechnung derharmonischen Zahl Hn = 1 + 1/2 + . . .+ 1/n. Die naive Rechnung mit den rationalen Zahlengeht so:

sage: def harmonic(n):....: return add([1/x for x in range(1,n+1)])

Nun wissen wir, dass Hn in der Form pn/qn mit pn, qn ganz geschrieben werden kann, wobeiqn das kgV von 1, 2, . . . , n ist. Weiter wissen wir, dass Hn ≤ log n + 1 ist, was pn einzugren-zen erlaubt. Daraus leiten wir folgende Funktion ab, die Hn durch modulare Rechnung undrationale Rekonstruktion bestimmt:

sage: def harmonic_mod(n,m):....: return add([1/x % m for x in range(1,n+1)])sage: def harmonic2(n):....: q = lcm(range(1,n+1))

118

Page 135: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.1. Ringe und endliche Körper

....: pmax = RR(q*(log(n)+1))

....: m = ZZ(2*pmax^2)

....: m = ceil(m/q)*q + 1

....: a = harmonic_mod(n,m)

....: return rational_reconstruction(a,m)

Die Zeile m = ZZ(2*pmax^2) garantiert, dass die rationale Rekonstruktion den Wert p ≤√m/2 ndet, während die folgende Zeile sicherstellt, dass m prim ist mit x = 1, 2, . . . , n,

wenn 1/x mod n keinen Fehler auslöst.

sage: harmonic(100) == harmonic2(100)True

In diesem Beispiel ist die Funktion harmonic2 nicht ezienter als die Funktion harmonic, esverdeutlicht aber unsere Absicht. Es ist nicht immer erforderlich, eine strenge Grenze für x undy zu kennen, eine Schätzung π mal Daumen reicht hin, wenn man u.a. einfach verizierenwill, dass x/y die gesuchte Lösung ist.

Wir können die rationale Rekonsruktion mit einem Zähler x und einem Nenner y unterschied-licher Gröÿe verallgemeinern (siehe Abschnitt 5.10 in [vzGG03]).

6.1.4. Chinesische Reste

Eine weitere nützliche Anwendung der modularen Rechnung ist diejenige, die gemeinhin chi-nesische Reste heiÿt. Seien zwei teilerfremde Moduln m und n gegeben, eine ganzzahligeUnbekannte x, sodass x ≡ m mod m und x ≡ b mod n. Dann erlaubt der Chinesische Rest-

satz die eindeutige Rekonstruktion des Wertes von x modulo dem Produkt mn. In der Tatleitet man aus x ≡ a mod n her, dass x in der Form x = a+ λm geschrieben wird mit λ ∈ Z.Setzen wir diesen Wert in x ≡ b mod n ein, bekommen wir λ ≡ λ0 mod n mit λ0 = (b− a)/mmod n. Daraus resultiert x = x0 + µmn, wobei x0 = a+ λ0m ist und µ eine beliebige ganzeZahl.

Wir beschreiben hier die einfachste Variante der chinesischen Reste. Ebenso können wirden Fall mehrerer Moduln m1,m2, . . . ,mk betrachten. Der Befehl zum Aunden von x0 ausa, b,m, n ist in Sage crt(a,b,m,n).

sage: a = 2; b = 3; m = 5; n= 7; lambda0 = (b-a)/m % n; a + \lambda0*m17sage: crt(a,b,m,n)17

Kommen wir auf die Berechnung von Hn zurück. Zunächst berechnen wir Hn mod m füri = 1, 2, . . . , k. Dann leiten wir Hn mod (m1 · · ·mk) mit den chinesischen Resten her undnden Hn schlieÿlich durch rationale Rekonstruktion:

sage: def harmonic3(n):....: q = lcm(range(1,n+1))....: pmax = RR(q*(log(n)+1))....: B = ZZ(2*pmax^2)....: a = 0; m = 1; p = 2^63....: while m < B:....: p = next_prime(p)

119

Page 136: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

....: b = harmonic_mod(n,p)

....: a = crt(a,b,m,p)

....: m = m*p

....: return rational_reconstruction(a,m)sage: harmonic(100) == harmonic3(100)True

Sages Funktion crt funktioniert auch dann, wenn die Moduln m und n nicht teilerfremd sind.Es sei g = gcd(m,n). Dann gibt es eine Lösung genau dann, wenn a mod g ≡ b mod g gilt:

sage: crt(15,1,30,4)45sage: crt(15,2,30,4)Traceback (click to the left of this block for traceback)...ValueError: No solution to crt problem since gcd(30,4) does not divide 15-2

In Übung 22 stellen wir eine komplexere Anwendung der chinesischen Reste vor.

6.2. Primzahltests

Die Prüfung, ob eine ganze Zahl eine Primzahl ist, stellt eine fundamentale Operation einesProgramms für symbolische Rechnungen dar. Selbst wenn der Anwender nicht darauf achtet,werden solche Prüfungen vom Programm tausende Male pro Sekunde ausgeführt. Um bei-spielsweise ein Polynom aus Z[x] zu faktorisieren, beginnen wir damit, es in Fp[x] nach einerPrimzahl p zu zerlegen und müssen daher eine solche Zahl p nden.

Die wichtigsten BefehleRing der ganzen Zahlen modulo n IntegerModRing(n)

endlicher Körper mit q Elementen GF(q)

Test auf Pseudoprimalität is_pseudoprime(n)

Test auf Primalität is_prime(n)

Tab. 6.1 - Wiederholung.

Es existieren zwei Klassen von Primzahltests. Am ezientesten sind die Pseudoprimzahltests,die im allgemeinen auf dem kleinen Satz von Fermat basieren, welcher besagt, dass, wenn pprim ist, dann jede ganze Zahl 0 < a < p von der Ordnung ist, die p−1 in der multiplikativenGruppe (Z/pZ)∗ teilt, und ap−1 ≡ 1 mod p gilt. Generell verwenden wir einen kleinen Wertvon a (2, 3, . . .), um die Berechnung von ap−1 mod p zu beschleunigen. Ist ap−1 6≡ 1 mod p, istp sicher keine Primzahl. Falls ap−1 ≡ 1 mod p ist, können wir nichts folgern: wir sagen dann,p ist pseudoprim zur Basis a. Die Annahme ist, dass wenn eine ganze Zahl p pseudoprim istzu mehreren Basen, sie dann groÿe Chancen hat prim zu sein (siehe jedoch später). AllenPseudoprimzahltest ist gemeinsam, dass wenn sie False ergeben, die Zahl mit Sicherheitzusammenngesetzt ist, und bei True nichts gefolgert werden kann.

Die zweite Klasse wird von den echten Primzahltests gebildet. Diese Test geben immer ei-ne korrekte Antwort, können aber bei Zahlen, die zu vielen Basen pseudoprim sind, wenigerezient sein als die Pseudoprimzahltests, besonders aber dann, wenn sie echte Primzahlensind. Etliche Programme führen nur Pseudoprimzahltests aus. So lässt der Name der ent-sprechenden Funktion (zum Beispiel isprime) den Anwender glauben, es handele sich um

120

Page 137: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.2. Primzahltests

einen (echten) Primzahltest. Sage bietet zwei verschiedene Funktionen, den Pseudoprimzahl-test is_pseudoprime und den Primzahltest i_prime.

sage: p = previous_prime(2^400)sage: timeit('is_pseudoprime(p)')625 loops, best of 3: 603 µs per loopsage: timeit('is_prime(p)')5 loops, best of 3: 318 ms per loop

Wir sehen an diesem Beispiel, dass der Primzahltest sehr viel aufwendiger ist; wenn möglich,werden wir is_pseudoprime vorziehen.

Bestimmte Test-Algorithmen liefern ein Zertikat , das unabhängig veriziert werden kann,was oft ezienter ist als der Test selbst. Sage liefert in der aktuellen Version ein solchesZertikat noch nicht, doch mit dem Satz von Pocklington können wir eines erzeugen:

Satz. Sei n > 1 eine ganze Zahl, sodass n−1 = FR mit F ≥√n. Wenn für jeden Primfaktor

von F ein a existiert, sodass ap−1 ≡ 1 mod n gilt, und an−1p − 1 teilerfremd zu n ist, dann ist

n eine Primzahl.

Sei beispielsweise n = 231 − 1. Die Zerlegung von n − 1 ist 2 · 32 · 7 · 11 · 31 · 151 · 331. Wirkönnen F = 151 · 331 nehmen. a = 3 passt zu den beiden Faktoren p = 151 und p = 331. Nunreicht der Nachweis hin, dass 151 und 331 prim sind. Dieser Test macht intensiven Gebrauchvon der modularen Potenzierung.

Carmichael-Zahlen

Die Carmichael-Zahlen sind zusammengesetzte ganze Zahlen, die zu allen Basenpseudoprim sind. Der kleine fermatsche Satz erlaubt nicht, sie von Primzahlen zuunterscheiden, wieviele Basen auch probiert werden. Die kleinste Carmichael-Zahl ist561 = 3 ·11 ·17. Eine Carmichael-Zahl hat mindestens drei Primfaktoren. In der Tat,wenn wir annehmen, n = pq sei eine Carmichael-Zahl mit p, q prim und p < q, dannhaben wir nach Denition der Carmichael-Zahlen für jedes a, das (Z/pZ) erzeugt,die Gleichung an−1 ≡ 1 modulo n und dann auch modulo q, was impliziert, dassn− 1 ein Vielfaches von q − 1 ist, was mit n = pq wegen p < q aber nicht vereinbarist. Haben wir jedoch n = pqr, dann genügt an−1 ≡ 1 mod p - ebenso mit q und r -und wir erhalten mit dem chinesischen Restsatz an−1 ≡ 1 mod n. Eine hinreichendeBedingung ist, dass n− 1 ein Vielfaches von p− 1, q − 1 und r − 1 ist.

sage: [560 % (x-1) for x in [3, 11, 17]][0, 0, 0]

Übung 19. Schreiben Sie in Sage eine Funktion, die die Carmichael-Zahlen n = pqr ≤ Nzählt mit verschiedenen Primzahlen p, q, r. Wieviele nden Sie für N = 104, 105, 106, 107?(Richard Pinch hat 20138200 Carmichael-Zahlen unterhalb 1021 gezählt.)

Um eine Operation auf einem Intervall von Primzahlen auszuführen, ist es besser, mit derKonstruktion prime_range zu arbeiten, die mit einem Sieb eine Primzahlliste liefert, statteine Schleife mit next_probable_prime oder next_prime zu verwenden.

121

Page 138: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

sage: def count_primes1(n):....: return add([1 for p in range(n+1) if is_prime(p)])sage: timeit('count_primes(10^5)')5 loops, best of 3: 556 ms per loop

Die Funktion ist mit is_pseudoprime schneller als mit is_prime:

sage: def count_primes2(n):....: return add([1 for p in range(n+1) if is_pseudoprime(p)])sage: timeit('count_primes2(10^5)')5 loops, best of 3: 204 ms per loop

In nächsten Beispiel erweist es sich als besser, eine Schleife zu verwenden, die es vermeidet,eine Liste mit 105 Elementen zu erzeugen, und auch hier ist is_pseudoprime schneller alsis_prime:

sage: def count_prime3(n):....: s = 0; p = 2....: while p <= n: s += 1; p = next_prime(p)....: return ssage: timeit('count_prime3(10^5)')5 loops, best of 3: 67.4 ms per loopsage: def count_prime4(n):....: s = 0; p = 2....: while p <= n: s += 1; p = next_probable_prime(p)....: return ssage: timeit('count_prime4(10^5)')5 loops, best of 3: 53.2 ms per loop

Noch schneller geht es mit prime_range:

sage: def count_prime5(n):....: s = 0....: for p in prime_range(n): s += 1....: return ssage: timeit('count_prime5(10^5)')25 loops, best of 3: 4.7 ms per loop

6.3. Faktorisierung und diskreter Logarithmus

Wir sagen, eine ganze Zahl a ist ein Quadrat - oder ein quadratischer Rest - modulo n, wennein x existiert mit 0 ≤ x < n, sodass a ≡ x2 mod n ist. Andernfalls sagen wir, a ist keinquadratischer Rest modulo n. Ist n = p eine Primzahl, kann dieser Test dank der Berechnungdes Jacobi-Symbols von a und p, geschrieben (a|p), das die Werte -1,0,1 annehmen kann,ezient entschieden werden, Dabei bedeutet (a|p) = 0, dass a ein Vielfaches von p ist, und(a|p) = 1 (bzw. (a|p) = −1), dass a ein quadratischer Rest modulo p ist (bzw. nicht ist).Die Komplexität der Berechnung des Jacobi-Symbols (a|n) ist im wesentlichen die gleichewie die der Berechnung des ggT von a und n, nämlich O(M(l) log l), wobei l die Gröÿevon n ist und M(l) der Aufwand für das Produkt der beiden ganzen Zahlen der Gröÿe l. AlleImplementierungen des Jacobi-Symbols - wie auch des ggT - haben etwa dieselbe Komplexität(a.jacobi(n) berechnet (a|n)):

122

Page 139: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.3. Faktorisierung und diskreter Logarithmus

sage: p = (2^42737+1)//3; a = 3^42737sage: timeit('a.gcd(p)')125 loops, best of 3: 3.6 ms per loopsage: timeit('a.jacobi(p)')125 loops, best of 3: 3.59 ms per loop

Wenn n zusammengesetzt ist, ist die Suche nach den Lösungen von x2 ≡ a mod n genausoschwierig wie die Zerlegung von n. In jedem Fall gibt das Jacobi-Symbol, das relativ leicht zuberechnen ist, eine Teil-Information. Ist nämlich (a|n) = −1, gibt es keine Lösung, denn füreine Lösung muss (a|p) = 1 für alle Primfaktoren p von n gelten.

Der diskrete Logarithmus. Seien n eine natürliche Zahl, g ein Generator der multiplika-tiven Gruppe modulo n und a teilerfremd zu n mit 0 < a < n. Da g nach Voraussetzung einGenerator ist, gibt es eine ganze Zahl x, sodass gx = a mod n. Das Problem des diskretenLogarithmus besteht darin, eine solche ganze Zahl x zu nden. Die Methode log erlaubt dasProblem zu lösen:

sage: p = 10^10+19; a = mod(17,p); a.log(2)6954104378sage: mod(2,p)^6954104378;17

Die besten bekannten Algorithmen zur Berechnung eines diskreten Logarithmus sind vongleicher Komplexitätsordnung - als Funktion der Gröÿe von n - wie diejenigen zur Zerlegungvon n. Die aktuelle Implementierung in Sage ist durchaus annehmbar:

sage: p = 10^20+39; a = mod(17,9)sage: time r = a.log(3)Time: CPU 0.54 s, Wall: 1.00 s

Aliquot-Folgen (Inhaltsketten)

Die einer natürlichen Zahl n zugeordnete Aliquot-Folge ist die rekursiv denierteFolge (sk) mit s0 = n und sk+1 = σ(sk)− sk, wobei σ(k) die Summe der Teiler vonsk ist, d.h. sk+1 ist die Summe der echten Teiler von sk, also ohne sk selbst. Wirhalten die Iteration an, sobald sk = 1 ist - dann ist sk−1 prim - oder wenn die Folge(sk) einen Zyklus beschreibt. Ausgehend von n = 30 erhalten wir beispielsweise:

30, 42, 54, 66, 78, 90, 144, 259, 45, 33, 15, 9, 4, 3, 1.

Hat der Zyklus die Länge eins, nennen wir die entsprechende Zahl vollkommen, sosind zum Beispiel 6 = 1+2+3 und 28 = 1+2+4+7+14 vollkommene Zahlen. Wennder Zyklus die Länge zwei hat, nennen wir die beiden Zahlen befreundet , wie 220und 284. Hat der Zyklus die Länge drei oder mehr, heiÿen die den Zyklus bildendenZahlen gesellig .

Übung 20. Berechnen Sie die mit 840 beginnende Inhaltskette, geben Sie die 5 Primzahlenund die letzten 5 Elemente aus, und zeichnen Sie den Graphen von log10 sk als Funktion vonk (Sie können mit der Funktion sigma arbeiten).

123

Page 140: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Endliche Körper und elementare Zahlentheorie

6.4. Anwendungen

6.4.1. Die Konstante δ

Die Konstante δ ist eine zweidimensionale Verallgemeinerung der Konstanten γ von Euler. Sieist deniert wie folgt:

δ = limn→∞

(n∑k=2

1

πr2k

− log n

), (6.1)

wobei rk der Radius der kleinsten Scheibe der anen Ebene R2 ist, die mindestens k Punkteaus Z2 enthält, zum Beispiel r2 = 1/2, r3 = r4 =

√2/2, r5 = 1, r6 =

√5/2, r7 = 5/4,

r8 = r9 =√

2:

Übung 21 (Konstante von Masser-Gramain)

1. Schreiben Sie eine Funktion, die als Eingabe eine natürliche Zahl k erhält und den Radiusrk und den Mittelpunkt (xk, yk) einer kleinsten Scheibe zurückgibt, die mindestens kPunkte aus Z2 enthält. Wir nehmen rk <

√k/π an.

2. Schreiben Sie eine Funktion, die den Kreis mit dem Zentrum (xk, yk) und dem Radiusrk mit m ≥ k Punkten in Z2 zeichnet - wie oben zu sehen.

3. Berechnen Sie im Rahmen von√π(k − 6) + 2−

√2

π< rk <

√k − 1

π(6.2)

eine Näherung von δ mit einer Fehlerschranke von 0.3.

124

Page 141: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.4. Anwendungen

6.4.2. Berechnung mehrfacher Integrale durch rationale Rekonstruktion

Diese Anwendung ist durch den Artikel [Bea09] inspiriert. Seien k und n1, n2, . . . , nk natürlicheZahlen oder null. Wir wollen das Integral∫

Vxn1

1 xn22 · · ·x

nkk dx1dx2 · · · dxk

berechnen, wobei der Integrationsbereich durch V = x1 ≥ x2 ≥ . . . ≥ xk ≥ 0, x1 + . . .+ xx ≤ 1deniert ist. Wir erhalten beispielsweise für k = 2, n1 = 3, n2 = 5 den Wert

I =

∫ 1/2

x2=0

∫ 1−x2

x1=x2

x31x

52dx1dx2 =

13

258048.

Übung 22. Unter der Annahme, dass I rational ist, soll ein Algorithmus erstellt werden,der mit rationaler Rekonstruktion und/oder dem chinesischen Restsatz arbeitet, um I zuberechnen. Man implementiere diesen Algorithmus in Sage und wende ihn an auf den Fall

[n1, . . . , n31] = [9, 7, 8, 11, 6, 3, 7, 6, 6, 4, 3, 4, 1, 2, 2, 1, 1, 1, 2, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0].

125

Page 142: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 143: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Dieses Kapitel ist den Polynomen mit einer Unbestimmten und verwandten Objekten gewid-met, im wesentlichen den gebrochen rationalen Ausdrücken und den formalen Potenzreihen.Zu Anfang werden wir sehen, wie mit Sage zum Beispiel die euklidsche Polynomdivision ausge-führt wird, die Zerlegung in irreduzible Polynome, das Ziehen von Wurzeln oder die Zerlegungvon gebrochen rationalen Ausdrücken in einfache Elemente. Dies erfolgt unter Beachtung desRinges oder des Körpers, zu dem die Koezienten der betrachteten Polynome gehören: Sageerlaubt uns das Rechnen auf den Polynomringen A[x], deren Quotienten A[x]/ < (P (x) >,den Körpern der gebrochen rationalen Terme K(x) oder auch den Ringen der formalen Po-tenzreihen A[[x]] für eine ganze Palette von Basisringen.

Die Operationen auf den Polynomen haben aber auch überraschende Anwendungen. Wie errätman automatisch den nächsten Term der Folge

1, 1, 2, 3, 8, 11, 39, . . . ?

Beispielsweise mit der Padé-Approximation von gebrochen rationalen Funktionen, was in Un-terabschnitt 7.4.3 gezeigt wird! Wie werden die Lösungen der Gleichung exf(x) = f(x) mühelosin eine Reihe entwickelt? Die Antwort ndet man im Unterabschnitt 7.5.3.

Generell stellen wir uns vor, dass der Leser mit rationalen und gebrochen rationalen Ausdrückeauf dem Niveau einer universitären Veranstaltung für das erste Studienjahr umgehen kann.Darüber hinaus bringen wir auch einige anspruchsvollere Themen zur Sprache. (Wie beweistman, dass die Lösungen der Gleichung x5 − x − 1 = 0 sich nicht mit Wurzeln ausdrückenlassen? Es reicht hin, seine Galois-Gruppe zu berechnen wie in Unterabschnitt 7.3.4 erklärt.)Die entsprechenden Passagen werden später im Buch nicht gebraucht, und der Leser mag sieschadlos überspringen. Schlieÿlich enthält das Kapitel etliche Beispiele für die Manipulationalgebraischer und p-adischer Zahlen.

Die Polynome mit mehreren Unbestimmten sind ihrerseits Gegenstand des 9. Kapitels.

7.1. Polynomringe

7.1.1. Einführung

In Kapitel 2 haben wir gesehen. wie Rechnungen mit symbolischen Ausdrücken, den Elementendes symbolischen Ringes SR ausgeführt werden. Einige der auf diese Ausdrücke anwendbarenMethoden, zum Beispiel degree gelten für Polynome:

sage: x=var('x'); p = (2*x+1)*(x+2)*(x^4-1)sage: print(p, 'ist vom Grad', p.degree(x))(x+2)*(2*x+1)*(x^4-1) ist vom Grad 6

In manchen CAS wie Maple oder Maxima ist die Darstellung der Polynome als symbolischeAusdrücke die normale Art für ihre Bearbeitung. Nach dem Vorbild von Axiom, Magma oder

127

Page 144: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

MuPAD1 erlaubt Sage auch, Polynome mehr algebraisch zu behandeln und kann auf Ringenwie Q[x] oder Z/4Z[x, y, z] rechnen.

So weisen wir der Python-Variablen x die Unbestimmte des Polynomringes in x mit ratio-

nalen Koezienten zu, die durch polygen(QQ, 'x') statt der durch var('x') zurückgege-benen2symbolischen Variablen x zu, um das vorstehende Beispiel dadurch zu reproduzieren,dass wir auf einem wohldenierten Polynomring arbeiten.

sage: x = polygen(QQ, 'x'); p = (2*x+1)*(x+2)*(x^4-1)sage: print p, 'ist vom Grad', p.degree()2*x^6 + 5*x^5 + 2*x^4 - 2*x^2 - 5*x - 2 ist vom Grad 6

Zu beachten ist, dass das Polynom automatisch entwickelt wird. Die algebraischen Polynomewerden immer in Normalform dargestellt. Das ist ein wesentlicher Unterschied im Vergleich zuPolynomem aus SR. Insbesondere ist die Darstellung zweier mathematisch gleicher Polynomeim Rechner die gleiche, und ein Koezientenvergleich genügt für die Prüfung auf Gleichheit.

Die Möglichkeiten des Rechnens mit algebraischen Polynomen sind vielfältiger als die mitpolynomialen Ausdrücken.

7.1.2. Erzeugung von Polynomringen

In Sage haben Polynome wie viele andere algebraische Objekte im allgemeinen Koezientenaus einem kommutativen Ring. Diesen Standpunkt nehmen wir ein, doch die meisten unsererBeispiele betreen Polynome auf Körpern. Im ganzen Kapitel bezeichnen die Buchstaben Aund K einen kommutativen Ring bzw. einen beliebigen Körper.

Die erste Etappe zur Durchführung einer Rechnung in einer algebraischen Struktur R ist oftdie Erzeugung von R selbst. Wir erzeugen Q[x] mit

sage: R = PolynomialRing(QQ, 'x')sage: x = R.gen()

Manipulation von Polynomringen R = A[x]

Erzeugung (voll besetzt) R.<x> = A[] oder R.<x> = PolynomialRing(A, 'x')

Z[x], Q[x], R[x], Z/nZ[x] ZZ['x'], QQ['x'], RR['x'], Integers(n)['x']

Erzeugung (dünn besetzt) R.<x> = PolynomialRing(A, 'x', sparse=True)

Zugri auf den Basisring A R.base_ring()

Zugri auf die Variable x R.gen() oder R.0Prüfungen

(ganzzahlig, noethersch, ...) R.is_integral_domain(), R.is_noetherian(), ...

Tab. 7.1 - Polynomringe

Das 'x' in der ersten Zeile ist eine Zeichenkette, der Name der Unbestimmten oder der Gene-rator des Ringes. Das x der zweiten Zeile ist eine Python-Variable, in der wir den Generatorwiedernden; die Verwendung des gleichen Namens verbessert die Lesbarkeit des Codes. Dasso in der Variablen x gespeicherte Objekt repräsentiert das Polynom x ∈ Q[x]. Als Vorfahr(in Sage ist der Vorfahr eines Objektes die algebraische Struktur aus der es stammt, sieheAbschnitt 5.1) hat es den Ring QQ['x']:

1MuPAD ist inzwischen an Mathworks Inc. (MATLAB) verkauft worden.2Ein kleiner Unterschied: wenn var('x') die gleiche Wirkung hat wie x = var('x') bei der interaktivenVerwendung, dann ändert polygen(QQ, 'x') ohne Zuweisung den Wert der Python-Variablen x nicht.

128

Page 145: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.1. Polynomringe

sage: x.parent()Univariate Polynomial Ring in x over Rational Field

Polynome mit polynomialen Koezienten

In Sage können wir Ringe von Polynomen denieren, deren Koezienten wieder-um Polynome aus einem beliebigen kommutativen Ring sind - einschlieÿlich einemanderen Polynomring. Doch Vorsicht, Ringe des nach diesem Verfahren gebildetenTyps A[x][y] sind von den echten Polynomringen mit mehreren Variablen wie A[x, y]verschieden. Die letzteren, die in Kapitel 9 vorgestellt werden, sind für die gängigenRechnungen besser geeignet. Tatsächlich gleicht die Arbeit mit A[x][y] . . . oft einemSpiel mit Unbestimmten sehr unsymmetrischen Verhaltens.Dennoch möchten wir gelegentlich eine Variable bevorzugen und die anderen alsParameter behandeln. Die Methode polynomial der multivariaten Polynome erlaubtdie Isolation einer Variablen, etwa wie die Methode collect der Ausdrücke. Hierals Beispiel die Berechnung des reziproken Polynoms eines hinsichtlich einer seinerUnbestimmten gegebenen Polynoms:sage: R.<x,y,z,t> = QQ[]; p = (x+y+z*t)^2sage: p.polynomial(t).reverse()(x^2 + 2*x*y + y^2)*t^2 + (2*x*z + 2*y*z)*t + z^2Hier erzeugt p.polynomial(t) ein Polynom mit der einzigen Unbestimmten t undKoezienten aus QQ[x,y,z], auf welches wir dann die Methode reverse anwenden.Die übrigen Konversionen zwischen A[x, y, . . .] und A[x][y] . . . funktionieren wie er-wartet:sage: x = polygen(QQ); y = polygen(QQ[x], 'y')sage: p = x^3 + x*y + y + y^2; py^2 + (x + 1)*y + x^3sage: q = QQ['x,y'](p); qx^3 + x*y + y^2 + ysage: QQ['x']['y'](q)y^2 + (x + 1)*y + x^3

Das Polynom x ∈ Q[x] wird zugleich als verschieden angesehen von den Polynomen derIdentität x ∈ A[x], vom Basisring A 6= Q und von denen, deren Unbestimmte einen anderenNamen hat wie t ∈ Q[t].

sage: x = PolynomialRing(QQ, 'x').gen()

Bei dieser Gelegenheit sei darauf hingewiesen, dass wir aus mehreren Darstellungsweisen imSpeicher wählen können, wenn wir einen Polynomring erzeugen. Die Unterschiede zwischenden Darstellungsweisen werden in Abschnitt 7.6 diskutiert werden.

Übung 23 (Variable und Unbestimmte).

1. Wie sind x und y zu denieren, um folgende Ergebnisse zu beobachten?

sage: x^2 + 1y^2 + 1sage: (y^2 + 1).parent()Univariate Polynomial Ring in x over Rational Field

129

Page 146: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

2. Welchen Wert besitzt p nach den Anweisungen

sage: Q.<x> = QQ[]; p = x + 1; x = 2; p = p + x

7.1.3. Polynome

Erzeugung und einfache Arithmetik. Nach der Anweisung R.<x> = QQ[] sind die mit x undrationalen Konstanten und mit + und ∗ gebildeten Ausdrücke Elemente von Q[x]. Beispiels-weise legt Sage bei p = x + 2 automatisch fest, dass der Wert der Variablen x und die Zahl2 beide als Elemente von Q[x] interpretiert werden können. Daher wird die Additionsroutinevon Q[x] aufgerufen; sie liefert das Polynom x+ 2 ∈ Q[x].

Eine andere Möglichkeit der Erzeugung eines Polynoms besteht aus der Auistung seinerKoezienten:

sage: def turm_polynomial(n, var='x'):....: return ZZ[var]([binomial(n, k)^2*factorial(k) for k in (0..n)])

Diese Funktion erzeugt Polynome, bei denen der Koezient von xk als Anzahl der Möglich-keiten interpretiert wird, k Türme auf einem Schachbrett so aufzustellen, dass sie sich nichtbedrohen - daher der Name. Die Klammern nach ZZ[var] dienen der Umwandlung eines ge-gebenen Objektes in ein Element dieses Ringes. Die Konversion einer Liste [a0, a1, . . .] in einElement von ZZ['x'] gibt das Polynom a0 + a1x+ . . . ∈ Z[x] zurück.

Zugri auf Daten, syntaktische OperationenUnbestimmte x p.variables(), p.variable_name()

Koezient von xk p[k]

führender Koezient p.leading_coefficient()

Grad p.degree()

Liste der Koezienten p.coeffs()

Liste der von null verschiedenen Koezienten p.coefficients()

Diktionär Grad 7→ Koezient p.dict()

Prüfungen (unitär, konstant, . . . ) p.is_monic(), p,is_constant, ...

einfache ArithmetikOperationen p+ q, p− q, p× q, pk p + q, p - q, p*q, p^k

Substitution x := a p(a) oder p.subs(a)Ableitung p.derivative() oder diff(p)

TransformationenTransformation der Koezienten p.map_coefficients(f)

Wechsel des Basisrings A[x] 7→ B[x] p.change_ring(B) oder B['x'](p)reziprokes Polynom p.reverse()

Tab. 7.2 - einfache Operationen mit den Polynomen p, q ∈ A[x].

Übersicht über die Menge der Operationen auf Polynomen. Die Elemente eines Poly-nomringes werden als Python-Objekte der Klasse Polynomial oder abgeleiteter Klassen dar-gestellt. Die wichtigsten verfügbaren Operationen3 auf diesen Objekten sind in den Tabellen

3Davon gibt es noch viel mehr. Die Tabellen führen keine zu sehr zugespitzte Funktionalitäten auf, keinestärker spezialisierten Varianten der erwähnten Methoden und auch nicht viele der Methoden, die allenElementen von Ringen gemeinsam sind, auch keine Sage-Objekte, die für Polynome nicht von besonderemInteresse sind. Wir weisen jedoch darauf hin, dass die speziellen Methoden (zum Beispiel p.rescale(a),das zu p(a*x) äquivalent ist), oftmals ezienter sind als die mehr generellen Methoden, die sie ersetzenkönnen.

130

Page 147: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.1. Polynomringe

7.2 bis 7.5 zusammengestellt. So ndet man den Grad eines Polynoms durch Aufruf seiner Me-thode degree. Ebenso ergibt p.subs(a) oder einfach p(a) den Wert von p im Punkt a, dientaber auch zur Berechnung der Komposition p a, wenn a selbst ein Polynom ist, und, nochallgemeiner, der Auswertung eines Polynoms aus A[x] in einem Element einer A-Algebra:

sage: R.<x> = QQ[]sage: p = R.random_element(degree=4) # ein zufälliges Polynomsage: p1/2*x^4 - x^3 + 1/4*x^2 - 5/4*x - 1/2sage: p.subs(x^2)1/2*x^8 - x^6 + 1/4*x^4 - 5/4*x^2 - 1/2 sage: p.subs(matrix([[1,2],[3,4]]))[125/2 91][273/2 199]

Auf den Inhalt der beiden letzten Tabellen kommen wir in Unterabschnitt 7.2.1 und Abschnitt7.3 zurück.

Wechsel des Ringes. Die exakte Liste der verfügbaren Operationen, ihr Eekt und ihreEzienz hängen stark vom Basisring ab. Beispielsweise besitzen die Polynome aus ZZ['x']eine Methode content, die ihren Inhalt zurückgibt, d.h. den ggT ihrer Koezienten; die vonQQ['x'] aber nicht, weil die Operation trivial ist. Die Methode factor existiert für alle Poly-nome, wirft aber eine Exzeption NotImplementedError bei einem Polynom mit Koezientenaus SR oder aus Z/4Z. Diese Exzeption bedeutet, dass diese Operation für diesen Objekttypin Sage nicht zur Verfügung steht, obwohl sie einen mathematischen Sinn hat.

Daher ist es sehr angenehm, mit den verschiedenen Ringen von Koezienten jonglieren zukönnen, auf denen wir dasselbe Polynom betrachten können. Angewendet auf ein Polynomaus A[x] gibt die Methode change_ring sein Bild in B[x] zurück, wenn eine Methode zurKonversion der Koezienten existiert. Oft geschieht die Konversion durch einen kanonischenMorphismus von A nach B: insbesondere dient change_ring zur Erweiterung des Basisrings,um zusätzliche algebraische Eigenschaften anzubringen. In diesem Beispiel ist das Polynomirreduzibel auf den ganzen Zahlen, wird aber auf R faktorisiert:

sage: x = polygen(QQ)sage: p = x^2 - 16*x + 3sage: p.factor()x^2 - 16*x + 3sage: p.change_ring(RDF).factor()(x - 15.810249675906654) * (x - 0.18975032409334563)

RDF ist die Menge der Maschinenzahlen, die in Kapitel 11 vorgestellt werden. Die erhalteneZerlegung ist nur eine Näherung, mit ihr kann das Ausgangspolynom nicht exakt rekonstruiertwerden. Zu einer solchen Darstellung der reellen Wurzeln von Polynomen mit ganzzahligenKoezienten, die exakte Rechnungen erlaubt, verwenden wir die Menge AA der algebraischenreellen Zahlen. In den folgenden Abschnitten werden wir einige Beispiel sehen.

Die Methode change_ring ermöglicht auch die Reduktion eines Polynoms aus Z[x] moduloeiner Primzahl:

sage: p.change_ring(GF(3))x^2 + 2*x

131

Page 148: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Wenn umgekehrt B ⊂ A ist und die Koezienten von p in B liegen, dann ist es wiederchange_ring, womit wir p nach B[x] zurückholen.

Iteration. Zuweilen müssen wir eine Transformation auf alle Koezienten eines Polynomsanwenden. Dazu ist die Methode map_coefficients da. Wird sie auf ein Polynom A[x] miteiner Funktion f als Parameter angewendet, gibt sie das eingegebene Polynom zurück, nach-dem die Funktion f auf jeden von null verschiedenen Koezienten von p angewendet wordenist. Meistens ist f eine mit der Konstrultion lambda eingeführte anonyme Funktion (sieheUnterabschnitt 3.3.2). Hier ein Beispiel, wie die Konjugierte eines Polynoms mit komplexenKoezienten zu berechnen ist:

sage: QQi.<myI> = QQ[I] # myI ist das i von QQi, I dasjenige von SRsage: R.<x> = QQi[]; p = (x + 2*myI)^3; px^3 + 6*I*x^2 - 12*x - 8*Isage: p.map_coefficients(lambda z: z.conjugate())x^3 - 6*I*x^2 - 12*x + 8*I

Im vorliegenden Fall können wir auch schreiben p.map_coefficients(conjugate), denn fürz ∈ Q hat conjugate(z) die gleiche Wirkung wie z.conjugate. Der explizite Aufruf ei-ner Methodes des Objektes z ist sicherer: der Code funktioniert so mit allen einer Methodeconjugate() übergebenen Objekten und nur dort.

Teilbarkeit und euklidsche DivisionPrüfung auf Teilbarkeit p | q p.divides(q)

Multiplizität eines Teilers qk | p k = p.valuation(q)

euklidsche Division p = qd+ r q, r = p.quo_rem(d) oder q = p//d, r = p%d

Pseudodivision akp = qd+ r q, r, k = p.pseudo_divrem(d)

gröÿter gemeinsamer Teiler p.gcd(q) oder gcd([p1, p2, p3])

kleinstes gemeinsames Vielfaches p.lcm(q) oder lcm([p1, p2, p3])

erweiterter ggT g = up+ vq g, u, v = p.xgcd(q) oder xgcd(p,q)chinesische Reste c ≡ a mod p c = crt(a, b, p, q)

c ≡ p mod qVerschiedenes

Interpolation p(xi) = yi p = R.lagrange_polynomial([(x1,y1), ...])

Inhalt von p ∈ Z[x] p.content()

Tab. 7.3 - Arithmetik der Polynome

7.2. Euklidsche Arithmetik

Nach Summe und Produkt sind hier die elementarsten Operationen die euklidsche Divisionund die Berechnung des gröÿten gemeinsamen Teilers (ggT). Die entsprechenden Operatorenund Methoden (Tab. 7.3) ähneln denjenigen der ganzen Zahlen. Doch oft sind diese Opera-tionen unter einer Decke zusätzlicher mathematischer Abstraktion verborgen: Quotienten vonRingen (Unterabschnitt 7.2.2), wo jede arithmetische Operation eine implizite euklidsche Di-vision enthält, oder gebrochen rationale Ausdrücke, zu deren Normierung der ggT berechnetwird usw.

132

Page 149: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.2. Euklidsche Arithmetik

7.2.1. Teilbarkeit

Die euklidsche Division funktioniert auf einem Körper, und allgemeiner auf einem kommu-tativen Ring. Wenn der führende Koezient des Divisors invertierbar ist, dann ist dieserKoezient das einzige Element des Basisringes, durch den bei der Berechnung zu dividierenist:

Operationen auf Polynomringen

Die Vorfahren polynomialer Objekte, die Ringe A[x], sind ihrerseits vollwertige Sage-Objekte. Schauen wir kurz, wozu sie dienen können.Eine erste Familie von Methoden erlaubt die Bildung von interessanten Polynomen,ihre zufällige Auswahl oder die Auistung ganzer Familien von Polynomen; dies hiersind alle Polynome zweiten Grades auf F2:sage: list(GF(2)['x'].polynomials(of_degree=2))[x^2, x^2 + 1, x^2 + x, x^2 + x + 1]Einige dieser Methoden werden wir in den folgenden Beispielen aufrufen, um Objektezu erzeugen, mit denen wir arbeiten. Das 15. Kapitel erklärt in gröÿerer Allgemein-heit, wie Elemente endlicher Mengen in Sage aufgezählt werden.Zweitens kennt das System einige Fakten zu jedem Polynomring. Wir können tes-ten, ob ein gegebenes Objekt ein Ring ist, ob es noethersch ist:sage: A = QQ['x']sage: A.is_ring() and A.is_noetherian()Trueoder auch, ob Z ein Unterring von Q[x] ist, und für welche Werte von n der RingZ/nZ integral ist.sage: ZZ.is_subring(A)Truesage: [n for n in range(20)....: if Integers(n)['x'].is_integral_domain()][0, 2, 3, 5, 7, 11, 13, 17, 19]Diese Möglichkeiten beruhen weitgehend auf dem System von Kategorien von Sage(siehe auch Unterabschnitt 5.2.3). Die Polynomringe sind Glieder einer bestimmtenZahl von Kategorien, wie der Kategorie der Mengen, der Kategorie der euklidschenRinge und einiger anderer:sage: A.categories()[Join of Category of euclidean domains and Category of commutative...Category of sets with partial maps, Category of objects]Das spiegelt wider, dass jeder Polynomring auch eine Menge ist, ein euklidscherRing und so fort. Das System kann die allgemeinen Eigenschaften der Objekte dieserverschiedenen Kategorien auf die Polynomringe automatisch übertragen.

sage: R.<t> = Integers(42)[]; (t^20-1) % (t^5+8*t+7)22*t^4 + 14*t^3 + 14*t + 6

Da der führende Koezient nicht invertierbar ist, können wir eine euklidsche Pseudodivisiondenieren: seien A ein kommutativer Ring, p, d ∈ A[x] und a der führende Koezient von

133

Page 150: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

d. Dann existieren zwei Polynome q, r ∈ A[x] mit deg(r) < deg(d) und eine ganze Zahlk ≤ deg(p)− deg(d) + 1, sodass gilt

akp = qd+ r.

Die euklidsche Pseudodivision ist gegeben durch pseudo_divrem.

Um eine exakte Division auszuführen, verwendet man ebenfalls den euklidschen Divisionsope-rator //. Tatsächlich gibt die Division durch ein nicht konstantes Polynom mit / ein Resultatgebrochen-rationalen Typs zurück, was scheitert, weil es keinen Sinn ergibt:

sage: ((t^2+t)//t).parent()Univariate Polynomial Ring in t over Ring of integers modulo 42sage: (t^2+t)/tTraceback (click to the left of this block for traceback)...TypeError: self must be an integral domain.

Übung 24. Normalerweise werden Polynome aus Q[x] in Sage mit der monomialen Basis(xn)n∈N dargestellt. Die durch Tn(cos θ) = cos(nθ) denierten Tschebyschow-Polynome bil-den eine Familie von orthogonalen Polynomen und somit eine Basis von Q[x]. Die erstenTschebyschow-Polynome sind

sage: x = polygen(QQ); [chebyshev_T(n, x) for n in (0..4)][1, x, 2*x^2 - 1, 4*x^3 - 3*x, 8*x^4 - 8*x^2 + 1]

Schreiben Sie eine Funktion, der als Argument ein Element aus Q[x] übergeben wird undwelche die Koezienten der Zerlegung zur Basis (Tn)n∈N zurückgibt.

Übung 25. (Division nach wachsenden Potenzen). Seien n ∈ N und u, v ∈ A[x] mit invertier-barem v[0]. Dann existiert eindeutig ein Paar (q, r) von Polynomen aus A[x] mit deg(q) ≤ n,sodass gilt u = qv+xn+1r. Schreiben Sie eine Funktion, die q und r mit einem Analogon zumAlgorithmus der euklidschen Division berechnet. Wie ist diese Rechnung mit existierendenFunktionen am einfachsten zu machen?

ggT. Sage kann den ggT von Polynomen auf einem Körper dank der euklidschen Strukturvon K[x] berechnen, aber auch auf bestimmten anderen Ringen wie den ganzen Zahlen:

sage: S.<x> = ZZ[]; p = 2*(x^10-1)*(x^8-1)sage: p.gcd(p.derivative())2*x^2 - 2

Wir können den mehr symmetrischen Ausdruck gcd(p,q) vorziehen, der das gleiche Resultatliefert wie p.gcd(q). Er ist in Sage allerdings nicht ganz so natürlich, denn das ist keinallgemeiner Mechanismus: die von gcd(p,q) aufgerufene Routine ist eine Funktion mit zweiArgumenten, die im Quellcode von Sage manuell deniert ist und ihrerseits p.gcd aufruft.Nur ein paar der üblichen Methoden besitzen eine solche zugeordnete Funktion. Der erweiterteggT (engl. extended greatest common divisor), d.h. die Berechnung einer Bézout-Identität

g = ggT(p, q) = ap+ bq, g, p, q, a, b ∈ K[x]

wird durch p.xgcd(q) geliefert:

134

Page 151: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.2. Euklidsche Arithmetik

sage: R.<x> = QQ[]; p = x^5-1; q = x^3-1sage: print 'Der ggT ist %s = (%s)*p + (%s)*q.' % p.xgcd(q)Der ggT ist x - 1 = (-x)*p + (x^3 + 1)*q.

Die Methode xgcd existiert auch für Polynome aus ZZ['x'], aber Vorsicht: da der Ring Z[x]kein Hauptidealring ist, ist das Ergebnis im allgemeinen keine Bézout-Identität!

7.2.2. Ideale und Quotientenringe

Ideale aus A[x]. Die Ideale der Polynomringe und die Quotientenringe dieser Ideale werdendurch Sage-Objekte dargestellt, die mit ideal und quo aus Polynomringen gebildet werden.Das Produkt eines Tupels von Polynomen mit einem Polynomring wird als Ideal interpre-tiert:

sage: R.<x> = QQ[]sage: J1 = (x^2 - 2*x + 1, 2*x^2 + x - 3)*R; J1Principal ideal (x - 1) of Univariate Polynomial Ring in x over Rational Field

Wir können die Ideale multiplizieren und ein Polynom modulo eines Ideals reduzieren:

sage: J2 = R.ideal(x^5 + 2)sage: ((3*x+5)*J1*J2).reduce(x^10)421/81*x^6 - 502/81*x^5 + 842/81*x - 680/81

In diesem Fall bleibt das reduzierte Polynom ein Element von QQ['x']. Eine andere Möglich-keit besteht darin, den Quotientenring duch ein Ideal zu bilden und die Elemente darauf zuprojizieren. Dessen Vorfahr ist dann der Quotientenring. Die Methode lift der Elemente desQuotientenrings dient dann dazu, sie wieder in den Ausgangsring zurückzuführen.

sage: B = R.quo((3*x+5)*J1*J2) # quo heiÿt automatisch 'xbar'sage: B(x^10) # der Generator des Bildes B von x421/81*xbar^6 - 502/81*xbar^5 + 842/81*xbar - 680/81sage: B(x^10).lift()421/81*x^6 - 502/81*x^5 + 842/81*x - 680/81

Ist K ein Körper, ist K[x] ein Hauptidealring: Ideale werden bei den Rechnungen durch einenGenerator dargestellt, und all das ist wohl kaum eine besonders algebraische Sprache für die inUnterabschnitt 7.2.1 gezeigten Operationen. Ihr Hauptverdienst ist, dass die Quotientenringein neuen Konstrktionen mühelos verwendet werden können, hier die von

(F5[t]/(t2 + 3)

)[x]:

sage: R.<t> = GF(5)[]; R.quo(t^2+3)['x'].random_element()(2*tbar + 1)*x^2 + (2*tbar + 1)*x + 2*tbar

Sage erlaubt auch die Bildung von Idealen, die keine Hauptidealringe sind wie Z[x], doch sinddie verfügbaren Funktionen begrenzt - auÿer im Fall von Polynomen mit mehreren Unbe-stimmten auf einem Körper. Das ist Gegenstand von Kapitel 9.

Übung 26. Wir denieren die Folge (un)n∈N durch die Anfangsbedingungen un = n+ 7 für0 ≤ n < 1000 und die Relation der linearen Rekursion

un+100 = 23un+729 − 5un+2 + 12un+1 + 7un (n ≥ 0).

135

Page 152: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Berechnen Sie die letzten fünf Ziern von u1010000 . Hinweis: wir können uns durch den Al-gorithmus in Unterabschnitt 3.2.4 inspirieren lassen. Der braucht aber zu lange, wenn dieOrdnung der Rekursion hoch ist. Führen Sie einen sinnvollen Quotientenring ein, um diesesProblem zu vermeiden.

Bildung von Idealen und Quotientenringen Q = R/J

Ideal < u, v, w > R.ideal(u, v, w) oder (u, v, w)*R

Reduktion von p modulo J J.reduce(p) oder p.mod(J)Quotientenring R/J,R/(p) R.quo(J), R.quo(p)

Q zu einem Quotientenring gemacht Q.cover_ring()

Körper der isomorphen Zahlen Q.number_field()

Elemente von K[x]/p

erhoben (Schnitt von R→ R/J) u.lift()

minimales Polynom u.minpoly()

charakteristisches Polynom u.charpoly()

Matrix u.matrix()

Spur u.trace()

Tab. 7.4 - Ideale und Quotientenringe

Algebraische Erweiterungen. Ein wichtiger Sonderfall ist der Quotient von K[x] durch einirreduzibles Polynom, um eine algebraische Erweiterung von K zu realisieren. Die Körperder Zahlen, endliche Erweiterungen von Q, werden durch NumberField-Objekte dargestelltund sind von Quotienten von QQ['x'] verschieden. Wenn das Sinn macht, gibt die Methodenumber_field eines Quotientenringes von Polynomen den Körper der entsprechenden Zahlenzurück. Die Schnittstelle des Körpers der Zahlen, der umfangreicher ist als der der Quotien-tenringe, sprengt den Rahmen dieses Buches. Die als algebraische Erweiterungen der primenendlichen Körper Fp realisierten zusammengesetzten endlichen Körper Fpk sind im Abschnitt6.1 beschrieben.

7.3. Faktorisierung und Wurzeln

Eine dritte Ebene nach den elementaren Operationen und der euklidschen Arithmetik betritdie Zerlegung von Polynomen in Produkte irreduzibler Faktoren oder die Faktorisierung. Dasist vielleicht das Gebiet, wo sich das symbolische Rechnen am nützlichsten erweist.

7.3.1. Faktorisierung

Prüfung auf Irreduzierbarkeit. Auf der algebraischen Ebene ist die einfachste Frage, diedie Faktorisierung eines Polynoms betrit, ob es als Produkt zweier nichttrivialer Faktorengeschrieben werden kann, oder, im Gegenteil, irreduzibel ist. Natürlich hängt die Antwort vomBasisring ab. Die Methode is_irreducible zeigt, ob ein Polynom auf seinem Vorfahrringirreduzibel ist. Beispielsweise ist das Polynom 3x2 − 6 auf Q reduzibel, auf Z aber nicht(warum?).

sage: R.<x> = QQ[]; p = 3*x^2 - 6sage: p.is_irreducible(), p.change_ring(ZZ).is_irreducible()(True, False)

136

Page 153: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.3. Faktorisierung und Wurzeln

Faktorisierung. Die Primfaktorzerlegung einer ganzen Zahl mit hunderten oder tausendenvon Stellen ist eine sehr schwierige Aufgabe. Dagegen braucht die Faktorisierung eines Poly-noms 1000. Grades auf Q oder Fp nur ein paar Sekunden Prozessorzeit4:

sage: p = QQ['x'].random_element(degree=1000)sage: timeit('p.factor()')5 loops, best of 3: 5.23 s per loop

Daher endet hier die algorithmische Ähnlichkeit von Polynomen und ganzen Zahlen, die wir inden vorhergehenden Abschnitten beobachten konnten. Genau wie der Test auf Irreduzibilitätndet die Faktorisierung auf dem Basisring des Polynoms statt. Beispielsweise setzt sich dieFaktorisierung eines Polynoms auf Z aus einem konstanten Teil, der in Primzahlen zerlegt ist,und einem Produkt von primitiven Polynomen zusammen, die untereinander teilerfremd sind:

sage: x = polygen(ZZ); p = 54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12sage: p.factor()2 * 3 * (3*x + 1)^2 * (x^2 - 2)

Sage erlaubt die Zerlegung auf verschiedenen Ringen - rationalen, komplexen (näherungswei-se), endlichen Körpern und besonders Zahlenkörpern:

sage: for A in [QQ, ComplexField(16), GF(5), QQ[sqrt(2)]]:....: print A, ':'; print A['x'](p).factor()Rational Field :(54) * (x + 1/3)^2 * (x^2 - 2)Complex Field with 16 bits of precision :(54.00) * (x - 1.414) * (x + 0.3333)^2 * (x + 1.414)Finite Field of size 5 :(4) * (x + 2)^2 * (x^2 + 3)Number Field in sqrt2 with defining polynomial x^2 - 2 :(54) * (x - sqrt2) * (x + sqrt2) * (x + 1/3)^2

FaktorisierungTest auf Irreduzibilität p.is_irreducible

Faktorisierungt p.factor()

quadratfreie Faktorisierungt p.squarefree_decomposition()

quadratfreiet Teil p/ggT (p, p′)t p.radical()

WurzelnWurzeln in A, in D p.roots(), p.roots(D)

reelle Wurzeln p.roots(RR), p.real_roots()

komplexe Wurzeln p.roots(CC), p.complex_roots()

Isolation der reellen Wurzeln p.roots(RIF)

Isolation der komplexen Wurzeln p.roots(CIF)

Resultante p.resultant(q)

Diskriminante p.discriminant()

Galois-Gruppe (p irreduzibel) p.galois_group()

Tab. 7.5 - Faktorisierung und Wurzeln

4Von einem theoretischen Standpunkt können wir in Q[x] in polynomialer Zeit faktorisieren und in Fp[x] inprobabilistisch polynomialer Zeit, währen wir nicht wissen, ob es möglich ist, ganze Zahlen in polynomialerZeit zu faktorisieren.

137

Page 154: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Das Ergebnis einer Zerlegung in irreduzible Faktoren ist kein Polynom (weil Polynome immerin Normalform sind, d.h. ausmultipliziert!), sondern ein Objekt f des Typs Factorization.Wir können den i-ten Faktor mit f[i] nden, und wir gewinnen das Polynom mit f.expand()zurück. Die Objekte von Factorization verfügen auch über Methoden wie gcd oder lcm, wel-che die gleiche Bedeutung haben wie für Polynome, aber auf faktorisierten Formen arbeiten.

Quadratfreie Zerlegung. Trotz seiner guten theoretischen und praktischen Komplexität istdie vollständige Faktorisierung eines Polynoms eine komplexe Operation. Die quadratfreieZerlegung bildet eine schwächere Form der Zerlegung, viel leichter zu erhalten - einige Be-rechnungen von ggT genügen - und die schon viel an Information bringt.

Sei p =r∏i=1

pmii ∈ K[x] ein Polynom, das in irreduzible Faktoren auf einem Körper K zerlegt

ist. Wir sagen, p ist quadratfrei (squarefree auf englisch), wenn alle Faktoren pi die Multipli-zität mi = 1 haben, d.h. wenn die Wurzeln von p in einem abgeschlossenen Gebiet von Keinfach sind. Eine quadratfreie Zerlegung ist eine Faktorisierung in ein Produkt von quadrat-freien Faktoren, die wechseitig teilerfremd sind:

p = f1f22 · · · fss wobei fm =

∏mi=m

pi.

Die quadratfreie Zerlegung ordnet daher die irreduziblen Faktoren von p nach Multiplizitäten.Der quadratfreie Teil f1 · · · fs = p1 · · · pr von p ist das Polynom aus den einfachen Wurzeln,das abgesehen von den Multiplizitäten dieselben Wurzeln hat wie p.

7.3.2. Wurzelsuche

Die Berechnung der Wurzeln eines Polynoms lässt viele Varianten zu, je nachdem, ob wirreelle Wurzeln suchen, komplexe oder andere Wurzeln, exakte oder genäherte, mit oder oh-ne Multiplizitäten, auf garantierte oder auf heuristische Weise. . . Die Methode roots einesPolynoms gibt in der Voreinstellung die Wurzeln in seinem Basisring in Form einer Liste vonPaaren (Wurzel, Multiplizität) zurück:

sage: R.<x> = ZZ[]; p = (2*x^2 - 5*x + 2)*(x^4 - 7); p.roots()[(2, 2)]

Mit Argument gibt roots(D) die Wurzeln im Denitionsbereich D zurück, hier erst die ra-tionalen Wurzeln, dann Näherungen der l-adischen Wurzeln für l = 19:

sage: p.roots(QQ)[(2, 2), (1/2, 2)]sage: p.roots(Zp(19, print_max_terms=3))[(7 + 16*19 + 17*19^2 + ... + O(19^20), 1),(12 + 2*19 + 19^2 + ... + O(19^20), 1),(10 + 9*19 + 9*19^2 + ... + O(19^20), 2),(2 + O(19^20), 2)]

Das funktioniert mit einem breiten Spektrum von Denitionsbereichen und mit unterschied-licher Ezienz.

138

Page 155: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.3. Faktorisierung und Wurzeln

Insbesondere erlaubt die Wahl des Körpers der algebraischen Zahlen QQbar für D oder deralgeraischen reellen AA die exakte Berechnung der komplexen oder reelen Wurzeln eines Po-lynoms mit rationalen Koezienten:

sage: wurzeln = p.roots(AA); wurzeln[(-1.626576561697786?, 1),(0.500000000000000?, 2),(1.626576561697786?, 1),(2.000000000000000?, 2)]

Sage jongliert auf für den Anwender transparente Weise mit verschiedenen Darstellungsweisender algebraischen Zahlen. Eine besteht beispielsweise darin, jedes α ∈ Q über sein an einehinreichend genaue Einschachtelung gekoppeltes minimales Polynom zu kodieren, um α vonanderen Wurzeln zu unterscheiden. So sind die zurückgegebenen Wurzeln dem Augenscheinzum Trotz nicht bloÿe Näherungswerte. Sie können in exakten Rechnungen weiterverwendetwerden:

sage: a = wurzeln[0][0]^4; a.simplify(); a7

Hier haben wir die erste gefundene Wurzel zur vierten Potenz erhoben und Sage dann ge-zwungen, das Resultat ausreichend zu vereinfachen, um zu verdeutlichen, dass es sich um dieganze Zahl 7 handelt.

Eine Variante der exakten Lösung besteht darin, die Wurzeln einfach zu isolieren, d.h. In-tervalle zu berechnen, die jeweils genau eine Wurzel enthalten, wozu als DenitionsbereichD derjenige der reellen Intervalle RIF oder der komplexen CIF übergeben wird. Von den an-deren Denitionsmengen im Fall eines Polynoms mit rationalen Koezienten erwähnen wirRR, CC, RDF und CDF, die alle zahlenmäÿig genäherten Wurzeln entsprechen wie der Kör-per der Zahlen QQ[alpha]. Die spezischen Methoden real_roots, complex_roots und (fürbestimmte Basisringe) real_root_intervals bieten zusätzliche Optionen oder liefern vomAufruf von roots leicht abweichende Ergebnisse. Die Suche nach und die Isolation von nume-rischen Wurzeln wird genauer in Abschnitt 12.2 behandelt

7.3.3. Resultante

Auf jedem Faktorring wird die Existenz eines nicht konstanten, zwei Polynomen gemeinamenFaktors durch die Annullierung ihrer Resultanten Res(p, q) charakterisiert, welche ein Polynomin deren Koezienten ist. Ein gröÿeres Interess an der Resultante bezüglich des ggT beruhtdarauf, dass sie sich auf Morphismen von Ringen spezialiert . Zum Beispiel sind die Polynomex−12 und x−20 in Z[x] teilerfremd, doch zeigt die Annulation modulo n ihrer Resultanten

sage: x = polygen(ZZ); (x-12).resultant(x-20)-8

dass sie in Z/nZ genau dann eine gemeinsame Wurzel haben, wenn 8 von n geteilt wird.

139

Page 156: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Seien p =∑m

i=0 pixi und q =

∑ni=0 qix

i zwei nicht konstante Polynome aus A[x] mit pm, qn 6=0. Die Resultante von p und q ist deniert durch

Res(p, q) =

∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣

pm · · · · · · p0

. . . . . .pm · · · · · · p0

qn · · · q0

. . . . . .. . . . . .

qn · · · q0

∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣. (7.1)

Das ist die Determinante in passenden Basen der linearen Abbildung

An−1[x]×Am−1[x]→ Am+n−1[x]

u, v 7→ up+ vq

wobei Ak[x] ⊂ A[x] den Untermodul des Polynoms höchstens vom Grad k bezeichnet. Sindp und q zerlegt, dann wird ihre Resultante auch als Funktion der Dierenzen ihrer Wurzelngeschrieben:

Res(p, q) = pnmqmn

∏i,j

(αi − βj),p = pm(x− α1) · · · (x− αm)q = qn(x− β1) · · · (x− βn).

Die Eigenschaft der weiter oben erwähnten Spezialisierung leitet sich aus der Denition (7.1)her: wenn ϕ : A→ A′ ein Ringmorphismus ist, dessen Anwendung auf p und q deren Gradenicht sinken lässt, oder anders gesagt, sodass ϕ(pm) 6= 0 und ϕ(qn) 6= 0 ist, dann haben wir

Res(ϕ(p), ϕ(q)) = ϕ(Res(p, q)).

Somit verschwindet ϕ(Res(p, q)), wenn ϕ(p) und ϕ(q) einen gemeinsamen Faktor haben. Wirhaben ein wenig weiter oben ein Beispiel dieser Erscheinung mit der kanonischen Projektionvon Z nach Z/nZ für ϕ gesehen.

Doch die häugste Anwendung einer Resultante betrit den Fall, wo der Basisring selbst einPolynomring ist: p, q,∈ A[x] mit A = K[a1, . . . , ak]. Seien insbesondere α1, . . . , αk ∈ K undbetrachten wir die Spezialisierung

ϕ : B[a1, . . . , ak] → Kq(a1, . . . , ak) 7→ q(α1, . . . , αk)

Man sieht dann, dass sich die Resultante genau dann in q(α1, . . . , αk) aufhebt, wenn dieSpezialisierungen ϕ(p), ϕ(q) ∈ K[x] einen Faktor gemeinsam haben unter dem Vorbehalt,

dass einer der führenden Terme von p oder q in (α1, . . . , αk) von null verschieden ist.

Beispielsweise ist die Diskriminante von p deniert durch

disk(p) = (−1)m(m−1)/2Res(p, p′)/pm.

Diese Denition verallgemeinert die klassischen Diskriminanten der Polynome 2. und 3. Gra-des:

sage: R.<a,b,c,d> = QQ[]; x = polygen(R); p = a*x^2 + b*x + csage: p.resultant(p.derivative())

140

Page 157: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.3. Faktorisierung und Wurzeln

-a*b^2 + 4*a^2*csage: p.discriminant()b^2 - 4*a*csage: (a*x^3 + b*x^2 + c*x + d).discriminant()b^2*c^2 - 4*a*c^3 - 4*b^3*d + 18*a*b*c*d - 27*a^2*d^2

Wie die Diskriminante von p verschwindet die Resultante von p und seiner Ableitung genaudann, wenn p eine mehrfache Wurzel hat.

7.3.4. Galoisgruppen

Die Galoisgruppe eines irreduziblen Polynoms p ∈ Q[x] ist ein algebraisches Objekt, das be-stimmte Symmetrien der Wurzeln von p beschreibt. Es handelt sich um ein zentrales Objektder Theorie der algebraischen Gleichungen. Insbesondere ist die Gleichung p(x) = 0 durchRadikale lösbar, d.h. die Lösungen werden ausgehend von den Koezienten des Polynomsgenau dann mit vier Operationen und dem Ziehen der n-ten Wurzel ausgedrückt, wenn dieGaloisgruppe von p lösbar ist.

Sage gestattet die Berechnung der Galoisgruppen von Polynomen nicht zu hohen Grades mitrationalen Koezienten und alle Arten von Operationen auf den erhaltenen Gruppen auszu-führen. Sowohl die Galoistheorie als auch Sages Funktionalitäten für Gruppen überschreitenden Rahmen dieses Buches. Beschränken wir uns darauf, den Satz von Galois ohne weitereErläuterungen auf die Lösbarkeit mit Radikalen anzuwenden. Die folgende Rechnung erfor-dert eine Liste endlicher Gruppen, die in der Basisinstallation von Sage nicht enthalten ist,die man aber mit dem Befehl ./sage -i database_gap aus dem Netz herunterladen undautomatisch installieren kann. 5 Sie zeigt, dass sich die Wurzeln von x5 − x − 1 nicht durchRadikale ausdrücken lassen.

sage: x = polygen(QQ); G = (x^5 - x - 1).galois_group(); GTransitive group number 5 of degree 5sage: G.is_solvable()False

Es handelt sich um eines der einfachsten Beispiele für diesen Fall, da die Polynome 4. oderkleineren Grades immer mit Radikalen lösbar sind, genau so oensichtlich wie x5− a. Bei derPrüfung der Generatoren von G als Gruppe von Permutationen erkennen wir, dass G ' S5

gilt, was wir leicht verzieren:

sage: G.gens()[(1,2,3,4,5), (1,2)]sage: G.is_isomorphic(SymmetricGroup(5))True

5Vorsicht: erstens dauert die Installation recht lange (eine Stunde oder mehr) und es kann passieren, dassdanach in Sage nicht mehr alle bisherigen Funktionalitäten verfügbar sind.

141

Page 158: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

7.4. Gebrochen rationale Ausdrücke

7.4.1. Erzeugung und elementare Eigenschaften

Die Division zweier Polynome (auf einem Integritätsring) ergibt einen gebrochen rationalenAusdruck. Dessen Vorfahr ist der Körper der Brüche des Polynomrings, der mit Frac(R)erhalten wird:

sage: x = polygen(RR); r = (1 + x)/(1-x^2); r.parent()Fraction Field of Univariate Polynomial Ring in x over RealField with 53 bits of precisionsage: r(x + 1.00000000000000)/(-x^2 + 1.00000000000000)

Wir beobachten, dass die Vereinfachung nicht automatisch erfolgt. Dies, weil RR kein exakterRing ist, d.h. seine Elemente werden als Näherungen mathematischer Objekte interpretiert.Die Methode reduce setzt den Bruch in die gekürzte Form. Sie gibt kein neues Objekt zurück,sondern modiziert den vorhandenen gebrochen rationalen Ausdruck:

sage: r.reduce(); r1.00000000000000/(-x + 1.00000000000000)

Umgekehrt werden die gebrochen rationalen Ausdrücke auf einem exakten Ring automatischgekürzt.

Die Operationen auf gebrochen rationalen Ausdrücken sind analog zu denen auf Polynomen.Diejenigen, die in beiden Fällen sinnvoll sind (Substitution, Ableitung, Faktorisierung. . . )werden auf gleiche Weise verwendet. Die Tabelle 7.6 listet weitere nützliche Methoden auf.Die Zerlegung in einfache Elemente und vor allem die rationale Rekonstruktion verdieneneinige Erläuterungen.

Gebrochen-rationale AusdrückeKörper der Brüche K(x) Frac(K['x'])

Zähler r.numerator()

Nenner r.denominator()

Vereinfachung (modiziert r) r.reduce()

Zerlegung in einfache Elemente r.partial_fraction_decomposition()

rationale Rekonstruktion von s mod m s.rational_reconstruct(m)

Abgeschnittene ReihenRing A[[t]] PowerSeriesRing(A, 'x', default_prec=n)

Ring A((t)) LaurentSeriesRing(A, 'x', default_prec=n)

Koezient [xk]f(x) f[k]

Abschätzung des Wertes x + O(x^n)

Genauigkeit f.prec()

Ableitung, Integral f.derivative(), f.integral()

häuge Operationen√f , exp, . . . f.sqrt(), f.exp(), ...

Reziprok-Wert (f g = g f = x) g = f.reversion()

Lösung von y′ = ay + b a.solve_linear_de(precision, b)

Tab. 7.6 Mit Polynomen gebildete Objekte.

142

Page 159: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.4. Gebrochen rationale Ausdrücke

7.4.2. Zerlegung in einfache Elemente

Sage berechnet die Zerlegung eines gebrochen rationalen Ausdrucks a/b aus Frac(K['x']) ineinfache Elemente, indem es mit b aus K['x'] beginnt. Daher handelt es sich um die Zerlegungin einfache Elemente auf K. Das Ergebnis besteht aus einem Polynom und einer Liste vongebrochen rationalen Ausdrücken, deren Nenner Potenzen der irreduziblen Faktoren von bsind:

sage: R.<x> = QQ[]; r = x^10 / ((x^2-1)^2 * (x^2+3))sage: poly, parts = r.partial_fraction_decomposition()sage: polyx^4 - x^2 + 6sage: for part in parts: part.factor()(17/32) * (x - 1)^-1(1/16) * (x - 1)^-2(-17/32) * (x + 1)^-1(1/16) * (x + 1)^-2(-243/16) * (x^2 + 3)^-1

Somit haben wir die Zerlegung in einfache Elemente auf rationalen Zahlen erhalten

r =x10

(x2 − 1)2(x3 + 3)= x4 − x2 + 6 +

1732x−

1532

(x− 1)2+−17

32x−1532

(x+ 1)2+−243

16

x2 + 3.

Es is unschwer zu sehen, dass dies auch die Zerlegung von r auf den reellen Zahlen ist.

Auf den komplexen Zahlen hingegen ist der Nenner des letzten Terms nicht irreduzibel, unddeshalb kann der gebrochen rationale Ausdruck weiter zerlegt werden. Wir können die Zerle-gung in einfache Elemente auf den reellen oder komplexen Zahlen numerisch berechnen:

sage: C = ComplexField(15)sage: Frac(C['x'])(r).partial_fraction_decomposition()(x^4 - x^2 + 6.000,(x^4 - x^2 + 6.000,[0.5312/(x - 1.000),0.06250/(x^2 - 2.000*x + 1.000),4.385*I/(x - 1.732*I),(-4.385*I)/(x + 1.732*I),(-0.5312)/(x + 1.000),0.06250/(x^2 + 2.000*x + 1.000)])

Die exakte Zerlegung auf C erhalten wir auf die gleiche Weise, indem wir nämlich C durchQQbar ersetzen. Bei der Berechnung auf AA hätten wir die Zerlegung auf den reellen Zahlen,selbst wenn nicht alle reellen Wurzeln des Nenners rational sind.

7.4.3. Rationale Rekonstruktion

Ein Analogon zu der in Unterabschnitt 6.1.3 vorgestellten rationalen Rekonstruktion existiertauch für Polynome in A = Z/nZ. Sind m, s ∈ A[x] gegeben, berechnet der Befehl

sage: s.rational_reconstruct(m, dp, dq)

143

Page 160: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

falls möglich die Polynone p, q ∈ A[x], sodass

qs ≡ p mod m, deg p ≤ dp, deg q ≤ dq.

Beschränken wir uns auf die Vereinfachung für den Fall, dass n eine Primzahl ist. Eine solcheBeziehung zwischen den teilerfremden q und m zieht p/q = s in A[x]/ < m > nach sich, daherdie Bezeichnung rationale Rekonstruktion.

Das Problem der rationale Rekonstruktion wird in ein lineares Gleichungssystem mit Ko-ezienten von p und q übersetzt, und ein einfaches Dimensionsargument zeigt, dass es einenicht-triviale Lösung gibt, sobald dp+dq ≥ degm−1 ist. Nicht immer gibt es eine Lösung mitteilerfremden p und m (z.B. sind die Lösungen von p ≡ qx mod x2 mit deg p ≤ 0, deg q ≤ 1die multiplen Konstanten von (p, q) = (0, x)), doch rational_reconstruct sucht bevorzugtLösungen für teilerfremde q und m.

Padé-Approximation. Der Fall m = xn heiÿt Padé-Approximation. Eine Padé-Näherungdes Typs (k, n−k) einer symbolischen Reihe f ∈ K[[x]] ist ein gebrochen rationaler Ausdruckp/q ∈ K(x), sodass deg p ≤ k − 1, deg q ≤ n − k, q(0) = 1 und p/q = f + O(xn) ist. Wirhaben dann p/q ≡ f mod xn.

Beginnen wir mit einem rein symbolischen Beispiel. Die folgenden Befehle berechnen einePadé-Näherung der Reihe f =

∑∞i=0(i+ 1)2xi mit Koezienten in Z/10Z:

sage: A = Integers(101); R.<x> = A[]sage: f6 = sum( (i+1)^2 * x^i for i in (0..5) ); f636*x^5 + 25*x^4 + 16*x^3 + 9*x^2 + 4*x + 1sage: num, den = f6.rational_reconstruct(x^6, 1, 3); num/den(100*x + 100)/(x^3 + 98*x^2 + 3*x + 100)

Bei erneuter Reihenentwicklung des gefundenen gebrochen rationalen Ausdrucks beobachtenwir, das die Entwicklungen nicht nur bis zur Ordnung 6 zusammenfallen, sondern der folgendeTerm sogar richtig ist.

sage: S = PowerSeriesRing(A, 'x', 7); S(num)/S(den)1 + 4*x + 9*x^2 + 16*x^3 + 25*x^4 + 36*x^5 + 49*x^6 + O(x^7)

In der Tat ist f selbst gebrochen rational: wir haben f = (1 + x/(1 − x)3). Die abbrechen-de Entwicklung f6 mit begrenzten Graden von Zähler und Nenner genügt für die eindeutigeDarstellung. So gesehen, ist die Berechnung von Padé-Näherungen die Umkehrung der Rei-henentwicklung von gebrochen rationalen Ausdrücken: sie erlaubt, von dieser alternativenDarstellung zur üblichen Darstellung als Quotient zweier Polynome zurückzukehren.

Ein analytisches Beispiel. Historisch sind die Padé-Approximationen nicht bei dieser Artvon symbolischen Betrachtungen entstanden, sondern im Zusammenhang mit der Theorie derApproximation analytischer Funktionen. Tatsächlich nähern die Padé-Approximationen einerReihenentwicklung die Funktion oft besser an als abbrechende Reihen. Wenn der Grad desNenners groÿ genug ist, können sie sogar auÿerhalb des Konvergenzradius der Reihe guteNäherungen liefern. Wir sagen manchmal, dass sie die Pole verschlucken. Die Abbildung7.1, welche die Konvergenz der Näherungen der Tangensfunktion des Typs (2k, k) in derUmgebung von 0 zeigt, illustriert dieses Phänomen.

144

Page 161: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.4. Gebrochen rationale Ausdrücke

Typ (4,2) Typ (8,4) Typ (12,6)........... .-.-.- - - - - -

Abb. 7.1 - Die Tangensfunktion und einige Padé-Approximationen auf [−2π, 2π].

Obwohl rational_reconstruct auf Polynome in Z/nZ beschränkt ist, ist es damit möglich,Padé-Approximationen mit rationalen Koezienten zu berechnen und diese Abbildung zuerzielen. Am einfachsten beginnt man damit, die rationale Rekonstruktion modulo einer rechtgroÿen Primzahl auszuführen:

sage: x = var('x'); s = tan(x).taylor(x, 0, 20)sage: p = previous_prime(2^30); ZpZx = Integers(p)['x']sage: Qx = QQ['x']

sage: num, den = ZpZx(s).rational_reconstruct(ZpZx(x)^10,4,5)sage: num/den(1073741779*x^3 + 105*x)/(x^4 + 1073741744*x^2 + 105)

um dann die gefundene Lösung anzuheben. Die folgende Funktion hebt ein Element a ausZ/pZ zu einer ganzen Zahl mit dem Absolutwert von höchstens p/2.

sage: def lift_sym(a):....: m = a.parent().defining_ideal().gen()....: n = a.lift()....: if n <= m // 2: return n....: else: return n - m

Wir erhalten:

sage: Qx(map(lift_sym, num))/Qx(map(lift_sym, den))(-10*x^3 + 105*x)/(x^4 - 45*x^2 + 105)

Wenn die gesuchten Koezienten für dieses Verfahren zu groÿ sind, können wir die Rech-nung modulo mehrerer Primzahlen ausführen und den chinesischen Restsatz anwenden,umeine Lösung mit ganzzahligen Koezienten zu nden wie in Unterabschnitt 6.1.4 erklärt.

145

Page 162: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Eine andere Möglichkeit ist die Berechnung einer Rekursionsbeziehung mit konstanen Ko-ezienten, die den Koezienten der Reihe genügt. Diese Rechnung ist zur Berechnung ei-ner Padé-Approximation nahezu äquivalent (siehe Übung 27), doch erlaubt Sages Funktionberlekamp_massey die Ausführung auf beliebigen Körpern.

Systematisieren wir die vorstehende Rechnung, indem wir eine Funktion schreiben, welchedie Näherung mit rationalen Koezienten unter hinreichend förderlichen Annahmen direktberechnet:

sage: def mypade(pol, n, k):....: x = ZpZx.gen();....: n,d = ZpZx(pol).rational_reconstruct(x^n, k-1, n-k)....: return Qx(map(lift_sym, n))/Qx(map(lift_sym, d))

Wir müssen auf die Ausgaben dieser Funktion nur noch plot anwenden, um die Grak inAbbildung 7.1 zu erhalten (Die Ausgaben werden in Elemente von SR umgewandelt, denn plotkann den Graphen einer algebraischen rationalen Funktion nicht unmittelbar zeichnen.)

sage: add(....: plot(expr, -2*pi, 2*pi, ymin=-3, ymax=3,....: linestyle=sty, detect_poles=True, aspect_ratio=1)....: for (expr, sty) in [....: (tan(x), '-'),....: (SR(mypade(s, 4, 2)), ':' ),....: (SR(mypade(s, 8, 4)), '-.'),....: (SR(mypade(s, 12, 6)), '--') ])

Die folgenden Übungen stellen weitere klassische Anwendungen der rationalen Rekonstruktiondar.

Übung 27.

1. Zeigen Sie: wenn (un)n∈N einer linearen Rekursion mit konstanten Koezienten genügt,dann ist die symbolische Reihe

∑n∈N unz

n ein gebrochen rationaler Ausdruck. Wiewerden Zähler und Nenner repräsentiert?

2. Erraten Sie die nächsten Terme der Folge

1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339, 3056, 371, 14602,−4257, . . . ,

indem Sie rational_reconstruct verwenden. Finden Sie das Ergebnis auch mit derFunktion berlekamp_massey.

Übung 28 (Interpolation von Cauchy). Finden Sie einen gebrochen rationalen Ausdruckr = p/q ∈ F17(x), sodass r(0) = −1, r(1) = 0, r(2) = 7 und r(3) = 5 wird, wobei p vonmöglichst kleinem Grad ist.

146

Page 163: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.5. Formale Potenzreihen

7.5. Formale Potenzreihen

Eine formale Potenzreihe ist eine Potentreihe, die als eine einfache Folge von Koezienten er-scheint, ohne dass ihre Konvergenz untersucht wird. Genauer, wenn A ein kommutativer Ringist, sind formale Potenzreihen (engl. formal power series) einer Unbestimmten x mit Koezi-enten aus A die symbolischen Summen

∑∞n=0 anx

n, wobei (an) eine Folge beliebiger Elementeaus A ist. Ausgestattet mit den Operationen der üblichen Addition und Multiplikation

∞∑n=0

anxn +

∞∑n=0

bnxn =

∞∑n=0

(an + bn)xn,

( ∞∑n=0

anxn

)( ∞∑n=0

bnxn

)=

∞∑n=0

∑i+j=n

aibj

xn

bilden die formalen Potenzreihen einen mit A[[x]] bezeichneten Ring.

In einem System zum symbolischen Rechnen werden mit solchen Reihen analytische Funktio-nen dargestellt, die nicht in exakter Schreibweise vorliegen. Wie immer führt der ComputerRechnungen aus, es ist aber Sache des Anwenders, ihnen einen mathematischen Sinn zu geben.Er muss sicherstellen, dass die Reihen, mit denen er arbeitet, konvergent sind.

Formale Potenzreihen begegnen auch ausgiebig in der Kombinatorik, insofern es erzeugendeReihen sind. In Unterabschnitt 15.1.2 werden wir ein Beispiel dafür sehen.

7.5.1. Operationen auf abbrechenden Reihen

Den Ring der formalen Potenzreihen Q[[x]]erhalten wir mit

sage: R.<x> = PowerSeriesRing(QQ)

oder dessen Abkürzung R.<x> = QQ[[]]6 mit QQ['x'].completion('x'). Die Elemente vonA[['x']] sind die abbrechenden Reihen, d.h. Objekte der Form

f = f0 + f1x+ . . .+ fn−1xn−1 +O(xn).

Sie spielen die Rolle von Approximationen der mathematischen unendlichen Reihen, genauwie die Elemente von RR die Näherungen der reellen Zahlen darstellen. Der Ring A[[x]] istdaher kein exakter Ring.

Jede Reihe besitzt ihre eigene Abbruchordnung7 und die Genauigkeit ergibt sich im Verlaufder Rechnungen automatisch:

sage: R.<x> = QQ[[]]sage: f = 1 + x + O(x^2); g = x + 2*x^2 + O(x^4)sage: f + g1 + 2*x + O(x^2)sage: f * gx + 3*x^2 + O(x^3)6Oder aus Q[x].7In bestimmter Hinsicht ist der Hauptunterschied zwischen einem Polynom modulo xn und einer abbrechen-den Reihe der Ordnung n: die Operationen auf beiden Arten von Objekten sind analog, aber die Elementevon A[[x]]/〈xn〉 haben alle dieselbe Genauigkeit.

147

Page 164: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Es gibt Reihen unendlicher Genauigkeit, die den Polynomen genau entsprechen:

sage: (1 + x^3).prec()+Infinity

Eine voreingestellte Genauigkeit kommt zur Anwendung, wenn es erforderlich ist, ein exaktesResultat abzuschneiden. Sie wird mit der Erzeugung des Ringes festgelegt oder danach mitder Methode set_default_prec:

sage: R.<x> = PowerSeriesRing(Reals(24), default_prec=4)sage: 1/(1 + RR.pi() * x)^21.00000 - 6.28319*x + 29.6088*x^2 - 124.025*x^3 + O(x^4)

Das hat zur Folge, dass ein Test auf mathematische Gleichheit zweier Reihen nicht möglichist. Dies ist ein wichtiger begriicher Unterschied zwischen dieser und anderen Klassen vonObjekten, die in diesem Kapitel vorkommen. Sage sieht deshalb zwei Elemente aus A[['x']]als gleich an, sobald sie bis auf die schwächste ihrer Genauigkeiten übereinstimmen:

sage: R.<x> = QQ[[]]sage: 1 + x + O(x^2) == 1 + x + x^2 + O(x^3)True

Achtung: das impliziert beispielsweise, dass der Test O(x^2) == 0 wahr zurückgibt, weil dieNullserie eine unendliche Genauigkeit hat.

Die arithmischen Basisoperationen funktionieren wie bei Polynomen. Wir verfügen auch übereinige der üblichen Funktionen, beispielsweise f.exp() mit f(0) = 0, sowie über Ableitungund Integration. So ist eine asymptotische Entwicklung für x→ 0 von

1

x2exp

x∫0

√1

1 + tdt

gegeben durch

sage: (1/(1+x)).sqrt().integral().exp() / x^2 + O(x^4)x^-2 + x^-1 + 1/4 + 1/24*x - 1/192*x^2 + 11/1920*x^3 + O(x^4)

Hier wird jede Operation, selbst dann, wenn nur vier Terme im Resultat erscheinen, mit dervoreingestellten Genauigkeit von 20 ausgeführt, was weithin ausreicht für ein Endergebnis inO(x4). Um mehr als zwanzig Terme zu erhalten, müsste die Genauigkeit der Zwischenrech-nungen erhöht werden.

Dieses Beispiel zeigt auch, dass wenn f, g ∈ K[[x]] ist und g(0) = 0, der Quotient f/g ein Ob-jekt formale Laurent-Reihe zurückgibt. Anders als bei Laurent-Reihen der komplexen Analysisder Form

∑∞n=−∞ anx

n sind die formalen Laurent-Reihen Summen des Typs∑∞

n=−N anxn

mit einer endlichen Anzahl von Termen mit negativen Exponenten. Diese Beschränkung istnötig, damit das Produkt zweier formaler Potenzreihen sinnvoll gebildet wird: ohne sie würdejeder Koezient des Produktes als Summe einer unendlichen Reihe ausgedrückt werden.

148

Page 165: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.5. Formale Potenzreihen

7.5.2. Reihenentwicklung von Gleichungslösungen

Angesichts einer Dierentialgleichung, deren exakte Lösungen zu kompliziert sind, um sie zuberechnen oder, wenn berechnet, zu kompliziert sind für die Auswertung, besteht ein häugerAusweg darin, eine Lösung in Form einer Potenzreihe zu suchen. Üblicherweise beginnen wirmit der Bestimmung der Lösungen der Gleichung im Raum der formalen Potenzreihen, undwenn nötig schlieÿen wir dann mit einem Konvergenznachweis, dass die gebildeten formalenLösungen einen analytischhen Sinn haben. Für die erste Etappe kann Sage eine wertvolle Hilfesein.

Betrachten wir beispielsweise die Dierentialgleichung

y′(x) =√

1 + x2y(x) + exp(x), y(0) = 1.

Diese Gleichung lässt als eindeutige Lösung eine formale Potenzreihe zu, deren erste Termeberechnet werden können mit

sage: R.<x> = PowerSeriesRing(QQ, default_prec=10)sage: (1+x^2).sqrt().solve_linear_de(prec=6, b=x.exp())1 + 2*x + 3/2*x^2 + 5/6*x^3 + 1/2*x^4 + 7/30*x^5 + O(x^6)

Des weiteren sichert der Satz von Cauchy zur Existenz von Lösungen linearer Dierentialglei-chungen mit analytischen Koezienten, dass diese Potenzreihe für |x| < 1 konvergiert: dieSumme bildet daher eine analytische Lösung auf dem komplexen Enheitskreis.

Dieser Ansatz ist nicht auf Dierentialgleichungen beschränkt. Die Funktionsgleichung exf(x) =f(x) ist komplexer und das nur, weil sie nicht linear ist. Es ist aber eine Fixpunktgleichung,wir können versuchen, eine (symbolische) Lösung iterativ zu verfeinern:

sage: S.<x> = PowerSeriesRing(QQ, default_prec=5)sage: f = S(1)sage: for i in range(5):....: f = (x*f).exp()....: print f1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + O(x^5)1 + x + 3/2*x^2 + 5/3*x^3 + 41/24*x^4 + O(x^5)1 + x + 3/2*x^2 + 8/3*x^3 + 101/24*x^4 + O(x^5)1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + O(x^5)1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + O(x^5)

Was geht hier vor? Die Lösungen von exf(x) = f(x) in Q[[x]] sind Fixpunkte der Transfor-mation Φ : f 7→ exf . Wenn eine Folge von Iterierten der Form Φn(a) konvergiert, ist ihrGrenzwert notwendigerweise Lösung der Gleichung. Setzen wir umgekehrt f(x) =

∑∞n=0 fnx

n

und entwickeln wir eine Reihe mit zwei Gliedern: es kommt

∞∑n=0

fnxn =

∞∑k=0

1

k!

x ∞∑j=0

fjxj

k

=∞∑n=0

∞∑k=0

1

k!

∑j1,...jk∈N

j1+...+jk=n−k

fj1fj2 . . . fjk

xn. (7.2)

149

Page 166: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Weniger wichtig sind die Details der Formel; wesentlich ist, dass fn als Funktion der vor-angehenden Koezienten f0, . . . , fn−1 berechnet wird, wie man bei der Identizierung derKoezienten der beiden Glieder sieht. Jede Iteration von Φ liefert somit einen neuen korrek-ten Term.

Übung 29. Berechnen Sie die auf die Ordnung 15 beschränkte Entwicklung von tanx in derUmgebung von null aus der Dierentialgleichung tan′ = 1 + tan2.

7.5.3. Faule Reihen

Das Phänomen des Fixpunktes motiviert die Einführung einer weiteren Art formaler Potenz-reihen, die faulen Reihen (engl. lazy). Das sind keine abbrechenden Reihen sondern unendlicheReihen; das Adjektiv faul besagt, dass die Koezienten nur dann berechnet werden, wenn esausdrücklich verlangt wird. Andererseits können wir nur Reihen darstellen, deren Koezi-enten wir berechnen können: im wesentlichen die Kombinationen von einfachen Reihen mitbestimmten Gleichungslösungen, für die Beziehungen wie (7.2) existieren. Beispielsweise istdie faule Reihe lazy_exp, die durch

sage: L.<x> = LazyPowerSeriesRing(QQ)sage: lazy_exp = x.exponential(); lazy_expL.<x> = LazyPowerSeriesRing(QQ)O(1)

deniert ist, ein Objekt, das in seiner internen Darstellung alle notwendigen Informationenenthält, um die Reihenentwicklung von exp x beliebiger Ordnung zu berechnen. Zu Beginnwird sie nur als O(1) angezeigt, denn noch ist kein Koezient berechnet. Der Versuch, auf denKoezienten von x5 zuzugreifen, löst die Berechnung aus und die berechneten Koezientenwerden dann gespeichert:

sage: lazy_exp[5]1/120 sage: lazy_exp1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + O(x^6)

Greifen wir das Beispiel von exf(x) = f(x) wieder auf, um zu sehen, wie es mit faulen Rei-hen behandelt wird. Wir können zunächst versuchen, die weiter oben im Ring QQ[['x']]ausgeführte Rechnung zu reproduzieren:

sage: f = L(1) # die konstante faule Reihe 1sage: for i in range(5):....: f = (x*f).exponential()....: f.compute_coefficients(5) # erzwingt die Berechnung....: print f # der ersten Koeffizienten1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + O(x^6)1 + x + 3/2*x^2 + 5/3*x^3 + 41/24*x^4 + 49/30*x^5 + O(x^6)1 + x + 3/2*x^2 + 8/3*x^3 + 101/24*x^4 + 63/10*x^5 + O(x^6)1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + 49/5*x^5 + O(x^6)1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + 54/5*x^5 + O(x^6)

150

Page 167: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.6. Rechnerinterne Darstellung von Polynomen

Die erhaltenen Entwicklungen sind selbstverständlich dieselben wie vorher8. Doch ist nun derWert von f bei jeder Iteration eine unendliche Reihe, deren Koezienten wir auf Anforderungberechnen können. Alle diese Reihen werden als Zwischenergebnisse gespeichert. Die Berech-nung einer jeden von ihnen mit der gewünschten Genauigkeit wird in der Weise automatischangestoÿen, dass zum Beispiel der Koezient von x7 in der letzten Iteration berechnet wird,sobald wir versuchen, darauf zuzugreifen:

sage: f[7]28673/630

Mit dem Code aus Unterabschnitt 7.5.2 hätte der Zugri auf f[7] zu einem Fehler geführt,weil der Index 7 auÿerhalb der Abbruchordnung der Reihe f liegt.

Allerdings ist der von f[7] zurückgegebene Wert der Koezient von x7 nur in der IteriertenΦ5(1), nicht aber in der Lösung. Die Kraft der faulen Reihen liegt in der Möglichkeit, direktzur Grenze zu gehen, indem sie selbst als faule Reihe kodiert wird:

sage: from sage.combinat.species.series import LazyPowerSeriessage: f = LazyPowerSeries(L, name='f')sage: f.define((x*f).exponential())sage: f.coefficients(8)[1, 1, 3/2, 8/3, 125/24, 54/5, 16807/720, 16384/315]

Was die iterative Berechnung funktionieren lässt, ist die Gleichung (7.2). Hinter den Kulis-sen leitet Sage aus der rekursiven Denition f.define((x*f).exponential()) eine Formelderselben Art her, die eine rekursive Berechnung der Koezienten erlaubt.

7.6. Rechnerinterne Darstellung von Polynomen

Ein und dasselbe mathematische Objekt - das Polynom p mit Koezienten aus A - kann imRechner auf drei verschiedene Arten codiert werden. Auch wenn das mathematische Ergeb-nis einer Operation auf p selbstverständlich unabhängig von der Darstellung ist, hängt dasVerhalten der entsprechenden Sage-Objekte doch damit zusamen. Die Wahl der Darstellungbeeinusst die möglichen Operationen, die exakte Form ihrer Ergebnisse und besonders dieEzienz der Berechnungen.

Voll und dünn besetzte Darstellung. Für die Darstellung von Polynomen gibt es vorallem zwei Möglichkeiten. Bei der voll besetzten Darstellung werden die Koezienten vonp =

∑ni=0 pix

i in einer Liste [p0, . . . , pn] mit den Exponenten als Indizes gespeichert. Bei derdünn besetzten Speicherung werden nur die von null verschiedenen Koezienten gespeichert:das Polynom wird durch eine Menge von Exponent-Koezient-Paaren (i, pi) kodiert, in einerListe zusammengefasst oder besser in einer von den Exponenten indizierten Raung (sieheUnterabschnitt 3.3.9).

Für Polynome, die praktisch voll besetzt sind, d.h. deren Koezienten meistens von nullverschieden sind, verbraucht die volle Darstellung weniger Speicher und erlaubt schnellere

8Wir stellen allerdings fest, dass Sage gelegentlich inkohärente Konventionen verwendet: die Methode exp

für die abbrechenden Reihen heiÿt hier exponential, und compute_coefficients(5) berechnet die Ko-ezienten bis zur Ordnung 5 einschlieÿlich, wohingegen default_prec=5 Reihen ergibt, die nach demKoezienten von x4 abbrechen.

151

Page 168: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Polynome

Rechnungen. Sie erspart die Speicherung der Exponenten und der internen Datenstrukturender Diktionäre: es bleibt nur das absolut Notwendige, die Koezienten. Mehr noch, der Zugriauf ein Element oder die Iteration über die Elemente sind bei einer Liste schneller als beieinem Diktionär. Umgekehrt erlaubt die dünn besetzte Darstellung eziente Rechnungen aufPolynomen, die bei voll besetzter Darstellung gar nicht in den Speicher passen würden:

sage: R = PolynomialRing(ZZ, 'x', sparse=True)sage: p = R.cyclotomic_polynomial(2^50); p, p.derivative()(x^562949953421312 + 1, 562949953421312*x^562949953421311)

Wie dieses Beispiel illustriert, ist die Darstellung eine Charakteristik des Polynomrings, diewir bei seiner Bildung festlegen. Das voll besetzte Polynom p ∈ Q[x] und das dünn besetz-te Polynom p ∈ Q[] haben deshalb nicht denselben9 Vorfahren. Die voreingestellte Darstel-lung von Polynomen mit einer Unbestimmten ist voll besetzt. Die Option sparse=True vonPolynomialRing dient zu Bildung eines dünn besetzten Polynomrings.

Ein wenig Theorie

Um die beste Lösung für schnelle Operation auf Polynomen zu nden, ist es gut, eineVorstellung von ihrer algorithmischen Komplexität zu haben. Hier nun eine kurzeÜbersicht für den in der Algorithmik etwas erfahrenen Leser. Wir beschränken unsauf den Fall voll besetzter Polynome.Additionen, Subtraktionen und andere direkte Manipulationen der Koezienten wer-den in Abhängigkeit vom Grad der betreenden Polynome einfach in linearer Zeitbewältigt. Ihre Geschwindigkeit hängt daher in der Praxis wesentlich von der Mög-lichkeit des schnellen Zugris auf die Koezienten ab und damit von der Daten-struktur.Die kritische Operation ist die Multiplikation. Die ist tatsächlich nicht nur einearithmetische Grundoperation, sondern auch andere Operationen arbeiten mit Al-gorithmen, deren Komplexität entscheidend von der Komplexität der Multiplikationabhängt. Wir können zum Beispiel die euklidsche Division zweier Polynome höchs-tens n-ten Grades mit Kosten von O(1) Multiplikationen berechnen, oder auch ihrenggT mit O(log n) Multiplikationen.Die gute Nachricht: wir können Polynome in beinahe linearer Zeit multiplizie-ren. Genauer gesagt ist die beste bekannte Komplexität auf einem beliebigen RingO(n log n log logn) Operationen auf dem Basisring. Sie beruht auf Verallgemeinerun-gen des berühmten Algorithmus von Schönhage-Strassen, welcher die gleiche Kom-plexität bei der Multiplikation ganzer Zahlen erreicht. Zum Vergleich, das Verfahren,das wir für die Multiplikation von Polynomen von Hand verwenden, erfordert eineAnzahl von Operationen in der Gröÿenordnung n2.Die Algorithmen für schnelle Multiplikation sind in der Praxis bei Polynomen hinrei-chend hohen Grades konkurrenzfähig genauso wie die daraus abgeleiteten Divisions-verfahren. Die Bibliothen, auf die sich Sage bei bestimmten Typen von Koezientenstützt, arbeiten mit dieser Art von ausgefeilten Algorithmen. Das ist der Grund,weshalb Sage mit Polynomen astronomischen Grades auf bestimmten Koezienten-ringen so ezient arbeiten kann.

9Trotzdem gibt QQ['x'] == PolynomialRing(QQ, 'x', sparse=True) wahr zurück: die beiden Vorfahrensind gleich, denn sie repräsentieren dasselbe mathematische Objekt. Natürlich gibt der entsprechende Testmit is falsch zurück.

152

Page 169: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.6. Rechnerinterne Darstellung von Polynomen

Bestimmte Details der Darstellung variieren überdies je nach der Natur der Koezientendes Polynoms. Es kommt bei der Ausführung der grundlegenden Operationen auch auf denverwendeten Code an. Tatsächlich bietet Sage auÿer einer generischen Implementierung derPolynome, die auf jedem kommutativen Ring funktioniert, mehrere optimierte Varianten füreinen speziellen Typ von Koezienten. Diese verfügen über zusätzliche Funktionalitäten undsind vor allem beträchtlich ezienter als die generische Version. Sie greifen dafür auf speziali-sierte externe Bibliotheken zurück, im Fall von Z[x] beispielsweise auf FLINT oder NTL.

Bei der Ausführung vieler umfangreicher Rechnungen kommt es entscheidend darauf an, soweitwie irgend möglich auf solchen Polynomringen zu arbeiten, die eziente Implementierungenbieten. Die für ein Polynom p mit p? angezeigte Hilfeseite zeigt, welche Implementierungvorliegt. Die Wahl der Implementierung ergibt sich meistens aus den Implementierungen vonBasisring und Darstellung. Die Option implementation von PolynomialRing erlaubt diePräzisierung einer Implementierung, wenn mehrere Möglichkeiten zur Auswahl stehen.

Symbolische Ausdrücke. Die in den Kapiteln 1 und 2 beschriebenen symbolischen Aus-drücke (d.h. die Elemente von SR) liefern eine dritte Darstellung von Polynomen. Sie stelleneine natürliche Wahl dar, wenn eine Rechnung Polynome und komplexere Ausdrücke mischt,wie das in der Analysis häug der Fall ist. Die Flexibilität der Darstellung aber, die sie bieten,ist zuweilen sogar in einem eher algebraischen Kontext von Nutzen. Das Polynom (x+ 1)1010

beispielsweise ist entwickelt voll besetzt, es ist aber nicht nötig (auch nicht wünschbar), esauszumultiplizieren, um es abzuleiten oder numerisch auszuwerten.

Doch Vorsicht: anders als algebraische Polynome sind symbolische Polynome (aus SR) nichtan einen bestimmten Koezientenring gebunden und werden nicht in kanonischer Form be-handelt. Dasselbe Polynom hat eine Vielzahl verschiedener Schreibweisen, wobei es Sachedes Anwenders ist, die nötigen Umwandlungen zischen ihnen anzugeben. Es entspricht dieserDenkweise, dass in der Denitionsmenge SR alle symbolischen Ausdrücke zusammengefasstwerden, ohne einen Unterschied zwischen den Polynomen und den anderen zu machen, wirkönnen aber mit f.is_polynomial(x) explizit testen, ob ein symbolischer Ausdruck f einPolynom in der Variablen x ist.

153

Page 170: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 171: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Mathematik ist die Kunst, jedes Problem auf lineare Algebra zu reduzieren.

William Stein

Dieses Kapitel behandelt die exakte und symbolische lineare Algebra, d.h. das symbolischeRechnen auf solchen Ringen wie Z, endlichen Körpern, Polynomringen. . . Was die numerischelineare Algebra betrit, so wird sie in Kapitel 13 behandelt. Die Konstruktionen auf Matri-zen und ihren Räumen stellen wir so dar, dass die Basisoperationen (Abschnitt 8.1), danndie verschiedenen, auf Matrizen möglichen, Rechnungen, in zwei Gruppen zusammengefasstwerden: die eine, die mit der Gauÿ-Methode und mit Äquivalenz-Umformungen von links zutun hat, die andere, die mit Ähnlichkeits-Transformationen (Unterabschnitt 8.2.3) verbundenist. In den Büchern von Gantmacher [Gan90], von zur Gathen und Gerhard [vzGG03] sowievon Abdeljaoued und Lombardi [AL03] kann man eine gründliche Behandlung der in diesemKapitel angerissenen Themen nden.

8.1. Erstellung und elementare Operationen

8.1.1. Vektorräume, Matrix-Vektorräume

Ebenso wie Polynome werden Vektoren und Matrizen als algebraische Objekte behandelt, diezu einem Vektorraum gehören. Wenn die Koezienten Elemente eines Körpers K sind, ist dasein Vektorraum auf K; gehören sie zu einem Ring, ist es ein freies K-Modul.

So konstruiert man den VektorraumM2,3 und den Vektorrarum (F23)3 durch

sage: MS = MatrixSpace(ZZ,3,3); MSFull MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: VS = VectorSpace(GF(3^2,'x'),3); VSVector Space of dimension 3 over Finite Field in x of size 3^2

Ein System von Erzeugenden für diese Vektorräume ist durch die kanonische Basis gegeben;man kann sie mit MS.gens() als Tupel oder mit MS.basis() als Liste bekommen.

sage: MatrixSpace(ZZ,2,3).basis()[(1 0 00 0 0

),

(0 1 00 0 0

),

(0 0 10 0 0

),

(0 0 01 0 0

),

(0 0 00 1 0

),

(0 0 00 0 1

)]

155

Page 172: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Matrixgruppen. Wir können auÿerdem Untergruppen des gesamten Matrix-Vektorraumsdenieren. So gibt der Konstruktor MatrixGroup([A,B,...]) die Gruppe zurück, die vonden als Argument übergebenen Matrizen erzeugt wird. Sie müssen invertierbar sein.

sage: A = matrix(GF(11), 2, 2, [1,0,0,2])sage: B = matrix(GF(11), 2, 2, [0,1,1,0])sage: MG = MatrixGroup([A,B])

Matrix-VektorräumeKonstruktion MS = MatrixSpace(K, nrows, ncols)

von dünn besetzten M. MS = MatrixSpace(K, nrows, ncols), sparse=True

Ring mit Basis K MS.base_ring()

Ringerweiterung MS.base_extend(B)

Ringänderung MS.change_ring(B)

aufgespannte Gruppe MatrixGroup([A,B])

Basis des Vektorraums MS.basis() oder MS.gens()

Erzeugung von MatrizenNullmatrix MS() oder MS.zero() oder matrix(K,nrows,ncols)

Matrix mit Elementen MS([1,2,3,4] oder matrix(K,2,2,[1,2,3,4]) oder

matrix(K,[[l,2] , [3,4]])

Identitätsmatrix MS.one() oder MS.identity_matrix() oder

identity_matrix(K,n)

Zufallsmatrix MS.random_element() oder

random_matrix(K,nrows,ncols)

Jordan-Block jordan_block(x,n)

Matrix durch Blöcke block_matrix([A,l,B,0]) oder block_diagonal_matrix

Manipulations de baseZugri auf ein Element A[2,3]

Zugri auf Zeile oder Spalte A[-l,:], A[:,2]

Zugri auf Spaltenpaare A[:,0:8:2]

Untermatrizen A[3:4,2:5], A[:,2:5], A[:4,2:5]

A.matrix_from_rows( [1,3]),

A.matrix_from_columns([2,5]),

A.matrix_from_rows_and_columns([1,3], [2,5])

A.submatrix(i,j,nrows,ncols)

Verkettung durch Zeilen A.stack(B)

Verkettung durch Spalten A.augment(B)

Tabelle 8.1 - Konstruktoren von Matrizen und ihren Vektorräumen.

sage: MG.cardinality()200sage: identity_matrix(GF(11),2) in MGTrue

Die allgemeine lineare Gruppe vom Grad n auf einem Körper K, geschrieben GLn(K), istdie von den invertierbaren n × n-Matrizen gebildete Gruppe. In Sage konstruiert man sienatürlicherweise mit dem Befehl GL(n,K). Die spezielle lineare Gruppe SLn(K) mit Elementenaus GLn(K) mit der Determinante 1 konstruiert man mit dem Befehl SL(n,K).

156

Page 173: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.1. Erstellung und elementare Operationen

8.1.2. Erzeugung von Matrizen und Vektoren

Matrizen und Vektoren können selbstverständlich als Elemente eines Vektorraums durch Über-gabe der Liste ihrer Einträge als Argument erzeugt werden. Bei Matrizen werden sie als Zeileeingelesen:

MS = MatrixSpace(ZZ,2,3); A = MS([1,2,3,4,5,6]); A(1 2 34 5 6

)Der leere Konstruktor MS() gibt eine Nullmatrix zurück, genau wie die Methode MS.zero().Mehrere spezielle Konstruktoren ermöglichen die Erzeugung gebräuchlicher Matrizen wierandom_matrix, identity_matrix, jordan_bloc (siehe Tabelle 8.1). Insbesondere könnenwir Matrizen und Vektoren mit den Konstruktoren matrix und vector erzeugen, ohne zuvorden zugehörigen Vektorraum bilden zu müssen. In der Voreinstellung wird eine Matrix aufdem Ring der ganzen Zahlen Z konstruiert und hat als Dimensionen 0× 0.

sage: a = matrix(); a.parent()Full MatrixSpace of 0 by 0 dense matrices over Integer Ring

Natürlich kann man für die Einträge eine Denitionsmenge wie auch die Dimensionen angeben,wenn eine Nullmatrix erzeugt wird oder sonst auch eine Liste aller Einträge als Argument.

sage: a = matrix(GF(8,'x'),3,4); a.parent()Full MatrixSpace of 3 by 4 dense matrices over Finite Field in x of size 2^3

Der Konstruktor matrix akzeptiert auch Objekte als Argument, die eine natürliche Transfor-mation in eine Matrix zulassen. Er kann so verwendet werden, um die Adjazenzmatrix einesGraphen in Gestalt einer Koezientenmatrix in Z zu bekommen.

sage: g = graphs.PetersenGraph()sage: m = matrix(g); m; m.parent()

[0 1 0 0 1 1 0 0 0 0][1 0 1 0 0 0 1 0 0 0][0 1 0 1 0 0 0 1 0 0][0 0 1 0 1 0 0 0 1 0][1 0 0 1 0 0 0 0 0 1][1 0 0 0 0 0 0 1 1 0][0 1 0 0 0 0 0 0 1 1][0 0 1 0 0 1 0 0 0 1][0 0 0 1 0 1 1 0 0 0][0 0 0 0 1 0 1 1 0 0]Full MatrixSpace of 10 by 10 dense matrices over Integer Ring

157

Page 174: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Blockmatrizen. Zur Konstruktion einer Blockmatrix aus Untermatrizen können wir dieFunktion block_matrix nutzen.

sage: A = matrix([[1,2],[3,4]])sage: block_matrix([[A,-A],[2*A,A^2]])

1 2 −1 −23 4 −3 −4

2 4 7 106 8 15 22

Voreingestellt ist eine quadratische Struktur, doch kann die Anzahl der Zeilenblöcke oder derSpaltenblöcke durch die optionalen Argumente ncols und nrows festgelegt werden. Nachdemdas möglich ist, kann ein Eintrag wie 0 oder 1 als Diagonalblock mit passenden Dimensioneninterpretiert werden (hier als Nullmatrix und Identitätsmatrix)

sage: A = matrix([[1,2],[3,4]])sage: block_matrix([1,A,0,0,-A,2], ncols=3)

1 0 1 2 3 0 00 1 4 5 6 0 0

0 0 −1 −2 −3 2 00 0 −4 −5 −6 0 2

Im Spezialfall diagonaler Blockmatrizen übergeben wir dem Konstruktor block_diagonal_matrix einfach die Liste der diagonalen Blöcke.

sage: A = matrix([[1,2,3],[0,1,0]])sage: block_diagonal_matrix(A, A.transpose())

1 2 3 0 00 1 0 0 0

0 0 0 1 00 0 0 2 10 0 0 3 0

Die Blockstruktur ist nur eine Abart der Eingabe, und Sage behandelt die Matrix wie jedeandere auch. Wir können diese Eingabe auch deaktivieren, indem wir dem Konstruktor dasArgument subdivide=False hinzufügen.

8.1.3. Grundlegende Operationen und Matrizen-Arithmetik

Indizes und der Zugri auf Einträge. Der Zugri auf Einträge sowie auf Untermatrizengeschieht mit eckigen Klammern A[i,j], wobei die Regeln von Python gelten. Die Zeilenin-dizes i und die Spaltenindizes j müssen für den Zugri auf Einträge ganze Zahlen sein (wirerinnern uns, dass die Indizierung in Python mit 0 beginnt und die Intervalle schlieÿen dieuntere Grenze ein, die obere aber aus). Das Intervall " : " ohne Grenzen entspricht derGesamtheit der möglichen Indizes in der betrachteten Dimension. Die Schreibweise a:b:k er-möglicht den Zugri auf Indizes zwischen a und b−1 mit der Schrittweite k. Negative Indizessind ebenfalls gültig und ermöglichen, die Indizes vom Ende her zu durchlaufen. So entsprichtA[-2,:] der vorletzten Zeile. Der Zugri auf Untermatrizen ist sowohl lesend wie schreibendmöglich. Eine gegebene Spalte können wir beispielsweise auf folgende Weise verändern:

158

Page 175: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.1. Erstellung und elementare Operationen

sage: A = matrix(3,3,range(9))sage: A[:,1] = vector([1,1,1]); A 0 1 2

3 1 56 1 8

Der Schrittparameter k kann auch negativ sein und bezeichnet dann einen Durchlauf in ab-steigender Richtung.

sage: A[::-1], A[:,::-1], A[::2,-1]6 1 83 1 50 1 2

,

2 1 05 1 38 1 6

,

(28

)

Isolation von Untermatrizen. Um eine Matrix unter Angabe einer Liste von Zeilen- oderSpaltenindizes zu isolieren, die nicht unbedingt benachbart sein müssen, benutzten wir dieMethode A.matrix_from_rows_and_columns.

sage: A = matrix(ZZ,4,4,range(16)); A0 1 2 34 5 6 78 9 10 1112 13 14 15

sage: A.matrix_from_rows_and_columns([0,2,3],[1,2]) 1 2

9 1013 14

Um eine Untermatrix mit benachbarten Zeilen und Spalten zu extrahieren, können wir unsauch der Methode submatrix(i,j,m,n) bedienen, die eine m×n-Matrix bildet, deren obererlinker Eintrag sich an Position (i, j) bendet.

Einfügen und Erweitern. Möchte man einen Matrix-Vektorraum in einen solchen gleicherDimension, aber mit Einträgen aus einer Erweiterung des Basisringes einfügen, kann man mitder Methode base_extend des Matrix-Vektorraumes arbeiten. Diese Operation ist jedoch nurgültig für die Erweiterung eines Körpers oder eines Ringes. Um die Änderung eines Basisringeszu bewirken, die einem Morphismus folgt (sofern der existiert), verwendet man besser dieMethode change_ring.

sage: MS = MatrixSpace(GF(3),2,3)sage: MS.base_extend(GF(9,'x'))Full MatrixSpace of 2 by 3 dense matrices over Finite Field in x of size 3^2sage: MS = MatrixSpace(ZZ,2,3)sage: MS.change_ring(GF(3))Full MatrixSpace of 2 by 3 dense matrices over Finite Field of size 3

159

Page 176: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Mutabilität und Zwischenspeicherung. Die Objekte, die Matrizen repräsentieren, sind nachVoreinstellung mutabel, was heiÿt, dass ihre Einträge nach ihrer Erzeugung noch beliebigmodiziert werden können. Will man eine Matzrix vor Veränderung schützen, benutzt mandie Funktion A.set_immutable(). Es ist dann weiterhin möglich, mit der Funktion copy(A)mutable Kopien herzustellen. Anzumerken ist, dass der Mechanismus der Zwischenspeicherungder Ergebnisse von Berechnungen (wie Rang, Determinante usw.) funktionsfähig bleibt, obnun mutabel oder nicht.

8.1.4. Grundlegende Operationen mit Matrizen

Die arithmetischen Operationen mit Matrizen geschehen mit den üblichen Operatoren +,−,∗und ^. Die Inverse einer Matrix kann sowohl A^-1 als auch ~A geschrieben werden. Wenn aein Skalar ist und A eine Matrix, entspricht die Operation a*A der äuÿeren Multiplikationdes Matrix-Vektorraumes. Bei den anderen Operationen, bei denen ein Skalar a anstelle einerMatrix eingegeben wird (zum Beispiel die Operation a+A), wird a als skalare Matrix angesehen,die aIn entspricht, wenn a 6= 0 ist und die Dimensionen das erlauben. Die elementweiseMultiplikation zweier Matrizen wird mit der Operation elementwise_product angestoÿen.

8.2. Rechnungen mit Matrizen

In der linearen Algebra können Matrizen zur Darstellung von Vektorfamilien verwendet wer-den, von linearen Gleichungssystemen, von linearen Anwendungen und von Untervektorräu-men. So wird die Berechnung einer Eigenschaft wie der Rang einer Familie, der Lösung einesGleichungssystems, von Eigenräumen einer linearen Anwendung oder der Dimension einesUntervektorraumes zurückgeführt auf Transformationen von Matrizen, die diese Eigenschaftaufweisen.

Grundlegende OperationenTransponierte, Konjugierte A.transpose(), A.conjugate()

äuÿeres Produkt a*A

Summe, Produkt, k-te Potenz, Inverse A + B, A*B, A^k, A^-1 oder -A

Tab. 8.2 - Grundlegende Operationen und Arithmetik mit Matrizen

Diese Transformationen entsprechen Basiswechseln, die auf der Ebene der Matrizen als Äqui-valenzumformungen erscheinen: B = PAQ−1, wobei P und Q invertierbare Matrizen sind.Zwei Matrizen heiÿen äquivalent, wenn eine solche Umformung existiert, die eine in die andereumwandelt. Für diese Relation können wir auch Äquivalenzklassen bilden, und wir denierenNormalformen, um jede Äquivalenzklasse auf eindeutige Weise zu charakterisieren. Im Fol-genden stellen wir die wichtigsten Rechnungen mit Matrizen vor, die in Sage verfügbar sind.Dabei betrachten wir besonders zwei Fälle dieser Transformationen:

- Die Äquivalenzumformungen von links der Form V = UA, die solche charakteritischen Ei-genschaften für die Vektorfamilien zeigen, wie den Rang (Anzahl der linear unabhängigenVektoren), die Determinante(Volumen des Parallelepipeds, das durch die Vektorfamilie be-schrieben wird), das Rangprol (erste Teilmenge von Vektoren, die eine Basis bilden),. . .Der Gauÿ-Algorithmus ist das zentrale Werkzeug für diese Umformungen und die reduzierteTreppennormalform (die Gauÿ-Jordan-Form in einem Körper oder die Hermite-Form in Z)ist die normale Form. Darüberhinaus dienen diese Transformationen zur Lösung linearerGleichungssysteme.

160

Page 177: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

- Die Ähnlichkeitstransformationen der Form B = UAU−1, welche die charakteritischen Ei-genschaften von Matrizen zeigen, die Endomorphismen darstellen, wie Eigenwerte, Eigenräu-me, minimale und charakteristische Polynome,. . . Die Jordan-Form oder die Frobenius-Formwerden je nach Denitionsmenge der Rechnung die Normalformen für diese Transformatio-nen sein.

Die Form von Gram-Schmidt ist eine weitere Zerlegung, die auf Äquivalenzumformungen vonlinks basiert und die eine Matrix in eine Menge von orthogonalen Vektoren umwandelt.

8.2.1. Gauÿ-Algorithmus und Treppennormalform

Gauÿ-Algorithmus und Äquivalenz von links. Der Gauÿ-Algorithmus ist eines der grundle-genden Verfahren in der linearen Algebra; denn er erlaubt den Zugri auf eine Matrixdarstel-lung, die an das Rechnen angepasst ist wie die Lösung von Gleichungssystemen und gleich-zeitig einige ihrer fundamentalen Eigenschaften zeigt wie den Rang, die Determinante, dasRangprol usw. Die wesentlichen Operationen des Verfahrens sind die elementaren Zeilenope-rationen:

- Vertauschen zweier Zeilen: Li ↔ Lj ,

- Addition des Vielfachen einer Zeile zu einer anderen: Li ← Li + sLj .

Auf der Matrixebene entsprechen diese Transformationen der Multiplikation von links mit derTranspositionsmatrix Ti,j bzw. mit der Transvektionsmatrix Ci,j,s, die gegeben sind durch

i j

Ti,j =

1. . .

0 1. . .

1 0. . .

1

, Ci,j,s =

1. . .

1 s. . .

1. . .

i

j.

Diese Matrizen haben alle eine Determinante 1 oder −1. Somit kann jede Multiplikation vonlinks mit einem Produkt dieser Matrizen als Basiswechsel gesehen werden, der das Volumenkonstant lässt und daher insbesondere die Determinante (bis auf das Vorzeichen). In Sage er-folgt die Transvektion mit der Methode add_multiple_of_row(i,j,s) und die Transpositionmit der Methode swap_rows(i,j).

161

Page 178: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Gauÿ-Algorithmus und AnwendungenZeilen-Transvektion add_multiple_of_row(i,j,s)

Spalten-Transvektion add_multiple_of_column(i,j,s)

Zeilen-, Spalten-Transposition swap_rows(i1,i2), swap_columns(j1,j2)

Gauÿ-Jordan-Form, unveränderlich echelon_form

Gauÿ-Jordan-Form, in place echelonize

invariante Faktoren elementay_divisors

Normalform von Smith smith_form

Determinante, Rang det, rank

Minoren der Ordnung k minors(k)

Rangprol der Spalte, der Zeile pivots, pivot_rows

Lösung des Systems von links (txA = b) b/A oder A.solve_left(b)Lösung des Systems von rechts (Ax = b) A\b oder A.solve_right(b)

Bild des Vektorraumes image

Kern von links kernel oder left_kernelKern von rechts right_kernel

Kern im Basis-Ring integer_kernel

Spektralzerlegungminimales Polynom minimal_polynomial oder minpoly

charakteristisches Polynom charakteristic_polynomial oder charpolyKrylow-Iteration von links maxspin(v)

Eigenwerte eigenvalues

Eigenvektoren von links, von rechts eigenvectors_left, eigenvectors_right

Eigenräume von links, von rechts eigenspaces_left, eigenspaces_right

Diagonalisierung eigenmatrix_left, eigenmatrix_right

Jordanblock Ja,k jordan_block(a,k)

Tab. 8.3 - Rechnungen mit Matrizen

Zu einem gegebenen Spaltenvektor x =

x1...xm

, dessen k-ter Eintrag xk invertierbar ist, denie-ren wir die Gauÿ-Transformation als Komposition der Transvektion Ci,k,li für i = k+ 1, . . .mmit li = − xi

xk(ungeachtet der Reihenfolge, in der sie wechseln). Die entsprechende Matrix ist

die folgende:

Gz,k = Ck+1,k,lk+1× . . .× Cm,k,lm

1. . .

1

lk+1. . .

lk+2. . .

.... . .

lm 1

k

.

Eine Gauÿ-Transformation Gx,k bewirkt, dass die Einträge unterhalb des Pivotelements xkverschwinden:

Gx,k =

x1...xkxk+1...xm

=

x1...xk0...0

.

162

Page 179: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

Für eine Matrix A = [ai,j ] der Dimension m × n schreitet der Pivot-Algorithmus von Gauÿiterativ voran, von der linken zur rechten Spalte. Unter der Voraussetzung, dass die erstenk − 1 Spalten bereits bearbeitet sind, was p ≤ k − 1 Pivots geliefert hat, wird die k-te Spaltewie folgt behandelt:

- Finde den ersten invertierbaren Eintrag ai,k der Spalte Ck auf einer Zeile i > p. Wir nennenihn die Pivotstelle.

- Wird keine Pivotstelle gefunden, gehe weiter zur nächsten Spalte.

- Wende die Transposition Ti,p+1 auf die Zeilen an, um die Pivotstelle auf die Position (p+1, k)zu setzen.

- Wende die Gauÿ-Transformation Gx,p+1 an mit x als der neuen Spalte Ck.

Dieser Algorithmus transformiert die Matrix A in eine obere Dreiecksmatrix. Genauer gesagt,wird sie in Treppennormalform sein, d.h. dass der erste von 0 verschiedene Eintrag jeder Zeilesich rechts vom ersten solchen Eintrag der Zeile darüber bendet; auÿerdem nden sich alleNullzeilen unten in der Matrix. Hier ein Beispiel für den Ablauf dieses Algorithmus:

sage: a = matrix(GF(7),4,3,[6,2,2,5,4,4,6,4,5,5,1,3]); a6 2 25 4 45 1 3

sage: u = copy(identity_matrix(GF(7),4)); u[1:,0] = -a[1:,0]/a[0,0]sage: u, u*a

1 0 0 05 1 0 06 0 1 05 0 0 1

,

6 2 20 0 00 2 30 4 6

sage: v = copy(identity_matrix(GF(7),4)); v.swap_rows(1,2)sage: b = v*u*a; v, b|

1 0 0 00 0 1 00 1 0 00 0 0 1

,

6 2 20 2 30 0 00 4 6

sage: w = copy(identity_matrix(GF(7),4))sage: w[2:,1] = -b[2:,1]/b[1,1]; w, w*b

1 0 0 00 1 0 00 0 1 00 5 0 1

,

6 2 20 2 30 0 00 0 0

163

Page 180: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Der Gauÿ-Jordan-Algorithmus. Die Transformation von Gauÿ-Jordan ähnelt dem Gauÿ-Algorithmus, es wird Gx,k die Transvektion hinzugefügt, die der Zeile mit dem Index i < kentspricht. Das läuft darauf hinaus, dass die Einträge einer Spalte unterhalb und oberhalbdes Pivots eliminiert werden. Teilt man auÿerdem jede Zeile durch ihren Pivot, erhält maneine Treppennormalform, die reduziert oder Gauÿ-Jordan-Form genannt wird. Für jede Äqui-valenzklasse von Matrizen existiert eine eindeutige Matrix in dieser Gestalt; es handelt sichdabei also um eine Normalform.

Definition. Eine Matrix bendet sich in reduzierter Treppennormalform, wenn:

- sich alle Nullzeilen unten in der Matrix benden,

- der am weitesten links bendliche von 0 verschiedene Eintrag, der Pivot, eine 1 ist undrechts des Pivots der Zeile darüber liegt,

- die Pivots die einzigen von 0 verschiedenen Einträge innerhalb ihrer Spalte sind.

Satz. Für jede Matrix A der Dimension m × n mit Einträgen aus einem Körper existierteine eindeutige Matrix R der Dimension m × n in reduzierter Treppennormalform und eineinvertierbare Matrix U der Dimension m×n, sodass UA = R gilt. Es handelt sich hierbei umdie Gauÿ-Jordan-Zerlegung.

In Sage erhält man die reduzierte Treppennormalform mit den Methoden echelonize undechelon_form. Die erstere ersetzt die ursprüngliche Matrix durch ihre reduzierte Treppennor-malform, währen die zweite eine unveränderliche Matrix zurückgibt ohne die ursprüngliche zuverändern.

sage: A = matrix(GF(7),4,5,[4,4,0,2,4,5,1,6,5,4,1,1,0,1,0,5,1,6,6,2])sage: A, A.echelon_form()

4 4 0 2 45 1 6 5 41 1 0 1 05 1 6 6 2

,

1 0 5 0 30 1 2 0 60 0 0 1 50 0 0 0 0

Mehrere Varianten des Gauÿ-Algorithmus erscheinen als verschiedene Formen der Matrizen-zerlegung, die bei Rechnungen zuweilen nützlich sind: Die Zerlegung A = LU für generischeMatrizen, A = LUP für reguläre Matrizen, A = LQUP oder A = PLUQ für Matrizenbeliebigen Ranges. Die Matrizen L sind untere Dreiecksmatrizen (mit Nullen oberhalb derHauptdiagonalen, auf englisch Lower triangular), U obere Dreiecksmatrix (Upper triangular),und die Matrizen P,Q sind Permutationen. Wenn diese Varianten algorithmisch auch wenigeraufwendig sind als die reduzierte Treppennormalform, bieten sie doch nicht den Vorteil, eineNormalform zu liefern.

Treppennormalform auf euklidschen Ringen. Auf einem euklidschen Ring sind die von 0verschiedenen Einträge nicht unbedint invertierbar, und der Gauÿ-Algorithmus beruht daherauf der Auswahl des ersten invertierbaren Eintrags in der aktuellen Spalte als Pivot. Sokönnen bestimmte Spalten, obwohl ein von 0 verschiedener Eintrag vorhanden ist, keinenPivot enthalten, und das Verfahren ist nicht durchführbar.

Es ist demgegenüber immer möglich, eine unimodulare Transformation zu denieren, die mitHilfe des erweiterten euklischen Algorithmus den Eintrag am Anfang einer Zeile mit demje-nigen einer anderen eliminiert.

164

Page 181: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

Sei A =

[a ∗b ∗

]und sei g = pgcd(a, b). Seien u und v die vom erweiterten, auf a und b

angewandten euklidschen Algorithmus ermittelten Bézout-Koezienten (sodass g = ua + vbist), und s = −b/g, t = a/g sodass[

u vs t

] [a ∗b ∗

]=

[g ∗0 ∗

].

Diese Transformation ist unimodular, denn es gilt det

([v vs t

])= 1.

Auÿerdem kann man wie bei Gauÿ-Jordan den Zeilen darüber immer Vielfache der Pivotzeilehinzufügen, um ihre Einträge in derselben Spalte modulo des Pivotelements g zu reduzieren.Wird diese Operation nach und nach auf alle Spalten der Matrix angewendet, ergibt das diehermitesche Normalform.

Definition. Eine Matrix heiÿt hermitesch, wenn

- sich die Nullzeilen unten benden,

- die am weitesten links stehenden und von 0 verschiedenen Einträge jeder Zeile, die Pivot-elemente heiÿen, sich rechts vom Pivotelement in der Zeile darüber benden,

- alle Einträge oberhalb des Pivots reduziert sind modulo des Pivots.

Satz. Zu jeder Matrix A der Dimension m×n mit Koezienten aus einem euklidschen Ringexistieren eine eindeutige hermitesche Matrix H der Dimension m× n und eine unimodulareMatrix U der Dimension m×m sodass UA = H gilt.

Bei einem Körpers entspricht die hermitesche Form der Zeilentreppenform oder der Form vonGauÿ-Jordan. In diesem Fall sind alle Pivotelemente tatsächlich invertierbar, jede Zeile kanndurch ihr Pivotelement dividiert werden, und die Einträge darüber können wieder durch eineGauÿ-Transformation eliminiert werden, wodurch eine reduzierte Treppennormalforn entsteht.In Sage gibt es dafür eine einzige Methode: echelon_form, die entweder die hermitesche Formoder die reduzierte Treppennormalform zurückgibt, je nachdem, ob die Einträge der Matrixaus einem Ring oder einem Körper kommen.

Für eine Matrix mit Koezienten aus Z beispielsweise erhalten wir zwei verschiedene Trep-pennormalformen, je nachdem ob die Basismenge Z oder Q ist:

sage: a = matrix(ZZ, 4, 6, [2,1,2,2,2,-1,1,2,-1,2,1,-1,2,1,-1,\-1,2,2,2,1,1,-1,-1,-1]); a.echelon_form()

1 2 0 5 4 −10 3 0 2 −6 −70 0 1 3 3 00 0 0 6 9 3

sage: a.base_extend(QQ).echelon_form()

1 0 0 0 52

116

0 1 0 0 −3 −83

0 0 1 0 −32 −3

20 0 0 1 3

212

165

Page 182: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Für Matrizen auf Z kann die hermitesche Normalform auch mit hermite_form berechnetwerden. Um die Übergangsmatrix U zu erhalten, sodass UA = H wird, können wir die Optiontransformation=True wählen.

sage: A = matrix(ZZ,4,5,[4,4,0,2,4,5,1,6,5,4,1,1,0,1,0,5,1,6,6,2])sage: H, U = A.echelon_form(transformation=True); H, U

1 1 0 0 20 4 −6 0 −40 0 0 1 −20 0 0 0 0

,

0 1 1 −10 −1 5 00 −1 0 11 −2 −4 2

Invariante Faktoren und die Normalform von Smith. Wenn wir die hermitesche Formmit weiteren unimodularen Transformationen von rechts (d.h. mit den Spalten) umformen,erhalten wir eine kanonische Diagonalmatrix, die Normalform von Smith. Ihre Einträge aufder Diagonalen sind die invarianten Faktoren (engl. elementary divisors) der Matrix. Sie sindnach Teilbarkeit total geordnet (d.h. si | si+1).

Satz. Zu jeder Matrix A der Dimension m × n mit Einträgen aus einem Hauptidealringexistieren unimodulare Matrizen U und V der Dimension m × m bzw. n × n und einem × n-Diagonalmatrix S, sodass S = UAV ist. Die Einträge si = Si,i erfüllen für i ∈1, . . . ,min(m,n) die Beziehung si | si+1 und heiÿen invariante Faktoren von A.

In Sage gibt die Methode elementary_divisors die Liste der invarianten Faktoren zurück.Wirkönnen auÿerdem die Normaform von Smith berechnen sowie mit dem Befehl smith_form dieÜbergangsmatrizen U und V .

sage: A = matrix(ZZ, 4, 5, [-1,-1,-1,-2,-2,-2,1,1,-1,2,2,2,2,2,-1,2,2,2,2,2])sage: S,U,V = A.smith_form(); S,U,V

1 0 0 0 00 1 0 0 00 0 3 0 00 0 0 6 0

,

1 0 0 00 0 1 0−2 1 0 0

0 0 −2 −1

,

0 −2 −1 −5 01 0 1 −1 −10 0 0 0 1−1 2 0 5 0

0 −1 0 −2 0

sage: A.elementary_divisors()[1, 1, 3, 6]sage: S == U*A*VTrue

Rang, Rangprol und Pivotelemente. Der Gauÿ-Algorithmus oenbart zahlreiche Invari-anten der Matrix wie ihren Rang und ihre Determinante (die als Produkt der Pivotstellengelesen werden kann). Sie sind mit den Funktionen det und rank zugänglich. Diese Wer-te werden intern gespeichert und werden deshalb bei einem erneuten Aufruf nicht nochmalsberechnet.

Allgemeiner ist der Begri des Rangprols sehr nützlich, wenn die Matrix als Folge von Vek-toren betrachtet wird.

Definition. Das Rangprol nach Spalten einer m× n-Matrix mit dem Rang r ist die Folgeder r lexikographisch minimalen Indizes, sodass die entsprechenden Spalten von A linearunabhängig sind.

166

Page 183: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

Das Rangprol wird an der reduzierten Treppennormalform als Folge der Indizes der Pivot-stellen direkt abgelesen. Es wird von der Funktion pivots berechnet. Wenn die reduzierteTreppennormalform bereits berechnet ist, ist auch das Rangprol schon gespeichert und kannohne zusätzliche Rechnung erhalten werden.

Das Rangprol nach Zeilen ist auf ähnliche Weise deniert, indem die Matrix als Folge vonm Zeilenvektoren angesehen wird. Wir bekommen es mit dem Befehl pivot_rows oder alsUnterprodukt der reduzierten Treppennormalform der Transponierten Matrix.

sage: B = matrix(GF(7),5,4,[4,5,1,5,4,1,1,1,0,6,0,6,2,5,1,6,4,4,0,2])sage: B.transpose().echelon_form()

1 0 5 0 30 1 2 0 60 0 0 1 50 0 0 0 0

sage: B.pivot_rows()(0, 1, 3)sage: B.transpose().pivots() == B.pivot_rows()True

8.2.2. Lösung von Gleichungssystemen; Bild und Basis des Kerns

Lösung von Gleichungssystemen. Ein lineares Gleichungssystem kann durch eine Matrix Adargestellt werden und einen Vektor b, sei es von rechts: Ax = b, sei es von links: txA = b. DieFunktionen solve_right und solve_left bewirken die Lösung. Auch kann man, gleichwertigdazu, die Operatoren A\b und b/A benutzen. Sobald das System durch eine Koezientenma-trix auf einem Ring gegeben ist, wird die Lösung systematisch auf dem Körper der Brüchedieses Ringes berechnet (z.B. Q für Z oder K(X)) für K[X]). im weiteren wird man sehen,wie die Lösung im Ring selbst berechnet wird. Das rechte Glied in der Gleichung des Systemskann sowohl ein Vektor sein als auch eine Matrix (was der gleichzeitigen Lösung mehrererlinearer Systeme mit gleicher Matrix entspricht).

Die Matrizen der Systeme können rechteckig sein, und die System können keine, genau eineoder unendlich viele Lösungen besitzen. In diesem letzteren Fall gibt die Funktion solve einedieser Lösungen zurück, indem sie die Bestandteile, die linear abhängigen Spalten des Systemsentsprechen, zu null setzt.

sage: R.<x> = PolynomialRing(GF(5),'x')sage: A = random_matrix(2,3); A(

4x2 + 1 2x2 + 4x+ 1 4x2 + 33x2 + 3x 3x+ 4 2x2 + x+ 1

)sage: b = random_matrix(R,2,1); b (

2x+ 12x2 + x

)

167

Page 184: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

sage: A.solve_right(b) 4x2 + 3x+ 3

x2 + 3x+ 32x2 + x

x2 + 3x+ 30

sage: A.solve_right(b) == A\bTrue

Bild und Kern. Als lineare Abbildung Φ interpretiert, deniert eine m × n-Matrix A zweiUntervektorräume Km und Kn bzw. Bild und Kern von Φ.

Das Bild ist die Menge der Vektoren von Km, die durch Linearkombination der Spalten vonA erhalten wird, Man bekommt es mit der Funktion image, die einen Vektorraum mit derBasis in Treppennormalform zurückgibt.

Der Kern ist der Untervektorraum Kn von Vektoren x, sodass Ax = 0 ist. Die Berechnungeiner Basis dieses Untervektorraums dient insbesondere zur Beschreibung der Lösungsmengeeines linearen Systems, wenn es unendlich viele Lösungen besitzt: wenn x eine Lösung vonAx = b ist und V der Kern von A, dann wird die Lösungsmenge einfach x + V geschrieben.Wir erhalten ihn mit der Funktion right_kernel, die eine Beschreibung des Vektorraums zu-sammen mit einer Basis in Gestalt der reduzierten Treppennormalform zurückgibt. Natürlichkönnen wir auch den Kern von links denieren (die Menge der x in Km mit txA = 0), welcherdem Kern von rechts der Transponierten von A entpricht (d.h. der Adjungierten von Φ). Denerhalten wir mit der Funktion left_kernel. Es ist festgelegt, dass die Funktion kernel denKern von links zurückgibt. Auÿerdem werden die Basen in beiden Fällen als Matrizen vonZeilenvektoren zurückgegeben.

sage: a = matrix(QQ,3,5,[2,2,-1,-2,-1,2,-1,1,2,-1/2,2,-2,-1,2,-1/2])sage: a.image()Vector space of degree 5 and dimension 3 over Rational FieldBasis matrix:[ 1 0 0 1/4 -11/32][ 0 1 0 -1 -1/8][ 0 0 1 1/2 1/16]sage: a.right_kernel()Vector space of degree 5 and dimension 2 over Rational FieldBasis matrix:[ 1 0 0 -1/3 8/3][ 0 1 -1/2 11/12 2/3]

Der Begri des Kerns wird für den Fall verallgemeinert, dass die Koezienten keine Körperele-mente mehr sind; dann handelt es sich um ein freies Modul. Ist eine Matrix insbesondere übereinem Körper von Brüchen deniert, werden wir den Kern mit dem Befehl integer_kernelin einem Basisring erhalten. Zu einer Matrix mit Koezienten aus Z beispielsweise, die in denVektorraum der Matrizen mit Koezienten aus Q eingebettet ist, können wir den Kern sehrwohl auch als Untervektorraum von Qm oder als freien Modul von Zm berechnen.

sage: a = matrix(ZZ,5,3,[1,1,122,-1,-2,1,-188,2,1,1,-10,1,-1,-1,-1])sage: a.kernel()Free module of degree 5 and rank 2 over Integer Ring

168

Page 185: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

Echelon basis matrix:[ 1 979 -11 -279 811][ 0 2079 -22 -569 1488]sage: b = a.base_extend(QQ)sage: b.kernel()Vector space of degree 5 and dimension 2 over Rational FieldBasis matrix:[ 1 0 -121/189 -2090/189 6949/63][ 0 1 -2/189 -569/2079 496/693]sage: b.integer_kernel()Free module of degree 5 and rank 2 over Integer RingEchelon basis matrix:[ 1 979 -11 -279 811][ 0 2079 -22 -569 1488]

8.2.3. Eigenwerte, Jordanform und Ähnlichkeitstransformationen

Wenn wir eine quadratische Matrix als linearen Operator interpretieren (ein Endomorphis-mus), ist sie nur die Darstellung zu einer gegebenen Basis. Jeder Basiswechsel entspricht einerÄhnlichkeitstransformation B = U−1AU der Matrix. Die beiden Matrizen A und B heiÿendeshalb ähnlich. So werden die Eigenschaften des linearen Operators, die von der Basis un-abhängig sind, durch die Untersuchung der Ähnlichkeitsinvarianten der Matrix gefunden.

Unter diesen Invarianten sind die einfachsten der Rang und die Determinante. Tatsächlich istder Rang von U−1AU , wobei U−1 und U invertierbare Matrizen sind, gleich dem Rang von A.Auÿerdem ist det(U−1AU) = det(U−1) det(A) det(U) = det(U−1U) det(A) = det(A). Ebensoist das charakteristische Polynom der Matrix A, das durch χA(x) = det(xId − A) deniertist, bei Ähnlichkeitstransformation invariant:

det(xId− U−1AU) = det(U−1(xId−A)U) = det(xId−A).

Als Konsequenz sind die charakteristischen Werte einer Matrix, die als Wurzeln des charakte-ristischen Polynoms in ihrem Zerlegungskörper deniert sind, ebenfalls Ähnlichkeitsinvarian-ten. Denitionsgemäÿ ist ein Skalar λ ein Eigenwert einer Matrix A, wenn ein Vektor u, derkein Nullvektor ist, existiert, sodass Au = λu ist. Der einem Eigenwert λ zugeordnete Eigen-raum ist die Menge der Vektoren u, sodass Au = λu ist. Das ist ein durch Eλ = Ker(λId−A)denierter Untervektorraum.

Die Eigenwerte fallen mit den charakteristischen Werten zusammen:

det(λId−A) = 0⇔ dim(Ker(λId−A)) ≥ 1⇔ ∃u 6= 0, λu−Au = 0.

Diese beiden Sichtweisen entsprechen jeweils dem algebraischen bzw. dem geometrischen An-satz der Eigenwerte. Bei der geometrischen Sichtweise interessieren wir uns für die Wirkungdes linearen Operators A auf die Vektoren des Vektorraums mit gröÿerer Genauigkeit als beider algebraischen Sichtweise. Insbesondere unterscheiden wir die Begrie der algebraischenVielfachheit, die der Ordnung der Wurzeln des charakteristischen Polynoms entspricht, vonder geometrischen Vielfachheit, die der Dimension des dem Eigenwert zugeordneten Eigen-untervektorraums entspricht. Bei diagonalisierbaren Matrizen sind beide Begrie äquivalent.Andernfalls ist die geometrische Vielfachheit immer kleiner als die algebraische.

169

Page 186: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Die geometrische Sichtweise erlaubt eine weitergehende Beschreibung der Struktur der Matrix.Auÿerdem gibt es viel schnellere Algorithmen für die Berechnung der Eigenwerte und -räumesowie der charakteristischen und minimalen Polynome.

Zyklische invariante Vektorräume und Frobenius-Normalform. Sei A eine n × n-Matrixauf einem Körper K und u ein Vektor aus Kn. Die Familie der Vektoren u, Au, A2u, . . ., Anuheiÿt Krylow-Folge und ist damit verbunden (als Familie von n+1 Vektoren der Dimension n).Sei d eine Zahl, sodass Adu der erste Vektor der linear abhängigen Folge mit den Vorgängernu,Au, . . . , Ad−1u ist. Wir schreiben diese Relation der linearen Abhängigkeit dann

Adu =

d−1∑i=0

αiAiu.

Das Polynom ϕA,u(x) = xd −∑d−1

i=0 αixi, das die Gleichung ϕA,u(A)u = 0 erfüllt, ist somit

ein unitäres Annihilator-Polynom der Krylow-Folge und von minimalem Grad. Wir nennenes das Minimalpolynom des Vektors u (bezüglich der Matrix A). Die Menge der Annihilator-Polynome von u bildet ein von ϕA,u erzeugtes Ideal von K[X]

Das Minimalpolynom der Matrix A ist als unitäres Polynom ϕA(x) kleinsten Grades de-niert, das die Matrix A annulliert: ϕA(A) = 0. Wenn insbesondere ϕA(A) auf den Vektor uangewendet wird, stellen wir fest, dass ϕA ein Annihilator der Krylow-Folge ist. Es ist da-her notwendigerweise ein Vielfaches des Minimalpolynoms von u. Überdie können wir zeigen(siehe Übung 30), dass ein Vektor u existiert, sodass

ϕA,u = ϕA. (8.1)

Wird der Vektor u zufällig ausgewählt, ist die Wahrscheinlichkeit, dass er Gl. (8.1) genügt,umso gröÿer, je gröÿer der Körper ist (man kann zeigen, dass sie mindesten 1− n

|K| beträgt).

Übung 30. Wir möchten zeigen, dass immer ein Vektor u existiert, dessen Minimalpolynommit dem Minimalpolynom der Matrix zusammenfällt.

1. Sei (e1, . . . , en) eine Basis des Vektorraums. Zeigen Sie, dass ϕA mit dem kgV der ϕA,eizusammenfällt.

2. Zeigen Sie für den Fall, dass ϕA eine Potenz eines irreduziblen Polynoms ist, dass einIndex i0 existiert, sodass ϕA = ϕA,ei0 wird.

3. Zeigen Sie, dass wenn die Minimalpolynome ϕi = ϕA,ei und ϕA,ej teilerfremd sind, dannϕA,ei+ej = ϕiϕj gilt.

4. Zeigen Sie, dass wenn ϕA = P1P2 mit teilerfremden P1 und P2 gilt, dann Vektorenx1 6= 0 und x2 6= 0 existieren, sodass Pi das Minimalpolynom von xi ist.

5. Folgern Sie mit Faktorisierung in irreduzible Polynome, dass ϕA = ϕm11 · . . . · ϕmkk gilt.

6. Veranschaulichung: sei A =

0 0 3 0 01 0 6 0 00 1 5 0 00 0 0 0 50 0 0 1 5

eine Matrix aus GF(7). Berechnen Sie die

Grade der Minimalpolynome der Vektoren der kanonischen Basis u = e1 und v = e4

170

Page 187: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

sowie von u+v. Wir können uns der Funktion maxspin(u) bedienen, die bei Anwendungauf die Transponierte von A die maximale Folge der Iterierten von Krylow eines Vektorsu zurückgibt.

Sei P = xk +∑k−1

i=0 ein unitäres Polynom k-ten Grades. Die dem Polynom P zugeordneteBegleitmatrix ist die k × k-Matrix, die deniert ist durch

Cp =

0 −α0

1 −α1

. . ....

1 −αk−1

.Diese Matrix hat die Eigenschaft, P als minimales und charakteristisches Polynom zu haben.Sie spielt somit eine groÿe Rolle bei der Berechnung von minimalen und charakteristischenPolynomen.

Proposition. SeiKu die von den ersten d Krylow-Iterierten eines Vektors u gebildete Matrix.Dann gilt

AKu = KuCϕA,u

Wenn d = n ist, ist die Matrix Ku somit quadratisch der Ordnung n und invertierbar. Siedeniert eine Ähnlichkeitstransformation K−1

u AKu = KuCϕA,u , welche die Matrix A zu ei-ner Begleitmatrix reduziert. Nun bewahrt diese Transformation die Determinante und somitauch das charakteristische Polynom; wir können deshalb die Koezienten des minimalen undcharakteristischen Polynoms (die hier identisch sind) an der Begleitmatrix direkt ablesen.

sage: A = matrix(GF(97), 4, 4, [86,1,6,68,34,24,8,35,15,36,68,42,27,1,78,26])sage: e1 = identity_matrix(GF(97),4)[0]sage: U = matrix(A.transpose().maxspin(e1)).transpose()sage: F = U^-1*A*U; F

0 0 0 831 0 0 770 1 0 200 0 1 10

sage: K.<x> = GF(97)[]sage: P = x^4-sum(F[i,3]*x^i for i in range(4)); Px4 + 87x3 + 77x2 + 20x+ 14

sage: P == A.charpoly()True

Im allgemeinen Fall (d ≤ n) bilden die iterierten Vektoren u, . . . , Ad−1u eine Basis eines Un-tervektorraums I, der gegen Einwirkung der Matrix A invariant ist (d.h. AI ⊆ I). Da wirjeden dieser Vektoren zyklisch durch Anwendung der Matrix A auf den vorherigen Vektorerhalten, nennen wir ihn auch zyklischen Untervektorraum. Die maximale Dimension einessolchen Untervektorraums ist der Grad des Minimalpolynoms der Matrix. Es wird von denKrylow-Iterierten des in Übung 30 gebildeten Vektors erzeugt, den wir mit u∗1 bezeichnen.Wir nennen ihn den ersten invarianten Untervektorraum. Dieser erste Vektorraum lässt einenkomplementären Vektorraum V zu. Bei Berechnung modulo des ersten invarianten Vektor-raums, d.h. wenn zwei Vektoren als gleich gelten, wenn ihre Dierenz zum ersten invariantenUntervektorraum gehört, können wir zu den Vektoren in diesem komplementären Vektorraum

171

Page 188: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

einen zweiten invarianten Untervektorraum denieren wie auch ein Minimalpolynom, das diezweite Ähnlichkeitsinvariante genannt wird. Wir erhalten dann eine Beziehung der Form:

A[Ku∗1Ku∗2

] = [Ku∗1Ku∗2

]

[Cϕ1

Cϕ2

],

worin ϕ1, ϕ2 die beiden ersten Ähnlichkeitsinvarianten sind undKu∗1,Ku∗2

die Krylow-Matrizen,die den beiden von den Vektoren u∗1 und u∗2 aufgespannten zyklischen Vektorräumen entspre-chen.

Wir bilden iterativ eine quadratische, invertierbare Matrix K = [Ku∗1. . . Ku∗k

], so dass

K−1AK =

Cϕ1

. . .Cϕk

. (8.2)

Da jedes u∗i durch die ϕj mit j ≤ i annulliert wird, ersehen wir daraus, dass ϕi | ϕi−1 für alle2 ≤ i ≤ k, anders gesagt, die Folge der ϕi ist bezüglich der Division total geordnet. Wir könnenbeweisen, dass zu jeder Matrix eine eindeutige Folge von invarianten Polynomen ϕ1, . . . , ϕkexistiert. So ist die diagonale Blockmatrix Diag(Cϕ1 , . . . , Cϕk), zur Matrix A ähnlich, und diesePolynome zeigt eine Normalform, die rational kanonische Form genannt wird oder Frobenius-Normalform.

Satz (Frobenius-Normalform). Jede quadratische Matrix A auf einem Körper ist zu einer

eindeutigen Matrix F =

Cϕ1

. . .Cϕk

mit ϕi+1 | ϕi für jedes i < k ähnlich.

Gemäÿ Gl. (8.2) können wir anscheinend die Basen der invarianten Untervektorräume an derÜbergangsmatrix K ablesen.

Bemerkung. Der Satz von Caley-Hamilton besagt, dass das charakteristische Polynom seineMatrix annulliert: χA(A) = 0. Das zu beweisen ist nach Einführung der Frobenius-Normalformeinfach. Es gilt

χA(x) = det(xId−A) = det(K) det(xId− F ) det(K−1)

=k∏i=1

det(xId− Cϕi) =k∏i=1

ϕi(x).

Somit ist das Minimalpolynom ϕ1 ein Teiler des charakteristischen Polynoms, das deshalbAnnihilator der Matrix A ist.

In Sage können wir die Frobenius-Normalform in Q mit Koezienten aus Z mit der Methodefrobenius berechnen1:

sage: A = matrix(ZZ,8,[[6,0,-2,4,0,0,0,-2],[14,-1,0,6,0,-1,-1,1],\....: [2,2,0,1,0,0,1,0],[-12,0,5,-8,0,0,0,4],\....: [0,4,0,0,0,0,4,0],[0,0,0,0,1,0,0,0],\....: [-14,2,0,-6,0,2,2,-1],[-4,0,2,-4,0,0,0,4]])

1Das ist eine leichte Abweichung der aktuellen Schnittstelle des Programms: obwohl die Frobenius-Form fürjede Matrix auf einem Körper deniert ist, erlaubt Sage die Berechnung nur für Matrizen auf Z und bewirktimplizit die Einbettung in Q.

172

Page 189: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

sage: A.frobenius()

0 0 0 4 0 0 0 01 0 0 4 0 0 0 00 1 0 1 0 0 0 00 0 1 0 0 0 0 00 0 0 0 0 0 4 00 0 0 0 1 0 0 00 0 0 0 0 1 1 00 0 0 0 0 0 0 2

Auÿerdem können wir die Liste der invarianten Polynome erhalten, indem wir als Argument1 übergeben. Um Informationen zu den zugeordneten invarianten Vektorräumen zu erhalten,übergeben wir das Argument 2, was die Übergangsmatrix K erzeugt. Sie liefert eine Basisdes gesamten Vektorraums, der in die direkte Summe der invarianten Vektorräume zerlegtwird:

sage: A.frobenius(1)[x4 − x2 − 4x− 4, x3 − x2 − 4, x− 2

]sage: F,K = A.frobenius(2)sage: K

1 −1556

17224

1556 − 17

896 0 − 15112

1764

0 29224 − 13

224 − 23448 − 17

896 − 17896

29448

13128

0 − 75896

75896 − 47

896 0 − 17896 − 23

44811128

0 17896 − 29

89615896 0 0 0 0

0 0 0 0 1 0 0 00 0 0 0 0 1 0 00 1 0 0 0 0 1 00 − 4

21 − 421 −10

21 0 0 − 221 1

sage: K^-1*F*K == ATrue

Diese Resultate geben zu verstehen, dass die Matrix A mit Koezienten aus Z in den KörperQ eingebettet wurde. Um das Verhalten der Matrix A auf dem freien Modul Zn und die Zer-legung des Moduls, das sie erzeugt, zu studieren, benutzen wir die Funktion decomposition;allerdings sprengt deren Studium den Rahmen dieses Buches.

Invariante Faktoren und Ähnlichkeitsinvarianten. Eine wichtige Eigenschaft verbindet dieÄhnlichkeitsinvarianten mit den invarianten Faktoren, die wir in Unterabschnit 8.2.1 gesehenhaben.

Satz. Die Ähnlichkeitsinvarianten einer Matrix A mit Koezienten aus einem Körper ent-sprechen den invarianten Faktoren ihrer charakteristischen Matrix xId−A.

Der Beweis dieses Resultats sprengt den Rahmen dieses Buches, sodass wir uns mit der Ver-anschaulichung des vorigen Beispiels zufrieden geben.

sage: S.<x> = QQ[]sage: B = x*identity_matrix(8) - Asage: B.elementary_divisors()[1, 1, 1, 1, 1, x− 2, x3 − x2 − 4, x4 − x2 − 4x− 4

]

173

Page 190: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

sage: A.frobenius(1)[x4 − x2 − 4x− 4, x3 − x2 − 4, x− 2

]Eigenwerte, Eigenvektoren Wenn wir das Minimalpolynom in irreduzible Faktoren zerlegen,ϕ1 = ψm1

1 · . . . ·ψmss , dann werden alle invarianten Faktoren in der Form ϕi = ψmi,11 · . . . ·ψmi,ss

mit den Multiplizitäten mi,j ≤ mk geschrieben. Wir zeigen, dass dann eine Ähnlichkeitstrans-formation gefunden werden kann, die jeden Begleitblock Cϕ der Frobenius-Form in einenDiagonalblock Diag(C

ψmi,11 )

, . . . , Cψmi,ss )

) verwandelt. Diese Variante der Frobenius-Form, die

wir Zwischenform nennen, wird immer von Begleitblocks gebildet, doch diesmal entsprichtjeder einer Potenz eines irreduziblen Polynoms.

F =

Cψm1,11

. . .Cψm1,ss

Cψm2,11

. . .. . .

Cψmk,11

. . .

(8.3)

Sobald ein irreduzibler Faktor ψi den Grad 1 und die Multiplizität 1 hat, ist sein Begleit-block eine 1× 1-Matrix auf der Diagonalen und entspricht somit einem Eigenwert. Wenn dasMinimalpolynom reduzibel und quadratfrei ist, ist die Matrix deshalb diagonalisierbar.

Die Eigenwerte erhalten wir mit der Methode eigenvalues. Die ihrem Eigenwert und dessenVielfachheit zugeordnete Liste der Eigenvektoren von rechts (bzw. von links) wird durch dieMethode eigenvectors_right (bzw. eigenvectors_left) angegeben. Schlieÿlich werden dieEigenräume wie auch deren Basis von Eigenvektoren von den Methoden eigenspaces_rightund eigenspaces_left geliefert.

sage: A = matrix(GF(7),4,[5,5,4,3,0,3,3,4,0,1,5,4,6,0,6,3])sage: A.eigenvalues()[4, 1, 2, 2]sage: A.eigenvectors_right()[(4, [(1, 5, 5, 1)], 1), (1, [(0, 1, 1, 4)], 1), (2, [(1, 3, 0, 1),(0, 0, 1, 1)], 2)]

sage: A.eigenspaces_right()[(4, Vector space of degree 4 and dimension 1 over Finite Field of size 7User basis matrix:[1 5 5 1]),(1, Vector space of degree 4 and dimension 1 over Finite Field of size 7

174

Page 191: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

User basis matrix:[0 1 1 4]),(2, Vector space of degree 4 and dimension 2 over Finite Field of size 7User basis matrix:[1 3 0 1][0 0 1 1])]

Kürzer gibt die Methode eigenmatrix_right das aus der diagonalisierten Matrix und der Ma-trix ihrer Eigenvektoren von rechts gebildete Paar zurück. (Die Methode eigenmatrix_lefttut dasselbe mit den Eigenvektoren von links).

sage: A.eigenmatrix_right()

4 0 0 00 1 0 00 0 2 00 0 0 2

,

1 0 1 05 1 3 05 1 0 11 4 1 1

Jordanform. Wenn das Minimalpolynom reduzibel ist, aber Faktoren hat, deren Vielfachheitgröÿer ist als 1, ist die Zwischenform (8.3) nicht diagonal. Wir beweisen jetzt, dass es keineÄhnlichkeitstransformation gibt, die sie diagonal macht, die anfängliche Matrix ist also nichtdiagonalisierbar. Wir können sie jedoch trigonalisieren, d.h. sie zu einer oberen Dreiecksma-trix machen, sodass ihre Eigenwerte auf der Diagonalen erscheinen. Unter den verschiedenenmöglichen Dreiecksmatrizen ist die am weitesten vereinfachte die Jordan-Normalform.

Ein Jordanblock Jλ,k, der dem Eigenwert λ und der Ordnung k zugeordnet ist, ist die k × k-Matrix Jλ,k, die gegeben ist durch

Jλ,k =

λ 1

. . . . . .λ 1

λ

.Diese Matrix spielt eine ähnliche Rolle wie die Begleitblöcke, indem sie die Multiplizität einesEigenwertes genauer aufzeigt. Tatsächlich ist ihr charakteristisches Polynom χJλ,k = (X−λ)k.Des weiteren ist auch ihr Minimalpolynom ϕJλ,k = (X − λ)k und ist notwendigerweise einVielfaches von P = X − λ. Nun ist die Matrix

P (Jλ,k) =

0 1

. . . . . .0 1

0

nilpotent der Ordnung k, woraus ϕJλ,k = χJλ,k = (X − λ)k folgt. Die Jordan-Normalformentspricht der Zwischenform (8.3), wobei die Begleitblöcke ψ

mi,jj durch Jordanblöcke Jλj ,mi,j

ersetzt sind (wir erinnern uns, dass wenn das Minimalpolynom reduzibel ist, die ψj in derForm X − λj geschrieben werden).

175

Page 192: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8. Lineare Algebra

Bei reduziblem Minimalpolynom ist somit jede Matrix ähnlich einer Jordanmatrix der Form

J =

Jλ1,m1,1

. . .Jλs,m1,s

Jλ1,m2,1

. . .. . .

Jλ1,mk,1. . .

(8.4)

Insbesondere ist die Jordanform auf jedem algebraisch abgeschlossenen Körper wie C stetsdeniert.

In Sage produziert der Konstruktor jordan_block(a,k) den Jordanblock Ja,k. Die Jordan-Normalform erhalten wir mit jordan_form. Die Option transformation=True erlaubt, dieTransformationsmatrix U zu erhalten, sodass U−1AU in Jordanform ist.

sage: A = matrix(ZZ,4,[3,-1,0,-1,0,2,0,-1,1,-1,2,0,1,-1,-1,3])sage: A.jordan_form()

3 0 0 0

0 3 0 0

0 0 2 10 0 0 2

sage: J,U = A.jordan_form(transformation=True)sage: U^-1*A*U == JTrue

Die Jordanform ist bis auf eine Permutation der Jordanblöcke eindeutig. Gemäÿ der Lite-ratur kann man vorschreiben oder auch nicht, dass die Reihenfolge ihres Auftreten auf derDiagonalen wie in Gleichung (8.4) der Reihenfolge der invarianten Polynome entspricht. Wirbemerken in obigem Beispiel, dass Sage diese Ordnung nicht respektiert, weil das erste inva-riante Polynom (das Minimalpolynom) das Polynom (X − 3)(X − 2)2 ist.

Primäre Normalform. Der Vollständigkeit halber müssen wir eine letzte Normalform erwäh-nen, welche die Jordanform für den beliebigen Fall verallgemeinert, wo das Minimalpolynomnicht reduzibel ist. Für ein irreduzibles Polynom P k-ten Grades denieren wir den Jordan-block der Multiplizität m als die Matrix JP,m der Dimension km× km

JP,m =

CP B

. . . . . .CP N

CP

.wobei B die k × k-Matrix ist, deren einziger von null verschiedener Eintrag Bk,1 = 1 ist, undCP ist die dem Polynom P zugeordnete Begleitmatrix (Unterabschnitt 8.2.3). Wir sehen, wiewir für P = X−λ den dem Eigenwert λ zugeordneten Jordanblock wiedernden. Auf ähnliche

176

Page 193: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2. Rechnungen mit Matrizen

Weise zeigen wir, dass für die minimalen und die charakteristischen Polynome dieser Matrixgilt:

χJP,m = ϕJP,m = Pm.

Somit zeigen wir, dass eine Ähnlichkeitstransformation existiert, die jeden Begleitblock Cψjmi,j

der Zwischenform (8.3) durch einen Jordanblock Jψj,mi,j ersetzt. Die so gebildete Form wirdbeschränkte Form oder auch zweite Frobeniusform genannt. Es handelt sich hierbei wieder umeine Normalform, d.h. sie ist eindeutig bis auf eine Permutation der Blöcke auf der Diagonalen.Die Einzigartigkeit dieser Normalformen ermöglicht insbesondere zu testen, ob zwei Matrizenähnlich sind und bei dieser Gelegenheit eine Matrix für den Übergang der einen in die anderezu erzeugen.

Übung 31. Schreiben Sie ein Programm, das bestimmt, ob zwei Matrizen A und B ähnlichsind und das die Übergangsmatrix U zurückgibt, sodass A = U−1BU ist (es wird Nonezurückgegeben, wenn die Matrizen nicht ähnlich sind).

177

Page 194: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 195: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Dieses Kapitel führt die beiden vorigen weiter. Sein Gegenstand sind Gleichungssysteme mitmehreren Variablen wie in Kapitel 8. Diese Gleichungen sind nun Polynome wie in Kapitel 7.Im Vergleich zu Polynomen in einer einzigen Unbestimmten präsentieren diese in mehrerenUnbestimmten einen groÿen mathematischen Reichtum, aber auch neue Schwierigkeiten, diebesonders damit zusammenhängen, dass der Ring K[x1, . . . , xn] kein Hauptidealring ist. DieTheorie der Gröbnerbasen liefert Werkzeuge, diese Begrenzung zu umgehen. Im Endeekt ver-fügen wir über machtvolle Methoden zur Untersuchung polynomialer Systeme mit unzähligenAnwendungen auf den verschiedensten Gebieten.

Ein guter Teil des Kapitels setzt nur Grundkenntnisse über Polynome in mehreren Unbestimm-ten voraus. Manche Passagen sind jedoch auf dem Niveau einer Vorlesung über kommutativeAlgebra im fortgeschrittenen Bachelor- oder im Masterstudium. Sucht der Leser eine leich-ter zugängliche Einführung in die mathematische Theorie der polynomialen Systeme, kommt(in französischer Sprache) der Beitrag von Faugère und Safey El Din in [FSE09] in Frage.Eine eher fortgeschrittene Behandlung ndet man in dem Buch von Elkadi und Mourrain[EM07]. Schlieÿlich, und diesmal in englischer Sprache, ist das Buch von Cox, Little undO'Shea [CLO07] sowohl leicht zugänglich als auch umfassend.

9.1. Polynome in mehreren Unbestimmten

9.1.1. Die Ringe A[x1, . . . , , xn]

Wir interessieren uns hier für Polynome in mehreren Unbestimmten, die auch - mit dem inder symbolischen Mathematik verbreiteten Anglizismus - multivariat genannt werden.

Wie bei anderen algebraischen Strukturen, die es in Sage gibt, müssen wir vor der Bildungvon Polynomen eine Familie von Unbestimmten denieren, die alle zum selben Ring gehören.Die Synntax ist praktisch die gleiche wir für eine Variable (siehe Unterabschnitt 7.1.1):

sage: R = PolynomialRing(QQ, 'x,y,z')sage: x,y,z = R.gens() # ergibt das n-Tupel der Unbestimmten

oder kürzer:

sage: R.<x,y,z> = QQ[]

(oder auch R = QQ['x,y,z']). Der Konstruktor PolynomialRing erlaubt auch die Erzeugungeiner Familie von Unbestimmten gleichen Namens mit ganzzahligen Indizes:

sage: R = PolynomialRing(QQ, 'x', 10)

Die Unterbringung des n-Tupels, das von gens zurückgegeben wird, in der Variablen x erlaubtnun natürlich mit x[i] den Zugri auf die Unbestimmte xi:

179

Page 196: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

sage: x = R.gens()sage: sum(x[i] for i in xrange(5))x0 + x1 + x2 + x3 + x4

Die Reihenfolge der Variablen ist wichtig. Der Vergleich von QQ['x,y'] und QQ['y,x'] mit== gibt falsch zurück und dasselbe Polynom, das als Element des einen oder des anderengesehen wird, wird unterschiedlich ausgegeben:

sage: def test_poly(ring, deg=3):....: monomials = Subsets(....: flatten([(x,)*deg for x in (1,) + ring.gens()]),....: deg, submultiset=True)....: return add(mul(m) for m in monomials)

sage: test_poly(QQ['x,y'])x^3 + x^2*y + x*y^2 + y^3 + x^2 + x*y + y^2 + x + y + 1sage: test_poly(QQ['y,x'])y^3 + y^2*x + y*x^2 + x^3 + y^2 + y*x + x^2 + y + x + 1sage: test_poly(QQ['x,y']) == test_poly(QQ['y,x'])True

Übung 32. Erläutern Sie die Arbeitsweise der soeben denierten Funktion test_poly.

Des weiteren erfordert das Schreiben des Polynoms in kanonischer Form die Festlegung ei-ner Reihenfolge der Summanden. Das Ordnen nach der Gröÿe der Exponenten drängt sichauf, wenn es nur eine Unbestimmte gibt, doch bei multivariaten Polynomen erfüllt keineReihenfolge der Monome alle Wünsche. Sage ermöglicht deshalb mit der Option order vonPolynomialRing die Wahl zwischen verschiedenen Möglichkeiten. Die Reihenfolge deglexzum Beispiel ordnet die Monome nach dem Totalgrad, der Summe der Exponenten und beiGleichheit dann nach der lexikographischen Reihenfolge der Unbestimmten:

sage: test_poly(PolynomialRing(QQ, 'x,y', order='deglex'))x^3 + x^2*y + x*y^2 + y^3 + x^2 + x*y + y^2 + x + y + 1

Konstruktion von PolynomringenRing A[x, y] PolynomialRing(A, 'x,y') oder A['x,y']

Ring A[x0, . . . , xn−1] PolynomialRing(A, 'x', n)

Ring A[x0, x1, . . . , y0, y1, . . .] InfinitePolynomialRing(A, ['x','y'])

n-Tupel von Generatoren R.gens()

1., 2.,. . . Generator R.0, R.1,. . .Unbestimmte von R = A[x, y][z] . . . R.variable_names_recursive()

Umwandlung A[x1, x2, y]→ A[x1, x2][y] p.polynomial(y)

Zugri auf KoezientenExponenten, Koezienten p.exponents(), p.coefficients()

Koezient eines Monoms p[x^2*y] oder p[2,1]Grad(e) gesamt, in x, partiell p.degree(), p.degree(x), p.degrees()

Leitmonom/Leitkoezient/Leitterm p.lm(), p.lc(), p.lt()

Grundlegende OperationenTransformation der Koezienten p.map_coefficients(f)

partielle Ableitung ∂/∂x p.dervative(x)

Auswertung p(x, y)x=a,y=b p.subs(x=a, y=b) oder p(x=a, y=b)

Homogenisierung p.homogenize()

Hauptnenner (p ∈ Q[x, y, . . .]) p.denominator

Tab. 9.1 - Polynome in mehreren Unbestimmten

180

Page 197: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.1. Polynome in mehreren Unbestimmten

Die wichtigsten verfügbaren Ordnungen werden in Unterabschnitt 9.3.1 genau beschrieben.Wir werden sehen, dass die Wahl der Ordnung nicht nur eine Frage der Ausgabe ist, sondernauch bestimmte Rechnungen beeinusst.

Übung 33. Denieren Sie den Ring Q[x2, x3, . . . , x37], dessen Unbestimmte durch die Prim-zahlen unterhalb 40 indiziert sind und mit x2, x3,...,x37 auf die Unbestimmten zugegrienwerden kann.

Es kann sich in einigen Fällen als nützlich erweisen, Polynome in mehreren Unbestimmten inrekursiver Darstellung zu bearbeiten, d.h. als Elemente eines Polynomrings mit Koezienten,die selber Polynome sind (siehe den Rahmen auf Seite 129)

9.1.2. Polynome

Genau wie Polynome in einer Variablen Instanzen der Klasse Polynomial sind, sind Polynomein mehreren Variablen (in Ringen mit einer endlichen Anzahl von Unbestimmten) Instanzender Klasse MPolynomial1. Bei normalen Basisringen (wie Z, Q oder Fq) stützen sie sich aufdas Programm Singular, ein CAS, das auf schnelle Rechnungen mit Polynomen spezialisiertist. In den übrigen Fällen weicht Sage auf eine viel langsamere generische Implementierungaus.

1Anders als Polynomial ist diese Klasse nicht direkt nach der Kommandozeile zugänglich:man muss den vollständigen Namen verwenden. Wir können beispielsweise mit isinstance(p,

sage.rings.polynomial.multi_polynomial.MPolynomial) testen, ob ein Objekt ein multivariates Po-lynom ist

181

Page 198: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Die Ringe A[(xn, yn. . . .)n∈N]

Es kommt vor, dass man bei Beginn einer Rechnung nicht weiÿ, wieviele Variablengebraucht werden. Das nimmt PolynomialRing jedoch ziemlich genau: man muss miteiner ersten Denitionsmenge beginnen und dann jedesmal, wenn eine neue Variablehinzukommen soll, erweitern und alle Elemente konvertieren.Polynomringe in unendlich vielen Unbestimmten bieten eine viel exiblere Daten-struktur. Ihre Elemente können Variable enthalten, die aus einer oder mehreren unen-lichen Familien von Unbestimmten genommen werden. Jeder Generator des Ringesentpricht nicht einer einzigen Variablen, sondern einer Familie von Variablen, diedurch natürliche Zahlen indiziert werden:sage: R.<x,y> = InfinitePolynomialRing(ZZ, order='lex')sage: p = mul(x[k] - y[k] for k in range(2)); px_1*x_0 - x_1*y_0 - x_0*y_1 + y_1*y_0sage: p + x[100]x_100 + x_1*x_0 - x_1*y_0 - x_0*y_1 + y_1*y_0Wir gelangen mit der Methode polynomial zu einem normalen Poly-nomring PolynomialRing zurück, der das Bild eines Elementes einesInfinitePolynomialRing aus einem Ring zurückgibt, der groÿ genug ist, umalle Elemente des Ringes in unendlich vielen Variablen zu enthalten, die bis dahinbearbeitet sind. Der erhaltene Ring ist im allgemeinen nicht der kleinste mit dieserEigenschaft.Im Gegensatz zu dieser Flexibilität sind diese Ringe weniger ezient als Ringe ausPolynomialRing. Auÿerdem werden ihre Haupideale bei Rechnungen mit polyno-mialen Systemen, dem zentralen Gegenstand dieses Kapitels, nicht durch solche dernormalen Polynomringe ersetzt

Polynome in mehreren Unbestimmten werden immer in dünn besetzter Darstellung kodiert2.Wozu die Festlegung? Ein voll besetztes Polynom in n Variablen des gesamten Grades dzählt

(n+dn

)Monome: für n = d = 10 macht das 184756 zu speichernde Koezienten! Es

ist deshalb sehr schwierig, grosse voll besetzte Polynome so zu behandeln, wie man das beieiner Variablen tut. Auÿerdem haben die Stützstellen (die Positionen der von 0 verschiedenenMonome), denen man in der Praxis begegnet, verschiedene Formen. Wenn nun beispielsweiseein bis zum gesamten Grad d− 1 voll besetztes Polynom in n Variablen mit groÿem d durchein rechteckiges Schema d × . . . × d dargestellt wird, ist nur etwa ein Koezient von n! vonnull verschieden. Umgekehrt wird die dünn besetzte Darstellung durch ein Diktionär an dieForm der Stützstellen sowie an die auf den Monomen geltende Ordnung angepasst.

9.1.3. Grundlegende Operationen

Legen wir etwas Terminologie fest. Sei R = A[x1, . . . , xn] ein Polynomring. Wir nennen Mo-

nom einen Ausdruck der Form xα11 xα2

2 . . . xαnn , d.h. ein Produkt von Unbestimmten, das wirabkürzend xα nennen. Das n-Tupel ganzer Zahlen α = (α1, α2, . . . , αn) ist der Exponent

des Monoms xα. Ein Term ist ein Monom multipliziert mit einem Element aus A, seinemKoezienten.

2Die rekursive Darstellung (siehe Kasten Seite 129) liefert indessen eine teilweise voll besetzte Form multiva-riater Polynome. Bei der Darstellung eines Polynoms aus A[x][y] im Speicher belegt jeder Koezient vonyk (im allgemeinen) Platz, der zu seinem Grad in x proportional ist und dem Platz proportional zum Gradvon y für das Polynom selbst hinzugefügt werden muss.

182

Page 199: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.1. Polynome in mehreren Unbestimmten

Da die Anordnung der Terme nicht eindeutig ist, haben die Elemente von R als mathemati-sche Objekte keinen Leitkoezienten. Ist bei der Erzeugung des Ringes aber eine Ordnungfestgelegt worden, ist es möglich und nützlich, das in der Ausgabe am weitesten links stehendeMonom als Leitmonom festzulegen. Die Methoden lm (für leading monomial), lc (leading co-ecient) und lt (leading term) eines Polynoms in mehreren Varianten geben das Leitmonom,dessen Koezienten bzw. den Term, den sie zusammen bilden, zurück:

sage: R.<x,y,z> = QQ[]sage: p = 7*y^2*x^2 + 3*y*x^2 + 2*y*z + x^3 + 6sage: p.lt()7*x^2*y^2

Die arithmetischen Operationen +, - und * ebenso wir die Methoden dict, coefficientsund viele andere werden wie ihre Analoga in nur einer Variablen verwendet. Zu den kleinenUnterschieden gehört, dass der Operator [] für die Extraktion eines Koezienten als Parametersowohl dessen Monom als auch dessen Exponenten akzeptiert:

sage: p[x^2*y] == p[(2,1,0)] == p[2,1,0] == 3True

Ebenso müssen bei der Auswertung Daten für alle Variablen eingegeben oder die zu substi-tuierenden präzisiert werden:

sage: p(0, 3, -1)0sage: p.subs(x = 1, z = x^2+1)2*x^2*y + 7*y^2 + 5*y + 7

Die Methode subs kann auch gleichzeitig eine beliebige Anzahl von Variablen ersetzen, sie-he die Dokumentation hinsichtlich anspruchsvollerer Beispiele. Der Grad kann als gesamteSumme der Exponenten (total) und für einzelne Variablen (partiell) ausgegeben werden:

sage: print "total=d (nur x)=dx partiell=ds"\....: .format(d=p.degree(), dx=p.degree(x), ds=p.degrees())total=4 (nur x)=3 partiell=(3, 2, 1)

Andere Konstruktionen erfahren evidente Anpassungen, beispielsweise erhält die Methodederivative diejenige Variable als Parameter, nach der abgeleitet werden soll.

9.1.4. Arithmetik

Auÿer den elementaren syntaktischen und arithmetischen Operationen sind die in Sage ver-fügbaren Funktionen generell auf Polynome auf einem Körper und zuweilen auf Z oder Z/nZbeschränkt. In diesem Kapitel bewegen wir uns auf einem Körper, wenn anders nicht expliziterwähnt.

Die euklidsche Polynomdivision hat nur in einer Variablen Sinn. In Sage bleiben die Metho-de quo_rem und die zugehörigen Operatoren // und % für multivariate Polynome dennochdeniert. Die Division mit Rest, die damit berechnet wird, genügt der Beziehung

(p//q)*q + (p%q) == p

183

Page 200: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

und stimmt mit der euklidschen Division überein, wenn p und q nur von einer Variablenabhängen. Das ist dann aber selbst keine euklidsche Division und sie ist nicht kanonisch. Sieerweist sich dennoch als nützlich, wenn die Division exakt ist oder wenn der Divisor ein Monomist. In den übrigen Fällen ziehen wir die in Unterabschnitt 9.2.3 beschriebene Funktion modder Funktion quo_rem und ihren Varianten vor, weil sie ein Polynom modulo eines Haupidealsreduziert und die Festlegung der Ordnung der Monome berücksichtigt:

sage: R.<x,y> = QQ[]; p = x^2 + y^2; q = x + ysage: print("(quo)*(q) + (rem) == p".format( \....: quo=p//q, q=q, rem=p%q, p=p//q*q+p%q))(-x + y)*(x + y) + (2*x^2) == x^2 + y^2sage: p.mod(q) # ist NICHT äquivalent zu p%q

Die Methoden divides, gcd, lcm oder auch factor haben die gleiche Bedeutung wie beinur einer Variablen. Wegen fehlerhafter euklidscher Division sind die ersteren bei Koezi-enten beliebigen Typs nicht einsetzbar, sie funktionieren jedoch auf diversen gebräuchlichenKörpern, beispielsweise dem Körper der Zahlen:

sage: R.<x,y> = QQ[exp(2*I*pi/5)][]sage: (x^10 + y^5).gcd(x^4 - y^2)x^2 + ysage: (x^10 + y^5).factor()(x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + (a)*y) * (x^2 +(-a^3 - a^2 - a - 1)*y)

9.2. Polynomiale und ideale Systeme

Nun wenden wir uns dem zentralen Gegenstand dieses Kapitels zu. Die Unterabschnitte 9.2.1und 9.2.2 bieten ein Panorama der verschiedenen Möglichkeiten, mit Hilfe von Sage Lösungeneines Systems von polynomialen Gleichungen zu nden und zu verstehen. Der Unterabschnitt9.2.3 ist den diesen Systemen zugeordneten Haupidealen gewidmet. Die danach folgendenAbschnitte kommen auf die Werkzeuge zur algebraischen Elimination und zur Lösung dieserSysteme vertiefend zurück.

9.2.1. Ein erstes Beispiel

Wir betrachten eine Variante des polynomialen Systems aus Abschnitt 2.2:x2yz = 18

xy3z = 24

xyz4 = 6.

(9.1)

Operationen auf Polynomen mit mehreren UnbestimmtenTeilbarkeit p | q p.divides(q)

Faktorisierung p.factor()

ggT, kgV p.gcd(q), p.lcm(q)

Test ob quadratfrei p.is_squarefree

Resultante Resx(p, q) p.resultant(q, x)

Tab. 9.2 - Arithmetik

184

Page 201: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

Sages Funktion solve hatte uns nur erlaubt, eine numerische Lösung zu nden. Wir sehenjetzt, wie es Sage gelingt, das System exakt zu lösen, und mit etwas Unterstützung durch denAnwender einfache geschlossene Formen für alle Lösungen zu nden3.

Auisten der Lösungen Wir beginnen damit, das Problem in mehr algebraische Form zubringen, indem wir das Ideal von Q[x, y, z] mit diesen Gleichungen bilden:

sage: R.<x,y,z> = QQ[]sage: J = R.ideal(x^2 * y * z - 18,....: x * y^3 * z - 24,....: x * y * z^4 - 6)

Wie wir in Unterabschnitt 9.2.3 sehen werden, erlaubt uns der folgende Befehl zu verizieren,dass das Ideal J die Dimension null hat, d.h. dass das System (9.1) auf C3 eine endliche Zahlvon Lösungen besitzt.

sage: J.dimension()0

Der erste Reex ist nun, mit der Methode variety alle Lösungen des System zu berechnen.Ohne Parameter liefert sie alle Lösungen auf dem Basiskörper des Polynomrings:

sage: J.variety()[y: 2, z: 1, x: 3]

Die bereits gefundene Lösung (3, 2, 1) ist demnach die einzige Lösung des Systems.

Der folgende Schritt besteht in der Auistung der komplexen Lösungen. Um das exakt zu tun,arbeiten wir auf dem Körper der algebraischen Zahlen. Wir bekommen 17 Lösungen:

sage: V = J.variety(QQbar)sage: len(V)17

Die letzten drei Lösungen haben folgendes Aussehen:

sage: V[-3:][z: 0.9324722294043558? - 0.3612416661871530?*I, y: -1.700434271459229?+ 1.052864325754712?*I, x: 1.337215067329615? - 2.685489874065187?*I,z: 0.9324722294043558? + 0.3612416661871530?*I, y: -1.700434271459229?- 1.052864325754712?*I, x: 1.337215067329615? + 2.685489874065187?*I,z: 1, y: 2, x: 3]

Die Lösungspunkte werden als Diktionär ausgegeben, dessen Schlüssel die Generatoren vonQQbar['x,y,z'] sind (und nicht von QQ['x,y,z'], von wo mit einem kleinen Umweg daraufzugegrien werden kann), und die Koordinaten des Punktes die zugehörigen Werte. Auÿerdem vorhin identizierten Wert der rationalen Lösung sind die ersten Koordinaten sämtlichalgebraische Zahlem 16. Grades:

3Weil der Zweck der Übung ist, die Werkzeuge zur Lösung von polynomialen Systemen zu erläutern, lassenwir die Möglichkeit auÿer acht, (9.1) durch Logarithmieren in lineare Gleichungen zu überführen!

185

Page 202: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

sage: (xx, yy, zz) = QQbar['x,y,z'].gens()sage: [ pt[xx].degree() for pt in V ][16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1]

Rechnen mit den Lösungen und Ermitteln ihrer Struktur. Wir haben eine exakte Darstel-lung der komplexen Lösungen des Systems (9.1) bekommen, doch ist diese Darstellung nichtoen explizit. Das ist nicht schlimm: mit den Koordinaten als Elementen von QQbar könnenhier die exakten Rechnungen ausgeführt weren.

Beispielsweise ist es nicht schwierig zu sehen, dass wenn (x, y, z) eine Lösung des Systems(9.1) ist, dann auch (|x|, |y|, |z|). Konstruieren wir die Menge der (|x|, |y|, |z|) für die Lösung(x, y, z):

sage: Set(tuple(abs(pt[i]) for i in (xx,yy,zz)) for pt in V)(3, 2, 1)

Alle Werte von x (bzw. von y) sind daher vom selben Modul. Besser noch, wir können veri-zieren, dass die Substitution

(x, y, z) 7→ (ωx, ω9y, ω6z) mit ω = e2πi/17 (9.2)

dass System unverändert lässt. Insbesondere sind die letzten Koordinaten der Lösungen genaudie 17. Einheitswurzeln, was uns deshalb dank der Möglichkeit, auf den algebraischen Zahlengenau zu rechnen, sicher sein lässt:

sage: w = QQbar.zeta(17); w # Primitivwurzel von 10.9324722294043558? + 0.3612416661871530?*Isage: Set(pt[zz] for pt in V) == Set(w^i for i in range(17))True

Lösungen des Systems sind daher die Tripel (3ω, 2ω9, ω6) für ω17 = 1. Und das sagt dochalles.

Übung 34. Zu suchen sind die reellen Lösungen (nicht bloÿ die rationalen), um unmittelbarzu verizieren, dass es nur (3, 2, 1) gibt. Finden Sie durch Berechnung mit Sage auch dieSubstitution (9.2), darin auch den Wert 17 für die Ordnung von ω als Wurzel der Einheit.

Zum gleichen Ergebnis hätten wir auch durch einen Blick auf die Minimalpolynome der Ko-ordinaten der Punkte in V kommen können. Wir erkennen, dass die gleiche Koordinate füralle anderen Lösungspunkte als (3, 2, 1) dasselbe Minimalpolynom hat. Das gemeinsame Mi-nimalpolynom ihrer dritten Koordinate ist nichts anderes als das zyklotome Polynom Φ17.

sage: set(pt[zz].minpoly() for pt in V[:-1])x^16 + x^15 + x^14 + x^13 + x^12 + x^11 + x^10 + x^9 +x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1

Die gemeinsamen Minimalpolynome der ersten und der zweiten Koordinate sind 316 ·Φ17(x/3)bzw. 216 · Φ17(x/2).

186

Page 203: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

Geschlossene Formeln. Ein expliziter Ausdruck für die Lösungen ist deshalb durch Rückgriauf die Exponentialschreibweise der komplexen Zahlen möglich:

sage: def polar_form(z):....: rho = z.abs(); rho.simplify()....: theta = 2 * pi * z.rational_argument()....: return (SR(rho) * exp(I*theta))sage: [tuple(polar_form(pt[i]) for i in [xx,yy,zz]) for pt in V[-3:]][(3*e^(-6/17*I*pi), 2*e^(14/17*I*pi), e^(-2/17*I*pi)),(3*e^(6/17*I*pi), 2*e^(-14/17*I*pi), e^(2/17*I*pi)), (3, 2, 1)]

Wären wir nicht auf die Idee gekommen, die Elemente von V als Potenzen zu schreiben, hättedas am Ende genügt.

Vereinfachung des Systems. Es ist auch ein anderer Ansatz möglich. Statt nach Lösungenzu suchen, versuchen wir, eine einfachere Form des Systems zu berechnen. Die grundlegendenWerkzeuge, die Sage dafür anbietet, sind die Dreieckszerlegung und die Gröbnerbasen. Wirwerden im weiteren sehen, was sie exakt berechnen; versuchen wir schon einmal, sie mit diesemBeispiel zu verwenden:

sage: J.triangular_decomposition()[Ideal (z^17 - 1, y - 2*z^10, x - 3*z^3) of MultivariatePolynomial Ring in x, y, z over Rational Field]sage: J.transformed_basis()[z^17 - 1, -2*z^10 + y, -3/4*y^2 + x]

Auf die eine Weise wie auf die andere erhalten wir das äquivalente System

z17 = 1 y = 2z10 x = 3z3,

dasselbe wie V =

(3ω3, 2ω10, ω) | ω17 = 1. Das ist wieder eine unmittelbare Parameterdar-

stellung der kompakten Schreibweise der oben bereits von Hand gefundenen Lösungen.

9.2.2. Was heiÿt Lösen?

Ein polynomiales System, das Löungen besitzt, hat davon oft unendlich viele. Die sehr einfacheGleichung x2−y = 0 lässt auf Q2 unendlich viele Lösungen zu, ganz zu schweigen von R2 oderC2. Es ist dann nicht möglich sie aufzulisten. Das beste, was man tun kann, ist die Menge derLösungen so explizit wie möglich zu beschreiben, d.h. eine Darstellung zu berechnen, aus derdie interessierenden Informationen leicht extrahiert werden können. Die Situation ist ähnlichwie bei linearen Systemen, für die (im homogenen Fall) eine Basis des Kerns des Systems einegute Beschreibung des Lösungsraumes ist.

In dem Spezialfall, wo die Anzahl der Lösungen endlich ist, wird es möglich, sie zu berech-nen. Doch versucht man auch in diesem Fall, die Lösungen in Q oder einem endlichen KörperFq aufzulisten? Um numerische Näherungen der reellen oder komplexen Lösungen zu nden?Oder auch, wie im Beispiel aus dem vorigen Abschnitt, die letzteren mit Hilfe algebraischerZahlen darzustellen, d.h. beispielsweise die Minimalpolynome ihrer Koordinaten zu berech-nen?

187

Page 204: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Dasselbe Beispiel illustriert, dass andere Darstellungen der Lösungsmenge als eine einfacheListe vor allem dann aussagekräftiger sein könnenn, wenn die Lösungen zahlreich sind. Somitist eine Aufzählung nicht zwangsläug die beste Art des Vorgehens, selbst wenn das möglichist. Kurzum, wir versuchen nicht so sehr, Lösungen zu nden, sondern mit ihnen zu rechnen,um daraus dann gemäÿ der Aufgabenstellung die Informationen zu gewinnen, für die wir unseigentlich interessieren. Dieses Kapitel erkundet verschiedene Werkzeuge, dies zu erreichen.

9.2.3. Ideale und Systeme

Wenn s Polynome p1, . . . , ps ∈ K[x] in einem Punkt x mit Koordinaten aus K oder einerErweiterung von K null werden, dann verschwindet auch jedes Element des Ideals, das sieerzeugen, im Punkt x. Es ist deshalb nur natürlich, dem polynomialen System

p1(x) = p2(x) = . . . = ps(x) = 0

das Ideal J = 〈p1, . . . , pa〉 ⊂ K[x] zuzuordnen. Zwei polynomiale Systeme, die dasselbe Idealerzeugen, sind in dem Sinne äquivalent, dass sie die gleichen Lösungen haben. Ist L ein Kenthaltender Körper, dann nennen wir die Menge

VL(J) = x ∈ Ln | ∀p ∈ J, p(x) = 0 = x ∈ Ln | p1(x) = . . . = ps(x) = 0

der Lösungen des Systems mit Koordinaten aus L eine algebraische Subvarietät . VerschiedeneIdeale können dieselbe Varietät zugeordnet haben. Beispielsweise haben die Gleichungen x = 0und x2 = 0 in C dieselbe eindeutige Lösung, obwohl wir 〈x2〉 ( 〈x〉 haben. Was ein voneinem polynomialen System erzeugtes Ideal vor allem bringt, ist die intuitive Schreibweise derLösung mit Multiplizitäten.

So drücken die beiden folgenden Systeme jedes den Schnitt des Einheitskreises mit dem Gra-phen der Gleichung αx2y2 = 1 aus, wobei jeweils zwei gleichseitige Hyperbeln auftreten (sieheAbb. 9.1):

(S1)

x2 + y2 = 1

16x2y2 = 1(S2)

x2 + y2 = 1

4x2y2 = 1(9.3)

Das System (S1) besitzt auf C acht Lösungen, alle mit reellen Koordinaten. Verzerrt man(S2) durch Veränderung des Parameters α, haben sich die beiden Lösungen auf jedem Ast derHyperbel soweit angenähert, dass sie verschmelzen. Das System S2 hat nur vier Lösungen,jede in gewissem Sinne zweifach. Würde α noch weiter verringert, gäbe es keine reelle Lösungmehr, dafür aber acht komplexe.

188

Page 205: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

(a) (S1) (b) (S2)

sage: R.<x,y> = QQ[]sage: J = R.ideal(x^2 + y^2 - 1, 16*x^2*y^2 - 1)sage: opts = 'axes':True, 'gridlines':True, 'frame':False,....: 'aspect_ratio':1, 'axes_pad':0, 'fontsize':12,....: 'xmin':-1.3, 'xmax':1.3, 'ymin':-1.3, 'ymax':1.3sage: (ideal(J.0).plot() + ideal(J.1).plot()).show(**opts)4

Abb. 9.1 - Schnitt zweier ebener Kurven, siehe die Systeme (9.3)

Rechnung modulo eines Ideals. Wie im Fall der Polynome mit nur einer Unbestimmtenerlaubt Sage die Denition von Idealen5 J ⊂ K[x], von Quotientenringen K[x]/J und natürlichdas Rechnen mit den Elementen dieser Quotientenringe. Das (S1) zugeordnete Ideal J1 wirdgebildet mit

sage: R.<x,y> = QQ[]sage: J = R.ideal(x^2 + y^2 - 1, 16*x^2*y^2 - 1)

Dann können wir den Quotienten von K[x] durch J1 ausführen, dabei Polynome auswerfen,mit Äquivalenzklassen modulo J1 rechnen und sie als Repräsentanten aueben lassen:

sage: ybar2 = R.quo(J)(y^2)sage: [ybar2^i for i in range(3)][1, ybar^2, ybar^2 - 1/16]sage: ((ybar2 + 1)^2).lift()3*y^2 + 15/16

Hier gibt es eine theoretische Schwierigkeit. Die Elemente von K[x]/J werden in Normal-form dargestellt, was erforderlich ist, um zwei Elemente auf Gleichheit testen zu können. Nunist diese Normalform aus dem in Unterabschnitt 9.1.4 schön erwähnten Grund nicht eindeu-tig zu denieren: die Division des Repräsentanten einer Äquivalenzklasse p + J durch einenHauptgenerator von J , die zum Rechnen auf K[x]/J gebraucht wird, hat bei mehreren Va-riablen keine Entsprechung. Begnügen wir uns für den Moment damit, dass nichtsdestotrotzeine Normalform existiert, die von der bei der Erzeugung des Ringes festgelegten Ordnungauf den Elementen abhängt und die auf einem besonderen System von Erzeugenden beruht,die Gröbnerbasen heiÿen. Der Abschnitt 9.3 am Ende dieses Kapitels ist der Denition derGröbnerbasen gewidmet und soll zeigen, wie wir sie bei den Rechnungen verwenden können.Sobald erforderlich, berechnet Sage Gröbnerbasen automatisch; diese Rechnungen sind gele-gentlich jedoch sehr aufwendig, besonders wenn die Anzahl der Variablen sehr groÿ ist, sodassdie Rechnung auf einem Quotientenring schwierig sein kann.

Kehren wir zu Sage zurück. Wenn p ∈ J ist, schreibt der Befehl p.lift(J) p als lineareKombination mit Polynomen des Generators von J als Koezienten:

sage: u = (16*y^4 - 16*y^2 + 1).lift(J); u[16*y^2, -1]

4Dieser Code erzeugt nur Teil (a); um Teil (b) zu erhaltem muss die Denition von J geändert werden.5Vorsicht: die Objekte InfinitePolynomialRing haben ebenfalls eine Methode ideal, die aber nicht dasselbeVerhalten zeigt wie bei den normalen Polynomringen. (Ein beliebiges Ideal von k[(xn)n∈N] hat keinenGrund, endlich erzeugt zu sein!) Diese Objekte werden im weiteren Verlauf des Kapitels nicht verwendet.

189

Page 206: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

sage: u[0]*J.0 + u[1]*J.116*y^4 - 16*y^2 + 1

Zu einem beliebigen Polynom ergibt der Ausdruck p.mod(J) die Normalform von p moduloJ , die als Element von K[x] gesehen wird:

sage: (y^4).mod(J)y^2 - 1/16

Achtung: wenn J.reduce(p) auch zu p.mod(J) äquivalent ist, so gibt andererseits die Variantep.reduce([p1, p2, ...]) einen Repräsentanten von p + J zurück, der nicht unbedingt inNormalform ist (siehe Unterabschnitt 9.3.2).

sage: (y^4).reduce([x^2 + y^2 - 1, 16*x^2*y^2 - 1])y^4

Durch Kombination von p.mod(J) und p.lift(J) können wir ein Polynom p in eine Linear-kombination mit polynomialen Koezienten des Generators von J plus einem Rest zerlegen,der genau dann verschwindet, wenn p ∈ J ist.

Radikal eines Ideals und Lösungen. Der wesentliche Punkt bei der Entsprechung von Idea-len und Varietäten ist der Hilbertsche Nullstellensatz . Sei K ein algebraischer Abschluss vonK.

Satz (Nullstellensatz). Seien p1, . . . , ps ∈ K[x] und Z ⊂ Kn die Menge der gemeinsamenNullstellen von pi. Ein Polynom p ∈ K[x] verschwindet auf Z identisch, genau dann, wenneine ganze Zahl k existiert, sodass pk ∈ 〈p1, . . . , p2〉 ist.

IdealeIdeal 〈p1, p2〉 ⊂ R R.ideal(p1, p2) oder (p1, p2)*R

Summe, Produkt, Potenz I + J, I*J, I^k

Schnittmenge I ∩ J I.intersection(J)

Quotient I : J = p | pJ ∈ I I.quotient(J)

Radikal√J J.radical()

Reduktion modulo J J.reduce(p) oder p.mod(J)Sektion von R R/J p.lift(J)

Quotientenring R/J R.quo(J)

homogenisiertes Ideal J.homogenize()

Einige vordenierte Idealeirrelevantes Ideal 〈x1, . . . , xn〉 R.irrelevant_ideal()

Jacobi-Ideal 〈∂p/∂xi〉i p.jacobian_ideal()

zyklische Wurzeln (9.11) sage.rings.ideal.Cyclic(R)

Körpergleichungen xqi = xi sage.rings.ideal.FieldIdeal(GF(q)['x1,x2'])

Tab. 9.3 - Ideale

Dieses Result liefert ein algebraisches Kriterium für den Test, ob ein polynomiales SystemLösungen besitzt. Das konstante Polynom 1 wird auf Z genau dann identisch 0, wenn Z leerist. Deshalb hat das System p1(x) = . . . = ps(x) genau dann Lösungen in K, wenn 1 im Ideal〈p1, . . . , ps〉 nicht enthalten ist. Beispielsweise schneiden sich die Kreise mit dem Radius 1 undden Zentren in (0, 0) und 4, 0 im Komplexen:

sage: 1 in ideal(x^2+y^2-1, (x-4)^2+y^2-1)False

190

Page 207: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

Andererseits hat das System keine Lösung mehr, wenn x = y hinzugefügt wird. Wir könneneinen trivialen Beweis angeben, um zu verizieren, dass es schon ein Widerspruch ist, wennwir eine Kombination von untereinander widerspruchsfreien Gleichungen zeigen, die sich auf1 = 0 reduzieren lässt. Die Rechnung

sage: R(1).lift(ideal(x^2+y^2-1, (x-4)^2+y^2-1, x-y))[-1/28*y + 1/14, 1/28*y + 1/14, -1/7*x + 1/7*y + 4/7]

liefert in unserem Fall die Beziehung

1

28

((−y + 2)(x2 + y2 + 1) + (y + 2)

((x− 4)2 + y2 − 1

)+ (−4x+ 4y + 16)(x− y)

)= 1.

In Begrien der Ideale bestätigt der Nullstellensatz , dass die Menge der Polynome, die aufder einem Ideal J zugeordneten Varietät VK(J) identisch null sind, das Radikal dieses Idealsist, das deniert ist durch

√J =

p ∈ K[x] | ∃k ∈ N.pk ∈ J

.

Wir habenV ((√

J)

= V (J),

doch intuitiv werden beim Übergang zum Radikal die Multiplizitäten vergessen. Somit istdas Ideal J1 sein eigenes Radical (man sagt, es sei radikal), wohingegen das (S2) zugeordneteIdeal J2 der Beziehung J(

√J2 genügt:

sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*Rsage: J2 = (x^2 + y^2 - 1, 4*x^2*y^2 - 1)*Rsage: J1.radical() == J1Truesage: J2.radical()Ideal (2*y^2 - 1, 2*x^2 - 1) of Multivariate Polynomial Ring in x, yover Rational Fieldsage: 2*y^2 - 1 in J2False

Systeme, Ideale und die Kryptographie

Die spezischen Module sage.rings.polynomial.multi_polynomial_sequenceund sage.crypto.mq bieten Werkzeuge für den Umgang mit polynomialen Syste-men, indem sie der besondere Gestalt der Gleichungen Rechnung tragen und nichtnur dem Ideal, das sie erzeugen. Das ist nützlich für die Arbeit mit groÿen struk-turierten Systemen, wie solchen, die bei der Kryptographie vorkommen. Das Modulsage.crypto deniert auch mehrere polynomiale Systeme, die den klassischen kryp-tographischen Konstruktionen zugeordnet sind.

191

Page 208: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Operationen auf Idealen. Es ist auch möglich, mit den Idealen selbst zu rechnen. Erinnernwir uns, dass die Summe zweier Ideale deniert ist durch

I + J = p+ q | p ∈ I und q ∈ J = 〈I ∪ J〉.

Sie entspricht geometrisch der Schnittmenge der Varietäten:

V (I + J) = V (I) ∩ V (J).

Somit wird das (S1) zugeordnete Ideal J1 als Summe von C = 〈x2 + y2 − 1〉 und H =〈16x2y2−1〉 geschrieben, welche den Kreis bzw. die doppelte Hyperbel denieren. In Sage:

sage: C = ideal(x^2 + y^2 - 1); H = ideal(16*x^2*y^2 - 1)sage: C + H == J1True

Der Test auf Gleichheit stützt sich auch auf eine Berechnung der Gröbnerbasis.

Die Schnittmenge, das Produkt und der Quotient genügen ebenfalls den Gleichungen

I ∩ J = p | p ∈ I und q ∈ JI · J = p | p ∈ I und q ∈ JI : J = p | pJ ⊂ I

V (I ∩ J) = V (I) ∪ V (J)V (I · J) = V (I) ∪ V (J)

V (I : J) = V (I)\V (J)

und werden berechnet, wie in Tabelle 9.3 gezeigt. Die überstrichene Schreibweise X bezeichnethier den Abschluss von Zariski vonX, d.h. die kleinste algebraische Subvarietät, dieX enthält.Beispielsweise ist die Kurve in Abb. 9.1 (a) die Menge der Nullstellen der Polynome von C∩Hund der Quotient (C ∩H) : 〈4xy− 1〉 entspricht der Vereinigungsmenge des Kreises und einerder beiden Hyperbeln.

sage: CH = C.intersection(H).quotient(ideal(4*x*y-1)); CHIdeal (4*x^3*y + 4*x*y^3 + x^2 - 4*x*y + y^2 - 1) ofMultivariate Polynomial Ring in x, y over Rational Fieldsage: CH.gen(0).factor()(4*x*y + 1) * (x^2 + y^2 - 1)

Dagegen ist die erhaltene Kurve keine algebraische Subvarietät, wenn eine endliche Anzahlvon Punkten aus V (H) entfernt wird, wie etwa:

sage: H.quotient(C) == HTrue

Dimension. Jedem Ideal J ⊂ K[x] ist zudem eine Dimension zugeordnet, die intuitiv dermaximalen Dimension der Komponenten der Varietät V (J) auf einem abgeschlossenenalgebraischen Körper entspricht6. Zum Beispiel haben wir:

sage: [J.dimension() for J in [J1, J2, C, H, H*J2, J1+J2]][0, 0, 1, 1, 1, -1]

In der Tat werden V (J1) und V (J2) von einer endlichen Anzahl von Punkten gebildet, V (C)und V (H) sind Kurven, V (H · J2) ist eine Vereinigung von Kurven und isolierten Punkten,

6Im Unterabschnitt 9.3.3 geben wir eine strengere, wenn auch weniger erhellende Denition. Wegen einerausführlicheren Behandlung siehe die am Anfang des Kapitels erwähnten Literaturhinweise.

192

Page 209: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

und V (J1 + J2) ist leer. Systeme mit der Dimension null, das sind solche, die ein Ideal derDimension null erzeugen, oder auch (bei Systemen mit gebrochenen Koezienten), die nureine endliche Anzahl von Lösungen besitzen, haben im weiteren Verlauf des Kapitels einebesondere Bedeutung, weil sie meistens diejenigen sind, die wir explizit lösen können.

9.2.4. Elimination

Eine Variable in einem Gleichungssystem zu eliminieren heiÿt Folgen zu nden oder besseralle Folgen des Systems, die von dieser Variablen unabhängig sind. Anders gesagt handeltes sich darum, Gleichungen zu nden, die jeder Lösung genügen, in denen die eliminierteVariable aber nicht vorkommt, was sie oft leichter analysierbar macht.

Beispielsweise können wir aus dem folgenden Gleichungssystem2x+ y − 2z = 0

2x+ 2y + z = 1(9.4)

x eliminieren, indem wir die erste Gleichung von der zweiten abziehen. Es kommt y+ 3z = 1,was zeigt, dass jedes Lösungstripel (x, y, z) von (9.4) die Form (x, 1− 3z, z) hat.

Allgemeine polynomiale Systeme: Elimination, GeometrieEliminationsideal J ∩A[z, t] ⊂ K[x, y, z, t] J.elimination_ideal(x, y)

Resultante Resx(p, q) p.resultant(q, x)

Dimension J.dimension()

Art J.genus()

Dimension null (endliche Lösungsmenge)Lösungen in L ⊇ K J.variety(L)

Dimension des Quotienten auf K J.vector_space_dimension()

Basis des Quotienten J.normal_basis()

Dreieckszerlegung J.triangular_decomposition()

Tab. 9.4 Lösung polynomialer Gleichungssysteme.

Dann können wir verizieren, dass jede partielle Lösung (1 − 3z, z) zu einer (eindeutigen)Lösung von (9.4)

(5z−1

2 , 1− 3z, z)erweitert wird. Das illustriert, dass der Gauÿ-Algorithmus

lineare Systeme durch Elimination löst, im Gegensatz beispielsweise zu den Formeln vonCramer.

Eliminationsideale. Im Kontext der polynomialen Systeme sind die Folgen der Gleichun-gen p1(x) = . . . = ps(x) = 0 die Elemente des Ideals 〈p1, . . . , ps〉. Wenn J ein Ideal vonK[x1, . . . , xn] ist, dann nennen wir die Menge

Jk = J ∩K[xk+1, . . . , xn] (9.5)

der Elemente von J , wobei nur die letzten n−k Variablen auftreten, das k-te Eliminationsidealvon J .

In Sage wird der Methode elimination_ideal die Liste der zu eliminierenden Variablenübergeben. Achtung: sie gibt nicht Jk ⊂ K[xk+1, . . . , xv] zurück, sondern das Ideal 〈Jk〉 vonK[xk+1, . . . , xv], das von diesem erzeugt wird. Für das lineare System (9.4) ndet man

193

Page 210: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

sage: R.<x,y,z> = QQ[]sage: J = ideal(2*x+y-2*z, 2*x+2*y+z-1)sage: J.elimination_ideal(x)Ideal (y + 3*z - 1) of Multivariate Polynomial Ring in x, y, zover Rational Fieldsage: J.elimination_ideal([x,y])Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field

Mathematisch interpretieren wir diese Resultate so: wir haben J ∩ Q[y, z] = 〈y + 3z − 1〉 ⊂Q[y, z] und L ∩ Q[z] = Q[z], d.h. Q[z] ⊂ J . (Tatsächlich entspricht das Ideal von 〈0〉 demreduzierten System mit der einzigen trivialen Gleichung 0 = 0, von der jedes Polynom eineLösung ist.) Freilich ist das keine empfehlenwerte Vorgehensweise zur Lösung eines linearenSystems: die in Kapitel 8 diskutierten spezischen Werkzeuge sind viel ezienter!

Als weniger triviales Beispiel greifen wir das System (S1) aus Unterabschnitt 9.2.3 wieder auf(siehe Abb. 9.1 (a)):

sage: R.<x,y> = QQ[]sage: J1 = ideal(x^2 + y^2 - 1, 16*x^2*y^2 - 1)

Die Eliminierung von y liefert ein Ideal von Q[x] - daher Haupideal -, das von einem Polynomg erzeugt wird. Dessen Wurzeln sind die Abszissen

±√

2±√

3

2

der acht Lösungen von (S1):

sage: g = J1.elimination_ideal(y).gens(); g[16*x^4 - 16*x^2 + 1]sage: SR(g[0]).solve(SR(x)) # gelöst durch Radikale[x == -1/2*sqrt(sqrt(3) + 2), x == 1/2*sqrt(sqrt(3) + 2),x == -1/2*sqrt(-sqrt(3) + 2), x == 1/2*sqrt(-sqrt(3) + 2)]

Durch Wiedereinsetzten jedes der zu (S1) gefundenen x-Werte erhalten wir ein (redundantes)Gleichungssystem nur in y, welches die entsprechenden beiden Werte von y zu berechnenerlaubt.

Eliminieren = Projizieren. Das vorstehende Ergebnis illustriert, dass die Elimination von yaus einem Gleichungssystem geometrisch der Projektion π der Lösung der Varietät auf einerHyperebene der Gleichung y =const. entspricht. Aber betrachten wir getrennt davon die idealeC = 〈x2 + y2 − 1〉 und H = 〈16x2y2 − 1〉, deren J1 die Summe ist, und eliminieren wir yerneut:

sage: C.elimination_ideal(y).gens()[0]sage: H.elimination_ideal(y).gens()[0]

Was C betrit, ist das keine Überraschung. Der Kreis

(x, y) ∈ R2 | x2 + y2 = 1wird zwar

auf [−1, 1] projiziert, doch es ist klar, dass es nicht darauf ankommt, welcher x-Wert in dieeindeutige Gleichung x2 + y2− 1 = 0 wieder eingesetzt wird und dass die erhaltene Gleichungin y komplexe Lösungen hat. Was die Eliminierung von y in C überträgt, ist die Projektion

194

Page 211: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

auf die erste Koordinate des komplexen Kreises

(x, y) ∈ C2 | x2 + y2 = 1, und das ist das

ganze C.

Die Situation bei H ist ein klein wenig komplizierter. Die Gleichung 16x2y2 = 1 hat keine,auch keine komplexe Lösung. Diesmal haben wir

VC(H ∩Q[x]) = C ( π(VC(H)) = C\ 0 .

Tatsächlich ist die Projektion der Hyperbel C\ 0 keine algebraische Subvarietät. Die Moralvon der Geschicht': die Elimination entspricht wohl der Projektion (auf einen algebraischabgeschlossenen Körper), doch berechnet sie nicht die exakte Projektion einer anen Varietät,sondern nur deren Zariski-Abschluss.

Abb. 9.2 - Ein Teil der durch (9.6) denierten Kurve in (x, y, t) und ihre Projektion auf die Ebene t = 0.

Anwendungen: ein wenig Geometrie der Ebene. Wenn X ⊂ Ck durch eine rationale Pa-rametrisierung gegeben ist:

X = (f1(t), f2(t), . . . , fk(t)) , f1, . . . , fk ∈ Q(t1, . . . , tn),

soll eine implizite Gleichung für X gefunden werden, die den Teil von Ck+n auf den Unterraumvon (x1, . . . , xk) ' Ck projiziert, der durch die Gleichungen xi = fi(t) deniert ist. Das ist eineAufgabe für die Elimination. Betrachten wir die klassische Parametrisierung des Kreises

x =1− t2

1 + t2y =

2t

1 + t2(9.6)

der dem Ausdruck von (sin θ, cos θ) als Funktion von tan(θ/2) zugeordnet ist. Sie wird durchpolynomiale Beziehungen übertragen, die ein Ideal von Q[x, y, t] denieren:

195

Page 212: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

sage: R.<x,y,t> = QQ[]sage: Param = R.ideal((1-t^2)-(1+t^2)*x, 2*t-(1+t^2)*y)

Eliminieren wir t:

sage: Param.elimination_ideal(t).gens()

Wir erhalten eine Kreisgleichung. Wir können bemerken, dass diese Gleichung in (x, y) =(−1, 0) null wird, obwohl die Parametrisierung (9.6) diesen Punkt nicht enthält, denn derKreis, der einen Punkt nicht enthält, ist keine algebraische Subvarietät.

Ein anderes Beispiel: Zeichnen wir mit Sage (siehe Abb. 9.3) einige Kreise (Ct) der Gleichung

Ct : x2 + (y − t)2 =t2 + 1

2(9.7)

sage: R.<x,y,t> = QQ[]sage: eq = x^2 + (y-t)^2 - 1/2*(t^2+1)sage: fig = add((eq(t=k/5)*QQ[x,y]).plot() for k in (-15..15))sage: fig.show(aspect_ratio=1, xmin=-2, xmax=2, ymin=-3, ymax=3)

Abb. 9.3 - Eine Familie von Kreisen und ihre Evolvente

Wir sehen die Evolvente der Familie der Kreise zum Vorschein kommen, eine Grenzkurve,die alle Ct berührt, die man informell als Menge der Schnittpunkte der unendlich nahe ange-näherten Kreise der Familie beschreiben kann.

Genauer, wenn f eine dierenzierbare Funktion ist und die Kurve Ct hat für alle t die Gleichungf(x, y, t) = 0, dann ist die Evolvente von (Ct) die Menge der (x, y), für die gilt

∃t, f(x, y, t) = 0 und∂f

∂t(x, y, z) = 0. (9.8)

Bei den Kreisen (9.7) ist die Funktion f(x, y, z) ein Polynom. Ihre Evolvente ist die Projektionauf die x, y-Ebene der Lösungen von (9.8), weshalb wir durch Berechnung des Eliminations-ideals folgende Gleichung bestimmen können:

196

Page 213: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

sage: env = ideal(eq, eq.derivative(t)).elimination_ideal(t)sage: env.gens()[2*x^2 - 2*y^2 - 1]

Die gefundene Kurve ist nur noch zu zeichnen:

sage: env.change_ring(QQ[x,y]).plot((x,-2,2), (y,-3,3))

Resultante und Elimination. Die Operationen der Elimination in den vorstehenden Bei-spielen stützen sich implizit auf Gröbnerbasen, die von Sage automatisch berechnet werden.Wir sind in diesem Buch jedoch zuvor schon einem anderen Werkzeug für die Eliminationbegegnet: der Resultanten.

Ungleichungen

Betrachten wir ein Dreieck mit den Ecken A = (0, 0), B = (1, 0) und C = (x, y).Setzen wir die Winkel ∠BAC = A und ∠CBA = B als gleich voraus und versuchenwir durch Rechnung zu beweisen, dass das Dreieck dann gleichschenklig ist. NachEinführung des Parameters t = tan A = tan B wird die Situation durch die Glei-chungen y = tx = t(1 − x) kodiert und dann muss gezeigt werden, dass aus ihnenfolgt

x2 + y2 = (1− x)2 + y2.

Mit Sage bekommen wirsage: R.<x,y,t> = QQ[]sage: J = (y-t*x, y-t*(1-x))*Rsage: (x^2+y^2) - ((1-x)^2+y^2) in JFalseUnd das aus gutem Grund: für x = y = t = sind zwar die Voraussetzungen erfüllt,aber die Konklusion ist falsch! Geometrisch gesehen müssen wir den Fall ebenerDreiecke ausschlieÿen, die zwei gleiche Winkel haben können, ohne gleichschenkligzu sein.Wie ist beispielsweise die Bedingung t 6= 0 zu kodieren? Der Trick besteht darin, eineHilfsvariable u einzuführen und tu = 1 vorzuschreiben. Die Rechnung wird dann:sage: R.<x,y,t,u> = QQ[]sage: J = (y-t*x, y-t*(1-x), t*u-1)*Rsage: (x^2+y^2) - ((1-x)^2+y^2) in JTrueund diesmal erhalten wir das erwartete Ergebnis. Nebenbei bemerken wir, dass wirdurch eine Gleichung des Typs t1t2 · · · tnu = 1 mehrere Ausdrücke gleichzeitig ver-arbeiten können, damit keine einzige Hilfsvariable null wird.

Betrachten wir zwei nicht konstante Polynome p, q ∈ K[x1, . . . , xn, y]. Wir bezeichnen mitResy(p, q) die Resultante von p und q, die als Polynome in einer Unbestimmten y angesehenwerden. In Unterabschnitt 7.3.3 haben wir gesehen, dass es ein Polynom von K[x1, . . . , xn]gibt, das in u ∈ Kn genau dann zu null wird, wenn p(u1, . . . , un, y) und q(u1, . . . , un) (zwei

197

Page 214: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Polynome aus K[y]) eine Nullstelle gemeinsam haben, auÿer vielleicht wenn die Leitkoezi-enten (in y) von p in u selbst null sind. Wir können noch mehr sagen: in der Tat erzeugtResy(p, q) das Eliminationsideal7 〈p, q〉 ∩K[x1 . . . , xn].

Somit können alle Berechnungen zur Elimination, die wir zu zwei Polynomen angestellt haben,durch die Resultanten ersetzt werden. Beispielsweise ist die Gleichung der Evolvente der Kreise(9.7)

sage: eq.derivative(t).resultant(eq, t)x^2 - y^2 - 1/2

Wir werden hier bei zwei Polynomen bleiben. Es ist möglich, das Ergebnis oder seine Verallge-meinerungen für allgemeinere Aufgaben der Eliminierung zu verwenden, jedoch ist die Theoriekomplizierter und die entsprechenden Werkzeuge stehen in Sage noch nicht zur Verfügung.

9.2.5. Systeme der Dimension null

Wir können die Probleme mit der alleinigen Berechnung der Eliminationsideale lösen, und Sagebietet kaum anderes black box - Werkzeug zur Lösung allgemeiner polynomialer Systeme.Die Situation ist anders, wenn es um Systeme mit Dimension null geht.

Wir sagen, ein Ideal J ⊂ K[x] hat die Dimension null, wenn der Quotientenring K[x]/J einendlichdimensionaler Vektorraum ist. Auf einem algebraisch abgeschlossenen Körper ist dasäquivalent zu der Aussage, dass die Varietät V (J) von einer endlichen Anzahl von Punktengebildet wird. Somit erzeugen die Systeme (9.1) und (9.3) Ideale der Dimension null - wirsagen auch, dass sie ihrerseits die Dimension null haben. Andererseits hat das Ideal 〈(x2 +y2)(x2 + y2 + 1)〉 von Q[x, y] die Dimension 1, obwohl die einzige reelle Lösung (0, 0) ist:

sage: R.<x,y> = QQ[]sage: ((x^2 + y^2)*(x^2 + y^2 + 1)*R).dimension()1

Systeme der Dimension null werden klarer gelöst als diejenigen, welche die allgemeinen Werk-zeuge des vorigen Abschnitts zulassen. Wir haben bei der Arbeit mit dem Beispiel in Unter-abschnitt 9.2.1 bereits mehrere dieser Möglichkeiten gesehen.

Auisten der Lösungen. Zunächst ermöglicht die Tatsache, nur eine endliche Anzahl vonLösungen zu haben, ihre Auistung entweder exakt oder näherungsweise.

Der Sage-Ausdruck J.variety(L) dient zur Berechnung der Varietät VL(J). Er zeitigt einenFehler, wenn J nicht die Dimension null hat. In der Voreinstellung sucht er die Lösungen desSystems mit Koordinaten im allgemeinen Basiskörper des Polynomrings. Beispielsweise ist diedurch J1 denierte Subvarietät von Qn leer.

sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*Rsage: J1.variety()|[]

7Die Punkte, an denen die Leitkoezienten verschwinden und die Eigenschaft der Spezialisierung der Re-sultanten nicht gilt, sind diejenigen, die bei der Projektion durch den Übergang zum Zariski-Abschlusshinzugefügt worden sind.

198

Page 215: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

Doch ebenso wie die Methode roots der Polynome mit einer Unbestimmten funktioniertvariety bei allen Arten von Denitionsmengen L. Für uns ist der wichtigste der Körper deralgebraischen Zahlen. Man kann tatsächlich beweisen, dass die Lösungen eines Systems derDimension null mit Koezienten in K ihrerseits Koordinaten im algebraischen Abschluss vonK besitzen. Somit ist es möglich, die einem Ideal J ⊂ Q[x] zugeordnete komplexe VarietätVC(J) = VQ(J) direkt zu berechnen;

sage: J1.variety(QQbar)[0:2][y: -0.9659258262890683?, x: -0.2588190451025208?,y: -0.9659258262890683?, x: 0.2588190451025208?]

Übung 35. Es ist zu beweisen, dass die Lösungen von (S1) Koordinaten in Q[√

2−√

3]haben. Sie sind mit Radikalen anzugeben.

Dreieckszerlegung. Intern geht J.variety(L) über die Berechnung einer Dreieckszerlegungdes Ideals J . Diese Zerlegung ist selbst schon interessant, denn sie ergibt für den Fortgangder Rechnung oft eine bequemere Beschreibung der Varietät V (J), die nämlich einfacher zuinterpretieren ist als die Ausgabe von variety (siehe Unterabschnitt 9.2.1), besonders dann,wenn die Lösungen zahlreich sind.

Ein polynomiales System heiÿt dreieckig, wenn es die Formp1(x:1) := xd11 + a1,d1x

d1−11 + . . .+ a1,0 = 0

p(x1, x2) := xd22 + a2,d2−1(x1)xd2−12 + . . .+ a2,0(x1) = 0

...pn(x1, . . . , xn) := xdnn + an,dn−1(x1, . . . , xn−1)xdn−1

n + . . . = 0

hat, anders gesagt, wenn in jedem Polynom pi nur Variablen x1, . . . , xi vorkommen. und wennes in der Variablen xi unitär ist. Liegt ein System der Dimension null in dieser Gestalt vor,wird seine Lösung auf eine endliche Anzahl polynomialer Gleichungen mit einer Variablenzurückgeführt: es genügt, die Wurzeln x1 von p1 zu nden, sie in p2 einzusetzen, dann dieWurzeln x2 von p2 zu suchen und so weiter. Diese Strategie funktioniert bei der Suche sowohlnach exakten wie auch genäherten Lösungen.

Nicht jedes System ist zu einem Dreieckssystem äquivalent. Es sei zum Beispiel das Ideal Jdeniert durch:

sage: R.<x,y> = PolynomialRing(QQ, order='lex')sage: C = ideal(x^2+y^2-1)sage: D = ideal((x+y-1)*(x+y+1))sage: J = C + D

Als Bild (siehe Abb. 9.4):

sage: opts = 'axes':True, 'gridlines':True, 'frame':False,'aspect_ratio':1, 'axes_pad':0, 'xmin':-1.3, 'xmax':1.3,'ymin':-1.3, 'ymax':1.3, 'fontsize': 8show(C.plot() + D.plot(), figsize=[2,2], **opts)

Die Varietät V (J) enthält zwei Punkte mit der Abszisse 0, doch nur einen mit der Abszisse−1, und ebenso einen Punkt mit der Ordinate −1, gegenüber zwei Punkten mit der Ordinatenull. Das Ideal J kann deshalb nicht durch ein System in Dreiecksform beschrieben werden.

199

Page 216: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Abb. 9.4 - In beiden Fällen ist die dem Ideal J zugeordnete Varietät der Schnitt eines Kreises mit der

Vereinigung zweier Geraden.

Man kann auf der anderen Seite zeigen, dass jedes Ideal der Dimension null als endlicheSchnittmenge von den Dreieckssystemen erzeugten Ideale geschrieben wird. Die Methodetriangular_decomposition berechnet eine solche Zerlegung:

sage: J.triangular_decomposition()[Ideal (y, x^2 - 1) of Multivariate Polynomial Ring in x, yover Rational Field,Ideal (25*y^2 - 16, 4*x + 3*y) of Multivariate Polynomial Ring in x, yover Rational Field]

Geometrisch erhalten wir eine Darstellung der Varietät als Vereinigung der den einfacherenSystemen zugeordneten Varietäten, die oft einfach genug sind, um eine gute Beschreibung derLösungen zu formulieren.

Etliche Schwierigkeiten Zu Recht können wir uns fragen, welche Bedeutung die Dreiecks-zerlegung für die Auistung der Lösungen hat. Nach all dem ist es bei einem System derDimension null immer möglich, durch eine Berechnung des Eliminationsideals ein Polynommit einer einzigen Variablen zu nden, dessen Wurzeln exakt die ersten Koordinaten der Lö-sungen sind. Durch Rückwärts-Einsetzen dieser Wurzeln in das Gleichungssystem vermindernwir die Anzahl der Variablen, was erlaubt, den Vorgang zu wiederholen, bis wir das Systemvollständig gelöst haben.

Doch der Aufstieg im System durch Verbreitung der Teilergebnisse kann heikel sein. Modi-zieren wir das obige System ein wenig:

sage: D = ideal((x+2*y-1)*(x+2*y+1)); J = C + Dsage: J.variety()[y: -4/5, x: 3/5, y: 0, x: -1, y: 0, x: 1, y: 4/5, x: -3/5]sage: [T.gens() for T in J.triangular_decomposition()][[y, x^2 - 1], [25*y^2 - 16, 4*x + 3*y]]

Die Form der Dreieckszerlegung verändert sich nicht: für jede Komnponente verfügen wirüber eine Gleichung nur in y und eine andere Gleichung, die erlaubt, x als Funktion von yauszudrücken.

Eliminieren wir deshalb x, um eine Gleichung in y allein zu erhalten, wobei das Produkt derbeiden vorhergehenden auftritt:

200

Page 217: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2. Polynomiale und ideale Systeme

sage: Jy = J.elimination_ideal(x); Jy.gens()[25*y^3 - 16*y]

Um x zu nden, gibt es nun nichts weiter einzusetzen als die Wurzeln dieser Gleichung in dieGleichungen, die das Ideal J denieren. Mit der ersten Gleichung x2 + y2 − 1 = 0 kommt

sage: ys = QQ['y'](Jy.0).roots(); ys[(4/5, 1), (0, 1), (-4/5, 1)]sage: QQ['x'](J.1(y=ys[0][0])).roots()[(-3/5, 1), (-13/5, 1)]

Einer der beiden erhaltenen Werte ist korrekt - wir haben (−3/5, 4/5) ∈ V (J) - doch derandere entspricht keiner Lösung: wir müssen die gefundenen Werte mittels der zweiten Aus-gangsgleichung (x+ 2y − 1)(x+ 2y + 1) überprüfen, um ihn auszuschlieÿen.

Das Problem kompliziert sich, wenn wir die univariaten Gleichungen numerisch lösen, waswegen des Aufwands bei algebraischen Zahlen zuweilen erforderlich ist:

sage: ys = CDF['y'](Jy.0).roots(); ys[(-0.8000000000000002, 1), (0.0, 1), (0.8, 1)]sage: [CDF['x'](p(y=ys[0][0])).roots() for p in J.gens()][[(-0.5999999999999999 - 1.306289919090511e-16*I, 1),(0.6000000000000001 + 1.3062899190905113e-16*I, 1)],[(0.6000000000000001 - 3.1350958058172247e-16*I, 1),(2.600000000000001 + 3.135095805817224e-16*I, 1)]]

Durch Einsetzen von y ' −0.8 in die beiden Erzeugenden von J nden wir hier zwei Wertevon x nahe 0.6. Wie können wir sicher sein, dass dies Näherungen der Koordinate x einerexakten Lösung (x, y) = (0.6,−0.8) sind und keine Gespenster wie im vorigen Beispiel? DieseErscheinungen verstärken sich, wenn die Anzahl der Variablen und der Gleichungen zunimmt.Wenn das System andererseits dreieckig ist, gibt es bei jedem Schritt des Aufstiegs nur eineGleichung zu betrachten, und da diese immer unitär ist, beeinussen die numerischen Nähe-rungen die Anzahl der Lösungen nicht.

Fahren wir in dieser Richtung fort. Für das folgende System berechnet J.variety() (exakt)eine Dreieckszerlegung von J und sucht dann numerisch die reellen Lösungen des oder dererhaltenen Systeme. Das ergibt eine eindeutige reelle Lösung:

sage: R.<x,y> = QQ[]; J = ideal([ x^7-(100*x-1)^2, y-x^7+1 ])sage: J.variety(RealField(51))[y: 396340.890166545, x: -14.1660266425312]

Führt man jedoch die Rechnung konsequent exakt aus, sieht man, dass nicht nur Lösungenfehlen, sondern die numerisch gefundene Lösung auch fehlerhaft ist:

sage: J.variety(AA)[x: 0.00999999900000035?, y: -0.999999999999990?,x: 0.01000000100000035?, y: -0.999999999999990?,x: 6.305568998641385?, y: 396340.8901665450?]

Moral: die Dreieckszerlegung ist kein Allheilmittel und entbindet den Anwender nicht davon,die Ergebnisse von Näherungsrechnungen mit Sorgfalt zu interpretieren.

201

Page 218: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Es existiert eine groÿe Anzahl weiterer Verfahren, um Lösungen von Systemen der Dimensionnull zu parametrieren und anzunähern, die den Problemen mehr oder weniger gut angepasstsind, die in Sage aber nicht implementiert sind. Übung 36 gibt einen Einblick in bestimmtedabei verwendete Ideen.

Quotientenalgebra. Quotienten durch Ideale der Dimension null sind im Allgemeinen vielbesser handhabbar als die Quotienten von Polynomringen, denn Rechnungen in der Quotien-tenalgebra werden auf endlichdimensionale lineare Algebra zurückgeführt.

Anspruchsvollere Mathematik

Sage verfügt auch über eine groÿe Zahl von Funktionen der kommutativen Algebraund der algebraischen Geometrie, die das Niveau dieses Buches jedoch weit über-steigen. Der interessierte Leser ist eingeladen, die Dokumentation der Ideale vonPolynomen zu erkunden wie auch diejenige des Moduls sage.schemes. Über dasInterface zu den spezialisierten Programmen Singular, CoCoA und Macauley2 sindnoch weitere Funktionalitäten zugänglich.

Wenn J ⊂ K[x] ein Ideal der Dimension null ist, dann ist die Dimension dimK[x]/J des Quoti-entenrings als K-Vektorraum eine Schranke für die Anzahl der Punkte von V (J). (Tatsächlichexistiert zu jedem u ∈ V (J) ein Polynom mit Koezienten aus K, das in jedem anderenPunkt von V den Wert 0 oder 1 annimmt. Zwei dieser Polynome können nicht äquivalentsein modulo J .) Man kann sich diese Dimemsion als Anzahl der Lösungen des Systems mitMultiplizitäten im algebraischen Abschluss von K vorstellen. Beispielsweise hatten wir fest-gestellt, dass die vier Lösungen des in Unterabschnitt 9.2.3 eingeführten Systems (S2) jeweilsdie doppelte Schnittmenge der beiden Kurven sind. Das erklärt, weshalb gilt:

sage: len(J2.variety(QQbar)), J2.vector_space_dimension()(4, 8)

Die Methode normal_basis berechnet eine Liste von Monomen, deren Projektionen in K[x]/Jeine Basis bilden:

sage: J2.normal_basis()[x*y^3, y^3, x*y^2, y^2, x*y, y, x, 1]

Die zurückgegebene Basis hängt von der Ordnung ab, die bei der Bildung des Polynomringsgewählt worden ist; genauer beschreiben wir sie in Unterabschnitt 9.3.3.

Übung 36. Sei J ein Ideal der Dimension null aus Q[x, y] und χx das charakteristischePolynom der linearen Abbildung

mx : Q[x, y]/J → Q[x, y]/J

7→ xp+ J.

Berechnen Sie χx für den Fall J = J2 = 〈x2 + y2− 1, 4x2y2− 1〉. Zeigen Sie, dass jede Wurzeldie Abszisse eines Punktes der Varietät VC(J) ist.

202

Page 219: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

9.3. Gröbnerbasen

Bis jetzt haben wir die Funktionalitäten der algebraischen Elimination und der Lösung poly-nomialer Systeme benutzt, die Sage als black box anbietet. Dieser Abschnitt führt nun einigemathematische Werkzeuge und ihnen zugrunde liegende Algorithmen ein. Das Ziel ist, vonihnen Gebrauch zu machen und gleichzeitig Funktionen, die zuvor vorgesteltt worden sind,auf höherem Niveau klug anzuwenden.

Wichtige monomiale Ordnungen für das Beispiel Q[x, y, z]

lex xα < xβ ⇐⇒ α1 < β1 oder (α1 = β1 und α2 < β2) oder . . .oder (α1 = β1, . . . , αn−1 = βn−1 und αn < βn)

x3 > x2y > x2z > x2 > xy2 > xyz > xy > xz2 > xz > x > y3

> y2z > y2 > yz2 > yz > y > z3 > z2 > z > 1

invlex xα < xβ ⇐⇒ αn < βn oder (αn = betan und αn−1 < βn−1) oder . . .oder (αn = βn, . . . , α2 = β2 und α1 < β1)

z3 > yz2 > xz2 > z2 > y2z > xyz > yz > x2z > xz > z > y3

> xy2 > y2 > x2y > xy > y > x3 > x2 > x > 1

deglex xα < xβ ⇐⇒ |α| < |β| oder (|α| = |β| und xα <lex xβ)

x3 > x2y > xy2 > xyz > xz2 > y3 > y2z > yz2 > z3 > x2

> xy > xz > y2 > yz > z2 > x > y > z > 1

degrevlex xα < xβ ⇐⇒ |α| < |β| oder (|α| = |β| und xα >invlex xβ)

x3 > x2y > xy2 > y3 > x2z > xyz > y2z > xz2 > yz2 > z3 > x2

> xy > y2 > xz > yz > z2 > x > y > z > 1

Bildung der monomialen OrdnungenObjekt, das eine vordenierte Ordnung auf n Elementen darstellt TermOrder('nom', n)

Matrizenordnung: xα <M xβ ⇐⇒ Mα <textlex Mβ TermOrder(M)

Blöcke: xαyβ < xγyδ ⇐⇒ α <1 γ oder (α = γ und β <2 δ) T1 + T2

Tab. 9.5 - Monomiale Ordnungen

Die von Sage für Rechnungen auf Eliminationsidealen angewandten Techniken beruhen aufdem Begri der Gröbnerbasis. Wir können sie uns als Erweiterung der Darstellung durchden Hauptgenerator der Ideale von K[x] auf mehrere Unbestimmte vorstellen. Das zentraleProblem dieses Abschnitts sind die Denition und die Berechnung einer Normalform der Ele-mente der Quotientenringe K[x]. Unser Standpunkt bleibt der des Anwenders.: wir denerendie Gröbnerbasen, zeigen, wie wir sie in Sage bekommen und wozu sie dienen können, wirgehen aber nicht auf die zur Berechnung verwendeten Algorithmen ein.

9.3.1. Monomiale Ordnungen

Eine monomiale Ordnung oder (globale) zulässige Ordnung ist eine totale Ordnung auf denMonomen xα eines Polynomrings K[x], die folgenden Bedingungen genügt:

xα < xβ =⇒ xα+γ < xβ+γ und γ 6= 0 =⇒ 1 < xγ (9.9)

für alle Exponenten α,β,γ. Auf die gleiche Weise können wir < als eine Ordnung auf denExponenten α ∈ Nn betrachten oder auch auf den Termen cxα. Die Leitmonome, Leitko-ezienten und Leitterme eines Polynoms p (siehe Unterabschnitt 9.1.3) für die vorliegendeOrdnung sind die mit den gröÿten Exponenten; wir bezeichnen sie mit lm p, lc p und lt p.

Die erste der Aussagen (9.9) drückt eine Bedingung der Kompatibilität mit der Multiplikationaus: das Produkt mit einem festen Monom verändert die Ordnung nicht. Die zweite Aussage

203

Page 220: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

bestimmt, dass < eine Wohlordnung ist, d.h. dass keine streng abnehmende endliche Folgevon Monomen existiert. Wir stellen fest, das die allein zulässige Ordnung auf K[x] die üblicheist mit xn > xn−1 > . . . > 1.

In Unterabschnitt 9.1.1 haben wir gesehen, dass Sage bei der Denition eines Ringes dieFestlegung einer Ordnung erlaubt, und zwar mit einer Konstruktion wie

sage: R.<x,y,z,t> = PolynomialRing(QQ, order='lex')

Tabelle 9.5 verzeichnet die wichtigsten vordenierten Ordnungen8: lex ist die lexikographischeOrdnung der Exponenten, invlex die von rechts nach links gelesene lexikographische Ordnungder Exponenten. Die Denition von degrevlex ist etwas komplizierter: die Monome sind nachder Summe der Exponenten geordnet und dann in absteigender lexikographischer Ordnungder von rechts gelesenen Exponenten. Diese merkwürdige Ordnung ist dennoch die, welcheangewendet wird, wenn die Option order weggelassen wird, denn für bestimmte Rechnungenist sie ezienter als die anderen.

Gemeinhin (aber nicht immer!) legen wir die Reihenfolge der Variablen und der Monomex1 > x2 > . . . > xn zusammen fest, und wir sprechen beispielsweise oft von der Ordnunglex, sodass x > y > z ist statt von der Ordnung lex auf K[x, y, z]. Die vordenierten Ord-nungen lex, deglex und degrevlex gehorchen dieser Konvention; was die Ordnung invlexauf K[x, y, z] betrit, ist das auch die Ordnung lex, sodass z > y > x, d.h. die Ordnung aufK[z, y, x].

9.3.2. Division durch eine Familie von Polynomen

Sei G = g1, g2, . . . , gs eine endliche Menge von Polynomen von K[x] mit festgelegter mono-mialer Ordnung <. Mit 〈G〉 bezeichnen wir das durch G erzeugte Ideal von K[x].

Die Division eine Polynoms p ∈ K[x] durch G ist ein multivariates Analogon zur euklidschenDivision in K[x]. Wie letztere ordnet sie p einen Rest zu, der in Sage durch den Ausdruckp.reduce(G) gegeben wird. Das ist ein kleineres Polynom, welches zur selben Äquivalenz-klasse modulo 〈G〉 gehört:

sage: ((x+y+z)^2).reduce([x-t, y-t^2, z^2-t])2*z*t^2 + 2*z*t + t^4 + 2*t^3 + t^2 + t

Der Rest wird erhalten, indem von p soviele Vielfache der Elemente von G abgezogen werdenwie möglich. Bei der Subtraktion heben sich der Leitterm von G und ein Term von p auf. ImUnterschied zum univariaten Fall kann es vorkommen, dass sich ein Term von p heraushebt,der kein Leitterm ist. Wir fordern daher nur, dass ein im Sinne der monomialem Ordnunggröÿter Term zu null wird.

8Sage kennt noch weitere Ordnungen (sog. lokale Ordnungen), bei denen 1 das gröÿte Monom ist statt daskleinste zu sein. Beispielsweise haben wir bei der Ordnung neglex auf Q[x, y, z] 1 > z > z2 > zu3 > y >yz > yz2 > y2 > y2z > y3 > x > xz > xz2 > xy > xyz > xy2 > x2 > x2z > x2y > x3. Die lokalenOrdnungen sind im Sinne der Denition (9.9) nicht zulässig, und wir verwenden sie auch nicht in diesemBuch, doch kann der interessierte Leser die Tabelle 9.5 mit der in Unterabschnitt 9.1.1 denierten Funktiontest_poly vervollständigen.

204

Page 221: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

Formell bezeichnen wir für p ∈ K[x] mit ltGp den Term von p mit dem gröÿten Exponenten,der durch einen Leitterm eines Elementes von G teilbar ist. Wir nennen elementare Reduktion

jede Transformation der Form

p 7→ p = p− cxαg, worin g ∈ G und ltGp = cxαltg. (9.10)

Eine elementare Reduktion erhält die Äquivalenzklasse von p modulo 〈G〉 und lässt das gröÿteMonom von p, das sie zuordnet, verschwinden: wir haben

p− p ∈ 〈G〉 und ltGp < ltGp.

Da < eine Wohlordnung ist, ist es nicht möglich, unendlich viele elementare Reduktionennacheinander auf p anzuwenden. Jede Folge elementarer Reduktionen endet deshalb bei einemPolynom, das nicht reduziert werden kann, und das ist der Rest der Division.

Halten wir fest, dass dieses Verfahren die bekannten Eliminationsmethoden sowohl für Polyno-me mit einer Unbestimmten wir für lineare Systeme verallgemeinert. Gibt es nur eine Variable,reduziert sich die Division durch eine Einsermenge G = g genau auf die euklidsche Divisionvon p durch g. Im anderen Extremfall eines Polynoms mit mehreren Unbestimmten, wobeijedoch alle Monome vom 1. Grade sind, stimmt sie mit der elementaren Reduktionsoperationdes Gauÿ-Jordan-Verfahrens überein.

Doch anders als das, was in diesen Spezialfällen geschieht, hängt der Rest generell von derWahl der elementaren Reduktionen ab. (Man sagt, das Regelsystem der Transformation (9.10)ist nicht konuent.) Somit führt die Änderung der Reihenfolge, in der die Elemente von Ggegeben sind, im folgenden Beispiel zur Wahl verschiedener Reduktionen:

sage: R.<x,y> = PolynomialRing(QQ, order='lex')sage: (g, h) = (x-y, x-y^2); p = x*y - xsage: p.reduce([g, h]) # zwei Reduktionen durch hy^3 - y^2sage: p.reduce([h, g]) # zwei Reduktionen durch gy^2 - y

Selbst wenn die Ordnung der Elemente von G als determiniert angesehen wird (sodass fürgegebene p und G ein eindeutiges Ergebnis erhalten wird), wie stellt man beispielsweise sicher,dass die Folge der gewählten elementaren Reduktionen von p durch g, h die folgende Relationzeitigen wird, die beweist, dass p ∈ 〈g, h〉 ist?

sage: p - y*g + h0

9.3.3. Gröbnerbasen

Die Einschränkungen bei der multivariaten Division erklären die im Unterabschnitt 9.2.3erwähnten Schwierigkeiten, für die Elemente der Algebren K[x]/J eine Normalform zu be-kommen: die Division durch die Erzeugenden des Ideals reicht nicht aus. . . zumindest nichtgenerell! Es existieren nämlich spezielle Generatoren, für welche die Division konuent ist undeine Normalform berechnet. Diese Systeme heiÿen Gröbnerbasen oder Standardbasen.

205

Page 222: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Treppen. Eine schöne Möglichkeit Gröbner-Bassen kennen zu lernen, ergibt sich durch denBegri der Treppe eines Ideals. Wir möchten jedes von null verschiedene Polynom ausK[x1, . . . , xn] auf einen Punkt Nn abbilden, der durch seinen Leitexponenten gegeben ist, unddie Teilmenge E ⊂ Nn markieren, die durch ein Ideal J belegt ist (siehe Abb. 9.5 bis 9.7).Die erhaltene Darstellung (die von der monomialen Ordnung abhängt), hat Treppenform:tatsächlich haben wir α + Nn ⊂ E für jedes α ∈ E. Die Elemente von J\ 0 benden sichim grau unterlegten Bereich oberhalb oder an der Treppenline. Die Punkte streng unterhalbder Treppenlinie entsprechen ausschlieÿlich den Polynomen aus K[x]\J , es liegen jedoch nichalle Polynome aus K[x]\J unter der Treppenlinie.

Beispielsweise ist jedes Monom in einem Polynom aus 〈x3, xy2z, xz2〉, Leitmonom oder nicht,ein Vielfaches eines der Polynome x3, xy2z und xz2. Die Leitmonome sind deshalb genau diexαyβzγ , die Exponent für Exponent einer der Ungleichungen (α, β, γ) ≥ (3, 0, 0), (α, β, γ) ≥(1, 2, 1) oder (α, β, γ) ≥ (1, 0, 2) genügen (Abb. 9.5). Ein Polynom, dessen Leitexponentendiese Bedingungen nicht erfüllen, zum Beispiel x2 + xz2 bei lexikographischer Ordnung mitx > y > z, kann dem Ideal nicht angehören. Bestimmte Polynome wie x3 +x sind nicht mehrim Ideal, obwohl ein Monom unterhalb der Treppenlinie liegt. Die Situation ist für jedes vonMonomen erzeugte Ideal entsprechend.

Für ein beliebiges Ideal wird die Gestalt der Treppe nicht einfach aus den Erzeugenden ab-gelesen. Wenn wir also mit δ1 . . . , δs die Leitexponenten der Erzeugenden bezeichnen, habenwir in allen Beispielen der Abb. 9.6 und 9.7

⋃si=1(δ + Nn) ( E, auÿer in der zweiten. Wir

können indessen zeigen, dass E immer als Vereinigung einer endlichen Anzahl von Mengender Form α+ Nn geschrieben wird. Intuitiv heiÿt das, die Treppenlinie hat nur endlich vieleEcken. Dieses Ergebnis heiÿt manchmal Lemma von Dickson.

Gröbnerbasen Eine Gröbnerbasis ist schlicht eine Familie von Erzeugenden, die die Formder Treppenlinie ausmachen, genauer, die an jeder ihrer Ecken ein Polynom zählt.

Definition. Eine Gröbnerbasis eines Ideals J ⊂ K[x] bezogen auf eine monomiale Ordnung< ist eine endliche Teilmenge G von J , sodass für jedes von null verschiedene p ∈ J ein g ∈ Gexistiert, für dessen Leitmonom (zur Ordnung <) gilt: lm g teilt lm p.

Die Prüfung, ob die Erzeugenden, die ein Ideal denieren, eine Gröbnerbasis bilden, wird inSage mit der Methode basis_is_groebner durchgeführt. Wir haben schon bemerkt, dass jedeMenge von Monomen eine Gröbnerbasis ist:

sage: R.<x,y> = PolynomialRing(QQ, order='lex')sage: R.ideal(x*y^4, x^2*y^3, x^4*y, x^5).basis_is_groebner()True

Andererseits ist das Systemx2 + y2 − 1, 16x2y2 − 1

, das den Schnitt von Kreis und Hyper-

beln kodiert, keine Gröbnerbasis:

sage: R.ideal(x^2+y^2-1, 16*x^2*y^2-1).basis_is_groebner()False

206

Page 223: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

y

x

〈xy4, x3y3, x4y, x5〉

x

y

z

〈x3, xy2z, xz2〉

Abb. 9.5 - Treppen der von Monomen erzeugten Ideale.

y

x

〈x2 + y2 − 1, 16x2y2 − 1〉

y

x

〈16x2y2 − 1〉

y

x

〈x2 + y2 − 1, (x+ y)2 − 1〉

Abb. 9.6 - Treppen der in diesem Kapitel angeführten Ideale von Q[x, y]. In diesen drei Fällen sind die Treppen

und die Positionen der Generatoren für die Ordnungen lex, deglex und degrevlex dieselben.

y

x

lex(x, y)

y

x

invlex(x, y) = lex(y, x)

y

x

degrevlex(x, y)

Abb. 9.7 - Treppe des Ideals 〈xy+ x+ y2 + 1, x2y+ xy2 + 1〉 ⊂ QQ[x, y] bezogen auf verschiedene monomialeOrdnungen.

In jedem Schema entspricht das grau unterlegte Gebiet den Leittermen der Elemente des Ideals. Die schwarzenQuadrate geben die Positionen der für seine Beschreibung verwendeten Generatoren an.

Gemäÿ der Gestalt der Treppenlinie (Abb. 9.6) fehlt dafür ein Polynom von J1 des Leitmonomsy4.

Das oben angedeutete und auf dem Dickson-Lemma gründende Argument zeigt, dass jedesIdeal Gröbnerbasen zulässt9. Berechnen wir Gröbnerbasen von J1 und weiteren Idealen, deren

9Dieses Ergebnis kann man auch als eine eektive Version des Hilbertschen Basissatzes sehen, der besagt,dass die Ideale von K[x] durch eine endliche Anzahl von Elementen erzeugt werden. Ein klassischer Beweisdieses Satzes erinnert stark an die Bildung einer Gröbnerbasis für die lexikographische Ordnung.

207

Page 224: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Treppenlinien in Abb, 9.6 dargestellt sind. Für J1 kommt

sage: R.ideal(x^2+y^2-1, 16*x^2*y^2-1).groebner_basis()[x^2 + y^2 - 1, y^4 - y^2 + 1/16]

Wie erwartet erscheinen hier die Leitmonome x2 und y4. Ihr Auftreten erklärt, wie sich dieTreppenlinie auf die Achsen zurückzieht, woraus wir erkennen, dass das für Systeme derDimension null charakteristisch ist. Bezogen allein auf die Doppelhyperbel nden wir

sage: R.ideal(16*x^2*y^2-1).groebner_basis()[x^2*y^2 - 1/16]

d. h. ein Vielfaches des erzeugenden Polynoms. Ganz generell ist jedes einzelne Polynom eineGröbnerbasis. Das dritte Beispiel zeigt, dass eine Gröbnerbasis mehrere Polynome benötigenkann als ein beliebiges System von Erzeugenden:

sage: R.ideal(x^2+y^2-1, (x+y)^2-1).groebner_basis()[x^2 + y^2 - 1, x*y, y^3 - y]

Aufgrund der Einfachheit der vorstehenden Beispiele hängen diese drei Gröbnerbasen nichtoder nur wenig von der monomialen Ordnung ab. Das ist im allgeneinen nicht so. Die Abb.9.7 stellt Treppenlinien für drei klassische monomiale Ordnungen dar, die demselben Idealvon Q[vx] zugeordnet sind. Die entsprechenden Gröbnerbasen sind:

sage: R_lex.<x,y> = PolynomialRing(QQ, order='lex')sage: J_lex = (x*y+x+y^2+1, x^2*y+x*y^2+1)*R_lex; J_lex.gens()[x*y + x + y^2 + 1, x^2*y + x*y^2 + 1]sage: J_lex.groebner_basis()[x - 1/2*y^3 + y^2 + 3/2, y^4 - y^3 - 3*y - 1]

sage: R_invlex = PolynomialRing(QQ, 'x,y', order='invlex')sage: J_invlex = J_lex.change_ring(R_invlex); J_invlex.gens()[y^2 + x*y + x + 1, x*y^2 + x^2*y + 1]sage: J_invlex.groebner_basis()[y^2 + x*y + x + 1, x^2 + x - 1]

sage: R_drl = PolynomialRing(QQ, 'x,y', order='degrevlex')sage: J_drl = J_lex.change_ring(R_drl); J_drl.gens()[x*y + y^2 + x + 1, x^2*y + x*y^2 + 1]sage: J_drl.groebner_basis()[y^3 - 2*y^2 - 2*x - 3, x^2 + x - 1, x*y + y^2 + x + 1]

Reduktionmultivariate Divison von p durch G p.reduce(G)

zwischenreduzierte Erzeugende J.interreduced_basis()

GröbnerbasenTest, ob Gröbnerbasis J.basis_is_groebner()

Gröbnerbasis (reduziert) J.groebner_basis()

Wechsel der Ordnung für lex J.transformed_basis()

Wechsel der Ordnung R1 7→ R2 J.transformed_basis('fglm', other_ring=R2)

Tab. 9.6 - Gröbnerbasen

208

Page 225: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

Die Gröbnerbasis zur Ordnung lex hebt die Regel für die neue Schreibweise x = 12y

3 −y2 − 3

2 deutlich hervor, dank der wir die Elemente des Quotientenrings als Funktion nureiner Variablen y ausdrücken können. Die verlängerte Form der entsprechenden Treppenliniespiegelt diese Möglichkeit wieder. Ebenso zeigt die Gröbnerbasis zur Ordnung invlex an, dasswir die Potenzen von y durch die Gleichung y2 = −xy − x − 1 eliminieren können. Daraufkommen wir am Ende des Kapitels noch einmal zurück.

9.3.4. Eigenschaften der Gröbnerbasen

Die Gröbnerbasen dienen zur Implementierung der in Abschnitt 9.2 untersuchten Operationen.Wir benutzen sie nämlich zu Berechnung der Normalformen von Idealen von Polynomringen,und der Elemente der Quotienten durch diese Ideale, zur Eliminierung von Variablen in po-lynomialen Systemen oder auch zur Bestimmung der Charakteristik der Lösungen wie ihrerDimension.

Division durch eine Gröbnerbasis. Die Division durch eine Gröbnerbasis G eines Polynomsaus 〈G〉 kann bei einem von null verschiedenen Element aus 〈G〉 nicht terminieren. Das isteine unmittelbare Konsequenz der Denition: ein solches Element befände sich oberhalb derzu 〈G〉 gehörenden Treppenlinie und wäre daher auch durch G teilbar. Jedes Element in 〈G〉reduziert sich somit bei der Division durch G auf null. Insbesondere erzeugt eine Gröbnerbasiseines Ideals J wiederum J .

Ebenso kann die Division eines Polynoms p /∈ J durch eine Gröbnerbasis von J nur bei einemPolynom unter der Treppe terminieren, nun gehören aber zwei verschiedene Polynome un-ter der Treppe zu verschiedenen Äquivalenzklassen modulo J (weil ihre Dierenz auch unterder Treppe ist). Die Division durch eine Gröbnerbasis liefert daher eine Normalform für dieElemente des Quotientenrings K[x]/J , und das unabhängig von der Reihenfolge, in der dieelementaren Reduktionen vorgenommen werden. Die Normalform einer Äquivalenzklasse p+Jist ihr einziger Repräsentant, der unter der Treppenlinie liegt oder null ist. Es ist diese Nor-malform, welche die in Unterabschnitt 9.2.3 vorgestellten Operationen der Quotientenalgebraberechnen. Um das Beispiel der Abb. 9.7 fortzusetzen, wird die Reduktion

sage: p = (x + y)^5sage: J_lex.reduce(p)17/2*y^3 - 12*y^2 + 4*y - 49/2

zerlegt in eine Berechnung der Gröbnerbasis und eine anschlieÿende Division

sage: p.reduce(J_lex.groebner_basis())17/2*y^3 - 12*y^2 + 4*y - 49/2

Das Ergebnis einer Projektion in den Quotienten ist im Wesentlichen dasselbe:

sage: R_lex.quo(J_lex)(p)17/2*ybar^3 - 12*ybar^2 + 4*ybar - 49/2

Natürlich verursacht ein Wechsel der monomialen Ordnung eine andere Bestimmung der Nor-malform:

sage: R_drl.quo(J_drl)(p)5*ybar^2 + 17*xbar + 4*ybar + 1

209

Page 226: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Die Monome, die in der Normalform auftreten, entsprechen Punkten unter der Treppenlinie.

Somit hat das Ideal J die Dimension null genau dann, wenn die Anzahl der Punkte unterseiner Treppe endlich ist, und diese Anzahl der Punkte ist die Dimension des QuotientenringsK[x]/J . In diesem Fall ist die in Unterabschnitt 9.2.5 beschriebene Basis, die von der Methodenormal_basis zurückgegeben wird, einfach die Menge der Monome unter der Treppenlinie fürdie vorliegende monomiale Ordnung.:

sage: J_lex.normal_basis()[y^3, y^2, y, 1]sage: J_invlex.normal_basis()[x*y, y, x, 1]sage: J_drl.normal_basis()[y^2, y, x, 1]

Nebenbei bemerken wir, dass die Anzahl der Monome unter der Treppenlinie unabhängig vonder monomialen Ordnung ist.

Dimension. Wir sind nun gerüstet, eine Denition der Dimemsion eines Ideals für den all-gemeinen Fall zu geben: J hat die Dimemsion d, wenn die Anzahl der Punkte unter derTreppenlinie, die den Monomen des Totalgrades höchstens t entspricht, von der Ordnung td

ist, wenn t→∞ geht. Zum Beispiel hat das Ideal 〈16x2x2−1〉 (Abb. 9.6) die Dimension 1:

sage: ideal(16*x^2*y^2-1).dimension()1

In der Tat ist die Anzahl der Monome m unter der Treppenlinie so, dass degxm+ degym ≤ tfür t ≥ 3 gleich 4t − 2 ist. Genauso haben die beiden Ideale in Abb. 9.5 die Dimensionen1 bzw. 2. Man kann zeigen, dass der Wert der Dimension von der monomialen Ordnungnicht abhängt, sondern bis auf entartete Fälle der geometrischen Dimension der dem Idealzugehörigen Varietät entspricht.

Reduzierte Basen. Eine endliche Menge von Polynomen, die eine Gröbnerbasis enthält, istselber eine Gröbnerbasis, weshalb ein von null verschiedenes Ideal unendlich viele Gröbner-basen hat. Eine Gröbnerbasis G = g1, . . . , gs heiÿt reduziert, wenn

• die Leitkoezienten der gi sind sämtlich 1 (und 0 /∈ G);

• kein gi ist im Sinne der Regeln (9.10) durch den Rest der Basis G\ gi reduzierbar.

Bei festgelegter monomialer Ordnung lässt jedes Ideal eine eindeutige reduzierte Gröbnerbasiszu. Beispielsweise ist die reduzierte Gröbnerbasis des Ideals 〈1〉 die einelementige Menge 1für welche Ordnung auch immer. Die reduzierten Gröbnerbasen liefern daher für die Idealevon K[x] eine Normalform.

Eine reduzierte Gröbnerbasis ist in dem Sinne minimal, dass das, was nach Wegnahme einesbeliebigen Elements übrig bleibt, kein Erzeugendensystem des Ideals mehr ist. Konkret um-fasst sie genau ein Polynom pro Ecke der Treppenlinie. Sie kann aus einer beliebigen Gröb-nerbasis G berechnet werden, indem jedes Element g ∈ G durch seinen Rest der Division durchG\ g, soweit das möglich ist, ersetzt wird. Das ist es, was die Methode interreduced_basismacht. Die zu null reduzierten Polynome werden gelöscht.

210

Page 227: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

Elimination. Die lexikographischen Ordnungen erfreuen sich folgender grundlegender Eigen-schaft: wenn G eine Gröbnerbasis für die lexikographische Ordnung von J ⊂ K[x1, . . . , xn] ist,dann sind die G∩K[xk+1,...,xn ] Gröbnerbasen der Eliminationsideale10 J ∩K[xk+1,...,xn ]. Einelexikographische Gröbnerbasis wird in Blöcke zerlegt, deren letzter nur von xn abhängt, dervorletzte von xn und xn−1 usw.11:

sage: R.<t,x,y,z> = PolynomialRing(QQ, order='lex')sage: J = R.ideal(t+x+y+z-1, t^2-x^2-y^2-z^2-1, t-x*y)sage: [u.polynomial(u.variable(0)) for u in J.groebner_basis()][t + x + y + z - 1,(y + 1)*x + y + z - 1,(z - 2)*x + y*z - 2*y - 2*z + 1,(z - 2)*y^2 + (-2*z + 1)*y - z^2 + z - 1]

In diesem Beispiel hängt das letzte Basispolynom nur von y und z ab. Zunächst kommt einBlock von zwei Polynomen in x, y und z und als erstes ein Polynom, in dem sämtliche Variablenvorkommen. Die aufeinander folgenden Eliminationsideale werden unmittelbar abgelesen.

Wir haben indessen gesehen (Unterabschnitt 9.2.5), dass die letzteren keine vollständige Be-schreibung des Ideals liefern. Hier ist der Block mit z allein leer, daher erscheint jeder Wertvon z, vielleicht bis auf endlich viele Ausnahmen, als letzte Koordinate einer Lösung. Wirsind versucht, die möglichen y-Werte für jedes z mittels der letzten Gleichung auszudrücken.Es sind zwei an der Zahl, auÿer für z = 2, wozu nur y = −1 passt. Nur beim Übergang zurvorstehenden Gleichung sehen wir, dass die Festlegung z = 2 widersprüchlich ist. Umgekehrtfolgt gemäÿ der letzten Gleichung wiederum z = 2 aus y = −1 und ist daher ausgeschlossen.Es erweist sich daher, dass jeder Leitkoezient der Polynome (geschrieben in ihrer jeweiligenHaupvariablen, wie im Auszug weiter oben) für z 6= 2 zu null wird.

Übung 37 (Trigonometrische Beziehungen). Es soll (sin θ)6 als Polynom in u(θ) = sin θ+cos θund v(θ) = sin(2θ) + cos(2θ) geschrieben werden.

9.3.5. Berechnung

Wir verweisen den an Algorithmen zur Berechnung von Gröbnerbasen interessierten Lesernochmals auf die in der Einleitung erwähnte Literatur [CLO07, FSED09, EM07]. Als Ergän-zung bieter der Modul sage.rings.polynomial.toy_buchberger eine pädagogische Imple-mentierung des Buchberger-Algorithmus und weiterer damit verbundener Algorithmen, dieseiner theoretischen Beschreibung eng folgt.

10Für gegebenes k stimmt dies noch allgemeiner bei jeder Ordnung mit i ≤ k < j ⇒ xi > xj . Eine Ordnungmit dieser Eigenschaft heiÿt blockweise (siehe auch Tab. 9.5).

11Das ist deshalb eine Dreiecksform des Systems, die von den Erzeugenden des Ideals gebildet wird, wennauch in schwächerem Sinne als die in Unterabschnitt 9.2.5 denierte: a priori können wir über die Anzahlder Polynome jedes Blocks oder ihre Leitterme nichts aussagen.

211

Page 228: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Polynomiale Systeme

Wechsel der Ordnung

Die interessantesten Gröbnerbasen sind nicht die, die am einfachsten zu berechnensind: oft ist die Ordnung degrevlex am wenigsten aufwendig, doch mehr Informa-tionen entnimmt man einer lexikographischen Gröbnerbasis. Auÿerdem braucht manmanchmal Gröbnerbasen eines Ideals zu verschiedenen Ordnungen.Das motiviert zur Einführung weiterer allgemeiner Algorithmen zur Berechnung vonGröbnerbasen, sogenannten Algorithmen für den Ordnungswechsel. Sie berechnenaus einer Gröbnerbasis zu einer monomialen Ordnung zum selben Ideal eine Gröb-nerbasis zu einer anderen monomialen Ordnung. Oft sind sie ezienter als dieje-nigen, die von einem beliebigen Erzeugendensystem ausgehen. So besteht eine oft-mals fruchtbare Strategie, eine lexikographische Gröbnerbasis zu erhalten, darin, eineGröbnerbasis zur Ordnung degrevlex zu berechnen und dann ein Verfahren für denOrdnungswechsel anzuwenden.Die Methode transformed_basis ermöglicht die Berechnung von Gröbnerbasendurch Ordnungswechsel von Hand, wenn das Ideal die Ordnung null hat oder dieZielordnung lex ist. Notfalls beginnt die Methode mit der Berechnung einer Gröb-nerbasis zu der Ordnung, die zum Polynomring gehört.

Merken wir uns jedenfalls, dass die Berechnung einer Gröbnerbasis eine aufwendige Operationist, aufwendig hinsichtlich Rechenzeit und Speicherbedarf, in ungünstigen Fällen sogar sehraufwendig. Die Methode groebner_basis lässt auÿerdem zahlreiche Optionen12 zu, die demerfahrenen Anwender erlauben, einen Algorithmus zur Berechnung einer Gröbnerbasis je nachEigenart des Problems von Hand festzulegen.

Betrachten wir die Ideale Cn(K) ⊂ K[x1, . . . , xn−1], die deniert sind durch

C2(K) = 〈x0 + x1, x0x1 − 1〉C3(K) = 〈x0 + x1 + x2, x0x1 + x0x2 + x1x1, x0x1x2 − 1〉

... (9.11)

Cn(K) =⟨ ∑i∈Z/nZ

k∏j=0

xi+j

⟩n−2

k=0+ 〈x0 . . . xn−1 − 1〉,

und in Sage zu bilden durch Befehle wie

sage: from sage.rings.ideal import Cyclicsage: Cyclic(QQ['x,y,z'])Ideal (x + y + z, x*y + x*z + y*z, x*y*z - 1) ofMultivariate Polynomial Ring in x, y, z over Rational Field

Dies sind klassische Testaufgaben zur Leistungsbewertung von Werkzeugen zur Lösung poly-nomialer Systeme. Auf einer Maschine, wo Sage für die Berechnung der reduzierten Gröbner-basis von C6(Q) weniger als eine Sekunde benötigt:

sage: def C(R, n): return Cyclic(PolynomialRing(R, 'x', n))

sage: %time len(C(QQ, 6).groebner_basis())CPU times: user 0.25 s, sys: 0.01 s, total: 0.26 s

12Wegen Details siehe ihre Hilfeseite sowie diejenigen der internen Methoden des betreenden Ideals, derenNamen mit _groebner_basis beginnt.

212

Page 229: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3. Gröbnerbasen

Wall time: 0.97 s45

endet die Berechnung der Gröbnerbasis von C7(Q) nicht in einem Dutzend Stunden undbenötigt 3 Go Speicher.

Statt die Gröbnerbasis auf den rationalen Zahlen berechnen zu lassen, versuchen wir, Q durcheinen endlichen Körper Fp zu ersetzen. Die Idee, normal bei symbolischer Rechnung, ist dieEingrenzung des Aufwands der Operationen mit den Koezienten: Operationen mit den Ele-menten von Fp benötigen eine konstante Zeit, während die Anzahl der Ziern der rationalenZahlen die Tendenz hat, im Verlauf der Rechnung gewaltig anzuwachsen. Wir wählen p hin-reichend klein, damit die Rechnungen auf Fp direkt auf den ganzen Zahlen der Maschineausgeführt werden können. Doch p darf auch nicht zu klein gewählt werden, damit die Gröb-nerbasis auf Fp die Chance hat, an einem guten Teil der Struktur von Q teilzuhaben.

Mit einem vertretbaren p hat beispielsweise die Gröbnerbasis von C6(Fp) die gleiche Anzahlvon Elementen wie diejenige von C6(Q):

sage: p = previous_prime(2^30)sage: len(C(GF(p), 6).groebner_basis())45

Bei Vergröÿerung des zu behandelnden Systems sehen wir den Einuss des Koezientenkör-pers auf die Rechenzeit und der ist weit davon entfernt, vernachlässigbar zu sein: die Fällen = 7 und n = 8 werden problemlos machbar.

sage: %time len(C(GF(p), 7).groebner_basis())CPU times: user 3.71 s, sys: 0.00 s, total: 3.71 sWall time: 3.74 s209sage: %time len(C(GF(p), 8).groebner_basis())CPU times: user 104.30 s, sys: 0.07 s, total: 104.37 sWall time: 104.49 s372

Diese Beispiele illustrieren noch ein weiteres wichtiges Phänomen: die Ausgabe einer Berech-nung der Gröbnerbasis kann viel gröÿer werden als die Eingabe. Somit zeigt die letze Rechnungoben, dass jede Gröbnerbasis, reduziert oder nicht, von C8(Fp) (mit diesem Wert für p) zurOrdnung degrevlex mindestens 372 Elemente zählt, wenn C8 von nur 8 Polynomen erzeugtwird.

213

Page 230: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 231: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Betrachten Sie diese Dierentialgleichung solange,bis sich die Lösung von selbst einstellt.

George Pólya

10.1. Dierentialgleichungen

10.1.1. Einführung

Wenn die Methode von George Pólya nicht verfangen will, ziehen Sie Sage hinzu, auch wenndas Gebiet der symbolischen Lösung von Dierentialgleichungen eine Schwäche vieler Rechen-programme bleibt. Sage ist jedoch in voller Entwicklung und vergröÿert sein Leistungsspek-trum mit jeder neuen Version.

Wenn man möchte, kann man Sage aufrufen, um eine qualitative Untersuchung zu erhalten,und in der Tat leiten dann Sages numerische und grasche Werkzeuge die Intuition. Das istGegenstand von Abschnitt 14.2 des Kapitels, das der numerischen Integration gewidmet ist.Werkzeuge zur graschen Untersuchung werden in Unterabschnitt 4.1.6 angegeben. Lösungs-verfahren mit Hilfe von Reihen nden sich in Unterabschnitt 7.5.2.

Man kann die exakte Lösung von Dierentialgleichungen vorziehen. Sage kann hier zuwei-len helfen, indem es direkt eine symbolische Antwort gibt, wie wir in diesem Kapitel sehenwerden.

In den meisten Fällen muss Sage mit einer geschickten Umstellung dieser Gleichungen geholfenwerden. Vor allen Dingen muss man beachten, dass die erwartete Lösung einer Dierential-gleichung eine in einem bestimmten Intervall dierenzierbare Funktion ist, dass Sage aberAusdrücke ohne Denitionsbereich manipuliert. Die Maschine benötigt daher einen mensch-liche Eingri, um zu einer hinreichend genauen Lösung zu gelangen.

Wir werden zunächst gewöhnliche Dierentialgleichungen 1. Ordnung allgemein studieren undeinige besondere Fälle wie die linearen Gleichungen, die Gleichungen mit trennbaren Varia-blen, die homogenen Gleichungen, eine Gleichung, die von einem Parameter abhängt Un-terabschnitt 10.1.2), dann eher summarisch die Gleichungen 2. Ordnung, sowie ein Beispieleiner partiellen Dierentialgleichung (Unterabschnitt 10.1.3). Wir werden mit dem Gebrauchder Laplace-Transformation (Unterabschnitt 10.1.4) und der Lösung bestimmter Systeme vonDierentialgleichungen schlieÿen.

Wir erinnern uns, dass eine gewöhnliche Dierentialgleichung (mannchmal mit GDG abge-kürzt oder ODE auf englisch) eine Gleichung ist, in der eine (unbekannte) Funktion einerVeränderlichen auftritt sowie eine oder mehrere Ableitungen dieser Funktion.

In der Gleichung y′(x) + x · y(x) = sin(x) wird die unbekannte Funktion y die abhängige

Variable genannt und x die unabhängige Variable, mit deren Gröÿe sich y ändert.

215

Page 232: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Eine partiellen Dierentialgleichung (manchmal mit PDG abgekürzt oder PDE auf englisch)ist eine Funktion, in der mehrere unabhängige Variablen auftreten und somit auch partielleAbleitungen der abhängigen Variablen nach diesen unabhängigen Variablen.

Wenn nicht anders erwähnt, betrachten wir in diesem Kapitel Funktionen einer reellen Varia-

blen.

10.1.2. Gewöhnliche Dierentialgleichungen 1. Ordnung

Grundlegende Befehle. Wir wollen eine GDG 1. Ordnung lösen

F (x, y(x), y′(x)) = 0

Wir beginnen mit der Denition einer Variablen x und einer von ihr abhängigen Variableny:

sage: x = var('x')sage: y = function('y')(x)

Dann schreibt man

sage: desolve(gleichung, variable, ics = ..., ivar = ...,....: show_method = ..., contrib_ode = ...)

worin

- gleichung die Dierentialgleichung ist. Gleichheit wird durch == symbolisiert. Beispiels-weise wird die Gleichung y′ = 2y + x so geschrieben: diff(y,x) == 2*y + x;

- variable ist der Name der abhängigen Variablen, d.h. in y′ = 2y + x ist das die Funktiony;

- ics ist ein optionales Argument, mit dem die Anfangsbedingungen angegeben werden kön-nen. Für eine Gleichung 1. Ordnung ist das eine Liste [x0, y0], für eine Gleichung 2. Ordnungist das [x0, y0, x1, y1] oder [x0, y0, y

′0];

- ivar ist ein optionales Argument, mit dem die unabhängige Variable präzisiert werden kann,d.h. in y′ = 2y + x ist das x. Dieses Argument muss unbedingt dann angegeben werden,falls Gleichungen von Parametern abhängen wie zum Beispiel y′ = ay + bx+ c;

- show_method ist ein optionales Argument, das mit False voreingestellt ist. Andernfalls ver-langt es von Sage, das Lösungsverfahren anzugeben. Das können sein linear, separabel,exact, homogeneous, bernoulli, generalzed homogeneous. Sage gibt dann eine Liste zu-rück,deren erstes Argument die Lösung ist und deren zweites das verwendete Lösungsver-fahren;

- contrib_ode ist ein optionales Argument, das mit False voreingestellt ist. Bei True kannSage mit Gleichungen von Riccati, Lagrange, Clairaut und mit anderen pathologischenFällen umgehen.

216

Page 233: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

Gleichungen 1. Ordnung können mit Sage direkt gelöst werden. Wir werden indiesem Abschnitt studieren, wie mit Sage die linearen Gleichungen mit trennbaren Variablen,die Gleichungen von Bernoulli, die homogenen Gleichungen, die exakten Gleichungen, sowiedie Gleichungen von Riccati, Lagrange und Clairaut zu lösen sind.

Lineare Gleichungen. Dabei handelt es sich um Gleichungen des Typs

y′ = P (x)y = Q(x),

wobei es sich bei P und Q um Funktionen handelt, die auf den gegebenen Intervallen stetigsind.Beispiel: y′ + 3y = ex.

sage: x=var('x'); y = function('y')(x)

sage: desolve(diff(y,x)+3*y==exp(x), y, show_method=True)[1/4*(4*_C + e^(4*x))*e^(-3*x), 'linear']

Gleichungen mit trennbaren Variablen. Hierbei handelt es sich um Gleichungen desTyps

P (x) = y′Q(y),

wobei es sich bei P und Q um Funktionen handelt, die auf den gegebenen Intervallen stetigsind.Beispiel: yy′ = x.

sage: desolve(y*diff(y,x) == x, y, show_method=True)[1/2*y(x)^2 == 1/2*x^2 + _C, 'separable']

Achtung! Manchmal erkennt Sage nicht, dass es sich um eine Gleichung mit trennbaren Va-riablen handelt und behandlet sie als exakte Gleichungen. Beispiel: y′ = ex+y.

sage: desolve(diff(y,x) == exp(x+y), y, show_method=True)[-(e^(x + y(x)) + 1)*e^(-y(x)) == _C, 'exact']

Gleichungen von Bernoulli. Das sind Gleichungen des Typs

y′ = P (x)y = Q(x)yα,

wobei es sich bei P und Q um Funktionen handelt, die auf den gegebenen Intervallen stetigsind.Beispiel: y′ − y = xy4.

sage: desolve(diff(y,x)-y == x*y^4, y, show_method=True)[e^x/(-1/3*(3*x - 1)*e^(3*x) + _C)^(1/3), 'bernoulli']

Homogene Gleichungen. Es handelt sich um Gleichungen des Typs

y′ =P (x, y)

Q(x, y),

wobei es sich bei P und Q um Funktionen handelt, die auf den gegebenen Intervallen stetigsind.Beispiel: x2y′ = y2 + xy + x2.

sage: desolve(x^2*diff(y,x) == y^2 + x*y + x^2, y, show_method=True)[_C*x == e^(arctan(y(x)/x)), 'homogeneous']

217

Page 234: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Die Lösungen werden nicht in expliziter Form ausgegeben. Später werden wir sehen, wie wiruns in bestimmten Fällen helfen können.

Exakte Gleichungen. Es handelt sich um Gleichungen des Typs

f ′ =∂f

∂xdx+

∂f

∂ydy

mit einer dierenzierbaren Funktion f zweier Variablen.

Beispiel: y′ =cos(y)− 2x

y + x sin(y)mit f = x2 − x cos y + y2/2.

sage: desolve(diff(y,x) == (cos(y)-2*x)/(y+x*sin(y)), y,....: show_method=True)[x^2 - x*cos(y(x)) + 1/2*y(x)^2 == _C, 'exact']

Auch hier werden die Lösungen nicht explizit ausgegeben.

Gleichungen von Riccati. Es handelt sich um Gleichungen des Typs

y′ = P (x)y2 +Q(x)y +R(x),

wobei es sich bei P,Q und R um Funktionen handelt, die auf den gegebenen Intervallen stetigsind.

Beispiel: y′ = xy2 +1

xy − 1

x2.

In diesem Fall muss die Option contrib_ode auf True gesetzt werden, damit Sage mit kom-plexeren Verfahren nach einer Lösung sucht.

sage: desolve(diff(y,x) == x*y^2 + y/x - 1/x^2, y,....: contrib_ode=True, show_method=True)[1]'riccati'

Gleichungen von Lagrange und von Clairaut. Wenn die Gleichung die Form y =xP (y′) +Q(y′) hat mit auf einem bestimmten Intervall stetigen Funktionen P und Q, sprichtman von einer Lagrange-Gleichung. Ist P = 1, spricht man von einer Clairaut-Gleichung.Beispiel: y = xy′ − y′2.

sage: desolve(y == x*diff(y,x) - diff(y,x)^2, y,....: contrib_ode=True, show_method=True)[[y(x) == -_C^2 + _C*x, y(x) == 1/4*x^2], 'clairault']

Lineare Gleichung. Lösen wir beispielsweise y′ + 2y = x2 − 2x+ 3;

sage: x = var('x'); y = function('y')(x)

sage: DE = diff(y,x) + 2*y == x**2 - 2*x + 3sage: desolve(DE, y)1/4*((2*x^2 - 2*x + 1)*e^(2*x) - 2*(2*x - 1)*e^(2*x) + 4*_C+ 6*e^(2*x))*e^(-2*x)

Wir ordnen das ein wenig mit der Methode expand:

sage: desolve(DE, y).expand()1/2*x^2 + _C*e^(-2*x) - 3/2*x + 9/4

218

Page 235: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

Wir gewöhnen uns daher an, desolve(...).expand() zu schreiben. Welches Verfahren istzur Anwendung gekommen?

sage: desolve(DE, y, show_method=True)[1]'linear'

Nun wollen wir Anfangsbedingungen hinzufügen, zum Beispiel x(0) = 1:

sage: desolve(DE, y, ics=[0,1]).expand()1/2*x^2 - 3/2*x - 5/4*e^(-2*x) + 9/4

Gleichungen mit separierbaren Variablen. Untersuchen wir die Gleichungy′ ln(y) = y sin(x):

sage: x = var('x'); y = function('y')(x)sage: desolve(diff(y,x)*log(y) == y*sin(x), y, show_method=True)[1/2*log(y(x))^2 == _C - cos(x), 'separable']

Sage ist mit uns einer Meinung: das ist tatsächlich eine Gleichung mit trennbaren Variablen.

Gewöhnen wir uns an, unsere Lösungen zu benennen, damit wir sie später wiederverwendenkönnen:

sage: ed = desolve(diff(y,x)*log(y) == y*sin(x), y); ed1/2*log(y(x))^2 == _C - cos(x)

Hier ist y(x) nicht in expliziter Form gegeben:1

2∗ log(y(x))2 == _C − cos(x).

Man kann mit solve einen Ausdruck für y(x) verlangen. Wir schauen uns nun ed und ygenauer an:

sage: solve(ed, y)[y(x) == e^(-sqrt(2*_C - 2*cos(x))), y(x) == e^(sqrt(2*_C - 2*cos(x)))]

Wir müssen dabei besonders auf den Term sqrt(2*_C - 2*cos(x)) achten, auch wenn Sageuns nicht gleich warnt, müssen wir deshalb dafür sorgen, dass _C ≥ 1 bleibt.

Um das Verhalten der Kurven der Lösungen zu erhalten, müssen wir die rechte Seite der Glei-chung mit der Methode rhs() weiterverwenden. Statt beispielsweise die rechte Seite der erstenLösung nach Einsetzen von 5 für _C zu bekommen, sehen wir zunächst eine Fehlermeldung:

sage: solve(ed, y)[0].subs_expr(_C==5).rhs()-----------------------------------------------------------------------NameError Traceback (most recent call last)<ipython-input-5-77ebca8faf1a> in <module>()----> 1 solve(ed, y)[Integer(0)].subs_expr(_C==Integer(5)).rhs()

NameError: name '_C' is not defined

In der Tat haben wir _C nicht deniert. Sage hat es gemerkt. Um auf _C zugreifen zu können,müssen wir die Methode variables() verwenden, welche die Liste der in einem Ausdruckvorkommenden Variablen ausgibt.

219

Page 236: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

sage: ed.variables()(_C, x)

Nur _C und x werden also als Variablen angesehen, denn y ist als Funktion der Variablen xdeniert worden. Wir bekommen _C daher mit ed.variables()[0]:

sage: _C = ed.variables()[0]sage: solve(ed, y)[0].subs(_C == 5).rhs()e^(-sqrt(-2*cos(x) + 10))

Ein anderes Beispiel: Um den Graphen der ersten Lösung mit _C=2 zu erhalten, schreiben wirsage: plot(solve(ed, y)[0].subs(_C == 2).rhs(), x, -3. 3)

und wir erhalten

Um mehrere Kurven zu bekommen (siehe Abb. 10.1) arbeiten wir mit einer Schleife:

sage: P = Graphics()sage: for k in range(1,20,2):....: P += plot(solve(ed, y)[0].subs(_C == 1 + k/4).rhs(), x, -3, 3)sage: P

220

Page 237: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

Abb. 10.1 - Mehrere Lösungen von y′ ln y = y sin(x).

Mit zwei Schleifen könnten wir versuchen, die Bilder zweier Lösungen einzufangen,

sage: P = Graphics()sage: for j in [0, 1]:....: for k in range(1,10,2):....: f = solve(ed, y)[0].subs(_C == 2 + k/4).rhs()....: P += plot(f, x, -3, 3) sage: P

doch die Dierenz der Maÿstäbe beider Lösungen verhindert, dass man die Kurven der erstenLösung unterscheiden kann:

221

Page 238: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Übung 38. (Dierentialgleichungen mit trennbaren Variablen). Lösen Sie folgende Dieren-tialgleichungen mit trennbaren Variablen auf R:

1. (E1) :yy′√1 + y2

= sin(x); 2. (E2) : y′ =sin(x)

cos(x).

Homogene Gleichungen. Wir wollen die homogene Gleichung xy′ = y+√y2 + x2 lösen. In

der Tat ist dies eine homogene Gleichung, denn man kann sie auch so schreiben:

dy

dx=y +

√y2 + x2

x=N(y, x)

M(y, x)

oder N(ky, kx) = kN(y, x) und M(ky, kx) = kM(y, x).

Daher genügt es, diese Gleichung durch die Substitution y(x) = x ·u(x) in eine Gleichung mittrennbaren Variablen zu überführen:

sage: u = function('u')(x)sage: y = x*usage: DE = x*diff(y,x) == y + sqrt(x**2 + y**2)

Wir wenden die Substitution auf die Ausgangsgleichung an.

Da die Gleichung für x = 0 nicht deniert ist, werden wir sie auf den Intervallen ]−∞, 0[ und]0,∞[ lösen. Arbeiten wir zunächst auf ]0,∞[.

sage: assume x > 0sage: desolve(DE, u)x == _C*e^arcsinh(u(x))

Wir erhalten u nicht in expliziter Form. Um dem zu begegnen, werden wir mit dem Maxima-Befehl ev (wie evaluieren) und der Option logarc=True, die angibt, dass die Areafunktionenmit Hilfe von Logarithmen umgewandelt werden. Danach können wir u durch den Befehlsolve erhalten:

sage: S = desolve(DE, u)._maxima_().ev(logarc=True).sage().solve(u); S[u(x) == -(sqrt(u(x)^2 + 1)*_C - x)/_C]

Hier ist S eine Liste, die nur aus einer Gleichung besteht; S[0] ist daher die Gleichung selbst.

Trotzdem wird die Gleichung nicht immer explizit gelöst. Wir werden Sage ein wenig zur Handgehen, indem wir es zur Lösung der äquivalenten Gleichung

_C2(u2 + 1) = (x− u ·_C)2

mit folgenden Befehlen auordern:

sage: _C = S[0].variables()[0]sage: solu = (x-S[0]*_C)^2; solu(_C*u(x) - x)^2 == (u(x)^2 + 1)*_C^2sage: sol = solu.solve(u); sol[u(x) == -1/2*(_C^2 - x^2)/(_C*x)]

Wir müssen jetzt nur noch zurück zu y gelangen:

222

Page 239: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

sage: y(x) = x*sol[0].rhs(); y(x)-1/2*(_C^2 - x^2)/_C

Nunmehr erhalten wir die Lösungen in expliziter Form:

y(x) =x2 −_C2

2 ·_C.

Jetzt müssen die Lösungen auf ]0,∞[ noch gezeichnet werden, wobei darauf zu achten ist,dass _C nicht null wird.

sage: P = Graphics()sage: for k in range(-19,19,2):....: P += plot(y(x).subs(_C == 1/k), x, 0, 3)sage: P

Übung 39. (Homogene Dierentialgleichungen). Lösen Sie auf R folgende Dierentialglei-chung: (E3) : xyy′ = x2 + y2.

Eine Parametergleichung: das Modell von Verhulst. Die relative Rate des Wachstumseiner Bevölkerung ist eine mit der Gröÿe der Bevölkerung linear abnehmende Funktion. Beiihrer Untersuchung kann eine Gleichung der Form

y′ = ay − y2

zu lösen sein mit den positiv reellen Parametrern a und b.

sage: x = var('x'); y = function('y')(x); a, b = var('a, b')sage: DE = diff(y,x) - a*y == -b*y^ 2sage: sol = desolve(DE, [y,x]); sol-(log(b*y(x) - a) - log(y(x)))/a == _C + x

223

Page 240: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Wir erhalten damit y nicht explizit. Versuchen wir, es mit solve zu isolieren.

sage: Sol = solve(sol, y)[0]; Sollog(y(x)) == (_C + x)*a + log(b*y(x) - a)

Die explizite Lösung haben wir immer noch nicht. Wir werden die Terme auf die linke Seiteumgruppieren und diesen Ausdruck mit Hilfe von simplify_log() vereinfachen:

sage: Sol(x) = S.lhs() - Sol.rhs(); Sol(x)-(_C + x)*a - log(b*y(x) - a) + log(y(x))sage: Sol.simplify_log(); Sol(x)-(_C + x)*a + log(y(x)/(b*y(x) - a))sage: solve(Sol, y)[0].simplify()y(x) == a*e^(_C*a + a*x)/(b*e^(_C*a + a*x) - 1)

10.1.3. Gleichungen 2. Odnung

Lineare Gleichungen mit konstanten Koezienten. Lösen wir jetzt eine lineare Gleichung2. Ordnung mit konstanten Koezienten, zum Beispiel

y′′ + 3y = x2 − 7x+ 31.

Wir verwenden die gleiche Syntax wie für Gleichungen 1. Grades. Die 2. Ableitung von y nachx bekommt man mit diff(y,x,2).

sage: x = var('x'); y = function('y')(x)sage: DE = diff(y,x,2) + 3*y == x^2 - 7*x + 31sage: desolve(DE, y).expand()1/3*x^2 + _K2*cos(sqrt(3)*x) + _K1*sin(sqrt(3)*x) - 7/3*x + 91/9

Fügen wir noch Anfangsbedingungen hinzu, beispielsweise y(0) = 1 und y′(0) = 2:

sage: desolve(DE, y, ics=[0,1,2]).expand()1/3*x^2 + 13/9*sqrt(3)*sin(sqrt(3)*x) - 7/3*x - 82/9*cos(sqrt(3)*x) + 91/9

oder auch y(0) = 1 und y(−1) = 0:

sage: desolve(DE, y, ics=[0,1,-1,0]).expand()1/3*x^2 - 7/3*x - 82/9*cos(sqrt(3))*sin(sqrt(3)*x)/sin(sqrt(3)) +115/9*sin(sqrt(3)*x)/sin(sqrt(3)) - 82/9*cos(sqrt(3)*x) + 91/9

das heiÿt

1

3x2 − 7

3x− 82 sin(

√3x) cos(

√3)

9 sin(√

3)+

115 sin(√

3x)

9 sin(√

3)− 82

9cos(√

3x) +91

9.

224

Page 241: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

Lösung einer PDG: die Wärmeleitungsgleichung. Wir untersuchen die berühmte Wärme-leitungsgleichung. Die Temperatur z verteilt sich in einem geraden homogenen Stab der Längel gemäÿ der Gleichung (in der x die Abszisse längs des Stabes und t die Zeit ist):

∂2z

∂x2(x, t) = C

∂z

∂t(x, t).

Wir geben folgende Anfangs- und Randbedingungen vor:

∀t ∈ R+ : z(0, t) = 0 z(l, t) = 0 ∀x ∈]0, l[: z(x, 0 = 1).

Wir suchen die nicht verschwindenden Lösungen der Form

z(x, t) = f(x)g(t).

Dies ist das Verfahren der Trennung der Variablen:

sage: x, t = var('x, t'); f = function('f')(x); g = function('g')(x)sage: z = f*gsage: eq(x,t) = diff(z,x,2) == diff(z,t); eq(z,t)g(t)*diff(f(x), x, x) == f(x)*diff(g(t), t)

Das ist Gleichung

g(t)d2 f(x)

dx2= f(x)

d gt

d t.

Wir dividieren durch f(x)g(t), das wir ungleich null voraussetzen:

sage: eqn = eq/z; eqn(x,t)diff(f(x), x, x)/f(x) == diff(g(t), t)/g(t)

Wir bekommen dann eine Gleichung, bei der jede Seite nur von einer Variablen abhängt:

1

f(x)

d 2f(x)

dx2=

1

g(t)

d g(t)

d t.

Beide Seiten müssen konstant sein, und wir führen eine Konstante k ein:

sage: k = var('k')sage: eq1(x,t) = eqn(x,t).lhs() == k; eq2(x,t) = eqn(x,t).rhs() == k

Lösen wir jede der Gleichungen für sich und beginnen mit der zweiten;

sage: g(t) = desolve(eq2(x,t),[g,t]); g(t)_C*e^(k*t)

also ist g(t) = cekt mit einer Konstanten c.

Bei der ersten kommen wir nicht gleich weiter:

sage: desolve(eq1,[f,x])Traceback (click to the left of this block for traceback)...Is k positive, negative or zero?

Verwenden wir assume:

225

Page 242: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

sage: assume(k>0); desolve(eq1,[f,x])_K1*e^(sqrt(k)*x) + _K2*e^(-sqrt(k)*x)

Das bedeutetf(x) = k1e

x√k + k2e

−x√k.

10.1.4. Laplace-Transformation

Die Laplace-Transformation erlaubt die Umwandlung einer Dierentialgleichung mit Anfangs-bedingungen in eine algebraische Gleichung, und die Rücktransformation ermöglich dann dieRückkehr zu einer eventuell existierenden Lösung der Dierentialgleichung. Zur Erinnerung:wenn f eine auf R denierte Funktion ist, die im Intervall ]−∞, 0[ verrschwindet, dann nennenwir die unter bestimmten Bedingungen durch

L(f(x)) = F (s) =

+∞∫0

e−sxf(x) dx

denierte Funktion F die Laplace-Transformierte von f .

Leicht erhalten wir die Laplace-Transformierten von polynomialen Funktionen, von trigono-metrischen Funktionen, Exponentialfunktionen usw. Diese Transformierten haben höchst in-teressante Eigenschaften, insbesondere was die Transformierten einer Ableitung betrit: wennf ′ auf R+ stückweise stetig ist, dann ist

L(f ′(x)) = sL(f(x))− f(0),

und wenn f ′ den für f geltenden Bedingungen genügt, dann ist

L(f ′′(x)) = s2L(f(x))− sf(0)− f ′(0).

Beispiel. Wir wollen die Dierentialgleichung y′′− 3y′− 4y = sin(x) mit den Anfangsbedin-gungen y(0) = 1 und y′(0) = −1 mit Hilfe der Laplace-Transformierten lösen. Dann ist:

L(y′′ − 3y′ − 4y) = L(sin(x)),

das heiÿt:(s2 − 3s− 4)L(y)− sy(0)− y′(0) + ey(0) = L(sin(x)).

Sollten wir die Listen der Laplace-Transformierten der gängigen Funktionen vergessen haben,können wir die Transformierte des Sinus auch mit Sage nden:

sage: x, s = var('x, s'); f = function('f',x)sage: f(x) = sin(x); f.laplace(x,s)x |--> 1/(s^2 + 1)

Somit erhalten wir einen Ausdruck für die Laplace-Transformierte von y:

L(y) =1

(s2 − 3s− 4)(s2 + 1)+

s− 4

s2 − 3s− 4.

Mit Sage erhalten wir nun die Rücktransformierte:

226

Page 243: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.1. Dierentialgleichungen

sage: X(s) = 1/(s^2-3*s-4)/(s^2+1) + (s-4)/(s^2-3*s-4)sage: X(s).inverse_laplace(s, x)3/34*cos(x) + 1/85*e^(4*x) + 9/10*e^(-x) - 5/34*sin(x)

Mit etwas Schummelei können wir X(s) zunächst in einfachere Elemente zerlegen:

sage: X(s).partial_fraction()1/34*(3*s - 5)/(s^2 + 1) + 9/10/(s + 1) + 1/85/(s - 4)

Wir müssen nur noch eine Liste der Rücktransformationen zur Hand nehmen. Indessen könn-ten wir auch direkt die Blackbox desolve_laplace benutzen, die uns die Lösung sofort lie-fert:

sage: x = var('x'); y = function('y',x)sage: eq = diff(y,x,x) - 3*diff(y,x) - 4*y - sin(x) == 0sage: desolve_laplace(eq, y)1/85*(17*y(0) + 17*D[0](y)(0) + 1)*e^(4*x) + 1/10*(8*y(0) - 2*D[0](y)(0)- 1)*e^(-x) + 3/34*cos(x) - 5/34*sin(x)sage: desolve_laplace(eq, y, ics=[0,1,-1])3/34*cos(x) + 1/85*e^(4*x) + 9/10*e^(-x) - 5/34*sin(x)

10.1.5. Lineare Dierentialsysteme

Ein Beispiel eines einfachen linearen Dierentialsystems 1. Ordnung. Wir wollen dasfolgende Dierentialsystem lösen:

y′(x) = A · y(x)y(0) = c

mit

A =

2 −2 0−2 0 20 2 2

, y(x) =

y1(x)y2(x)y3(x)

, c =

21−2

.Wir schreiben:

sage: x = var('x'); y1 = function('y1', x)sage: y2 = function('y2', x); y3 = function('y3', x)sage: y = vector([y1, y2, y3])sage: A = matrix([[2,-2,0],[-2,0,2],[0,2,2]])sage: system = [diff(y[i], x) - (A * y)[i] for i in range(3)]sage: desolve_system(system, [y1, y2, y3], ics=[0,2,1,-2])[y1(x) == e^(4*x) + e^(-2*x),y2(x) == -e^(4*x) + 2*e^(-2*x),y3(x) == -e^(4*x) - e^(-2*x)]

Für die Anfangsbedingungen gilt diese Syntax: ics = [x0,y1(x0),y2(x0),y3(x0)].

227

Page 244: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Mit einer Matrix komplexer Eigenwerte. Diesmal nehmen wir

A =

[3 −41 3

], c =

[20

].

Mit Sage:

sage: x = var('x'); y1 = function('y1', x); y2 = function('y2', x)sage: y = vector([y1,y2])sage: A = matrix([[3,-4],[1,3]])sage: system = [diff(y[i], x) - (A * y)[i] for i in range(2)]sage: desolve_system(system, [y1, y2], ics=[0,2,0])[y1(x) == 2*cos(2*x)*e^(3*x), y2(x) == e^(3*x)*sin(2*x)]

kommt y1(x) = 2 cos(2x)e3x

y2(x) = sin(2x)e3x.

Ein System 2. Ordnung. Wir wollen dieses System lösen:y′′1(x)− 2y1(x) + 6y2(x)− y′1(x)− 3y′2(x) = 0y′′2(x)− 2y1(x)− 6y2(x)− y′1(x)− y′2(x) = 0

Wir führen es auf ein System 1. Ordnung zurück und setzen dazu

u = (u1, u2, u3, u4) = (y1, y2, y′1, y′2).

Dann haben wir u′1 = u3

u′2 = u4

u′3 = 2u1 − 6u2 + u3 + 3u4

u′4 = −2u1 + 6u2 + u3 − u4,

das heiÿt u′ = A · u(x) mit

A =

0 0 1 00 0 0 12 −6 1 3−2 6 1 −1

.Mit Sage:

sage: x = var('x'); u1 = function('u1', x); u2 = function('u2', x)sage: u3 = function('u3', x); u4 = function('u4', x)sage: u = vector([u1,u2,u3,u4])sage: A = matrix([[0,0,1,0],[0,0,0,1],[2,-6,1,3],[-2,6,1,-1]])sage: system = [diff(u[i], x) - (A*u)[i] for i in range(4)]sage: sol = desolve_system(system, [u1, u2, u3, u4])

Wir berücksichtigen nur die beiden ersten Komponenten, denn es sind y1 und y2, die unsinteressieren, d.h. u1 und u2:

sage: sol[0]u1(x) == 1/12*(2*u1(0) - 6*u2(0) + 5*u3(0) + 3*u4(0))*e^(2*x) +

1/24*(2*u1(0) - 6*u2(0) - u3(0) + 3*u4(0))*e^(-4*x) + 3/4*u1(0) +3/4*u2(0) - 3/8*u3(0) - 3/8*u4(0)

228

Page 245: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.2. Rekursiv denierte Folgen

sage: sol[1]u2(x) == -1/12*(2*u1(0) - 6*u2(0) - u3(0) - 3*u4(0))*e^(2*x) -

1/24*(2*u1(0) - 6*u2(0) - u3(0) + 3*u4(0))*e^(-4*x) + 1/4*u1(0) +1/4*u2(0) - 1/8*u3(0) - 1/8*u4(0)

Das kann bei guter Beobachtungsgabe zusammengefasst werden zuy1(x) = k1e

2x + k2e−4x + 3k3

y2(x) = k4e2x − k2e

−4x + k3

mit k1, k2, k3 und k4 als Parametern, die von den Anfangsbedingungen abhängen.

10.2. Rekursiv denierte Folgen

10.2.1. Durch un+1 = f(un) denierte Folgen

Denition einer Folge. Wir betrachten eine durch die Beziehung un+1 = f(un) mit u0 = arekursiv denierte Folge. Natürlich können wir die Folge mit einem rekursiven Algorithmusdenieren. Nehmen wir als Beispiel eine logistische Folge (eine durch eine Beziehung der Formxn+1 = rxn(1− xn) denierte Folge):

f : x 7→ 3.83 ·(

1− x

100000

)und u0 = 20000.

Diese Folge können wir in Sage denieren durch

DierentialgleichungenVariablendeklaration x=var('x')

Funktionsdeklaration y=function('y')(x)

Lösung einer Gleichung desolve(gleichung, y, <optionen>)

Lösung eines Systems desolve_system([gl1, ...]], [y1, ...]], <optionen>)

Anfangsbedingungen 1. Ordnung [x0, y(x0)]Anfangsbedingungen 2. Ordnung [x0, y(x0), x1, y(x1)]

[x0, y(x0), y′(x0)]Anfangsbedingungen für Systeme [x0, y1(x0), y2(x0), . . .]

unabhängige Variable ivar=x

Lösungsverfahren show_method=True

Aufruf sdpezieller Verfahren contrib_ode=True

Laplace-TransformierteTransformation einer Funktion f : x 7→ f(x) f.laplace(x,s)

Rücktransformation von X(s) X(s).inverse_laplace(s,x)

Lösung durch Laplace-Transformation desolve_laplace(gleichung,funktion)

Verschiedene BefehleAusdruck der 1. Ableitung diff(y,x)

ausmultiplizierte Form eines Ausdrucks expr.expand()

In einem Ausdruck vorkommende Variablen expr.variables()

Substitution einer Variablen expr.subs(var==val)

rechte Seite eine Gleichung gleichung.rhs()

linke Seite einer Gleichung gleichung.lhs

Tab. 10.1 - Befehle für die Lösung von Dierentialgleichungen

229

Page 246: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

sage: x = var('x'); f = function('f',x)sage: f(x) = 3.83*x*(1 - x/100000)sage: def u(n):....: if n==0: return(20000)....: else: return f(u(n-1))

Wir können eine iterative Denition vorziehen:

sage: def v(n):....: V = 20000;....: for k in [1..n]:....: V = f(V)....: return V

Graphische Darstellung. Wir können die Punkte mit den Koordinaten (k, uk) zeichnen las-sen:

sage: def wolke(u,n):....: L = [[0,u(0)]];....: for k in [1..n]:....: L += [[k,u(k)]]....: points(L).show()

Ausgehend von der folgenden Abbildung vermuten wir die Existenz von drei Häufungspunk-ten:

sage: wolke(u,50)

230

Page 247: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.2. Rekursiv denierte Folgen

Wir hätten stattdessen auch eine Darstellung wählen können, wo der Graph von f auf dieWinkelhalbierende trit. Da diese nicht von sich aus in Sage vorhanden ist, werden wir einekleine Prozedur schreiben, welche die Arbeit erledigt:

sage: def schnecke(f,x,u0,n,xmin,xmax):....: u = u0....: P = plot(x, x, xmin, xmax, color='gray')....: for i in range(n):....: P += line([[u,u],[u,f(u)],[f(u),f(u)]], color = 'red')....: u = f(u)....: P += f.plot(x, xmin, xmax, color='blue') # Courbe de f....: P.show()

Beispielsweise beobachten wir für die gleiche Folge:

sage: f(x) = 3.83*x*(1 - x/100000)sage: schnecke(f,x,20000,100,0,100000)

ebenfalls drei Häufungspunkte:

10.2.2. Lineare rekursiv denierte Folgen

Sage kann auch mit Folgen des Typs

akun+k + ak−1un+k−1 + · · ·+ a1un+1 + a0un = 0

umgehen, wobei (ai)0≤i≤k eine Familie von Skalaren ist.

231

Page 248: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10. Dierentialgleichungen und rekursiv denierte Folgen

Wir betrachen als Beispiel die Folge

u0 = −1, u1 = 1, un+2 =3

2un+1 −

1

2un.

In Sage 7 ist die bekannte Funktion rsolve nicht direkt nutzbar. Man ndet sie in Sympy,was gewisse Unanehmlichketen zur Folge hat, wie die Syntaxänderung bei der Deklarationder Variablen. Hier der nötige Vorspann für die Denition der Folge:

sage: from sympy import Function, Symbolsage: u = Function('u'); n = Symbol('n', integer=True)

Anschlieÿend muss die lineare Relation in der Form akun+k+. . .+a0un = 0 deniert werden:

sage: f = u(n+2)-(3/2)*u(n+1)+(1/2)*u(n)

Schlieÿlich rufen wir rsolve auf und achten dabei genau darauf, wie die Anfangsbedingungendeklariert werden:

sage: from sympy import rsolvesage: rsolve(f, u(n), u(0):-1,u(1):1)3 - 4*2**(-n)

das heiÿt un = 3− 12n−2 .

Bemerkung. Zu beachten sind gewisse Einschränkungen bei rsolve. Zum Beispiel wird beirekursiv denierten Folgen 2. Ordnung ein korrektes Resultat nur erhalten, wenn die charakte-ristische Gleichung zwei verschiedene reelle Wurzeln hat wie im vorstehendem Beispiel. Sonstdrückt Sage die Lösung mit Hilfe des Pochhammer-Symbols aus (RisingFactorial(x,n)),und das ist wenig ergiebig.

10.2.3. Rekursiv denierte Folgen mit zweitem Glied

Sage kann auch mit Folgen dieses Typs umgehen:

ak(n)un+k + ak−1(n)un+k−1 + . . .+ a1(n)un+1 + a− 0(n)un = f(n)

mit einer Familie von Polynomen (ai)0≤i≤k in n und einer polynomialen, einer gebrochenrationalen oder einer hypergeometrischen Funktion f vonh n.

Entsprechend der Natur von f(n) sind die Befehle verschieden:

• rsolve_poly wenn f eine Polynomfunktion ist,

• rsolve_ratio, wenn f eine gebrochen rationale Funktion ist,

• rsolve_hyper, wenn f eine hypergeometrische Funktion ist.

232

Page 249: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.2. Rekursiv denierte Folgen

Wir denieren die ai(n) als Liste [a0(n), . . . , ak−1(n), ak(n)]. Um beispielsweise die Komple-xität von Mergesort zu untersuchen, sind wir gehalten, die Folge

un+1 = 2un + 2n+2, u0 = 0

zu studieren. Die Rechnung ergibt

sage: from sympy import rsolve_hypersage: n = Symbol('n', integer=True)sage: rsolve_hyper([-2,1],2**(n+2),n)2**n*C0 + 2**(n + 2)*(C0 + n/2)

und wegen u0 = 0 ist C0=0, daher ist un = n · 2n+1.

233

Page 250: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 251: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Teil III.

Numerisches Rechnen

235

Page 252: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 253: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

In den folgenden Kapiteln stehen die Gleitpunktzahlen im Zentrum der Aufmerksamkeit. Esist sinnvoll, sie zu studieren, denn ihr Verhalten folgt genauen Regeln.

Wie sollen reelle Zahlen maschinell dargestellt werden? Da diese Zahlen im allgemeinen nichtmit einer endlichen Menge an Information kodiert werden können, sind sie auf einem Rechnernicht immer darstellbar: man muss sie also durch eine Gröÿe mit endlichem Speicherbedarfannähern.

Es hat sich zur näherungsweisen Darstellung reeller Zahlen mit einer festen Menge von Infor-mation ein Standard herausgebildet: die Gleitpunkt-Darstellung.1

In diesem Kapitel ndet man: eine summarische Beschreibung der Gleitpunktzahlen und ver-schiedener in Sage verfügbarer Typen dieser Zahlen sowie die Demonstration einiger ihrerEigenschaften. Etliche Beispiele zeigen bestimmte Schwierigkeiten, denen man beim Rechnenmit Gleitpunktzahlen begegnet, einige Knie, mit denes es gelegentlich gelingt, sie zu umschif-fen, wobei wir erwarten, dass der Leser die nötige Bedachtsamkeit entwickelt. Als Konsequenzversuchen wir einige Eigenschaften zu benennen, welche die numerischen Methoden habenmüssen, um mit diesen Zahlen verwendet werden zu können.

Für weitere Informationen kann der Leser die im Netz verfügbaren Dokumente [BZ10] und[Go191] konsultieren oder das Buch [MBdD+10].

11.1. Einführung

11.1.1. Denition

Eine Menge F (β, r,m,M) von Gleitpunktzahlen ist durch vier Parameter deniert: eine Basisβ ≥ 2, eine Anzahl von Ziern r und zwei ganze Zahlen m bzw. M . Die Elemente vonF (β, r,m,M) sind Zahlen der Form

x = (−1)s 0.d1d2 . . . dr · βj ,

worin die Ziern di ganze Zahlen sind, die 0 ≤ di < β für i ≥ 1 und 0 < d1 < β erfüllen. DieAnzahl r der Ziern ist die Genauigkeit , das Vorzeichenbit s kann 0 oder 1 sein, der Exponentj liegt zwischen den beiden ganzen Zahlen m und M und 0.d1d2 . . . dr ist die Mantisse.

1In der deutschsprachigen Literatur hält sich noch der Begri Gleitkomma, auch wenn in der Informatikgrundsätzlich der Punkt als Dezimaltrennzeichen dient und das Komma als Trennzeichen in Listen unddergleichen fungiert.

237

Page 254: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

11.1.2. Eigenschaften, Beispiele

Die Normalisierung 0 < d1 < β garantiert, dass alle Zahlen dieselbe Anzahl von signikantenZiern haben. Man bemerkt, dass die Zahl null mit der Konvention d1 > 0 nicht darstellbarist: null braucht eine spezielle Darstellung.

Als Beispiel: die −0.028 gschriebene Zahl zur Basis 10 (Festpunkt-Darstellung) wird als−0.28 · 10−1 dargestellt (vorbehaltlich natürlich, dass r ≥ 2 und m ≤ −1 ≤ M). Da zurrechnerinternen Binärdarstellung die Basis 2 dient, ist β gleich 2 in den verschiedenen vonSage angebotenen Mengen von Gleitpunktzahlen und wir werden uns daher im Verlaufe diesesKapitels immer in diesem Rahmen bewegen. Um ein Beispiel zu geben, 0.101 · 21 stellt mitden Werten aus der Menge F (2, 3,−1, 2) die Zahl 5/4 dar..

Da für β = 2 der einzige mögliche Wert von d1 gleich d1 = 1 ist, kann er in einer Maschinenim-plementierung weggelassen werden und, immer mit den Werten aus der Menge F (2, 3,−1, 2),kann beispielsweise 5/4 mit 5 bits, nämlich als 00110 maschinencodiert werden, worin dieerste Zier von links das Vorzeichen + darstellt, die beiden folgenden Ziern, nämlich 01 dieMantisse (101) und die letzten beiden Ziern den Exponenten (00 codiert den Wert −1 desExponenten, 01 den Wert 0 usw.).

Dem Leser muss völlig klar sein, dass die Mengen F (β, r,m,M) nur eine endliche Untermengeder reellen Zahlen beschreiben. Zur Darstellung einer reellen Zahl x, die zwischen zwei auf-einander folgenden Zahlen aus F (β, r,m,M) liegt, wird eine Rundung genannte Anwendungbenötigt, die festlegt, welche Zahl eine Näherung von x ist: man kann die Zahl nehmen, diex am nächsten liegt, doch sind auch andere Entscheidungen möglich; die Norm bestimmt,dass die Rundung F (β, r,m,M) unverändert lässt. Die Menge der darstellbaren Zahlen istbeschränkt, und die Mengen der Gleitpunktzahlen enthalten auch die Sonderwerte +∞ und−∞, die nicht nur unendliche Werte (wie 1/0) darstellen2, sondern auch alle Werte oberhalbder gröÿten darstellbaren positiven Zahl (oder unterhalb der kleinsten darstellbaren negativenZahl). Es gibt auch ein Zeichen zur Darstellung undenierter Operationen wie 0/0.

11.1.3. Normalisierung

Nach einigen tastenden Versuchen wird die Notwendigkeit einer Norm spürbar, damit identi-sche Programme auf vschiedenen Rechnern gleiche Resiultate liefern. Seit 1985 deniert dieNorm IEEE-7543 mehrere Zahlenmengen, darunter die in 64 Bits gespeicherten Zahlen dop-pelter Genauigkeit): Das Vorzeichen s ist mit 1 Bit codiert, die Mantisse bekommt 53 Bits(wovon nur 52 gespeichert werden), der Exponent 11 Bits. Die Zahlen haben die Gestalt

(−1)s 0.d1d2 . . . d53 · 2j−1023.

Sie entsprechen dem Typ double in C.

2Diese Festlegungen entsprechen der Norm IEEE-754.3siehe https://de.wikipedia.org/wiki/IEEE_754

238

Page 255: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.2. Die Gleitpunktzahlen

11.2. Die Gleitpunktzahlen

Sage stellt zwei Arten von Gleitpunktzahlen bereit:

1. Gleitpunktzahlen doppelter Genauigkeit, wie in 11.1.3 beschrieben: das sind die vomProzessor des Rechners gelieferten Zahlen. In Sage gehören diese Zahlen zur Klasse RDF:

sage: xrdf = RDF(3.0)

2. Gleitpunktzahlen beliebiger Genauigkeit: jede Instanz der Klasse RealField denierteine Menge von Gleitpunktzahlen gegebener Genauigkeit (und eventuell mit einem ge-gebenen Rundungsmodus: siehe 11.3.2). Um eine Zahl x100 mit 100 Bits Genauigkeitzu deklarieren, wird man beispielsweise schreiben:

sage: R100 = RealField(100) # Genauigkeit: 100 bitsage: x100 = R100(3/8); x1000.37500000000000000000000000000

Die Zahlen der Menge RealField(p) haben die Form

(−1s) 0.d1d2 . . . dp · 2e

mit s ∈ 0, 1: die Mantisse ist p Binärziern breit, und e kann 30 Bits haben (auf manchenMaschinen auch mehr). Man kann die Genauigkeit auch oen lassen:

sage: Rdefaut = RealField() # voreingestellte Genauigkeit 53 Bitssage: xdefault = Rdefault(2/3)

und man kann die Genauigkeit aller Gleitpunktzahlen mit der Methode prec()testen:

sage: xrdf.prec()53sage: x100.prec()100sage: xdefault.prec()53

Also haben die Zahlen der Menge RealField() und die der Menge RDF dieselbe Genauigkeit,doch akzeptiert RealField() auch gröÿere Exponenten. Die Menge RealField() mit derGenauigkeit 53 Bits ist in Sage der voreingestellte Typ für reelle Zahlen.

sage: x = 1.0; print type(x)<type 'sage_rings.real_mpfr.RealLiteral'>sage: x.prec()53

Hier zeigt real_mpfr.RealLiteral an, dass die Menge der Zahlen, zu der x gehört, mit derBibliothek GNU MPFR implementiert ist.

Erinnern wir uns, dass der Typ einer Zahl durch die rechte Seite einer Zuweisung automatischdeniert ist:

sage: x = 1.0 # x gehört zum RealField()sage: x = 0.1e+1 # idem: x gehört zum RealField()

239

Page 256: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

sage: x = 1 # x ist eine ganze Zahlsage: x = RDF(1) # x ist Gleitpunktzahl doppelter Maschinengenauigkeitsage: x = RDF(1.) # idem: x ist Gleitpunktzahl doppelter Genauigkeitsage: x = RDF(0.1e+1) # idemsage: x = 4/3 # x ist eine rationale Zahlsage: R = RealField(20)sage: x = R(1) # x ist Gleitpunktzahl mit 20 Bits Genauigkeit

und es werden normale Konversionen rationaler Zahlen bewerkstelligt:

sage: RDF(8/3)2.66666666667sage: R100 = RealField(100); R100(8/3)2.6666666666666666666666666667

sowie auch die Konversion zwischen Zahlen, die zu verschiedenen Mengen von Gleitpunktzah-len gehören:

sage: x = R100(8/3)sage: R = RealField(); R(x)2.66666666666667sage: RDF(x)2.66666666667

Die verschiedenen Mengen von Gleitpunktzahlen enthalten auch die speziellen Werte +0, -0,+infinity, -infinity und NaN:

sage: 1.0/0.0+infinitysage: RDF(1)/RDF(0)+infinitysage: |RDF(-1.0)/RDF(0.)|-infiniy

Der Wert NaN ist nicht denierten Ergebnissen zugeordnet.

sage: 0.0/0.0NaNsage: RDF(1)/RDF(0)NaN

x R2 RDF(x).ulp() R100(x).ulp()

10−30 3.9e-31 1.751623080406e-46 1.2446030555722283414288128108e-6010−10 2.9e-11 1.292469707114e-26 9.1835496157991211560057541970e-4110−3 0.00049 2.168404344980e-19 1.5407439555097886824447823541e-331 0.50 2.220446049260e-16 1.5777218104420236108234571306e-30103 510. 1.136868377216e-13 8.0779356694631608874161005085e-281010 4.3e9 1.907348632812e-6 1.3552527156068805425093160011e-201030 3.2e29 1.407374883554e14 1.0000000000000000000000000000

Tabelle 11.1 - Abstände zwischen Gleitpunktzahlen.

240

Page 257: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.3. Einige Eigenschaften der Gleitpunktzahlen

11.2.1. Welchen Zahlentyp wählen?

Die Gleitpunktzahlen beliebiger Genauigkeit ermöglichen Rechnungen sehr hoher Genauig-keit, während die Genauigkeit für die Zahlen RDF konstant ist. Im Gegensatz dazu rufenRechnungen mit Zahlen aus RealField die Softwarebibliothek GNU MPFR auf, sodass beiden Zahlen RDF die Rechnungen durch die Gleitpunkt-Arithmetik des Prozessors ausgeführtwerden, was erheblich schneller ist. Wir geben in 13.2.10 einen Vergleich, wo sich die Ezi-enz der Maschinenzahlen mit dem Gebrauch der für diese Zahlen optimierten Bibliothekenverbindet. Halten wir fest, dass unter den numerischen Berechnungsverfahren, denen man inden folgenden Kapiteln begegnet, viele sind, die allein die Gleitpunktzahlen RDF verwenden,und, was immer man auch tut, Gleitpunktzahlen jeweils in dieses Format konvertieren.

R2, eine Zahlenmenge zum Spielen. Die Gleitpunktzahlen beliebiger Genauigkeit, diefür Rechnungen, die hohe Genauigkeit verlangen, unersetzlich sind, erlauben daneben auchdie Denition einer Klasse von Gleitpunktzahlen, die sehr ungenau sind und deshalb quasi alsderen Karikatur Eigenschaften der Gleitpunktzahlen verdeutlichen: die Menge R2 der Zahlenmit 2 Bits Genauigkeit.

sage: R2 = RealField(2)

11.3. Einige Eigenschaften der Gleitpunktzahlen

11.3.1. Mengen voller Löcher

In jeder Menge von Gleitpunktzahlen gibt die Methode ulp() (unit in the last place) dieGröÿe des Intervalls an, das eine Zahl von der nächstgelegenen darstellbaren Zahl (in derRichtung von null weg) trennt.

sage: x2 = R2(1.); x2.ulp()0.50sage: xr = 1.; xr.ulp()2.22044604925031e-16

Der Leser wird den für x2.ulp() angegebenen Wert leicht verizieren können.

Die Tabelle 11.1 gibt die Gröÿe des Intervalls an, das eine Zahl x - oder genauer R(x), wobeiR die betrachtete Menge ist - von ihrem nächsten Nachbarn trennt (in der Richtung von nullweg) für verschiedene Zahlenmengen (R100 ist die Menge RealField(100)) und verschiedeneWerte von x.

Wie leicht zu sehen ist, wächst die Ausdehnung der Löcher , die zwei aufeinander folgendeZahlen trennen, mit der Gröÿe der Zahlen.

Übung 40 (ein etwas überraschender Wert). Zu zeigen ist, dass R100(1030).ulp() genau1.0000000000000000000000000000 ist.

241

Page 258: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

11.3.2. Das Runden

Wie ist eine Zahl anzunähern, die in einer Menge von Gleitpunktzahlen nicht enthalten ist?Man kann das Runden auf verschiedene Weisen denieren:

- zur nächstgelegenen darstellbaren Zahl hin - so wird in der Menge RDF vorgegangen unddas ist auch das voreingestellte Verhalten der mit RealField erzeugten Zahlen. Für eineZahl genau zwischen zwei darstellbaren Zahlen wird zur geraden Mantisse hin gerundet;

- in Richtung −∞; RealField(p,rnd='RNDD') ergibt dieses Verhalten mit einer Genauigkeitvon p Bits;

- in Richtung null; Beispiel: RealField(p,rnd='RNDZ');

- in Richtung +∞; Beispiel: RealField(p,rnd='RNDU'.

11.3.3. Einige Eigenschaften

Das notwendige Runden in Mengen von Gleitpunktzahlen ruft etliche gefährliche Eekte her-vor. Sehen wir uns einige davon genauer an.

Eine gefährliche Erscheinung. Hierbei handelt es sich um die als Auslöschung (engl. ca-tastrophic cancellation) bekannte Einbuÿe an Genauigkeit, die aus der Subtraktion zweierbenachbarter Zahlen folgt: genauer handelt es sich um eine Vergröÿerung der Fehler:

sage: a = 10000.0; b = 9999.5; c = 0.1; c0.100000000000000sage: a1 = a+c # a wird beeinträchtigtsage: a1-b0.600000000000364

Hier bewirkt der an a angebrachte Fehler c die ungenaue Berechnung der Dierenz (die letztendrei Stellen sind falsch).

Anwendung: Berechnung der Wurzeln eines Trinoms zweiten Grades. Sogar dieLösung einer Gleichung zweiten Grades ax2 + bx+ c = 0 kann Probleme bereiten. Betrachtenwir den Fall a = 1.0, b = 10.04, c = 1:

sage: a = 1.0; b = 10.0^4; c = 1sage: delta =b^2-4*a*csage: x = (-b-sqrt(delta)))/(2*a); y = (-b+sqrt(delta)))/(2*a)sage: x, y(-9999.99990000000, -0.000100000001111766)

Die Summe der Wurzeln ist korrekt, das Produkt aber nicht:

sage: x+x+b/a0.000000000000000sage: x*y-c/a1.11766307320238e-9

Der Fehler resultiert aus der Auslöschung, die eintritt, wenn man -b und sqrt(delta) addiert,nachdem y berechnet ist. Hier kann man eine bessere Näherung von y erzielen:

242

Page 259: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.3. Einige Eigenschaften der Gleitpunktzahlen

sage: y = (c/a)/x; y-0.000100000001000000sage: x+y+b/a0.000000000000000

Wir stellen fest, dass bei der Rundung die Summe der Wurzeln korrekt bleibt. Der Leser magalle für die Wahl von a, b und c möglichen Fälle ins Auge fassen, um sich zu überzeugen,dass das Schreiben eines robusten numerischen Programms zur Berechnung der Wurzeln einesTrinoms 2. Grades keine simple Angelegenheit ist.

Die Mengen der Gleitpunktzahlen sind bezüglich der Addition keine Gruppen. Tatsäch-lich ist die Addition nicht assoziativ. Nehmen wir die Menge R2 (mit 2 Bits Genauigkeit):

sage: x1 = R2(1/2); x2 = R2(4); x3 = R2(-4)sage: x1, x2, x3(0.50, 4.0, -4.0)sage: : x1+(x2+x3)|0.50\sage: (x1+x2)+x30.00

Daraus können wir folgern, dass die verschiedenen möglichen Reihenfolgen der Rechnungenin einem Programm nicht ohne Einuss auf das Ergebnis sind!

Rekursiv denierte Folgen mit Gleitpunktzahlen. Betrachten wir4 die rekursiv denierteFolge un+1 = 4un − 1. Für u0 = 1/3 ist die Folge stationär: ui = 1/3 für alle i.

sage: x = RDF(1/3)sage: for i in range(1,100): x = 4*x-1; print x0.3333333333330.3333333333330.333333333333...-1.0-5.0-21.0-85.0-341.0-1365.0-5461.0-21845.0...

Die berechnete Folge divergiert! Wir können erkennen, dass dieses Verhalten ziemlich selbst-verständlich ist, denn es handelt sich um eine klassische Erscheinung von Instabilität. EinFehler von u0 wird bei jeder Iteration mit 4 multipliziert, und wir wissen, dass die Gleitpunkt-arithmetik Fehler mit sich bringt, die dann bei jeder Iteration vergröÿert werden.

4Dank an Marc Deléglise (Institut Camille Jordan, Lyon) für dieses Beispiel.

243

Page 260: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

Berechnen wir nun die rekursiv denierte Folge un+1 = 3un − 1 mit u0 = 1/2. Wir erwartenein ähnliches Ergebnis: die exakt berechnete Folge ist konstant, doch ein Fehler wird bei jedemSchritt verdreifacht.

sage: x = RDF(1/2)sage: for i in range(1,100): x = 3*x-1; print x0.50.50.5...0.5

Diesmal bleibt die Folge konstant. Wie sind die unterschiedlichen Verhaltensweisen zu erklä-ren? Betrachten wir jeweils die binäre Darstellung von u0.

Im ersten Beispiel (un+1 = 4uu − 1) haben wir

1

3=

1

4

∞∑i=0

1

4i=

1

4

∞∑i=0

1

22i,

also ist 1/3 in den Mengen der Gleitpunktzahlen, über die wir verfügen (mit β = 2), nicht exaktdarstellbar, mit welcher Genauigkeit auch immer. Der Leser ist eingeladen, die vorstehendeRechnung mit Zahlen groÿer Genauigkeit, zum Beispiel aus RealField(1000) zu wiederholen,um zu verizieren, dass die berechnete Folge immer divergiert. Wir wollen erwähnen, dasswenn man im ersten Programm die Zeile

sage: x = RDF(1/3)

ersetzt durch

sage: x = 1/3,

dass dann die Rechnungen in der Menge der rationalen Zahlen ausgeführt werden und dieiterierten Werte immer 1/3 ergeben.

Im zweiten Beispiel (un+1 = 3un − 1) werden u0 und 3/2 mit der Basis 2 als 0.1 bzw.1.1 geschrieben; sie sind daher mit den verschiedenen Mengen von Gleitpunktzahlen ohneRundung exakt darstellbar. Die Rechnung ist somit genau und die Folge bleibt konstant.

Die folgende Übung zeigt, dass eine Folge, die mit einer Menge von Gleitpunktzahlen pro-grammiert ist, gegen einen falschen Grenzwert konvergieren kann.

Übung 41 (Beispiel von Jean-Michel Muller). Man betrachte die rekursiv denierte Folge(siehe [MBsD+10, S. 9]):

un = 111− 1130

un−1+

3000

un−1un−2.

Es kann gezeigt werden, dass die allgemeine Lösung diese Form hat:

un =α100n+1 + β6n+1 + γ5n+1

α100n + β6n + γ5n.

1. Man wähle u0 = 2 und u1 = −4: welches sind die Werte von α, β und γ? Gegen welchenGrenzwert konvergiert die Folge?

244

Page 261: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.3. Einige Eigenschaften der Gleitpunktzahlen

2. Die rekursiv denierte Folge ist zu programmieren (immer mit u0 = 2 und u1 = −4)mit der Menge RealField() (oder mit RDF). Was kann festgestellt werden?

3. Erläutern Sie dieses Verhalten.

4. Führen Sie die gleiche Rechnung mit einer Menge groÿer Genauigkeit aus, beispielsweisemit RealField(5000). Kommentieren Sie das Ergebnis.

5. Die Folge ist auf Q deniert. Programmieren Sie sie mit rationalen Zahlen und kom-mentieren Sie das Ergebnis.

Gleitpunktzahlen und die Summenbildung bei numerischen Reihen. Wir betrachten einereelle numerische Reihe mit dem positiven allgemeinen Term un. Die Berechnung der Partial-summen

∑mi=0 ui mit einer Menge von Gleitpunktzahlen wird durch Rundungsfehler gestört

werden. Der Leser kann sich damit vergnügen zu zeigen, dass un gegen 0 strebt, wenn n überalle Grenzen wächst, und wenn die Partialsummen im Bereich der darstellbaren Zahlen blei-ben, dann ist ab einem bestimmten m die mit Rundung berechnete Folge

∑mi=0 ui stationär

(siehe [Sch91]). Kurzum, in der Welt der Gleitpunktzahlen ist das Leben einfach: Reihen de-ren positiver allgemeiner Term gegen 0 tendiert, konvergieren unter der Bedingung, dass diePartialsummen nicht zu sehr anwachsen!

Schauen wir uns das bei der (divergenten) harmonischen Reihe mit dem Term un = 1/n an:

sage: def sumharmo(p):....: RFP = RealField(p)....: y = RFP(1.); x = RFP(0.); n = 1....: while x <> y:....: y = x; x += 1/n; n += 1....: return p, n, x

Testen wir diese Funktion mit verschiedenen Genauigkeiten p:

sage: sumharmo(2)(2, 5, 2.0)sage: sumharmo(20)(20, 131073, 12.631)

Der Leser kann mit Papier und Stift nachvollziehen, dass mit unserer Spielmenge von Gleit-punktzahlen R2 die Funktion nach 5 Iterationen gegen den Wert 2.0 konvergiert. Oenbarhängt das Ergebnis von der Genauigkeit p ab; und ebenso kann der Leser (immer mit Papierund Stift) verizieren, dass für n > βp die berechnete Summe stationär ist. Trotzdem Vor-sicht: mit der voreingestellten Genauigkeit von 53 Bits und bei 109 Operationen pro Sekundebraucht es 253/109/3600 Stunden, das sind etwa 104 Tage, bis man einen stationären Werterhält!

245

Page 262: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

Verbesserte Berechnung bestimmer rekursiv denierter Folgen. Mit einiger Vorsicht istes möglich, manche Resultate zu verbessern: hier ein Beispiel.

Häug tritt eine rekursiv denierte Folge dieser Form auf:

yn+1 = y + δn,

wobei die Zahlen δn dem absoluten Wert nach klein sind gegenüber yn: zu denken ist beispiels-weise an die Integration von Dierentialgleichungen in der Himmelsmechanik zur Simulationdes Sonnensystems, wo groÿe Werte (von Entfernungen oder Geschwindigkeiten) über langeZeiträume kleine Störungen erleiden [HLW02]. Auch wenn wir die Terme δn genau berech-nen können, führen die Rundundungsfehler bei der Addition yn+1 = y + δn zu beträchtlichenAbweichungen. Nehmen wir als Beispiel die durch y0 = 1013, δ0 = 1 und δn+1 = aδn mita = 1− 10−8 denierte Folge. Hier das naive Programm zur Berechnung von yn:

sage: def iter(y,delta,a,n):....: for i in range(0,n):....: y += delta....: delta *= a....: return y

Mit den rationalen Werten, die wir für y0, δ0 und a gewählt haben, können wir mit Sage denexakten Wert der Iterierten exakt berechnen:

sage: def exakt(y,delta,a,n):....: return y+delta*(1-a^n)/(1-a)

Berechnen wir jetzt 100000 Iterierte (zum Beispiel) mit Gleitpunktzahlen RDF und vergleichendas Ergebnis mit dem genauen Wert:

sage: y0 = RDF(10^13); delta0 = RDF(1); a = RDF(1-10^(-8)); n = 100000sage: ii = iter(y0,delta0,a,n)sage: s = exact(10^13,1,1-10^(-8),n)sage: print "exakt - klassische Summierung:", s-iiexakt - klassische Summierung: -45.498046875

Jetzt der Algorithmus für die kompensierte Summierung :

sage: def sumcomp(y,delta,e,n,a):....: for i in range(0,n):....: b = y....: e += delta....: y = b+e....: e += (b-y)....: delta = a*delta # nouvelle valeur de delta....: return y

Um dessen Verhalten zu verstehen, betrachten wir das untenstehende Schema (wir folgenhier den Darstellungen in [Hig93] und [HLW02]), worin die Kästen die Mantissen der Zahlendarstellen. Die Position der Kästen entspricht dem Exponenten (je weiter links der Kastensteht, desto gröÿer ist der Exponent):

246

Page 263: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.3. Einige Eigenschaften der Gleitpunktzahlen

b = yn b1 b2

e e1 0

δn δ1 δ2

e = e+ δn δ1 e1 + δ2

yn+1 = b+ e b1 b2 + δ1

e = e+ (b− yn+1) e1 + δ2 0

Der Rundungsfehler wird in e angesammelt, und wir stellen fest, dass keine Zier von δn ver-loren geht, während mit dem naiven Verfahren die Bits δ2 aus der Rechnung verschwinden.

Führen wir die Berechnung der 100000 Iterierten mit dem Verfahren der kompensierten Sum-mierung nochmals aus:

sage: c = sumcomp(y0,delta0,RDF(0.0),n,a)sage: print "exakt - kompensierte Summierung: %.5f" %\....: RDF(s-RR(c).exact_rational())exakt - kompensierte Summierung: -0.00042

Der absolute Fehler beträgt mit dem naiven Algorithmus −45.5, und −0.00042 mit der kom-pensierten Summierung! Nebenbei sehen wir auch, dass wir für die relativen Fehler bei naiverSummierung 4.55 · 10−12 bekommen und 4.16 · 10−17 bei kompensierter Summierung.

11.3.4. Komplexe Gleitpunktzahlen

Sage schlägt zwei Familien von komplexen Zahlen vor, die rechnerintern als Paare von Gleit-punktzahlen dargestellt werden, wie sie in den vorstehehenden Beispielen schon aufgetretensind:

1. Komplexe Zahlen doppelter Genauigkeit ComplexDoubleField (oder abgekürzt CDF). Essind Zahlen der Form x+ i · y, wobei x und y Gleitpunktzahlen doppelter Genauigkeitsind. Die Zahlen werden wie folgt erzeugt:

sage: x = CDF(2,1.); x2.0 + 1.0*Isage: y = CDF(20,0); y20.0

oder auch so:

sage: z = ComplexDoubleElement(2.,1.); z2.0 + 1.0*I

2. Komplexe Zahlen beliebiger Genauigkeit ComplexField. Das sind Zahlen der Form x+i · y, wobei x und y dieselbe Genauigkeit von p Bits besitzen. Eine Instanz der KlasseComplexField erzeugt ein Zahlenpaar gegebener Genauigkeit (voreingestellt ist 53):

sage: C = ComplexField(); C(2,3)2.00000000000000 + 3.00000000000000*Isage: C100 = ComplexField(100); C100(2,3)2.0000000000000000000000000000 + 3.0000000000000000000000000000*I

247

Page 264: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11. Gleitpunktzahlen

Wohlgemerkt, Rechnungen mit diesen Zahlen werfen die gleichen Rundungsprobleme auf wiedie mit reellen Gleitpunktzahlen.

11.3.5. Die Methoden

Wir haben bereits die Methoden prec und ulp kennengelernt. Die verschiedenenen Zahlen-mengen, denen wir hier begegnen, stellen eine groÿe Anzahl weiterer Methoden bereit. Gebenwir einige Beispiele:

- Methoden, die Konstanten zurückgeben. Beispiele:

sage: R200 = RealField(200); R200.pi()3.1415926535897932384626433832795028841971693993751058209749sage: R200.euler_constant()0.57721566490153286060651209008240243104215933593992359880577

- trigonometrische Funktionen sin, cos, arcsin, arccos usw. Beispiele:

sage: x = RDF.pi()/2; x.cos() # Gleitpunkt-Näherungswert für null!6.123233995736757e-17sage: x.cos().arccos() - x0.0

- Logarithmen (log, log10, log2 usw.), hyperbolische Winkelfunktionen und deren Inverse(sinh, arcsinh, cosh, arccosh usw.),

- spezielle Funktionen (gamma, j0, j1, jn(k) usw.)

Der Leser möge die Dokumentation von Sage konsultieren, um eine vollständige Liste der sehrzahlreichen Methoden zu bekommen, die verfügbar sind. Wir erinnern uns, dass diese Listeonline erhalten werden kann durch Eingabe von

sage: x = 1.0; x.

und ansschlieÿendes Drücken der Tabulator-Taste. Zu jeder Methode erhalten wir ihre De-nition, ihre eventuellen Parameter und ein Beispiel für die Anwendung, wenn wir eingeben(hier für die Gamma-Funktion von Euler Γ(x)):

sage: x.gamma?

Mengen der Gleitpunktzahlenreelle Zahlen mit Genauigkeit p Bits RealField(p)

Maschinen-Gleitpunktzahlen RDF

komplexe Zahlen mit Genauigkeit p Bits ComplexField(p)

komplexe Maschinenzahlen CDF

Tab. 11.2 - Zusammenfassung: Gleitpunktzahlen

248

Page 265: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.4. Schlussbemerkungen

11.4. Schlussbemerkungen

Die in Sage implantierten numerischen Verfahren, die in den folgenden Kapiteln beschrie-ben werden, sind alle theoretisch untersucht worden; ihre theoretische Analyse besteht unteranderem in der Untersuchung des Konvergenzverhaltens der iterativen Methoden, des durchVereinfachung eines Problems verursachten Fehlers, um es überhaupt berechenbar zu machen,aber auch des Verhaltens der Rrechnungen bei Auftreten von Störungen, zum Beispiel solchendie durch die ungenaue Gleitpunktarithmetik entstehen.

Betrachten wir einen Algorithmus F , der aus den Daten d das Ergebnis x = F(d) berechnet.Dieser Algorithmus wird nur brauchbar sein, wenn er die Fehler von d nicht übermäÿig ver-gröÿert; einer Störung ε von d entspricht eine gestörte Lösung xε = F(d+ε). Der entstehendeFehler xε−x muss in vernünftiger Weise von ε abhängen (er muss stetig sein, nicht zu schnellwachsen,. . . ): die Algorithmen müssen Stabilität besitzen, um brauchbar zu sein. In Kapitel13 erörtern wir die Stabilitätsprobleme der in der linearen Algebra benutzten Algorithmen.

Wir müssen auch sagen, dass bestimmte Probleme mit endlicher Genauigkeit denitiv nichtrealisierbar sind wie beispielsweise die Berechnung der in Übung 41 gegebenen Folge: jedeStörung, so klein sie auch sein mag, bewirkt die Konvergenz der Folge gegen einen falschenGrenzwert. Dies ist eine typische Erscheinung der Instabilität bei dem Problem, das wir zulösen versuchen: die experimentelle Untersuchung einer Folge mittels Gleitpunktzahlen mussmit groÿer Vorsicht erfolgen.

Der Leser kann die Praxis des Rechnens mit Gleitpunktzahlen vielleicht für honungslos hal-ten, doch dieses Urteil muss abgemildert werden: die groÿe Mehrheit der für das Rechnenverfügbaren Ressourcen wird für Operationen auf diesen Zahlenmengen benutzt: Näherungs-lösungen von partiellen Dierentialgleichungen, Optimierungen der Signalverarbeitung usw.Die Gleitpunktzahlen müssen mit Misstrauen betrachtet werden, sie haben die Entwicklungder Rechnung und deren Anwendung aber nicht verhindert: es sind nicht die Rundungsfehler,die die Zuverlässigkeit der Wettervorhersage begrenzen, um nur dieses Beispiel zu erwäh-nen.

249

Page 266: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 267: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

Dieses Kapitel erklärt, wie mit Sage eine nichtlineare Gleichung zu lösen ist. In einem erstenAbschnitt untersuchen wir polynomiale Gleichungen und zeigen die Grenzen bei der Suchenach exakten Lösungen. Danach beschreiben wir die Wirkungsweise einiger klassischer Me-thoden für eine numerischen Lösung. Dabei weisen wir darauf hin, welche Algorithmen fürdie Lösung in Sage implementiert sind.

12.1. Algebraische Gleichungen

Unter einer algebraischen Gleichung verstehen wir eine Gleichung der Form p(x) = 0, wobei pein Polynom einer Unbestimmten bezeichnet, dessen Koezienten zu einem Integritätsring Agehören. Wir sagen, dass ein Element α ∈ A eine Wurzel des Polynoms p ist, wenn p(α) = 0gilt.

Sei α ein Element von A. Die euklidsche Division von p durch p−α sichert die Existenz eineskonstanten Polynoms r, sodass gilt:

p = (x− α)q + r.

Wenn wir diese Gleichung in α auswerten, bekommen wir r = p(α). Daher wird p von demPolynom x − α genau dann geteilt, wenn α eine Wurzel von p ist. Diese Bemerkung erlaubtdie Einführung des Begris der Vielfachheit einer Wurzel α eines Polynoms: es handelt sichum die gröÿte ganze Zahl m, sodass (x − α)m p teilt. Wir stellen fest, dass die Summe derVielfachheiten aller Wurzeln von p kleiner oder gleich dem Grad von p ist.

12.1.1. Die Methode Polynomial.roots()

Die Lösung der algebraischen Gleichung p(x) = 0 besteht in der Identizierung der Wurzelndes Polynoms p mitsamt ihrer Vielfachheiten. Die Methode Polynomial.roots() liefert dieWurzeln eines Polynoms. Sie erhält bis zu drei Parameter, die alle optional sind. Der Parame-ter ring ermöglicht die Präzisierung, in welchem Ring die Wurzeln zu suchen sind. Wird fürdiesen Parameter kein Wert festgelegt, wird der Ring der Koezienten des Polynoms angenom-men. Der boolesche Wert multiplicities bezeichnet die Art der von Polynomial.roots()zurückgegebenen Informationen: jede Wurzel kann von ihrer Vielfacheit begleitet werden. DerParameter algorithm dient zur Festlegung des zu verwendenden Algorithmus; die möglichenWerte werden im weiteren Verlauf erklärt (siehe Unterabschnitt 12.2.2).

sage: R.<x> = PolynomialRing(RealField(prec=10))sage: p = 2*x^7 - 21*x^6 + 64*x^5 - 67*x^4 + 90*x^3 + 265*x^2 - 900*x + 375sage: p.roots()[(-1.7, 1), (0.50, 1), (1.7, 1), (5.0, 2)]sage: p.roots(ring=ComplexField(10), multiplicities=False)[-1.7, 0.50, 1.7, 5.0, -2.2*I, 2.2*I]

251

Page 268: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

sage: p.roots(ring=RationalField())[(1/2, 1), (5, 2)]

12.1.2. Zahlendarstellung

Erinnern wir uns, wie in Sage die gängigen Ringe bezeichnet werden (siehe Abschnitt 5.2). Dieganzen Zahlen werden durch Objekte der Klasse Integer dargestellt, und für Umwandlungenwird der Vorfahr ZZ benutzt oder die Funktion IntegerRing, der das Objekt ZZ zurückgibt.Genauso werden die rationalen Zahlen durch Objekte der Klasse Rational dargestellt; dergemeinsame Vorfahr dieser Objekte ist das Objekt QQ, das die Funktion RationalField zu-rückgibt. In beiden Fällen verwendet Sage für Rechnungen mit beliebiger Genauigkeit dieBibliothek GMP. Ohne auf Einzelheiten der Realisierung dieser Bibliothek einzugehen, sinddie mit Sage manipulierten ganzen Zahlen von beliebiger Gröÿe, die einzige Beschränkungergibt sich aus der verfügbaren Speichergröÿe der Maschine, auf der das Programm läuft.

Es stehen mehrere genäherte Darstellungen reeller Zahlen zur Verfügung (siehe Kapitel 11).Es gibt ein RealField() für Darstellungen mit Gleitpunktzahlen einer gegebener Genauigkeit,insbesondere RR mit einer Genauigkeit von 53 Bits. Es gibt aber auch RDF und die FunktionRealDoubleField() für Maschinenzahlen doppelter Genauigkeit; und dann noch die KlassenRIF und RealIntervalField, bei denen eine reelle Zahl durch ein Intervall dargestellt wird,in dem sie liegt. Die Grenzen dieses Intervalls sind Gleitpunktzahlen.

Die analogen Darstellungen von komplexen Zahlen heiÿen: CC, CDF und CIF. Auch hier istjedem Objekt eine Funktion zugeordnet; es sind ComplexField(), ComplexDoubleField, undComplexIntervalField().

Die von Polynomial.roots() ausgeführten Rechnungen sind exakt oder je nach Art derDarstellung der Koezienten des Polynoms bzw. einem eventuellen Wert des Parametersring genähert: beispielsweise sind die Rechnungen mit ZZ oder QQ exakt, mit RR genähert. Imzweiten Teil dieses Kapitels präzisieren wir den Algorithmus für die Berechnung der Wurzelnund die Rolle der Parameter ring und algorithm (siehe Abschnitt 12.2).

Die Lösung algebraischer Gleichungen ist mit dem Zahlbegri eng verbunden. Der Zerle-

gungskörper des Polynoms p (als nicht konstant vorausgesetzt) ist die kleinste Erweiterungdes Körpers der Koezienten von p, worin p ein Produkt der Polynome 1. Grades ist; wirzeigen, dass eine solche Erweiterung immer existiert. Mit Sage können wir den Zerlegungskör-per eines irreduziblen Polynoms mit der Methode Polynomial.root_field() bilden. Danachkönnen wir mit den im Zerlegungskörper implizit enthaltenen Wurzeln rechnen.

sage: R.<x> = PolynomialRing(QQ, 'x')sage: p = x^4 + x^3 + x^2 + x + 1sage: K.<alpha> = p.root_field()sage: p.roots(ring=K, multiplicities=None)[alpha, alpha^2, alpha^3, -alpha^3 - alpha^2 - alpha - 1]sage: alpha^51

252

Page 269: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.1. Algebraische Gleichungen

12.1.3. Der Gauÿ-d'Alembertsche Fundamentalsatz der Algebra

Der Zerlegungskörper des Polynoms mit reellen Koezienten x2 + 1 ist nichts anderes alsder Körper der komplexen Zahlen. Es ist bemerkenswert, dass jedes nicht konstante Polynommit komplexen Koezienten mindestens eine komplexe Wurzel besitzt: das besagt der Funda-mentalsatz der Algebra. In der Konsequenz ist jedes komplexe, nicht konstante Polynom einProdukt von Polynomen 1. Grades. Etwas weiter oben haben wir bemerkt, dass die Summeder Vielfachheiten der Wurzeln eines Polynoms p kleiner oder gleich dem Grad von p ist. Wirwissen jetzt, dass im Körper der komplexen Zahlen diese Summe genau gleich dem Grad vonp ist. Anders gesagt besitzt jede polynomiale Gleichung n-ten Grades n komplexe Wurzeln,die samt ihrem Vielfachheiten gezählt werden.

Schauen wir einmal, wie die Methode Polynomial.roots() dieses Resultat zu illustrieren ver-mag. Im folgenden Beispiel bilden wir den Ring der Polynome mit reellen Koezienten (wirbegnügen uns mit einer Darstellung, die mit Gleitpunktzahlen der Genauigkeit 53 Bit arbei-tet). Dann wird aus diesem Ring ein Polynom mit einem Grad unter 15 zufällig ausgewählt.Schlieÿlich summieren wir Vielfachheiten der mit der Methode Polynomial.roots() berech-neten komplexen Wurzeln auf und vergleichen diese Summe mit dem Grad des Polynoms.

sage: R.<x> = PolynomialRing(RR, 'x')sage: d = ZZ.random_element(1, 15)sage: p = R.random_element(d)sage: p.degree() == sum(r[1] for r in p.roots(CC))True

12.1.4. Verteilung der Wurzeln

Wir fahren fort mit einer überraschenden Demonstration der Leistungsfähigkeit der MethodePolynomial.roots: wir zeichnen alle Punkte der komplexen Ebene, deren Zahlenwert Wurzeleines Polynoms 12. Grades mit den Koezienten 1 oder −1 ist. Die Wahl des Grades istein mehr oder weniger willkürlicher Kompromiss; wir erhalten damit eine genaue Zeichnungin annehmbarer Zeit. Der Gebrauch von Näherungswerten für die komplexen Zahlen erfolgtebenfalls aus Leistungsgründen (siehe Kapitel 13).

Abb. 12.1 - Verteilung der Wurzeln aller Polynome 12. Grades mit Koezienten 1 oder −1.

253

Page 270: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

sage: def build_complex_roots(degree):....: R.<x> = PolynomialRing(CDF, 'x')....: v = []....: for c in cartesian_product([[-1, 1]] * (degree + 1)):....: v.extend(R(list(c)).roots(multiplicities=False))....: return vsage: data = build_complex_roots(12)sage: points(data, pointsize=1, aspect_ratio=1)

12.1.5. Lösung durch Wurzelausdrücke

In bestimmten Fällen ist es möglich, die exakten Werte der Wurzeln eines Polynoms zu be-rechnen. Das ist beispielsweise der Fall, sobald man die Wurzeln als Funktion der Koezientenoder durch Wurzelausdrücke (Quadratwurzeln, Kubikwurzeln usw.) ausdrücken kann. In sol-chen Fällen sprechen von Lösung durch Wurzelausdrücke.

Um diesen Lösungstyp mit Sage auszuführen, müssen wir mit Objekten der Klasse Expressionarbeiten, die symbolische Ausdrücke darstellen. Wir haben gesehen, dass die durch Objekte derKlasse Integer dargestellten ganzen Zahlen denselben Vorfahr haben, nämlich das Objekt ZZ.Ebenso haben die Objekte der Klasse Expression einen gleichen Vorfahr: es handelt sich umdas Objekt SR (kurz für Symbolic Ring); er bietet nicht zuletzt Möglichkeiten der Konversionzur Klasse Expression.

Quadratische Gleichungen.

sage: a, b, c, x = var('a, b, c, x')sage: p = a * x^2 + b * x + csage: type(p)<type 'sage.symbolic.expression.Expression'>sage: p.parent()sage: Symbolic Ringsage: p.roots(x)[(-1/2*(b + sqrt(b^2 - 4*a*c))/a, 1),(-1/2*(b - sqrt(b^2 - 4*a*c))/a, 1)]

Ein Grad gröÿer als 2. Es ist auch möglich, komplexe algebraische Gleichungen 3. und4. Grades mit Wurzelausdrücken zu lösen. Umgekehrt ist es unmöglich, polynomiale Glei-chungen höheren als 4. Grades mit Wurzelausdrücken zu lösen (siehe Unterabschnitt 7.3.4).Diese Unmöglichkeit lässt uns numerische Lösungsverfahren ins Auge fassen (siehe Abschnitt12.2).

sage: a, b, c, d, e, f, x = var('a, b, c, d, e, f, x')sage: p = a*x^5+b*x^4+c*x^3+d*x^2+e*x+fsage: p.roots(x)Traceback (most recent call last):...RuntimeError: no explicit roots found

254

Page 271: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.1. Algebraische Gleichungen

Wir wollen mit Sage ein Lösungsverfahren für Gleichungen 3. Grades auf dem Körper derkomplexen Zahlen vorführen. Zuerst zeigen wir, dass sich die allgemeine Gleichung 3. Gradesauf die Form x3 + px+ q = 0 zurückführen lässt.

sage: x, a, b, c, d = var('x, a, b, c, d')sage: P = a * x^3 + b * x^2 + c * x + dsage: alpha = var('alpha')sage: P.subs(x = x + alpha).expand().coefficient(x, 2)3*a*alpha + bsage: P.subs(x = x - b / (3 * a)).expand().collect(x)a*x^3 - 1/3*(b^2/a - 3*c)*x + 2/27*b^3/a^2 - 1/3*b*c/a + d

Um die Wurzeln einer Gleichung der Form x3 +px+q = 0 zu erhalten, setzen wir x = u+v.

sage: p, q, u, v = var('p, q, u, v')sage: P = x^3 + p * x + qsage: P.subs(x = u + v).expand()u^3 + 3*u^2*v + 3*u*v^2 + v^3 + p*u + p*v + q

Wir nehmen den letzten Ausdruck gleich null an. Wir sehen dann, dass u3 + v3 + q = 0 gleich3uv + p = 0 ist; und weiter, wenn die Gleichheit veriziert ist, sind u3 und v3 Wurzeln einerGleichung 2. Grades: (X − u3)(X − v3) = X2 − (u3 + v3)X + (uv)3 = X2 + qX − p3/27.

sage: P.subs(x: u + v, q: -u^3 - v^3).factor()sage: (3*u*v + p)*(u + v)sage: P.subs(x: u+v, q: -u^3 - v^3, p: -3 * u * v).expand()0sage: X = var('X')sage: solve([X^2 + q*X - p^3 / 27 == 0], X, solution_dict=True)[X: -1/2*q - 1/18*sqrt(12*p^3 + 81*q^2),X: -1/2*q + 1/18*sqrt(12*p^3 + 81*q^2)]

Die Lösungen der Gleichung x3 + px + q = 0 sind daher die Summen u + v, wobei u und vdie Kubikwurzeln sind von

−√

4p3 + 27q2√

3

18− q

2und

√4p3 + 27q2

√3

18− q

2

was 3uv + p = 0 veriziert.

12.1.6. Die Methode Expression.roots()

Die vorstehenden Beispiele verwenden die Methode Expression.roots(). Diese Methodegibt eine Liste mit exakten Wurzeln zurück, doch ohne die Garantie, tatsächlich alle zu n-den. Unter den optionalen Parametern dieser Methode ndet man die Parameter ring undmultiplicities, die uns schon bei der Methode Polynomial.roots() begegnet sind. Es istwichtig, sich daran zu erinnern, dass die Methode Expression.roots() nicht allein auf poly-nomiale Ausdrücke angewendet wird.

sage: e = sin(x) * (x^3 + 1) * (x^5 + x^4 + 1)sage: roots = e.roots(); len(roots)9sage: roots

255

Page 272: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

[(0, 1),(-1/2*(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)*(I*sqrt(3) + 1)- 1/6*(-I*sqrt(3) + 1)/(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3), 1),(-1/2*(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)*(-I*sqrt(3) + 1)- 1/6*(I*sqrt(3) + 1)/(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3), 1),((1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3) + 1/3/(1/18*sqrt(23)*sqrt(3)- 1/2)^(1/3), 1),(-1/2*I*sqrt(3) - 1/2, 1), (1/2*I*sqrt(3) - 1/2, 1),(1/2*I*sqrt(3)*(-1)^(1/3) - 1/2*(-1)^(1/3), 1),(-1/2*I*sqrt(3)*(-1)^(1/3) - 1/2*(-1)^(1/3), 1), ((-1)^(1/3), 1)]

Da in Sage der Parameter ring nicht deniert ist, delegiert die Methode roots() der Klas-se Expression die Berechnung der Wurzeln an das Programm Maxima, das den Ausdruckzu faktorisieren sucht, um dann eine Lösung mit Wurzelausdrücken für jeden Faktor auszu-geben, dessen Grad kleiner ist als 5. Wenn der Parameter ring deniert ist, wird der Aus-druck in ein Objekt der Klasse Polynomial konvertiert, dessen Koezienten als Vorfahr dasdurch den Parameter ring festgelegte Objekt haben; danach wird das Resultat der MethodePolynomial.roots() zurückgegeben. Im weiteren Verlauf werden wir den hier verwendetenAlgorithmus beschreiben (siehe Unterabschnitt 12.2.2).

Wir stellen ebenfalls Rechenbeispiele mit impliziten Wurzeln vor, zu denen wir über die Ob-jekte QQbar und AA gelangen, welche den Körper der algebraischen Zahlen darstellen (sieheUnterabschnitt 7.3.2).

Elimination von Mehrfachwurzeln. Ist ein Polynom p mit Mehrfachwurzeln gegeben, dannkann ein Polynom mir Einfachwurzeln (d.h. mit der Vielfachheit 1) gebildet werden, das mit pidentisch ist. Wenn wir also die Wurzeln eines Polynoms berechnen, können wir immer davonausgehen, dass die Wurzeln einfach sind. Weisen wir nun die Existenz eines Polynoms mitEinfachwurzeln nach und sehen wir zu, wie es gebildet wird. Das gestattet uns, eine neueVeranschaulichung der Methode Expression.roots() zu geben.

Sei α eine Wurzel des Polynoms p, deren Vielfachheit m eine Zahl gröÿer als 1 ist. Das ist eineWurzel des abgeleiteten Polynoms p′ mit der Vielfachheitm−1. In der Tat, wenn p = (x−α)mqist, dann haben wir p′ = (x− α)m−1(mq + (x− α)q′).

sage: alpha, m, x = var('alpha, m, x'); q = function('q')(x)sage: p = (x - alpha)^m * qsage: p.derivative(x)(-alpha + x)^(m - 1)*m*q(x) + (-alpha + x)^m*diff(q(x), x)sage: simplify(p.derivative(x)(x=alpha))0

In der Konsequenz ist der ggT von p und p′ das Produkt∏α∈Γ(x − α)mα−1 mit Γ als der

Menge der Wurzeln von p mit einer Vielfachheit gröÿer als 1, und mα ist die Vielfachheit derWurzel α. Wenn d diesen ggT bezeichnet, dann hat der Quotient p durch d die erwartetenEigenschaften.

Wir bemerken, dass der Grad des Quotienten von p durch d kleiner als der Grad von p ist.Wenn insbesondere der Grad kleiner ist als 5, dann ist es möglich, die Wurzeln des Polynomsmit Wurzelausdrücken anzugeben. Das folgende Beispiel veranschaulicht dies für ein Polynom13. Grades mit rationalen Koezienten.

256

Page 273: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

sage: R.<x> = PolynomialRing(QQ, 'x')p = 128 * x^13 - 1344 * x^12 + 6048 * x^11 - 15632 * x^10 \....: + 28056 * x^9 - 44604 * x^8 + 71198 * x^7 - 98283 * x^6 \....: + 105840 * x^5 - 101304 * x^4 + 99468 * x^3 - 81648 * x^2 \....: + 40824 * x - 8748sage: d = gcd(p, p.derivative())sage: (p // d).degree()4sage: roots = SR(p // d).roots(multiplicities=False)sage: roots[1/2*I*sqrt(3)*2^(1/3) - 1/2*2^(1/3),-1/2*I*sqrt(3)*2^(1/3) - 1/2*2^(1/3), 2^(1/3), 3/2]sage: [QQbar(p(alpha)).is_zero() for alpha in roots][True, True, True, True]

12.2. Numerische Lösung

In der Mathematik ist es Tradition, diskret und kontinuiertlich gegenüberzustellen. Die nume-rische Analyse relativiert diesen Gegensatz auf gewisse Art: ein wichtiger Aspekt der numeri-schen Analyse besteht tatsächlich darin, sich Fragen bezüglich der reellen Zahlen zuzuwenden,im Kern also dem Kontinuum, indem wir einen experimemtellen Standpunkt einnehmen, dersich auf den Rechner stützt, der seinerseits vom Diskreten abhängt.

Wenn es um das Lösen von nichtlinearen Gleichungen geht, stellt sich natürlich auÿer derBerechnung von Näherungswerten der Lösung eine Reihe von Fragen: wieviele reelle Wurzelnbesitzt eine gegebene Gleichung? Wieviele imaginäre, positive oder negative?

Im Folgenden beginnen wir damit, Teilantworten zu Sonderfällen algebraischer Gleichungen zugeben. Danach beschreiben wir einige Approximationsverfahren, mit denen Näherungswertevon Lösungen einer nichtlinearen Gleichung berechnet werden können.

12.2.1. Lokalisierung der Lösungen algebraischer Gleichungen

Vorzeichenregel von Descartes. Die Regel von Descartes besagt, dass die Anzahl der posi-tiven Wurzeln eines Polynoms mit reellen Koezienten kleiner ist oder gleich der Anzahl derVorzeichenwechsel in der Folge der Koezienten des Polynoms.

sage: R.<x> = PolynomialRing(RR, 'x')sage: p = x^7 - 131/3*x^6 + 1070/3*x^5 - 2927/3*x^4 \....: + 2435/3*x^3 - 806/3*x^2 + 3188/3*x - 680sage: sign_changes = \....: [p[i] * p[i + 1] < 0 for i in range(p.degree())].count(True)sage: real_positive_roots = \....: sum([alpha[1] if alpha[0] > 0 else 0 for alpha in p.roots()])sage: sign_changes, real_positive_roots(7, 5)

Seien nun p ein Polynom mit reellen Koezienten vom Grad d und p′ das abgeleitete Polynom.Wir bezeichnen mit u und u′ die Folgen der Vorzeichen der Koezienten der Polynome p und

257

Page 274: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

p′: wir haben ui = ±1, je nachdem, ob der Koezient des Grades i positiv oder negativ ist.Die Folge u′ ergibt sich aus u durch einfaches Abschneiden: wir bekommen u′i = ui+1 für0 ≤ i < d. Daraus folgt, dass die Anzahl der Vorzeichenwechsel der Folge u höchsten gleichder Anzahl der Vorzeichenwechsel der Folge ′ plus 1 ist.

Auÿerdem ist die Anzahl der positiven Wurzeln von p höchstens gleich der Anzahl positiverWurzeln von p′ plus 1: ein Intervall, dessen Grenzen Wurzeln von p sind, enthält immer eineWurzel von p′.

Da die Regel von Descartes auch für ein Polynom 1. Grades richtig ist, zeigen die beidenvorstehenden Beobachtungen, dass sie auch für ein Polynom 2. Grades stimmt usw.

Es ist möglich, die Beziehung zwischen den Anzahlen positiver Wurzeln und der Anzahl derVorzeichenwechsel der Folge der Koezienten zu präzisieren: die Dierenz dieser beiden Zahlenist immer gerade.

Isolation der reellen Wurzeln der Polynome. Wir haben gesehen, dass man bei Polynomenmit reellen Koezienten eine Obergrenze der im Intervall [0,∞[ enthaltenen Wurzeln be-stimmen kann. Noch allgemeiner, es gibt Mittel, die Anzahl der Wurzeln in einem gegebenenIntervall zu präzisieren.

Nehmen wir beispielsweise den Satz von Sturm. Seien p ein Polynom mit reellen Koezienten,d dessen Grad und [a, b] ein Intervall. Rekursiv bilden wir eine Folge von Polynomen. AmAnfang seien p0 = p und p1 = p′. Dann ist pi+2 das Negative des Restes der euklidschenDivision von pi durch pi+1. Wenn wir diese Folge von Polynomen an den Stellen a und bauswerten, erhalten wir zwei endliche reelle Folgen (p0(a), . . . , pd(a)) und (p0(b), . . . , pd(b)).Der Satz von Sturm besagt: die Anzahl der Wurzeln von p im Intervall [a, b] ist gleich derAnzahl der Vorzeichenwechsel der Folge (p0(a), . . . , pd(a)) vermindert um die Anzahl derVorzeichenwechsel der Folge (p0(b), . . . , pd(b)) unter der Annahme, dass die Wurzeln von peinfach sind sowie p(y) 6= 0 und p(b) 6= 0.

Wir zeigen, wie dieser Satz mit Sage implementiert wird.

sage: def count_sign_changes(p):....: l = [c for c in p if not c.is_zero()]....: changes = [l[i]*l[i + 1] < 0 for i in range(len(l) - 1)]....: return changes.count(True)

sage: def sturm(p, a, b):....: assert p.degree() > 2....: assert not (p(a) == 0)....: assert not (p(b) == 0)....: assert a <= b....: remains = [p, p.derivative()]....: for i in range(p.degree() - 1):....: remains.append(-(remains[i] % remains[i + 1]))....: evals = [[], []]....: for q in remains:....: evals[0].append(q(a))....: evals[1].append(q(b))....: return count_sign_changes(evals[0]) - count_sign_changes(evals[1])

258

Page 275: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

Hier nun eine Illustration dieser Funktion sturm().

sage: R.<x> = PolynomialRing(QQ, 'x')sage: p = (x - 34) * (x - 5) * (x - 3) * (x - 2) * (x - 2/3)sage: sturm(p, 1, 4)2sage: sturm(p, 1, 10)3sage: sturm(p, 1, 200)4sage: p.roots(multiplicities=False)[34, 5, 3, 2, 2/3]sage: sturm(p, 1/2, 35)5

12.2.2. Verfahren der sukzessiven Approximation

Der Begri der Approximation ist von fundamentaler Bedeutung für das Verständ-

nis der Beziehung zwischen Realität und wissenschaftlicher Modellbildung. Schon

der Versuch, Aspekte der Wirklichkeit in einer Theorie zu erklären, bedeutet die

Vernachlässigung gewisser für die spezielle Fragestellung nicht so wesentlicher Ein-

zelheiten. Nur die Wirklichkeit selbst beschreibt die Wirklichkeit vollständig, jedes

Modell leistet dies nur approximativ.

Walter Trockel, Ein mathematischer Countdown zurWirtschaftswissenschaft1

In diesem Unterabschnitt veranschaulichen wir verschiedene Verfahren der Approximation andie Lösungen einer nichtlinearen Gleichung f(x) = 0. Es gibt im wesentlichen zwei Vorgehens-weisen zur Berechnung solcher Näherungen. Der leistungsfähigste Algorithmus kombiniert siebeide.

Bei der ersten Vorgehensweise bilden wir eine Folge von geschachtelten Intervallen, die eineLösung der Gleichung enthalten. Wir steuern die Genauigkeit, die Kovergenz ist gesichert,doch ist die Konvergenzgeschwindigkeit nicht immer gut.

Die zweite Vorgehensweise nimmt einen Näherungswert einer Lösung als bekannt an. Wenn daslokale Verhalten der Funktion f hinreichend gleichförmig ist, können wir einen neuen Nähe-rungswert berechnen, der näher an der Lösung liegt. Durch Rekursion bekommen wir deshalbeine Folge von Näherungswerten. Diese Vorhensweise setzt also eine erste Approximation andie gesuchte Zahl als bekannt voraus. Auÿerdem hängt ihre Ezienz vom lokalen Verhaltender Funktion f ab. Von vornherein beherrschen wir die Genauigkeit der Näherungswerte nicht;aber schlimmer noch, die Konvergenz der Folge der Näherungswerte ist nicht garantiert.

Im Folgenden betrachten wir eine nichtlineare Gleichung f(x) = 0, wobei f eine numerischeFunktion bezeichnet, die auf einem Interval [a, b] deniert und stetig ist. Wir setzen voraus,dass die Funktion an den Grenzen des Intervalls nicht verschwindet, sondern verschiedene

1Im Original heiÿt es:Approximation: Gén. au sing. Opération par laquelle on tend à se rapprocher de plus en plus de la valeur

réelle d'une quantité ou d'une grandeur sans y parvenir rigoureusement.

Trésor de la Langue Française

259

Page 276: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

Vorzeichen hat: anders gesagt, das Produkt f(a)f(b) ist negativ. Die Stetigkeit von f sichertdann die Existenz von mindestens einer Lösung der Gleichung f(x) = 0.

Bei jedem Verfahren experimentieren wir mit folgender Funktion:

sage: f(x) = 4 * sin(x) - exp(x) / 2 + 1sage: a, b = RR(-pi), RR(pi)sage: bool(f(a) * f(b) < 0)True

Der Hinweis ist angebracht, dass bei diesem Beispiel der Befehl solve nicht von Nutzen ist.

sage: solve(f(x) == 0, x)[sin(x) == 1/8*e^x - 1/4]sage: f.roots()Traceback (most recent call last):...RuntimeError: no explicit roots found

Die Algorithmen zur Suche von Lösungen nichtlinearer Gleichungen können aufwendig sein:zweckmäÿigerweise trit man vor der Programmausführung einige Vorsichtsmaÿnahmen. Wirversichern uns der Existenz von Lösungen, indem wir Stetigkeit und Dierenzierbarkeit derFunktion prüfen, die gleich null gesetzt werden soll, sowie auch eventueller Vorzeichenwechsel.Dafür kann die Zeichnung des Graphen eine Hilfe sein (siehe Kapitel 4).

Abb. 12.2 - Graph der Funktion f .

260

Page 277: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

Die Bisektion. Dieses Verfahren beruht auf der ersten Vorgehensweise: dabei ist eine Folgevon geschachtelten Intervallen zu bilden, von denen jedes eine Lösung der Gleichung f(x) = 0enthält.

Wir teilen das Intervall [a, b] an seiner Mitte, die wir c nennen. Wir nehmen f(c) 6= 0 an(andernfalls haben wir schon eine Lösung gefunden). Ist f(a)f(c) kleiner als null, enthält dasIntervall [a, c] notwendigerweise eine Lösung der Gleichung; ist f(c)f(b) kleiner als null, dannenthält das Intervall [b, c] eine Lösung der Gleichung. So können wir ein Intervall nden, daseine Lösung enthält und dessen Länge nur halb so groÿ ist wie das Intervall [a, b]. DurchWiederholung dieses Schrittes erhalten wir eine Folge von Intervallen mit den erwartetenEigenschaften. Um dieses Vorgehensweise ins Werk zu setzen, denieren wir die Python-Funktion intervalgen:

sage: def phi(s, t): return (s + t) / 2sage: def intervalgen(f, phi, s, t):....: msg = 'Wrong arguments: f(0)*f(1)>=0)'.format(s, t)....: assert (f(s) * f(t) < 0), msg....: yield s....: yield t....: while True:....: u = phi(s, t)....: yield u....: if f(u) * f(s) < 0:....: t = u....: else:....: s = u

Die Denition dieser Funktion verdient einige Erläuterungen. Die Anwesenheit des Schlüssel-wortes yield in der Denition von intervalgen macht daraus einen Generator (siehe Unter-abschnitt 15.2.4). Bei einem Aufruf der Methode next eines Generators werden alle lokalenDaten gesichert, wenn der Interpreter auf das Schlüsselwort yield trit, die Ausführung wirdunterbrochen, und der unmittelbar rechts vom Schlüsselwort stehende Ausdruck wird zurüch-gegeben. Der auf die Methode next folgende Aufruf fährt mit der Anweisung fort, die demSchlüsselwort yield folgt und den lokalen Daten, die vor der Unterbrechung gesichert wor-den sind. In einer Endlosschleife (while True:) erlaubt das Schlüsselwort yield daher diePrgrammierung einer rekursiv denierten Folge mit eine Syntax, die ihrer mathematischenBeschreibung nahe ist. Die Ausführung kann mit dem üblichen Schlüsselwort return beendetwerden.

Der Parameter phi stellt eine Funktion dar. Für das Verfahren der Bisektion berechnet dieseFunktion die Mitte eines Intervalls. Um ein anderes Verfahren der sukzessiven Approximati-on zu testen, das ebenfalls auf der Bildung geschachtelter Intervalle basiert, geben wir eineneue Denition der Funktion phi an und bilden mit der Funktion intervalgen wieder denentsprechenden Generator.

Die Parameter s und t der Funktion stehen für die Grenzen des ersten Intervalls. Ein Aufrufvon assert prüft, ob die Funktion f zwischen den Grenzen des Intervalls das Vorzeichenwechselt; wir wissen, dass gegebenenfalls eine Lösung existiert.

Die beiden ersten Werte des Generators entsprechen den Parametern s und t. Der dritteWert ist die Mitte des jeweiligen Intervalls. Danach repräsentieren die Parameter s und tdie Grenzen des zuletzt berechneten Intervalls. Nach Auswertung von f in der Mitte dieses

261

Page 278: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

Intervalls ändern wir eine Grenze des Intervalls so ab, dass das neue Intervall wieder eineLösung enthält. Als Näherungswert der gesuchten Lösung bietet sich die Mitte des zuletztberechneten Intervalls an.

Experimentieren wir mit unserem Beispiel: es folgen drei Approximationen mit dem Verfahrender Bisektion, das auf das Intervall [−π, π] angewendet wird.

sage: a, b(-3.14159265358979, 3.14159265358979)sage: bisection = intervalgen(f, phi, a, b)sage: bisection.next()-3.14159265358979sage: bisection.next()3.14159265358979sage: bisection.next()0.000000000000000

Um die verschiedenen Näherungsverfahren zu vergleichen, ist es sinnvoll, über einen Mecha-nismus zu verfügen, der die Berechnung des Näherungswertes einer Lösung der Gleichungf(x) = 0 mit Hilfe von mit Sage für jedes dieser Verfahren denierten Generatoren automa-tisiert. Dieser Mechanismus muss die Steuerung der Rechengenauigkeit und der Maximalzahlder Iterationen ermöglichen. Das ist die Aufgabe der Funktion iterate, deren Denition hierfolgt.

sage: from types import GeneratorType, FunctionTypesage: def checklength(u, v, w, prec):....: return abs(v - u) < 2 * precsage: def iterate(series, check=checklength, prec=10^-5, maxit=100):....: assert isinstance(series, GeneratorType)....: assert isinstance(check, FunctionType)....: niter = 2....: v, w = series.next(), series.next()....: while niter <= maxit:....: niter += 1....: u, v, w = v, w, series.next()....: if check(u, v, w, prec):....: print 'After 0 iterations: 1'.format(niter, w)....: return....: print 'Failed after 0 iterations'.format(maxit)

Der Parameter series muss ein Generator sein. Wir speichern die letzten drei Werte diesesGenerators, damit wir einen Konvergenztest machen können. Das ist die Aufgabe des Parame-ters check: eine Funktion, die die Iterationen notfalls beendet. In der Voreinstellung benutztdie Funktion iterate die Funktion checklength, die die Iterationen abbricht, wenn das letzteberechnete Intervall kleiner ist als das Doppelte des Parameters prec; das garantiert, dass dermit dem Verfahren der Bisektion berechnete Wert ein Näherungswert ist mit einem Fehler,der kleiner ist als prec.

Sobald die Anzahl der Iterationen den Parameter maxit übersteigt, wird eine Exzeption aus-gelöst.

262

Page 279: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

sage: bisection = intervalgen(f, phi, a, b)sage: iterate(bisection)After 22 iterations: 2.15847275559132

Übung 42. Die Funktion intervalgen ist so zu modizieren, dass der Generator anhält,wenn eine der Intervallgrenzen verschwindet.

Übung 43. Programmieren Sie mit den Funktionen intervalgen und iterate die Berech-nung eines Näherungswertes einer Lösung der Gleichung f(x) = 0 mit verschachtelten Inter-vallen, wobei jedes Intervall durch eine zufällige Teilung des vorhergehenden Intervalls erhaltenwird.

Verfahren der falschen Position. Auch dieses Verfahren basiert auf der ersten Vorgehens-weise: zu bilden ist eine Folge von verschachtelten Intervallen, von denen jedes eine Lösungder Gleichung f(x) = 0 enthält. Um die Intervalle zu teilen, verwenden wir diesmal jedocheine lineare Interpolation der Funktion f .

Genauer gesagt betrachten wir den Abschnitt des Graphen von f , der von den beiden Punktenvon f mit den Abszissen a und b begrenzt wird. Da f(a) und f(b) entgegengesetzte Vorzeichenhaben, schneidet dieser Abschnitt die Abszissenachse. Er teilt daher das Intervall [a, b] in zweiIntervallle. Wie beim Verfahren der Bisektion identizieren wir das eine Lösung enthaltendeIntervall, indem wir den Wert berechnen, den f an der Stelle annimmt, die beide Intervallegemeinsam haben.

Abb. 12.3 - Verfahren der falschen Position auf [−π, π].

263

Page 280: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

Die Gerade durch die Punkte (a, f(a)) und (b, f(b)) hat die Gleichung:

y =f(b)− f(a)

b− a(x− a) + f(a). (12.1)

Wegen f(b) 6= f(a) schneidet diese Gerade die Abszisse an der Stelle

a− f(a)b− a

f(b)− f(a).

Wir können dieses Verfahren nunmehr folgendermaÿen testen:

sage: phi(s, t) = s - f(s) * (t - s) / (f(t) - f(s))sage: falsepos = intervalgen(f, phi, a, b)sage: iterate(falsepos)After 8 iterations: -2.89603757331027

Wichtig ist, dass die mit den Verfaren der Bisektion wie auch der falschen Position gebildetenFolgen nicht notwendig gegen die gleiche Lösung konvergieren. Durch Verkleinerung des unter-suchten Intervalls ndet man auch die positive Lösung, die mit dem Verfahren der Bisektionerhalten wurde.

Abb. 12.4 - Verfahren der falschen Position auf [−π/2, π].

sage: a, b = RR(pi/2), RR(pi)sage: phi(s, t) = t - f(t) * (s - t) / (f(s) - f(t))sage: falsepos = intervalgen(f, phi, a, b)sage: phi(s, t) = (s + t) / 2sage: bisection = intervalgen(f, phi, a, b)

264

Page 281: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

sage: iterate(falsepos)After 15 iterations: 2.15846441170219sage: iterate(bisection)After 20 iterations: 2.15847275559132

Das Newton-Verfahren. Wie das Verfahren der falschen Position verwendet auch das New-ton-Verfahren eine lineare Approximation der Funktion f . Graphisch gesehen handelt es sichdarum, eine Tangente an den Graphen von f als Näherung dieser Kurve zu betrachten.

Wir setzen jetzt voraus, dass f dierenzierbar ist und dass die Ableitung f ′ im Intervall[a, b] dasselbe Vorzeichen hat. Somit ist f hier monoton. Wir setzen auch voraus, dass f dasVorzeichen im Intervall [a, b] wechselt. Die Gleichung f(x) = 0 hat somit in diesem Intervalleine eindeutige Lösung; diese Zahl bezeichnen wir mit α.

Sei u0 ∈ [a, b]. Die Tangente an den Graphen von f an der Stelle u0 hat die Gleichung

y = f ′(u0)(x− u0) + f(u0). (12.2)

Die Koordinaten des Schnittpunktes dieser Gerade mit der Abszisse sind

(u0 − f(u0)/f ′(u0), 0).

Mit ϕ bezeichnen wir die Funktion x 7→ x− f(x)/f ′(x). Sie ist unter der Bedingung deniert,dass f ′ im Intervall [a, b] nicht verschwindet. Wir interessieren uns für die rekursiv durchun+1 = ϕ(un) denierte Folge u. Wenn die Folge u konvergiert,2 dann erfüllt ihr Grenzwert ldie Bezehung l = l − f(l)/f ′(l), woraus sich f(l) = 0 ergibt; der Grenzwert ist gleich α, unddas ist die Lösung der Gleichung f(x) = 0. Damit das Beispiel die Bedingung der Monotonieerfüllt, reduzieren wir das untersuchte Intervall.

Abb. 12.5 - Newton-Verfahren.

2Ein Satz von Leonid Witaljewitsch Kantorowitsch liefert eine hinreichende Bedingung für die Konvergenzdes Newton-Verfahrens.

265

Page 282: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

sage: f.derivative()x |--> 4*cos(x) - 1/2*e^xsage: a, b = RR(pi/2), RR(pi)

Wir denieren einen Python-Generator newtongen, der eine rekursiv zu denierende Folgedarstellt. Dann formulieren wir einen neuen Konvergenztest checkconv, der terminiert, wenndie beiden zuletzt berechneten Wert nahe genug beieinander liegen, doch ist zu beachten, dassdieser Test die Konvergenz keineswegs garantiert.

sage: def newtongen(f, u):....: while True:....: yield u....: u -= f(u) / f.derivative()(u)sage: def checkconv(u, v, w, prec):....: return abs(w - v) / abs(w) <= prec

Wir können nun das Newton-Verfahren mit unserem Beispiel testen.

sage: iterate(newtongen(f, a), check=checkconv)After 6 iterations: 2.15846852566756

Sekantenverfahren Beim Newton-Verfahren kann die Berechnung der Ableitung sehr auf-wendig sein. Es ist bei dieser Rechnung möglich, die Ableitung durch eine lineare Interpolationzu ersetzen: wenn wir über zwei Näherungswerte für die Lösung, und damit über zwei Punktedes Graphen von f verfügen, und wenn die Gerade durch diese beiden Punkte die Abszis-senachse trit, dann betrachten wir die Abszisse des Schnittpunktes als neue Näherung. ZuBeginn und wenn beide Geraden parallel sind, berechnen wir die nächste Approximation mitdem Newton-Verfahren.

Abb. 12.6 - Sekantenverfahren.

266

Page 283: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

Das führt auf dieselbe Iterationsmethode wie das Verfahren der falschen Position, aber mitanderen Punkten. Anders als das Verfahren der falschen Position bestimmt das Sekantenver-fahren kein Intervall mit einer Wurzel.

Wir denieren einen Python-Generator, der das Verfahren in Gang setzt:

sage: def secantgen(f, a):....: yield a....: estimate = f.derivative()(a)....: b = a - f(a) / estimate....: yield b....: while True:....: fa, fb = f(a), f(b)....: if fa == fb:....: estimate = f.derivative()(a)....: else:....: estimate = (fb - fa) / (b - a)....: a = b....: b -= fb / estimate....: yield b

Nun können wir das Sekantenverfahren an unserem Beispiel ausprobieren.

sage: iterate(secantgen(f, a), check=checkconv)After 8 iterations: 2.15846852557553

Das Muller-Verfahren. Wir können das Sekantenverfahren erweitern, indem wir f durchein Polynom beliebigen Grades ersetzen. Beispielsweise arbeitet das Muller-Verfahren3 mitquadratischen Approximationen.

Angenommen, wir haben schon drei Näherungslösungen r, s und t der Gleichung f(x) =0 berechnet. Wir betrachten das Interpolationspolynom von Lagrange, das durch die dreiKurvenpunkte mit den Abszissen r, s und t bestimmt ist. Das ist ein Polynom zweiten Grades.Sinnvollerweise nehmen wir als neue Näherung die Wurzel des Polynoms, die am nächsten beit liegt. Vorher werden die drei Anfangsterme der Folge auf beliebige Weise xiert, a, b unddann (a + b)/2. Es muss gesagt werden, dass die Wurzeln des Polynoms - und damit dieberechneten Näherungswerte - komplexe Zahlen sein können.

Die Programmierung dieses Verfahrens in Sage ist nicht schwierig; sie erfolgt nach dem glei-chen Muster wie das Sekantenverfahren. Unsere Realisierung verwendet allerdings eine Da-tenstruktur, die an die Auistung der Terme einer rekursiv denierten Folge besser angepasstist.

sage: from collections import dequesage: basering = PolynomialRing(CC, 'x')sage: def quadraticgen(f, r, s):....: t = (r + s) / 2....: yield t....: points = deque([(r,f(r)), (s,f(s)), (t,f(t))], maxlen=3)

3Es handelt sich um David E. Muller, bekannt auch als Ernder des Reed-Muller-Codes, nicht um den inKapitel 11 erwähnten Jean-Michel Muller

267

Page 284: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

....: while True:

....: pol = basering.lagrange_polynomial(points)

....: roots = pol.roots(ring=CC, multiplicities=False)

....: u = min(roots, key=lambda x: abs(x - points[2][0]))

....: points.append((u, f(u)))

....: yield points[2][0]

Das Modul collections aus Pythons Referenzbibliothek implementiert mehrere Datenstruk-turen. In quadraticgen wird die Klasse deque benutzt, um die zuletzt berechneten Appro-ximationen zu speichern. Ein Objekt deque speichert Daten bis zur Grenze maxlen, die beiseiner Erzeugung festgelegt wurde; hier ist die maximale Datenanzahl gleich der Rekursions-tiefe der Näherungen. Wenn ein Objekt deque seine maximale Speicherkapazität erreicht hat,fügt die Methode deque.append() die neuen Daten nach dem Prinzip FIFO (rst in, rstout) hinzu.

Zu erwähnen ist, dass die Iterationen dieses Verfahrens keine Berechnung der Ableitungswerteerfordern. Jede Iteration verlangt nur eine Auswertung der Funktion f .

sage: generator = quadraticgen(f, a, b)sage: iterate(generator, check=checkconv)After 5 iterations: 2.15846852554764

Zurück zu den Polynomen. Kehren wir zu der Situation zurück, die wir zu Beginn diesesKapitels untersucht haben. Es geht um die Berechnung der Wurzeln eines Polynoms mitreellen Koezienten; wir nennen diese Polynom P . Wir wollen P als unitär voraussetzen:

P = a0 + a1x+ . . .+ ad−1xd−1 + xd.

Es ist einfach zu verizieren, dass P das charakteristische Polynom der Begleitmatrix ist (sieheUnterabschnitt 8.2.3):

A =

0 0 0 . . . 0 −a0

1 0 0 . . . 0 −a1

0 1 0 . . . 0 −a2

. . . . . . . . . . . . . . . . . .0 0 0 . . . 1 −ad−1

.

Folglich sind die Wurzeln des Polynoms P die Eigenwerte der Matrix A. Deshalb werden hierdie Verfahren aus Kapitel 13 angewendet.

Wir haben gesehen, dass die Methode Polynomial.roots() bis zu drei Parameter aufnimmt,die alle optional sind: ring, multiplicities und algorithm. Wir wollen annehmen, dass einSage-Objekt der Klasse Polynomial dem Namen p zugeordnet ist (deshalb gibt isinstance(p,'Polynomial') den Wert True zurück). Welchen Algorithmus der Befehl p.roots() benutzt,hängt dann von den Parametern ring und algorithm sowie vom Koezientenring des Poly-noms ab, d.h. von p.base_ring().

Der Algorithmus prüft, ob die in ring und p.base_ring() ausgeführten arithmetischen Ope-rationen exakt sind. Sollte dies nicht der Fall sein, werden die Näherungswerte der Wurzeln mitder Bibliothek NumPy berechnet, falls RDF der p.base_ring() ist, und wenn CDF, dann mitder Bibliothek PARI (der Parameter algorithm ermöglicht dem Anwender eine abweichendeWahl der Bibliothek für die Berechnung). Im Quellcode von NumPy sieht man, dass das von

268

Page 285: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

dieser Bibliothek für die Wurzeln benutzte Approximationsverfahren aus der Berechnung derEigenwerte der Begleitmatrix besteht.

Der folgende Befehl gestattet die Identikation derjenigen Objekte, bei denen die arithmeti-schen Operationen exakt sind (der von der Methode Ring.is_exact() zurückgegebene Wertist in diesem Fall True).

sage: for ring in [ZZ, QQ, QQbar, RDF, RIF, RR, AA, CDF, CIF, CC]:sage: print("0:50 1".format(ring, ring.is_exact()))Integer Ring TrueRational Field TrueAlgebraic Field TrueReal Double Field FalseReal Interval Field with 53 bits of precision FalseReal Field with 53 bits of precision FalseAlgebraic Real Field TrueComplex Double Field FalseComplex Interval Field with 53 bits of precision FalseComplex Field with 53 bits of precision False

Wenn der Parameter ring gleich AA oder RIF ist, während p.base_ring() gleich ZZ,QQ oder AA ist, ruft der Algorithmus die Funktion real_roots() aus dem Modul sage.rings.polynomial.real_roots auf. Diese Funktion konvertiert das Polynom zur Bernstein-Basis,wendet dann den Algorithmus von Casteljau an (um das in Bernstein-Basis ausgedrücktePolynom auszuwerten) und die Regel von Descartes (siehe Unterabschnitt 12.2.1), um dieWurzeln zu lokalisieren.

Ist der Parameter ring gleich QQbar oder CIF und p.base_ring() gleich ZZ, QQ, AA oderstellt er Gauÿsche rationale Zahlen dar, delegiert der Algorithmus die Berechnungen an Num-Py und PARI, deren Ergebnisse in die erwarteten Ringe konvertiert werden. In der Dokumen-tation zur Methode Polynomial.roots() kann man alle Situationen kennen lernen, die vondieser Methode abgedeckt werden.

Konvergenzgeschwindigkeit. Betrachten wir eine konvergente numerische Folge u und be-zeichnen wir mit l ihren Grenzwert. Wir sagen, dass die Konvergenzgeschwindigkeit linear ist,wenn ein K existiert, sodass

limn→∞

|un+1 − l||un − l|

= K.

Die Konvergenzgeschwindigkeit der Folge u wird quadratisch genannt, wenn ein K > 0 exis-tiert, sodass

limn→∞

|un+1 − l||un − l|2

= K.

Wenden wir uns wieder dem Newton-Verfahren zu. Wir haben eine Folge u durch un+1 = ϕ(u)rekursiv deniert mit ϕ als der Funktion x 7→ x − f(x)/f ′(x). Unter der Annahme, dass fzweimal dierenzierbar ist, kann die Taylorgleichung für die Funktion ϕ und mit x in derNähe der Wurzel α so geschrieben werden:

ϕ(x) = ϕ(α) + (x− α)ϕ′(α) +(x− α)2

2ϕ′′(α) +Oα((x− α)3).

269

Page 286: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12. Nichtlineare Gleichungen

Nunmehr ist ϕ(α) = α, ϕ′(α) = 0 und ϕ′′(α) = f ′′(α)/f ′(α). Durch Einsetzen in die vorste-hende Gleichung und Rückkehr zur Denition der Folge u erhalten wir:

un+1 − α =(un − α)2

2

f ′′(α)

f ′(α)+O∞((un − α)3).

Da das Newton-Verfahren konvergiert, ist die Geschwindigkeit der gebildeten Folge quadra-tisch.

Konvergenzbeschleunigung. Aus einer konvergenten Folge, deren Geschwindigkeit linearist, können wir eine Folge bilden, deren Konvergenzgeschwindigkeit quadratisch ist. DieseTechnik ist bei Anwendung auf das Newton-Verfahren unter der Bezeichnung Steensen-Verfahren bekannt.

sage: def steffensen(sequence):....: assert isinstance(sequence, GeneratorType)....: values = deque(maxlen=3)....: for i in range(3):....: values.append(sequence.next())....: yield values[i]....: while True:....: values.append(sequence.next())....: u, v, w = values....: yield u - (v - u)^2 / (w - 2 * v + u)

sage: g(x) = sin(x^2 - 2) * (x^2 - 2)sage: sequence = newtongen(g, RR(0.7))sage: accelseq = steffensen(newtongen(g, RR(0.7)))sage: iterate(sequence, check=checkconv)After 17 iterations: 1.41422192763287sage: iterate(accelseq, check=checkconv)After 10 iterations: 1.41421041980166

Man sieht, dass die Konvergenzgeschwindigkeit asymptotisch verläuft: sie sagt über den Fehler|un − l| für gegebenes n nichts aus.

sage: sequence = newtongen(f, RR(a))sage: accelseq = steffensen(newtongen(f, RR(a)))sage: iterate(sequence, check=checkconv)After 6 iterations: 2.15846852566756sage: iterate(accelseq, check=checkconv)After 7 iterations: 2.15846852554764

Lösung von nichtlinearen Gleichungenangenäherte Wurzeln eines Polynoms Polynomial.roots()

exakte Wurzeln ohne Garantie alle zu nden Expression.roots()

angenäherte Wurzeln auf den reellen Zahlen real_roots

angenäherte Wurzeln mit dem Brent-Verfahren Expression.find_root()

Tab. 12.1 - In diesem Kapitel beschriebene Befehle

270

Page 287: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2. Numerische Lösung

Die Methode Expression.find_root(). Wir interessieren uns jetzt für die allgemeinsteSituation: die Berechnung eines Näherungswertes der Lösung einer Gleichung f(x) = 0. InSage erfolgt diese Berechnung mit der Methode Expression.find_root().

Die Parameter der Methode Expression.find_root() gestatten die Angabe eines Intervall,wo eine Wurzel zu suchen ist, der Rechengenauigkeit oder der Anzahl der Iterationen. DerParameter full_output gibt Informationen zur Berechnung, insbesondere zur Anzahl derIterationen und zur Anzahl der Auswertungen der Funktion.

sage: result = (f == 0).find_root(a, b, full_output=True)sage: result[0], result[1].iterations(2.1584685255476415, 9)

In Wirklichkeit implementiert die Methode Expression.find_root() keinen Suchalgorith-mus für das Lösen von Gleichungen: die Rechnung wird an das Modul SciPy delegiert. Dievon Sage für die Lösung eine Gleichung benutzte Funktionalität von SciPy implementiert dasBrent-Verfahren, das drei uns schon bekannte Verfahren kombiniert: die Bisektion, das Se-kantenverfahren und die quadratische Interpolation. Die ersten beiden Näherungswerte sinddie Grenzen des Suchintervalls für die Lösung der Gleichung. Den folgenden Näherungswerterhält man durch lineare Interpolation, wie das beim Sekantenverfahren gemacht wird. Beiden dann folgenden Iterationen wird die Funktion durch quadratische Interpolation angenä-hert, und die Abszisse des Schnittpunktes der Interpolationskurve mit der Achse ist der neueNäherungswert, es sei denn, dieser Wert liegt nicht zwischen den beiden vorhergehenden; indiesem Fall würde mit Bisektion fortgefahren.

Die Bibliothek SciPy ermöglicht keine Rechnung mit beliebiger Genauigkeit (auÿer bei Rech-nung mit ganzen Zahlen); auÿerdem beginnt die Methode Expression.find_root, die Gren-zen in Maschinenzahlen doppelter Genauigkeit zu konvertieren. Demgegenüber funktionierenalle anderen in diesem Kapitel erläuterten Lösungsverfahren mit beliebiger Genauigkeit odersogar symbolisch.

sage: a, b = pi/2, pisage: generator = newtongen(f, a)sage: generator.next(); generator.next()1/2*pi1/2*pi - (e^(1/2*pi) - 10)*e^(-1/2*pi)

Übung 44. Für das Brent-Verfahren ist ein Generator zu schreiben, der mit beliebiger Ge-nauigkeit funktioniert.

271

Page 288: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 289: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

Hier behandeln wir die numerischen Aspekte der linearen Algebra, nachdem die symbolischelineare Algebra in Kapitel 8 präsentiert worden ist. An französischen Lehrbüchern zur nu-merischen Analyse der linearen Algebra kann man die Bücher von M. Schatzman [Sch91], P.Ciarlet [Cia82] oder die mehr spezialisierten von Lascaux-Théodor [LT93, LT94] heranziehen.Das auf englisch geschriebene Buch von Golub und Van Loan [GVL96] ist als Referenz einabsolutes Muss.

Numerische lineare Algebra spielt beim sogenannten wissenschaftlichen Rechnen eine Rolle.Diese Bezeichnung ist nicht ganz passend, um die Probleme zu beschreiben, die bei der mathe-matischen Untersuchung der numerischen Analyse begegnen: bei der näherungsweisen Lösungvon Systemen gewöhnlicher und partieller Dierentialgleichungen, bei Optimierungsaufgaben,bei der Signalverarbeitung usw.

Die numerische Lösung der Mehrzahl dieser Aufgaben, auch linearer Probleme, basiert aufAlgorithmen, die mit Endlosschleifen arbeiten. Im tiefsten Grunde solcher Schleifen ist sehroft ein lineares System zu lösen. Häug ndet das Newton-Verfahren zur Lösung nichtlineareralgebraischer Systeme Anwendung: auch dabei sind lineare Systeme zu lösen. Leistungsfähig-keit und Robustheit der Verfahren der numerischen linearen Algebra sind daher ausschlagge-bend.

Dieses Kapitel umfasst drei Abschnitte: im ersten bemühen wir uns den Leser für den Ein-uss der Ungenauigkeiten von Rechnungen in der linearen Algebra zu sensibilisieren; derzweite Abschnitt (13.2) behandelt, ohne erschöpfend zu sein, klassische Probleme (Lösungvon Gleichungssystemen. Berechnung von Eigenwerten, kleinste Quadrate); im dritten Ab-schnitt (13.3) zeigen wir, wie bestimmte Probleme zu lösen sind, wenn Matrizen als dünnbesetzt angesehen werden können. Dieser letzte Teil will ebenso eine Einführung in Methodengeben, die in einem aktiven Forschungsgebiet benutzt werden, wie auch eine Anleitung zuihrer Anwendung.

13.1. Ungenaues Rechnen in der linearen Algebra

Wir interessieren uns für klassische Aufgaben der linearen Algebra (Lösung von Gleichungssys-temen, Berechnung von Eigenwerten und Eigenvektoren usw.), die mit ungenauer Rechnunggelöst werden. Die erste Quelle von Ungenauigkeiten entspringt aus der Benutzung von (re-ellen oder komplexen) Flieÿpunktzahlen, also nicht nur aus der Arbeit mit Objekten, vondenen man weiÿ, das sie nicht exakt sind, sondern auch daraus, dass sämtliche Rechnungenfehlerbehaftet sind. Die verschiedenen in Sage angebotenen Typen von Flieÿpunktzahlen sindin Kapitel 12 beschrieben.

Es ist beispielsweise das Gleichungssystem Ax = b zu lösen, wobei A eine Matrix mit reellenKoezienten ist. Welchen Fehler δx macht man, wenn A mit δA und b mit δb gestört ist? Indiesem Kapitel tragen wir dazu Teilantworten zusammen.

273

Page 290: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

13.1.1. Normen von Matrizen und Kondition

Sei A ∈ Rn×n (oder Cn×n). Wir statten Rn (oder Cn) mit einer Norm aus: ||x||∞ = max |xi|oder ||x||1 =

∑ni=1 |xiu| oder auch mit der euklidschen Norm ||x||2 =

(∑ni=1 x

2i

)1/2; dann

deniert die Gröÿe||A|| = max

||x||=1||Ax||

eine Norm auf der Menge der n × n-Matrizen. Man sagt, dass es sich um eine der auf Rn(oder Cn) denierten Norm untergeordnete Norm handelt. Die Kondition von A ist durchκ(A) = ‖A−1‖ · ‖A‖ deniert. Das wichtigste Ergebnis besteht darin, dass die Lösung x deslinearen Gleichungssystems Ax = b mit δx gestört ist, wenn man A eine (kleine) Störung δAaufprägt und b eine Störung δb:

‖δx‖‖x‖

≤ κ(A)

1− κ(A)‖δA‖/‖A‖

(‖δA‖‖A‖

+‖δb‖‖b‖

).

Die Normen ‖ · ‖∞ und ‖ · ‖1 sind leicht zu berechnen: ‖A‖∞ = max1≤i≤n(∑n

j=1 |Aij |) und‖A‖1 = max1≤j≤n(

∑ni=1)|Aij |. Im Gegensatz dazu erhalten wir die Norm ‖·‖2 nicht so einfach,

denn ‖A‖2 =√ρ(tAA), der Spektralradius ρ einer Matrix A ist der Absolutwert des absolut

gröÿten seiner Eigenwerte.

Die Frobeniusnorm ist deniert durch

‖A‖F =

n∑i=1

n∑j=1

|aij |21/2

.

Anders als die übrigen Normen ist sie nicht untergeordnet. Man veriziert leicht, dass ‖A‖2F =Spur(tAA) ist.

Die Berechnung der Normen einer Matrix in Sage. Matrizen besitzen eine Methodenorm(p). Je nach Wert des Argumentes p bekommen wir:

p = 1 : ‖A‖1, p = 2 : ‖A‖2,p = Infinity : ‖A‖∞, p = 'frob' : ‖A‖F

Diese Methode ist nur anwendbar, wenn die Koezienten der Matrix in komplexe ZahlenCDF konvertiert werden können. Anzumerken ist, dass man zwar A.norm(Infinity) schreibt,doch A.norm('frob'). Mit A.norm() bekommen wir die Norm ‖A‖2 (Voreinstellung).

Fehler und Kondition - eine Illustration: zuerst mit exakter Rechnung, dann genähert.Wir wollen in Sage die Möglichkeit nutzen, exakte Rechnungen auszuführen, wenn die Koef-zienten rational sind. Wir betrachten die Hilbertmatrix

Aij = 1/(i+ j − 1), i, j = 1, . . . , n.

Das folgende Programm berechnet die Kondition von Hilbertmatrizen in der Norm ‖ · ‖∞:

sage: def cond_hilbert(n):....: A = matrix(QQ, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])....: return A.norm(Infinity) * (A^-1).norm(Infinity)

Hier nun die Ergebnisse als Funktion von n:

274

Page 291: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.1. Ungenaues Rechnen in der linearen Algebra

n Kondition2 27.04 28375.08 33872791095.016 5.06277478751e+2232 1.35710782493e+47

Wir beobachten ein äuÿerst rasantes Wachstum der Kondition in Abhängigkeit von n. Mankann zeigen, dass κ(A) ≈ e7n/2, was oensichtlich eine Gröÿe ist, die die sehr schnell wächst.Immer mit exakter Rechnung mit rationalen Zahlen können wir die Matrix A stören unddie Lösung des originalen linearen Gleichungssystems mit der des gestörten Systems verglei-chen:

sage: def diff_hilbert(n):....: x = vector(QQ,[1 for i in range(0,n)])....: A = matrix(QQ, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])....: y = A*x....: A[n-1,n-1] = (1/(2*n-1))*(1+1/(10^5)) # verändert die Matrix....: sol = A\y....: return max(abs(float(sol[i]-x[i])) for i in range(0,n))

Wir erhalten

n Fehler (diff_hilbert)2 3.9998400064e-054 0.005976095617538 4.8053565800216 67.988505746832 20034.3477421

sodass die Rechnungen sehr bald mit einem nicht mehr tolerierbaren Fehler erfolgen.

Rechnen wir nun mit Matrizen und Vektoren mit Flieÿpunktkoezienten. Diesmal stören wirdie Matrix A nicht explizit, doch bringt die Flieÿpunktarithmetik kleine Störungen mit sich.Wir wiederholen obige Rechnung: das zweite mit y = Ax berechnete Glied versuchen wir auchdurch Lösung des linearen Gleichungssystems As = y zu nden:

sage: def hilbert_diff(n):....: A = matrix(RR, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])....: x = vector(RR, [1 for i in range(0,n)])....: y = A*x....: s = A.solve_right(y)....: return max(abs(float(s[i]-x[i])) for i in range(0,n))

Abhängig von n erhalten wir:

275

Page 292: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

n Fehler (diff_hilbert)2 5.55111512313e-164 4.7384318691e-138 6.82028985288e-0716 8.6851528827932 378.704279105

Wir sehen, dass zum Beispiel für n = 16 der Fehler (mit Unendlich-Norm) so groÿ ist, dassalle Ziern des Ergebnisses falsch sind (bei unserer Wahl von x mit xi = 1 fallen absoluterund relativer Fehler zusammen).

Bemerkungen. Warum also mit Flieÿpunktzahlen rechnen? Die Frage der Leistungsfähigkeitist nicht so vordringlich, da Bibliotheken existieren, welche die Algorithmen der linearen Alge-bra in rationaler Arithmetik ezient implementieren (Sage verwendet Linbox), Algorithmen,die ohne so leistungfsfähig zu sein wie wie ihre Flieÿpunkt-Entsprechungen, für bestimmteAufgaben wie die Lösung von linearen Gleichungssystem moderater Gröÿe vorteilhaft ver-wendet werden können. Doch hier kommt ein zweiter Unsicherheitsfaktor ins Spiel: bei reellenAnwendungen können die Koezienten nur näherungsweise bekannt sein. Beispielsweise lässtdie Lösung eines nichtlinearen Gleichungssystems mit dem Newton-Verfahren Terme auftre-ten, die unexakt berechnet worden sind.

Schlecht konditionierte lineare Gleichungssysteme (auch ohne so extreme Fälle wie die Hilbert-Matrix) sind eher die Regel als die Ausnahme: häug treen wir (in Pysik, Chemie, Biolo-gie usw.) auf Systeme gewöhnlicher Dierentialgleichungen der Form du/dt = F (u), wo dieJacobi-Matrix DF (u), also die Matrix der partiellen Ableitungen ∂Fi/∂uj ein schlecht kon-ditioniertes lineares System deniert: die Eigenwerte sind in einer sehr ausgedehnten Mengeverteilt, was die schlechte Kondition von DF (u) nach sich zieht; diese Eigenschaft rührt da-her, dass das System aus mehreren Zeitskalen zusammengesetzte Erscheinungen modelliert.Leider müssen in der Praxis lineare Systeme mit der Matrix DF (u) gelöst werden.

Alle Rechnungen (Zerlegung von Matrizen, Berechnung von Eigenwerten und -vektoren, Kon-vergenz von iterativen Verfahren) werden durch die Kondition beeinusst. Deshalb solltenwir diesen Begri immer im Hinterkopf haben, wenn wir mit Flieÿpunkt-Darstellungen reellerZahlen arbeiten.

13.2. Voll besetzte Matrizen

13.2.1. Lösung linearer Gleichungssysteme

Zu vermeidende Verfahren. Was man (fast) nie verwenden sollte, ist die Cramersche Regel.Überlegungen zur Rekursion zeigen. dass der Aufwand für die Berechnung der Determinanteeiner n×m-Matrix mit der Cramerschen Regel von der Ordnung n! Multiplikationen ist (undebenso vielen Additionen). Für die Lösung eines System der Gröÿe n sind n+1 Determinantenzu berechnen. Nehmen wir n = 20:

sage: n = 20; aufwand = (n+1)*factorial(n); aufwand51090942171709440000

276

Page 293: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

Wir bekommen den respektablen Wert von 51090942171709440000 Multiplikationen. Wennwir annehmen, dass unser Compoter pro Sekunde 3 · 109 Multiplikationen ausführt (was rea-listisch ist), kommt die folgende Rechenzeit zustande:

sage: v = 3*10^9sage: print "%3.3f"%float(aufwand/v/3600/24/365)540.028

Die Berechnung braucht also etwa 540 Jahre! Selbstverständlich können Sie eine 2×2-Systemmit der Cramerschen Regel lösen, darüber aber nicht! Allen in der Praxis benutzten Verfahrenist polynomialer Aufwand gemein, d.h. die Ordnung np mit kleinem p (üblicherweise p = 3).

Praktikable Verfahren. Die Lösung linearer Gleichungssysteme Ax = b basiert meistens aufeiner Faktorisierung der Matrix A in ein Produkt von zwei Matrizen A = M1M2, wobei M1

und M2 lineare Systeme denieren, die leicht lösbar sind. Zur Lösung von Ax = b löst mannacheinander erst M1y = b und dann M2x = b.

Beispielsweise könnenM1 undM2 Dreiecksmatrizen sein; in diesem Fall sind zwei Gleichungs-systeme in Dreiecksgestalt zu lösen, nachdem die Faktorisierung bewerkstelligt ist. Der Auf-wand für die Faktorisierung ist deutlich höher als der für die Lösung der beiden Gleichungssys-teme (z.B. O(n3) für die LU -Zerlegung gegenüber O(n2) für die Lösung der Systeme in Drei-ecksgestalt). Daher ist es bei der Lösung von mehreren Gleichungssystemen mit der gleichenMatrix zweckmäÿig, die Zerlegung nur einmal vorzunehmen. Wichtig ist, dass eine Matrix zurLösung eines Gleichungssystems niemals invertiert wird. Die Inversion erfordert die Zerlegungder Matrix und dann die Lösung von n Gleichungssystemen, statt eines einzigen.

13.2.2. Direkte Lösung

Dies ist die einfachste Vorgehensweise:

sage: A = matrix(RDF, [[-1,2],[3,4]])sage: b = vector(RDF, [2,3])sage: x = A\b; x(-0.20000000000000018, 0.9000000000000001)

In Sage besitzen Matrizen zur Lösung linearer Gleichungssysteme eine Methode solve_right(die auf der QR-Zerlegung basiert); diesen Befehl rufen wir jetzt auf:

sage: x = A.solve_right(b)

Die Syntax ist praktisch die gleiche wie in Matlab, Octave oder Scilab.

277

Page 294: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

13.2.3. Die LU-Zerlegung

sage: A = matrix(RDF, [[-1,2],[3,4]])sage: P, L, U = A.LU()

Diese Methode liefert die Faktoren L und U sowie die Permutationsmatrix P , sodass A = PLUist (oder damit gleichwertig: PA = LU , wie der aufmerksame Leser bemerkt haben wird).Es ist die Wahl der Pivotstellen, wodurch die Bildung von P bestimmt wird. L ist eine un-tere Dreiecksmatrix mit einer Einser-Diagonalen und U ist eine obere Dreiecksmatrix. DiesesVerfahren ist direkt aus dem in Unterabschnitt 8.2.1 beschriebenen Gauÿ-Algorithmus abge-leitet. Der Übersichtlichkeit halber übergehen wir die Wahl der Pivotstellen. Dann bewirktder Gauÿ-Algorithmus, dass Nullen in der ersten Spalte unter der Diagonale erscheinen, dannin der zweiten Spalte unter der Diagonalen usw. Diese Eliminierung kann man so schreiben:

Ln−1 · · ·L2L1A = U.

Setzen wir L = (Ln−1 · · ·L2L1)−1, erhalten wir A = LU und wir verizieren ohne Schwierig-keit, dass L in unterer Dreiecksgestalt ist mit einer Einser-Diagonalen.

Wir machen darauf aufmerksam, dass Sage die Faktorisierung von A speichert: der BefehlA-LU_valid gibt True genau dann zurück, wenn die LU -Zerlegung bereits berechnet wordenist. Besser noch, der Befehl A.solve_right(b) berechnet die Faktorisierung nur, wenn dasnotwendig ist, also wenn sie zuvor noch nicht berechnet worden ist oder wenn die Matrix Averändert wurde.

Beispiel. Wir erzeugen eine Zufallsmatrix der Gröÿe 1000 und einen Vektor dieser Gröÿe,

sage: A = random_matrix(RDF, 1000)sage: b = vector(RDF, range(1000))

faktorisieren A

sage: %time A.LU()CPU times: user 204 ms, sys: 16 ms, total: 220 msWall time: 252 ms

und lösen jetzt das System Ax = b:

sage: %time x = A.solve_right(b)CPU times: user 116 ms, sys: 8 ms, total: 124 msWall time: 122 ms

Die Lösung geht schneller, weil sie die schon berechnete LU -Zerlegung verwendet.

13.2.4. Die Cholesky-Zerlegung reeller positiv deniter symmetrischer Matrizen

Eine symmetrische Matrix A heiÿt positiv denit, wenn für jeden Vektor x, der nicht derNullvektor ist, txAx > 0 gilt. Zu jeder symmetrischen positiv deniten Matrix existiert eineuntere Dreiecksmatrix C, sodass A = CtC. Diese Faktorisierung ist die Cholesky-Zerlegung. InSage wird sie durch Aufruf der Methode cholesky berechnet. Im folgenden Beispiel erzeugenwir eine Matrix A, die fast sicher positiv denit ist:

278

Page 295: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

sage: m = random_matrix(RDF, 10)sage: A = transpose(m)*msage: C = A.cholesky()

Wir haben anzumerken, dass es mit vertretbarem Aufwand nicht möglich ist zu testen, obeine symmetrische Matrix positiv denit ist. Wenn wir die Methode von Cholesky auf eineMatrix anwenden, die es nicht ist, kann die Zerlegung nicht berechnet werden und es wird imVerlauf der Rechnung von cholesky() ein ValueError ausgegeben.

Um ein Gleichungssystem Ax = b mit der Cholesky-Zerlegung zu lösen, gehen wir vor wiebei der LU -Zerlegung. Ist die Zerlegung einmal berechnet, führen wir A.solve_right(b) aus.Auch hier wird die Zerlegung nicht wiederholt.

Warum verwendet man die Cholesky-Zerlegung und nicht die LU -Zerlegung zur Lösung vonSystemen mit symmetrischen positiv deniten Matrizen? Natürlich benötigen die Faktorennur halb soviel Speicherplatz, doch es geht vor allem um die Anzahl der Operationen, wo sichdie Cholesky-Zerlegung als vorteilhaft erweist. Für eine Matrix der Gröÿe n müssen bei derCholesky-Zerlegung n Quadratwurzeln berechnet werden, n(n− 1)/2 Divisionen, (n3 − n)/6Additionen und ebenso viele Multiplikationen. Zum Vergleich: die LU -Zerlegung benötigtauch n(n− 1)/2 Divisionen, aber (n3 − n)/3 Additionen und Multiplikationen.

13.2.5. Die QR-Zerlegung

Sei A ∈ Rn×m mit n ≥ m. Hier sind zwei Matrizen Q und R zu nden, sodass A = QR ist,wobei Q ∈ Rn×n orthogonal ist (tQQ = I) und R ∈ Rn×m in oberer Dreiecksgestalt ist. Istdie Zerlegung einmal berechnet, kann man sie natürlich zur Lösung von linearen Gleichungs-systemen benutzen, wenn die Matrix A quadratisch und invertierbar ist. Wie wir aber sehenwerden, ist sie vor allem eine interessante Zerlegung für die Lösung von Systemen kleinsterQuadrate und für die Berechnung von Eigenwerten. Zu beachten ist, dass A nicht quadratischsein muss. Die Zerlegung existiert, wenn der Rang maximal ist, also gleich m. Beispiel:

sage: A = random_matrix(RDF,6,5)sage: Q, R = A.QR()

Übung 45 (Störung eines linearen Systems). Sei A eine invertierbare quadratische Matrix,zu der eine Zerlegung berechnet worden ist (LU , QR, Cholesky usw.). Seien u und v zweiVektoren. Wir betrachten die Matrix B = A + utv und setzen 1 + tvA−1u 6= 0 voraus. Wieist das System Bx = f mit geringstem Aufwand (d.h. ohne B zu faktorisieren) zu lösen?

Zu verwenden ist die Gleichung von Sherman und Morrison (die man beweisen oder einfachübernehmen kann):

(A+ u tv)−1 = A−1 − A−1u tvA−1

1 + tvA−1u.

13.2.6. Die Singulärwertzerlegung

Diese Zerlegung wird zwar selten unterrichtet, ist aber dennoch reich an Anwendungen! SeiA eine n × m-Matrix mit reellen Koezienten. Dann existieren zwei orthogonale MatrizenU ∈ Rn×n und V ∈ Rm×m, so dass

tU ·A · V = Σ = diag(σ1, σ2, . . . , σp),

279

Page 296: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

wobei σ1 ≥ σ2 ≥ . . . ≥ σp ≥ 0 (mit p = min(m,n)). Die Zahlen σ1 ≥ σ2 ≥ . . . ≥ σp sind dieSingulärwerte von A.

Die Matrizen U und V sind orthogonal (U · tU = I) und V · tV = I), woraus folgt:

A = UΣ tV.

Beispiel (die Rechnungen sind oensichtlich niemals exakt):

sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2],[1,1,1]])sage: U, Sig, V = A.SVD()sage: A1 = A - U*Sig*transpose(V); A1[ 2.220446049250313e-16 0.0 0.0][3.3306690738754696e-16 -4.440892098500626e-16 -4.440892098500626e-16][-9.298117831235686e-16 1.7763568394002505e-15 -4.440892098500626e-16][ 4.440892098500626e-16 -8.881784197001252e-16 -4.440892098500626e-16]

Es kann gezeigt werden, dass die Singulärwerte einer Matrix A die Quadratwurzeln der Ei-genwerte von tAA sind. Es ist leicht zu verizieren, dass bei einer quadratischen Marix derGröÿe n die euklidsche Norm ‖A‖2 gleich σ1 ist und dass, wenn die Matrix auÿerdem nichtsingulär ist, die Kondition von A mit der euklidschen Norm gleich σ1/σn ist. Der Rang vonA ist die natürliche Zahl r, die deniert ist durch

σ1 ≥ σ2 ≥ . . . ≥ σr ≥ σr+1 = . . . = σp = 0.

13.2.7. Anwendung auf kleinste Quadrate

Wir möchten das überbestimmte Gleichungssystem Ax = b lösen, wobei A eine Matrix mitreellen Koezienten ist, rechtwinklig mit n Zeilen und m Spalten und n > m. Selbstverständ-lich hat dieses System nicht immer eine Lösung. Wir wenden uns nun der Aufgabe zu, dasQuadrat der euklidschen Norm ‖ · ‖2 des Restes zu minimieren:

minx‖Ax− b‖22.

Die Matrix A kann einen Rang kleiner als m haben.

Das Lösen normaler Gleichungen. Wenn wir bei der Minimierungsaufgabe die Ableitungnach x gleich null setzen, stellen wir ohne groÿe Mühe fest, dass die Lösung dieser Bedingunggenügt:

tAAx = tAb.

Wenn wir voraussetzen, dass A den maximalen Rangm hat, können wir die Matrix tAA bildenund das System tAAx =t Ab lösen, beispielsweise durch Berechnung der Cholesky-Zerlegungvon tAA. Das ist auch der Ursprung des Verfahrens des Kommandeurs Cholesky1 Welches istdie Kondition von tAA? Die wird die Genauigkeit der Rechnung konditionieren. Die Singu-lärwerte von tAA (Dimension m×m) sind die Quadrate der Singulärwerte von A; Konditionmit euklidscher Norm ist daher σ2

1/σ2m, also recht groÿ. Wir ziehen daher Verfahrewn vor, die

entweder auf der QR-Zerlegung von A basieren oder auf der Singulärwertzerlegung2.

1Ingenieur und Ozier der Artillerie (1875-1918); das Verfahren ist zur Lösung geodätischer Aufgaben er-funden worden.

2Der Kommandeur Cholesky hatte noch keinen Computer und sah sich wahrscheinlich nur der Lösung kleinerSysteme gegenüber, bei denen schlechte Kondition nicht wirklich problematisch ist.

280

Page 297: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

Trotz allem ist das Verfahren für kleine Systeme, die nicht zu schlecht konditioniert sind,brauchbar. Hier der entsprechende Code:

sage: A = matrix(RDF, [[1,3,2],[1,4,2],[0,5,2],[1,3,2]])sage: b = vector(RDF, [1,2,3,4])sage: Z = transpose(A)*Asage: C = Z.cholesky()sage: R = transpose(A)*bsage: Z.solve_right(R)(-1.5, -0.5, 2.75)

Wohlgemerkt, die Cholesky-Zerlegung ist hier verborgen, und Z.solve_right(R) verwendetsie ohne erneute Berechnung.

Mit QR-Zerlegung. Wir setzen A mit maximalem Rang3 voraus. Es sei A = QR. Danngilt

‖Ax− b‖22 = ‖QRx− b‖22 = ‖Rx− tQb‖22.

Wir haben R =

[R1

0

], wobei R1 ein Block der Gröÿe m in oberer Dreiecksgestalt ist und

tQb =

[cd

]mit c der Gröÿe m. Daher ist ‖Ax− b‖22 = ‖R1x− c‖22 + ‖d‖22, und wir bekommen

das minimale x als Lösung des dreieckigen Systems R1x = c:

sage: A = matrix(RDF, [[1,3,2],[1,4,2],[0,5,2],[1,3,2]])sage: b = vector(RDF, [1,2,3,4])sage: Q, R = A.QR()sage: R1 = R[0:3,0:3]sage: b1 = transpose(Q)*bsage: c = b1[0:3]sage: R1.solve_right(c)(-1.499999999999999, -0.49999999999999867, 2.749999999999997)

Wir berechnen die Konditionszahl von tAA mit der Unendlich-Norm:

sage: Z = A.transpose()*Asage: Z.norm(Infinity)*(Z^-1).norm(Infinity)1992.3750000000168

Da das System nur klein ist, ist es nicht zu schlecht konditioniert. Die QR-Zerlegung und dasVerfahren für normale Gleichungen (Seite 280) ergeben deshalb das gleiche Resultat.

Mit Singulärwertzerlegung. Auch die Singulärwertzerlegung A = UΣ tV ermöglicht dieBerechnung einer Lösung; mehr noch, sie ist sogar dann anwendbar, wenn A nicht den maxi-malen Rang hat. Wenn A nicht identisch null ist, besitzt Σ r ≤ m positive Koezienten σi(in fallender Ordnung). Mit ui bezeichnen wir die Spalten von U . Dann haben wir:

‖Ax− b‖22 = ‖ tUAV tV x−t Ub‖22.

3Diese Einschränkung kann entfallen, wenn wir QR-Zerlegung mit Pivotstellen verwenden.

281

Page 298: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

Mit der Abkürzung λ =t V x erhalten wir

‖Ax− b‖22 =

p∑i=1

(σiλi −t uib)2 +

m∑i=p+1

(tuib)2.

Das Minimum ist daher zu erwarten, wenn wir λi = (tuib)/σi setzen mit 1 ≤ i ≤ p. Wirwählen dann λi = 0 mit i > p und erhalten schlieÿlich die Lösung x = V λ.

Hier das Sage-Programm (wir müssen U.column(i) nicht transponieren):

sage: A = matrix(RDF, [[1,3,2],[1,3,2],[0,5,2],[1,3,2]])sage: b = vector(RDF, [1,2,3,4])sage: U, Sig, V = A.SVD()sage: m = A.ncols()sage: x = vector(RDF, [0]*m)sage: lamb = vector(RDF, [0]*m)sage: for i in range(0,m):....: s = Sig[i,i]....: if s < 1e-12:....: break....: lamb[i] = U.column(i)*b / ssage: x = V*lamb; x(0.2370370370370367, 0.4518518518518521, 0.3703703703703702)

Man sieht, dass die obige Matrix den Rang 2 hat (was wir mit dem Befehl A.rank() verizie-ren können), also nicht den maximalen Rang, der 3 betragen würde. Es gibt somit mehrereLösungen für das Problem der kleinsten Quadrate, und der oben angegebene Beweis zeigt,das x die Lösung der minimalen euklidschen Norm ist.

Betrachten wir die Singulärwerte:

sage: m = 3sage: [ Sig[i,i] for i in range(0,m) ][8.309316833256451, 1.3983038884881154, 0.0]

Da die Matrix A den Rang 2 hat, ist der dritte Singulärwert zwangsläug 0. Um eine Divisiondurch 0 zu vermeiden, ignorieren wir Singulärwerte, die sich von 0 zu wenig unterscheiden(das ist der Grund für den Test if s < 1e-12 im Programm).

Beispiel. Unter den schönsten Anwendungen der Singulärwertzerlegung (SVD engl. für Sin-gular Value Decomposition, SWZ auf deutsch), die mit einem anderen Verfahren wohl kaumlösbar wäre: es seien A und B ∈ Rn×m die Ergebnisse eines zweimal wiederholten Experiments.Wir fragen uns, ob B auf A gedreht werden kann, d.h. existiert eine orthogonale Matrix Q,sodass A = BQ ist. Wird den Messungen ein Rauschen hinzugefügt, hat die Aufgabe ge-nerell oensichtlich keine Lösung. Zweckmäÿigerweise wird sie dann in kleinsten Quadratengestellt; dafür muss deshalb die orthogonale Matrix Q berechnet werden, die das Quadrat derFrobenius-Norm minimiert:

‖A−BQ‖2F ,

Wir erinnern uns an ‖A‖2F = Spur(tAA). Dann ist

‖A−BQ‖2F = Spur(tAA) + Spur(tBB)− 2Spur(tQ tBA) ≥ 0,

282

Page 299: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

und daher ist Spur(tQ tBA) zu maximieren. Wir berechnen nun die SWZ von tBA: wir habentU(tBA)V = Σ. Seien die σi die Singulärwerte und O =t V tQU . Diese Matrix ist orthogonalund deshalb sind alle Koezienten absolut kleiner oder gleich 1. Dann gilt:

Spur(tQ tBA) = Spur(tQUΣ tV ) = Spur(OΣ) =m∑i=1

Oiiσi ≤m∑i=1

σi

und das Maximum wird für Q = U tV erwartet.

sage: A = matrix(RDF, [[1,2],[3,4],[5,6],[7,8]])

Man erhält B durch Hinzufügen eines zufälligen Rauschens zu A und durch eine Rotation umden Winkel ϑ (Rotationsmatrix R):

sage: th = 0.7sage: R = matrix(RDF, [[cos(th),sin(th)],[-sin(th),cos(th)]])sage: B = (A + 0.1*random_matrix(RDF,4,2)) * transpose(R)sage: C = transpose(B)*Asage: U, Sigma, V = C.SVD()sage: Q = U*transpose(V)

Die zufällige Störung ist schwach, und wie erwartet ist Q nahe bei R:

sage: Q[ 0.7628142512578093 0.6466176753522814][-0.6466176753522812 0.7628142512578091]sage: R[0.7648421872844885 0.644217687237691][-0.644217687237691 0.7648421872844885]

Übung 46 (Quadratwurzel einer symmetrischen positiv semideniten Matrix.) Sei A einesymmetrische positiv semidenite Matrix (d.h. sie erfüllt txAx ≥ 0 für jeden Vektor x). Zubeweisen ist, dass man eine Matrix X berechnen kann, die ebenfalls symmetrisch und positivsemidenit ist und zwar so, dass X2 = A ist.

13.2.8. Eigenwerte, Eigenvektoren

Bis jetzt haben wir nur direkte Verfahren verwendet (LU -, QR- und Cholesky-Zerlegung), dienach einer endlichen Anzahl von Operationen (den vier Grundrechenarten und dem Ziehen derQuadratwurzel bei der Cholesky-Zerlegung) eine Lösung liefern. Das kann bei der Berechnungder Eigenwerte nicht der Fall sein: Tatsächlich kann man (siehe Seite 287) jedem Polynomeine Matrix zuordnen, deren Eigenwerte die Wurzeln des Polynoms sind; wir wissen aber, dasskeine explizite Formel für die Berechng der Wurzeln eines Polynoms höheren als 4. Gradesexistiert, eine Formel also, die ein direktes Verfahren ergäbe. Andererseits wäre die Bildungdes charakteristischen Polynoms, um daraus die Wurzeln zu berechnen, extrem aufwendig(siehe Seite 277): jedenfalls stellen wir fest, dass der Algorithmus von Faddeev-Le Verrier dieBerechnung des charakterischen Polynoms einer Matrix der Gröÿe n mit O(n4) Operationenermöglicht, was trotzdem als recht aufwendig betrachtet wird. Die numerischen Verfahren fürdie Berechnung von Eigenwerten und -vektoren sind sämtlich iterativ.

283

Page 300: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

Wir werden deshalb Folgen bilden, die gegen die Eigenwerte (und die Eigenvektoren) konver-gieren und die Iterationen beenden, sobald wir der Lösung nahe genug sind4.

Das Verfahren der iterierten Potenz. Sei A eine Matrix Cn×n. Wir legen eine beliebigeNorm ‖ · ‖ auf Cn fest. Beginnend mit x0 betrachten wir die Folge der xk, die deniert istdurch

xk+1 =Axk‖Axk‖

.

Wenn für die Eigenwerte |λ1| > |λ2| > · · · > |λn| gilt, dann konvergiert die Folge gegen einenEigenvektor, der dem betragsgröÿten (dominanten) Eigenwert |λ1| zugeordnet ist. Zudemkonvergiert die Folge vk =t xk+1xk gegen |λ1|. Die Voraussetzung der Trennung der Eigenwertekann entfallen.

sage: n = 10sage: A = random_matrix(RDF, n); A = A*transpose(A)sage: # A vérifie (presque sûrement) les hypothèsessage: x = vector(RDF, [1 for i in range(0,n)])sage: for i in range(0,1000):....: y = A*x....: z = y/y.norm()....: lam = z*y....: s = (x-z).norm()....: print i, "\ts=", s, "\tlambda=", lam....: if s < 1e-10: break....: x = z0 s= 2.56148717112 lambda= 5.918153437521 s= 0.444153427849 lambda= 4.736369695432 s= 0.213992596115 lambda= 5.817029006493 s= 0.203955698809 lambda= 6.339960556124 s= 0.191707607395 lambda= 6.87035572995 s= 0.158957852503 lambda= 7.316148903046 s= 0.120059107245 lambda= 7.610714102577 s= 0.0859426802981 lambda= 7.775143277898 s= 0.0599388946502 lambda= 7.858604569739 s= 0.0413557016799 lambda= 7.8990822113910 s= 0.028440512895 lambda= 7.91835470562...

Jetzt verwenden wir

sage: A.eigenvalues()[7.9357467710246175,0.039892714739813435,0.34784684826304274,1.2880284207988963,1.0559522706787432,2.58212362822616,3.416559364279167,

4In den nachstehenden Beispielen wird die Wahl des Kriteriums für den Abbruch der Iteration aus Gründender Einfachheit ausgespart.

284

Page 301: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

5.537503736446404,4.365136545605719,4.954088504781742]

Wir haben den dominanten Eigenwert berechnet.

Das Interesse an diesem Verfahren mag begrenzt scheinen, es wächst aber an, sobald dünnbesetzte Matrizen zu untersuchen sind. Es motiviert auch das, was nun folgt, und das ist vongroÿem Nutzen.

Das Verfahren der inversen Potenz mit Translation. Wir setzen eine Approximation µeines Eigenwertes λj mit λj (µ und λj ∈ C) als bekannt voraus. Wie berechnet man einen λjzugordneten Eigenvektor?

Wir treen die Annahme, dass ∀k /∈ j, 0 < |µ−λj | < |µ−λk| gilt, und somit ist λj ein einfacherEigenwert. Wir betrachten dann den Ausdruck (A−µI)−1, dessen gröÿter Eigenwert (λj−µ)−1

ist, und wenden das Verfahren der iterierten Potenz auf diese Matrix an.

Nehmen wir als Beispiel:

sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2]])

Mit Aufruf der Methode A.eigenvalues() nden wir die Eigenwerte 6.392947916489187,0.5605194761119395, -1.9534673926011217. Wir werden den zum zweiten Eigenwert ge-hörigen Eigenvektor suchen und dazu von einem Näherungswert ausgehen:

sage: mu = 0.50519sage: AT = A - mu*identity_matrix(RDF, 3)sage: x = vector(RDF, [1 for i in range(0,A.nrows())])sage: P, L, U = AT.LU()sage: for i in range(1,10):....: y = AT.solve_right(x)....: x = y/y.norm()....: lamb = x*A*x....: print x, lamb(0.9607985552565431, 0.18570664546988727, -0.2058620364352333)1.08914936279(0.927972943625375, 0.1044861051800865, -0.3576994125289455)0.563839629189(0.9276916133832703, 0.10329827357690813, -0.35877254233619243)0.560558807639(0.9276845318283404, 0.10329496332009931, -0.35879180586954856)0.560519659839(0.9276845648427788, 0.1032947552966817, -0.3587917803972978)0.560519482021(0.9276845629124328, 0.10329475732310033, -0.3587917848049623)0.560519476073(0.9276845629447148, 0.10329475725254855, -0.3587917847418061)0.560519476114(0.9276845629438836, 0.1032947572539018, -0.3587917847435661)0.560519476112

285

Page 302: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

(0.9276845629439012, 0.10329475725386913, -0.35879178474352963)0.560519476112

Wir fügen einige Bemerkungen an:

- wir berechnen das Inverse der Matrix A− µI nicht, sondern verwenden ihre LU -Zerlegung,die (mit solve_right) ein für alle Mal berechnet wird;

- wir protieren für die verbesserte Schätzung des Eigenwertes von den Iterationen;

- die Konvergenz erfolgt sehr schnell; man kann gut zeigen (mit der obigen Annahme sowie derWahl eines Anfangsvektors, der zu dem Eigenvektors qj , der zu λj gehört, nicht orthogonalist), dass wir als Iterierte x(i) und λ(i)

‖x(i) − qj‖ = O

(∣∣∣ µ− λjµ− λK

∣∣∣i)und

‖λ(i) − λj‖ = O

(∣∣∣ µ− λjµ− λK

∣∣∣2i)bekommen, wobei λK der zu µ zweitnächste Eigenwert ist;

- die Konditionszahl von (A − µI) (gebunden an das Verhältnis von gröÿtem unf kleinstemEigenwert von (A − µI)) ist schlecht; man kann jedoch zeigen (siehe [Sch91], wo Parlettzitiert wird), dass die Fehler trotz allem unbedeutend sind!

Das QR-Verfahren. Sei A eine quadratische nichtsinguläre Matrix. Wir betrachten die FolgeA0, A1, A2, . . . , Ak, Ak+1, . . .. In der Rohform des QR-Verfahrens wird der Übergang von Aknach Ak+1 so bewerkstelligt:

1. wir berechnen die QR-Zerlegung von Ak: Ak = QkRk,

2. wir berechnen Ak+1 = RkQk

Programmieren wir dieses Verfahren mit einer reellen symmetrischen Matrix für A:

sage: m = matrix(RDF, [[1,2,3,4],[1,0,2,6],[1,8,4,-2],[1,5,-10,-20]])sage: Aref = transpose(m)*msage: A = copy(Aref)sage: for i in range(0,20):....: Q, R = A.QR()....: A = R*Q....: print A.str(lambda x: RealField(30)(x).str())[ 347.58031 -222.89331 -108.24117 -0.067928252][ -222.89331 243.51949 140.96827 0.081743964][ -108.24117 140.96827 90.867499 -0.0017822044][ -0.067928252 0.081743964 -0.0017822044 0.032699348]...[ 585.03056 -3.2281469e-13 -6.8752767e-14 -9.9357605e-14][-3.0404094e-13 92.914265 -2.5444701e-14 -3.3835458e-15][-1.5340786e-39 7.0477800e-25 4.0229095 2.7461301e-14][ 1.1581440e-82 -4.1761905e-68 6.1677425e-42 0.032266909]

286

Page 303: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

Wir beobachten eine schnelle Konvergenz gegen eine quasi-diagonale Matrix. Die Koezientenauf der Diagonalen sind die Eigenwerte von A. Wir verizieren

sage: Aref.eigenvalues()[585.0305586200212, 92.91426499150643, 0.03226690899408103, 4.022909479477674]

Man kann die Konvergenz beweisen, wenn die hermitesche Matrix positiv denit ist. Rechnetman mit einer nichtsymmetrischen Matrix, ist es sinnvoll, auf C zu arbeiten, wo die Eigenwertea priori komplex sind, und wenn das Verfahren konvergiert, tendieren die dreieckigen Teileunterhalb von Ak gegen null, während die Diagonale zu den Eigenwerte tendiert.

Das QR-Verfahren benötigt etliche Verbesserungen, um ezient zu sein, insbesondere weildie sukzessiven QR-Zerlegungen aufwendig sind; bei den gebräuchlichen Verfeinerungen wirdim allgemeinen mit der Reduktion der Matrix in eine einfachere Form begonnen (Hessenberg-Form: obere Dreiecksgestalt mit einer Subdiagonalen), was die QR-Zerlegung deutlich wenigeraufwendig macht; dann müssen zur Beschleunigung der Konvergenz die geschickt gewähltenTranslationen A := A + σI ausgeführt werden (siehe z.B [GVL96]). Wir verraten noch, dassdieses Verfahren von Sage angewendet wird, wenn man mit voll besetzten Matrizen (CDF oderRDF) zu tun hat.

In der Praxis. Die obigen Programme sind hier als pädagogische Beispiele angeführt. Manwird daher im Rahmen des Möglichen die von Sage bereitgestellten Methoden verwendenund die optimierten Routinen der Bibliothek Lapack benutzen. Die Schnittstellen erlaubenentweder die Berechnung nur der Eigenwerte oder der Eigenwerte und Eigenvektoren:

sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2]])sage: A.eigenmatrix_right()([ 6.39294791648918 0.0 0.0][ 0.0 0.560519476111939 0.0][ 0.0 0.0 -1.9534673926011215],

[ 0.5424840601106511 0.9276845629439008 0.09834254667424457][ 0.5544692861094349 0.10329475725386986 -0.617227053099068][ 0.6310902116870117 -0.3587917847435306 0.780614827194734])

Dieses Beispiel berechnet die Diagonalmatrix der Eigenwerte und die Matrix der Eigenvekto-ren der Eigenwerte (Eigenvektoren sind die Spalten).

Beispiel (Berechnung der Wurzeln eines Polynoms). Ist ein Polynom (mit reellen oder kom-plexen Koezienten) p(x) = xn+an−1x

n−1+. . .+a1x+a0 gegeben, dann kann leicht veriziertwerden, dass die Eigenwerte der Begleitmatrix M , die durch Mi+1,i = 1 und Mi,n−1 = −aideniert ist, die Wurzeln von p sind (siehe Unterabschnitt 8.2.3), was somit ein Verfahren zurErmittlung der Wurzeln von p liefert:

sage: def pol2companion(p):....: n = len(p)....: m = matrix(RDF,n)....: for i in range(1,n):....: m[i,i-1]=1....: for i in range(0,n):

287

Page 304: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

....: m[i,n-1]=-p[i]

....: return m

sage: q = [1,-1,2,3,5,-1,10,11]sage: comp = pol2companion(q); comp[ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0][ 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0][ 0.0 1.0 0.0 0.0 0.0 0.0 0.0 -2.0][ 0.0 0.0 1.0 0.0 0.0 0.0 0.0 -3.0][ 0.0 0.0 0.0 1.0 0.0 0.0 0.0 -5.0][ 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0][ 0.0 0.0 0.0 0.0 0.0 1.0 0.0 -10.0][ 0.0 0.0 0.0 0.0 0.0 0.0 1.0 -11.0]sage: racines = comp.eigenvalues(); racines[0.3475215101190289 + 0.5665505533984981*I,0.3475215101190289 - 0.5665505533984981*I,0.34502377696179265 + 0.43990870238588275*I,0.34502377696179265 - 0.43990870238588275*I,-0.5172576143252197 + 0.5129582067889322*I,-0.5172576143252197 - 0.5129582067889322*I,-1.3669971645459291, -9.983578180965276]

In diesem Beispiel wird das Polynom durch die Liste q seiner Koezienten von 0 bis n − 1dargestellt. Das Polynom x2 − 3x+ 2 wird so durch die Liste q = [2,−3] abgebildet.

13.2.9. Polynomiale Angleichung: die Rückkehr des Teufels

Stetige Version. Wir möchten die Funktion f(x) auf dem Intervall [α, β] durch ein PolynomP (x) höchstens n-ten Grades annähern. Wir formulieren das Problem in kleinsten Quadra-ten.

mina0,...,an∈R

J(a0, . . . , an) =

β∫α

(f(x)−n∑i=0

aixi)2dx.

Durch Ableitung von J(a0, . . . , an) nach den Koezienten ai nden wir, dass die a0, . . . , anLösungen eines linearen Gleichungssystems Ma = F sind mit Mi,j =

∫ βα x

ixjdx und Fj =∫ βα x

jf(x)dx. Wenn wir den Fall α = 0 und β = 1 betrachten, sehen wir sofort, dass Mi,j dieHilbert-Matrix ist! Es gibt aber ein Mittel: es reicht hin, eine Basis der orthogonalen Polynomezu verwenden (beispielsweise die Basis der Legendre-Polynome, wenn α = −1 ist und β = 1):dann wird die Matrix M zur Einheitsmatrix.

Diskrete Version. Wir betrachten m Beobachtungen y1, . . . , ym eines Phänomens an denPunkten x1, . . . , xm. Wir möchten ein Polynom n-ten Grades

∑ni=0 aix

i anpassen, das anhöchstens m− 1 dieser Punkte übereinstimmt. Wir minimieren also das Funktional:

J(a0, . . . , an) =

m∑j=1

(n∑i=0

aixij − yj

)2

.

So geschrieben wird die Aufgabe eine Matrix ergeben, die einer Hilbert-Matrix sehr nahekommt, und das System wird schwer lösbar sein. Wir bemerken jetzt aber, dass 〈P,Q〉 =

288

Page 305: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

∑mj=1 P (xj) · Q(xj) ein Skalarprodukt von Polynomen des Grades n ≤ m − 1 deniert. Wir

können deshalb zunächst n Polynome mit abgestuften Graden bilden, die für das Skalarpro-dukt orthonormiert sind, und dann das lineare System diagonalisieren. Wenn wir uns daranerinnern,5 dass das Verfahren von Gram-Schmidt sich für die Berechnung der orthogonalenPolynome zu einer Rekursion mit drei Termen vereinfacht, suchen wir das Polynom Pn+1(x)in der Form Pn+1(x) = xPn(x) − αnPn−1(x) − βnPn−2(x): genau das macht die Funktionorthopoly hierunter (wir stellen hier die Polynome durch die Liste ihrer Koezienten dar:zum Beispiel repräsentiert [1,−2, 3] das Polynom 1− 2x+ 3x2).

Die Auswertung eines Polynoms mit dem Horner-Schema wird nun so programmiert:

sage: def eval(P,x):....: if len(P) == 0:....: return 0....: else:....: return P[0]+x*eval(P[1:],x)

Nun können wir das Skalarprodukt der beiden Polynome programmieren:

sage: def pscal(P,Q,lx):....: return float(sum(eval(P,s)*eval(Q,s) for s in lx))

und die Operation P ← P + aQ für die Polynome P und Q:

sage: def padd(P,a,Q):....: for i in range(0,len(Q)):....: P[i] += a*Q[i]

Ein etwas ernsthafteres Programm muss eine Exzeption auswerfen, sobald es unpassend ver-wendet wird; in unserem Fall veranlassen wir die Exzeption wenn n ≥ m ist:

sage: class BadParamsforOrthop(Exception):....: def __init__(self, degreplusun, npoints):....: self.deg = degreplusun....: self.np = npoints....: def __str__(self):....: return "degre: " + str(self.deg) + \....: " nb. points: " + repr(self.np)

Die folgende Funktion berechnet die n orthogonalen Polynome:

sage: def orthopoly(n,x):....: if n > len(x):....: raise BadParamsforOrthop(n-1, len(x))....: orth = [[1./sqrt(float(len(x)))]]....: for p in range(1,n):....: nextp = copy(orth[p-1])....: nextp.insert(0,0)....: s = []....: for i in range(p-1,max(p-3,-1),-1):....: s.append(pscal(nextp, orth[i], x))

5Der Beweis ist nicht schwierig!

289

Page 306: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

....: j = 0

....: for i in range(p-1,max(p-3,-1),-1):

....: padd(nextp, -s[j], orth[i])

....: j += 1

....: norm = sqrt(pscal(nextp, nextp, x))

....: nextpn = [nextp[i]/norm for i in range(len(nextp))]

....: orth.append(nextpn)

....: return orth

Wenn die orthogonalen Polynome P0(x), . . . , Pn(x) berechnet sind, ist die Lösung gegebendurch P (x) =

∑ni=1 γiPi(x) mit

γi =

m∑j=1

Pi(xj)yj ,

was wir oensichtlich auf die Basis der Monome 1, x, . . . , xn zurückführen können.

Abb. 13.1 - Polynomiale Anpassung

Beispiel (n = 15):

sage: L = 40sage: X = [100*float(i)/L for i in range(40)]sage: Y = [float(1/(1+25*X[i]^2)+0.25*random()) for i in range(40)]sage: n 15; orth = orthopoly(n, X)

Berechnen wir nun die Lösung mit der Basis der orthogonalen Polynome:

sage: coeff = [sum(Y[j]*eval(orth[i],X[j]) for j in....: range(0,len(X))) for i in range(0,n)]

Jetzt können wir dieses Resultat in die Basis der Monome 1, x, . . . , xn transformieren, umbeispielsweise den Graphen zeichnen zu können:

sage: polmin = [0 for i in range(0,n)]sage: for i in range(0,n):

290

Page 307: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Voll besetzte Matrizen

....: padd(polmin, coeff[i], orth[i])sage: p = lambda x: eval(polmin, x)sage: plot(p(x), x, 0, X[len(X)-1])

Wir setzen hier weder die Berechnung der naiven Anpassung mit den Monomen xi als Basisauseinander, noch ihre graphische Darstellung. Wir erhalten die Abbildung 13.1. Beide Kur-ven, die eine entspricht der Anpassung mit orthogonalen Polynomen als Basis, die andere demnaiven Verfahren, liegen dicht beieinander, doch wenn wir ihren Rest berechnen (der Wertdes Funktionals J), nden wir 0.1202 für die Anpassung mit orthogonalen Polynomen und0.1363 für die naive Anpassung.

13.2.10. Implementierung und Leistung

Rechnungen mit Maztrizen mit Koezienten aus RDF werden mit der Flieÿpunkt-Arithmetikdes Prozessors ausgeführt, diejenigen mit Matzrizen über RR mit Hilfe der Bibliothek GNUMPFR. Auÿerdem bedient sich Sage im ersten Fall der Python-Module NumPy/SciPy, die aufdie Bibliothek Lapack zugreifen (die in Fortran codiert ist) und diese Bibliothek verwendetwiederum BLAS6 und ATLAS, die für jede Maschine optimiert sind. So bekommen wir beider Berechnung der Produkte zweier Matrizen der Gröÿe 1000 die Angaben

sage: a = random_matrix(RR, 1000)sage: b = random_matrix(RR, 1000)sage: %time a*bCPU times: user 421.44 s, sys: 0.34 s, total: 421.78 sWall time: 421.79 s

sage: c = random_matrix(RDF, 1000)sage: d = random_matrix(RDF, 1000)sage: %time c*dCPU times: user 0.18 s, sys: 0.01 s, total: 0.19 sWall time: 0.19 s

und die Rechenzeiten unterscheiden sich um den Faktor 2000!

Wir bemerken auch die Geschwindigkeit der Rechnungen mit Matrizen mit Koezienten ausRDF: wir sehen sofort, dass das Produkt zweier quadratischer Matrizen der Gröÿe n3 Mul-tiplikationen erfordert (und ebenso viele Additionen); hier werden also 109 Additionen undMultiplikationen in 0.18 Sekunden ausgeführt. Das sind ungefähr 1010 Operationen, die proSekunde ausgeführt werden oder auch 10 Gigaops7. Die Zentraleinheit der Testmaschine istmit 3.1 GHz getaktet, es wird also mehr als eine Operation je Takt ausgeführt, was nur mög-lich wird durch quasi direkten Aufruf der entsprechenden Routine der Bibliothek ATLAS8.Wir weisen darauf hin, dass auch ein Algorithmus existiert, der den Aufwand bei der Mul-tiplikation zweier Matrizen kleiner macht als n3: das Verfahren von Strasser. Es ist in derPraxis (für Gleitpunktrechnungen) aus Gründen der numerischen Stabilität nicht implemen-tiert. Der Leser kann sich anhand der obigen Programme überzeugen, dass die Rechnung inSage proportional zu n3 ist.

6Basic Linear Algebra Subroutines7op für oating point operation8Diese Bibliothek arbeitet blockweise, wobei die Gröÿe der Blöcke während der Compilierung automatischangepasst wird. Sie ist teilweise für die beträchtliche Dauer der Erstellung von Sage aus den Quellenverantwortlich.

291

Page 308: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

13.3. Dünn besetzte Matrizen

Dünn besetzte Matrizen treten in wissenschaftlichen Rechnungen häug auf: dünne Besetzung(sparsity auf englisch) ist eine gut erforschte Eigenschaft, die das Lösen von umfangreichenProblemen ermöglicht, die mit voll besetzten Matrizen nicht angegangen werden könnten.

Eine vorläuge Denition: wir sagen, dass eine Menge von Matrizen Mnn (der Gröÿe n) eineFamilie dünn besetzter Matrizen ist, wenn die Anzahl der von null verschiedenen Koezientenvon der Ordnung O(n) ist.

Selbstverständlich werden solche Matrizen rechnerintern mit Datenstrukturen dargestellt, beidenen nur die von null verschiedenen Elemente gespeichert werden. Durch Berücksichtigungder dünnen Besetzung von Matrizen will man natürlich Speicherplatz sparen und daraufhinsehr groÿe Matrizen handhaben können, aber auch die Rechenzeiten deutlich senken.

13.3.1. Vorkommen dünn besetzter Matrizen

Randwertaufgaben. Das häugste Vorkommen ist die Diskretisierung partieller Dieren-tialgleichungen. Betrachten wir beispielsweise die Poisson-Gleichung (stationäre Wärmelei-tung):

−∆u = f

mit u = u(x, y), f = f(x, y),

∆u :=∂2u

∂x2+∂2u

∂y2.

Die Gleichung ist im Quadrat [0, 1]2 mit der Bedingung u = 0 an den Rändern des Quadratsaufgestellt. Das eindimensionale Analogon ist das Problem

−∂2u

∂x2= f (13.1)

mit u(0) = u(1) = 0.

Eins der einfachsten Verfahren für eine Näherungslösung dieser Gleichung ist das Finite-Dierenzen-Verfahren. Wir zerschneiden das Intervall [0, 1] in eine endliche Anzahl N vonIntervallen konstanter Schrittweite h. Mit ui bezeichnen wir den Näherungswert von u imPunkt xih. Wir nähern die Ableitung von u durch (ui+1− ui)/h an und die zweite Ableitungmit

(ui+1 − ui)/h− (ui − ui−1)/h

h=ui+1 − 2ui + ui−1

h2.

Man sieht sofort, dass die u0, . . . , uN , die u in den Punkten ih annähern, ein lineares Glei-chungssystem bilden, das nur drei von null verschiedene Terme je Zeile aufweist (und deshalbkönnen wir sagen, dass die Matrix symmetrisch positiv denit ist.)

Bei zwei Dimensionen können wir ein Netz mit der Maschenweite h über das Einheitsquadratlegen und wir bekommen ein System mit fünf Diagonalen (4/h2 auf der Hauptdiagonalen, zweiDiagonalen darüber und zwei darunter mit den Koezienten −1/h2). Bei drei Dimensionengehen wir in einem Würfel entsprechen vor und bekommen ein System, wo jede Zeile siebenvon null verschiedene Koezienten hat. Somit haben wir jeweils dünn besetzte Matrizen.

292

Page 309: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.3. Dünn besetzte Matrizen

Zufallsweg durch einen groÿen dünn besetzten Graphen. Wir betrachten einen Graphen,in dem jeder Knoten mit einer kleinen Anzahl von Knoten (klein in Bezug auf die Gesamtzahlder Knoten) verbunden ist. Wir können uns beispielsweise einen Graphen vorstellen, dessenKnoten Internetseiten sind: jede Seite ist nur mit einer kleinen Anzahl von Seiten verlinkt(was die Kanten des Graphen ausmacht), doch handelt es sich mit Sicherheit um einen groÿenGraphen. Ein Zufallsweg durch diesen Graphen wird durch eine stochastische Matrix beschrie-ben, also eine Matrix mit reellwertigen Koezienten, die alle zwischen 0 und 1 (einschlieÿlich)liegen und deren Summe in jeder Zeile gleich eins ist. Wir zeigen, dass eine solche Matrix einendominanten Eigenwert von eins hat. Die stationäre Verteilung des Zufallsweges ist der Eigen-vektor von links, der dem dominanten Eigenwert zugeordnet ist, d.h. der Vektor, der Ax = xveriziert. Eine der spektakulärsten Anwendungen ist der Pagerank -Algorithmus von Google,wo der Vektor x dazu dient, die Suchergebnisse zu gewichten.

13.3.2. Sage und dünn besetzte Matrizen

Sage gestattet mit dünn besetzten Matrizen zu arbeiten, indem bei der Erzeugung der Ma-trix sparse = True angegeben wird. Es handel sich um eine interne Speicherung als Diktio-när. Andererseits werden Berechnungen bei groÿen dünn besetzten Matrizen mit Flieÿpunkt-Koezienten (RDF oder CDF) von Sage mit der Bibliothek SciPy ausgeführt, die für dünnbesetzte Matrizen eigene Klassen bereitstellt. Beim gegenwärtigen Stand der Dinge gibt eskein Interface zwischen Sages sparse-Matrizen und den dünn besetzten Matrizen von SciPy.Zweckmäÿigerweise verwendet man direkt die SciPy-Objekte.

Die von SciPy für die Darstellung dünn besetzter Matrizen angebotenen Klassen sind:

- eine Struktur in Gestalt einer Liste von Listen (die aber mit der von Sage verwendeten nichtidentisch ist) geeignet für die Erzeugung und Modizierung von Matrizen, die lil_matrix;

- immutable Strukturen, die nur die von null verschiedenen Koezienten speichern und prak-tisch Standard für die dünn besetzte lineare Algebra sind (Formate csr undcsv).

13.3.3. Lösung linearer Systeme

Für ein- und zweidimensionale Systeme mittlerer Gröÿe, wie wir sie oben besprochen haben,können wir ein direktes Verfahren benutzen, das auf der LU -Zerlegung basiert. Ohne groÿeProbleme kann man sich davon überzeugen, dass bei der LU -Zerlegung einer dünn besetztenMatrix A die Faktoren L und U im allgemeinen zusammen mehr von null verschiedene Termeenthalten als A. Wir müssen Algorithmen der Umnummerierung von Unbekannten verwenden,um die Gröÿe des erforderlichen Speichers zu begrenzen, wie in der von Sage auf transparenteWeise benutzten Bibliothek SuperLU:

sage: from scipy.sparse.linalg.dsolve import *sage: from scipy.sparse import lil_matrixsage: from numpy import arraysage: n = 200sage: n2 = n*nsage: A = lil_matrix((n2, n2))sage: h2 = 1./float((n+1)^2)sage: for i in range(0,n2):....: A[i,i]=4*h2+1.

293

Page 310: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

....: if i+1<n2: A[i,int(i+1)]=-h2

....: if i>0: A[i,int(i-1)]=-h2

....: if i+n<n2: A[i,int(i+n)]=-h2

....: if i-n>=0: A[i,int(i-n)]=-h2sage: Acsc = A.tocsc()sage: b = array([1 for i in range(0,n2)])sage: solve = factorized(Acsc) # LU-Zerlegungsage: S = solve(b) # Lösung

Nach Erzeugung der Matrix als lil_matrix (Achtung: dieses Format verlangt Indizes vomPython-Typ int) muss sie in das Format csc konvertiert werden. Dieses Programm istnicht besonders leistungsfähig: die Bildung der lil_matrix geht langsam und die Strukturenlil_matrix sind nicht besonders ezient. Dafür sind die Konversion in eine csc-Matrix unddie Zerlegung schnell, und die sich ergebende Lösung ist es noch mehr.

Die wichtigsten BefehleLösung eines linearen Gleichungssystems x = A\b

LU -Zerlegung P, L, U = A.LU()

Cholesky-Zerlegung C = A.cholesky()

QR-Zerlegung Q, R = A.QR()

Singulärwertzerlegung U, Sig, V = A.SVD()

Eigenwerte und -vektoren Val, Vect = A.eigenmatrix_right()

Tab. 13.1 - Zusammenfassung

Iterative Verfahren. Das Prinzip dieser Verfahren ist die Bildung einer Folge, die gegen dieLösung des Systems Ax = b konvergiert. Moderne iterative Verfahren verwenden den Krylow-Vektorraum Kn, der durch b, Ab, . . . , Anb aufgespannt wird. Von den bekanntesten Verfahrennenn wir:

- das Verfahren des konjugierten Gradienten: es kann nur mit Systemen verwendet werden,deren Matrix A symmetrisch und positiv denit ist. In diesem Fall ist ‖x‖A =

√txAx eine

Norm und die Iterierte xn wird durch Minimierung der Abweichung ‖x − xn‖A zwischender Lösung x und xn berechnet mit xn ∈ Kn (es gibt explizite, leicht zu programmierendeFormeln, siehe z.B. [LT94], [GVL96]);

- das GMRES-Verfahren (Akronym für Generalized Minimal RESidual): es hat den Vorteil,bei nichtsymmetrischen linearen Systemen eingesetzt werden zu können. Bei der n-ten Ite-ration ist es die euklidsche Norm ‖Axn − b‖2, die für xn ∈ Kn minimiert wird. Man sieht,es handelt sich um eine Aufgabe der kleinsten Quadrate.

In der Praxis sind diese Verfahren nur vorkonditioniert ezient: statt Ax = b zu lösen,löst man MAx = Mb, wobei M eine Matrix ist, sodass MA besser konditioniert ist alsA. Die Untersuchung und das Aunden von ezienten Vorkonditionierern ist ein aktuellesGebiet und reich an Entwicklungen der numerischen Analyse. Als Beispiel hier die Lösungdes oben mit dem Verfahren des konjugierten Gradienten untersuchten Systems, wobei derVorkonditioniererM diagonal ist und die Inverse der Diagonalen von A. Das ist ein einfacher,aber wenig ezienter Vorkonditionierer:

sage: b = array([1 for i in range(0,n2)])sage: m = lil_matrix((n2, n2))sage: for i in range(0,n2):....: m[i,i] = 1./A[i,i]

294

Page 311: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.3. Dünn besetzte Matrizen

sage: msc = m.tocsc()sage: from scipy.sparse.linalg import cgsage: x = cg(A, b, M = msc, tol=1.e-8)

13.3.4. Eigenwerte, Eigenvektoren

Das Verfahren der iterierten Potenz. Das Verfahren der iterierten Potenz ist besonders anden Fall sehr groÿer dünn besetzter Matrizen angepasst; tatasächlich reicht es aus zu wissen,wie Matrix-Vektor-Produkte (und Skalarprodukte) gebildet werden, um diesen Algorithmusimplementieren zu können. Als Beispiel greifen wir den Zufallsweg durch einen dünn besetztenGraphen wieder auf und berechnen mit dem Verfahren der iterierten Potenz die stationäreVerteilung:

sage: from scipy import sparsesage: from numpy.linalg import *sage: from numpy import arraysage: from numpy.random import randsage: def power(A,x): # iterierte Potenz....: for i in range(0,1000):....: y = A*x....: z = y/norm(y)....: lam = sum(x*y)....: s = norm(x-z)....: print i,"s= "+str(s)+" lambda= "+str(lam)....: if s < 1e-3:....: break....: x = z....: return xsage: n = 1000sage: m = 5sage: # Bilden eine stochstischen Matrix der Gröÿe nsage: # mit m von null verschiedenen Koeffizienten je Zeilesage: A1 = sparse.lil_matrix((n, n))sage: for i in range(0,n):....: for j in range(0,m):....: l = int(n*rand())....: A1[l,i] = rand()sage: for i in range(0,n):....: s = sum(A1[i,0:n])....: A1[i,0:n] /= ssage: At = A1.transpose().tocsc()sage: x = array([rand() for i in range(0,n)])sage: # Berechnen des dominanten Eigenwertes undsage: # des zugehörigen Eigenvektorssage: y = power(At, x)0 s= 17.637122289 lambda= 255.5379583361 s= 0.374734872232 lambda= 0.912439963212 s= 0.215216267956 lambda= 0.9689709017843 s= 0.120794893336 lambda= 0.98672095617

295

Page 312: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13. Numerische lineare Algebra

4 s= 0.071729229056 lambda= 0.990593746559...

Führen wir dieses Beispiel aus, können wir uns damit amüsieren, die Rechenzeiten für dieverschiedenen Teile zu messen. Wir werden dann feststellen, dass fast die gesamte Rechenzeitfür die Erstellung der Matrix verbraucht wird; die Berechnung der Transponierten ist nichtsehr zeitaufwendig; die Iterationen beanspruchen eigentlich nur eine vernachlässigbar kleineZeit (etwa 2% der gesamten Rechenzeit auf dem Testrechner). Das Speichern groÿer Matrizenals Listen ist nicht sehr ezient, und solche Probleme sollten besser mit kompilierten Sprachenund angepassten Datenstrukturen behandelt werden.

13.3.5. Gegenstand des Nachdenkens: Lösung von sehr groÿen nicht-linearen Systemen

Das Verfahren der iterierten Potenz und die auf dem Krylow-Vektorraum basierenden Ver-fahren teilen eine wertvolle Eigenschaft: es genügt zu wissen, wie Matrix-Vektor-Produkteberechnet werden, um sie implementieren zu können. Wir müssen noch nicht einmal die Ma-trix kennen, es reicht aus zu wissen, was die Matrix mit einem Vektor macht. Wir könnendaher auch dann Rechnungen ausführen, wenn wir die Matrix nicht genau kennen oder sienicht berechnen können. Die Methoden von SciPy akzeptieren tatsächlich lineare Operatoren

als Argumente. Hier nun eine Anwendung, über die man nachdenken (und die man imple-mentieren) kann.

Sei F : Rn → Rn. Wir wollen F (x) = 0 lösen. Das Verfahren der Wahl ist das Newton-Verfahren, bei dem wir ausgehend von x0 die Iterierten xn+1 = xn−J(xn)−1·F (xn) berechnen.Die Matrix J(xn) ist die Jacobi-Matrix von F nach xn, die Matrix der partiellen Ableitungenvon F nach xn. In der Praxis wird man nacheinander J(xn)y=F (x) und dann xn+1 = xn −yn lösen. Wir müssen also ein lineares Gleichungssystem lösen. Ist F ein etwas kompliziertzu berechnendes Objekt, dann sind seine Ableitungen im allgemeinen noch viel schwierigerzu berechnen und zu kodieren, und die Rechnung kann sich als praktisch undurchführbarerweisen. Dann nimmt man seine Zuucht zur numerischen Ableitung: ist ej der Vektor aufRn, der überall 0 ist auÿer der j-ten Komponente, die gleich 1 ist, dann liefert (F (x+ hej)−F (x))/h eine (gute) Näherung der j-ten Spalte der Jacobi-Matrix. Wir müssen also n +1 Auswertungen von F vornehmen, um J näherungsweise zu erhalten, was sehr aufwendigist, wenn n groÿ ist. Und wenn wir ein iteratives Verfahren vom Krylow-Typ zur Lösungdes Systems J(xn)yn einsetzen? Wir sehen dann, dass J(xn)V ≈ (F (xn + hV ) − F (xn))/hfür hinreichend kleines h wird, und das vermeidet die Berechnung der gesamten Matrix.In SciPy muss also nur ein linearer Operator deniert werden wie es die Funktion V →(F (xn+hV )−F (xn))/h ist. Solche Verfahren werden aktuell zur Lösung groÿer, nichtlinearerGleichungssysteme eingesetzt. Ist die Matrix nicht symmetrisch, wird man beispielsweiseGMRES benutzen.

296

Page 313: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

Dieses Kapitel behandelt die numerische Berechnung von Integralen (Abschnitt 14.1) sowiedie numerische Lösung von gewöhnlichen Dierentialgleichungen (Abschnitt 14.2) mit Sage.Wir wiederholen die theoretischen Grundlagen der Integrationsverfahren, danach besprechenwir die verfügbaren Funktionen und ihren Gebrauch im einzelnen (Unterabschnitt 14.1.1).

Die symbolische Integration mit Sage ist bereits behandelt worden (Unterabschnitt 2.3.8),und wird hier nur kursorisch erwähnt als eine Möglichkeit für die Berechnung des nume-rischen Wertes eines Integrals. Dieses Vorgehen (erst symbolisch, dann rechnerisch) bildet,sofern es möglich ist, eine der Stärken von Sage und ist vorzuziehen, denn die Anzahl der aus-zuführenden Rechenschritte und damit die Gröÿe der Rundungsfehler ist gemeinhin kleinerals bei der numerischen Integration.

Wir geben eine knappe Einführung in die klassischen Verfahren für die Lösung von Die-rentialgleichungen, sodann wird die Behandlung eines Beispiels (Unterabschnitt 14.2.1) dasInventar der verfügbaren Funktionen anführen.

14.1. Numerische Integration

Wir interessieren uns für die numerische Berechnung von Integralen reeller Funktionen; füreine Funktion f : I → R, worin I ein Intervall von R ist, wollen wir∫

I

f(x)dx

berechnen. Wir berechen beispielsweise

3∫1

exp(−x2) ln(x)dx.

Abb. 14.1 - Die Funktionen x 7→ exp(−x2) ln(x) und x 7→ sin(x2)

x2.

297

Page 314: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

sage: x = var('x'); f(x) = exp(-x^2)*log(x)sage: N(integrate(f, x, 1, 3))0.035860294991267694sage: plot(f, 1, 3, fill='axis')

Die Funktion integrate berechnet das symbolische Integral des Ausdrucks; um einen Zah-lenwert zu erhalten, muss das explizit verlangt werden.

Es ist im Prinzip auch möglich, Integrale auf einem Intervall zu berechnen, das nicht begrenztist:

N(integrate(sin(x^2)/(x^2), x, 1, infinity))0.285736646322853 + 6.93889390390723e-18*Iplot(sin(x^2)/(x^2), x, 1, 10, fill='axis')

Es existieren in Sage mehrere Verfahren zur numerischen Berechnung eines Integrals, undwenn sich ihre Implementierungen auch technisch unterscheiden, beruhen sie alle auf einemder beiden folgenden Prinzipien:

- polynomiale Interpolation (insbesondere das Verfahren von Gauÿ-Kronrod);

- Transformation der Funktion (doppelt exponentielles Verfahren).

Interpolierende Verfahren. Bei diesen Verfahren wertet man die zu integrierende Funktionf an einer bestimmten Zahl n von zweckmäÿig gewählten Punkten x1, x2, . . . , xn aus undberechnet einen Näherungswert des Integrals von f auf [a, b] mit

b∫a

f(x)dt ≈n∑i=1

wif(xi).

Die Koezienten wi werden die Gewichte des Verfahrens genannt. Sie werden durch die Bedin-gung bestimmt, dass das Verfahren für jedes Polynom f vom Grade n−1 genau sein muss. Fürdie festen Punkte (xi) sind die Gewichte (wi) durch diese Bedingung eindeutig bestimmt. DieOrdnung des Verfahrens wird als der höchste Grad der exakt integrierten Polynome bestimmt;diese Ordnung ist daher mindestens n− 1, kann aber auch gröÿer sein.

So wählt auch die Familie der Integrationsverfahren von Newton-Cotes (zu denen auch dieRechteck- die Trapez- und die Regel von Simpson gehören) äquidistante Integrationspunkteauf dem Intervall [a, b]:

sage: fp = plot(f, 1, 3, color='red')sage: n = 4sage: interp_points = [(1+2*u/(n-1), N(f(1+2*u/(n-1)))) for u in xrange(n)]sage: A = PolynomialRing(RR, 'x')sage: pp = plot(A.lagrange_polynomial(interp_points), 1, 3, fill='axis')sage: show(fp+pp)

298

Page 315: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.1. Numerische Integration

Bei den interpolierenden Verfahren kann man deshalb davon ausgehen, dass wir das Lagrange-Interpolationspolynom der gegebenen Funktion berechnen und dass der Wert dieses Integralsals Näherungswert des gesuchten Integrals ausgegeben wird. Diese beiden Etappen werden inWirklichkeit in einer Formel zusammengefasst, welche die Regel der Quadratur genannt wird.Das Interpolationspolynom von Lagrange wird aber nicht explizit berechnet, doch beeinusstdie Wahl der Stützstellen die Güte der Näherung erheblich, und die Wahl gleichverteilterStützstellen stellt die Konvergenz nicht sicher, wenn deren Anzahl steigt (Phänomen vonRunge). Dieses Integrationsverfahren kann daher zu Erscheinungen führen, wie sie in Abb.14.2 zu sehen sind.

Abb. 14.2 - Interpolation durch ein Polynom 10. Grades (blau) der Funktion x 7→ 1/(1 + x2) (rot) mit 11

äquidistanten Stützstellen im Intervall [−10, 10]. Das Phänomen von Runge zeigt sich an den Rändern.

299

Page 316: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

Wenn wir von Sage verlangen, ein Integral auf einem beliebigen Intervall numerisch zu berech-nen, wird das Integrationsverfahren nicht direkt auf das gesamte Intervall angewendet; wirunterteilen den Integrationsbereich in hinreichend kleine Intervalle, damit das elementare Ver-fahren ein hinreichend genaues Resultat liefert (wir sprechen von Komposition der Verfahren).Als Strategie für die Unterteilung kann man sich beispielsweise dem Verlauf der zu integrieren-den Funktion dynamisch anpassen: wenn wir Iba(f) den Wert des vom Integrationsverfahrenberechneten Wertes von

∫ ba f(x)dx nennen, vergleichen wir

I0 = Iba(f)

mitI1 = I(a+b)/2

a (f) + Ib(a+b)/2(f)

und wir beenden die Unterteilung, sobald |I0 − I1| klein ist gegenüber der bei der Rechnungverwendeten Genauigkeit. Hier ist der Begri der Ordnung eines Verfahrens wichtig: bei einemVerfahren n-ter Ordnung teilt die Zweiteilung des Integrationsbereiches den theoretischenFehler ohne Berücksichtigung des Rundungsfehlers durch 2n.

Ein in Sage zur Verfügung stehendes besonderes Interpolationsverfahren ist das Verfahrenvon Gauÿ-Legendre. Bei diesem Verfahren werden die n Integrationspunkte als Wurzeln desLegendre-Polynoms n-ten Grades bestimmt (mit einem Denitionsbereich, der in das Inter-vall der vorliegenden Integration, [a, b], korrekt übersetzt ist). Die Eigenschaften der für dasSkalarprodukt orthogonalen Legendre-Polynome

〈f, g〉 =

b∫a

f(x)g(x)dx

bewirken, dass das Integrationsverfahren die Integrale bis 2n− 1-ten Grades genau berechnetund nicht nur bis zum n − 1-ten Grad, wie man erwarten könnte. Zudem sind die entspre-chenden Gewichte der Integration stets positiv, was das Verfahren gegenüber den numerischenProblemen des Typs Auslöschung1 weniger verwundbar macht.

Um mit den Interpolationsverfahren zum Ende zu kommen ist das Verfahren von Gauÿ-Kronrod an 2n + 1 Punkten eine Verbesserung des Verfahrens von Gauÿ-Legendre an nPunkten:

- unter den n+ 1 Punkten benden sich die n Punkte des Verfahrens von Gauÿ-Legendre,

- das Verfahren ist exakt für jedes Polynom höchstens 3n+ 1-ten Grades.

Ganz unvoreingenommen können wir sehen, dass die 3n + 2 Unbekannten (2n + 1 Gewichteund n + 1 hinzugenommene Punkte) a priori dadurch bestimmt sind, das verlangt wird,dass das Verfahren mindesten 3n+ 1-ter Ordnung sein soll (was 3n+ 2 Bedingungen ergibt).Aber Vorsicht: die mit dem Verfahren von Gauÿ-Kronrod verbundenen Gewichte an den nPunkten von Gauÿ-Legendre müssen nicht diejenigen sein, die ihnen bei dem Verfahren vonGauÿ-Legendre zugeordnet werden.

Das Interesse an einem solchen verbesserten Verfahren erwächst, sobald wir überlegen, dassder Hauptaufwand bei einem Integrationsalgorithmus die Anzahl der Auswertungen der zuintegrierenden Funktion f ist (besonders dann, wenn die Punkte und Gewichte tabelliert

1Diese Erscheinung zeigt sich, wenn eine Summe absolut signikant kleiner ist als die Summanden: jederRundungsfehler kann dann gröÿer werden als das Endergebnis, wobei die Genauigkeit völlig verloren geht;siehe auch Unterabschnitt 11.3.3.

300

Page 317: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.1. Numerische Integration

sind). Da das Verfahren von Gauÿ-Kronrod im Prinzip genauer ist als das Verfahren vonGauÿ-Legendre, können wir sein Ergebnis I1 verwenden, um das Ergebnis I0 des letzteren zubestätigen und eine Abschätzung des Fehlers von |I1 − I0| zu bekommen, was die Anzahl derAufrufe von f verringert. Diese für das Verfahren von Gauÿ-Legendre eigentümliche Strategiekönnen wir mit der allgemeineren Strategie der Unterteilung vergleichen, die wir auf Seite 300gesehen haben.

Doppelt exponentielle Verfahren. Die doppelt exponentiellen Verfahren (DE) beruhen ei-nerseits auf einem Wechsel der Variablen, der auf R einen beschränkten Integrationsbereichtransformiert und andererseits auf der mit dem Trapezverfahren auf R erhaltenen sehr gutenGenauigkeit für analytische Funktionen.

Für eine auf R integrierbare Funktion f und eine Schrittweite h besteht das Trapezverfahrenaus der Berechnung von

Ih = h

+∞∑i=−∞

f(hi)

als Näherungswert von∫ +∞−∞ f(x)dx. Die doppelt exponentielle Transformation ist 1973 von

Takahasi und Mori entwickelt worden und wird aktuell von Programmen für die numerischeIntegration verwendet. Eine Einführung in die Transformation und ihre Entdeckung wird in[Mor05] mitgeteilt; hier soll das Wesentliche wiedergegeben werden. Man ndet darin insbe-sondere eine Erklärung für die frappierende Genauigkeit, die mit dem Trapezverfahren (dasin gewissem Sinne optimal ist) bei analytischen Funktionen erreicht wird.

Zur Berechnung von

I =

1∫−1

f(x)dx

kann eine Transformation x = ϕ(t) benutzt werden, wobei ϕ auf R analytisch ist und dieBedingungen

limt→−∞

ϕ(t) = −1 und limt→∞

ϕ(t) = 1

erfüllt. Dann ist

I =

∞∫−∞

f(ϕ(t))ϕ′(t)dt.

-3 -2 -1 1 2 3

-1

-0.5

0.5

1

-3 -2 -1 1 2 3

0.2

0.4

0.6

0.8

1

1.2

1.4

1.6

Abb. 14.3 - Die im doppelt exponentiellen Verfahren verwendete Transformation ϕ(t) = tanh(π2

sinh t) (links)

und die Abnahme von ϕ′(t) (rechts).

301

Page 318: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

Wir wenden die Trapezformel auf den letzten Ausdruck an und berechnen

INh = h

N∑k=−N

f(ϕ(kh))ϕ′(kh)

mit einer bestimmten Schrittweite h, wobei wir die Summe auf die Terme von −N bis Nbeschränken. Die vorgeschlagene Transformation ist

ϕ(t) = tanh(π

2sinh t

).

Das ergibt die Formel

INh = hN∑

k=−Nf(

tanh(π

2sinh kh

)) π2 cosh kh

cosh2(π2 sin kh).

Die Formel verdankt ihren Namen der doppelt exponentiellen Abnahme von

ϕ′(t) =π2 cosh t

cosh2(π2 sinh t),

wenn |t| → ∞ geht (siehe Abb. 14.3). Das Prinzip der Transformation besteht darin, dasWesentliche des Beitrags der zu integrierenden Funktion um 0 herum zu konzentrieren, von wodie starke Abnahme rührt, wenn |t| wächst. Es gilt einen Kompromiss zu nden zwischen derFestlegung der Parameter und der verwendeten Transformation ϕ: eine schnellere Abnahme alsdie doppelt exponentielle vermindert den durch den Abbruch entstehenden Fehler, vergröÿertjedoch den Fehler durch die Diskretisierung.

Nach der Entwicklung der DE-Transformation wird dieses Verfahren allein oder zusammen mitanderen Transformationen angewendet, je nach der Art des Integranden, seiner Singularitätenund des Integrationsbereiches. Ein solches Beispiel ist die Kardinalsinus-Zerlegung sinc:

f(x) ≈N∑

k=−Nf(kh)Sk,h(h)

-4 -3 -2 -1 1 2 3 4

-0.2

0.2

0.4

0.6

0.8

1

Abb. 14.4 - Die Kardinalsinus-Funktion

302

Page 319: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.1. Numerische Integration

mit

Sk,h(x) =sin(π(x− kh)/h)

π(x− kh)/h,

was zusammen mit dem doppelt exponentiellen Verfahren in [TSM05] zur Verbesserung dervorstehenden Formeln verwendet wird, die nur eine einfach exponentielle Transformationϕ(t) = tanh(t/2) benutzen. Die Funktion sinc ist deniert durch

sinc =

1 für x = 0,sin(πx)

πxsonst.

Ihren Graphen zeigt die Abbildung 14.4.

Die Auswahl der zu benutzenden Transformation bestimmt zu groÿen Teilen die Qualitätdes Ergebnisses bei Vorhandensein von Singularitäten an den Grenzen (bei Singularitätenim Inneren des Intervalls gibt es hingegen keine gute Lösung). Später werden wir sehen,dass in der betrachteten Version von Sage nur die Integrationsfunktionen von PARI doppeltexponentielle Transformationen benutzen mit der Möglichkeit, das Verhalten an den Grenzenzu präzisieren.

14.1.1. Funktionen für die Integration

Wir werden uns nun die verschiedenen Arten der Berechnung eines numerischen Integralsanhand einiger Beispiele der Berechnung von Integralen genauer ansehen:

I1 =

42∫17

exp(−x2) log(x)dx, I2 =

1∫0

x log(1 + x)dx =1

4,

I3 =

1∫0

√1− x2dx =

π

4,

I4 =

1∫0

max(sin(x), cos(x))dx =

π4∫

0

cos(x)dx+

1∫π4

sin(x)dx

= sinπ

4+ cos

π

4− cos 1 =

√2− cos 1,

I5 =

1∫0

sin(sin(x))dx, I6 =

x∫0

sin(x) exp(cos(x))dx = e− 1

e,

I7 =

1∫0

1

1 + 1010x2dx = 10−5 arctan(105), I8 =

1.1∫0

exp(−x100)dx,

I9 =

10∫0

x2 sin(x3)dx =1

3(1− cos(1000)), I10 =

1∫0

√xdx =

1

3.

Wir behandeln die Funktionen zur Integration hier nicht erschöpfend - das ndet man in derOnline-Hilfe - vielmehr nur deren eher normale Verwendung.

303

Page 320: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

N(integrate(...)). Das erste Verfahren, das wir mit Sage zur numerischen Berechnungverwenden können, ist N(integrate(...)):

sage: N(integrate(exp(-x^2)*log(x), x, 17, 42))2.5657285006962035e-127

Es ist nicht garantiert, dass die Integrale auf diese Weise wirklich numerisch berechnet werden,in der Tat verlangt die Funktion integrate eine symbolische Integration. Wenn diese möglichist, wird Sage den erhaltenen symbolischen Ausdruck nur auswerten:

sage: integrate(log(1+x)*x, x, 0, 1)1/4sage: N(integrate(log(1+x)*x, x, 0, 1))0.250000000000000

Die Funktion numerical_integral verlangt im Gegenteil explizit eine numerische Integrationder als Parameter gegebenen Funktion. Dafür benutzt sie die numerische Bibliothek GSL(GNU Scientic Library), welche das Verfahren von Gauÿ-Kronrod für eine feste Zahl n vonIntegrationspunkten implementiert. Die Punkte und Gewichte sind vorberechnet, und dieGenauigkeit ist auf die Genauigkeit der Flieÿpunktzahlen der Maschine begrenzt (53 Bitsder Mantisse). Das Resultat ist ein Paar, das sich aus dem berechneten Ergebnis und einerAbschätzung des Fehlers zusammensetzt:

sage: numerical_integral(exp(-x^2)*log(x), 17, 42)(2.5657285006962035e-127, 3.3540254049238093e-128)

Die Abschätzung des Fehlers ist keine garantierte Schranke für den eingetretenen Fehler,sondern ein Wert, der einfach auf die Schwierigkeit der Berechnung des gegebenen Integralsverweist. Bei obigem Beispiel stellen wir fest, dass aufgrund der gegebenen Fehlerabschätzngalle Ziern des Ergebnisses (auÿer der ersten) zweifelhaft sind.

Die Argumente von numerical_integral erlauben vor allem

- die Anzahl der verwendeten Punkte festzulegen (sechs Einstellungen von rule=1 für 15Punkte bis rule=6 für 61 Punkte, den voreingestellten Wert);

- eine adaptive Unterteilung zu verlangen (Festlegung voreingestellt) oder eine direkte An-wendung des Verfahrens ohne Zusätze auf dem Integrationsbereich (durch Hinzufügung vonalgorithm='qng');

- die Anzahl der Aufrufe des Integranden zu begrenzen.

Wird GSL an einer adaptiven Integration gehindert, kann das zu einem Verlust an Genauigkeitführen:

sage: numerical_integral(exp(-x^100), 0, 1.1)(0.994325851191501, 4.077573041369464e-09)sage: numerical_integral(exp(-x^100), 0, 1.1, algorithm='qng')(0.9943275385765318, 0.016840666914688864)

Findet die Funktion integrate den analytischen Ausdruck nicht, der dem geforderten Integralentspricht, gibt sie den symbolischen Ausdruck unverändert zurück:

304

Page 321: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.1. Numerische Integration

sage: integrate(exp(-x^2)*log(x), x, 17, 42)integrate(e^(-x^2)*log(x), x, 17, 42)

und die numerische Rechnung, die mit N angestoÿen wird, verwendet numerical_integral.Dies erklärt insbesondere, weshalb der Genauigkeitsparameter in diesem Fall ignoriert wird:

sage: N(integrate(exp(-x^2)*log(x), x, 17, 42), 200)2.5657285006962035e-127

doch wir bekommen

sage: N(integrate(sin(x)*exp(cos(x)), x, 0, pi), 200)2.3504023872876029137647637011912016303114359626681917404591

denn hier ist die symbolische Integration möglich.

sage.calculus.calculus.nintegral. Bei den symbolisch denierten Funktionen ist es mög-lich, von Maxima zu verlangen, ein Integral numerisch zu berechnen:

sage: sage.calculus.calculus.nintegral(sin(sin(x)), x, 0, 1)(0.4306061031206906, 4.78068810228705e-15, 21, 0)

doch ist es ebenso möglich, die Methode integral bei einem Objekt des Typs Expressiondirekt aufzurufen:

sage: g(x) = sin(sin(x))sage: g.nintegral(x, 0, 1)(0.4306061031206906, 4.78068810228705e-15, 21, 0)

Maxima setzt die numerische Integrationsbibliothek QUADPACK ein, die wie GSL auf dieFlieÿpunktzahlen der Maschine beschränkt ist. Die Funktion nintegral verwendet eine Stra-tegie der adaptiven Unterteilung des Integrationsbereiches und wir können präzisieren:

- die für die Ausgabe gewünschte Genauigkeit;

- die maximale Anzahl der Teilintervalle, die bei der Rechnung betrachtet werden.

Die Ausgabe ist ein Tupel:

1. der Näherungswert des Integrals,

2. eine Abschätzung des absoluten Fehlers,

3. die Anzahl der Aufrufe des Integranden,

4. ein Fehlercode (0, wenn kein Problem aufgetreten ist; wegen der anderen Werte könnenSie mit sage.calculus.calculus.nintegralk? die Dokumentation befragen).

gp('intnum(...)'). In Sage steht das Programm PARI zur Verfügung und enthält auch denBefehl intnum zur numerischen Integration von Funktionen:

sage: gp('intnum(x=17, 42, exp(-x^2)*log(x))')2.5657285005610514829176211363206621657 E-127

Die Funktion intnum arbeitet nach dem doppelt exponentiellen Verfahren.

305

Page 322: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

Es ist möglich, die globale Genauigkeit des Interpreters PARI und damit die Genauigkeit desErgebnisses festzulegen:

sage: gp('intnum(x=0, 1, sin(sin(x)))')0.43060610312069060491237735524846578643sage: old_prec = gp.set_precision(50)sage: gp('intnum(x=0, 1, sin(sin(x)))')0.43060610312069060491237735524846578643360804182200

Ein gröÿerer Nachteil dieser Methode ist, dass die zu integrierende Funktion wegen der Syn-tax von PARI als Zeichenkette angegeben werden muss. Deshalb kann nicht jede beliebigeFunktion integriert werden.

Die Funktion intnum gestattet die Angabe des Verhaltens des Integranden an den Grenzen desIntegrationsbereiches. Das folgende Beispiel illustriert den Einuss, den das auf die Genauig-keit des Ergebnisses haben kann. Integrieren wir x 7→ x−1/2 zunächst ohne diese Angabe:

sage: p = gp.set_precision(old_prec) # die voreingestellte Genauigkeitsage: gp('intnum(x=0, 1, x^(-99/100))')73.62914262423378369

Mit Angabe der Art der Singularität, dass sich nämlich die Funktion bei x = 0 wie x 7→x−99/100 verhält, kommt richtig

sage: gp('intnum(x=[0, -99/100], 1, x^(-99/100))')100.00000000000000000000000000000000000

Der Anwender ist für die Richtigkeit der Angabe des Verhaltens verantwortlich; wird irrtümlichbeispielsweise gesagt, dass sich die Funktion bei x = 0 wie x 7→ x−1/42 verhält, wird der Fehlererheblich bleiben:

sage: gp('intnum(x=[0, -1/42], 1, x^(-99/100))')74.47274932028288503

mpmath.quad*. Die Bibliothek mpmath ist eine in Python geschriebene Bibliothek für be-liebig genaues numerisches Rechnen. Sie kann mit reellen und komplexen Flieÿpunktzahlenrechnen, mit Matrizen und Intervallen von reellen Flieÿpunktzahlen.

Sie verfügt über Funktionen zur numerischen Integration (die wichtigste ist quad) und kannin Sage importiert werden:

sage: import mpmathsage: mpmath.mp.prec = 53sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])mpf('0.43060610312069059')

Es gibt keine Garantie, dass der Ausgabewert die geforderte Genauigkeit aufweist, wie wiranhand des folgenden Beispiels sehen können:

sage: mpmath.mp.prec = 113sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])mpf('0.430606103120690604912377355248465809')

306

Page 323: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.1. Numerische Integration

sage: mpmath.mp.prec = 114sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])mpf('0.430606103120690604912377355248465785')

Es ist möglich, die geforderte Genauigkeit als Anzahl der Dezimalstellen anzugeben (mpmath.mp.dps)oder als Anzahl der Bits (mpmath.mp.prec). Zwecks Übereinstimmung mit der Funktion N vonSage verwenden wir nur die Genauigkeit in Bits.

Die Funktion mpmath.quad kann entweder das Verfahren von Gauÿ-Legendre aufrufen oderdie doppelt exponentielle Transformation (letztere ist voreingestellt). Mit den Funktionenmpmath.quadg1 und mpmath.wuadts2 kann die zu verwendende Methode direkt angegebenwerden.

Eine wichtige Einschränkung bei der Benutzung der Funktionen von mpmath zur Integrationist, dass sie nicht mit beliebigen in Sage denerten Funktionen zurechtkommen:

sage: mpmath.quad(sin(sin(x)), [0, 1])Traceback (most recent call last):...TypeError: no canonical coercion from<type 'sage.libs.mpmath.ext_main.mpf'> to Symbolic Ring

Die Situation ist jedoch nicht so problematisch wie bei PARI, welches auf eine Interaktion inTextform angewiesen ist. Tatsächlich können nämlich für Auswertung und Konversion nötigeFunktionen hinzugefügt werden, um beliebige Funktionen mit mpmath.quad integrieren zukönnen3:

sage: g(x) = max_symbolic(sin(x), cos(x))sage: mpmath.mp.prec = 100

0 0.2 0.4 0.6 0.8 1

0.7

0.75

0.8

0.85

0.9

0.95

1

Abb. 14.5 - Die Funktion x 7→ max(sin(x), cos(x)). Die Irregularität bei π/4 führt zu einer sehr

problematischen Integration

2Die verwendete Transformation ϕ : t 7→ tanh(π2

sinh(t))wurde schon vorgestellt.

3Der Leser, der wissen möchte, weshalb wir max_symbolic verwendet haben, wird es mit max probieren unddann die Dokumentation von max_symbolic konsultieren.

307

Page 324: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

sage: mpmath.quadts(lambda x: g(N(x, 100)), [0, 1])mpf('0.873912416263035435957979086252')

Wir stellen fest, dass die Integration von nichtregulären Funktionen (wie das Beispiel I4 weiteroben) einen Genauigkeitsverlust zur Folge haben kann, selbst dann, wenn wir ein Ergebnismit hoher Genauigkeit forden:

sage: mpmath.mp.prec = 170sage: mpmath.quadts(lambda x: g(N(x, 190)), [0, 1])mpf('0.87391090757400975205393005981962476344054148354188794')sage: N(sqrt(2) - cos(1), 100)0.87391125650495533140075211677

Nur fünf Stellen sind hier korrekt. Man kann mpmath dennoch helfen, indem eine Unterteilungdes Integrationsbereiches vorgenommen wird (hier im irregulären Punkt, siehe Abb. 14.5):

sage: mpmath.quadts(lambda x: g(N(x, 170)), [0, mpmath.pi / 4, 1])mpf('0.87391125650495533140075211676672147483736145475902551')

Nichtstetige Funktionen stellen für die Integrationsverfahren eine klassische Falle dar. Trotz-dem kann eine Strategie der automatischen Anpassung durch Unterteilung den Schaden be-grenzen.

Übung 47 (Berechnung der Koezienten von Newton-Cotes). Wir versuchen, die Koezien-ten des Verfahrens von Newton-Cotes in n Punkten zu berechnen, das in Sage nicht verfügbarist. Zur Vereinfachung überlegen wir, dass der Integrationsbereich I = [0, n− 1] ist, demnachdie Integrationspunkte x1 = 0, x2 = 1, . . ., xn = n− 1. Die Koezienten (wi) des Verfahrenssind derart, dass die Gleichung

n−1∫0

f(x)dx =

n−1∑i=0

wif(i) (14.1)

für jedes Polynom f höchstens n− 1-ten Grades exakt ist.

1. Wir betrachten für i ∈ 0, . . . , n− 1 das Polynom Pi(X) =n−1∏

j=0,j 6=i(X − xj). Die Glei-

chung (14.1) ist auf Pi anzuwenden, um wi als Funktion von Pi zu erhalten.

2. Daraus ist eine Funktion NCRule herzuleiten, welche den n Punkten auf dem Intervall[0, n− 1] die Koezienten des Verfahrens von Newton-Cotes zuordnet.

3. Zeigen Sie, wie diese Gewichte auf einen beliebigen Integrationsbereich [a, b] anzuwendensind.

4. Schreiben Sie eine Funktion QuadNC, die das Integral einer Funktion auf einer Teilmengevon R berechnet, die durch einen Parameter gegeben ist. Vergleichen Sie das Resultatmit den Ergebnissen der in Sage zur Verfügung stehenden Funktionen für die IntegraleI1 bis I10.

308

Page 325: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.2. Numerische Lösung gewöhnlicher Dierentialgleichungen

14.2. Numerische Lösung gewöhnlicher Dierentialgleichungen

Wir interessieren uns in diesem Abschnitt für die numerische Lösung von gewöhnlichen Dif-ferentialgleichungen. Die in Sage für die Lösung verfügbaren Funktionen sind in der Lage,Gleichungssysteme der Form

dy1

dt(t) = f1(t, y1(t), y2(t), . . . , yn(t))

dy2

dt(t) = f2(t, y1(t), y2(t), . . . , yn(t))

...dyndt

(t) = fn(t, y1(t), y2(t), . . . , yn(t))

mit den Anfangsbedingungen y1(0), y2(0), . . . , yn(0) zu behandeln.

Diese Formeln machen es möglich, dass wir uns auch für Probleme mit Ordnungen über1 interessieren, indem wir zusätzliche Variablen einführen (siehe das in 14.2.1 entwickelteBeispiel). Sie gestatten jedoch nicht, das durch die ρ-Funktion von Dickman

uρ′(u) + ρ(u− 1) = 0 für u ≥ 1,ρ(u) = 1 für 0 ≤ u ≤ 1

beschriebene Gleichungssystem auszudrücken. Die Werkzeuge zur Lösung von gewöhnlichenDierentialgleichungen sind an eine solche Gleichung nämlich nicht angepasst (sog. retardierteDierentialgleichung).

Die sog. Einschritt-Verfahren zur numerischen Lösung machen alle von demselben allgemei-nen Prinzip Gebrauch: für einen Schritt h und bekannte Werte von y(t0) und y′(t0) berechnetman einen Näherungswert von y(t0+h) und geht dabei von einem Schätzwert für y′(t) aus, derauf dem Intervall [t0, t0 + h] genommen wird. Beispielsweise besteht das einfachste Verfahrenin der Näherung

∀t ∈ [t0, t0 + h], y′(t) ≈ y′(t0),

t0+h∫t0

y′(t)dt ≈ hy′(t0),

y(t0 + h) ≈ y(t0) + hy′(t0).

Wenn hier y′ durch eine konstante Funktion angenähert wird, erinnert das an das numerischeIntegrationsverfahren mit Rechtecken. Das vorliegende Verfahren ist von 1. Ordnung, d.h.dass der nach einem Rechenschritt erhaltene Fehler unter der Annahme, dass f hinnreichendgleichmäÿig verläuft, im Bereich O(h2) liegt. Allgemein ist ein Verfahren von der Ordnung p,wenn der bei einem Schritt erhaltene Fehler im Bereich O(hp+1) bleibt. Der für t1 = t0 + herhaltene Wert dient dann als Ausgangspunkt für den nächsten Schritt und so lange weiterwie gewünscht.

Dieses nach Euler benannte Verfahren 1. Ordnung ist nicht wegen seiner Genauigkeit be-rühmt (genauso wie die Integration mit Rechtecken), und es gibt Verfahren höherer Ord-nung, beispielsweise das Verfahren von Runge-Kutta 2. Ordnung zur Lösung der Gleichung

309

Page 326: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

y′ = f(t, y):

k1 = hf(tn, y(tn))

k2 = hf(tn +1

2h, y(tn) +

1

2k1)

y(tn+1) ≈ y(tn) + k2 +O(h3)

Bei diesem Verfahren wird versucht, y′(tn + h/2) auszuwerten, um einen besseren Schätzwertfür y(tn + h) zu erhalten.

Man ndet auch Mehrschritt-Verfahren (zum Beispiel die Verfahren von Gear), die darin beste-hen, y(tn) ausgehend von schon für l Schritte erhaltenenWerten (y(tn−1), y(tn−2), . . . , y(tn−L))zu berechnen. Diese Verfahren starten notwendigerweise mit einer Initialierungsphase bis eineausreichende Zahl von Schritten ausgeführt ist.

Genau wie das Verfahren zur numerischen Integration von Gauÿ-Kronrod existieren hybrideVerfahren zur Lösung von Dierentialgleichungen. So berechnet das Verfahren von Dormandund Prince mit den gleichen Stützstellen einen Wert 4. und 5. Ordnung, wobei letztere zurAbschätzung des Fehlers der ersteren dient. Wir sprechen hier von einem adaptiven Verfah-ren.

Wir unterscheiden noch die sogenannten expliziten Verfahren von den impliziten: bei einemexpliziten Verfahren ist der Wert y(tn+1) durch eine Formel gegegeben, die nur bekannteWerte benutzt; bei einem impliziten Verfahren muss eine Gleichung gelöst werden. Nehmenwir als Beispiel das implizite Euler-Verfahren:

y(tn−1) = y(tn) + hf(tn+1, y(tn+1)).

Wir stellen fest, dass der gesuchte Wert y(tn+1) auf beiden Seiten der Gleichung vorkommt;ist die Funktion f hinreichend komplex, muss ein nichtlineares algebraisches Systen gelöstwerden, typischerweise mit dem Newton-Verfahren (siehe Unterabschnitt 12.2.2).

A priori erwarten wir umso genauere Ergebnisse zu bekommen, je kleiner wir den Integrati-onsschritt h machen; auÿer dem Aufwand für zusätzliche Rechnungen, den das kostet, wirdder erhote Gewinn an Genauigkeit teilweise wieder aufgezehrt durch eine gröÿere Anzahlvon Rundungsfehlern, die das Ergebnis auf lange Sicht belasten.

14.2.1. Beispiellösung

Betrachten wir den van-der-Pol-Oszillator mit dem Parameter µ, der der folgenden Dieren-tialgleichung genügt:

d2x

dt2(t)− µ(1− x2)

dxdt

(t) + x(t) = 0.

Setzen wir y0(t) = x(t) und y1(t) = dxdt , erhalten wir dieses System 1. Ordnung:dy0

dt= y1

dy1

dt= µ(1− y2

0)y1 − y0

Um es zu lösen, werden wir ein Löser-Objekt verwenden, das wir mit dem Befehl ode_solverbekommen:

310

Page 327: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.2. Numerische Lösung gewöhnlicher Dierentialgleichungen

sage: T = ode_solver()

Ein Löser-Objekt dient zur Aufnahme der Parameter und zur Denition des zu lösenden Sys-tems; es verschat Zugri auf die in der Bibliothek GSL vorhandenen und im Zusammenhangmit der numerischen Integration bereits erwähnten Funktionen zur numerischen Lösung vonDierentialgleichungen.

Die Gleichungen des Systems werden als Funktion angegeben:

sage: def f_1(t, y, params): return [y[1],params[0]*(1-y[0]^2)*y[1]-y[0]]sage: T.function = f_1

Der Parameter y steht für den Vektor der unbekannten Funktionen und wir sollten den Vek-tor der rechten Seite des System als Funktion von t und eines optionalen Parameters (hierparams[0], der für µ steht) zurückgeben.

Bestimmte Algorithmen von GSL benötigen zusätzlich die Jacobi-Matrix des Systems (dieMatrix mit den Einträgen ∂fi

∂yjan der Stelle (i, j) und deren letzte Zeile ∂fj

∂t enthält):

sage: def j_1(t, y, params):....: return [[0,1],....: [-2*params[0]*y[0]*y[1]-1, params[0]*(1-y[0]^2)],....: [0,0]]sage: T.jacobian = j_1

Nun kann eine numerische Lösung verlangt werden. Wir legen den Algorithmus und dasIntervall fest, auf dem die Lösung zu berechnen ist und die Anzahl der gewünschten Schritte(wodurch h bestimmt wird):

sage: T.algorithm = "rk8pd"sage: T.ode_solve(y_0=[1,0], t_span=[0,100], params=[10],....: num_points=1000)sage: f = T.interpolate_solution()

Hier haben wir für die Lösung auf [0, 100] den Algorithmus von Runge-Kutta Dormand-Prince genommen; die Anfangsbedingungen und die Werte der Parameter (hier nur einer) sindebenfalls gegeben: hier steht y_0=[1,0] für y0(0) = 1, y1(0) = 0, d.h. x(0) = 1, x′(0) = 0.

Der Graph der Lösung zeigt (mit plot(f, 0, 2)), dass die Ableitung bei t = 0 gleich nullist),

sage: plot(f, 0, 100)

311

Page 328: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

14.2.2. Verfügbare Funktionen

Unter den Löser-Objekten von GSL haben wir das Verfahren rk8pd bereits erwähnt. WeitereVerfahrenen sind:

rkf45: Runge-Kutta-Fehlberg, ein adaptives Verfahren 5. und 4. Ordnung,

rk2: adaptives Runge-Kutta 3. und 2. Ordnung,

rk4: das klassische Runge-Kutta-Verfahren 4. Ordnung,

rk2imp: ein implizites Runge-Kutta-Verfahren 2. Ordnung mit Auswertung in Intervallmitte,

rk4imp: eim implizites Runge-Kutta-Verfahren 4. Ordnung mit Auswertung an den Gauÿ-Punkten,4

bsimp: das implizite Verfahren von Burlisch-Stoer,

gear1: das implizite Einschritt-Verfahren von Gear,

gear2: das implizite Zweischritt-Verfahren von Gear.

Den an Einzelheiten zu diesen Verfahren interessierten Leser verweisen wir auf [AP98] oder[CM84].

Es ist anzumerken, dass die Beschränkung von GSL auf Maschinenzahlen - und damit aufeine feste Genauigkeit -, die bei der numerischen Integration schon angesprochen worden ist,auch für die Lösungsverfahren von Dierentialgleichungen gültig bleibt.

4Es handelt sich um die Wurzeln des Legendre-Polynoms 2. Grades auf dem Intervall [t, t+ h]. Sie sind nachdem Integrationsverfahren von Gauÿ-Legendre benannt.

312

Page 329: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.2. Numerische Lösung gewöhnlicher Dierentialgleichungen

Maxima stellt mit seiner eigenen Syntax ebenfalls numerische Routinen für die Lösung be-reit:

sage: t, y = var('t, y')sage: desolve_rk4(t*y*(2-y), y, ics=[0,1], end_points=[0, 1], step=0.5)[[0, 1], [0.5, 1.12419127424558], [1.0, 1.461590162288825]]

Die Funktion desolve_rk4 benutzt das Runge-Kutta-Verfahren 4. Ordnung (genau wie rk4in GSL) und erhält als Parameter

- die rechte Seite der Gleichung y′(t) = f(t, y(t)), hier y′ = ty(2− y);

- den Namen der unbekannten Funktionsvariablen, hier y;

- die Anfangsbedingungen ics, hier t = 0 und y = 1;

- das Intervall für die Lösung end_points, hier [0, 1];

- die Schrittweite step, hier 0.5.

Wir besprechen hier nicht den ähnlichen Befehl desolve_system_rk4, der schon im 4. Kapitelerwähnt wurde und der auf ein System von Dierentialgleichungen angewendet wird. AuchMaxima wird durch die Maschinengenauigkeit begrenzt.

Sucht man Lösungen, die mit beliebig groÿer Genauigkeit berechnet werden, kann man sichodefun aus dem Modul mpmath zuwenden.

sage: import mpmathsage: mpmath.mp.prec = 53sage: sol = mpmath.odefun(lambda t, y: y, 0, 1)sage: sol(1)mpf('2.7182818284590451')sage: mpmath.mp.prec = 100sage: sol(1)mpf('2.7182818284590452353602874802307')sage: N(exp(1), 100)2.7182818284590452353602874714

Die Argumente der Funktion mpmath.odefun sind:

- die rechte Seite des Gleichungssystems als Funktion (t, y) 7→ f(t, y(t)), hier y′ = y wie beider Funktion ode_solver. Die Dimension des Systems wird automatisch aus der Dimensiondes Rückgabewertes der Funktion hergeleitet;

- die Anfangsbedingungen t0 und y(t0), hier y(0) = 1.

Beispielsweise ist für das System der Dimension 2y′1 = −y2

y′2 = y1

mit den Lösungen (cos(t), sin(t)) und den Anfangsbedingungen y1(0) = 1 und y2(0) = 0:

sage: mpmath.mp.prec = 53sage: f = mpmath.odefun(lambda t, y: [-y[1], y[0]], 0, [1, 0])sage: f(3)

313

Page 330: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14. Numerische Integration und Dierentialgleichungen

[mpf('-0.98999249660044542'), mpf('0.14112000805986721')]sage: (cos(3.), sin(3.))(-0.989992496600445, 0.141120008059867)

Die Funktion mpmath.odefun wendet das Taylorverfahren an. Für einen Grad vom p nimmtman

y(tn+1) = y(tn) + hdydt

(tn) +h2

2!

d2y

dt2(tn) + . . .+

hp

p!

dpydtp

(tn) +O(hp+1).

Die Frage nach den Ableitungen ist die wichtigste. Dafür berechnet odefun die Näherungs-werte

[y(tn + h), . . . , y(tn + ph)] ≈ [y(tn + h), . . . , y(tn + ph)]

mit p Schritten des weniger genauen Euler-Verfahrens. Daraufhin berechnen wir

dydt

(tn) ≈ y(tn + h)− y(tn)

h,

˜dydt

(tn + h) ≈ y(tn + 2h)− y(tn + h)

h

und dann

d2y

dt2(tn) ≈

˜dydt (tn + h)− dy

dt (tn)

h,

und so fort bis man die Schätzwerte der Ableitungen von y(tn) bis zur Ordnung p erhält.

Wir müssen aufpassen, sobald die Flieÿpunkt-Genauigkeit von mpmath verändert wird. Umdieses Problem zu illustrieren, greifen wir die Lösung der Dierentialgleichung y′ = y wiederauf, die mit der weiter oben gegebenen Funktion exp veriziert wird:

sage: mpmath.mp.prec = 10sage: sol = mpmath.odefun(lambda t, y: y, 0, 1)sage: sol(1)mpf('2.7148')sage: mpmath.mp.prec = 100sage: :sol(1)mpf('2.7135204235459511323824699502438')

Die Näherung von exp(1) ist sehr schlecht, und das, obwohl mit einer Genauigkeit von 100Bits gerechnet wurde! Die Lösung sol (ein Interpolant im Jargon von mpmath) ist mit nur10 Bits Genauigkeit berechnet worden und ihre Koezienten sind nach der Änderung derGenauigkeit nicht neu berechnet worden, was das Ergebnis erlärt.

314

Page 331: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Teil IV.

Kombinatorik

315

Page 332: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 333: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Dieses Kapitel spricht haupsächlich die Behandlung der folgenden kombinatorischen Problememit Sage an: das Abzählen (wieviele Elemente gibt es in einer Menge S?), die Angabe (Be-rechnen aller Elemente von S oder die Iteration über sie), das zufäliige Ziehen (Zufallswahleines Elements aus S gemäÿ einer Vorschrift, z.B. Gleichverteilung) . Diese Fragen stellen sichnatürlich bei der Berechnung der Wahrscheinlichkeiten (wie groÿ ist die Wahrscheinlichkeitbeim Poker einen Straight Flush oder vier Asse zu erhalten?), in der statistischen Physik,aber auch beim symbolischen Rechnen (Anzahl der Elemente eines endlichen Körpers) oderbei der algorithmischen Analysis. Die Kombinatorik deckt ein viel weiteres Gebiet ab (par-tielle Ordnungen, Theorie der Abbildungen usw.). Wir begnügen uns mit Hinweisen auf vonSage angebotenen Möglichkeiten. Graphen werden in Kapiel 16 behandelt.

Ein Charakteristikum rechnender Kombinatorik ist die Fülle an Typen von Objekten undMengen, die man bearbeiten möchte. Es wäre nicht möglich, sie alle zu beschreiben oder garzu implementieren. Nach einigen Beispielen (Abschnitt 15.1) veranschaulicht dieses Kapiteldie zugrunde liegende Methodik: Bausteine zum Fundament zu liefern, um die üblichen kombi-natorischen Mengen zu beschreiben (in Abschnitt 15.2), um Werkzeuge zu ihrer Kombinationzwecks Bildung neuer Mengen zu liefern (in Abschnitt 15.3) und auch generische Algorithmen,mit denen eine groÿe Klasse von Aufgaben behandelt werden kann (in Abschnitt 15.4). Zu-nächst kann dieses Kapitel quer gelesen werden, die Zusammenfassungen von Unterabschnitt15.1.2 und Abschnitt 15.3 aber schon genauer.

Das ist ein Gebiet, wo Sage mehr Funktionalitäten hat als die meisten anderen Systeme zumsymbolischen Rechnen und in voller Entwicklung begrien ist; gleichzeitig ist es immer nochsehr jung mit vielen unnötigen Brüchen und Einschränkungen.

15.1. Erste Beispiele

15.1.1. Poker und Wahrscheinlichkeiten

Wir beginnen mit der Lösung eines klassischen Problems: des Abzählens bestimmter Kombi-nationen von Karten beim Poker, um deren Wahrscheinlichkeit abzuleiten.

Beim Poker ist eine Karte durch eine Farbe (Herz, Karo, Pik, Kreuz) und einen Wert (2,3, ..., 10, Bube, Dame, König, As) charakterisiert. Das Spiel wird mit allen Karten gespielt,die möglich sind; es handelt sich um das cartesische Produkt der Menge der Farben und derMenge der Werte:

Karten = Farben × Werte = (f, w) | f ∈ Farben und w ∈ Werte

Diese Mengen bilden wir in Sage:

317

Page 334: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

sage: Farben = Set(['Karo','Herz','Pik','Kreuz'])sage: Werte = Set([2..10] + ['Bube', 'Dame', 'Koenig', 'As'])sage: Karten = cartesian_product([Farben, Werte])

Beim Poker gibt es 4 Farben und 13 mögliche Werte, also 4×13 = 52 Karten.

sage: Farben.cardinality()4sage: Werte.cardinality()verb|13|sage: Karten.cardinality()52

Wir ziehen eine Karte:

sage: Karten.random_element()['Kreuz', 6]

Nun ziehen wir zwei Karten:

sage: Set([Karten.random_element(), Karten.random_element()])('Herz', 2), ('Pik', 4)

Zurück zu unserem Vorhaben. Wir betrachten hier eine vereinfachte Form von Poker, wo jederSpieler unmittelbar fünf Karten zieht, die sein Blatt oder seine Hand bilden. Alle Karten sindverschieden und die Reihenfolge, in der sie gezogen werden, spielt keine Rolle; eine Hand istalso eine Untermenge der Gröÿe 5 der Menge aller Karten. Um eine Hand zu ziehen, beginnenwir mit der Bildung der Menge aller möglichen Hände, dann entnehmen wir daraus zufälligeine Hand.

sage: Haende = Subsets(Karten, 5)sage: Haende.random_element()('Herz', 4), ('Karo', 9), ('Pik', 8), ('Kreuz', 9), ('Herz', 7)

Die Gesamtzahl der Hände ist durch die Anzahl der Teilmengen der Gröÿe 5 einer Menge derGröÿe 52, d.h. durch den Binomialkoezienten

(525

)gegeben:

sage: binomial(52,5)2598960

Man kann sich um das Berechnungsverfahren auch keine Sorgen machen und einfach nach derGröÿe der Menge der Hände fragen:

sage: haende.cardinality()2598960

Der Rang oder die Wertigkeit einer Hand beim Poker hängt von der Art der Kombinationdieser Karten ab. Eine dieser Kombinationen ist der Flush; das ist eine Hand mit lauter Kartenderselben Farbe (grundsätzlich sind hier Straight Flush und Royal Flush auszuschlieÿen; diesesind Gegenstand einer Übung weiter unten). Eine solche Hand ist also charakterisiert durcheine bestimmte Farbe von vier möglichen und durch fünf Werte von 13 möglichen. Wir bildendie Menge aller Flushes, um deren Anzahl zu berechnen:

318

Page 335: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.1. Erste Beispiele

sage: Flushes = cartesian_product([Subsets(Werte, 5), farben])sage: Flushes.cardinality()5148

Die Wahrscheinlichkeit, beim Ziehen einer Hand zufällig einen Flush zu bekommen, ist da-her:

sage: Flushes.cardinality()/Haende.cardinality()33/16660

oder ungefähr zwei Promille:

sage: 1000.0*Flushes.cardinality()/Haende.cardinality()1.98079231692677

Machen wir eine kleine numerische Simulation. Die folgende Funktion prüft, ob eine gegebeneHand ein Flush ist:

sage: def is_Flush(Hand):....: return len(set(Farbe for (Farbe, Wert) in Hand)) == 1

Wir ziehen jetzt zufällig 10000 Hände und berechnen die Anzahl der erhaltenen Flushes (dasdauert etwa 10 Sekunden):

sage: n = 10000; nFlushes = 0sage: for i in range(n):....: Hand = Haende.random_element()....: if is_Flush(hand):....: nFlushes += 1....: print n, nFlushes10000 18

Übung 48. Eine Hand mit vier Karten gleichen Wertes heiÿt Vierling. Bilden Sie eine Mengesolcher Vierlinge. (Hinweis: verwenden Sie Arrangements zum zufälligen Ziehen eines Paaresmit verschiedenen Werten, und wählen Sie dann eine Farbe für den ersten Wert). BerechnenSie die Anzahl möglicher Vierlinge, listen Sie sie auf und bestimmen Sie anschlieÿend dieWahrscheinlichkeit für das Ziehen einer Hand mit einem Vierling.

Übung 49. Eine Hand mit lauter Karten gleicher Farbe und aufeinander folgenden Werten istein Straight Flush oder ein Royal Flush, aber kein Flush. Berechnen Sie die Anzahl möglicherStraight Flushes und Royal Flushes und leiten Sie dann die korrekte Wahrscheinlichkeit dafürher, einen Flush zu erhalten, wenn eine Hand zufällig gezogen wird.

Übung 50. Berechnen Sie die Wahrscheinlichkeit jeder Kartenkombination beim Poker (siehehttps://de.wikipedia.org/wiki/Hand_(Poker)) und vergleichen Sie sie mit den Ergebnis-sen von Simulationen.

319

Page 336: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

15.1.2. Abzählen von Bäumen durch erzeugende Reihen

In diesem Unterabschnitt diskutieren wir das Beispiel vollständiger Binärbäume und veran-schaulichen in diesem Zusammenhang viele Abzähltechniken, unter denen die formalen Po-tenzreihen eine natürliche Rolle spielen. Diese Techniken sind ziemlich allgemein und könnenimmer dann angewendet werden, wenn das in Rede stehende kombinatorische Objekt einerekursive Denition (rekursive Grammatik) zulässt (siehe Unterabschnitt 15.4.4 wegen einerautomatisierten Behandlung). Das Ziel ist keine formale Darstellung dieser Verfahren; dieRechnungen sind streng, die Begründungen werden aber meistens weggelassen.

Ein vollständiger Binärbaum ist entweder ein Blatt F oder ein Knoten mit zwei Binärbäumen(siehe Abb. 15.1).

Übung 51. Suchen Sie ohne Rechnerhilfe alle vollständigen Binärbäume mit n = 1, 2, 3, 4, 5Blättern (siehe auch Übung 59, um sie mit Sage zu nden.)

F F F FF F

F

F F

FF

F

FF

F

FF

F F

F

Abb.15.1 - Die fünf vollständigen Binärbäume mit vier Blättern.

Unser Ziel ist, die Anzahl cn der vollständigen Binärbäume mit n Blättern zu suchen (in diesemAbschnitt steht Bäume immer für vollständige Binärbäume, wenn nicht ausdrücklich etwasanderes gesagt ist). Das ist eine typische Situation, in der wir nicht nur an einer einzelnenMenge interessiert sind, sondern an einer Familie von Mengen, die typischerweise mit n ∈ Nparametrisiert werden.

Entsprechend der Lösung von Übung 51 sind die ersten Terme durch c1, . . . , c5 = 1, 1, 2, 5, 14gegeben. Die einfache Tatsache diese Zahlen zu kennen, ist bereits sehr wertvoll. Sie erlaubtnämlich die Suche in einer Goldmine von Informationen: auf der Seite Online Encyclopedia of

Integer Sequences http://oeis.org/, die nach ihrem wichtigsten Autor gemeinhin Sloanegenannt wird. Sie enthält mehr als 282892 ganzzahlige Folgen:

sage: oeis([1,1,2,5,14])0: A000108: Catalan numbers: C(n) = binomial(2n,n)/(n+1) =(2n)!/(n!(n+1)!). Also called Segner numbers.1: A120588: G.f. satisfies: 3*A(x) = 2 + x + A(x)^2, with a(0) = 1.2: A080937: Number of Catalan paths (nonnegative, starting and ending at0, step +/-1) of 2*n steps with all values <= 5.

Das Ergebnis lässt erkennen, dass die Bäume mit einer der berühmtesten Folgen abgezähltwerden, den Catalan-Zahlen. Bei Durchsicht der Ausgabe der Enzyklopädie sehen wir, dasdies tatsächlich so ist: die wenigen eingebenen Zahlen bilden einen Fingerabdruck unsererObjekte, der uns in einer umfangreichen Literatur in wenigen Sekunden ein genaues Ergebnisnden lässt.

320

Page 337: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.1. Erste Beispiele

Abzählen mit erzeugenden Reihen. Unser Aufgabe ist es, dieses Resultat nun auch mitSage zu nden. Sei Cn die Menge der Bäume mit n Blättern, also cn = |Cn|. Wie üblichdenieren wir C0 = ∅ und c0 = 0. Die Menge aller Bäume ist dann die disjunkte Vereinigungder Mengen Cn:

C =⊎n∈N

Cn.

Nachdem wir die Menge C aller Bäume benannt haben, können wir die rekursive Denitionin eine mengentheoretische Gleichung übersetzen:

C ≈ L ] C × C.

In Worten: ein Baum t (der denitionsgemäÿ in C liegt) ist entweder ein Blatt (also in L)oder ein Knoten mit den beiden Bäumen t1 und t2, die wir deshalb mit dem Paar (t1, t2) (imcartesischen Produkt C × C) identizieren können.

Die Gründungsidee der algebraischen Kombinatorik, die von Euler in einem Brief an Gold-bach von 1751 zur Behandlung eines ähnlichen Problems eingeführt worden ist [Vie07], bestehtdarin, alle Zahlen cn simultan zu behandeln, indem sie als Koezienten einer formalen Po-tenzreihe kodiert werden, welche die erzeugende Funktion der cn genannt wird:

C(z) =∑n∈N

cnzn,

wobei z eine symbolische Unbestimmte ist (weshalb wir uns um die Frage der Konvergenz nichtsorgen müssen). Die Schönheit dieser Idee besteht darin, dass die Mengenoperationen (A]B,A×B) ganz natürlich in algebraische Operationen mit den Reihen (A(z)+B(z), A(z) ·B(z))übersetzt werden, und zwar so, dass die Mengengleichung, die von C erfüllt wird, in einealgebraische Gleichung mit C(z) überführt wird:

C(z) = z + C(z) · C(z).

Nun können wir diese Gleichung mit Sage lösen. Dazu führen wir die beiden Variablen C undz ein und denieren die Gleichung

sage: C, z = var('C, z'); sys = [C = z + C*C]|

Es gibt zwei Lösungen, die zufällig geschlossene Formen haben:

sage: sol = solve(sys, C, solution_dict=True); sol[C: -1/2*sqrt(-4*z + 1) + 1/2, C: 1/2*sqrt(-4*z + 1) + 1/2]sage: s0 = sol[0][C]; s1 = sol[1][C]

und deren Taylor-Entwicklung beginnt mit

sage: s0.series(z, 6)1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + Order(z^6)sage: s1.series(z,6)1 + (-1)*z + (-1)*z^2 + (-2)*z^3 + (-5)*z^4 + (-14)*z^5 + Order(z^6)

Die zweite Lösung ist oensichtlich unbrauchbar, wohingegen die erste die erwarteten Koe-zienten liefert. Daher setzen wir

sage: C = s0

321

Page 338: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Wir können nun die nächsten Terme berechnen:

sage: C.series(z, 11)1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + 42*z^6 +132*z^7 + 429*z^8 + 1430*z^9 + 4862*z^10 + Order(z^11)

oder im Nu den 100. Koezienten:

sage: C.series(z, 101).coefficient(z, 100)227508830794229349661819540395688853956041682601541047340

Leider muss alles nochmals berechnet werden, falls wir einmal den 101.Koezienten brauchen.Faule Potenzreihen (siehe Unterabschnitt 7.5.3) machen hier Sinn, zumal wir sie direkt auseinem Gleichungssystem denieren können, ohne es zu lösen und auch deshalb, weil wir fürdie Antwort keine geschlossene Form brauchen. Wir beginnen mit der Denition von faulenPotenzreihen

L.<z> = LazyPowerSeriesRing(QQ)

Dann erzeugen wir eine freie Potenzreihe, der wir einen Namen geben und die wir danndurch eine rekursive Gleichung denieren:

sage: C = L()sage: C._name = 'C'sage: C.define(z + C*C)

sage: [C.coefficient(i) for i in range(11)][0, 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]

Wir können nun einen beliebigen Koezienten erfragen, ohne C neu denieren zu müssen:

sage: C.coefficient(100)227508830794229349661819540395688853956041682601541047340

sage: C.coefficient(200)129013158064429114001222907669676675134349530552728882499810851598901419\013348319045534580850847735528275750122188940

Rekursion und geschlossene Form. Wir kommen nun auf die geschlossenen Form von C(z)zurück:

sage: z = var('z'); C = s0; C-1/2*sqrt(-4*z + 1) + 1/2

Der n-te Koezient der Taylorentwicklung von C(z) ist durch 1n!C

(n)(0) gegeben. Wir be-trachten dazu die sukzessiven Ableitungen C(n)(z):

sage: derivative(C, z, 1)1/sqrt(-4*z + 1)sage: derivative(C, z, 2)2/(-4*z + 1)^(3/2)sage: derivative(C, z, 3)12/(-4*z + 1)^(5/2)

322

Page 339: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.1. Erste Beispiele

Das lässt die Existenz einer einfachen expliziten Formel vermuten, nach der wir jetzt suchenwerden. Die folgende kleine Funktion gibt dn = n!cn zurück:

sage: def d(n): return derivative(C, n).subs(z=0)

Mit Verwendung sukzessiver Quotienten

sage: [ (d(n+1) / d(n)) for n in range(1,17) ][2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62]

bemerken wir, dass dn der rekursiven Bezehung dn+1 = (4n − 2)dn genügt, aus der wirherleiten, dass cn die Gleichung cn+1 = 4n−2

n+1 cn erfüllt. Wir vereinfachen und nden, dass cndie (n− 1)-te catalansche Zahl ist:

cn = Catalan (n− 1) =1

n

(2(n− 1)

n− 1

).

Das prüfen wir:

sage: def c(n): return 1/n*binomial(2*(n-1),n-1)sage: [c(k) for k in range(1, 11)][1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]sage: [catalan_number(k-1) for k in range(1, 11)][1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]

Wir können nun auch die viel späteren Koezienten berechnen; hier berechnen wir c100000,das mehr als 60000 Ziern hat:

sage: time cc = c(100000)Time: CPU 0.35 s, Wall: 0.37 ssage: ZZ(cc).ndigits()60198

Systematische Behandlung mit algebraischen Dierentialgleichungen. Das Verfahren, daswir verwendet haben, wird auf alle rekursiv denierten Objekte verallgemeinert: die Glei-chungssysteme für Mengen werden in Gleichungssysteme für die erzeugende Reihe übersetzt;das gestattet die rekursive Berechnung ihrer Koezienten. Wenn die Gleichungssysteme fürMengen hinreichend einfach sind (wenn beispielsweise nur cartesische Produkte und disjunkteVereinigungen vorkommen), erhalten wir eine algebraische Gleichung in C(z). Diese hat nichtimmer eine Lösung in geschlossener Form; indessen können wir aus ihr durch Eingrenzungeine lineare Dierentialgleichungen herleiten, die ihrerseits in eine Rekursionsgleichung fes-ter Länge für die Koezienten cn umgeformt wird (die Reihe wird nun D-endlich genannt).Schlieÿlich geht die Berechnung der Koezienten nach diesen Vorberechnungen sehr schnell.Alle diese Schritte sind rein algorithmisch, und es ist vorgesehen, alle in Maple (die Pakete gfunund combstruct) oder MuPAD-Combinat (die Bibliothek decomposableObjects) vorhandenenImplementierungen nach Sage zu übertragen.

Für den Moment veranschaulichen wir das allgemeine Vorgehen für den Fall vollständi-ger Binärbäume. Die erzeugende Funktion C(x) ist Lösung einer algebraischen GleichungP (z, C(z)) = 0, wobei P = P (x, y) ein Polynom mit Koezienten aus Q ist. Im vorliegendenFall ist P = y2 − y + x. Wir dierenzieren diese Gleichung symbolisch nach z:

323

Page 340: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

sage: x, y, z = var('x, y, z')sage: P = function('P')(x, y); C = function('C')(z)sage: equation = P(x=z, y=C) == 0sage: diff(equation, z)diff(C(z), z)*D[1](P)(z, C(z)) + D[0](P)(z, C(z)) == 0

oder in besser lesbarer Form

dC(z)

dz∂P

y(z, C(z)) +

∂P

∂x(z, C(z)) = 0.

Daraus leiten wir her:dC(z)

dz= −

∂P∂x∂P∂y

(z, C(z)).

Bei vollständigen Binärbäumen ergibt das:

sage: P = y^2 - y + x; Px = diff(P, x); Py = diff(P, y)sage: - Px / Py-1/(2*y - 1)

Nun ist aber P (x, y) = 0. Wir können deshalb diesen Bruch modulo P berechnen und so dieAbleitung von C(z) als Polynom in C(z) mit Koezienten aus Q(z). Dazu bilden wir denQuotientenring R = Q(x)[y]/(P ):

sage: Qx = QQ['x'].fraction_field(); Qxy = Qx['y']sage: R = Qxy.quo(P); RUnivariate Quotient Polynomial Ring in ybarover Fraction Field of Univariate Polynomial Ring in xover Rational Field with modulus y^2 - y + x

Bemerkung: ybar ist der Name der Variablen y im Quotienten; wegen weiterer Informationenzu Quotientenringen siehe Unterabschnitt 7.2.2. Wir setzen nun die Berechnung dieses Bruchesin R fort

sage: fraction = - R(Px) / R(Py); fraction(1/2/(x - 1/4))*ybar - 1/4/(x - 1/4)

Wir heben das Ergebnis nach Q(x)[y] und ersetzen dann z und C(z), um einen Ausdrück fürddzC(z) zu bekommen:

sage: fraction = fraction.lift(); fraction(1/2/(x - 1/4))*y - 1/4/(x - 1/4)sage: fraction(x=z, y=C)2*C(z)/(4*z - 1) - 1/(4*z - 1)

oder besser lesbar∂C(z)

∂z=

1

1− 4z− 2

1− 4zC(z).

In diesem einfachen Fall können wir aus diesem Ausdruck eine lineare Dierentialgleichungmit Koezienten aus Q[z] unmittelbar herleiten:

sage: equadiff = diff(C,z) == fraction(x=z, y=C); equadiffdiff(C(z), z) == 2*C(z)/(4*z - 1) - 1/(4*z - 1)

324

Page 341: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.1. Erste Beispiele

sage: equadiff = equadiff.simplify_rational()sage: equadiff = equadiff * equadiff.rhs().denominator()sage: equadiff = equadiff - equadiff.rhs()sage: equadiff(4*z - 1)*diff(C(z), z) - 2*C(z) + 1 == 0

oder besser lesbar

(1− 4z)∂C(z)

∂z+ 2C(z)− 1 = 0.

Es ist trivial, diese Gleichung in geschlossener Form zu verizieren:

sage: Cf = sage.symbolic.function_factory.function('C')sage: bool(equadiff.substitute_function(Cf, s0))True

Im allgemeinen fahren wir mit der Berechnung der sukzessiven Ableitungen von C(z) fort.Diese Ableitungen sind auf den Quotientenring Q(z)[C]/P beschränkt, der die endliche Di-mension degP auf Q(z) hat. Dafür nden wir zwischen den ersten degP Ableitungen vonC(z) eventuell eine lineare Beziehung. Setzen wir das auf einen gemeinsamen Nenner, erhaltenwir eine lineare Dierentialgleichung vom Grad ≤ degP mit Koezienten aus Q[z]. DurchHerausziehen des Koezienten von zn in der Dierentialgleichung bekommen wir die verlang-te rekursive Beziehung zwischen den Koezienten. Hier treen wir wieder auf die Beziehung,die wir - auf der geschlossenen Form basierend - breits gefunden hatten:

cn+1 =4n− 2

n+ 1cn

Nach Festlegung der korrekten Anfangsbedingungen wird es möglich, die Koezienten vonC(z) rekursiv zu ermitteln:

sage: def C(n): return n if n <= 1 else (4*n-6)/n * C(n-1)sage: [ C(i) for i in range(10) ][0, 1, 1, 2, 5, 14, 42, 132, 429, 1430]

Wird n zu groÿ für eine explizite Berechnung von cn kann eine asymptotisch äquivalenteFolge von Koezienten cn gesucht werden. Auch hier gibt es wieder generelle Techniken. Daszentrale Werkzeug ist komplexe Analysis, speziell die Untersuchung der erzeugenden Funktionin der Nähe ihrer Singularitäten. Bei der vorliegenden Aufgabe bendet sich die Singularitätbei z0 = 1/4 und wir bekämen cn ≈ 4n−1

n3/2√π.

Zusammenfassung. Wir erkennen hier ein allgemeines Phänomen der Computeralgebra:die beste Datenstruktur zur Beschreibung eines komplizierten mathematischen Objektes (ei-ne reelle Zahl, eine Folge, eine formale Potenzreihe, eine Funktion, eine Menge) ist oft eineGleichung, die das Objekt deniert (oder ein Gleichungssystem, typischerweise mit Anfangs-bedingungen). Eine Lösung in geschlossener Form zu nden zu versuchen, ist nicht immerinteressant: einerseits existiert eine solche geschlossene Fom nur selten (z.B. bei der Lösungvon Polynomen durch Radikale), und andererseits enthält die Gleichung alle für die algo-rithmische Berechnung der Eigenschaften des betrachteten Objektes notwendige Informationin sich (z.B. eine numerische Näherung, die ersten Terme oder Elemente, ein asymptotischesÄquivalent) oder für die Rechnung mit dem Objekt selbst (z.B. Arithmetik mit Potenzreihen).Deshalb suchen wir nach der Gleichung, die das Objekt beschreibt und zu dem zu lösendenProblem am besten passt; siehe auch Unterabschnitt 2.2.2.

325

Page 342: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Wie wir an unserem Beispiel gesehen haben, ist Eingrenzung (beispielsweise in einem endlich-dimensionalen Vektorraum) ein grundlegendes Werkzeug für die Untersuchung solcher Glei-chungen. Der Begri der Eingrenzung ist bei Eliminationsverfahren breit anwendbar (lineareAlgebra, Gröbner-Basen und ihre Verallgemeinerungen bei algebraischen Dierentialgleichun-gen). Dasselbe Werkzeug spielt bei der automatischen Summierung und der automatischenPrüfung von Identitäten eine zentrale Rolle (Algorithmen von Gosper oder Zeilberger undihre Verallgemeinerungen [PWZ96]; siehe auch die Beispiele in Unterabschnitt 2.3.1 und inÜbung 54).

Alle diese Techniken und ihre vielfältigen Verallgemeinerungen sind Gegenstand sehr inten-siver Forschungen: automatische und analytischbe Kombinatorik mit gröÿeren Anwendungenin der Analyse von Algorithmen [FS09]. Es ist wahrscheinlich und wünschenswert, dass sienach und nach in Sage implementiert werden.

15.2. Die üblichen abzählbaren Mengen

15.2.1. Beispiel: Teilmengen einer Menge

Stellen wir uns eine Menge E der Gröÿe n vor und betrachten ihre Teilmengen der Gröÿek. Wir wissen, dass diese Teilmengen durch Binomialkoezienten

(nk

)abgezählt werden. Wir

können deshalb die Anzahl der Teilmengen der Gröÿe k = 2 von E = 1, 2, 3, 4 mit derBinomialfunktion berechnen:

sage: binomial(4, 2)6

Alternativ können wir die Menge P2(E) der Teilmengen der Gröÿe 2 von E konstruieren unddann nach ihrer Kardinalität fragen;

sage: S = Subsets([1,2,3,4], 2); S.cardinality()6

Liegt S einmal vor, können wir auch die Liste der Elemente bekommen, ein Element zufälligauswählen oder ein typisches Element verlangen.

sage: S.list()[1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4]sage: S.random_element()1, 4sage: S.an_element()2, 3

Genauer, das Objekt S modelliert die Menge P2(E), die mit einer festen Ordnung (hier dielexikographische Ordnung) ausgestattet ist. Daher ist es möglich, nach ihrem 5. Elementzu fragen, wobei zu beachten ist, dass in Python das erste Element mit 0 indiziert ist: alsAbkürzung kann man hier auch schreiben:

sage: S.unrank(4)2, 4sage: S[4]2, 4

326

Page 343: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

Das sollte aber mit Vorsicht gemacht werden, weil manche Mengen eine andere Indizierunghaben als (0, . . .).

Umgekehrt können wir die Position eines Elementes in dieser Ordnung berechnen:

sage: s = S([2,4]); S.rank(s)4

Beachten Sie, dass S nicht die Liste ihrer Elemente ist. Wir können beispielsweise die Menge

P(P(P(E))) bilden und deren Kardinalität 2224

berechnen:

sage: E = Set([1,2,3,4])sage: S = Subsets(Subsets(Subsets(E))); S.cardinality()2003529930406846464979072351560255750447825475569751419265016...736

was ungefähr 2 · 1019728 ist:

sage: S.cardinality().ndigits()19729

und nach dem 237102124. Element fragen:

sage: S.unrank(237102123)2, 4, 1, 4, , 1, 3, 4, 1, 2, 4, 4, 2, 3, 1, 3, 2,1, 3, 2, 4, 1, 2, 4, , 3, 4

Physikalisch ist es unmöglich alle Elemente von S explizit hinzuschreiben, denn es gibt vielmehr davon als Partikel im ganzen Universum vorhanden sind (schätzungsweise 1082).

Bemerkung: in Python wäre es nur natürlich, mit len(S) nach der Kardinalität von S zufragen. Das geht hier aber nicht, weil Python verlangt, dass das Ergebnis von len eine Zahlvom Typ int zu sein hat; das könnte zu einem Überlauf führen und bei unendlichen Mengenauch nicht den Wert Infinity zurückgeben.

sage: len(S)Traceback (most recent call last):...OverflowError: Python int too large to convert to C long

15.2.2. Partitionen natürlicher Zahlen

Wir nehmen uns jetzt ein anderes klassisches Problem vor: gegeben ist eine natürliche Zahln; auf wieviele Arten kann n in Form einer Summe n = i1 + i2 + . . .+ il geschrieben werden,wobei i1, . . . , il natürliche Zahlen sind? Zwei Fälle sind zu unterscheiden:

• die Reihenfolge der Summanden ist unwichtig; dann nennen wir n = i1 + i2 + . . . + ileine Partition von n;

• auf die Reihenfolge der Summanden kommt es an; dann nennen wir die Summe eineKomposition von n.

327

Page 344: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Wir beginnen mit den Partitionen von n = 5; wie zuvor bilden wir zuerst die Menge dieserPartitionen:

sage: P5 = Partitions(5); P5Partitions of the integer 5

dann fragen wir nach ihrer Kardinalität:

sage: P5.cardinality()7

Wir sehen uns diese 7 Partitionen an; da es auf die Reihenfolge nicht ankommt, werden dieEinträge vereinbarungsgemäÿ in absteigender Reihenfolge angeordnet.

sage: P5.list()[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]

Die Berechnung der Anzahl der Partitionen verwendet die Formel von Rademacher (siehehttps://de.wikipedia.org/wiki/Partitionsfunktion), implementiert in C und bestensoptimiert, was sie sehr schnell macht:

sage: Partitions(100000).cardinality()27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519

Partitionen natürlicher Zahlen sind Objekte der Kombinatorik, die mit vielen Operationenausgestattet sind. Sie werden im Vergleich zu einfachen Listen als reichere Objekte zurückge-geben.

sage: P7 = Partitions(7); p = P7.unrank(5); p[4, 2, 1]

sage: type(p)<class 'sage.combinat.partition.Partitions_n_with_category.element_class'>

Zum Beispiel können sie graphisch als Ferrers-Diagramm dargestellt werden.

sage: print p.ferrers_diagram()*******

Wir überlassen es dem Leser, die verfügbaren Operationen durch Introspektion zu erkun-den.

Wir können eine Partition auch direkt erzeugen mit

sage: Partition([4,2,1])[4, 2, 1]sage: P7([4,2,1])[4, 2, 1]

328

Page 345: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

Möchte man die möglichen Werte der Teile i1, . . . , il beschränken, zum Beispiel beim Wechselnvon Geld, kann man WeightedIntegerValues benutzen. Die folgende Rechnung beispielswei-se

sage: WeightedIntegerVectors(8, [2,3,5]).list()[[0, 1, 1], [1, 2, 0], [4, 0, 0]]

zeigt, dass 8 Dollar mit Banknoten zu 2$, 3$ und 5$ entweder in 3$ plus 5$ oder in 2$ plus 2mal 3$ oder 4 mal 2$ getauscht werden können.

Kompositionen von natürlichen Zahlen werden ebenso behandelt:

sage: C5 = Compositions(5); C5Compositions of 5 sage: C5.cardinality()16sage: C5.list()[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 2, 1], [1, 1, 3],[1, 2, 1, 1], [1, 2, 2], [1, 3, 1], [1, 4], [2, 1, 1, 1],[2, 1, 2], [2, 2, 1], [2, 3], [3, 1, 1], [3, 2], [4, 1], [5]]

Die Anzahl 16 scheint bedeutsam zu sein und lässt die Existenz einer Formel vermuten. Wirschauen auf die Anzahl der Kompositionen von n im Bereich von 0 bis 9:

sage: [ Compositions(n).cardinality() for n in range(10) ][1, 1, 2, 4, 8, 16, 32, 64, 128, 256]

Wenn wir die Anzahl der Kompositionen von 5 hinsichtlicht der Länge betrachten, nden wireine Zeile des pascalschen Dreiecks:

sage: x = var('x'); sum( x^len(c) for c in C5 )x^5 + 4*x^4 + 6*x^3 + 4*x^2 + x

Das obige Beispiel benutzt eine Funktionalität, die wir bislang noch nicht gesehen haben:Da C5 iterierbar ist, kann es wie eine Liste in einer for-Schleife oder einer Raung1engl.comprehension) verwendet werden (Unterabschnitt 15.2.4).

Übung 52. Beweisen Sie die von obigen Beispielen nahegelegte Formel für die Anzahl derKompositionen von n und die Anzahl der Kompositionen von n der Länge k; untersuchen Siedurch Introspektion, ob Sage diese Formeln zur Berechnung von Kardinalitäten verwendet.

15.2.3. Einige andere abzählbare endliche Mengen

Das Prinzip ist für alle endlichen Mengen, mit denen wir in Sage Kombinatorik betreibenwollen, im wesentlichen das gleiche; wir beginnen mit der Konstruktion eines Objektes, dasdiese Menge modelliert und benutzen dann die passenden Methoden, die einem immer gleichenInterface folgen2. Es folgen noch ein paar weitere typische Beispiele.

Intervalle natürlicher Zahlen:

sage: C = IntegerRange(3, 21, 2); C3, 5, ..., 19

1(2Oder zumindest sollte das so sein. Es sind aber immer noch etliche Ecken zu fegen.

329

Page 346: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

sage: C.cardinality()9sage: C.list()[3, 5, 7, 9, 11, 13, 15, 17, 19]

Permutationen:

sage: C = Permutations(4); CStandard permutations of 4sage: C.cardinality()24sage: C.list()[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2],[1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3],[2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1],[3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1],[3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2],[4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]

Abb. 15.2 - Ein Poset mit 8 Knoten

Mengenpartitionen:

sage: C = SetPartitions([1,2,3]); CSet partitions of 1, 2, 3sage: C.cardinality()5sage: C.list()[1, 2, 3, 1, 2, 3, 1, 3, 2, 1, 2, 3, 1, 2, 3]

Teilweise Ordnungen (posets) auf Mengen mit 8 Elementen bis auf Isomorphie:

330

Page 347: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

sage: C = Posets(8); CPosets containing 8 elementssage: C.cardinality()16999

Wir wollen eins dieser Posets zeichnen (siehe Abb. 15.2):

sage: show(C.unrank(20))

Wir können auch über alle diese Graphen bis auf Isomorphie iterieren. Es existieren beispiels-weise 34 einfache Graphen mit 5 Knoten:

sage: len(list(graphs(5)))34

Hier nun, wie wir diejenigen bekommen, die höchstens 4 Kanten haben (siehe Abb. 15.3):

sage: for g in graphs(5, lambda G: G.size() <= 4): show(g)

Allerdings steht die Menge C dieser Graphen in Sage noch nicht zur Verfügung. Die fogendenBefehle sind daher noch nicht implementiert:

sage: C = Graphs(5); C.cardinality()34sage: Graphs(5); C.cardinality()24637809253125004524383007491432768sage: Graphs(19).random_element()Graph on 19 vertices

Was wir bis jetzt gesehen haben, lässt sich im Prinzip auf endliche algebraische Strukturenwie Diedergruppen anwenden:

sage: G = DihedralGroup(4); GDihedral group of order 8 as a permutation groupsage: G.cardinality()8sage: G.list()[(), (1,4)(2,3), (1,2,3,4), (1,3)(2,4), (1,3), (2,4), (1,4,3,2), (1,2)(3,4)]

oder die Algebra der 2× 2-Matrizen auf dem endlichen Körper Z/2Z:

sage: C = MatrixSpace(GF(2), 2); C.list()[[0 0] [1 0] [0 1] [0 0] [0 0] [1 1] [1 0] [1 0] [0 1] [0 1][0 0], [0 0], [0 0], [1 0], [0 1], [0 0], [1 0], [0 1], [1 0], [0 1],

[0 0] [1 1] [1 1] [1 0] [0 1] [1 1][1 1], [1 0], [0 1], [1 1], [1 1], [1 1]]

sage: C.cardinality()16

331

Page 348: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Übung 53. Listen Sie alle Monome 5. Grades in drei Variablen auf (sieheIntegerVectors). Bearbeiten Sie die geordneten Mengenpartitionen (OrderedSetPartitions)und die Standardtabellen (StandardTableaux).

Abb. 15.3 - Die einfachen Graphen mit 5 Knoten und höchstens 4 Kanten

Übung 54. Listen Sie die Matrizen mit alternierenden Vorzeichen der Gröÿe 3, 4 und 5 aufund versuchen Sie, die Denition zu erraten (siehe AlternatingSignMatrices). Entdeckungund Beweis dieser Formel für die Auistung dieser Matrizen (siehe die Methode cardinality),die durch Berechnungen von Determinanten in der Physik motiviert worden waren, sind eineeigene Geschichte. Insbesondere ist der erste Beweis von Zeilberger 1992 durch ein Rechner-programm automatisch geführt worden. Er war 84 Seiten lang und es brauchte nahezu 100Leute, um ihn zu verzieren [Zei96].

Übung 55. Berechnen Sie die Anzahl der Vektoren in (Z/2Z)5 von Hand und dann dieAnzahl der Matrizen in GL3(Z/2Z) (d.h. die Anzahl der 3 × 3-Matrizen mit Koezientenin Z/2Z und Inversen). Verizieren Sie Ihre Antworten mit Sage. Verallgemeinern Sie das zuGLn(Z/qZ).

332

Page 349: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

Mengenraungen und Iteratoren

Wir zeigen nun einige der von Python angebotenen Möglichkeiten der Bildung von (und desDurchlaufs durch) Mengen in einer Schreibweise, die exibel ist und nahe am üblichen ma-thematischen Gebrauch sowie insbesondere, welche Vorteile das für die Kombinatorik hat.

Wir beginnen mit der Bildung der endlichen Mengei2 | i ∈ 1, 3, 7

:

sage: [ i^2 for i in [1, 3, 7] ][1, 9, 49]

und dann der gleichen Menge, nur dass i nun von 0 bis 9 läuft:

sage: [ i^2 for i in range(1,10) ][1, 4, 9, 16, 25, 36, 49, 64, 81]

In Python heiÿt diese Art der Bildung einer Menge Mengenraung . Eine Bedingung kannhinzugefügt werden, um nur die primen Elemente zu behalten:

sage: [ i^2 for i in range(1,10) if is_prime(i) ][4, 9, 25, 49]

Durch Kombination zweier Mengenraungen kann die Menge (i, j) | 1 ≤ k < i < 6 erzeugtwerden:

sage: [ (i,j) for i in range(1,6) for j in range(1,i) ][(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3),(5, 1), (5, 2), (5, 3), (5, 4)]

oder das pascalsche Dreieck:

sage: [[binomial(n, i) for i in range(n+1)] for n in range(10)][[1],[1, 1],[1, 2, 1],[1, 3, 3, 1],[1, 4, 6, 4, 1],[1, 5, 10, 10, 5, 1],[1, 6, 15, 20, 15, 6, 1],[1, 7, 21, 35, 35, 21, 7, 1],[1, 8, 28, 56, 70, 56, 28, 8, 1],[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]]

Die Ausführung einer Raung erfolgt in zwei Schritten; zuerst wird ein Iterator erzeugt,dann wird eine Liste nach und nach mit den vom Iterator zurückgegebenen Werten gefüllt.Technisch gesehen ist ein Iterator ein Objekt mit einer Methode next, die solange es geht beijedem Aufruf einen neuen Wert zurückgibt.

sage: it = (binomial(3, i) for i in range(4))

gibt nacheinander die Binomialkoezienten(

3i

)mit i = 0, 1, 2, 3 zurück:

sage: it.next()1

333

Page 350: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

sage: it.next()3sage: it.next()3sage: it.next()1

Wenn der Iterator schlieÿlich erschöpft ist, erscheint eine Exception:

sage: it.next()Traceback (most recent call last):...

StopIteration

Allgemein, eine Iterable ist ein Python-Objekt L (eine Liste, eine Menge,. . .), über derenElemente iteriert werden kann. Technisch wird der Iterator durch iter(L) erzeugt. In derPraxis werden die Befehle iter und next selten gebraucht, weil for-Schleifen und Raungeneine viel elegantere Syntax bieten:

sage: for s in Subsets(3): s1231, 21, 32, 31, 2, 3

sage: [ s.cardinality() for s in Subsets(3) ]0, 1, 1, 1, 2, 2, 2, 3]

Welches Interesse besteht an Iteratoren? Sehen wir uns das folgende Beispiel an:

sage: sum( [ binomial(8, i) for i in range(9) ] )256

Bei der Ausführung wird eine Liste von 9 Elementen gebildet, dann wird sie als Argument ansum übergeben, um die Elemente hinzuzufügen. Übergibt man den Iterator jedoch direkt ansum (zu beachten ist das Fehlen der eckigen Klammern),

sage: sum( binomial(8, i) for i in xrange(9) )256

übernimmt die Funktion sum den Iterator direkt und kann die Konstruktion der Zwischenlistekurzschlieÿen. Bei einer groÿen Anzahl von Elementen vermeidet das die Allokation einesgroÿen Speicherbereichs, der mit der Liste gefüllt wird, die sofort wieder gelöscht wird3.

Die meisten Funktionen die eine Liste von Elementen als Argument erhalten, akzeptierenstattdessen auch einen Iterator (oder eine Iterable). Um damit zu beginnen, können wir dieListe (oder das Tupel) von Elementen wie folgt erhalten:

3Technisches Detail: xrange gibt einen Iterator über 1, . . . , 8 zurück, während range die entsprechendeListe zurückgibt. Ab Python 3.0 verhält sich range genauso wie xrange und xrange wird nicht längergebraucht.

334

Page 351: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

sage: list(binomial(8, i) for i in xrange(9))[1, 8, 28, 56, 70, 56, 28, 8, 1]sage: tuple(binomial(8, i) for i in xrange(9))(1, 8, 28, 56, 70, 56, 28, 8, 1)

Wir betrachten nun die Funktionen all und any, die wie and bzw. or, aber für mehrereArgumente wirken.

sage: all([True, True, True, True])Truesage: all([True, False, True, True])Falsesage: any([False, False, False, False])Falsesage: any([False, False, True, False])True

Das folgende Beispiel bestätigt, dass alle Primzahlen von 3 bis 99 ungerade sind:

sage: all( is_odd(p) for p in xrange(3,100) if is_prime(p) )True

Eine Mersenne-Zahl ist eine Primzahl der Form 2p − 1. Wir verizieren für p < 1000, dass pprim ist, wenn 2p − 1 prim ist:

sage: def mersenne(p): return 2^p - 1sage: [ is_prime(p) for p in range(1000) if is_prime(mersenne(p)) ][True, True, True, True, True, True, True, True, True, True,True, True, True, True]

Ist auch die Umkehrung wahr?

Übung 56. Probieren Sie die folgenden Befehle aus und erklären Sie die beträchtlichen Un-terschiede in den Ausführungszeiten.

sage: all( [ is_prime(mersenne(p)) for p in range(1000) if is_prime(p)] )Falsesage: all( is_prime(mersenne(p)) for p in range(1000) if is_prime(p) )False

Wir versuchen jetzt, das kleinste Gegenbeispiel zu nden. Dazu verwenden wir die Sage-Funktion exists:

sage: exists( (p for p in range(1000) if is_prime(p)),...: lambda p: not is_prime(mersenne(p)) )(True, 11)|

Alternativ können wir einen Iterator über alle Gegenbeispiele konstruieren:

sage: contre_exemples = \....: (p for p in range(1000)....: if is_prime(p) and not is_prime(mersenne(p)))sage: contre_exemples.next()11 sage: contre_exemples.next()23

335

Page 352: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

Übung 57. Was bewirken die folgenden Befehle?

sage: cubes = [t**3 for t in range(-999,1000)]sage: exists([(x,y) for x in cubes for y in cubes], lambda (x,y): x+y == 218)sage: exists(((x,y) for x in cubes for y in cubes), lambda (x,y): x+y == 218)

Welche der letzten beiden ist sparsamer an Zeit? An Speicherplatz?

Übung 58. Probieren Sie alle folgenden Befehle und erläutern Sie die Ergebnisse. Warnung:Bei einigen davon muss die Ausführung abgebrochen werden.

sage: x = var('x'); sum( x^len(s) for s in Subsets(8) )

sage: sum( x^p.length() for p in Permutations(3) )

sage: factor(sum( x^p.length() for p in Permutations(3) ))

sage: P = Permutations(5)sage: all( p in P for p in P )

sage: for p in GL(2, 2): print p; print

sage: for p in Partitions(3): print p

sage: for p in Partitions(): print p

sage: for p in Primes(): print p

sage: exists( Primes(), lambda p: not is_prime(mersenne(p)) )

sage: contre_exemples = (p for p in Primes()....: if not is_prime(mersenne(p)))sage: for p in contre_exemples: print p

Operationen auf Iteratoren. Zur Manipulation von Iteratoren bietet Python zahlreicheMöglichkeiten; die meisten davon sind Teil der Bibliothek itertools, die importiert werdenkann mit

sage: import itertools

Wir zeigen einige Anwendungen und nehmen als Ausgangspunkt die Permutationen von 3:

sage: list(Permutations(3))[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Wir können die Elemente einer Menge auisten, indem wir sie numerieren:

sage: list(enumerate(Permutations(3)))[(0, [1, 2, 3]), (1, [1, 3, 2]), (2, [2, 1, 3]),(3, [2, 3, 1]), (4, [3, 1, 2]), (5, [3, 2, 1])]

oder nur die Elemente an den Positionen 2, 33 und 4 (analog zu l[1 : 4]):

sage: list(itertools.islice(Permutations(3), 1, 4))[[1, 3, 2], [2, 1, 3], [2, 3, 1]]

oder eine Funktion auf alle Elemente anwenden:

336

Page 353: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.2. Die üblichen abzählbaren Mengen

sage: list(itertools.imap(lambda z: z.cycle_type(), Permutations(3)))[[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]]

oder die Elemente auswählen, die einer bestimmten Bedingung genügen:

sage: list(itertools.ifilter(lambda z: z.has_pattern([1,2]),sage: ....: Permutations(3)))[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2]]

In allen diesen Situationen kann attrcall bei der Erstellung einer anonymen Funktion einevorteilhafte Alternative sein:

sage: list(itertools.imap(attrcall("cycle_type"), Permutations(3)))[[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]]

Implementierung neuer Iteratoren. Neue Iteratoren zu konstruieren ist einfach, wenn manin einer Funktion das Schlüsselwort yield anstelle von return verwendet:

sage: def f(n):....: for i in range(n):....: yield i

Nach yield wird die Ausführung nicht beendet, sondern nur angehalten und bereit vom selbenPunkt an fortzufahren. Das Ergebnis der Funktion ist daher ein Iterator über die aufeinanderfolgenden Werte, die von yield zurückgegeben werden:

sage: g = f(4)sage: g.next()0sage: g.next()1sage: g.next()2sage: g.next()3

sage: g.next()Traceback (most recent call last):...

StopIteration

Die Funktion kann folgendermaÿen angewendet werden:

sage: [ x for x in f(5) ][0, 1, 2, 3, 4]

Dieses Berechnungsschema namens Kontinuation erweist sich für die Kombinatorik als sehrnützlich, besonders wenn es mit Rekursion gekoppelt wird. (Siehe auch Unterabschnitt 2.2.2wegen weiterer Anwendungen.) Hier folgt, wie alle Wörter einer gegebenen Länge über einemgegebenen Alphabet erzeugt werden:

sage: def words(alphabet,l):....: if l == 0: yield []

337

Page 354: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

....: else:

....: for word in words(alphabet, l-1):

....: for l in alphabet: yield word + [l]sage: [ w for w in words(['a','b'], 3) ][['a', 'a', 'a'], ['a', 'a', 'b'], ['a', 'b', 'a'], ['a', 'b', 'b'],['b', 'a', 'a'],['b', 'a', 'b'],['b', 'b', 'a'], ['b', 'b', 'b']]

Diese Wörter können gezählt werden mit

sage: sum(1 for w in words(['a','b','c','d'], 10))1048576

Das Abzählen der Wörter eines nach dem anderen ist hier natürlich kein ezientes Verfahren,da man die Formel nl benutzen kann; beachten Sie aber, dass dies nicht der stupideste Ansatzist - er vermeidet immerhin die Erzeugung der kompletten Liste und deren Speicherung.

Wir betrachten nun die Wörter der Dyck-Sprache. Das sind wohlgeformte Ausdrücke mit denBuchstaben ( und ). Die untenstehende Funktion erzeugt nun alle Dyck-Wörter gegebenerLänge (wobei unter Länge die Anzahl der Klammerpaare zu verstehen ist), indem sie dierekursive Denition anwendet, die besagt, dass ein Dyck-Wort entewder leer ist oder von derForm (w1)w2, wobei w1 und w2 Dyck-Wörter sind.

sage: def dyck_words(l):....: if l == 0: yield ''....: else:....: for k in range(l):....: for w1 in dyck_words(k):....: for w2 in dyck_words(l-k-1):....: yield '(' + w1 + ')' + w2

Hier sind alle Dyck-Wörter der Länge 4:

sage: list(dyck_words(4))['()()()()', '()()(())', '()(())()', '()(()())', '()((()))','(())()()', '(())(())', '(()())()', '((()))()', '(()()())','(()(()))', '((())())', '((()()))', '(((())))']

Beim Abzählen entdecken wir eine wohlbekannte Folge:

sage: [ sum(1 for w in dyck_words(l)) for l in range(10) ][1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]

Übung 59. Erzeugen Sie einen Iterator auf der Menge Cn der vollständigen Binärbäume mitn Blättern (siehe Unterabschnitt 15.1.2).

Hinweis: Verwenden Sie BinaryTree; im untenstehenden Beispiel erzeugen wir ein Blatt undden zweiten Baum von Abbildung 15.1.

sage: BT = BinaryTreesage: BT().sage: t = BT([BT([BT(), BT([BT(),BT()])]), BT()]); t[[., [., .]], .]

338

Page 355: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.3. Konstruktionen

Vorsicht! Sage benutzt beim Zeichnen eines vollständigen Binärbaums die klassische Konven-tion, nur sein Skelett darzustellen.

sage: view(t)

15.3. Konstruktionen

Wir wollen nun sehen, wie ausgehend von diesen Bausteinen neue Mengen gebildet werden.In Wirklichkeit haben wir im vorigen Abschnitt mit der Konstruktion von P(P(P(1, 2, 3)))und mit der Konstruktion von Kartenmengen in Abschnitt 15.1 schon damit begonnen.

Betrachten wir ein groÿes cartesisches Produkt:

sage: C = cartesian_product([Compositions(8), Permutations(20)]); CThe Cartesian product of (Compositions of 8, Standard permutations of 20)sage: C.cardinality()311411457046609920000

Klar, es ist unpraktisch, die Liste aller dieser Elemente des cartesischen Produktes zu bilden.Trotzdem kann man mit ihr arbeiten und beispielsweise ein zufälliges Element generieren:

sage: C.random_element()([2, 3, 2, 1], [10, 6, 11, 13, 14, 3, 4, 19, 5, 12, 7, 18, 15, 8, 20, 1,

17, 2, 9, 16])

Die Konstruktion cartesian_product kennt die algebraischen Eigenschaften ihrer Elemente.Deshalb ist H im folgenden Beispiel genauso wie seine Produktgruppe mit den normalenOperationen der Kombinatorik ausgestattet.

sage: G = DihedralGroup(4)sage: H = cartesian_product([G,G])sage: H.cardinality()64sage: H in Sets().Enumerated().Finite()Truesage: H in GroupsTrue

Wir bilden jetzt die disjunkte Vereinigung der beiden vorliegenden Mengen:

sage: C = DisjointUnionEnumeratedSets([Compositions(4),Permutations(3)])sage: CDisjoint union of Family (Compositions of 4, Standard permutations of 3)sage: C.cardinality()14sage: C.list()

339

Page 356: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1],[4], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Es ist auch möglich, die Vereinigung von mehr als zwei disjunkten Mengen zu nehmen, ja sogarvon einer unbegrenzten Anzahl von Mengen. Wir bilden jetzt die Menge aller Permutationen,aufgefasst als Vereinigung der Mengen Pn der Permutationen der Gröÿe n. Wir beginnen mitder unendlichen Familie F = (Pn)n∈N:

sage: F = Family(NonNegativeIntegers(), Permutations); FLazy family (<class 'sage.combinat.permutation.Permutations'>(i))_i in

Non negative integerssage: F.keys()Non negative integerssage: F[1000]Standard permutations of 1000

Jetzt können wir die disjunkte Vereinigung⋃n∈N Pn bilden:

sage: U = DisjointUnionEnumeratedSets(F); UDisjoint union ofLazy family (<class 'sage.combinat.permutation.Permutations'>(i))_i in

Non negative integers

Das ist eine unendliche Menge:

sage: U.cardinality()+Infinity

die aber die Iteration über ihre Elemente nicht verhindert, so dass sie irgendwann abgebrochenwerden muss.

sage: for p in U: p[][1][1, 2][2, 1][1, 2, 3][1, 3, 2][2, 1, 3][2, 3, 1][3, 1, 2]...

Beachten Sie, dass obige Menge auch direkt erzeugt werden kann mit

sage: U = Permutations(); UStandard permutations

340

Page 357: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.4. Generische Algorithmen

Zusammenfassung. Um es kurz zu sagen, Sage bietet eine Biblithek von abzählbaren Men-gen, die durch Standardkonstruktionen kombiniert werden können, was eine Toolbox ergibt,die exibel ist (aber noch erweitert werden kann). Es ist auch möglich, Sage mit wenigenZeilen neue Bausteine hinzuzufügen (siehe den Code in Sets().Enumerated().Finite()).Das wird möglich durch die Übereinstimmung der Schnittstellen und die Tatsache, dass Sageauf einer objektorientierten Sprache basiert. Es können dank der faulen Auswertungsstrategie(Iteratoren usw.) auch sehr groÿe und sogar unendliche Mengen bearbeitet werden.

Da ist keine Zauberei dabei: unter der Haube wendet Sage die normalen Regeln an (beispiels-weise, dass die Kardinalität von E×E gleich |E|2 ist); der Mehrwert stammt aus der Fähigkeit,komplizierte Strukturen zu verarbeiten. Die Situation ist vergleichbar mit Sages Implemen-tierung der Dierentialrechnung: Sage verwendet die bekannten Regeln für die Ableitung vonFunktionen und ihre Kompositionen, wobei hier der Wertzuwachs aus der Möglichkeit her-vorgeht, komplizierte Gleichungen zu verarbeiten. In diesem Sinne implementiert Sage eineAnalysis endlicher abzählbarer Mengen.

15.4. Generische Algorithmen

15.4.1. Lexikographische Erzeugung ganzzahliger Listen

Unter den klassischen abzählbaren Mengen ist besonders in der algebraischen Kombinatorikeine bestimmte Anzahl aus ganzzahligen Listen mit konstanter Summe aufgebaut, wie Parti-tionen, Kompositionen oder ganzzahligen Vektoren. Diese Beispiele können auch ergänzendeNebenbedingungen aufweisen, die ihnen hinzugefügt worden sind. Hier sind einige Beispiele.Wir beginnen mit dem ganzzahligen Vektor mit der Summe 10 und der Länge 3 mit Teilen,die unten durch 2, 4 und 2 begrenzt sind

sage: IntegerVectors(10, 3, min_part = 2, max_part = 5,inner = [2, 4, 2]).list()

[[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]

Die Komposition von 5 mit jedem Teil von höchstens 3 und Länge 2 oder 3:

sage: Compositions(5, max_part = 3,min_length = 2, max_length = 3).list()

[[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [1, 3, 1],[1, 2, 2], [1, 1, 3]]

Die streng fallenden Partitionen von 5:

sage: Partitions(5, max_slope = -1).list()[[5], [4, 1], [3, 2]]

Diesen Mengen liegt die gleiche algorithmische Struktur zugrunde, die in der allgemeineren -und etwas umständlicher zu benutzenden - Klasse IntegerListsLex implementiert ist. DieseKlasse modelliert Mengen von Vektoren (l0, . . . , ll) nicht-negativer ganzer Zahlen mit Neben-bedingungen für Summe und Länge, sowie Grenzen für Teile aufeinander folgende Dierenzenzwischen den Teilen. Hier sind noch einige Beispiele:

341

Page 358: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

sage: IntegerListsLex(10, length=3, min_part = 2, max_part = 5,floor = [2, 4, 2]).list()

[[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]

sage: IntegerListsLex(5, min_part = 1, max_part = 3,min_length = 2, max_length = 3).list()

[[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [1, 3, 1],[1, 2, 2], [1, 1, 3]]

sage: IntegerListsLex(5, min_part = 1, max_slope = -1).list()[[5], [4, 1], [3, 2]]

sage: list(Compositions(5, max_length=2))[[5], [4, 1], [3, 2], [2, 3], [1, 4]]

sage: list(IntegerListsLex(5, max_length=2, min_part=1))[[5], [4, 1], [3, 2], [2, 3], [1, 4]]

Für das Modell von IntegerListsLex spricht der gute Kompromiss zwischen Allgemeingül-tigkeit und Ezienz der Iteration. Der Hauptalgorithmus gestattet die Iteration über einesolche Menge S in inverser lexikographischer Ordnung und konstanter mittlerer Zeitkomple-xität (Constant Amortized Time - CAT), auÿer in pathologischen Fällen; grob gesagt ist dieZeit, um über alle Elemente zu iterieren proportional zur Anzahl der Elemente, und das istoptimal. Auÿerdem ist der Speicherbedarf proportional zum gröÿten gefundenen Element, inder Praxis also vernachlässigbar,

()

(4, 1)

(1, 1, 1, 1, 1)

(3, 1, 1) (2, 1, 1)

(2, 1, 1, 1)

(2, 1)

(1, 1, 1)

(3, 1) (3, 2) (1, 1)

(5) (4)

(1, 1, 1, 1)

(3) (2)

(2, 2, 1)

(1)

(2, 2)

Abb. 15.4 - Der Präx-Baum der Partitionen von 5.

Dieser Algorithmus basiert auf einem sehr allgemeinen Prinzip der Traversierung eines Ent-scheidungsbaumes, nämlich Branch-and-Bound: auf dem obersten Niveau durchlaufen wir allemöglichen Alternativen für l0; zu jeder dieser Alternativen durchlaufen wir alle möglichen Al-ternativen für l1 und so fort. Mathematisch gesprochen haben wir auf die Elemente von S dieStruktur eines Präx-Baumes gelegt. Ein Knoten des Baumes in der Tiefe k entspricht einemPräx l0, . . . , lk von einem oder mehreren Elementen von S (siehe Abbildung 15.4).

Das übliche Problem bei diesem Anatz ist die Vermeidung schlechter Entscheidungen, die zumVerlassen des Präx-Baumes führen und zur Erkundung toter Äste. Das ist deshalb besonders

342

Page 359: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.4. Generische Algorithmen

problematisch, weil die Anzahl der Elemente mit der Tiefe exponentiell anwächst. Es stelltsich heraus, dass die oben aufgelisteten Bedingungen einfach genug sind, um die folgendeEigenschaft zu garantieren: bei gegebenem Präx l0, . . . , lk von S ist die Menge der lk+1 so,dass l0, . . . , lk+1 als Präx von S entweder leer ist oder ein Intervall der Form [a, b], und dieGrenzen a und b in linearer Zeit, also proportional zur Länge des längsten Elementes von Sberechnet werden können, welches das Präx l0, . . . , ll besitzt.

15.4.2. Ganzzahlige Punkte in Polytopen

Auch wenn der Algorithmus in IntegerListsLex ezient ist, ist sein Zählalgorithmus dochnaiv: er iteriert schlicht über alle Elemente.

Es gibt für dieses Problem einen alternativen Ansatz: die Modellierung der gewünschten ganz-zahligen Liste als Menge der ganzzahligen Punkte eines Polytops, will sagen, die Menge derLösungen mit ganzzahligen Koordinaten eines Systems von linearen Ungleichungen. In diesemsehr allgemeinen Kontext gibt es hoch entwickelte Zählalgorithmen (z.B. Barvinok), die in Bi-bliotheken wie LattE implementiert sind. Iteration stellt im Prinzip kein groÿes Problem dar,jedoch gibt es zwei Einschränkungen, die die Existenz von IntegerListsLex rechtfertigen.Die erste ist theoretidscher Natur: die Gitterpunkte in einem Polytop erlauben nur die Model-lierung von Problemen fester Dimension (Länge). Die zweite ist praktischer Art: zur Zeit hatnur die Bibliothek PALP eine Schnittstelle zu Sage, und obwohl es mehrere Möglichkeiten fürdie Untersuchung von Polytopen bietet, produziert es in der gegenwärtigen Fassung lediglicheine Liste von Gitterpunkten, ohne für einen Iterator oder nicht-naives Zählen zu sorgen:

Abb. 15.5 - Das Polytop L und seine ganzzahligen Punkte in stereographischer Ansicht (Kreuzblick)

Hier folgt, wie dieses Polytop in 3D gezeichnet wird (siehe Abb. 15.5):

sage: A = random_matrix(ZZ,6,3,x=7)sage: L = LatticePolytope(A)sage: L.points()M(1, 4, 3),M(6, 4, 1),...M(3, 5, 5),

343

Page 360: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

in 3-d lattice Msage: L.points().cardinality()23

sage: L.plot3d()

15.4.3. Arten, zerlegbare kombinatorischer Klassen

In Unterabschnitt 15.1.2 hatten wir gezeigt, wie die rekursive Denition binärer Bäume dazudient, sie mit generierten Funktionen ezient abzuzählen. Die verwendeten Techniken sindsehr allgemein und lassen sich immer dann anwenden, wenn die beteiligten Mengen rekursivdeniert werden können (je nachdem, wen sie fragen, heiÿt eine solche Menge eine zerlegbarekombinatorische Klasse oder, grob gesagt, eine kombinatorische Art). Das umfasst alle Typenvon Bäumen und auch Permutationen, Kompositionen, Funktionsgraphen usw.

Hier erläutern wir einige nur einige wenige Beispiele, die die Sage-Bibliothek für kombinato-rische Arten verwenden.

sage: from sage.combinat.species.library import *sage: o = var('o')

Wir beginnen damit, dass wir vollständige Binärbäume neu denieren; dazu wenden wir dieRekursionsbeziehung direkt auf die Mengen an:

sage: BT = CombinatorialSpecies()sage: Leaf = SingletonSpecies()sage: BT.define( Leaf + (BT*BT) )

Nun können wir die Menge der Bäume mit fünf Knoten bilden, sie auisten, sie zählen. . . :

sage: BT5 = BT.isotypes([o]*5); BT5.cardinality()14sage: BT5.list()[o*(o*(o*(o*o))), o*(o*((o*o)*o)), o*((o*o)*(o*o)), o*((o*(o*o))*o),o*(((o*o)*o)*o), (o*o)*(o*(o*o)), (o*o)*((o*o)*o), (o*(o*o))*(o*o),((o*o)*o)*(o*o), (o*(o*(o*o)))*o, (o*((o*o)*o))*o, ((o*o)*(o*o))*o,((o*(o*o))*o)*o, (((o*o)*o)*o)*o]

Die Bäume sind mittels einer generischen rekursiven Struktur erzeugt worden; die Ausgabe istdeshalb nicht berauschend. Um sie zu verbessern, müsste Sage mit spezielleren Datenstruktu-ren ausgestattet sein, die über die gewünschten Darstellungsfähigkeiten verfügen. Wir teenwieder auf die erzeugende Funktion der Catalan-Zahlen:

sage: g = BT.isotype_generating_series(); gx + x^2 + 2*x^3 + 5*x^4 + 14*x^5 + O(x^6)

die als faule Potenzreihe zurückgegen wird:

sage: g[100]227508830794229349661819540395688853956041682601541047340

Wir schlieÿen mit den Fibonacci-Wörtern, binären Wörtern ohne zwei aufeinander folgende1. Sie ermöglichen eine natürliche rekursive Denition:

344

Page 361: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.4. Generische Algorithmen

sage: Eps = EmptySetSpecies(); Z0 = SingletonSpecies()sage: Z1 = Eps*SingletonSpecies()sage: FW = CombinatorialSpecies()sage: FW.define(Eps + Z0*FW + Z1*Eps + Z1*Z0*FW)

Die Fibonacci-Folge kann hier leicht wiedererkannt werden, daher der Name:

sage: L = FW.isotype_generating_series().coefficients(15); L[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

sage: oeis(L)0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and

F(1) = 1.1: A212804: Expansion of (1-x)/(1-x-x^2).2: A132636: a(n) = Fibonacci(n) mod n^3

Das ist eine unmittelbare Konsequenz der Rekursionsrelation. Mit denselben Einschränkun-gen, die von der generischen Anzeige herrühren, können wir auch gleich alle Fibonacci-Wörtergegebener Länge generieren.

sage: FW3 = FW.isotypes([o]*3)sage: FW3.list()[o*(o*(o*)), o*(o*((*o)*)), o*(((*o)*o)*),((*o)*o)*(o*), ((*o)*o)*((*o)*)]

Nach Ersetzen von durch 0, von *o durch 1 und Weglassen der runden Klammern undauch des letzten geschweiften Klammerpaars lesen wir 000, 001, 100 bzw. 101.

15.4.4. Graphen bis auf Isomorphie

In Unterabschnitt 15.2.3 haben wir gesehen, dass Sage Graphen und partielle Ordnungen bisauf Isomorphie erzeugt. Jetzt wollen wir den zugrunde liegenden Algorithmus beschreiben, derin beiden Fällen der gleiche ist und eine wesentlich breitere Klasse von Problemen abdeckt.

Wir rufen zunächst einige Begrie in Erinnerung. Ein Graph G = (V,E) ist eine Menge V vonKnoten und eine Menge E von Kanten, die diese Knoten verbinden; eine Kante wird durchein Paar u, v verschiedener Knoten aus V beschrieben. Ein solcher Graph heiÿt benannt;seine Knoten sind typischerweise numeriert, zum Beispiel ist V = 1, 2, 3, 4, 5.

Bei vielen Problemen spielen die Namen der Knoten keine Rolle. Ein Chemiker möchte typi-scherweise alle möglichen Moleküle mit gegebener Zusammensetzung untersuchen, zum Bei-spiel die Alkane mit n = 8 Kohlenstoatomen und 2n + 2 = 18 Wasserstoatomen. Dahermöchte er alle Graphen nden, die aus 8 Knoten mit 4 Nachbarn bestehen und 18 Knoten mitnur einem Nachbarn. Die verschiedenen Kohlenstoatome werden jedoch alle als identisch an-gesehen, desgleichen die Wasserstoatome. Unser Chemieproblem ist nicht eingebildet; dieserAnwendungstyp steht aktuell am Anfang eines wichtigen Forschungszweiges zu isomorphenProblemen in der Graphentheorie.

Arbeitet man von Hand mit einem kleinen Graphen, ist es wie im Beispiel von Unterabschnitt15.2.3 möglich, eine Zeichnung zu erstellen, die Bezeichner zu entfernen und die geometrischeInformation zur Lage der Knoten in der Ebene zu vergessen. Um jedoch einen Graphen ineinem Rechnerprogramm darzustellen, müssen an den Knoten Bezeichner eingeführt werden,

345

Page 362: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15. Abzählende Kombinatorik

um beschreiben zu können, wie die Kanten miteinander verbunden sind. Um dann die da-durch eingeführte Extrainformation zu kompensieren, sagen wir, dass zwei Graphen g1 undg2 isomorph sind, wenn von den Knoten von g1 zu den Knoten von g2 eine Bijektion existiert,welche den Kanten von g1 die Kanten von g2 bijektiv zuordnet. Ein nicht benannter Graph

ist dann eine Äquivalenzklasse der benannten Graphen.

Generell ist die Prüfung zweier Graphen auf Isomorphie sehr aufwendig. Jedoch wächst dieAnzahl der Graphen, auch der unbenannten, sehr schnell an. Dennoch können unbenannteGraphen anhand ihrer Nummern sehr ezient aufgelistet werden. Beispielsweise kann dasProgramm Nauty die 12005168 einfachen Graphen mit 10 Knoten in 20 Sekunden auisten.

Wie in Unterabschnitt 15.4.1 ist das allgemeine Prinzip des Algorithmus die Organisationder Objekte, die numeriert werden sollen, in einem Baum, der traversiert wird. Dazu wirdin jeder Äquivalenzklasse benannter Graphen (das heiÿt für jeden unbenannten Graphen) einpassender kanonischer Repräsentant festgelegt. Die folgenden sind die grundlegenden Opera-tionen:

1. Testen, ob ein benannter Graph kanonisch ist;

2. Berechnen des kanonischen Repräsentanten eines benannten Graphen.

Diese unvermeidlichen Operationen bleiben aufwendig; deshalb versucht man, die Anzahl ihrerAufrufe zu minimieren.

Die kanonischen Repräsentanten werden in der Weise bestimmt, dass es zu jedem kanonischenbenannten Graphen G eine kanonische Festlegung einer Kante gibt, deren Entfernung wiedereinen kanonischen unbenannten Graphen produziert, der dann der Vater von G genannt wird.Diese Eigenschaft hat zur Folge, dass die kanonischen unbenannten Graphen auf einer Men-ge V von Knoten als Knoten eines Baumes organisiert werden können: an der Wurzel stehtder Graph ohne Kanten; darunter sein einziges Kind, der Graph mit einer Kante; dann dieGraphen mit zwei Kanten usw. Die Menge der Kinder eines Graphen G kann durch Augmen-

tation konstruiert werden, durch Hinzunahme jeweils einer weiteren Kante zu G, die auf allemöglichen Weisen erfolgt und nachfolgende Auswahl der Graphen, die noch kanonisch4 sind.Rekursiv erhält man alle kanonischen Graphen.

In welchem Sinne ist dieser Algorithmus generisch? Betrachten wir z.B. planare Graphen(Graphen, die in der Ebene gezeichnet werden können, ohne dass sich Kanten kreuzen): durchEntfernung einer Kante aus einem planaren Graphen erhalten wir wieder einen planarenGraphen; somit bilden planare Graphen einen Teilbaum des vorhergehenden Graphen. Um siezu erzeugen kann exakt derselbe Algorithmus verwendet werden, der nur die Kinder auswählt,die planar sind:

sage: [len(list(graphs(n, property = lambda G: G.is_planar())))....: for n in range(7)][1, 1, 2, 4, 11, 33, 142]

Auf ähnliche Weise kann man jede abgeschlossene Famile von Graphen durch Entfernung vonKanten erzeugen und insbesondere jede Famile, die durch verbotene Teilgraphen charakteri-siert ist. Das schlieÿt beispielsweise Wälder ein (Graphen ohne Schleifen), bipartite Graphen(Graphen ohne ungerade Schleifen) usw. Mit diesem Ansatz können auch erzeugt werden

4In der Praxis würde eine eziente Implementierung die Symmetrien von G ausnutzen, d.h. seine automorpheGruppe, um die Anzahl der zu untersuchenden Kinder zu reduzieren und den Aufwand für jeden Test, obes kanonisch ist.

346

Page 363: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.4. Generische Algorithmen

• partielle Ordnungen über die Bijektion mit Hasse-Diagrammen, gerichtete Graphen ohneSchleifen und ohne Kanten, die durch die Transitivität der Ordnungsrelation impliziertwerden;

• Gitter (in Sage nicht implementiert), über die Bijektion mit passenden Halbgittern, diedurch Entfernen des gröÿten Knoten erhalten werden; in diesem Fall wird eine Augmen-tation der Knoten, nicht der Kanten vorgenommen.

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

0

1

2

3

Abb. 15.6 - Der Baum der einfachen Graphen mit 4 Knoten.

347

Page 364: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 365: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

Dieses Kapitel bietet das Studium der Graphentheorie mit Sage. Zunächst wird die KlasseGraph beschrieben (Abschnitt 16.1) wie auch ihre Methoden (Abschnitt 16.2). Dann werdensie zur Lösung praktischer Probleme angewendet (Abschnitt 16.4) bzw. zur experimentellenVerizierung theoretischer Resultate (Abschnitt 16.3)

16.1. Erzeugen eines Graphen

16.1.1. Beginn bei Null

Hier denieren wir Graphen als Paare (V,E), wobei V eine Menge von Knoten darstellt(vertices im Englischen) und E eine Menge von Kanten (edges im Englischen). Der Graph inAbb. 16.1 ist auf der Menge der Knoten 0, 1, 2, 5, 9, 'Madrid', 'Edinburgh' deniert und hat(1, 2), (1, 5), (1, 9), (2, 5), (2, 9) sowie ('Madrid', Edinburgh) als Kanten.

In Sage werden Graphen - kaum überraschend - durch die Klasse Graph dargestellt:

sage: g = Graph()

Voreingestellt ist, dass der Graph g zunächst leer ist. Das folgende Beispiel illustriert, wieihm Knoten und Kanten hinzugefügt werden: Sobald eine Kante erzeugt worden ist, werdendie zugehörigen Knoten - wenn sie nicht schon im Graphen enthalten sind - stillschweigendeingefügt. Wir kontrollieren den Ablauf der Prozedur mit Methoden, deren Rollen leicht zuerraten sind:

sage: g.order(), g.size()(0,0)sage: g.add_vertex(0)sage: g.oder(), g.size()(1,0)sage: g.add_vertices([1,2,5,9])sage: g.order(), g.size()(5,0)sage: g.add_edges([(1,5),(9,2),(2,5),(1,9)])sage: g.order(), g.size()(5,4)sage: g.add_edge('Madrid','Edinburgh')sage: g.order(), g.size()(7,5)

Das Hinzufügen der Kante (1, 2) bedeutet dasselbe wie das Hinzufügen der Kante (2, 1).Man sieht auÿerdem, dass die Methoden add_vertex und add_edge beide einen Plural(add_vertices und add_edges) haben, dem jeweils eine Liste als Argument übergeben wird,was eine kompaktere Schreibweise erlaubt (siehe z.B. Unterabschnitt 16.4.1, wo wir einenGraph erzeugen, nachdem wir seine Kanten generiert haben).

349

Page 366: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

Generell achtet Sage nicht auf den Typ der Objekte, die als Knoten eines Graphen verwendetwerden können. Sage akzeptiert in der aktuellen Version 7 jedes nicht mutable Python-Objekt(und daher auch keine Objekte der Klasse Graph), d.h. alles was ein Diktionär als Schlüsselakzeptieren würde (siehe Unterabschnitt 3.3.9). Es ist dann selbstredend auch möglich, hin-zugefügte Elemente mit Hilfe der Methoden delete_* wieder zu entfernen und die Knotenoder Kanten aufzuzählen, über die wir häug iterieren.

sage: g.delete_vertex(0)sage: g.delete_edges([(1,5), (2,5)])sage: g.order(), g.size()(6,3)sage: g.vertices()[1,2,5,9,'Edinburgh', 'Madrid']sage: g.edges()[(1, 9, None), (2, 9, None), ('Edinburgh', 'Madrid', None)]

Für Sage sind Kanten in Wahrheit Tripel, deren letzter Eintrag ein Bezeichner (label) ist. Inihm werden meistens numerische Werte gespeichert - die zum Beispiel von Algorithmen fürden Fluss oder den Zusammenhang als Kapazitäten oder als Gewichtung für das Problemder Kopplung (matching) interpretiert werden - und kann auch ein nicht mutables Objektenthalten. Voreingestellt ist der Wert None.

Sind die Knoten und Kanten eines Graphen im voraus bekannt, kann man ihn auf kompakteWeise mit einem Diktionär erzeugen, das jedem Knoten die Liste seiner Nachbarn zuordnet:

sage: g = Graph(....: 0 : []....: 1 : [5,9]....: 2 : [1,5,9],....: 'Edinburgh' : ['Madrid']

Abb. 16.1 - Ein Graph, dessen Knoten Zahlen sind oder Zeichenketten

Auch dort könnte man sich erlauben, die Zeilen zu vergessen, die den Knoten 5, 9 oder'Madrid' entsprechen, die ja schon als Nachbarn anderer Knoten aufgeführt worden sind.Ebenso könnte man sagen, dass 1 ein Nachbar von 2 ist, obwohl 2 nicht in der Liste derNachbarn von 1 erscheint: die Kante (1,2) wird gleichwohl erzeugt.

Übung 60. (Zirkulierende Graphen). Der zirkulierende Graph mit den Parametern n, d istein Graph mit n Knoten, die von 0 bis n − 1 numeriert sind (die wir uns auf einem Kreisangeordnet denken können), sodass zwei Knoten u und v dann durch eine Kante verbundensind, wenn u ≡ v + c mod n ist und −d ≤ c ≤ d. Schreiben Sie eine Methode, der dieParameter n und d übergeben werden und die den zugehörigen Graphen zurückgibt.

350

Page 367: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.1. Erzeugen eines Graphen

16.1.2. Verfügbare Konstruktoren

Den vorstehehenden Illustrationen zum Trotz wird in Sage selten auf eine Adjazenztabellezugegrien oder gar manuell auf Kante nach der anderen, um einen Graphen zu erstellen.Meistens ist es ezienter, sie mit Hilfe bereits vordenierter Elemente zu erstellen: die Me-thoden graphs.* erlauben die Erstellung von über 70 Graphen oder Graphenfamilien, die wirjetzt vorstellen. Die Graphen von Chvatal und Petersen beispielsweise erhält man in Sage mitfolgenden Zeilen:

sage: P = graphs.PetersenGraph()sage: C = graphs.CvatalGraph()

Beginnen wir die Beschreibung mit kleinen Graphen - im Gegensatz zu Graphenfamilien,denen wir später begegnen werden.

Kleine Graphen. Diese Graphen tragen zumeist den Namen ihres Entdeckers oder einesObjejektes, dem sie ähneln (ein Haus, ein Schnuller, ein Stier).

Sie erschienen oft als Gegenbeispiele zu bestimmten Vermutungen oder als kleinere Graphen,die diese oder jene Eigenschaft besaÿen. Der Graph von Petersen ist zum Beispiel nicht planar:er besitzt - gleichzeitig - die beiden kleineren, vom Satz von Kuratowski verbotenen (K5 undK3,3). Es ist auÿerdem ein Graph ohne Dreieck (seine Masche - Umfang (girth) ist gleich 5),3-regulär und von der chromatischen Zahl 3. Es ist auch ein knotentransitiver Graph. Jederseiner Parameter kann von Sage mittels der entsprechenden Methoden aufgefunden werden:

Kleine GraphenBullGraph ChvatalGraph ClawGraphDesarguesGraph DiamondGraph DodecahedralGraphFlowerSnark FruchtGraph HeawoodGeaphHexahedralGraph HigmanSimsGraph HomanSingletonGraphHouseGraph HouseXGraph IcosahedralGraphKrackhardtKiteGraph LollipopGraph MoebiusKantorGraphOctahedralGraph PappusGraph PetersenGraphTetrahedralGraph ThomsenGraph

sage: P = graphs.PetersenGraph()sage: P.is_planar()Falsesage: P.minor(graphs.CompleteBipartiteGraph(3,3))0: [0, 1, 1: [2, 7], 2: [8, 3: [6, 9], 4: [5], 5: [3, 4]sage: P.minor(graphs.CompleteGraph(5))\0: [0, 5], 1: [4, 9], 2: [2, 7], 3: [3, 8], 4: [1, 6]sage: P.girth()5sage: P.is_regular()Truesage: P.chromatic_number()3sage: P.is_vertex_transitive()Truesage: P.show()

351

Page 368: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

Familien von Graphen. Die hier vorgestellten Konstruktoren beschreiben Familien von Gra-phen, sie nehmen deshalb einen oder mehrere Parameter als Argument auf (mit einer Aus-nahme, nauty_geng, das keine besondere Familie von Graphen beschreibt, sondern die Mengefast aller Graphen mit Isomorphismus - siehe Unterabschnitt 15.4.4).

Familien von GraphenBarbellGraph BubbleSortGraphCircularLadderGraph DegreeSequenceDegreeSequenceBipartite DegreeSequenceCongurationModelDegreeSequenceTree DorogovtsevGoltsevMendesGraphFibonacciTree FuzzyBallGraphGeneralizedPetersenGraph Grid2dGraphGridGraph HanoiTowerGraphHyperStarGraph KneserGraphLCFGraph LadderGraphNKStarGraph NStarGraphOddGraph ToroidalGrid2dGraphnauty_geng

In dieser Liste ndet sich eine Verallgemeinerung (eigentlich sogar zwei) des Petersengraphen:der Graph von Kneser. Dieser Graph wird ausgehend von zwei Parametern n und k erstellt,und seine Knoten sind die

(nk

)Teilmengen der Gröÿe k von 1, . . . , n. Zwei dieser Mengen sind

genau dann adjazent, wenn sie disjunkt sind. Die Kanten des Petersengraphen entsprechenden Teilmengen der Gröÿe k = 2 einer Menge der Gröÿe 5:

sage: K = graphs.KneserGraph(5, 2); P = graphs.PetersenGraph()sage: K.is_isomorphic(P)True

Nach Konstruktion sind die Knesergraphen auch knotentransitiv. Ihre chromatische Zahl istgenau n − 2k + 2, ein überraschendes Ergebnis, das von Lovász vermittels des Satzes vonBorsuk-Ulam bewiesen worden ist und somit durch topologische Betrachtungen [Mat03]. Ve-rizieren wir das gleich durch ein paar Beispiele:

sage: all(graphs.KneserGraph(n,k).chromatic_number() == n - 2*k + 2....: for n in range(5,9) for k in range(2,floor(n/2)))True

Übung 61. (Graphen von Kneser). Schreiben Sie eine Funktion mit den beiden Parame-tern n, k, die den zugehörigen Knesergraphen ausgibt, und dies, wenn möglich, ohne if zuverwenden.

352

Page 369: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.1. Erzeugen eines Graphen

Elementare Graphen. Folgende Graphen sind der Grundbestand, nämlich die gängigsten inder Graphentheorie (vollständige Graphen, bipartit vollständige, zirkulierende, Pfade, Kreise,Sterne usw.). Auch hier wieder eine Ausnahme: trees; diese Methode erlaubt die Iterationüber die Menge der Bäume mit n Knoten.

Zufallsgraphen. Diese letzte Klasse von Grapohen ist sehr reich an Eigenschaften. Wir n-den da unter anderem die Gn,p und Gn,m, die beiden einfachsten Modelle von zufälligenGraphen.

Elementare GraphenBalancedTree CirculantGraph CompleteBipartiteGraphCompleteGraph CubeGraph CycleGraphEmptyGraph PathGraph StarGraphWheelGraph trees

Die Graphen Gn,p werden durch eine ganze Zahl n und eine reelle Zahl 0 ≤ p ≤ 1 festgelegt.Wir erhalten einen Zufallsgraphen Gn,p mit n Knoten 0, . . . , n− 1, indem für jedes der

(n2

)Knotenpaare i, j eine Münze geworfen wird - wobei ihre Wahrscheinlichkeit, auf Zahl zufallen, gleich p ist - und dem Graphen die entsprechende Kante hinzugefügt wird, wenn Zahlkommt.

Wir beobachten, dass bei jedem festgelegten Graphen H die Wahrscheinlichkeit, dass Gn,p Hals induzierten Teilgraphen enthält, gegen 1 tendiert, wenn 0 < p < 1 fest ist und n gegenunendlich geht (siehe 16.3.4).H ist ein vonG induzierter Teilgraph, wenn es eine KnotenmengeS ⊆ V (G) gibt, sodass die Beschränkung auf S von G (d.h. der Graph, dessen Knoten S sindund dessen Kanten diejenigen Kanten von G sind, die nur die Knoten von S berühren) istisomorph zu H. Wir stellen auch fest, dass dieser Untergraph G[S] induziert.

sage: H = graphs.ClawGraph()sage: def test():....: g = graphs.RandomGNP(20,2/5)....: return not g.subgraph_search(H, induced=True) is Nonesage: sum(test() for i in range(100)) >= 80True

16.1.3. Disjunkte Vereinigungen

Zusätzlich zu diesen Grundbausteinen erlaubt Sage mit Hilfe von zwei einfachen, aber ezi-enten Operationen die Vereinigung von disjunkten Graphen. Die Addition von zwei Graphen

entspricht ihrer disjunkten Vereinigung.

sage: P = graphs.PetersenGraph()sage: H = graphs.HoffmanSingletonGraph()sage: U = P + H; U2 = P.disjoint_union(H)sage: U.is_isomorphic(U2)True

Das Produkt eines Graphen G mit einer ganzen Zahl k gibt die disjunkte Vereinigung von kKopien von G zurück:

353

Page 370: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

sage: C = graphs.ChvatalGraph()sage: U = 3*C; U2 = C.disjoint_union(C.disjoint_union(C))sage: U2.is_isomorphic(U)True

Die folgende Zeile erzeugt die disjunkte Vereinigung von drei Kopien des Petersengraphen undzwei Kopien des Graphen von Chvatal:

sage: U = 3*P + 2*C

ZufallsgraphenDegreeSequenceExpected RandomBarabasiAlbert RandomBipartiteRandomGNM RandomGNP RandomHolmeKimRandomInterval RandomLobster RandomNewmanWattsStrogatzRandomRegular RandomShell RandomTreePowerlaw

Es gibt viele Möglichkeiten, dieses Ergebnis zu erzielen, die alle Ausüchte dafür sind, einpaar Zeilen Code zu schreiben. Beispielsweise dadurch, dass sichergestellt wird, dass jedeVerbindung mit einem der beiden Graphen isomorph ist:

sage: all((CC.is_isomorphic(P) or CC.is_isomorphic(C))....: for CC in U.connected_components_subgraphs())True

oder durch Berechnung der genauen Anzahl von Untergraphen:

sage: sum(CC.is_isomorphic(P)....: for CC in U.connected_components_subgraphs())3 sage: sum(CC.is_isomorphic(C)....: for CC in U.connected_components_subgraphs())2

Technische Details. Es muss gesagt werden, dass die Operationen Addition und Multipli-kation hinsichtlich des Aufwands an Speicherplatz und Zeit Kopien sind. Das kann zuweilenQuelle von Verlangsamung werden. Andererseits wird die Modikation von P oder C nachvorstehendem Beispiel U nicht verändern. Mehr noch: bei diesen Operationen gehen zweiInformationen verloren:

- die Knoten des Endgraphen werden mit ganzen Zahlen 0, 1, 1, . . . umnumeriert,

- die Positionen der Knoten (im Plan) bleiben in U nicht erhalten.

Die Methode disjoint_union zeigt ein anderes Verhalten: wenn der Graph g einen Knotena enthält und der Graph h einen Knoten b, enthält der von g.disjoint_union(h) zurück-gegebene Graph die Knoten (0, a) und (1, b). Für den Fall, dass a oder b nicht ganzzahligsind sondern andere Objekte (Zeichenkette, Tupel), dann vereinfacht die Anwendung dieserMethode die Arbeit mit dem resultierenden Graphen erheblich.

354

Page 371: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.1. Erzeugen eines Graphen

16.1.4. Ausgabe von Graphen

Ein sehr willkommener Aspekt des Studiums von Graphen in Sage ist die Möglichkeit, sie zuvisualisieren. Ohne Varianten oder Schnörkel genügt ein einziger Befehl:

sage: C = graphs.ChvatalGraph(); C.show()

Dabei handelt es sich um ein präzises Werkzeug zur Visualisierung bestimmter Funktionen.Hier lassen wir eine unabhängige Menge zeichnen:

sage: C.show(partition = [C.independent_set()])

Dem Argument partition der Methode show wird, wie der Name sagt, eine Partition derKnotenmenge, eine Zerlegung also, übergeben. Eine Farbe wird dann jeder Menge (hier nureine: rot) der Partition zugewiesen, um sie sichtbar zu unterscheiden. Eine letze Farbe (hier:

355

Page 372: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

rosa) wird dann denjenigen Knoten zugewiesen, die nicht in der Partition erscheinen. In un-serem Beispiel haben wir somit insgesamt zwei Farben.

Es ist selbstverständlich möglich, die Farben selbst festzulegen, die man den Knoten gebenmöchte, nämlich mittels eines Diktionärs und einer einigermaÿen natürlichen Syntax:

sage: C.show(vertex_colors = ....: "red" : [0,1,2], "blue" : [3,4,5],....: "yellow" : [6,7,8], "purple" : [9,10,11])

Zuweilen wünscht man sich keine Grundfarben oder Mischfarben 1. Grades. Man kann dieFarben dann mit ihrem Hexadezimalcode festlegen, wie das auch bei HTML der Fall ist.Methoden wie coloring sind genau dafür gemacht:

sage: C.coloring(hex_colors = True)'#00ffff': [3,8,5], '#7f00ff': [11],'#ff0000': [0,2,7,10], '#7fff0000': [1,4,6,9]

356

Page 373: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.2. Methoden der Klasse Graph

Genauso verhält sich das Argument edge_colors:

sage: from sage.graphs.graph_coloring import edge_coloringsage: edge_coloring(C, hex_coloring = True)#00ffff: [(0,6),(1,2),(3,9),(4,8),(5,10),(7,11)]#7f00ff: [(0,9),(1,7),(2,6),(3,4),(5,11),(8,10)]#ff0000: [(0,1),(2,3),(4,5),(6,11),(7,8),(9,10)]#7fff00: [(0,4),(1,5),(2,8),(3,7),(6,10),(9,11)]sage: C.show(edge_colors = edge_coloring(C, hex_colors = True))

Bilder exportieren. Es ist auch möglich, die von Sage erzeugten Graphen einzeln zu ex-portieren. Das folgende Beispiel erzeugt vollständige Graphen mit 3, 4, . . . , 12 Knoten undspeichert sie in den Dateien graph0.png, ..., graph9.png.

sage: L = [graphs.CompleteGraph(i) for in range(3,3+10)]sage: for number, G in enumerate(L):....: G.plot().save('/tmp'/ + 'graph' + str(number) + '.png')

Für die Befehle show und plot gibt es keine ausführliche Dokumentation. Wir erwähnenimmerhin die Option figsize = 15, mit der die Auösung des Bildes bestimmt wird. Sieerweist sich bei groÿformatigen Graphen als nützlich.

16.2. Methoden der Klasse Graph

Die Klasse Graph verfügt über mehr als 250 Methoden, wenn man diejenigen beiseite lässt, dieexclusiv in der Klasse DiGraph deniert sind, wo sie nur in angehängten Modulen erscheinen.Das macht Sage zu einer ausdrucksstarken und vollständigen Bibliothek der Graphentheorie,die es erlaubt, sich auf das Wesentliche zu konzentrieren, d.h. es wird vermieden, vor denFunktionen, die uns interessieren erst noch andere Funktionen programmieren zu müssen.

Wie beim Erlernen jeder Programmiersprache (oder Bibliothek) ist es hilfreich, wenigstenseinmal die Liste ihrer Funktionen durchzugehen, um zu erkunden, was sie alles kann. Dieser

357

Page 374: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

(nicht erschöpfende) Abschnitt versucht, sie ..... vorzustellen. Dem Leser sei geraten, die paarMinuten zu opfern, die für die Lektüre des Inhalts jeder Kategorie nötig sind - und auch die

vollständige Liste der verfügbaren Methoden: die dafür benötigte Zeit wird sich angesichtseines Graphenproblem schlieÿlich als gute Investition erweisen! Es ist ebenfalls ratsam, eineoene Sagesitzung vor sich zu haben, um die Dokumentation der dargestellen Funktioneneinsehen zu können (z.B. g.degree_constrained_subgraph?), von denen manche mehrereOptionen haben oder wenn ihr Name nicht hinreichend aussagekräftig ist.

16.2.1. Modikation der Struktur von Graphen

Natürlich enthält ein Groÿteil der Klasse Graph Methoden, die mit der Denition und derModikation von Graphen zu tun haben, die erforderlich sind, obwohl sie keine merklicheFunktionalität hinzufügen.

Methoden für den Zugri und die Modikation der Klasse Graphadd_cycle add_edge add_edgesadd_path add_vertex add_verticesadjacency_matrix allow_loops allow_multiple_edgesallows_loops allows_multiple_edges cleardelete_edge delete_edges delete_multiedgedelete_vertex delete_vertices edge_iteratoredge_label edge_labels edgesedges_incident get_vertex get_verticeshas_edge has_loops has_multiple_edgeshas_vertex incidence_matrix latex_optionsloop_edges loop_vertices loopsmerge_vertices multiple_edges nameneighbor_iterator neighbors networkx_graphnum_edges num_verts number_of_loopsorde relabel remove_loopsremove_multiple_edges rename reset_namesave set_edge_label set_latex_optionsset_vertex set_vertices sizesubdivide_edge subdivide_edges vertex_iteratorvertices weighted weighted_adjacency_matrix

16.2.2. Operatoren

Ebenfalls zu den Methoden zählen die Operatoren, die ein Objekt des Typs Graph (oderDiGraph) zurückgeben. Wird beispielsweise die Methode complement auf G angewendet, gibtsie einen Graphen mit denselben Knoten zurück, dessen Kante uv nur existiert, wenn uv /∈ Gist. Die Methode subgraph erlaubt ihrerseits, zu einem Graphen G den von einer gegebe-nen Knotenmenge induzierten Untergraphen zu erhalten, eine Operation, die G[v1, . . . , vk]geschrieben wird.

Verizieren wir einige elementare Relationen. Das Komplement von P5 (geschrieben P5) istein Haus, und die Graphen P4 und C5 sind autocomplementär:

358

Page 375: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.2. Methoden der Klasse Graph

sage: P5 = graphs.PathGraph(5); Haus = graphs.HouseGraph()sage: P5.complement().is_isomorphic(Haus)Truesage: P4 = graphs.PathGraph(4); P4.complement().is_isomorphic(P4)Truesage: C5 = graphs.CycleGraph(5); C5.complement().is_isomorphic(C5)True

Sage deniert auch (mit der gleichnamigen Methode) den Kantengraphen (line graph) von G- oft mit L(G) bezeichnet - dessen Knoten den Kanten von G entsprechen und bei dem zweiKnoten adjazent sind, wenn die entsprechenden Kanten in G inzident sind. Wir nden auchdie Denition verschiedener Produkte von Graphen. In jedem der folgenden Beispiele nehmenwir an, dass G das Produkt von G1 und G2 ist, das auf der Knotenmenge V (G1) × V (G2)deniert ist. Zwei Knoten (u, v), (u′, v′) sind genau dann adjazent, wenn:

Kartesisches Produktcartesian_product

oder

u = u′ und vv′ ∈ E(G2)uu′ ∈ E(G1) und v = v′

Disjunktes Produktdisjunctive_product

oder

uu′ ∈ E(G1)vv′ ∈ E(G2)

Starkes Produktstrong_produkt

oder

u = u′ und vv′ ∈ E(G2)uu′ ∈ E(G1) und v = v′

uu′ ∈ E(G1) und vv′ ∈ E(G2)

Lexikographisches Produktlexicographic_product

oder

uu′ ∈ E(G1)u = u′ und vv′ ∈ E(G2)

Tensorprodukttensor_product

und

uu′ ∈ E(G1)vv′ ∈ E(G2)

Wir können das quadratische Gitter GridGraph als cartesisches Produkt von zwei Pfadenbilden:

sage: n = 5; Path = graphs.PathGraph(n)sage: Grid = Path.cartesian_product(Path)sage: Grid.is_isomorphic(graphs.GridGraph([n,n]))True

Produkte, Operatorencartesian_produkt categforial_product complement

copy disjoint_union disjunctive_product

kirchhoff_matrix laplacian_matrix line_graph

lexicographic_product strong_product subgraph

to_directed to_simple to_undirected

tensor_product transitive_closure transitive_reduction

union

359

Page 376: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

16.2.3. Traversierung von Graphen und Abstände

Sage bietet die üblichen Methoden zur Traversierung von Graphen wie die Tiefensuche (depth_first_search) und die Breitensuche (breadth_first_search). Das sind grundlegende Rou-tinen für die Abstandsberechnung, den Fluss oder die Konnektivität. Sage enthält auch ei-ne Implementierung des weniger klassischen lex_BFS (lexicographic breadt_rst search), diezum Beispiel zum Erkennen triangulierter (cordaler) Graphen (vgl. is_chordal). Diese Me-thoden geben Listen von Knoten zurück, deren Ordnung der Reihenfolge ihres Aundensentspricht1:

sage: g = graphs.RandomGNP(10, .6)sage: list(g.depth_first_search(0))[0, 6, 9, 8, 4, 7, 3, 2, 1, 5]sage: list(g.breadth_first_search(0))[0, 1, 6, 2, 3, 5, 8, 9, 4, 7]sage: g.lex_BFS(0)[0, 1, 6, 3, 8, 9, 5, 2, 4, 7]

Mit Hilfe dieser Traversierungen denieren wir die Methode shortest_path, die wahrschein-lich die meistbenutzte von allen ist2. Sage erlaubt gleichfalls die Berechnung verschiedenerInvarianten, die mit Abständen zu tun haben:

- eccentricity: ordnet einem Knoten v den maximalen Abstand zu allen anderen Knotendes Graphen zu;

- center: gibt einen zentralen Knoten des Graphen zurück - sozusagen die kleinste Exzen-trizität;

- radius: liefert die Exzentrizizät eines zentralen Knotens;

- diameter: gibt den gröÿten Abstand zwischen zwei Knoten zurück;

- periphery: gibt die Liste der Knoten zurück, deren Exzentrizität gleich dem Durchmesserist.

Abstände, Traversierungaverage_dstance breadth_first_search center

depth_first_search diameter distance

distance_all_pairs distance_graph eccentricity

lex_BFS periphery radius

shortest_path shortest_path_all_pairs shortst_path_length

shortest_path_length shortest_paths

1Wenn lex_BFS eine Knotenliste zurückgibt, sind die Methoden depth_first_search undbreadth_first_search die Iteratoren über die Knoten, daher die Verwendung der Methode list

2Es ist anzumerken, dass shortest_path nicht unbedingt breadth_first_search aufruft: sind die Kantenmit Abständen gewichtet, wird es von Implementierungen des Algorithmus von Dijkstra (Standard oderbidirektional) abgelöst.

360

Page 377: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.2. Methoden der Klasse Graph

16.2.4. Fluss, Konnektivität, Paarung (Matching)

Mit Hilfe der Methode flow (vgl. Unterabschnitt 17.4.3) kann Sage Probleme des gröÿten Flus-ses lösen3. Dank der vorstehend erwähnten Traversierung enthält Sage auch mehrere Metho-den, die mit dem Zusammenhang zu tun haben (is_connected, edge_connectivity, vertex_connectivity, connected_components,...) wie auch mit Konsequenzen aus dem Satz vonMenger:

Seien G ein Graph und u,v zwei seiner Knoten. Die folgenden Aussagen sind äquivalent:

- der Wert des maximalen Flusses zwischen u und v ist k (siehe flow);

- es existieren k (aber nicht k+1) kantendisjunkte Pfade zwischen u und v (siehe

edge_disjoint_paths);

- es existiert eine Menge von k Kanten in G, durch deren Entfernung aus dem Graphen

entfernt u und v getrennt werden (siehe edge_cut).

Gegenstücke dieser Methoden hinsichtlich des Zusammenhangs der Knoten sind flow (dankseiner Option vertex_bound=True), vertex_cut und vertex_disjoint_paths.

Wir verizieren, dass der Zusammenhang eines Zufallsgraphen Gn,p mit (sehr) groÿer Wahr-scheinlichkeit seinem minimalen Grad gleicht:

sage: n = 30; p = 0.3; trials = 50sage: def equality(G):....: return G.edge_connectivity() == min(G.degree())sage: sum(equality(graphs.RandomGNP(n,p)) for i in range(trials))/trials1

Wir können auch die Zerlegung eines Graphen in zweifache Knoten-Zusammenhangskomponentenerhalten oder auch seinen Baum von Gomory-Hu durch blocks_and_cut_vertices bzw.gomory_hu_tree.

Da es sich um eine grundlegende Funktion der Graphentheorie handelt, erwähnen wir hier auchdie Methode matching, die mit dem Algorithmus von Edmonds eine maximale Paarbildungbewirkt. Die Paarbildung wird auch in den Unterabschnitten 16.4.2 und 17.4.2 angespro-chen.

Flüsse, Zusammenhang,. . .blocks_and_cut_vertices connected_component_containing_vertex

connected_components connected_components_number

connected_components_subgraph degree_constraint_subgraph

edge_boundary edge_connectivity

edge_cut edhe_disjoint_paths

edge_disjoint_spanning_trees flow

gomory_hu_tree is_connected

matching multicommodity_flow

vertex_boundary vertex_connectivity

vertex_cut vertex_disjoint_paths

3Es stehen noch zwei andere Methoden zur Verfügung: die erste folgt dem Algorithmus von Ford-Fulkerson,die andere ist ein lineares Programm.

361

Page 378: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

16.2.5. NP-vollständige Probleme

Für bestimmte NP-vollständige Aufgaben enthält Sage Algorithmen für eine exakte Lösung.Wohlgemerkt können dieses Aufgaben je nach Fall lange Rechenzeiten benötigen, doch habenreale Beispiele oft die angenehme Eigenschaft einfacher zu sein als die theoretischen Gegen-beispiele. Beispielsweise ist es möglich, folgende Optimierungsaufgaben zu lösen.

Cliquen und maximale unabhängige Mengen. Eine maximale Clique eines Graphen ist eineMenge von paarweise adjazenten Knoten maximaler Kardinalität (nicht adjazent im Falle einerunabhängigen Menge). Eine Anwendung dieses Aufgabentyps wird in Unterabschnitt 16.4.1vorgestellt. Der verwendete Algorithmus ist der des Programms Cliquer [NO].Methoden: clique_maximum, independent_set

Färbung von Knoten und Kanten. Eine echte Färbung der Knoten eines Graphen bestehtdarin, je zwei adjazenten Knoten verschiedene Farben zu geben. Sage verfügt über mehre-re Funktionen zur exakten Berechnung bestimmter Farbgebungen, wobei meistens lineareProgrammierung oder der Algorithmus Dancing Links verwendet wird. Die Erklärung eineseinfachen, aber nicht optimalen Färbealgorithmus ndet der Leser im Unterabschnitt 16.3.1.Methoden: chromatic_number, coloring, edge_coloring, grundy_coloring4.

Führende Menge. Eine Knotenmenge S eines Graphen G heiÿt dominierend , wenn jederKnoten v von G Nachbar eines Elementes von S ist - wir sagen dann, dass sie führend ist -oder wenn er selbst Element von S ist. Da die Menge aller Knoten trivialerweise dominierendist, besteht die Aufgabe darin, die Gröÿe der Menge S zu minimieren. Dieses Problem wirdin Sage mit Hilfe der linearen Programmierung gelöst.Methode: dominating_set

Hamiltonkreis, Problem des Handlungsreisenden. Ein Graph heiÿt hamiltonisch, wenn ereinen Kreis besitzt, der jeden Knoten genau einmal passiert. Im Gegensatz zum Problem desEuler-Kreises - hier muss der Kreis genau einmal durch jede Kante von G gehen - ist diesesProblem NP-vollständig und wird in Sage mit linearer Programmierung wie ein Spezialfalldes Problems des Handlungsreisenden gelöst.

Wir illustrieren die Funktion hamiltonian_cycle, die einen Hamilton-Kreis zurückgibt, fallsein solcher Kreis existiert (Abb. 16.2):

sage: g = graphs.ChvatalGraph(); cycle = g.hamiltonian_cycle()sage: g.show(vertex_labels = False); cycle.show(vertex_labels = False)

Methoden: is_hamiltonian, hamiltonian_cycle, traveling_salesman_problem

4Diese Methoden sind über die Klasse Graph nicht unmittelbar zugänglich. Um auf sie wie auch auf andereFärbefunktionen zuzugreifen, konsultieren Sie das Modul graph_coloring

362

Page 379: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.2. Methoden der Klasse Graph

Abb. 16.2 - Der Graph von Chvatal und einer seiner Hamilton-Kreise

NP-vollständige Probleme (oder angeglichene)automorphism_group characteristicc_polynomial

chromatic_number chromatic_polynomial

coloring disjoint_routed_paths

edge_coloring dominating_set

genus hamiltonian_cycle

independent_set_of_representatives is_hamiltonian

is_isomorphic max_cut

minor multicommodity_flow

multiway_cut subgraph_search

traveling_salesman_problem steiner_tree

vertex_cover

Verschiedene Probleme. Sage kann auch das Geschlecht (genus) eines Graphen berechnen.die maximalen Schnitte (max_cut), Steiner-Bäume (steiner_tree) usw. Es erlaubt auch dieLösung von wichtigen Problemen wie Mehrfachüsse (multicommodity_flow), der Test aufExistenz vonMinoren (minor - Suche eines isomorphen Minoren zu einem gegebenen Graphen)oder die Suche nach Subgraphen (subgraph_search).

Obwohhl die theoretische Komplexität dieser Probleme noch nicht bekannt ist, sind dochAlgorithmen für das Problem des Isomorphismus von Graphen is_isomorphic sowie auchfür die Berechnung von Gruppen von Automorphismen von Graphen (automorphism_group)verfügbar.

16.2.6. Erkennen und Prüfen von Eigenschaften

Viele NP-vollständige Probleme besitzen einen ezienten Lösungsalgorithmus (linear, quadra-tisch. . . ), wenn die Graphen zu einer bestimmten Klasse gehören. Es ist beispielsweise trivial,ein Problem der maximalen Clique auf einem chordalen (triangulierten) Graphen zu lösen,und es ist polynomial (wenn auch kompliziert), eine optimale Färbung der Knoten eines voll-kommenen Graphen zu berechnen. Sage besitzt für einige elementare Klassen von GraphenAlgorithmen zur Erkennung: Wälder (is_forest), Bäume (is_tree), bipartite Graphen(is_bipartite), eulersche Graphen (is_eulerian), reguläre Graphen (is_regular) usw.Es ist ebenfall möglich, die folgenden Klassen zu identizieren.

363

Page 380: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

Chordale Graphen. Ein Graph heiÿt chordal , wenn er keinen Kreis als induzierten Subgraphzulässt, der gröÿer ist als 4. Auf dieselbe Weise kann jeder chordale Graph durch sequentielleWegnahme von Knoten zerlegt werden, deren Nachbarschaft ein vollständiger Graph ist (dieseReihenfolge der Zerlegung wird Ordnung der vollständigen Elimination genannt). Erkanntwerden diese Graphen mittels einer lexikographischen Breitensuche (lex_BFS).Methode: is_chordal

Intervallgraphen. Sei I = I1, . . . , In eine endliche Menge von Intervallen von Mengenreeller Zahlen. Wir denieren für I einen Graphen G auf n Knoten, dessen Knoten i und jgenau dann adjazent sind, wenn die Intervalle Ii und Ij eine nichtleere Schnittmenge haben.Die Graphen der Intervalle sind diejenigen, die wir auf diese Weise erhalten können. Sie bildeneine Unterklasse der chordalen Graphen, welche in linearer Zeit dank der Struktur von PQ-Bäumen zu erkennen ist.Methode: is_interval

Vollkommene Graphen. Ein Graph G heiÿt vollkommen, wenn für jeden induzierten Sub-graph G′ ⊆ G die chromatische Zahl von G gleich der maximalen Gröÿe einer Clique ist (d.h.die Gleichheit von χ(G′) = ω(G) ist gegeben). Auch wenn das Erkennen solcher Graphen einpolynomiales Problem ist, sind die bekannten Algorithmen komplex und die Implementierungvon Sage verwendet einen exponentiellen Algorithmus.Methode: is_perfect

Knotentransitive Graphen. Ein Graph G heiÿt knotentransitiv , wenn für jedes Knotenpaaru und v ein Isomorphismus h : V (G) 7→ V (G) so existiert, dass h(u) = v ist. Obwohl dietheoretische Komplexität dieses Problems noch nicht ermittelt ist, ist die in Sage verfügbareImplementation sehr ezient.Methode: is_vertex_transitive

Kartesisches Produkt von Graphen. Nur bestimmte Graphen lassen sich kartesisches Pro-dukt einer Folge von Graphen G1, . . . , Gk ausdrücken. Es ist auÿerdem möglich, zu einemgegebenen zusammenhängenden Graphen die einzige Möglichkeit zu nden, ihn so mit Hilfeeines eleganten Ergebnisses der Charakterisierung zu nden, das leicht in einen polynomialenAlgorithmus übersetzt werden kann.Methode: is_cartesian_transitive

Zu zahlreichen Klassen von Graphen ndet man auÿer ihrer Charakterisierung durch eine

Konstruktion (die chordalen Graphen) oder eine spezielle Eigenschaft (die vollkommenen Gra-

phen) eine äquivalente Formulierung mittels ausgeschlossener Subgraphen. Das läuft darauf

hinaus zu sagen, dass ein Graph G genau dann zu einer Klasse C gehört, wenn in ihm Graphen

aus G1, . . . , Gk vorkommt. In diesem Fall kann man einen Erkennungsalgorithmus beschrei-

ben, der nur auf die Existenz jedes dieses Subgraphen testet, was der Befehl subgraph_searchzu tun erlaubt.

364

Page 381: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.3. Graphen in Aktion

Erkennen und Prüfen von Eigenschaftenis_bipartite is_cordal is_directed

is_equitable is_eulerian is_even_hole_free

is_forest is_interval is_odd_hole_free

is_overfull is_regular is_split

is_subgraph is_transitively_reduced is_tree

is_triangle_free is_vertex_transitive

16.3. Graphen in Aktion

Es ist nun an der Zeit, aus den Funktionen, die wir gefunden haben, Nutzen zu ziehen. Diefolgenden Beispiele haben zur Motivation einen praktischen oder theoretischen Vorwand undsind nicht generell die beste Art und Weise, Sage zur Lösung der Probleme zu verwenden, diesie beschreiben. Oft sind sie roh und aufzählend, aber das verleiht ihnen auch ihren Charme:ihr Ziel ist natürlich das Aufstellen einer Liste von leicht und bequem zugänglichen Anwen-dungsbeispielen für die Verwendung der Bibliothek der Graphen von Sage - alles ist hier inder Form, nicht in der Substanz.

16.3.1. Gierige Färbung der Knoten eines Graphen

Das Färben der Knoten eines Graphen besteht darin, jedem von ihnen eine Farbe zuzuweisen(wir nehmen hier an, dass eine ganze Zahl eine Farbe bedeutet), und dies so, dass jeder Knoteneine Farbe hat, die von den Farben seiner Nachbarn verschieden ist. Das ist selbstverständlichmöglich: es genügt, soviele Farben zu wählen wie der Graph Knoten hat; aus diesem Grund istdas Färbungsproblem ein Minimierungsproblem: zu einem gegebenen Graphen G die kleins-te Anzahl von Farben chi(G) zu nden, die die Färbung der Knoten unter der genanntenBedingung erlaubt.

Auch wenn die Berechnung der Zahl chi(G) ein schwieriges Problem ist, das sich an einebeeindruckende Literatur anlehnt, wird ein Leser mit eher praktischem Blick entzückt sein zuerfahren, dass es recht schnell gelingen kann, näher am Optimum zu sein als durch Verwendungvon |V | Farben. Diesen schlagen wir folgenden Algorithmus vor: Gierige Färbung der Knoteneines Graphen.

Wir wählen einen Knoten zufällig und geben ihm die Farbe 0. Der Reihe nach wählen wireinen noch nicht gefärbten Knoten und geben ihm als Farbe die kleinste ganze Zahl, die vonseinen Nachbarn nicht verwendet wird.

Dieser Algorithmus erfordert zur Erklärung nur einige Zeilen und genauso läuft es in Sage ab.Wir wenden ihn hier auf einen Zufallsgraphen an:

365

Page 382: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

sage: n = 100; p = 5/n; g = graphs.RandomGNP(n, p)

sage: # Menge der verfügbaren Farben.sage: # In der Mehrzahl der Fälle genügen n Farbensage: verfuegbare_farben = Set(range(n))

sage: # Dieses Diktionär enthält die jedemsage: # Knoten des Graphen zugeordnete Farbesage: farbe = sage: for u in g:....: verbotene = Set([farbe[v] for v in g.neighbors(u)....: if v in farbe])....: farbe[u] = min(verfuegbare_farben - verbotene)sage: # Anzahl der verwendeten Farben sage: max(farbe.values()) + 16

Das ist deutlich ezienter als mit 100 Farben zu arbeiten. Es ist indessen einfach, diesenAlgorithmus zu verbessern, da man bemerkt, dass die Färbung eines Graphen von einer Un-bekannten abhängt: der Reihenfolge, in welcher die Knoten ausgewählt werden. Es stimmt,dass wir mit diesem Algorithmus über die Reihenfolge keinerlei Kontrolle haben, weil wir unsdamit begnügen, die Knoten mittels for u in g aufzuzählen, was vor allem der Kürze desProgramms zugute kommt. Das lehrreiche Kapitel 15 hat die Aufzählung von Mengen in Sagebehandelt, wozu auch Permutationen gehören. Besser noch, diese Klasse beitzt eine Methoderandom_element, derer wir uns nun bedienen können.

sage: P = Permutations([0,1,2,3]); P.random_element()[2, 0, 1, 3]

Daher werden wir versuchen, bessere Resultate zu erzielen, in dem wir die Knoten unseresGraphen 30 mal kolorieren, jeweils in der Reihenfolge wie sie die zufällige Permutation ergibt.Es ergibt sich der folgende Code, den wir auf den eben denierten Graphen anwenden:

sage: verfuegbare_farben = Set(range(n))

sage: anzahl_tests = 30sage: knoten = g.vertices()sage: P = Permutations(range(n))sage: bessere_faerbung = sage: bessere_chromatische_zahl = +oo

sage: for t in range(anzahl_tests):....: # Zufällige Ordnung auf den Knoten....: p = P.random_element()....: farbe = ....: for i in range(g.order()):....: u = knoten[p[i]]....: verbotene = Set([farbe[v] for v in g.neighbors(u)....: if v in farbe])....: farbe[u] = min(verfuegbare_farben - verbotene)....: # Aktualisierung der besseren Färbung....: if max(farbe.values()) + 1 < bessere_chromatische_zahl:....: bessere_faerbung = farbe....: bessere_chromatische_zahl = 1 + max(farbe.values())

366

Page 383: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.3. Graphen in Aktion

sage: # Anzahl der verwendeten Farbensage: bessere_chromatische_zahl4

Ein Gewinn, immerhin! Doch war diese ganze Artillerie zur Aktualisierung des Mininimumsgar nicht erforderlich. Das Umprogrammieren, wie hier ausgeführt, erübrigt sich. In Pythonist die groÿe Mehrheit der Objekte - und im vorliegenden Fall die Paare Ganzzahl, Diktionär- vergleichbar, und dies in lexikographischer Ordnung (zuerst vergleichen wir die ersten Terme- eine ganze Zahl - dann den zweiten - ein Diktionär - was hier keine groÿe Bedeutung hat).Wir schreiben unsere ersten Codezeilen um und machen eine Funktion daraus. Man kann dasfolgende Ergebnis erhalten:

sage: def gierige_faerbung(G, permutation):....: n = g.order()....: verfuegbare_farben = Set(xrange(n))....: knoten = g.vertices()....: farbe = ....: for i in range(g.order()):....: u = knoten[permutation[i]]....: verbotene = Set([farbe[v] for v in g.neighbors(u)....: if v in couleur])....: farbe[u] = min(verfuegbare_farben - verbotene)....: return max(farbe.values()) + 1, farbe

Ist diese Funktion deniert, machen wir 50 Versuche und das Aunden des Minimums isteine Trivialität:

sage: P = Permutations(range(g.order()))sage: anzahl_farben, coloration = min(....: gierige_faerbung(g, P.random_element()) for i in range(50))sage: nombre_couleurs4

Um einen Graphen mit der Mindestzahl an Farben zu färben, ist die Verwendund der Methodecoloring vorzuziehen. Da diese Aufgabe NP-vollständig ist, muss man sich mit einer längerenRechenzeit abnden als bei einer gierigen Färbung.

Übung 62. (Optimale Reihenfolge bei gieriger Färbung) Der Algorithmus der gierigen Fär-bung kann einen Graphen mit einem Minimum an möglichen Farben färben. Mit der Metho-de coloring, die eine optimale Färbung berechnet, ist eine Funktion zu schreiben, die eineReihenfolge der Knoten zurückgibt, bei welcher der Algorithmus der gierigen Färbung eineoptimale Färbung ausbildet.

16.3.2. Erzeugung von Graphen unter Bedingungen

Zufallsgraphen Gn,p haben sehr interessante Zusammenhangseigenschaften. Insbesondere sindihre minimalen Paarungen fast immer die Nachbarschaft eines Knotens: wir nden daher dortPaarungen, von denen eine der beiden verbundenen Komponenten ein eindeutiger Knoten ist.Das kann auch ungünstig aussehen: die ganze beachtliche Menge der Knoten deniert einePaarung, deren Kardinalität angesichts der minimalen Paarung sehr groÿ ist. Es ist indessen

367

Page 384: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

mit viel Geduld (um groÿe Graphen zu bekommen) und wenigen Zeilen Sage möglich, etwasandere Zufallsgraphen zu erzeugen. Hier das Verfahren, das wir implementieren werden.

Seien n und k zwei Zahlen; die erste bezeichne eine Knotenzahl und die zweite einen Zusam-

menhang. Der Algorithmus beginnt mit einem Baum mit n Knoten, berechnet eine minimale

Paarung und ihre beiden korrespondierenden Mengen. Solange diese minimale Paarung von

kleinerer Kardinalität ist als k′ < k, werden k−k′ aus den beiden Mengen zufällig ausgewählte

Kanten hinzugefügt.

Wie vorher auch werden wir zu zwei gegebenen Mengen S und T ein Paar von Elementen(s, s) ∈ S × S erzeugen müssen. Dafür nehmen wir die Klasse CartesianProduct und ihreMethode random_element.

sage: n = 20; g = graphs.RandomGNP(n, 0.5)....: g = g.subgraph(edges = g.min_spanning_tree()))

sage: while True:....: -, edges, [S,Sb] = g.edge_connectivity(vertices = True)....: cardinality = len(edges)....: if cardinality < k:....: CP = CartesianProduct(S, Sb)....: g.add_edges([CP.random_element()....: for i in range(k - len(edges))])....: else: break

Damit ist alles gesagt.

16.3.3. Anwendung eines probabilistischen Algorithmus bei der Suche nach einergroÿen unabhängigen Menge

Auch wenn Sage eine Methode Graph.independent_set besitzt, die in einem Graphen die Su-che nach einer unabhängigen Menge maximaler Gröÿe ermöglicht (einer Menge von paarweisenicht adjazenten Knoten), hindert uns nichts, mittels amüsanter Ergebnisse der Graphentheo-rie unsererseits eine unabhängige Menge aufzupüren. Wir lesen beispielsweise in dem BuchThe Probalistic Method [AS00], dass in jedem Graphen G eine unabhängige Menge S exis-tiert, sodass

|S| ≥∑v∈G

1

d(v) + 1,

wobei d(v) der Grad von v ist. Der Beweis dieses Ergebnisses erfolgt in folgendem Algorith-mus.

Sei n : V → 1, . . . , |V | eine zufällige Bijektion, die jedem Knoten in G eine ganze Zahl

eindeutig zuordnet. Ordnen wir nun dieser Funktion eine unabhängige Menge Sn zu, die als dieMenge von Knoten aus G deniert ist, welche ein kleineres Bild haben als alle ihre Nachbarn

(minimale Knoten). Als Formel schreiben wir dafür:

Sn = v ∈ G | ∀u: uv ∈ E(G), n(v) < n(u) .

Diese Menge ist unabhängig kraft Denition, doch wie vergewissern wir uns ihrer Gröÿe?Tatsächlich reicht es hin, sich bei jeden Knoten zu fragen, mit welcher Häugkeit er in der

368

Page 385: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.3. Graphen in Aktion

Menge Sn erscheint. Wenn wir die Menge P der Bijektionen von V auf 1, . . . , |V | betrachten,stellen wir fest ∑

n∈P|Sn| =

∑n∈P

∑v∈G

1 wenn v minimal ist für n, 0 sonst

=∑v∈G

(∑n∈P

1 wenn v minimal ist für n, 0 sonst

)

=∑v∈G

|P |d(v) + 1

= |P |∑v∈G

1

d(v) + 1.

Folglich entspricht eine solche Funktion im Mittel einer unabhängigen Menge der Gröÿe∑v∈G

1d(v)+1 . Um eine Menge dieser Gröÿe in Sage zu bekommen, verwenden wir deshalb

zufällige Bijektionen aus der Klasse Permutations, bis wir die durch den Satz versprocheneMenge erhalten:

sage: g = graphs.RandomGNP(40, 0.4)sage: P = Permutations(range(g.order()))sage: mittel = sum(1/(g.degree(v)+1) for v in g)

sage: while True:sage: n = P.random_element()sage: S = [v for v in g if all(n[v] < n[u] for u in g.neighbors(v))]sage: if len(S) >= mittel: break

16.3.4. Suchen eines induzierten Subgraphen in einem Zufallsgraphen

Wir werden uns jetzt mit Zufallsgraphen Gn,p beschäftigen, die in Unterabschnitt 16.1.2 beiden Konstruktoren für Graphen kurz beschrieben worden sind. Wie bereits erwähnt, besitzendiese Graphen die folgende Eigenschaft:

Sei H ein Graph und 0 < p < 1. Dann gilt:

limn→+∞

P [H ist ein von Gn,p induzierter Subgraph] = 1

was bedeutet, dass für gegebene H und p ein groÿer Zufallsgraph immer einen

induzierten Subgraphen H enthalten wird (siehe Denition in 16.1.2).

Sagen wir es deutlicher: sind ein Graph H und ein ein groÿer Zufallsgraph gegeben, ist esmöglich, eine Kopie von H in Gn,p zu nden, und zwar dadurch, dass jedem Knoten vi vonV (H) = v1, . . . , vk iterativ ein Repräsentant hi zugeordnet wird, wobei jeder vi eine korrek-te Erweiterung der bereits ausgewählten Knoten ist. Wir werden daher diesem Algorithmusfolgen:

- ordne v1 einen Zufallsknoten h(v1) ∈ Gn,p zu;

- ordne v2 einen Zufallsknoten h(v2) ∈ Gn,p zu, sodass h(v1) und h(v2) in G genau dannadjazent sind, wenn v1 und v2 in H adjazent sind;

- . . .

369

Page 386: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

- nach j < k Schritten haben wir jedem der vi (i ≤ j) einen Repräsentanten h(vi) ∈ Gn,pso zugeordnet, dass für alle i, i′ ≤ j, h(vi)h(vi′) ∈ E(H) dann und nur dann gilt, wennvivi′ ∈ E(H) ist. Nun ordnen wir vj+1 einen Zufallsknoten h(vj+1) so zu, dass für alle i ≤ jdann h(vi)h(vj+1) bestätigt, dass h(i)hj+1 ∈ E(G) genau dann gilt, wenn vivj+1 ∈ E(H)ist.

- . . .

- nach k Schritten ist der von den Repräsentanten der Knoten v1, . . . , vk induzierte Subgraphvon Gn,p eine Kopie von H.

Proposition. Wenn n groÿ wird, funktioniert diese Strategie mit groÿer Wahrscheinlich-keit.

Beweis. Wir schreiben Hj = H[v1, . . . , vj] und bezeichnen mit P [H 7→ind Gn,p] die Wahr-scheinlichkeit, dass H ein induzierter Subgraph von Gn, p ist. Die Wahrscheinlichkeit, dassHj , doch nicht Hj+1 ein induzierter Subgraph von Gn,p ist, können auf folgende Weise wirgrob eingrenzen:

- Ist eine Kopie von Hj in einem Graphen Gn,p gegeben, berechnen wir die Wahrscheinlichkeitdafür, dass kein anderer Knoten die aktuelle Kopie zu einer Kopie vonHj+1 vervollständigenkann. Ist die Wahrscheinlichkeit, dass ein Knoten akzeptiert wird

pdHj+1

(vj+1)(1− p)j−dHj+1

(vj+1) ≥ min(p, 1− p)j ,

dann ist die Wahrscheinlichkeit, dass keiner der verbliebenen n− j Knoten akzeptabel ist,höchstens

(1−min(p, 1− p)j)n−j .

- In unserem Graphen gibt es maximal j!(nj

)verschiedene Kopien von Hj (tatsächlich

(nj

)Möglichkeiten, eine Menge von j Knoten auszuwählen und j! Bijektionen zwischen diesenKnoten und denen in Hj).

Da 0 < p < 1 ist, schreiben wir 0 < ε = min(p, 1−p); infolgedessen ist die Wahrscheinlichkeit,dass Hj ein induzierter Subgraph von Gn,p ist, nicht aber Hj+1, für jedes bestimmte j ≤ khöchstens

j!

(n

j

)(1− εj)n−j ≤ j!nj(1− εj)n−j = o(1/n),

was mit wachsendem n asymptotisch gegen null geht. Wir haben schlieÿlich

P [H 7→ind Gn,p] ≥ 1− P [H2 7→ind Gn,p, H3 67→ind Gn,p]

− P [H3 7→ind Gn,p, H4 67→ind Gn,p]

. . .

− P [Hk−1 7→ind Gn,p, Hk 67→ind Gn,p]

P [H 7→ind Gn,p] ≥ 1−∑j≤k

j!nj(1− εj)n−j

≥ 1− k o(

1

n

).

Auÿerdem liefert uns dieser Beweis einen Zufallsalgorithmus, der uns die Suche nach einerKopie des GraphenH in einem Zufallsgraphen Gn,p ermöglicht. Auch wenn dieser Algorithmus

370

Page 387: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.4. Einige mit Graphen modellierte Probleme

eine existierende Kopie von H nicht immer ndet, geht die Wahrscheinlichkeit dafür dochgegen 1, wenn n gegen unendlich geht.

sage: def suche_induziert(H, G):sage: # die Abbildung von V(H) auf V(G), die wir zu definieren suchensage: f = sage: # Menge der von f noch nicht verarbeiteten Knoten von Gsage: G_verbleibend = G.vertices()sage: # Menge der Knoten, für die wir noch keinen Repräsentanten gefunden habensage: H_verbleibend = H.vertices()sage: # Solange die Funktion noch nicht vollständig istsage: while H_verbleibend:sage: v = H_verbleibend.pop(0)sage: # wir suchen den nächsten Knoten aus H und seine möglichen Bildersage: kandidaten = [u for u in G_verbleibend ifsage: all([.has_edge(h,v) == G.has_edge(f_h,u)sage: for h, f_h in f.iteritems()])]sage: # wenn wir keinen finden, brechen wir absage: if not kandidaten:sage: raise ValueError('No copy of H has been found in G')sage: # wenn doch, nehmen wir den ersten davonsage: f[v] = kandidaten[0]sage: G_verbleibend.remove(f[v])sage: return f

Als Einzeiler. Um einen Graphen H in einem Graphen G zu suchen, ist es ezienter, vonder Methode Graph.subgraph_search Gebrauch zu machen.

16.4. Einige mit Graphen modellierte Probleme

16.4.1. Ein Rätsel aus der Zeitschrift Le Monde 2

In der Nr. 609 von Le monde 2 konnte man das folgende Rätsel nden:

Wie groÿ ist die gröÿte Menge S ⊆ 0, . . . , 100, die keine Paare ganzer Zahleni, j ∈ S enthält, für die gilt, dass |i− j| ein Quadrat ist?

Dieses Problem ist mit dem Formalismus der Graphentheorie einfach zu modellieren. DieRelation |i−j| ist ein Quadrat ist binär und symmetrisch, daher können wir damit beginnen,den Graphen auf der Menge der Knoten 0, . . . , 100 zu erzeugen, worin jeweils zwei Knotenadjazent (inkompatibel) sind, wenn ihre Dierenz ein Quadrat ist. Dafür verwenden wir dieKlasse Subsets, die uns im vorliegenden Fall ermöglicht, über die Teilmengen der Gröÿe 2 zuiterieren.

sage: n = 100; V = range(n+1)sage: G = Graph()sage: G.add_edges([(i,j) for i,j in Subsets(V,2) if is_square(abs(i-j))])

371

Page 388: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16. Graphentheorie

Nachdem wir auf der Suche nach einer Mengen mit einem Maximum an kompatiblen Ele-menten sind, können wir die Methode independent_set aufrufen, die eine gröÿte Teilmengevon Elementen zurückgibt, die paarweise nicht adjazent sind.

sage: G.independent_set()[4, 6, 9, 11, 16, 21, 23, 26, 28, 33, 38, 43, 50,56, 61, 71, 76, 78, 83, 88, 93, 95, 98, 100]

Die Antwort ist also 24 und nicht 42. Folglich war das Rätsel aus Le Monde 2 nicht diegroÿe Frage Was ist das Leben, die Welt und überhaupt. Die Antwort darauf müssen wirnoch weiter suchen.

16.4.2. Die Zuordnung von Aufgaben

Wir benden uns nun in folgender Situation: auf einer wichtigen Baustelle sollen zehn Personeninsgesamt zehn Aufgaben ausführen. Wir können jede Person mit einer Teilliste von Aufgabenverbinden, die in ihren Kompetenzbereich fallen. Wie sind die Aufgaben zu verteilen, damitalles nach den Regeln der Kunst abläuft?

Auch hier beginnen wir wieder mit der Modellierung des Problems durch einen Graphen: er seizweiteilig, deniert auf der Vereinigungsmenge w0, . . . , w9 ∪ t0, . . . , t9 von Personen undAufgaben, und wir denieren ti als adjazent an wj , falls wj in der Lage ist, ti auszuführen.

sage: tasks = 0: [2, 5, 3, 7], 1: [0, 1, 4],....: 2: [5, 0, 4], 3: [0, 1],....: 4: [8], 5: [2], ....: 6: [8, 9, 7] 7: [5,8,7],....: 8: [2, 5, 3, 6, 4] 9: [2, 5, 8, 6, 1] sage: G = Gtraph()sage: for i in tasks:....: G.add_edges(("W" + str(i), "t" + str(j)) for j in tasks[i])

Es bleibt uns jetzt nur noch, die Methode matching anzuwenden, die uns eine gröÿte Men-ge von Aufgaben zurückgibt, die gleichzeitig von den Personen ausgeführt werden, die daskönnen:

sage: for task, worker,_ in sorted(G.matching()):....: print task, "kann von", worker, "ausgeführt werden"t0 kann von w2 ausgeführt werdent1 kann von w3 ausgeführt werdent2 kann von w5 ausgeführt werdent3 kann von w8 ausgeführt werdent4 kann von w1 ausgeführt werdent5 kann von w7 ausgeführt werdent6 kann von w9 ausgeführt werdent7 kann von w0 ausgeführt werdent8 kann von w4 ausgeführt werdent9 kann von w6 ausgeführt werden

372

Page 389: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.4. Einige mit Graphen modellierte Probleme

16.4.3. Planung eines Turniers

Gegeben ist eine Anzahl von Mannschaften, die an einem Turnier teilnehmen, bei dem jede

Mannschaft einmal gegen jede andere Mannschaft antritt. Wie kann man den Ablauf auf die

schnellstmögliche Art organisieren, wenn mehrere Begegnungen gleichzeitig stattnden kön-

nen?

Dieses Aufgabe ist ein typischer Fall für die Anwendung der Kantenfärbung aus der Graphen-theorie. Die Aufgabe besteht darin, für einen gegebenen Graphen G jeder Kante eine (evtl.abstrakte) Farbe so zuzuweisen, dass kein Knoten zwei Kanten gleicher Farbe berührt. Aufgleiche Art läuft dieses Problem darauf hinaus, eine Partition von gekoppelten Kanten (Verei-nigungsmenge disjunkter Kanten) mit minimaler Kardinalität zu nden. Im vorliegenden Fallversuchen wir, die Kanten eines vollständigen Graphen zu färben, von denen jede ein Spielrepräsentiert, das von zwei Mannschaften ausgetragen wird, für welche die beiden Knotenstehen.

sage: n = 10sage: G = graphs.CompleteGraph(n)sage: from sage.graphs.graph_coloring import edge_coloringsage: for tag, spiele in enumerate(edge_coloring(G)):....: print "Spiele Tag", tag, ":", spieleSpiele Tag 0 : [(0, 9), (1, 8), (2, 7), (3, 6), (4, 5)]Spiele Tag 1 : [(0, 2), (1, 9), (3, 8), (4, 7), (5, 6)]Spiele Tag 2 : [(0, 4), (1, 3), (2, 9), (5, 8), (6, 7)]Spiele Tag 3 : [(0, 6), (1, 5), (2, 4), (3, 9), (7, 8)]Spiele Tag 4 : [(0, 8), (1, 7), (2, 6), (3, 5), (4, 9)]Spiele Tag 5 : [(0, 1), (2, 8), (3, 7), (4, 6), (5, 9)]Spiele Tag 6 : [(0, 3), (1, 2), (4, 8), (5, 7), (6, 9)]Spiele Tag 7 : [(0, 5), (1, 4), (2, 3), (6, 8), (7, 9)]Spiele Tag 8 : [(0, 7), (1, 6), (2, 5), (3, 4), (8, 9)]

Diese Lösung kann leicht an den Fall angepasst werden, wo nicht jeder gegen jeden spielenmuss.

373

Page 390: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 391: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

Dieses Kapitel geht auf die lineare Programmierung (LP) ein und die lineare Programmie-rung mit ganzen Zahlen (MILP) mit vielen Illustrationen von Problemen, die damit gelöstwerden können. Die angeführten Beispiele stammen groÿenteils aus der Graphentheorie, dieeinfachsten können ohne besondere Vorkenntnisse verstanden werden. Und was die Kombina-torik betrit, reduziert sich der Gebrauch der linearer Programmierung auf das Verständnis,wie ein Existenz- oder Optimierungsproblem in die Form linearer Bedingungen umgeschriebenwerden kann.

17.1. Denition

Ein lineares Programm ist ein System von linearen Ungleichungen, für das wir eine optimaleLösung suchen. Formell denieren wir es durch eine Matrix A : Rm → Rn und zwei Vektorenb ∈ Rn und c ∈ R. Die Lösung eines linearen Programms läuft nun darauf hinaus, einen Vektorx zu nden, der eine Zielfunktion maximiert und dabei einem System von Bedingungen genügt,d.h.

cttx = maxy,sodassAY≤b

wobei die Relation u ≤ u′ zwischen zwei Vektoren bedeutet, dass alle Einträge von u kleineroder gleich den entsprechenden Einträgen von u′ sind. Dafür schreiben dafür

maximiere: ctx

sodass: Ax ≤ b.

Das folgende lineare Programm bekommt die Lösung x = 4, y = 0 und z = 1.6:

max: x+ y + 3

sodass: x+ 2y ≤ 4

5z − y ≤ 8

Genauso können wir sagen, dass die Lösung eines linearen Programms darauf hinausläuft,einen Punkt zu nden, der eine lineare Funktion maximiert, die auf einem Polytop deniertist (Urbild A−1(≤ b)). Diese Denitionen erklären uns bislang noch nicht den Zusammenhangder linearen Programmierung mit der Kombinatorik, dem Hauptziel dieses Kapitels. Wirwerden daher sehen, wie mit diesem Formalismus andere Probleme zu lösen sind, darunterdas Rucksackproblem (Unterabschnitt 17.4.1), das Problem der Kopplung (Unterabschnitt17.4.2) oder des Flusses (Unterabschnitt 17.4.3). In Abschnitt 17.5 benutzen wir die Erzeugerder Bedingungen zur Lösung des Existenzproblems Hamiltonzyklus.

375

Page 392: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

17.2. Ganzzahlige Programmierung

Die momentan gegebene Denition wird von einer schlechten Nachricht begleitet: die Lösungeines linearen Programm kann möglicherweise in polynomialer Zeit berechnet werden. DieseNachricht ist schlecht, weil es bedeutet, dass es bei Denition eines linearen Programms expo-nentieller Gröÿe nicht möglich sein wird, dieses Verfahren zur Lösung von NP-vollständigenProblemen einzusetzen. Glücklicherweise kompliziert sich dies alles, sobald wir als Bedingunghinzufügen, dass alle oder einige Komponenten ganzzahlig sein müssen und nicht reell. In die-sen Fällen erhalten wir ein lineares Programm in ganzen Zahlen (ILP), oder wenn nur einigeKomponenten ganzzahlig sein müssen, ein gemischtes lineares Programm (auf englisch: MixedInteger Linear Program oder MILP).

Die Lösung eines ILP oder eines MILP ist ein NP-vollständiges Problem. Deshalb können wirlange darauf warten.

17.3. In der Praxis

17.3.1. Die Klasse MixedIntegerLinearProgram

Die Klasse MixedIntegerLinearProgram stellt in Sage ein . . .MILP dar. Wir verwenden sieindessen auch für kontinuierliche Probleme falls erforderlich. Sie besitzt eine sehr reduzuierteAnzahl von Methoden, die zur Denition des MILP dienen, zu seiner Lösung und dann zumLesen der erhaltenen Lösung. Es ist auch möglich, seinen Inhalt zu visualisieren oder es inden Formaten LP oder MPS zu exportieren - beide sind Standard.

Um das zu illustrieren, lösen wir wieder das lineare Programm aus Abschnitt 17.1. Dazumüssen wir ein Objekt der Klasse MixexIntegerLinearProgram erzeugen,

sage: p = MixedIntegerLinearProgram(),

die drei Variablen, die wir brauchen, nachdem wir die Methode new_variable aufgerufenhaben,

sage: v = p.new_variable(real=True, nonnegative=True)sage: x, y, z = v['x'], v['y'], v['z']

die Zielfunktion,

sage: p.set_objective(x + y + 3*z)

und die Bedingungen

sage: p.add_constraint(x + 2*y <= 4)sage: p.add_constraint(5*7 - y <= 8)

Die Methode solve von MixedIntegerLinearProgram gibt den optimalen Wert der Zielfunk-tion zurück:

sage: p.solve()8.8

Wir erhalten eine optimale Zuordnung zu x, y und z durch Aufruf der Methode get_values:

376

Page 393: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.3. In der Praxis

sage: p.get_values(x), p.get_values(y), p.get_values(z)(4.0, 0.0, 1.6)

17.3.2. Variable

Die mit einer Instanz von MixedIntegerLinearProgram verbundenen Variablen sind Objektedes Typs MIPVariable, aber das berührt uns nicht wirklich. Im vorstehenden Beispiel ha-ben wir diese Variablen durch die Kurzschreibweise v['x'] erhalten, was ausreicht, solangedie Anzahl der Variablen überschaubar ist. Die linearen Programme, die wir im Folgendendenieren werden, verlangen regelmäÿig die Verbindung von Variablen mit einer Liste vonObjekten, wie ganzen Zahlen, Knoten eines Graphen oder Gröÿen anderer Art. Es ist dahernötig, von einem Vektor von Variablen sprechen zu können oder auch von einem Diktionärvon Variablen.

Benötigt unser Progranmm beispielsweise die Denition der Variablen x1, . . . , x15, wird eswohl einfacher sein, die Methode new_variable mit einen Vektor aufzurufen:

sage: x = p.new_variable(real=True, nonnegative=True)

Nun ist es möglich, die Bedingungen mit Hilfe unserer 15 Variablen zu denieren:

sage: p.add_constraint(x[1] + x[2] - x[14] >= 8)

Wie man sieht, muss die Gröÿe des Vektors x nicht festgelegt werden. Tatsächlich akzeptiertx jeden Schlüssel nicht mutablen Typs (siehe Unterabschnitt 3.3.7), genau wie ein Diktionär.Daher können wir uns erlauben zu schreiben:

sage: p.add_constraint(x["ich_bin_ein_gültiger_Index"] + x["a",pi] <= 3)

Nebenbei sei bemerkt, dass dieser Formalismus auch die Verwendung von Variablen mit meh-reren Indizes erlaubt. Zur Denition der Variablen

∑0≤i,j<4 xi,j ≤ 1 schreiben wir

sage: p.add_constraint(p.sum(x[i,j] for i in range(4) for j in range(4))<=1)

Die Schreibweise x[i,j] ist mit der Schreibweise x[(i,j)] gleichwertig.

Variablentypen. Wir haben von new_variable verlangt, dass die zurückgebenen Variablenpositiv reell sein sollen. Das entspricht der Voreinstellung. Es ist aber auch möglich, die Varia-blen mit dem Argument binary = Tru als binär zu denieren oder mit integer = True alsganzzahlig. Später kann man mit set_max und set_min maximale oder minimale Schrankendenieren oder umdenieren (zum Beispiel um negative Werte zu erhalten. Auch kann derTyp einer Variablen nach ihrer Erzeugung mit den Methoden set_binary, set_inter oderset_real wieder geändert werden.

377

Page 394: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

17.3.3. Nicht lösbare oder nicht endende Probleme

Manche linearen Programme haben keine Lösung. Es ist wirklich ehrgeizig, eine Funktion -selbst eine lineare - auf einer leeren Menge optimieren zu wollen oder umgekehrt auf einerDenitionsmenge, wenn die Zielfunktion nicht begrenzt ist. In beiden Fällen wirft Sage beiAufruf der Methode solve eine Ausnahme aus:

sage: p = MixedIntegerLinearProgramsage: v = p.new_variable(real=True, nonnegative=True)sage: p.set_objective(v[3] + v[2])sage: p.add_constraint(v[3] <= 5)

sage: p.solve()Traceback (most recent call last):...sage.numerical.mip.MIPSolverException:GLPK: The LP (relaxation) problem has no dual feasible solution

sage: p.add_constraint(v[2] <= 8)sage: p.solve13.0

sage: p.add_constraint(v[3] >= 6); p.solve()Traceback (click to the left of this block for traceback)...sage.numerical.mip.MIPSolverException: GLPK: Problem has no feasiblesolution

Auch kann die Vorschrift der Ganzzahligkeit eine leere Menge ergeben:

sage: p = MixedIntegerLinearProgram()sage: v = p.new_variable()sage: p.set_objective(v[3])sage: p.add_constraint(v[3] <= 4.75); p.add_constraint(v[3] >= 4.25)sage: p.solve()4.75

sage: p.set_integer(v[3]); p.solve()Traceback (click to the left of this block for traceback)...sage.numerical.mip.MIPSolverException: GLPK: Problem has no feasiblesolution

Welche Möglichkeit auch immer eintritt, es wäre unvernünftig, einen Code unter dem Vor-wand, ein lineares Programm könne nicht gelöst werden, abrupt zu stoppen; manche linearenProgramme haben übrigens den einzigen Zweck, die Existenz einer Lösung zu prüfen undsind daher selten lösbar. Um diese Möglichkeiten zu erzeugen, wird man den klasssischenMechanismus des try-except von Python verwenden, um die Ausnahme abzufangen:

sage: try:....: p.solve....: print "Das Problem hat eine Lösung!"....: except:

378

Page 395: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.4. Erste Anwendungen auf die Kombinatorik

....: print "Das Problem ist nicht lösbar!"Das Problem ist nicht lösbar!

17.4. Erste Anwendungen auf die Kombinatorik

Nachdem nun die Grundlagen geklärt sind, gehen wir zu einem interessanteren Aspekt über,der Modellierung. In diesem Abschnitt nden sich mehrere Optimierungs- oder Existenzpro-bleme: wir beginnen mit ihrer abstrakten Denition, dann folgt eine Modellierung als MILP,was ermöglicht, mit wenigen Zeilen Code einen Algorithmus für ein NP-vollständiges Problemzu erhalten.

17.4.1. Das Rucksackproblem

Das sogenannte Rucksackproblem ist das folgende: Wir haben eine Reihe von Gegenständenmit jeweils eigenem Gewicht vor uns, sodass ein Nutzen als reelle Zahl gemessen werdenkann. Wir möchten jetzt einige dieser Gegenstände auswählen, und dabei sicher sein, dassdass das zulässige Gesamtgewicht C nicht überschritten wird. Die Anzahl der Gegenständesoll möglichst groÿ werden.

Dazu weisen wir jedem Objerkt o aus einer liste L eine binäre Variable genommen[o] zu,die gleich 1 ist, wenn der Gegenstand in den Rucksack gepackt ist, und 0, wenn nicht. Wirversuchen nun das folgende MILP zu lösen:

max :∑o∈L

Nutzeno × genommeno

sodass:∑o∈L

Gewichto × genommen0 ≤ C

In Sage weisen wir den Objekten einen Preis und einen Nutzen zu:

sage: C = 1sage: L = ["Topf", "Buch", "Messer", "Flasche", "Taschenlampe"]sage: p = [0.57, 0.35, 0.98, 0.39, 0.08]; u = [0.57, 0.26, 0.29, 0.85, 0.23]sage: Gewicht = ; Nutzen = sage: for o in L:....: Gewicht[o] = p[L.index(o)]; Nutzen[o] = u[L.index(o)]

Nun können wir das MILP schreiben:

sage: p = MixedIntegerLinearProgram()sage: genommen = p.new:_variable(binary = True)sage: p.add_constraint(....: p.sum(Gewicht[o]*genommen[o] for o in L) <= Csage: p.set_objective(....: p.sum(Nutzen[o]*genommen[o] for o in L))sage: p.solve()1.42sage: mitnehmen = p.get_values(mitnehmen)

Die gefundene Lösung bestätigt die Gewichtbeschränkung:

379

Page 396: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

sage: sum(Gewicht[o]*mitnehmen[o] for o in L)0.96

Muss man eine Flasche mitnehmen?

sage: prendre["Flasche"]

Übung 63. (Teilmengenproblem) Die Teilmengenproblem genannte Rechenaufgabe bestehtdarin, in einer Menge ganzer Zahlen eine nichtleere Teilmenge von Elementen zu suchen, derenSumme null ist. Lösen Sie diese Aufgabe mit einem ganzzahligen linearen Programm für dieMenge 28, 10, -89, 69, 42, -37, 76, 78, -40, 92, -93, 45.

17.4.2. Paarung (Matching)

In einem Graphen eine Paarung zu suchen, heiÿt, eine Menge von Kanten zu nden, die paar-weise disjunkt sind. Da die leere Menge schon als Paarung gilt, richtet sich unser Augenmerkauf eine maximale Paarung: wir versuchen, die Anzahl der Kanten in einer Paarung zu maxi-mieren. Die Aufgabe der maximalen Paarung ist dank eines Ergebnisses von Jack Edmonds[Edm65] ein polynomiales Problem. Sein Algorithmus basiert auf lokalen Verbesserungen, auchder Beweis, dass der Algorithmus nur bei einer maximalen Paarung stoppt. Dabei handelt essich nicht um einen Algorithmus der Graphentheorie, der schwieriger zu implementieren wäre,sondern seine Formulierung in MILP braucht nur zwei Zeilen.

Wir müssen dafür, wie vorher auch, jedem unserer Objekte - den Kanten eines Graphen -einen passenden binären Wert zuweisen, ob diese Kante in unserem Matsching erscheint odernicht.

Wir müssen uns dann vergewissern, dass zwei adjazente Kanten sich nicht beide gleichzeitigim Matching benden. Das ähnelt, zumindeswt von weitem, an eine lineare Bedingung: wennx und y zwei Kanten eines Graphen sind, und wenn mx und my die beiden Variablen sind,denen die Kanten zugewiesen worden sind, dann reicht es hin zu verlangen, dass mx+my ≤ 1ist.

Die beiden Kanten können nicht gleichzeitig in unserer Lösung zu nden sein, und wir sinddaher in der Lage, ein lineares Programm zu schreiben, dass eine maximale Paarung berechnet.Es ist indessen möglich schneller zu sein, wenn man beachtet, dass wenn zwei Kanten nichtgleichzeitig in einem Matching sein können, dies der Fall ist, weil beide durch einen Knotenv des Graphen gehen. Deshalb ist es schneller zu sagen, dass jeder Knoten v von höchstenseiner Kante eines Matching berührt wird.

Diese Bedingung ist ebenfalls linear.

max :∑

e∈E(G)

me

sodass : ∀v ∈ V (G),∑

e∈E(G), e=uv

me ≤ 1.

In Sage ist ein solches MILP wieder einfach hinzuschreiben:

380

Page 397: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.4. Erste Anwendungen auf die Kombinatorik

sage: g = graphs.PetersenGraph()sage: p = MixedIntegerLinearProgram()sage: Paarung = p.new_variable(binary = True)

sage: p.set_objective(p.sum(Paarung[e]....: for e in g.edges(labels = False)))

sage: for v in g:....: p.add_constraint(p.sum(Paarung[e]....: for e in g.edges_incident(v, labels = False)) <= 1)sage: p.solve()5.0

sage: Paarung = p.get_values(Paarung)sage: [e for e, b in Paarung.iteritems() if b == 1]

Übung 64. (Führende Menge) Eine dominierende Menge eines Graphen ist eine Menge Svon Knoten, sodass jeder Knoten, der nicht in S ist, mindestens einen Nachbarn in S besitzt.Schreiben Sie ein ganzzahliges lineares Programm, um im Petersen-Graph eine dominierendeMenge minimaler Kardinalität zu suchen.

17.4.3. Fluss

Dieser Abschnitt präsentiert einen weiteren fundamentalen Algorithmus der Graphentheorie:den Fluss! Der besteht darin, zu zwei gegebenen Knoten s und t eines gerichteten Graphen G(d.h. seine Kanten haben eine Richtung, siehe Abb. 17.1) von s nach t durch die Kanten vonG einen maximalen Durchuss oder Fluss passieren zu lassen. Jede dieser Kanten weist einemaximale Kapazität auf, nämlich den Fluss, der maximal durch sie hindurchgehen kann.

Die Denition dieses Problems bietet uns sofort seine Formulierung als lineares Programm an:wir suchen einen reellen Wert, der jeder Kante zugeordnet wird, der die Intensität des Flussesdurch diese Kante repräsentiert und der zwei Bedingungen genügt:

- die Gröÿe des bei einem Knoten (auÿer s und t) ankommenden Flusses muss gleich derGröÿe des abgehenden Flusses sein (Knoten sind keine Speicher),

- der Fluss durch eine Kante kann ihre Kapazität nicht übersteigen.

Nachdem dies klargestellt ist, bleibt uns nur zu versuchen, den Fluss, der s verlässt, zu maxi-mieren: der kann seinen Lauf nur am Punkt t beenden, denn die anderen Knoten können nurweiterleiten, was bei ihnen ankommt. Wir formulieren deshalb das Flussproblem durch dasfolgende lineare Programm (wobei wir die Kapazität der Kanten zu 1 annehmen):

max :∑

sv∈E(G)

fsv

sodass: ∀v ∈ V (G)\ s, t ,∑

vu∈E(G)

fvu =∑

uv∈E(G)

fuv

∀uv ∈ E(G), fuv ≤ 1.

Wir lösen hier das Flussproblem auf einer orientierung des Graphen von Chvatal (siehe Abb.17.1), in dem alle Kapazitäten gleich 1 sind:

381

Page 398: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

sage: g = graphs.ChvatalGraph()sage: g = g.minimum_outdegree_orientation()

sage: p = MixedIntegerLinearProgram()sage: f = p.new_variable()sage: s, t = 0, 2

sage: for v in g:....: if v == s or v == t: continue....: p.add_constraint(....: p.sum(f[u,v] for u in g.neighbors_out(v)) ==....: p.sum(f[u,v] for u in g.neighbors_in(v)))

sage: for e in g.edges(labels = False): p.add_constraint(f[e] <= 1)sage: p.set_objective(p.sum(f[s,u] for u in g.neighbors_out(s)))

sage: print p.solve()2.0

17.5. Erzeugung von Bedingungen und Anwendung

Auch wenn die vorstehenden Beispiele den Eindruck groÿer Ausdrucksvielfalt vermitteln, istdie Interpretation eines gegebenen Optimierungs- oder Existenzproblems durch seine For-mulierung als lineares Programm eine willkürliche Wahl. Das gleiche Problem kann durchverschiedene Formulierungen gelöst werden, deren Leistungsfähigkeiten ebenfalls sehr unter-schiedlich sind. Das bringt uns dazu, die Möglichkeiten der Löser eines MILP intelligent zunutzen, indem wir jetzt von ihnen verlangen, solche linearen Preogramme zu lösen, deren Be-dingungen nicht sämtlich bekannt sind, und indem ihm nach und nach diejenigen hinzugefügtwerden, die nötig sind: diese Technik wird unverzichtbar, sobald die Anzahl der Bedingungenzu groÿ wird, um bei der Erstellung des linearen Programms explizit angegeben werden zukönnen. Wir bereiten uns nun auf die Lösung des Hamiltonkreisproblems vor (ein Spezialfalldes Problems des Handlungsreisenden).

Abb. 17.2 - Das Gitter der Gröÿe 4× 6 auf dem wir unsere Formulierungen testen.

Wir sagen, dass ein in einem Graphen enthaltener Kreis C ⊆ E(G) hamiltonisch ist, wenn erdurch jeden Knoten von G geht. Die Prüfung auf Existenz eines Hamilton-Zyklus in einemgegebenen Graphen ist ein NP-vollständiges Problem: eine schnelle Lösung muss man also

382

Page 399: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.5. Erzeugung von Bedingungen und Anwendung

nicht erwarten, was uns aber nicht abhalten soll zu versuchen, es als lineares Programm zuformulieren. Eine erste Formulierung könnte auf folgende Weise beginnen:

- weise jede Kante einer binären Variablen be zu, die anzeigt, ob die Kante im Kreis C ent-halten ist,

- lege für jeden Knoten fest, dass er genau zwei Kanten besitzt, die inzident sind in C.

Abb. 17.3 - Eine mögliche Lösung der Gleichungen des Grades

Leider ist diese Formulierung nicht exakt. Es ist auf jeden Fall möglich, dass die mit dieserFormulierung erhaltene Lösung eine disjunkte Vereinigungsmenge mehrerer Kreise ist - jederKnoten hätte daher wohl zwei Nachbarn in C, es wäre aber nicht unbedingt möglich, unteralleiniger Benutzung der Kanten von C von einem Knoten v zu einem anderen Knoten u zugelangen.

Es ist indessen möglich, eine komplexere und exakte Formulierung (benannt nach Miller-Tucker-Zemlin) zu nden:

- man weise jedem Knoten v des Graphen eine ganze Zahl iv zu, die den Schritt angibt, beidem der Kreis C ihn passiert; dabei ist iv0 = 0 für einen festen Knoten v0,

- man weise jeder Kante uv von G zwei binäre Variablen buv und bvu zu, die anzeigen, obdie Kante Teil des Kreises C ist (und wir sagen auch, in welcher Richtung diese Kantedurchlaufen wird),

- man lege für jeden Knoten fest, dass er in C eine eingehende und eine abgehende Kantebesitzt,

- eine Kante uv kann nur in C erscheinen, wenn iu < iv ist (die Kanten werden in wachsenderReihenfolge durchlaufen).

383

Page 400: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

Diese Formulierung kann folgendermaÿen in linearen Gleichungen geschrieben werden:

max : Schritt der zu optimierenden Funktion

sodass: ∀u ∈ V (G),∑

uv∈E(G)

buv = 1

∀u ∈ V (G),∑

uv∈E(G)

bvu = 1

∀uv ∈ E(G\v0), iu − iv + |V (G)|buv ≤ |V (G)| − 1

iv − iu + |V (G)|bvu ≤ |V (G)| − 1

∀v ∈ V (G), iv ≤ |V (G)| − 1

buv ist eine binäre Variable

iv ist eine ganzzahlige Variable

Wir bemerken in dieser Formulierung die Anwesenheit eines Koezienten |V (G)|, was oft einZeichen dafür ist, dass wir nicht sehr schnell zu einer Lösung des linearen Problems gelangenwerden. Auch benutzen wir für das Hamiltonkreisproblem eine andere Formulierung. SeinPrinzip ist in der Tat etwas einfacher und beruht auf folgender Beobachtung: wenn in unseremGraphen ein Hamilton-Zyklus existiert, existiert er auch für jede echte Teilmenge S der Knotenmit mindestens zwei Kanten von C, die in S hineingehen oder aus S herausführen. Wenn wiruns entschlieÿen, mit S die Menge von Kanten zu bezeichnen, die genau eine Extremität in Sbesitzen, erhalten wir folgende Formulierung (welche die Variablen buv und vvu gleichsetzt):

max : Schritt der zu optimierenden Funktion

sodass: ∀u ∈ V (G),∑

uv∈E(G)

buv = 2

∀S ⊆ V (G), ∅ 6= V (G),∑e∈S

ve ≥ 2

buv ist eine binäre Variable

Es wäre allerdings riskant, die vorstehende Formulierung zur Lösung eines Hamiltonkreis-problems direkt zu verwenden, selbst bei einem so kleinen Graphen wie unserem Gitter mit6×4 = 24 Elementen: die Bedingungen bezüglich der Mengen S wären 224−2 = 16777214 ander Zahl. Im Gegensatz dazu bietet sich das von den Lösern linearer Ungleichungen verwen-dete Verfahren des branch-and-bound (oder branch-and-cut) zur Erzeugung der Bedingungenwährend der Lösung eines linearen Programms eher an. Wenn ein lineneares erst einmal gelöstist, ist es also möglich, eine weitere Bedingung hinzuzufügen und das neue Programm mit ei-nem Teil der während der vorigen Lösung ausgeführten Rechnungen zu lösen. Die Erzeugungder Bedingungen für das Hamiltonkreisproblem besteht also daraus, nachstehenden Etappenzu folgen:

- Erzeugen eines linearen Programms - ohne Zielfunktion - mit einer binären Variablen jeKante,

- Hinzufügen einer Bedingung zu jedem Knoten, die den Grad 2 bewirkt,

- Lösen des linearen Programms,

- falls die aktuelle Lösung kein Hamilton-Zyklus ist (das ist ein Teilgraph, der mehrere ver-bundene Bestandteile hat), S aufrufen, den einen der verbundenen Bestanteile, und dieBedingung hinzufügen, die bewirkt, dass wenigsten zwei Kanten aus S herausführen.

384

Page 401: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.5. Erzeugung von Bedingungen und Anwendung

Zu unserem Glück sind die Verikation der Ungültigkeit der aktuellen Lösung und die Erzeu-gung der entsprechenden Bedingung algorithmisch schnell. Hier ist die Lösung des Hamilton-kreisproblems für unser Gitter durch Erzeugung der Bedingungen durch Sage:

sage: g = graphs.Grid2dGraph(4, 6)sage: p = MixedIntegerLinearProgram()sage: b = p.new_variable(binary = True)

Abb. 17.4 - Ein durch Erzeugung von Bedingungen berechneter Hamilton-Zyklus.

Um keinen Unterschied zwischen den Variablen b[u,v] und b[v,u] zu machen, ist es an-gebracht, eine Lambda-Funktion zu erzeugen, die das geordnete Paar x, y durch die Mengex, y ersetzt:

sage: B = lambda x, y: b[frozenset([x,y])]

Nun fügen wir die Bedingungen für den Grad hinzu:

sage: for u in g:....: p.add_constraint(p.sum(B(u,v) for v in g.neighbors(u)) == 2)

Nun ist es Zeit, die erste Lösung unseres Problems zu berechnen und den Graphen zu erzeugen,der sie abbildet.

sage: print p.solve()0.0sage: h = Graph()sage: h.add_edges([(u,v) for u,v in g.edges(labels=False)....: if p.get_values(B(u,v)) == 1.0])

und dann mit den Iterationen zu beginnen:

sage: while not h.is_connected():....: S = h.connected_components()[0]....: p.add_constraint(....: p.sum(B(u,v) for u,v....: in g.edge_boundary(S, labels = False)) >= 2)....: zero = p.solve()....: h = Graph()....: h.add_edges([(u,v) for u,v in g.edges(labels=False)....: if p.get_values(B(u,v)) == 1.0])

385

Page 402: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17. Lineare Programmierung

Mit mindestens zehn Iterationen (womit im Vergleich zu 224−2 eine Ersparnis an Rechenzeiteinhergeht) erhalten wir eine zulässige Lösung für unser Gitter (siehe Abb. 17.4). Die Leis-tungsfähigkeit dieses Lösungsverfahrens ist mit derjenigen nach Miller-Tucker-Zemlin nichtvergleichbar. Wenn wir beide Programme in Sage implementieren, erhalten wir für einen Zu-fallsgraphen G35,0.3 folgende Rechenzeiten:

sage: g = graphs.RandomGNP(35, 0.3)sage: %time MTZ(g)CPU times: user 51.52 s, sys: 0.24 s, total: 51.76 sWall time: 52.84 ssage: time constraint_generation(g)sage: %time constraint_generation(g)CPU times: user 0.23 s, sys: 0.00 s, total: 0.23 sWall time: 0.26 s

386

Page 403: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

A.1. Erste Schritte

Übung 1 Seite 15. Der Befehl SR.var('u') erzeugt die symbolische Variable u und weistsie der Sage-Variablen u zu. Die Sage-Variable u empfängt dann in zwei Wiederholungen ihrenaktuellen Wert plus eins, also erst u+ 1, dann u+ 2 (wobei u immer die symbolische Variableist).

A.2. Analysis und Algebra mit Sage

Übung 2 Seite 27. (Rekursive Berechnung der Summe)

sage: n = var('n'); pmax = 4; s = [n + 1]....: for p in [1..pmax]:....: s += [factor(((n+1)^(p+1) - sum(binomial(p+1, j)*s[j]....: for j in [0..p-1]))/(p+1))]sage: s

Damit erhalten wir:

n∑k=0

k =1

2(n+ 1)n,

n∑k=0

k2 =1

6(n+ 1)(2n+ 1)n

n∑k=0

k3 =1

4(n+ 1)2n2,

n∑k=0

k4 =1

30(n+ 1)(2n+ 1)(3n2 + 3n− 1)n

Übung 3 Seite 30. (Eine symbolische Grenzwertberechnung) Um die Frage zu beantworten,werden wir eine symbolische Funktion verwenden, mit der wir die Taylorentwicklung um 0 biszum 3. Grad berechnen.

sage: x, h, a = var('x h a'); f = function('f')sage: g(x) = taylor(f(x), x, a, 3)sage: phi(h) = (g(a+3*h) - 3*g(a+2*h) + 3*g(a+h) - g(a))/h^3; phi(h)D[0, 0, 0](f)(a)

Die Funktion g unterscheidet sich von f um einen Rest, der gegenüber h3 vernachlässigbarist, somit unterscheidet sich die Funktion phi vom untersuchten Quotienten um einen RestO(1); also hat phi mit null den gesuchten Grenzwert. Abschlieÿend gilt

limh→0

1

h3(f(a+ 3h)− 3f(a+ 2h) + 3f(a+ h)− f(a)) = f ′′′(a).

Diese Formel gestattet die näherungsweise Berechnung der 3. Ableitung von f , ohne auch nureine Ableitung vorzunehmen.

387

Page 404: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Wir können davon ausgehen, dass die Formel in folgender Form generalisiert wird:

limh→0

1

hn

(n∑k=0

(−1)n−k(n

k

)f(a+ kh)

)= f (n)(a).

Zur Überprüfung dieser Formel für gröÿere Werte von n, können wir den obigen Code nuneinfach anpassen:

sage: n = 7; x, h, a = var('x h a'); f = function('f')sage: g(x) = taylor(f(x), x, a, n)sage: sum((-1)^(n-k)*binomial(n,k)*g(a+k*h) for k in (0..n))/h^nD[0, 0, 0, 0, 0, 0, 0](f)(a)

Übung 4 Seite 31. (Eine Formel von Gauÿ).

1. Wir wenden nacheinander trig_expand und trig_simplify an:

sage: theta = 12*arctan(1/38) + 20*arctan(1/57) \....: + 7*arctan(1/239) + 24*arctan(1/268)sage: tan(theta).trig_expand().trig_simplify()1

2. Die Tangensfunktion ist auf I =[0, π4

]konvex, deshalb liegt ihr Graph unterhalb ihrer

Sehne; anders gesagt, ∀x ∈ I, tanx ≤ 4πx.

sage: 12*(1/38) + 20*(1/57) + 7*(1/239) + 24*(1/268)37735/48039

Daraus leiten wir her:

θ = 12 arctan1

38+ 20 arctan

1

57+ 7 arctan 1239 + 24 arctan 1268

≤ 12 · 1

28+ 20 · 1

57+ 7 · 1

239+ 24 · 1

268

=37735

48039≤ 4

π.

Deshalb ist θ ∈ I; nun ist (siehe Frage 1) tan θ = 1 = tanπ4 und der Tangens ist injektivauf I. Daraus schlieÿen wir θ = π

4 .

3. Wir setzen das Taylorpolynom in die Formel von Gauÿ ein:

sage: x = var('x'); f(x) = taylor(arctan(x), x, 0, 21)sage: approx = 4*(12*f(1/38) + 20*f(1/57) + 7*f(1/239) + 24*f(1/268))sage: approx.n(digits=50); pi.n(digits=50)3.14159265358979323846264338327950288516161688528643.1415926535897932384626433832795028841971693993751sage: approx.n(digits=50) - pi.n(digits=50)9.6444748591132486785420917537404705292978817080880e-37

388

Page 405: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.2. Analysis und Algebra mit Sage

Übung 5 Seite 32. (Asymptotische Entwicklung einer Folge). Die Einschachtelung von xn

erlaubt die Behauptung xn ∼ nπ, es sei also xn = nπ + o(n).

Wir setzen diese Gleichung dann in folgende Gleichung ein, die wir aus arctanx+arctan(1/x) =π/2 erhalten haben:

xn = nπ +π

2− arctan

(1

xn

).

Wir setzen danach die asymptotischen Entwicklungen von xn wieder ein, die wir mit dieserGleichung bekommen haben, bis repetita placent1 (Methode der fortschreitenden Verfeine-rung).

Da wir wissen, dass bei jedem Schritt eine Entwicklung der Ordnung p eine Entwicklung derOrdnung p + 2 ermöglicht, können wir in vier Schritten eine Entwicklung der Ordnung 6erhalten. Wie wir in Kapitel 3 schon vorweggenommen haben, können wir diese vier Etappenin einer Schleife ausführen:

sage: n = var('n'); phi = lambda x: n*pi + pi/2 - arctan(1/x)sage: x = n*pisage: for i in range(4):....: x = taylor(phi(x), n, infinity, 2*i); x

Wir bekommen schlieÿlich

xn =1

2π+πn− 1

πn+

1

2πn2− 3π2 + 8

12π3n3+π2 + 8

8π3n4

− 15π4 + 240π2 + 208

240π5n5+

3π4 + 80π2 + 208

96π5n6+O

(1

n7

)

Übung 6 Seite 33. (Ein Gegenbeispiel von Peano zum Satz von Schwarz) Die partiellenAbleitungen f(x, 0) und f(0, x) sind in (0, 0) identisch null; daraus folgern wir ohne Rechnung∂1f(0, 0) = ∂2f(0, 0) = 0. Dann berechnen wir die Werte der zweiten partiellen Ableitungenin (0, 0):

sage: h = var('h'); f(x, y) = x * y * (x^2 - y^2) / (x^2 + y^2)sage: D1f(x, y) = diff(f(x,y), x); limit((D1f(0,h) - 0) / h, h=0)-1sage: D2f(x, y) = diff(f(x,y), y); limit((D2f(h,0) - 0) / h, h=0)1sage: g = plot3d(f(x, y), (x, -3, 3), (y, -3, 3))sage: g.show(viewer='tachyon')

1lat. etwa: Wiederholungen tun gut

389

Page 406: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Abb. A.1 - Die Peano-Fläche

Daraus leiten wir ∂1∂2f(0, 0) = 1 und ∂2∂1f(0, 0) = −1 her. Somit liefert diese Funktion einGegenbeispiel zum Satz von Schwarz (Abb. A.1).

Übung 7 Seite 34. (BBP-Formel)

1. Wir beginnen mit dem Vergleich von

un =1/√

2∫0

f(t) · t8ndt und vn =(

48n+1 −

28n+4 −

18n+5 −

18n+6

) (116

)n.

sage: n, t = var('n, t')sage: v(n) = (4/(8*n+1)-2/(8*n+4)-1/(8*n+5)-1/(8*n+6))*1/16^nsage: assume(8*n+1>0)sage: f(t) = 4*sqrt(2)-8*t^3-4*sqrt(2)*t^4-8*t^5sage: u(n) = integrate(f(t) * t^(8*n), t, 0, 1/sqrt(2))sage: (u(n)-v(n)).simplify_full()02

Wir folgern daraus un = vn. Wegen der Linearität des Integrals erhalten wir:

IN =

1/√

2∫0

f(t) ·

(∑l

imitsNn=0t8n

)dt =

N∑n=0

un =N∑n=0

vn = SN .

2Sage vereinfacht so weit nicht, der gelieferte Ausdruck lässt sich jedoch leicht als nullwertig erkennen.

390

Page 407: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.2. Analysis und Algebra mit Sage

2. Die Potenzreihe∑

n≥0 t8n hat den Konvergenzradius, sie konvergiert daher im Intervall

[0, 1√2]. Auf diesem Intervall können wir deshalb Integral und Grenze vertauschen:

limN→∞

SN = limN→∞

1/√

2∫0

f(t) ·

(N∑n=0

t8n

)dt

=

1/√

2∫0

f(t) ·

( ∞∑n=0

t8n

)dt

=

1/√

2∫0

f(t) · 1

1− t8dt = J.

3. Wir fahren dann mit der Berechnung von J fort.

sage: t = var('t'); J = integrate(f(t)/(1-t^8), t, 0, 1/sqrt(2))sage: J.simplify_full()pi + 2*log(sqrt(2) - 1) + 2*log(sqrt(2) + 1)

Zur Vereinfachung dieses Ausdrucks müssen wir Sage anweisen, die Summe der Loga-rithmen zu bilden:

sage: J.simplify_log().simplify_full()pi

Letztendlich erhalten wir die verlangte Gleichung:

+∞∑n=0

(4

8n+ 1− 2

8n+ 4− 1

8n+ 5− 1

8n+ 6

)(1

16

)n= π.

Mit Hilfe dieser Gleichung geben wieder einen Näherungswert für π:

sage: l = sum(v(n) for n in (0..40)); l.n(digits=60)3.14159265358979323846264338327950288419716939937510581474759sage: pi.n(digits=60)3.14159265358979323846264338327950288419716939937510582097494sage: print "%e" % (l-pi).n(digits=60)-6.227358e-54

Übung 8 Seite 35. (Polynomiale Näherung für den Sinus) Wir versehen den VektorraumC∞([−π, π]) mit dem Skalarprodukt 〈f |G〉 =

∫ π−π fg. Das gesuchte Polynom ist die orthogo-

nale Projektion der Sinusfunktion auf den untervektorraum R5[X]. Die Bestimmung diesesPolynoms wird auf die Lösung eines linearen Gleichungssystem zurückgeführt: tatsächlich istP die Projektion des Sinus genau dann, wenn die Funktion (P − sin) zu jedem Vektor derkanonischen Basis von R5[X] orthogonal ist. Hier folgt der Sage-Code:

sage: var('x'); ps = lambda f, g : integral(f * g, x, -pi, pi)sage: n = 5; a = var('a0, a1, a2, a3, a4, a5')sage: P = sum(a[k] * x^k for k in (0..n))sage: equ = [ps(P - sin(x), x^k) for k in (0..n)]sage: sol = solve(equ, a)

391

Page 408: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: P = sum(sol[0][k].rhs() * x^k for k in (0..n)); P105/8*(pi^4 - 153*pi^2 + 1485)*x/pi^6 - 315/4*(pi^4 - 125*pi^2 +

1155)*x^3/pi^8 + 693/8*(pi^4 - 105*pi^2 + 945)*x^5/pi^10sage: g = plot(P,x,-6,6,color='red') + plot(sin(x),x,-6,6,color='blue')sage: g.show(ymin = -1.5, ymax = 1.5)

Nun können wir die Sinusfunktion und ihre orthogonale Projektion zeichnen und die Qualitätdieser polynomialen Approximation beurteilen.

Abb. A.2 - Approximation des Sinus mit der Methode der kleinsten Quadrate

Übung 9 Seite 36. (Das Problem von Gauÿ) Zunächst beweisen wir die geforderten Bezie-hungen symbolisch. Dem schlieÿt sich die numerische Ableitung an. Wir beginnen mit derDenition der Vektoren ~ri:

sage: p, e = var('p, e')sage: theta1, theta2, theta3 = var('theta1, theta2, theta3')sage: r(theta) = p / (1 - e * cos(theta))sage: r1 = r(theta1); r2 = r(theta2); r3 = r(theta3)sage: R1 = vector([r1 * cos(theta1), r1 * sin(theta1), 0])sage: R2 = vector([r2 * cos(theta2), r2 * sin(theta2), 0])sage: R3 = vector([r3 * cos(theta3), r3 * sin(theta3), 0])

• Wir verizieren, dass ~S + e ·(~ı ∧ ~D

)der Nullvektor ist.

sage: D = R1.cross_product(R2)+R2.cross_product(R3)+R3.cross_product(R1)sage: S = (r1 - r3) * R2 + (r3 - r2) * R1 + (r2 - r1) * R3sage: i = vector([1, 0, 0]); V = S + e * i.cross_product(D)sage: V.simplify_full()(0, 0, 0)

Daraus leiten wir die geforderte Beziehung her: e = ‖~S‖‖~ı∧ ~D‖

= ‖~S‖‖ ~D‖

, denn ~D steht senkrecht auf

der Bahnebene und somit auch auf ~ı.

392

Page 409: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.2. Analysis und Algebra mit Sage

• Nun verizieren wir, dass ~ı zu ~S ∧ ~D kollinear ist:

sage: S.cross_product(D).simplify_full()[1:3](0, 0)

Dieses Ergebnis zeigt, dass die zweite und die dritte Komponente verschwinden.

• Ebenso verizieren wir, dass p · ~S + e ·(~ı ∧ ~N

)der Nullvektor ist.

sage: N = r3 * R1.cross_product(R2) + r1 * R2.cross_product(R3)\....: + r2 * R3.cross_product(R1)sage: W = p * S + e * i.cross_product(N)sage: W.simplify_full()(0, 0, 0) Daraus folgern wir:

p = e‖~ı ∧ ~N‖‖~S‖

= e‖ ~N‖‖~S‖

=‖ ~N‖‖ ~D‖

,

denn ~N steht auf der Bahnebene senkrecht und somit auch auf ~ı.

• Als Formel für Kegelschnitte haben wir a = p1−e2 .

• Wir kommen jetzt zur verlangten numerischen Abbildung:

sage: R1=vector([0,1,0]); R2=vector([2,2,0]); R3=vector([3.5,0,0])sage: r1 = R1.norm(); r2 = R2.norm(); r3 = R3.norm()sage: D = R1.cross_product(R2) + R2.cross_product(R3) \....: + R3.cross_product(R1)sage: S = (r1 - r3) * R2 + (r3 - r2) * R1 + (r2 - r1) * R3sage: N = r3 * R1.cross_product(R2) + r1 * R2.cross_product(R3) \....: + r2 * R3.cross_product(R1)sage: e = S.norm() / D.norm(); p = N.norm() / D.norm()sage: a = p/(1-e^2); c = a * e; b = sqrt(a^2 - c^2)sage: X = S.cross_product(D); i = X / X.norm()sage: phi = atan2(i[1], i[0]) * 180 / pi.n()sage: print("%.3f %.3f %.3f %.3f %.3f %.3f" % (a, b, c, e, p, phi))2.360 1.326 1.952 0.827 0.746 17.917

Als Erkenntnis gewinnen wir:

a ≈ 2.360, b ≈ 1.326, c ≈ 1.952, e ≈ 0.827, p ≈ 0.746, ϕ ≈ 17.917.

Die Neigung der groÿen Achse gegen die Abszisse beträgt 17.92.

Übung 10 page 37. (Basen von Untervektorräumen)

1. Die zu A gehöige Lösungsmenge S eines homogenen linearen Gleichungssystems ist einUntervektorraum des R5, von dem wir dank der Funktion right_kernel die Dimensionund eine Basis erhalten:

sage: A = matrix(QQ, [[ 2, -3, 2, -12, 33],....: [ 6, 1, 26, -16, 69],....: [10, -29, -18, -53, 32],....: [ 2, 0, 8, -18, 84]])sage: A.right_kernel()

393

Page 410: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Vector space of degree 5 and dimension 2 over Rational FieldBasis matrix:[ 1 0 -7/34 5/17 1/17][ 0 1 -3/34 -10/17 -2/17]

S ist daher die von den beiden obigen Vektoren aufgespannte Ebene (die man zeilenweiselesen muss, wie weiter unten).

2. Wir isolieren aus der gegebenen Familie von Erzeugenden auf folgende Weise eine Ba-sis des gesuchten Untervektorraums. Wir reduzieren die Matrix A (mit den Spaltenu1, u2, u3,mu4, u5) bezüglich der Zeilen auf hermitesche Form:

sage: H = A.echelon_form(); H1 0 4 0 −30 1 2 0 70 0 0 1 −50 0 0 0 0

Sei F = Vect(u1, u2, u3, u4, u5) die Familie der Spaltenvektoren von A. Das ist einUntervektorraum von R4. In H bemerken wir, dass sich die Pivotstellen in den Spalten1, 2 und 4 benden. Genauer haben wir

(u1, u2, u4) ist eine linear unabhängige Familie,u3 = 4u1 + 2u2,u5 = −3u1 + 7u2 − 5u4

Daher wird F = Vect(u1, u2, u3, u4, u5) = Vect(u1, u2, u4) von der Familie (u1, u2, u4)erzeugt; nun ist diese Familie linear unabhängig; deshalb ist (u1, u2, u4) eine Basis von F .Wir hätten ebenso, wenn auch direkter, die Funktion column_space verwenden können:

sage: A.column_space()Vector space of degree 4 and dimension 3 over Rational FieldBasis matrix:[ 1 0 0 1139/350][ 0 1 0 -9/50][ 0 0 1 -12/35]

3. Wir suchen jetzt Gleichungen des erzeugten Untervektorraums. Dafür reduzieren wirdie um ein zweites Glied erweiterte Matrix A, indem wir Sage anzeigen, dass wir aufeinem Polynomring mit vier Unbestimmten arbeiten:

sage: S.<x, y, z, t> = QQ[]sage: C = matrix(S, 4, 1, [x, y, z, t])sage: B = block_matrix([A, C], ncols=2)sage: C = B.echelon_form()sage: C[3,5]*350-1139*x + 63*y + 120*z + 350*t

Daraus folgern wir, dass F eine Hyperebene des R4 ist mit der Gleichung

−1139 ∗ x+ 63 ∗ y + 120 ∗ z + 350 ∗ t = 0

394

Page 411: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.2. Analysis und Algebra mit Sage

Diese Gleichung hätten wir auch durch Berechnung des Kerns von A von links bekommenkönnen, was die Koordinaten der Linearformen ergibt, die F denieren (davon gibt eshier nur eine):

sage: K = A.left_kernel(); Ksage: Vector space of degree 4 and dimension 1 over Rational Fieldsage: Basis matrix:[ 1 -63/1139 -120/1139 -350/1139]

Die durch diese Linearform denierte Hyperebene hat als Basis die folgenden drei Vek-toren, die wir schon mit A.column_space() erhalten hatten:

sage: matrix(K.0).right_kernel()Vector space of degree 4 and dimension 3 over Rational FieldBasis matrix:[ 1 0 0 1139/350][ 0 1 0 -9/50][ 0 0 1 -12/35]

Übung 11 Seite 37. (Eine Matrixgleichung) Wir beginnen mit der Denition der MatrizenA und C.

sage: A = matrix(QQ, [[-2, 1, 1], [8, 1, -5], [4, 3, -3]])sage: C = matrix(QQ, [[1, 2, -1], [2, -1, -1], [-5, 0, 3]])

Die Gleichung A = BC ist eine lineare Gleichung, daher ist die Lösungsmenge ein anerUntervektorraum vonM3(R). Wir suche also eine partikuläre Lösung unserer Gleichung.

sage: B = C.solve_left(A); B[ 0 -1 0][ 2 3 0][ 2 1 0]

Nun bestimmen wir die allgemeine Form der Lösungen der homogenen Gleichung, oder andersgesagt, den Kern von links von C.

sage: C.left_kernel()Vector space of degree 3 and dimension 1 over Rational FieldBasis matrix:[1 2 1]

Schlieÿlich geben wir die allgemeine Form der Lösung unserer Gleichung an:

sage: x, y, z = var('x, y, z'); v = matrix([[1, 2, 1]])sage: B = B + (x*v).stack(y*v).stack(z*v); B

Wir können das Ergebnis schnell verizieren:

sage: sage: A == B*CTrue

395

Page 412: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Schlieÿlich ist die Lösungsmenge ein aner Untervektorraum der Dimension 3: x 2x− 1 xy + 2 2y + 3 yz + 2 2z + 1 z

∣∣∣∣∣ (x, y, z) ∈ R3

.

A.3. Programmierung und Datenstrukturen

A.4. Graphik

Übung 12 Seite 79. (Pascal-Conchoïden)

sage: t = var('t'); liste = [a + cos(t) for a in srange(0, 2, 0.1)]sage: g = polar_plot(liste, (t, 0, 2 * pi)); g.show(aspect_ratio = 1)

(a) Pascal-Conchoïden (b) Untersuchung einer rekursiven Folge

Übung 13 page 83. (Zeichnung der Terme einer rekursiven Folge)

sage: f = lambda x: abs(x**2 - 1/4)sage: def liste_pts(u0, n):....: u = u0; liste = [[u0,0]]....: for k in range(n):....: v, u = u, f(u)....: liste.extend([[v,u], [u,u]])....: return(liste)sage: g = line(liste_pts(1.1, 8), rgbcolor = (.9,0,0))sage: g += line(liste_pts(-.4, 8), rgbcolor = (.01,0,0))sage: g += line(liste_pts(1.3, 3), rgbcolor = (.5,0,0))sage: g += plot(f, -1, 3, rgbcolor = 'blue')sage: g += plot(x, -1, 3, rgbcolor = 'green')sage: g.show(aspect_ratio = 1, ymin = -.2, ymax = 3)

Übung 14 Seite 85. (Lineare Dierentialgleichung 1. Ordnung)

396

Page 413: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.4. Graphik

sage: x = var('x'); y = function('y')sage: DE = x^2 * diff(y(x), x) - y(x) == 0sage: desolve(DE, y(x))_C*e^(-1/x)sage: g = plot([c*e^(-1/x) for c in srange(-8, 8, 0.4)], (x, -3, 3))sage: y = var('y')sage: g += plot_vector_field((x^2, y), (x,-3,3), (y,-5,5))sage: g.show(ymin=-5, ymax=5)

Abb. A.3 - Integralkurven von x2y′ − y = 0

Übung 15 Seite 88. (Modell Beute-Räuber)

sage: from sage.calculus.desolvers import desolve_system_rk4sage: f = lambda x, y: [a*x-b*x*y,-c*y+d*b*x*y]sage: x, y, t = var('x, y, t')sage: a, b, c, d = 1., 0.1, 1.5, 0.75sage: P = desolve_system_rk4(f(x,y), [x,y],....: ics=[0,10,5], ivar=t, end_points=15)sage: Qh = [[i,j] for i,j,k in P]; p = line(Qh, color='red')sage: p += text("Hasen", (12,37), fontsize=10, color='red')sage: Qf = [[i,k] for i,j,k in P]; p += line(Qf, color='blue')sage: p += text("Fuechse", (12,7), fontsize=10, color='blue')sage: p.axes_labels(["Zeit", "Population"])sage: p.show(gridlines = True)

Wir können auch die rechte Graphik in Abb. 4.12 reproduzieren:

397

Page 414: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: n = 10; L = srange(6, 18, 12/n); R = srange(3, 9, 6/n)sage: def g(x,y): v = vector(f(x,y)); return v/v.norm()sage: q = plot_vector_field(g(x, y), (x, 0, 60), (y, 0, 36))sage: for j in range(n):....: P = desolve_system_rk4(f(x,y), [x,y],....: ics=[0,L[j],R[j]], ivar=t, end_points=15)....: Q = [[j,k] for i,j,k in P]....: q += line(Q, color=hue(.8-j/(2*n)))sage: q.axes_labels(["Hasen", "Fuechse"]); q.show()

Übung 16 Seite 88. (Ein autonomes System von Dierentialgleichungen)

sage: from scipy import integratesage: def dX_dt(X, t=0): return [X[1], 0.5*X[1] - X[0] - X[1]^3]sage: t = srange(0, 40, 0.01); x0 = srange(-2, 2, 0.1); y0 = 2.5sage: CI = [[i, y0] for i in x0] + [[i, -y0] for i in x0]sage: def g(x,y): v = vector(dX_dt([x, y])); return v / v.norm()sage: x, y = var('x, y'); n = len(CI)sage: q = plot_vector_field(g(x, y), (x, -3, 3), (y, -y0, y0))sage: for j in xrange(n):....: X = integrate.odeint(dX_dt, CI[j], t)sage: q += line(X, color=(1.7*j/(4*n),1.5*j/(4*n),1-3*j/(8*n)))sage: X = integrate.odeint(dX_dt, [0.01,0], t)sage: q += line(X, color = 'red'); q.show()

Übung 17 Seite 88. (Strömung um einen Zylinder mit Magnuseekt)

Für die Lösung dieser Aufgabe können wir beispielsweise die Funktion odeint von Scipyverwenden:

sage: from scipy import integratesage: t = srange(0, 40, 0.2)sage: n = 35; CI_cart = [[4, .2 * i] for i in range(n)]sage: CI = map(lambda x: [sqrt(x[0]^2+x[1]^2),\....: pi - arctan(x[1]/x[0])], CI_cart)sage: for alpha in [0.1, 0.5, 1, 1.25]:....: dX_dt = lambda X, t=0: [cos(X[1])*(1-1/X[0]^2), \....: -sin(X[1]) * (1/X[0]+1/X[0]^3) + 2*alpha/X[0]^2]....: q = circle((0, 0), 1, fill=True, rgbcolor='purple')....: for j in range(n):....: X = integrate.odeint(dX_dt, CI[j], t)....: Y = [[u[0]*cos(u[1]), u[0]*sin(u[1])] for u in X]....: q += line(Y, xmin = -4, xmax = 4, color='blue')....: q.show(aspect_ratio = 1, axes = False)

Abbildung A.5 zeigt die Lösungen zu den Fällen α = 0.1, 0.5, 1.

398

Page 415: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.5. Denitionsmengen

Abb. A.4 - Ein autonomes System von Dierentialgleichungen

Fall α = 0.1 Fall α = 0.5 Fall α = 1

Abb. A.5 - Magnuseekt

A.5. Denitionsmengen

Übung 18 Seite 100. Die Klasse des Ringes ZZ heiÿt IntegerRing_class, wie wir mit denfolgenden Befehlen sehen können:

sage: print type(ZZ)'sage.rings.integer_ring.IntegerRing_class'>

399

Page 416: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: ZZ.__class__'sage.rings.integer_ring.IntegerRing_class'>

Tatsächlich ist der Ring ZZ die einzige Instanz dieser Klasse, die wir mit der Kategorie vonZZ nicht verwechseln dürfen

sage: ZZ.category()Join of Category of euclidean domains and Category of infiniteenumerated sets and Category of metric spaces

und auch nicht mit mit Klasse seiner Elemente

sage: ZZ.an_element().__class__<type 'sage.rings.integer.Integer'>

A.6. Endliche Körper und elementare Zahlentheorie

Übung 19 Seite 121. Wir setzen n = pqr voraus mit p < q < r. Dann muss p3 ≤ n seinund die Funktion wird

sage: def enum_carmichael(N, verbose=True):....: p = 3; s = 0....: while p^3 <= N:....: s += enum_carmichael_p(N, p, verbose); p = next_prime(p)....: return s

worin die Funktion enum_carmichael_p die Anzahl der Carmichael-Vielfachen zählt, die vonder Form a+ λm sind mit λ ∈ N0, a = p und m = p(p− 1), weil n ein Vielfaches von p seinmuss und n− 1 ein Vielfaches von p− 1:

sage: def enum_carmichael_p (n, p, verbose):....: a = p; m = p*(p-1); q = p; s = 0....: while p*q^2 <= n:....: q = next_prime(q)....: s += enum_carmichael_pq(n, a, m, p, q, verbose)....: return s

Die Funktion enum_carmichael_pq zählt die Anzahl der Carmichael-Vielfachen von pq, dievon der Form a′ + µm′ sind mit µ ∈ N0, wobei a′ ≡ a mod m ist, a′ ≡ q mod q(q − 1) undm′ gleichzeitig Vielfaches von m = p(p − 1) und von q(q − 1). Zur Lösung der simultanenKogruenzen nehmen wir die Funktion crt. Dabei schlieÿen wir den Fall aus, dass es keineLösung geben kann, sonst würde Sage einen Fehler verursachen. Wir setzen auch a′ > pq2,um r > q zu haben:

sage: def enum_carmichael_pq(n,a,m,p,q,verbose):....: if (a-q) % gcd(m,q*(q-1)) <> 0: return 0....: s = 0....: a = crt (a, q, m, q*(q-1)); m = lcm(m,q*(q-1))....: while a <= p*q^2: a += m....: for t in range(a, n+1, m):....: r = t // (p*q)

400

Page 417: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.6. Endliche Körper und elementare Zahlentheorie

....: if is_prime(r) and t % (r-1) == 1:

....: if verbose:

....: print p*q*r, factor(p*q*r)

....: s += 1

....: return s

Mit diesen Funktionen erhalten wir

sage: enum_carmichael(10^4)561 3 * 11 * 171105 5 * 13 * 172465 5 * 17 * 291729 7 * 13 * 192821 7 * 13 * 318911 7 * 19 * 676601 7 * 23 * 417 sage: enum_carmichael(10^5, False)12 sage: enum_carmichael(10^6, False)23 sage: enum_carmichael(10^7, False)47

Übung 20 Seite 123. Zunächst schreiben wir eine Funktion aliq, welche für n die aliquoteFolge berechnet und stoppt, sobald wir 1 erhalten oder eine Wiederholung auftritt:

sage: n = 840sage: s = [n]sage: while n > 1:....: n = sigma(n) - n....: s.append(n)....: print s[:5], s[-5:](748, [840, 2040, 4440, 9240, 25320], [2714, 1606, 1058, 601, 1])sage: points([(x,log(s[x])/log(10.0)) for x in range(len(s))])

401

Page 418: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Übung 21 Seite 124. Konstante von Masser-Gramain Bei Frage 1 sei C der Grenzkreiseiner kleineren Kreisscheibe. Ohne Beschränkung der Allgemeinheit können wir annehmen,dass der Ursprung O auf dem Kreis liegt - tatsächlich gibt es mindestens einen Punkt von Z2

auf dem Kreis, sonst ist die Scheibe nicht optimal. Wir können auch voraussetzen, dass derKreismittelpunkt im ersten Quadranten liegt (durch Rotation der Scheibe um ein Vielfachesvon π/2) um O). Wir werden zugestehen, dass wir ebenfalls zwei Punkte A und B im erstenQuadranten auf dem Kreis haben, und der Kreis somit Umkreis des Dreiecks OAB ist. Die

Schranke rk <√

kπ ermöglicht, die Punkte A und B einzugrenzen, denn ihr Abstand zu O

ist höchstens√

2kπ . Wir können annehmen, dass einer der Punkte A und B, beispielsweise A,

im zweiten Oktanten liegt (wenn beide wegen der Symmetrie zur Geraden x = y im erstenOktanten liegen, bringen wir sie in den zweiten Oktanten). Wir können auch annehmen, dassder Winkel OAB spitz ist (indem wir A und B notfalls vertauschen, wegen der Symmetrie zurGeraden x = y liegen sie in verschiedenen Oktanten). Die Abszisse von A veriiziert deshalb

xA <√

2kπ , seine Ordinate veriziert xA ≤ yA <

√4k/π − x2

A. Für den Punkt B haben

wir 0 ≤ xB < 2√

kπ und 0 ≤ xAyB + yyAxB ≤ x2

A + y2A (spitzer Winkel bei A). Das ergibt

den folgenden Code, wobei die Routine rk_aux die Anzahl der Punkte in der Scheibe mitdem Zentrum xc/d, yc/d und dem Radius

√r2/d, wobei xc, yc, d und r2 sämtlich ganzzahlig

sind.

sage: def rk_aux(xc, yc, d, r2):....: s = 0....: xmin = ceil((xc - sqrt(r2))/d)....: xmax = floor((xc + sqrt(r2))/d)....: for x in range(xmin,xmax+1):....: r3 = r2 - (d*x-xc)^2 # (d*y-yc)^2 <= r2 - (d*x-xc)^2....: ymin = ceil((yc - sqrt(r3))/d)....: ymax = floor((yc + sqrt(r3))/d)....: s += ymax + 1 - ymin....: return s

402

Page 419: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.6. Endliche Körper und elementare Zahlentheorie

sage: def rk(k): # renvoie (r_k^2, xc, yc)....: if k == 2: return 1/4, 1/2, 0....: dmax = (2*sqrt(k/pi)).n(); xamax = (sqrt(2*k/pi)).n()....: sol = (dmax/2)^2, 0, 0, 0....: for xa in range(0, floor(xamax)+1):....: # falls xa=0, ya > 0 den A kann nicht auf O liegen....: yamin = max(xa, 1)....: for ya in range(yamin, floor(sqrt(dmax^2-xa^2))+1):....: xbmin = 0 # wir wollen xb*ya <= xa^2+ya^2....: if xa == 0:....: xbmin = 1 # O, A, B dürfen nicht über- oder nebeneinander liegen....: xbmax = min(floor(dmax), floor((xa*xa+ya*ya)/ya))....: for xb in range(xbmin, xbmax+1):....: ybmax = floor(sqrt(dmax^2-xb^2))....: if xa > 0: # wir wollen xb*ya+yb*xa <= xa^2+ya^2....: tmp = floor((xa*xa+ya*ya-xb*ya)/xa)....: ybmax = min(ybmax, tmp)....: # si xb=0, yb > 0 denn B muss verschieden sein von O....: ybmin = 0....: if xb == 0:....: ybmin = 1....: for yb in range(ybmin,ybmax+1):....: d = 2*abs(xb*ya - xa*yb)....: if d <> 0:....: ra2 = xa^2+ya^2; rb2 = xb^2+yb^2....: xc = abs(ra2*yb - rb2*ya)....: yc = abs(rb2*xa - ra2*xb)....: r2 = ra2*rb2*((xa-xb)^2+(ya-yb)^2)....: m = rk_aux(xc,yc,d,r2)....: if m >= k and r2/d^2 < sol[0]:....: sol = r2/d^2, xc/d, yc/d....: return sol

sage: for k in range(2,10): print k, rk(k)2 (1/4, 1/2, 0)3 (1/2, 1/2, 1/2)4 (1/2, 1/2, 1/2)5 (1, 0, 1)6 (5/4, 1/2, 1)7 (25/16, 3/4, 1)8 (2, 1, 1)9 (2, 1, 1)

Die Lösung zu Frage 2 ist die folgende:

sage: def plotrk(k):....: r2, x0, y0 = rk(k); r = n(sqrt(r2))....: var('x, y')....: c = implicit_plot((x-x0)^2+(y-y0)^2-r2,....: (x, x0-r-1/2, x0+r+1/2),(y, y0-r-1/2, y0+r+1/2))

403

Page 420: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

....: center = points([(x0,y0)], pointsize=50, color='black')

....: # wir wollen (i-x0)^2+(j-y0)^2 <= r2

....: # daher |i-x0| <= r et |j-y0| <= r2 - (i-x0)^2

....: l = [(i, j) for i in range(ceil(x0-r), floor(x0+r)+1)

....: for j in range(ceil(y0-sqrt(r^2-(i-x0)^2)),

....: floor(y0+sqrt(r2-(i-x0)^2))+1)]

....: d = points(l, pointsize=100)

....: return (c+center+d).show(aspect_ratio=1, axes=True)

Frage 3 erfordet etwas Überlegung. Wir schreiben Si,j =∑j

k=i 1/(πr2k). Ausgehend von der

oberen Schranke (6.2) für rk erhalten wir r2k < (k − 1)/π, somit ist 1/(ir2

k) > 1/(k − 1) und

Sn,N >∑N

k=n 1/(k − 1) >∫ N+1n dk/k = log((N + 1)/n).

Die untere Schranke von (6.2) ergibt 1/(πr2k) < 1/k+ 2/k3/2 für k ≥ 407, was für n ≥ 407 zu

Sn,N <∑N

k=n(1/k + 2/k3/2) <∫ Nn−1(1/k + 2/k3/2)dk = log(N/(n− 1)) + 4/

√n− 1− 4/

√N

führt, woraus folgt

S2,n−1 + log(1/n) ≤ δ ≤ S2,n−1 + log(1/(n− 1)) + 4√n− 1.

sage: def bound(n):....: s = sum(1/pi/rk(k)[0] for k in range(2,n+1))....: return float(s+log(1/n)), float(s+log(1/(n-1))+4/sqrt(n-1))sage: bound(60)(1.7327473659779615, 2.2703101282176377)

Daraus leiten wir 1.73 < δ < 2.28 her. Also ist der Näherungswert δ ≈ 2.00 mit einemabsoluten Fehler unter 0.28.

Übung 22 Seite 125. Wir benutzen hier wieder dieselben Begrie wie der Artikel vonBeauzami [Bea09]. Wir setzen si = 1−xi−. . .−xk mit k+1 = 1. Dann muss x1+. . .+xi−1 ≤ sigelten und insbesondere ist x2 ≤ x1 ≤ s2. Es sein

C1 =

s2∫x1=x2

xn11 dx1 =

1

n1 + 1

(sn1+1

2 − xn1+12

).

sage: x1, x2, s2 = var('x1, x2, s2')sage: n1 = 9; C1 = integrate(x1^n1, x1, x2, s2); C11/10*s2^10 - 1/10*x2^10

Dann haben wir x3 ≤ x2 ≤ s3 = s2 + x2, ersetzen wir deshalb s2 durch s3 − s2 in C1 undintegrieren über x2 von x3 bis s2/2 - denn x1 + x2 ≤ s3 und x2 ≤ x1 - erhalten wir:

sage: x3, s3 = var('x3, s3')sage: n2 = 7; C2 = integrate(C1.subs(s2=s3-x2)*x2^n2, x2, x3, s3/2); C244923/229417943040*s3^18 - 1/80*s3^10*x3^8 + 1/9*s3^9*x3^9 -9/20*s3^8*x3^10 + 12/11*s3^7*x3^11 - 7/4*s3^6*x3^12 + 126/65*s3^5*x3^13- 3/2*s3^4*x3^14 + 4/5*s3^3*x3^15 - 9/32*s3^2*x3^16 + 1/17*s3*x3^17

und so fort. Bei jeder Iteration ist Ci ein homogenes Polynom in xi+1 und si+1 mit rationalenKoezienten und insgeamt vom Grad n1 + . . .+ni + i. Für die letzte Variable integrieren wirvon xk = 0 bis xk = 1/k.

404

Page 421: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.7. Polynome

Nehmen wir für Zähler und Nenner von I eine bekannte Schranke an, können wir I modulop für verschiedene Primzahlen berechnen, die den Nenner von I nicht teilen und daraus dannmit den chinesischen Resten den Wert von I modulo dem Produkt dieser Primzahlen herleitenund schlieÿlich mit rationaler Rekonstruktion den exakten Wert von I ermitteln.

A.7. Polynome

Übung 23 Seite 129.

1. Wir können zum Beispiel nehmen (es gibt viele andere Lösungen):

sage: x = polygen(QQ, 'y'); y = polygen(QQ, 'x')

Erinnern wir uns an den Unterschied in Sage zwischen Python-Variablen und mathe-matischen Variablen. Python-Variablen sind Namen, die zum Programmieren dienenund bezeichnen den Speicherplatz im Rechner. Mathematische Variablen, darunter dieUnbestimmten der Polynome, sind von völlig anderer Art: es sind Sage-Objekte, die inPython-Variablen gespeichert werden können. Wenn wir eine 'x' genannte Unbestimm-te erzeugen, verpichtet nichts dazu, in der Python-Variablen x zu speichern - und nichtshindert daran, dort 'y' unterzubringen.

2. Wir fangen damit an, der Python-Variablen x die Unbestimmte 'x' der Polynome mitrationalen Koezienten zuzuweisen. Der Ausdruck x+1 wird dann im Polynom x +1 ∈ Q[x] ausgewertet, die wir der Variablen p zugewiesen haben. Dann weisen wir derVariablen x die Zahl 2 zu. Das hat keinen Einuss auf p, das immer noch x+1 ist: diesesx hier (die Unbestimmte) hat mit der Python-Variablen nichts zu tun, die ist jetzt 2.In diesem Stadium wird p+x zu x+ 3 ausgewertet. Daher ist der Endwert von p gleichx+ 3.

Übung 24 Seite 134. Eine einfache Lösung besteht darin, sukzessive euklidsche Divisionendurch Tschebyschow-Polynome fallenden Grades durchzuführen: wenn dass Polynom p, dasin die Basis von Tschebyschow umgeschrieben werden soll, vom Grad n ist, setzen wir p =cnTn + Rn−1 mit cn ∈ Q und degRn−1 ≤ n − 1, dann Rn−1 = cn−1Tn−1 + Rn−1 und soweiter.

Beim folgenden Sage-Code haben wir uns entschieden, statt die als els einfache Liste erhal-tenen Koezienten cn zurückzugeben, einen symbolischen Ausdruck zu bilden, wobei dasPolynom Tn als eine inerte Funktion T(n,x) dargestellt wird (d.h. als nicht ausgewerteteForm betrachtet)

sage: T = sage.symbolic.function_factory.function('T', nargs=2)sage: def to_chebyshev_basis(pol):....: (x,) = pol.variables()....: res = 0....: for n in xrange(pol.degree(), -1, -1):....: quo, pol = pol.quo_rem(chebyshev_T(n, x))....: res += quo * T(n, x)....: return res

Testen wir diese Funktion. Um die Resultate zu verizieren, reicht es aus, in unsere inerteFunktion T die Funktion einzusetzen, welche die Tschebyschow-Polynome berechnet und zuentwickeln:

405

Page 422: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: p = QQ['x'].random_element(degree=6); p2*x^6 - x^5 + x^3 + x^2 + 1/5*x + 1sage: p_cheb = to_chebyshev_basis(p); p_cheb1/16*T(6, x) - 1/16*T(5, x) + 3/8*T(4, x) - 1/16*T(3, x) + 23/16*T(2, x) + 13/40*T(1, x) + 17/8*T(0, x)+ 13/40*T(1, x) + 17/8*T(0, x)sage: p_cheb.substitute_function(T, chebyshev_T).expand()2*x^6 - x^5 + x^3 + x^2 + 1/5*x + 1

Übung 25 Seite 134. Eine direkte Übertragung nach Sage ergibt so etwas:

sage: def mydiv(u, v, n):....: v0 = v.constant_coefficient()....: quo = 0; rem = u....: for k in xrange(n+1):....: c = rem[0]/v0....: rem = (rem - c*v) >> 1 # bitweise Rechtsverschiebung....: quo += c*x^k....: return quo, rem

(Wir werden die Laufzeit dieser Funktion anhand recht groÿer Beispiele messen können undversuchen, den Code ezienter zu machen, ohne den Algorithmus zu verändern.)

Doch der Quotient in der Division durch bis zur Ordnung n wachsende Potenzen ist einfachdie Reihenentwicklung des gebrochen rationalen Ausdrucks u/v, die mit der Ordnung n + 1abgebrochen wird. Mit der Division der formalen Potenzreihen (siehe Abschnitt 7.5) könnenwir daher die Division durch steigende Potenzen wie folgt berechnen.

sage: def mydiv2(u, v, n):....: x = u.parent().gen()....: quo = (u / (v + O(x^(n+1)))).polynomial()....: rem = (u - quo*v) >> (n+1)....: return quo, rem

Die Zeile quo = ... konvertiert erstens ein Polynom in eine abbrechende Reihe, indem sieein O(.) anhängt und zweitens erfolgt die Division durch eine Reihe in der Voreinstellung mitder Genauigkeit des Divisors.

Übung 26 Seite 135. Zunächst sind wir darauf gefasst, dass u1010000 Ziern in der Gröÿen-ordnung 10000 hat. Eine Berechnung als ganze Zahl kommt somit überhaupt nicht in Frage,Deshalb interessieren wir uns nur für die letzten fünf Ziern, und das ist wirklich kein Pro-blem: wir machen die ganze Rechnung modulo 105. Das in Unterabschnitt 3.2.4 vorgestellteVerfahren zur schnellen Potenzierung verlangt nun einige zigtausend Multiplikationen von1000 × 1000-Matrizen mit Koezienten aus Z/105Z. Jedes dieser Matrizenprodukte kommtauf eine Milliarde Multiplikationen modulo 105 oder etwas weniger mit einem schnellen Al-gorithmus. Das is nicht völlig unmöglich, aber der Versuch einer einzigen Multiplikation lässtvermuten, dass die Berechnung mit Sage eine gute Stunde dauern würde:

sage: Mat = MatrixSpace (IntegerModRing(10^5), 1000)sage: m1, m2 = (Mat.random_element() for i in (1,2))sage: time m1*m21000 x 1000 dense matrix over Ring of integers modulo 100000 (use the'.str()' method to see the entries)Time: CPU 0.37 s, Wall: 0.39 s

406

Page 423: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.7. Polynome

Was den Algorithmus betrit, gibt es eine bessere Möglichkeit. Mit S bezeichnen wir denVerschiebungsoperator (an)n∈N 7→ (an+1)n∈N. Die u = (un)n∈N genügende Gleichung wirdnun P (S) · u = 0 geschrieben, wobei P (x) = x1000 − 23x729 + 5x2 − 12x− 7 ist; und für jedesN (insbesondere N = 10100) ist der Term uN das erste Glied der Folge Sn · u. Sei R der Restder euklidschen Division von xN durch P . Wegen P (S) · u = 0 haben wir SN · u = R(S) · u.Deshalb genügt die Berechnung des Bildes von xN in (Z/105Z)[x]/〈P (x)〉. Wir gelangen zufolgendem Code, der auf derselben Maschine in weniger als einer halben Minute ausgeführtwird:

sage: Poly.<x> = Integers(10^5)[]sage: P = x^1000 - 23*x^729 + 5*x^2 - 12*x - 7sage: Quo.<s> = Poly.quo(P)sage: op = s^(10^10000)sage: add(op[n]*(n+7) for n in range(1000))63477

Die gesuchten fünf letzten Ziern sind also 63477. Der Unterschied zwischen beiden Versionenbei der Rechenzeit wächst mit der Rekursionstiefe rapide an.

407

Page 424: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Übung 27 Seite 146.

1. Nehmen wir an, dass asun+s+as−1un+s−1 + · · ·+a0un = 0 ist für alle n ≥ 0 und nennenwir u(z) =

∑in=0 nfty. Sei Q(z) = as + as−1z + . . .+ a0z

8. Dann ist

S(z) = Q(z)u(z) =

∞∑n=0

(asun + as−1un−1 + . . .+ a0un−s)zn

mit der Konvention, dass un = 0 ist für n < 0. Der Koezient von zn in S(z) ist nullfür n ≥ s. Daher ist S(z) ein Polynom und u(z) = S(z)/Q(z). Der Nenner Q(z) istdas reziproke Polynom des charakteristischen Polynoms der Rekursion, und der Zählerkodiert die Anfangsbedingungen.

2. Die ersten Koezienten reichen hin, eine Rekursion 3. Ordnung zu erraten, die den ge-gebenen Daten oenbar genügen. Durch Aufruf von rational_reconstruct bekommenwir einen gebrochen rationalen Ausdruck, mit dem wir eine Reihe entwickeln können,in der alle gegebenen Koezienten wiederzunden sind sowie die wahrscheinlich dannfolgenden:

sage: p = previous_prime(2^30); ZpZx.<x> = Integers(p)[]sage: s = ZpZx([1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339])sage: num, den = s.rational_reconstruct(x^12, 6, 6)sage: S = ZpZx.completion(x)420sage: map(lift_sym, S(num)/S(den))[1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339, 3056, 371,14602, -4257, 72268, -50489, 369854, -396981]

(Die Funktion lift_sym wurde in Kapitel 7 deniert. Die ersten 20 Koezienten liegenweit unter 229, sodass wir die Rekursion modulo 230 entwickeln dürfen, nachdem wirdas Ergebnis in Z erstellt haben.)

Mit berlekamp_massey ist das Ergebnis das charakteristische Polynom der Rekursiondirekt mit Koezienten in Z:

sage: berlekamp_massey([1, 1, 2, 3, 8, 11, 34, 39, 148, 127])x^3 - 5*x + 2

Wir verizieren, dass alle gegebenen Koezienten der Gleichung un+3 = 5un+1 − 2ungenügen, und davon ausgehend erraten wir die fehlenden Koezienten 72268 = 5 ·14602− 2 · 371.− 50489 = 5 · (−4257)− 2 · 14602 und so weiter.

Übung 28 Seite 146. Wir beginnen mit der Berechnung eines Polynoms 3. Grades, dass diegegebene Interpolationsbedingung erfüllt. Das ergibt eine Lösung mit deg p = 3:

sage: R.<x> = GF(17)[]sage: pairs = [(0,-1), (1,0), (2,7), (3,5)]sage: s = R(QQ['x'].lagrange_polynomial(pairs)); s6*x^3 + 2*x^2 + 10*x + 16sage: [s(i) for i in range(4)][16, 0, 7, 5]

408

Page 425: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.8. Lineare Algebra

Wir werden damit wieder auf das Problem der rationalen Rekonstruktion verwiesen

p/q ≡ s mod x(x− 1)(x− 2)(x− 3).

Da s nicht invertierbar modulo x(x−1)(x−2)(x−3) ist (denn s(1) = 0), gibt es für konstantesp keine Lösung. Mit deg p = 1 nden wir:

sage: s.rational_reconstruct(mul(x-i for i in range(4)), 1, 2)(15*x + 2, x^2 + 11*x + 15)

Übung 29 Seite 150. Der Ablauf ist derselbe wie beim Beispiel im Text: wir codierendie Gleichung tanx =

∫ x0 (1 + tan2 t)dt und suchen ausgehend von der Anfangsbedingung

tan(0) = 0 einen Fixpunkt.

sage: S.<x> = PowerSeriesRing(QQ)sage: t = S(0)sage: for i in range(7): # hier ist t korrekt bis zum Grad 2i+1....: # O(x^15) vermeidet das Anwachsen der Abbruchordnung....: t = (1+t^2).integral() + O(x^15)sage: tx + 1/3*x^3 + 2/15*x^5 + 17/315*x^7 + 62/2835*x^9 + 1382/155925*x^11 +21844/6081075*x^13 + O(x^15)

A.8. Lineare Algebra

Übung 30 Seite 170. (Minimalpolynom von Vektoren)

1. ϕA ist ein Annihilator-Polynom aller Basisvektoren ei. Es ist deshalb ein gemeinsamesVielfaches von ϕA,ei . Sei ψ das kgV von ϕA,ei . Dann gilt ψ | ϕA. Auÿderdem ist ψ(A) =[ψ(A)e1 · . . . · ψ(A)en] = 0 Annihilator der Matrix A. Daraus folgt ϕA | ψ. Da diePolynome unitär sind, sind sie gleich.

2. In diesem Fall haben alle ϕA,ei die Form χli , wobei χ ein irreduzibles Polynom ist.Gemäÿ der vorigen Frage fällt ϕA mit dem der χli zusammen und hat den maximalenExponenten li.

3. Sei ϕ ein Annihilator-Polynom von e = ei + ej und ϕ1 = ϕA,ei und ϕ2 = ϕA,ej . Wirhaben ϕ2(A)ϕA,ei = ϕ2(A)ϕ(A)e − ϕ(A)ϕ2(A)ej = 0. Daher ist ϕ2ϕ Annihilator vonei und somit teilbar durch ϕ1. Da nun ϕ1 und ϕ2 teilerfremd sind, gilt ϕ1 | ϕ. Genausobeweist man ϕ2 | ϕ, weshalb ϕ ein Vielfaches von ϕ1ϕ2 ist. Nun ist ϕ1ϕ2 Annihilatorvon e, deshalb ist ϕ = ϕ1ϕ2.

4. Da P1 und P2 teilerfremd sind, existieren zwei Polynome α und β, sodass 1 = αP1+βP2.So haben wir x = α(A)P1(A)x + β(A)P2(A)x = x2 + x1 für jedes x, wobei x1 =β(A)P2(A)x ist und x2 = α(A)P1(A)x. Wegen ϕA = P1P2 ist P1 Annihilator vonx1 = β(A)P2(A)x (ebenso ist P2 Annihilator von x2). Ist x1 = 0 für jedes x, dann istβP2 Annihilator von A und ist somit ein Vielfaches von P1P2, woraus 1 = P1(α+ γP2)folgt, was degP1 = 0 impliziert. Es existiert daher ein x1 6= 0, sodass P1 ein Annihilator-Polynom von x1 ist. Zeigen wir, dass P1 für x1 minimal ist: sei P1 ein Annihilator-Polynom von x1. Dann ist P1(A)P2(A)x = P2(A)P1(A)x1 + 1(A)P2(A)x2 = 0, mithinist P1P2 ein Vielfaches von ϕA = P1P2. So gilt P1 | P1 und P1 ist das Minimalpolynomvon x1. Für x2 geht der Beweis genauso.

409

Page 426: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

5. Zu jedem Faktor ϕmii existiert ein Vektor xi. Dabei ist ϕmii das Minimalpolynom und

der Vektor x1 + . . .+ xk hat ϕA als Minimalpolynom.

6. Wir berechnen zunächst das Minimalpolynom der Matrix A.

sage: A = matrix(GF(7),[[0,0,3,0,0],[1,0,6,0,0],[0,1,5,0,0],....: [0,0,0,0,5],[0,0,0,1,5]])sage: P = A.minpoly(); Px^5 + 4*x^4 + 3*x^2 + 3*x + 1sage: P.factor()(x^2 + 2*x + 2) * (x^3 + 2*x^2 + x + 4)

Es ist vom höchsten Grad.

sage: e1 = identity_matrix(GF(7),5)[0]sage: e4 = identity_matrix(GF(7),5)[3]sage: A.transpose().maxspin(e1)[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0), (0, 0, 1, 0, 0)]sage: A.transpose().maxspin(e4)[(0, 0, 0, 1, 0), (0, 0, 0, 0, 1)]sage: A.transpose().maxspin(e1 + e4)[(1, 0, 0, 1, 0), (0, 1, 0, 0, 1), (0, 0, 1, 5, 5),(3, 6, 5, 4, 2), (1, 5, 3, 3, 0)]

Die Funktion maxspin iteriert einen Vektor von links. Wir wenden sie deshalb auf dieTransponierte von A an, um ausgehend von den Vektoren e1 und e4 die Liste der linearunabhängigen Krylow-Iterierten zu bekommen. Das Minimalpolynom von e1 hat daherden Grad 3, das von e4 den Grad 2 und das von e1 + e4 den Grad 5.

Wir sehen, dass die spezielle Gestalt der Matrix die Vektoren e1 und e4 wie Iterier-te anderer Vektoren der kanonischen Basis wirken lässt, Diese Form heiÿt Frobenius-Normalform (siehe Unterabschnitt 8.2.3). Sie beschreibt, wie die Matrix den Vektorraumin zyklische invariante unterräume zerlegt, die von den Vektoren der kanonischen Basiserzeugt werden.

Übung 31 Seite 177.

sage: def sind_aehnlich(A, B):....: F1, U1 = A.frobenius(2)....: F2, U2 = B.frobenius(2)....: if F1 == F2:....: return True, ~U2*U1....: else:....: return False, F1 - F2sage: B = matrix(ZZ, [[0,1,4,0,4],[4,-2,0,-4,-2],[0,0,0,2,1],....: [-4,2,2,0,-1],[-4,-2,1,2,0]])sage: U = matrix(ZZ, [[3,3,-9,-14,40],[-1,-2,4,2,1],[2,4,-7,-1,-13],....: [-1,0,1,4,-15],[-4,-13,26,8,30]])sage: A = (U^-1 * B * U).change_ring(ZZ)sage: ok, V = sind_aehnlich(A, B); okTruesage: V[ 1 2824643/1601680 -6818729/1601680

410

Page 427: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.9. Polynomiale Systeme

-43439399/11211760 73108601/11211760][ 0 342591/320336 -695773/320336-2360063/11211760 -10291875/2242352][ 0 -367393/640672 673091/640672-888723/4484704 15889341/4484704][ 0 661457/3203360 -565971/320336013485411/22423520 -69159661/22423520][ 0 -4846439/3203360 7915157/3203360-32420037/22423520 285914347/22423520]sage: ok, V = sind_aehnlich(2*A, B); okFalse

A.9. Polynomiale Systeme

Übung 32 Seite 180. Zu einem gegebenen Polynomring ring gibt die Funktion test_polydie Summe aller Monome des gesamten Grades zurück, der durch den Wert des Parametersdeg begrenzt ist. Der Code ist relativ kompakt, arbeitetet jedoch mit einigen Verrenkungen.

Die erste Anweisung erzeugt eine Menge (dargestellt durch ein spezisches Objekt SubMultiset,siehe Abschnitt 15.2) von Listen zu jedem deg und weist sie der lokalen Variablen monomialszu, mit Elementen, deren Produkt einen Term des Polynoms bildet:

sage: ring = QQ['x,y,z']; deg = 2sage: tmp1 = [(x,)*deg for x in (1,) + ring.gens()]; tmp1[(1, 1), (x, x), (y, y), (z, z)]sage: tmp2 = flatten(tmp1); tmp2[1, 1, x, x, y, y, z, z]sage: monomials = Subsets(tmp2, deg, submultiset=True); monomialsSubMultiset of [y, y, 1, 1, z, z, x, x] of size 2sage: monomials.list()[[y, y] , [y, 1] , [y, z] , [y, x] , [1, 1] , [1, z] , [1, x] , [z, z] , [z, x] , [x, x]]

Dafür beginnen damit, dem Tupel der Unbestimmten 1 hinzuzufügen und jedes Element desErgebnisses durch ein Tupel von deg Kopien von sich selbst zu ersetzen und dan diese Tu-pel in einer Liste zu gruppieren. Wir bemerken die Verwendung von (1,). das ein Tupelmit nur einem Element bezeichnet sowie Operatoren für die Verkettung und für die Wie-derholung *. Die erhalten Liste der Tupel wird durch flatten zu einer Liste gemacht, diejede Unbestimmte und die Konstante 1 genau deg mal enthält. Die Funktion Subsets mitder Option submultiset=True berechnet sodann die Menge der Teilmengen der Gröÿe degder Multimenge (eine Kollektion ohne Ordnung aber mit Wiederholung) der Elemente dieserListe. Das Objekt monomials ist iterierbar: so ist (mul(m) for m in monomials) ein Python-Generator, der die Monome durchläuft, die beim Durchgehen der Listen mit mul entstandensind und die Teilmengen darstellt. Dieser Generator wird schlieÿlich add übergeben.

Die letzte Zeile könnte durch add(map(mul, monomials)) ersetzt werden. Wir könnten auch((1,) + ring.gens())*deg schreiben, um den Ausdruck [(x,)*deg for x in (1,) +ring.gens()] zu vereinfachen.

Übung 33 Seite 181. Ein Beispiel von der Hilfeseite PolynomialRing? schlägt eine Lösungvor: um eine Familie von komplizierten Unbestimmten zu erhalten - hier durch Primzahlen

411

Page 428: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

indiziert - übergibt man PolynomialRing eine mit einer Raung erzeugte Liste (siehe Unter-abschnitt 3.3.2):

sage: ['x%d' % n for n in [2,3,5,7]]['x2', 'x3', 'x5', 'x7']sage: R = PolynomialRing(QQ, ['x%d' % n for n in primes(40)])sage: R.inject_variables()Defining x2, x3, x5, x7, x11, x13, x17, x19, x23, x29, x31, x37

Die Methode inject_variables initialisiert die Python-Variablen x2,x3,..., die jeweils denentsprechenden Generator von R enthalten.

Übung 34 Seite 186. Wir verizieren, dass (3, 2, 1) die einzige Lösung ist, beispielsweisemit

sage: R.<x,y,z> = QQ[]sage: J = R.ideal(x^2*y*z-18, x*y^3*z-24, x*y*z^4-6)sage: J.variety(AA)[x: 3, z: 1, y: 2]

oder auch

sage: V = J.variety(QQbar)sage: [u for u in V if all(a in AA for a in u.values())][z: 1, y: 2, x: 3]

Eine Substitution der Forn (x, y, z) 7→ (ωax, ωby, ωcz) mit ωk = 1 lässt das System genaudann unverändert, wenn (a, b, c) Lösung modulo k des linearen homogenen Systems dieserMatrix ist:

sage: M = matrix([ [p.degree(v) for v in (x,y,z)]....: for p in J.gens()]); M[2 1 1][1 3 1][1 1 4]

Nach Berechnung ihrer Determinante

sage: M.det()17

sieht man, dass K = 17 passt. Wir müssen nur noch ein von null verschiedenes Element desKerns nden:

sage: M.change_ring(GF(17)).right_kernel()Vector space of degree 3 and dimension 1 over Finite Field of size 17Basis matrix:[1 9 6]

Übung 35 Seite 199. Das ist beinahe sofort:

sage: L.<a> = QQ[sqrt(2-sqrt(3))]; LNumber Field in a with defining polynomial x^4 - 4*x^2 + 1sage: R.<x,y> = QQ[]sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*R

412

Page 429: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.9. Polynomiale Systeme

sage: J1.variety(L)[y: 1/2*a, x: 1/2*a^3 - 2*a,y: 1/2*a, x: -1/2*a^3 + 2*a,y: -1/2*a, x: 1/2*a^3 - 2*a,y: -1/2*a, x: -1/2*a^3 + 2*a,y: 1/2*a^3 - 2*a, x: 1/2*a,y: 1/2*a^3 - 2*a, x: -1/2*a,y: -1/2*a^3 + 2*a, x: 1/2*a,y: -1/2*a^3 + 2*a, x: -1/2*a]

Somit haben wir beispielsweise für die erste Lösung oben

x =1

2(2−

√3)3/2 − 2

√2−√

3, y =1

2

√2−√

3.

Übung 36 Seite 202. Wir haben gesehen, wie man eine Basis des Q-Vektorraums Q[x, y]/J2

erhält:

sage: R.<x,y> = QQ[]; J2 = (x^2+y^2-1, 4*x^2*y^2-1)*Rsage: basis = J2.normal_basis(); basisx[x*y^3, y^3, x*y^2, y^2, x*y, y, x, 1]

Wir berechnen dann das Bild von B unter mx und leiten daraus die Matrix von mx in derBasis B her:

sage: xbasis = [(x*p).reduce(J2) for p in basis]; xbasis[1/4*y, x*y^3, 1/4, x*y^2, -y^3 + y, x*y, -y^2 + 1, x]sage: mat = matrix([ [xp[q] for q in basis] for xp in xbasis])sage: mat[ 0 0 0 0 0 1/4 0 0][ 1 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 1/4][ 0 0 1 0 0 0 0 0][ 0 -1 0 0 0 1 0 0][ 0 0 0 0 1 0 0 0][ 0 0 0 -1 0 0 0 1][ 0 0 0 0 0 0 1 0]

Das Polynom χx und seine Wurzeln sind dann dann gegeben (siehe Kapitel 2 und 8) durch

sage: charpoly = mat.characteristic_polynomial(); charpolyx^8 - 2*x^6 + 3/2*x^4 - 1/2*x^2 + 1/16sage: solve(SR(charpoly), SR(x))[x == -1/2*sqrt(2), x == 1/2*sqrt(2)]

An diesem Beispiel kann man sehen, dass die Wurzeln von χ die Abszissen der Punkte vonV (J2) sind.

Für ein beliebiges Hauptideal J setzen wir χ(λ) = 0 voraus mit λ ∈ C. Daher ist λ einEigenwert von mx. Sei p ∈ Q[x, y]\J Repräsentant eines λ zugeordneten Eigenvektors: wirhaben xp = λp + q für ein q ∈ J . Wegen p /∈ J können wir (x0, y0) ∈ V (J) nden, sodassp(x0, y0) 6= 0 ist und haben dann

(x0 − λ)p(x0, y0) = q(x0, y0) = 0,

413

Page 430: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

woraus λ = x0 folgt.

Übung 37 Seite 211. Die Ausdrücke sin, cos, sin(2θ) und cos(2θ) sind verknüpft durch dieklassischen geometrischen Formeln

sin2 θ + cos2 θ = 1, sin(2θ) = 2(sin θ)(cos θ), cos(2θ) = cos2 θ − sin2 θ.

Zur Vereinfachung der Schreibweise setzen wir c = cos θ und s = sin θ. Das Hauptideal

〈u− (s+ c), v − (2sc+ c2 − s2), s2 + c2 − 1〉

von Q[s, c, u, v] bringt die Denitionen von u(θ) und v(θ) der Aufgabe sowie die Beziehungzwischen sin und cos zum Ausdruck. Für eine Anordnung der Monome, die vorrangig s und centfernt, gibt die kanonische Form von s6 modulo dieses Hauptideals das gesuchte Ergebnis.

sage: R.<s, c, u, v> = PolynomialRing(QQ, order='lex')sage: Rel = ideal(u-(s+c), v-(2*s*c+c^2-s^2), s^2+c^2-1)sage: Rel.reduce(s^6)1/16*u^2*v^2 - 3/8*u^2*v + 7/16*u^2 + 1/8*v^2 - 1/8*v - 1/8

A.10. Dierentialgleichungen und rekursiv denierte Folgen

Übung 38 Seite 222. (Dierentialgleichungen mit trennbaren Variablen)

1. Wir wenden dieselbe Methode an wie in Unterabschnitt 10.2.1:

sage: x = var('x')sage: y = function('y')(x)sage: ed = (desolve(y*diff(y,x)/sqrt(1+y^2) == sin(x),y)); edsqrt(y(x)^2 + 1) == _C - cos(x)

Da taucht das gleiche Problem auf: Wir legen fest, dass _C-cos(x) positiv ist:

sage: _C = ed.variables()[0]sage: assume(_C-cos(x) > 0)sage: sol = solve(ed,y); sol[y(x) == -sqrt(_C^2 - 2*_C*cos(x) + cos(x)^2 - 1),y(x) == sqrt(_C^2 - 2*_C*cos(x) + cos(x)^2 - 1)]

sage: P = Graphics()sage: for j in [0,1]:....: for k in range(0,20,2):

: P += plot(sol[j].subs(_C == 2+0.25*k).rhs(), x,-3,3)sage: P

414

Page 431: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.10. Dierentialgleichungen und rekursiv denierte Folgen

2. Dasselbe Verfahren:

sage: solu = desolve(diff(y,x) == sin(x)/cos(y),y, show_method = True)sage: solu[sin(y(x)) == _C - cos(x), 'separable']sage: solve(solu[0],y)[y(x) == arcsin(_C - cos(x))]

Übung 39 Seite 223. (Homogene Gleichungen) Wir verizieren, dasss die auf ]0,+∞[ undauf ]−∞, 0[ denierte Gleichung xyy′ = x2 + y2 bestimmt homogen ist. Dann versuchen wir,sie durch Veränderung einer unbekannten Funktion zu lösen, wie das im Unterabschnitt 10.1.2im Beispiel gezeigtworden ist.

sage: x = var('x')sage: y = function('y')(x)sage: id(x) = xsage: u = function('u')(x)sage: d = diff(u*id,x)sage: DE = (x*y*d == x**2+y**2).subs(y == u*id)sage: equ = desolve(DE,u)sage: solu = solve(equ,u)sage: solu[u(x) == -sqrt(2*_C + 2*log(x)), u(x) == sqrt(2*_C + 2*log(x))]|sage: Y = [x*solu[0].rhs() , x*solu[1].rhs()]sage: Y[0]-sqrt(2*_C + 2*log(x))*x

415

Page 432: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Wir könen für x Bedingungen hinzufügen (mit assume), um in Erinnerung zu rufen, dass dieGleichung für x = 0 nicht deniert ist.

A.11. Flieÿpunktzahlen

Übung 40 Seite 241. Wir schlagen zwei Lösungen vor.

1. Wir führen die Rechnung ohne die Methoden der Klasse RealField aus, welche Mantiiseund Exponent einer Zahl ausgeben. Wir verizieren zunächst 299 < 1030 < 2100 (1030 =(103)10 ≈ (210)10).

sage: R100=RealField(100)sage: x=R100(10^30)sage: x>2^99Truesage: x<2^100True

Wir berechnen dann die Mantisse von x:

sage: e = 2^100sage: s1 = 10^30sage: mantisse = []sage: anzziff = 0 # Zähler der notwendiger Ziffernsage: while s1 > 0:....: e /= 2....: if e <= s1:....: mantisse.append(1)....: s1 -= e....: else:....: mantisse.append(0)....: anzziff += 1sageprint mantisse[1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0,1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1,1, 1, 1, 0, 1, 0, 1, 0, 0, 1]

sage: print "Anzahl der notwendigen Ziffern ", anzziffAnzahl der notwendigen Ziffern 70

Die binären Ziern der Mantisse sind oberhalb der siebzigsten gleich null. Die zu 1030

nächstgelegene Zahl bekommt man daher durch Addition von 2−100 zur Mantisse, woraussich als Resultat für x.ulp() der Wert 2−100 · 2100 = 1 ergibt.

2. Mit der Methode sign_mantissa_exponent() der Klasse RealField erhalten wir un-mittelbar

sage: R100=RealField(100)sage: x=R100(10^30)sage: s,m,e = x.sign_mantissa_exponent()

416

Page 433: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.11. Flieÿpunktzahlen

sage: print s,m,e1 1000000000000000000000000000000 0

Der Befehl m.binary() erlaubt die Feststellung, dass wir in beiden Fällen die gleiche Mantisseerhalten.

Übung 41 Seite 244.

1. Wir suchen zunächst die Werte von α, β und γ in der Gleichung

un =α100n+1 + β6n+1 + γ5n+1

α100n + β6n + γ5n. (A.1)

Warum machen wir das nicht mit Sage? Wir bedienen uns der Werte u0, u1 und u2, umein Gleichungssystem zu bekommen und zu lösen, dessen Unbekannte α, β und γ sind.Wir formulieren die rekursiv denierte Folge und denieren die allgemeine Lösung:

sage: var("u0 u1 u2 alpha beta gamma n")(u0, u1, u2, alpha, beta, gamma, n)sage: recurrence = lambda a,b: 111-1130/a+3000/(a*b)sage: gener1 = lambda n :(alpha*100^n+beta*6^n+gamma*5^n)sage: solGen = lambda n: gener1(n+1)/gener1(n)

Wir berechnen u2 als Funktion von u1 und u0 und stellen das System auf:

sage: u2 = recurrence(u1,u0)sage: s = [u2==solGen(2),u1==solGen(1),u0==solGen(0)]sage: t = [s[i].substitute(u0=2,u1=-4) for i in range(0,3)]

Dann lösen wir es:

sage: solve(t,alpha,beta,gamma)[[alpha == 0, beta == -3/4*r1, gamma == r1]]

Die Rechnung zeigt uns, dass γ unbestimmt bleibt.

Wir müssen noch verizieren, dass wir tatsächlich eine allgemeine Lösung erhalten, d.h.dass die Gleichung (A.1) für jedes n erfüllt ist.

sage: alpha=0sage: beta = -3/4*gammasage: final = solGen(n) - recurrence(solGen(n-1), solGen(n-2))sage: print final.simplify_full()0

Für γ können wir einen beliebigen Wert einsetzen, z.B. γ = 4, dann haben wir β = −3und α = 0.

2. Wir denieren eine Funktion für die rekursiv denierte Folge mit exakten Koezienten,damit wir sie mit unterschiedlichen Genauigkeiten verwenden können:

sage: def recur(x1,x0):....: return 111 - 1130/x1 + 3000/(x0*x1)

Die Anfangsbedingungen werden hingegen aus RealField() genommen, sodass dieRechnung auf dieser Denitionsmenge erfolgt.

417

Page 434: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: u0 = 2.sage: u1 = -4.sage: for i in range(1,25):....: x = recur(u1,u0)....: print i,x....: u0 = u1....: u1 = x 1 18.50000000000002 9.378378378378383 7.801152737752174 7.154414480975335 6.806784736924816 6.59263276872179..................23 99.999998659216724 99.9999999193218

Oensichtlich konvergiert die Folge gegen 100.

3. Für die Erklärung des Verhaltens ist wichtig, dass die Werte un nicht exakt berechnetwerden: wenn die Folge mit Anfangsbedingungen un−1 und un−2 deniert würde, diemit einem Rundungsfehler behaftet wären, dann lieferte die Gleichung keine allgemeineLösung mehr.

Suchen wir nun die stationären Werte der Folge:

sage: var("x")xsage: solve(x==recurrence(x,x),x)[x == 100, x == 5, x == 6]

Es gibt drei stationäre Werte: 100, 5 und 6. Die Konvergenz gegen 100, die bei Anwe-senheit von Rundungsfehlern beobachtet wird, veranlasst Überlegungen zur Stabilitätdieser drei Werte (Überlegungen, die jenseits der Grenzen dieser Übung angesiedeltsind).

4. Die Erhöhung der Genauigkeit bringt nichts, die Folge konvergiert immer gegen 100:

sage: RL = RealField(5000)sage: u0 = RL(2)sage: u1 = RL(-4)sage: for i in range(1,2500):....: x = recur(u1,u0)....: u0 = u1....: u1= xsage: x100.00000000000000000000000000000000000000000000000000000...

Es genügt, dass ein einziges ui nicht exakt berechnet wird, damit die Folge divergiert(α ist nicht mehr null).

5. Das Programm erfährt nur geringfügige Änderungen. Wir lassen die Variablen u0 undu1 ganzzahlig initialisieren:

418

Page 435: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.12. Nichtlineare Gleichungen

sage: u0 = 2sage: u1 = -4sage: for i in range(1,2500):....: x = recur(u1,u0)....: u0 = u1....: u1 = xsage: float(x)6.0

Wir nden wirklich den Wert 6.0, doch wenn wir die rationale Zahl x ausgeben, sehen wirdie enorme Menge an Information, die für die Berechnung benötigt wird (die Ausgabewird hier nicht wiedergegeben!). Bei Ausgabe von x−6 erkennt man, dass der Grenzwertnicht verändert worden ist: die Gröÿe der rechnerinternen Darstellung von x wird nichtkleiner, wenn wir die Iterationen fortsetzen.

A.12. Nichtlineare Gleichungen

Übung 42 Seite 263. Wir haben gesehen, dass das Schlüsselwort return die Ausführungder Funktion beendet. Es reicht deshalb aus zu testen, ob f(0) null ist oder nicht. Um diemehrmalige Auswertung der Funktion f an der Stelle u zu vermeiden, speichern wir ihrenWert in einer Variablen. Mit dieser Änderung bekommen wir die folgende Funktion:

sage: def intervalgen(f, phi, s, t):....: assert (f(s) * f(t) < 0), \....: 'Wrong arguments: f(%s) * f(%s) >= 0)'%(s, t)....: yield s....: yield t....: while 1:....: u = phi(s, t)....: yield u....: fu = f(u)....: if fu == 0:....: return....: if fu * f(s) < 0:....: t = u....: else:....: s = u

Testen wir diese Funktion mit einer Gleichung, deren Lösung wir kennen, beispielsweise miteiner linearen Funktion.

sage: f(x) = 4 * x - 1sage: a, b = 0, 1sage: phi(s, t) = (s + t) / 2sage: list(intervalgen(f, phi, a, b))[0, 1, 1/2, 1/4]

Übung 43 Seite 263. Die intervalgen als Parameter übergebene Funktion phi bestimmtdie Stelle, an der ein Intervall geteilt werden soll. Wir müssen dieser Funktion also nur diepassende Denition übergeben.

419

Page 436: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: f(x) = 4 * sin(x) - exp(x) / 2 + 1sage: a, b = RR(-pi), RR(pi)sage: def phi(s, t): return RR.random_element(s, t)sage: random = intervalgen(f, phi, a, b)sage: iterate(random, maxit=10000)After 22 iterations: 2.15844376542606

Übung 44 Seite 271. Es bietet sich an, die Rechnungen mit PolynomialRing(SR, 'x') aus-zuführen. Es gibt jedoch eine technische Schwierigkeit: dieses Objekt nicht über die Methoderoors().

sage: basering.<x> = PolynomialRing(SR, 'x')sage: p = x^2 + xsage: p.parent()Univariate Polynomial Ring in x over Symbolic Ringsage: p.roots(multiplicities=False)Traceback (most recent call last):...NotImplementedError

Achtung: Hier wird noch eine Änderung erfolgen, denn inzwischen ist Sage in der Lage, einErgebnis zu liefern: [−1, 0].

Die Funktion solve ist nicht mehr eine Zusammenarbeit mit den Objekt PolynomialRing(SR, 'x').Eine Alternative besteht in der Verwendung von SR, das diese Methode implementiert, dochbietet sie kein Äquivalent für die Methode lagrange_polynomial() von PolynomialRing(SR, 'x').Daher werden wir zwischen diesen Objekten hin und her wechseln.

sage: from collections import dequesage: basering = PolynomialRing(SR, 'x')sage: q, method = None, Nonesage: def quadraticgen(f, r, s):....: global q, method....: t = r - f(r) / f.derivative()(r)....: method = 'newton'....: yield t....: pts = deque([(p, f(p)) for p in (r, s, t)], maxlen=3)....: while True:....: q = basering.lagrange_polynomial(pts)....: p = sum([c*x^d for d, c in enumerate(q.list())])....: roots = [r for r in p.roots(x,multiplicities=False) \....: if CC(r).is_real()]....: approx = None....: for root in roots:....: if (root - pts[2][0]) * (root - pts[1][0]) < 0:....: approx = root....: break....: elif (root - pts[0][0]) * (root - pts[1][0]) < 0:....: pts.pop()....: approx = root....: break....: if approx:

420

Page 437: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.13. Numerische lineare Algebra

....: method = 'quadratic'

....: else:

....: method = 'dichotomy'

....: approx = (pts[1][0] + pts[2][0]) / 2

....: pts.append((approx, f(approx)))

....: yield pts[2][0]

Jetzt ist es möglich, die ersten Terme der mit dem Verfahren von Brent rekursiv deniertenFolge auszugeben. Aber Achtung: Die Rechnung ist ziemlich langwierig (und die Ausgabe desErgebnisses passt nicht auf eine Seite dieses Buches. . . ).

sage: basering = PolynomialRing(SR, 'x')sage: a, b = pi/2, pisage: f(x) = 4 * sin(x) - exp(x) / 2 + 1sage: generator = quadraticgen(f, a, b)sage: print generator.next()1/2*pi - (e^(1/2*pi) - 10)*e^(-1/2*pi)

Wärend der Ausführung des folgenden Codes wird der geduldige Leser die Parabelbögen sehenkönnen, die bei der Berechnung der ersten Terme der Folge verwendet werden.

sage: generator = quadraticgen(f, a, b)sage: g = plot(f, a, b, rgbcolor='blue')sage: g += point((a, 0), rgbcolor='red', legend_label='0')sage: g += point((b, 0), rgbcolor='red', legend_label='1')sage: data = '2': 'blue', '3': 'violet', '4': 'green'sage: for l, color in data.iteritems():....: u = RR(generator.next())....: print u, method....: g += point((u, 0), rgbcolor=color, legend_label=l)....: if method == 'quadratic':....: q = sum([c*x^d for d, c in enumerate(q.list())])....: g += plot(q, 0, 5, rgbcolor=color)2.64959209030252 newton2.17792417785930 quadratic2.15915701651408 quadraticsage: g.show()

A.13. Numerische lineare Algebra

Übung 45 Seite 279. Mit der Gleichung von Sherman und Morrison ist die Lösung vonBx = f äquivalent zu derjenigen von Ax = σ(I + utvA−1)f mit σ = (1 + tvA−1u)−1. Wirgehen dann folgendermaÿen vor.

1. Wir berechnen w als Lösung von Aw = u, dann σ = (1 +t vw)−1.

2. Wir berechnen z als Lösung von Az = f , dann g =t vz (das ist ein Skalar).

3. Wir berechnen dann h = σ(f − gu) und lösen Ax = h; x ist die Lösung von Bx = f .

421

Page 438: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Wir stellen fest, dass wir drei lineare Systeme mit der zerlegten Matrix A gelöst haben, sprichdie Lösung von sechs linearen Systemen mit Dreiecksmatrix. Jede dieser Lösungen erfordertOperationen der Ordnung n2, viel weniger als der Aufwand für eine Zerlegung (die von derOrdnung n3 ist). Um die Gleichung von Sherman und Morrison zu verizieren, müssen wir nurdas zweite Glied der Gleichung mit A+ utv (von rechts) multiplizieren und dann verizieren,dass dieser Ausdruck gleich der identischen Matrix ist.

Übung 46 Seite 283. Wir betrachten die Cholesky-Zerlegung von A = CtC, dann dieSingulärwertzerlegung von C: C = UΣtV . Dann ist X = UΣtU . In der Tat: A = CtC =(UΣtV )(V ΣtU) = USigmatUUSigmatU = X2.

Erstellen wir eine symmetrische positiv denite Zufallsmatrix:

sage: m = random_matrix(RDF,4)sage: a = transpose(m)*msage: c = a.cholesky()sage: U,S,V = c.SVD()sage: X = U*S*transpose(U)

Verizieren wir, dass X2 − a null ist (abgesehen von numerischen Fehlern):

sage: M = (X*X-a)sage: all(abs(M[i,j]) < 10^-14....: for i in range(4) for j in range(4))True

A.14. Numerische Integration und Dierentialgleichungen

Übung 47 Seite 308. (Berechnung der Koezienten von Newton-Cotes)

1. Wenn wir bemerken, dass Pi n− 1-ten Grades ist (worauf Gleichung (14.1) angewendetwird), und dass Pi(j) = 0 für j ∈ 0, . . . , n− 1 und j 6= i, leiten wir daraus her:

n−1∫0

Pi(x)dx = wiPi(i)

also

wi =

n−1∫0

Pi(x)dx

Pi(i).

2. Einfach folgt daraus die Berechnung der Gewichte:

sage: x = var('x')sage: def NCRule(n):....: P = prod([x - j for j in xrange(n)])....: return [integrate(P / (x-i), x, 0, n-1) \....: / (P/(x-i)).subs(x=i) for i in xrange(n)]

422

Page 439: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.14. Numerische Integration und Dierentialgleichungen

3. Durch einen simplen Variablentausch:

b∫a

f(x)dx =b− an− 1

n−1∫0

f

(a+

b− an− 1

)du.

4. Wir wenden vorstehende Gleichung an und nden wir das folgende Programm:

sage: def QuadNC(f, a, b, n):....: W = NCRule(n)....: ret = 0....: for i in xrange(n):....: ret += f(a + (b-a)/(n-1)*i) * W[i]....: return (b-a)/(n-1)*ret

Bevor wir die Genauigkeit dieses Verfahrens mit der von anderen vergleichen, könnenwir bereits verizieren, dass es keine inkohärenten Ergebnisse liefert:

sage: QuadNC(lambda u: 1, 0, 1, 12)1sage: N(QuadNC(sin, 0, pi, 10))1.99999989482634

Nun vergleichen wir das erhaltene Verfahren kurz mit den Funktionen von GSL anhandder Integrale I2 und I3:

sage: numerical_integral(x * log(1+x), 0, 1)(0.25, 2.7755575615628914e-15)sage: N(QuadNC(lambda x: x * log(1+x), 0, 1, 19))0.250000000000001sage: numerical_integral(sqrt(1-x^2), 0, 1)(0.7853981677264822, 9.042725224567119e-07)sage: N(pi/4)0.785398163397448sage: N(QuadNC(lambda x: sqrt(1-x^2), 0, 1, 20))0.784586419900198

Wir bemerken, dass die Güte des Ergebnisses von der Anzahl der verwendeten Punkteabhängt:

sage: [N(QuadNC(lambda x: x * log(1+x), 0, 1, n) - 1/4)....: for n in [2, 8, 16]][0.0965735902799726, 1.17408932921378e-7, 2.13476805677182e-13]sage: [N(QuadNC(lambda x: sqrt(1-x^2), 0, 1, n) - pi/4)....: for n in [2, 8, 16]][-0.285398163397448, -0.00524656673640445, -0.00125482109302663]

Ein interessanterer Vergleich zwischen den verschiedenen Integrationsfunktionen vonSage mit unserem Verfahren QuadNC würde die Umwandlung in ein adaptives Verfah-ren verlangen, welches das betrachtete Intervall wie numerical_integral automatischunterteilt.

423

Page 440: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

A.15. Aufzählende Kombinatorik

Übung 48 Seite 319. (Wahrscheinlichkeit, beim Poker einen Vierling zu ziehen) Wir bildendie Menge der Vierlinge:

sage: Farben = FiniteEnumeratedSet(["Karo","Herz","Pik","Kreuz"])sage: Werte = FiniteEnumeratedSet([2, 3, 4, 5, 6, 7, 8, 9, 10,

"Bube", "Dame", "Koenig", "Ass"])sage: Vierlinge = cartesian_product([(Arrangements(Werte,2)), Farben])

Wir haben FiniteEnumeratedSet benutzt statt Set, um die Reihenfolge der Farben, derWerte und damit auch der Vierlinge festzulegen.

sage: Vierlinge.list()[[[2, 3], 'Karo'],[[2, 3], 'Herz'],...[['Ass', 'Koenig'], 'Kreuz']]

Diese Liste beginnt mit einem Zweier-Vierling und der Karo 3 und endet mit einem Vierlingvon Assen und dem Kreuz König. Insgesamt gibt es 624 Vierlinge.

sage: Carres.cardinality()624

Bezogen auf die Anzahl möglicher Hände haben wir eine Chance von 1:4165, einen Vierlingzu bekommen wenn ein Blatt zufällig gezogen wird.

sage: Karten = cartesian_product([Farben, Werte]).map(tuple)sage: Haende = Subsets(Karten, 5)sage: Vierlinge.cardinality() / Haende.cardinality()1/4165

Übung 49 Seite 319. (Wahrscheinlichkeit, beim Poker einen Straight Flush oder einen Flush

zu ziehen) Einen Straight Flush einzuordnen läuft zum Beispiel darauf hinaus, seine kleinsteKarte zu bestimmen (zwischen 1 und 10) und seine Farbe. Davon gibt es demnach 40.

sage: StraightFlush = cartesian_product([srange(1, 11), Farben])sage: StraightFlush.cardinality()40

Und es gibt 5108 Flushes:

sage: AlleFlushes = cartesian_product([Subsets(Werte,5),Farben])sage: AlleFlushes.cardinality() - StraightFlush.cardinality()5108

Schlieÿlich ist die Wahrscheinlichkeit, zufällig einen Flush zu ziehen, etwa zwei Promille:

sage: _ / Mains.cardinality()1277/649740sage: float(_)0.0019654015452334776

424

Page 441: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.15. Aufzählende Kombinatorik

Es wäre schön, die vorstehende Rechnung mit Mengenoperationen durchzuführen, indem dieMenge der Flushes explizit als Dierenz von alleFlushes und StraightFlush gebildet wird.Indes gibt es keinen ezienten generischen Algorithmus zur Berechnung der Dierenz zweierMengen A\B: ohne zusätzliche Information gibt es kaum etwas Besseres als alle Elementevon A zu prüfen, ob sie in B enthalten sind. In obiger Rechnung haben wir die Tatsachebenutzt, das B in A enthalten ist, was Sage vorher nicht wissen kann. Ein weiteres, leicht zuumgehendes Hindernis ist, dass die Elemente von B und A auf die gleiche Weise repräsentiertwerden müssen.

Übung 50 Seite 319. Wir beschränken uns darauf den Fall eines Full House zu illustrie-ren, das aus einem Drilling und einem Paar besteht. Beginnen wir damit, eine Funktion zuschtreiben, die prüft, ob eine Hand ein Full House ist. Eine knappe Schreibweise erzielen wirmit dieser Methode:

sage: Word(['a','b','b','a','a','b','a']).evaluation_dict()'a': 4, 'b': 3

sage: def is_Full_House(Hand):....: Farben = Word([Wert for (Farbe, Werte) in Hand])....: Wiederholungen = sorted(Farben.evaluation_dict().values())....: return Wiederholungen == [2,3]sage: is_Full_House(('Karo', 5), ('Karo', 6), ('Herz', 6),....: ('Pique', 5), ('Pique', 1))Falsesage: is_Full_House(('Kreuz', 3), ('Pik', 3), ('Herz', 3),....: ('Kreuz', 2), ('Pik', 2))True

Wir automatisieren jetzt die Abschätzung des Anteils von Full Houses. Allgemeiner, die fol-gende Funktion schätzt den Anteile jedes Elements der endlichen Menge menge, das einempraedikat genügt. Sie geht davon aus, dass die Menge mit einer Methode random_elementversehen ist, die gleichverteiltes Ziehen implementiert:

sage: def schaetzung_anteil(menge, praedikat, n):....: zaehler = 0....: for i in range(n):....: if praedikat(menge.random_element()):....: zaehler += 1....: return zaehler/nsage: float(schaetzung_anteil(Haende, is_Full_House, 10000))0.0009

Kommen wir jetzt zur symbolischen Rechnung. Ein Full House zu bestimmen heiÿt, zweiverschiedene Farben anzugeben, die eine für den Drilling, die andere für das Paar, sowie eineMenge von drei Werten für den Drilling und eine andere mit zwei Werten für das Paar:

sage: Full_Houses = cartesian_product([Arrangements(Valeurs, 2),....: Subsets(Symboles, 3), Subsets(Symboles, 2)])

Hier beispielsweise ein Full House mit einem Drilling von Zweien und einem Paar von Drei-en:

425

Page 442: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: Full_Houses.first()[[2, 3], 'Kreuz', 'Pik', 'Karo', 'Pik', 'Kreuz']

Die Wahrscheinlichkeit für ein Full House ist dann:

sage: float(MainsPleines.cardinality() / Mains.cardinality())0.0014405762304921968

Übung 51 Seite 320. (Berechnung der vollständigen Binärbäume von Hand) Es gibt einenvollständigen Binärbaum mit einem Blatt und einen mit zwei Blättern. Für n = 3, 4 und 5Blätter ndet man 2, 5 bzw. 14 Bäume (wegen n = 4 siehe Abbildung 15.1)

Übung 52 Seite 329. Die Kompositionen von n über k Teilen sind in Bijektion mit denTeilmengen der Gröÿe k von 1, . . . , n: der Menge i1, . . . , ik mit i1 < i2 < . . . < ik ordnenwir die Komposition (i1, i2 − i1, . . . , n.ik) zu und umgekehrt. Daraus leiten sich die Formelnfür das Abzählen ab: es gibt 2n Kompositionen von n. Davon sind binomnk Kompositionenmit k Teilen. Um herauszunden, ob diese Gleichungen verwendet werden, können wir unsdie Implementierung der Methode cardinality anschauen

sage: C = Compositions(5)sage: C.cardinality??

Im zweiten Fall liefert schon der Name der intern verwendeten Methode, _cardinality_from_iterator, die Information: die Kardinalität wird - inezient - durch Iteration über alleKompositionen berechnet.

sage: C = Compositions(5,length=3)sage: C.cardinality<bound method IntegerListsLex...._cardinality_from_iterator ...>

Übung 53 Seite 332. Einige Beispiele:

sage: IntegerVectors(5,3).list()[[5, 0, 0], [4, 1, 0], [4, 0, 1], [3, 2, 0], [3, 1, 1], [3, 0, 2],...[0, 4, 1], [0, 3, 2], [0, 2, 3], [0, 1, 4], [0, 0, 5]]

sage: OrderedSetPartitions(3).cardinality()13sage: OrderedSetPartitions(3).list()[[1, 2, 3], [1, 3, 2], [2, 1, 3], [3, 1, 2],...[1, 2, 3], [1, 3, 2], [2, 3, 1], [1, 2, 3]]sage: OrderedSetPartitions(3,2).random_element()[1, 3, 2]

sage: StandardTableaux([3,2]).cardinality()5sage: StandardTableaux([3,2]).an_element()[[1, 3, 5], [2, 4]]

Übung 54 Seite 332. Im Kleinen bekommen wir diese Permutationsmatrizen:

426

Page 443: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.15. Aufzählende Kombinatorik

sage: list(AlternatingSignMatrices(1))[[1]]sage: list(AlternatingSignMatrices(2))[[1 0] [0 1][0 1], [1 0]]

Das erste neue Element erscheint bei n = 3:

sage: list(AlternatingSignMatrices(3))[[1 0 0] [0 1 0] [1 0 0] [ 0 1 0] [0 0 1] [0 1 0] [0 0 1][0 1 0] [1 0 0] [0 0 1] [ 1 -1 1] [1 0 0] [0 0 1] [0 1 0][0 0 1], [0 0 1], [0 1 0], [ 0 1 0], [0 1 0], [1 0 0], [1 0 0]]

Bei Betrachtung der Beispiele mit gröÿerem n können wir sehen, dass es sich immer umMatrizen handelt mit Koezienten aus −1, 0, 1, sodass in jeder Zeile und jeder Spalte dievon null verschiedenen Koezienten zwischen −1 und 1 alternieren, wobei sie mit 1 beginnenund mit 1 enden.

Übung 55 Seite 332. Es gibt 25 Vektoren in (Z/2Z)5:

sage: GF(2)^5Vector space of dimension 5 over Finite Field of size 2sage: _.cardinality()32

Um eine invertierbare 3× 3-Matrix mit Koezienten aus Z/2Z zu bilden, reicht es hin, einenersten von null verschiedenen Zeilenvektor (aus 23 − 1) auszuwählen, dann einen zweitenVektor (aus 23 − 2), der nicht in der vom ersten aufgespannten Geraden liegt, dann einendritten Zeilenvektor (aus 23−3), der nicht in der von den ersten beiden aufgespannten Ebeneliegt. Das macht

sage: (2^3-2^0)*(2^3-2)*(2^3-2^2)168

Und wirklich:

sage: GL(3,2)General Linear Group of degree 3 over Finite Field of size 2sage: _.cardinality()168

Dieselbe Überlegung führt auf die allgemeine Formel, die mittels q_factorial ausgedrücktwird:

n−1∏k=0

(qn − qk) =qn

(q − 1)n[n]q!

Also:

sage: from sage.combinat.q_analogues import q_factorialsage: q = 2; n = 3

427

Page 444: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

sage: q^n/(q-1)^n *q_factorial(n,q)168

Übung 56 Seite 335. Im ersten Fall beginnt Python mit der Konstruktion der Liste allerErgebnisse, bevor sie an all übergen wird. Im zweiten Fall übergibt der Iterator die Ergebnissean all nach und nach; letztere kann deshalb terminieren, sobald ein Gegenbeispiel gefundenwird.

Übung 57 Seite 336. Die erste Zeile ergibt die Liste aller Kuben der ganzen Zahlen zwischen−999 und 999 einschlieÿlich. Die beiden folgenden suchen nach einem Paar von Kuben, derenSumme gleich 218 ist. Die letzte Zeile ist ezienter in der Zeit, denn sie terminiert, sobaldeine Lösung gefunden wird:

sage: cubes = [t**3 for t in range(-999,1000)]sage: %time exists([(x,y) for x in cubes for y in cubes],....: lambda (x,y): x+y == 218)CPU times: user 1.28 s, sys: 0.07 s, total: 1.35 sWall time: 1.35 s(True, (-125, 343))sage: %time exists(((x,y) for x in cubes for y in cubes),....: lambda (x,y): x+y == 218)CPU times: user 0.88 s, sys: 0.02 s, total: 0.90 sWall time: 0.86 s(True, (-125, 343))

Vor allem ist sie ezienter beim Speicherbedarf: wenn n die Länge der Liste der Kuben ist,ist die Gröÿe des benutzten Speichers von der Gröÿenordnung n statt n2. Das wird besondersdann spürbar, wenn wir n verzehnfachen.

Übung 58 Seite 336.

- Berechne die erzeugende Reihe∑

s⊂S x|s| aller Teilmengen von 1, . . . , 8 als Funktion ihrer

Kardinalität.

- Berechne die erzeugende Reihe der Permutationen von 1, 2, 3 als Funktion der Anzahlihrer Inversionen.

- Veriziere die Tautologie ∀x ∈ P, x ∈ P für die Menge P der Permutationen von 1, 2, 3, 4, 5.Das ist ein guter Test für den inneren Zusammenhang der Iterationsfunktionen und für dieZugehörigkeit zur selben Menge. Er ist zudem in den generischen Test von Sage enthalten;siehe:

sage: P = Partitions(5)sage: P._test_enumerated_set_contains??

Die Tautologie ∀x /∈ P, x /∈ P wäre gut geeignet. den Test auf Zugehörigkeit zu kom-plettieren. Allerdings müsste die Grundmenge präzisiert werden; und vor allem bräuchte eseinen Iterator auf dem Komplement von P in dieser Grundmenge, was keine gewöhnlicheOperation ist.

- Gib alle auf Z/2Z invertierbaren 2× 2-Matrizen aus.

- Gib alle Partitionen von 3 aus.

- Gib alle Partitionen der ganzen Zahlen (terminiert nicht!).

428

Page 445: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.16. Graphentheorie

- Gib alle Primzahlen aus (terminiert nicht!).

- Suche eine Primzahl, deren zugehörige Mersenne-Zahl nicht prim ist.

- Iteriere über alle Primzahlen, deren zugehörige Mersenne-Zahl nicht prim ist.

Übung 59 Seite 338. Bilden wir Leaf und Node wie vorgeschlagen:

sage: Leaf = var('Leaf'); Node = function('Node', nargs=2)

Dann denieren wir unseren Iterator rekursiv:

sage: : def C(n):|....: if n == 1:....: yield Leaf....: elif n > 1:....: for k in range(1,n):....: for t1 in C(k):....: for t2 in C(n-k):....: yield Node(t1, t2)

Hier die kleinen Bäume:

sage: list(C(1))[Leaf]sage: list(C(2))[Node(Leaf, Leaf)]sage: list(C(3))[Node(Leaf, Node(Leaf, Leaf)), Node(Node(Leaf, Leaf), Leaf)]sage: list(C(4))[Node(Leaf, Node(Leaf, Node(Leaf, Leaf))),Node(Leaf, Node(Node(Leaf, Leaf), Leaf)),Node(Node(Leaf, Leaf), Node(Leaf, Leaf)),Node(Node(Leaf, Node(Leaf, Leaf)), Leaf),Node(Node(Node(Leaf, Leaf), Leaf), Leaf)]

Wir treen wieder auf die Folge von Catalan:

sage: [len(list(C(n))) for n in range(9)][0, 1, 1, 2, 5, 14, 42, 132, 429]

A.16. Graphentheorie

Übung 60 Seite350. (Zirkulierende Graphen). Zwei Schleifen reichen aus!

sage: def circulant(n, d):....: g = Graph(n)....: for u in range(n):....: for c in range(d):....: g.add_edge(u, (u+c)%n)....: return g

429

Page 446: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A. Lösungen der Übungen

Übung 61 Seite 352. (Graph von Kneser) Das Einfachste ist, das Sage-Objekt Subsetszuverwenden. Wir listen dann alle Knotenpaare auf, um die adjacenten zu nden, doch daserfordert viel unnütze Rechnerei.

sage: def kneser(n,k):....: g = Graph()....: g.add_vertices(Subsets(n,k))....: for u in g:....: for v in g:....: if not u & v:....: g.add_edge(u,v)....: return g

Wir können allerdings Zeit gewinnen, wenn wir nur die adjazenten Knoten auisten.

sage: def kneser(n,k):....: g = Graph()....: sommets = Set(range(n))....: g.add_vertices(Subsets(sommets,k))....: for u in g:....: for v in Subsets(sommets - u,k):....: g.add_edge(u,v)....: return g

Übung 62 Seite 367. (Optimale Reihenfolge bei gieriger Färbung) Die Methode coloringliefert eine Färbung als Liste von Listen: die Liste der Knoten mit der Farbe 0, die Liste derKnoten mit der Farbe 1 usw. Um auf den Knoten eine Ordnung zu erhalten, die mit demgierigen Algorithmus eine optimale Färbung liefert, genügt es, die Knoten mit der Farbe 0aufzulisten (egal in welcher Reihenfolge), dan die mit der Farbe 1 uns so fort! So erhalten wirfür den Petersen-Graphen:

sage: g = graphs.PetersenGraph()sage: def ordre_optimal(g):....: ordre = []....: for classe_de_couleur in g.coloring():....: for v in classe_de_couleur:....: ordre.append(v)....: return ordresage: ordre_optimal(g)[1, 3, 5, 9, 0, 2, 6, 4, 7, 8]

A.17. Lineare Programmierung

Übung 63 Seite 380. (Teilsummenproblem) Jedem Element der Menge weisen wir einebinäre Variable zu, die anzeigt, ob das Objekt zur Teilmenge mit der Summe null gehört odernicht. Dann gibt es zwei Bedingungen:

- die Summe der zugehörigen Elemente muss null sein,

- die Menge darf nicht leer sein.

430

Page 447: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A.17. Lineare Programmierung

Das macht nun der folgende Code:

sage: l = [28, 10, -89, 69, 42, -37, 76, 78, -40, 92, -93, 45]sage: p = MixedIntegerLinearProgram()sage: b = p.new_variable(binary = True)sage: p.add_constraint(p.sum([v*b[v] for v in l]) == 0)sage: p.add_constraint(p.sum([b[v] for v in l]) >= 1)sage: p.solve()0.0sage: b = p.get_values(b)sage: print [v for v in b if b[v] == 1][-93, 10, 45, 78, -40]

Zu beachten ist, dass keine Zielfunktion deniert werden musste.

Übung 64 Seite 381. (Dominierende Menge) Die Bedingungen dieses ganzzahligen linearenProgramms entsprechen einem Überdeckungsproblem: eine Menge S von Knoten eines Gra-phen ist eine dominierende Menge genau dann, wenn für jeden Knoten v gilt (v ∪NG(v))∩S 6= ∅, wobei NG(v) die Menge der Nachbarn von v in G bezeichnet. Daraus leiten wirfolgenden Code her:

sage: g = graphs.PetersenGraph()sage: p = MixedIntegerLinearProgram(maximization = False)sage: b = p.new_variable(binary = True)sage: for v in g:....: p.add_constraint(p.sum([b[u] for u in g.neighbors(v)]) + b[v] >= 1)sage: p.set_objective(p.sum([b[v] for v in g]))sage: p.solve()3.0sage: b = p.get_values(b)sage: print [v for v in b if b[v] == 1][0, 2, 6]

431

Page 448: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 449: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

433

Page 450: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

B. Bibliographie

B. Bibliographie

[AL03] Journaïdi Abdeljaoued und Henri Lombardi, Méthodes matri-

cielles Introduction à la complexité algébrique. Springer, 2003,ISBN 3540202471.

[AP98] Uri M. Ascher und Linda R. Petzold, Computer Methods for Ordinary

Dierential Equations and Dierential-Algebraic Equations. Societyfor Industrial and Applied Mathematics, 1998, ISDBN 0898714128.

[AS] Noga Alon und Joel H. Spencer, The Probalistic Method. Wiley-Interscience, 2000, ISBN 0471370460.

[Bea] Bernard Beauzamy, Robust Mathematival Methods for Extremely

Rare Events. Online, 2009. http://www.scmsa.eu/RMM/BB_rare_events_2009_08.pdf, 20 Seiten

[BZ10] Richard P. Brent und Paul Zimmermann, Modern Computer Arith-

metic. Cambridge University Press, 2010, ISBN 0521194693. http:www.loria.fr/~zimmerma/mca/pub226.html.

[Cia82] Philippe G. Ciarlet, Introduction à l'analyse numérique matricielle

et à l'optimation. Mathematiques appliquées pour la maîtrise.Masson, 1982, ISBN 2225688931.

[CLO07] David Cox, John Little und Donal O'Shea, Ideals, Varieties, andAlgorithms. Undergraduate Texts in Mathematics. Springer-Verlag,3. Auage 2007, ISBN 0387946802.

[CM84] Michel Crouzeix und Alain L. Mignot, Analyse numérique des équationsdiérentielles. Mathématiques appliquées pour la maîtrise. Masson1984, ISBN 2225773416.

[Coh] Henri Cohen, A Course in Computational Algebraic Number Theory.

Nummer 138 in Graduate Texts in Mathematics. Springer-Verlag,1993, ISBN 3540556400.

[CP01] Richard Crandall und Carl Pomerance, Prime Numbers: A Computa-

tional Perspective. Springer-Verlag, 2001, ISBN 0387947779.[DGSZ95] Philippe Dumas, Claude Gomez, Bruno Salvy und Paul Zimmermann,

Calcul formel : mode d'emploi. Masson, 1995, ISBN 2225847800.[Edm65] Jack Edmonds, Paths, Trees, and Flowers. Canadian Journal of

Mathematics, 17(3):449-467, 1965.[EM07] Mohamed Elkadi und Bernard Mourrain, Introduction à la résolu-

tion des systèmes polynomiaux. Nummmer 59 in Mathématiques et

Applications. Springer-Verlag, 2007, ISBN 3540716467.[FS09] Philippe Flajolet und Robert Sedgewick, Analytic Combinatorics. Cam-

bridge University Press, 2009, ISBN 0521898065.[FSED09] Jean Charles Faugère und Mohab Safey El Din, De l'algèbre linéaire

à la résolution des systèmes polynomiaux. In Jacques ArthurWeil und Alain Yger (Herausgeber), Mathématiques appliquées L3, Seiten331-388. Pearson Education, 2009, ISBN 2744073520.

[Gan90] Félix Rudimovich Gantmacher, Théorie des Matrices. ÉditionsJacques Gabay, 1990, ISBN 2876470357.

[Gol91] David Goldberg, What Every Computer Scientist Should Know About

Floating Point Arithmetic. ACM Computing Surveys, 23(1):5-48, 1991.

434

Page 451: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

[GVL96] Gene H. Golub und Charles F. Van Loan, Matrix Computations. JohnsHopkins Studies in the Mathematical Sciences. Johns Hopkin Uni-versity Press, 3e édition, 1996, ISBN 0801854149.

[Hig93] Nicholas J. Higham, The Accuracy of Floating Point Summation.

SIAM Journal on Scientic Computing, 14(4):783-799, 1993, ISSN 1064-8275.[HLW02] Ernst Hairer, Christian Lubich und Gerhard Wanner, Geometric Nu-

merical Integration. Springer-Verlag, 2002, ISBN 3662050200.[HT04] Florent Hivert und Nicolas M. Thiéry, MuPAD-Combinat, an Open-

Source Package for Research in Algebraic Combinatorics. Sémi-naire lotharingien de combiuatoire, 51:B51z, 2004. http://www.mat.univie,ac.at/~slc/wpapers/s51thiery.html.

[LT93] Patrick Lascaux und Raymond Théodor, Analyse, numérique matri-cielle appliquée à l'art de l'ingénieur, Band 1. Masson, 2. Auage,1993, ISBN 2225841225.

[LT94] Patrick Lascaux und Raymond Théodor, Analyse, numérique matri-cielle appliquée à l'art de l'ingénieur, Band 2. Masson, 2. Auage,1994, ISBN 2225845468.

[Mas13] Thierry Massart, Syllabus INFO-F-101 Programmation. Online, 2013.http://www.ulb.ac.be/di/verif/tmassart/Prog/, version 3.2.

[Mat03] Ji°í Matou²ek, Using the Borsuk-Ulam Theorem: Lectures on Topo-

logical Methods in Combinatorics and Geometry. Springer-Verlag,2003, ISBN 3540003625.

[MBdD+10] Jean Michel Muller, Nicolas Brisebarre, Florent de Dinechin, ClaudePierre Jeannerod, Vincent Lefèvre, Guillaume Melquiond, NathalieRevol, Damien Stehlé et Serge Torres, Handbook of oating-pointarithmetic. Birkhäuser, 2010, ISBN 0817647049.

[Mor05] Masatake Mori. Discovery of the Double Exponential Transformation

and Its Developments. Publications of the Research Institute forMathematical Sciences. 41:897-935, 2005.

[NO] Sampo Niskancn und Patric R. J. Östergård, Cliquer Routines for

Clique Searching, http://users.tkk.fi/pat/cliquer.html.[PWZ96] Marko Petkov²ek, Herbert S. Wilf und Doron Zeilberger, A = B. A K

Peters Ltd., 1996, ISBN 1568810636.[Sch91] Michelle Schatzman, Analyse numérique. InterEditions, 1991,

ISBN 2729603731.[SwiOO] Gérard Swinnen, Apprendre à programmer avec Python. Eyrolles,

2009, ISBN 2212124743. http://inforef.be/swi/python.htm.[Swil2] Gérard Swinnen, Apprendre à programmer avec Python 3. Eyrolles,

2012, ISBN 2212134346. http://inforef.be/swi/python.htm.[TMF00] Gerald Tenenbaum und Michel Mendès France, Les nombres premiers.

Que sais-je? P.U.F.. 2000, ISBN 2130483992.[TSM05] Ken'ichiro Tanaka, Masaaki Sugihara und Kazuo Murota, Numerical

Indenite Integration by Double Exponential sinc Method. Mathe-matics of Computation, 74(250):655-679, 2005.

[Vie07] Xavier Viennot, Leonhard Euler, père de la combinatoire contem-

poraine. Exposé à la journée Leonhard Euler, mathémati.cien universel , IHÉS. Bures-sur-Yvette, mai 2007. http://www.xavierviennot.org/xgv/exposes_files/Euler_IHES_web.pdf.

[vzGG03] Joachim von zur Gathen und Jürgen Gerhard, Modern Computer Alge-

bra. Cambridge University Press, 2. Auage, 2003, ISBN 0521826462.http://www-math.uni-paderborn.de/mca.

[Zei96] Doron Zeilberger, Proof of the Alternating Sign Matrix Conjecture.

Electronic Journal of Combinatorics, 3(2), 1996.

435

Page 452: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 453: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

C. Register

437

Page 454: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 455: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

LU -Zerlegung, 286QR-Verfahren, 286QR-Zerlegung, 281, 286π, 11*, 43**, 43**=, 43*=, 43+, 43, 57, 71, 160, 354+=, 43 43-, 43-=, 43., 43.., 45/, 43//, 43/=, 43:, 43;, 42, 43<, 43, 43<=, 43<>, 43=, 43==, 17, 43>, 43>=, 43, 43, 406?, 12, 42%, 43&, 43Ähnlichkeit

Matrizen, 169Ähnlichkeitsinvariante, 169, 172, 173Äquivalenz

Matrix, 160Matrizen, 164

LATEX, 76

, 43_, 13lex_BFS, 360polygen, 128

plot_histogram, 90+, 57==, 44AA, 103, 269AlgebraicField, 103AlgebraicRealField, 103AlternatingSignMatrices, 332Arrangements, 319CC, 100, 252CDF, 248, 252CIF, 252CompleteBipartiteGraph, 353CompleteGraph, 357ComplexDoubleField, 252ComplexField, 111, 248, 252ComplexIntervalField, 252Cyclic, 190DiGraph, 357Digraph, 358Expression.find_root, 271Expression.roots, 255Expression, 254False, 11, 105FieldIdeal, 190Fields, 101FiniteEnumeratedSets, 341FiniteEnumeratedSet, 424FiniteField, 103, 117Frac, 142GF, 103GL(n,k), 156Gleichung

Sherman und Morrison, 421Graphics, 85, 90Graph, 350, 357, 358IF, 252InfinitePolynomialRing, 181, 182Infinity, 327IntegerListsLex, 341IntegerModRing, 106, 115, 120IntegerRing, 103IntegerVectors, 332Integers, 103, 115

439

Page 456: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

Integer, 252LaurentSeriesRing, 142LazyPowerSeriesRing, 150MPolynomial, 181MatricSpace, 156MatrixGroup, 156MatrixSpace, 107Mersenne-Zahl, 335MixedIntegerLinearProgram, 376NaN, 240None, 43NotImplementedError, 131NumberField, 136NumberFiels, 108OrderedSetPartitions, 332PetersenGraph, 351Polynomial.root_field, 252PolynomialRing, 103, 152, 179PowerSeriesRing, 103, 144QQbar, 103, 139, 185QQ, 104, 252RDF, 131, 239, 248, 252RIF, 137RR, 104, 252RationalField, 103, 252Rational, 95RealDoubleField, 252RealField, 103, 239, 248, 252RealIntervalField, 252SL(n,k), 156SR, 108, 146SVD (singular value decomposition), 280SVD (singular value decomposition), 282Set, 71, 424StandardTableaux, 332SubMultiset, 411Subsets, 411, 430TimeSeries, 82True, 11, 105VectorSpace, 155WeightedIntegerValues, 329ZZ, 103, 116, 252Zerlegung

in einfache Elemente, 142__add__, 96__mult__, 96abs, 9, 96, 105add_constraint, 376add_edges, 349add_edge, 349

add_vertex, 349add_vertices, 349add, 63all, 335, 428and, 105animate, 76any, 335append, 66, 268assert, 42assume, 225attrcall, 337augment, 156automorphism_group, 363bar_chart, 80, 90base_extend, 156, 159base_ring, 115, 128, 156basering.lagrange_polynomial, 268basis_is_groebner, 206basis, 156berlekamp_massey, 146, 408binomial, 9, 326block_diagonal_matrix, 158block_matrix, 156, 158bool, 17, 105breadth_first_search, 360cardinality, 331, 426cartesian_product, 339catagories, 133catalan, 8, 11category, 101center, 360change_ring, 131, 156, 159, 208characteristic_polynomial, 162characteristic, 115charpoly, 136, 162, 171chromatic_number, 352, 362circle, 89, 90class, 42clique_maximum, 362collections, 268collect, 18, 129coloring, 356, 362, 367column_space, 394combine, 20combstruct, 323complement, 358complex_plot, 79, 90conjugate, 132, 160connected_components, 361contrib_ode, 216

440

Page 457: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

copy, 69, 160, 286, 359count, 66cover_ring, 136crt, 119, 132decomposableObjects, 323decomposition, 173def, 42, 52degree, 130, 181delete_edge, 350delete_vertex, 350depth_first_search, 360deque, 268derivative, 134, 181, 256desolve_laplace, 227, 230desolve_rk4, 85, 90desolve_system, 228desolve, 216, 230det, 166dict, 130diff, 130, 230, 389, 397dimension, 185, 193discriminant, 137disjoint_union, 353, 354divides, 132, 185dominating_set, 362eccentricity, 360echelon_form, 162, 164, 394echelonize, 162, 164edge_cut, 361edge_disjoint_paths, 361eigenmatrix_left, 162eigenmatrix_right, 162eigenspaces_left, 162, 174eigenspaces_right, 162eigenspacesright, 174eigenvalues, 174eigenvectors_left, 162, 174eigenvectors_right, 162eigenvectors_riht, 174elementary_divisors, 166elementwise_product, 160elif, 52elimination_ideal, 193else, 51euler_gamma, 11exec, 42exists, 335expand, 18extend, 66factor_list, 20

factorial, 10, 104factor, 20, 96, 137, 185filter, 61, 66, 68, 70finance, 82flatten, 63, 68float, 103floor, 9flow, 361for, 42, 44, 62, 329for-Schleife, 44function_factory, 405function, 19galois_group, 137, 141gcd, 134, 185gens, 179genus, 193gen, 128get_values, 377gfun, 323ggT

Polynom, 132global, 53hamiltonian_cycle, 362homogenize, 181, 190ideal, 135, 136, 185, 190identity_matrix, 286if, 51, 61image, 162, 168imag, 105implicit_plot3d, 93implicit_plot, 79, 90import, 14, 42independent_set, 355, 362, 372index, 66infinity, 240inject_variables, 412integer_kernel, 162, 168integrate, 304interreduced_basis, 210intersection, 190int, 103, 327inverse_laplace, 227, 230in, 60, 71irrelevant_ideal, 190is_cartesian_transitive, 364is_chordal, 360, 364is_constant, 130is_integral_domain, 133is_interval, 364is_irreducible, 136, 137

441

Page 458: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

is_isomorphic, 354is_monic, 130is_noetherian, 128is_perfect, 364is_prime, 120is_pseudoprime, 120is_regular, 352is_ring, 133is_squarefree, 185is_vertex_transitive, 352, 364is_zero, 257itertools, 336iter, 334i (imaginäre Einheit), 11jacobian_ideal, 190jacobi, 123jordan_block, 156, 162jordan_form, 176kernel, 162, 168keys, 340lagrange_polynomial, 132, 298lambda, 42, 61laplace, 226, 230lcm, 119, 132, 185lc, 181leading_coefficient, 130left_kernel, 37, 162, 168len, 59, 327lhs, 224, 230lift, 116, 135, 136, 190limit, 389line3d, 93line, 83, 84, 90lm, 181log, 120, 248lt, 181map_coefficients, 181map, 61, 63, 68, 70matching, 350, 372matrix, 36, 107, 136max_symbolic, 307maxspin, 162, 171minimalpolynomial, 162minpoly, 136, 162mod, 116, 136, 184, 190mq, 191multi_polynomial_sequence, 191new_variable, 377, 382next_prime, 120next, 333, 334

normal_basis, 193, 202not, 105number_field, 136numerator, 142numerical_approx, 10, 98numer, 96ode_contrib, 218ode_solver, 84, 310odeint, 84, 90, 398oeis, 320one, 156order, 349or, 105parametric_plot, 78, 90parent, 115partial_fraction_decomposition, 143partial_fraction, 227pass, 42periphery, 360piecewise, 77pivot_rows, 162pivots, 162pi, 14plot3d, 15, 91plot_histogram, 90plot_points, 75plot_vectorfield, 87plot, 15, 75, 90, 220, 298, 357points, 90point, 82polar_plot, 79, 90polygon, 90polynomial, 182pop, 66prec, 142, 239prime_range, 121print, 42, 58pseudo_divrem, 134q_factorial, 428quit, 43quo_rem, 132, 184quotient, 190quo, 135, 136, 190radical, 137radius, 360random_element, 131, 366random_matrix, 156random, 82randrange, 80range, 334

442

Page 459: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

rank, 166rational_argument, 187rational_reconstruction, 118rational_reconstruct, 142, 144raw_input, 58real_root_intervals, 139real_roots, 137, 270real, 105reduce, 62, 135, 190resultant, 137, 185, 193return, 42, 47, 261, 337reverse, 64, 129reversion, 142rhs, 230right_kernel, 37, 162, 168, 393roots, 138, 199, 251, 256rsolve, 232save, 76scipy, 398set_binary, 377set_immutable, 160set_integer, 377set_max, 377set_min, 377set_objective, 378set_real, 377show, 76, 90, 355, 357simplify, 11, 109size, 349smith_form, 162, 166solve_left, 37, 162, 168solve_right, 37, 162, 168solve, 89, 185, 222, 376, 378sorted, 66sort, 65split, 68squarefree_decomposition, 138stack, 156str, 68, 103subgraph_search, 353, 371subgraph, 358submatrix, 156substitute_function, 406subs, 18, 130, 181, 183sum, 63, 334swap_columns, 162swap_rows, 162taylor, 145test_poly, 180text, 91

timeit, 117trace, 136transformed_basis, 187, 212transpose, 160, 279, 283trees, 353triangular_decomposition, 187, 193, 200trig_expand, 388trig_simplify, 388try, 42, 81ulp, 241variable_names_recursive, 181variable_name, 130variables, 230variety, 185, 193, 198var, 15, 230vector_space_dimension, 193vertex_connectivity, 361vertex_cut, 361vertex_disjoint_paths, 361while, 42while-Schleife, 45with, 42xgcd, 132xrange, 334x (symbolische Variable), 14yield, 42, 261, 337zip, 70

AbleitungPolynom, 130

Abschluss von Zariski, 192Absolutwert, 9Abstand, 360Adjazenztabelle, 351Algebra

linear, 155numerisch, 273

AlgorithmusDijkstra, 360Ford-Fulkerson, 361Gauÿ, 161Gauÿ-Jordan, 162, 164schnelle Multiplikation, 152

Alias, 68alternierende Folge, 49Anfangsbedingung, 216Animation, 76anonyme Funktion, 61Anweisungsblock, 44Approximation

numerisch, 47, 139

443

Page 460: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

Padé, 144Arbeitsblatt, 5Arithmetik

endlicher Körper, 117Matrix, 160modulo n, 116Polynom, 130Polynome, 132, 183

ATLAS, 291Ausdruck

Funktion, 19gebrochen rational, 20gebrochen-rational, 142symbolisch, 15, 17, 105, 108, 111, 153,

405Ausgabe, 57, 85, 355Auslöschung, 242Austausch der Variablen, 222Auswerten, 18Auswertung, 131automatische Vervollständigung, 98Axiom, 99, 127

Basistyp, 103Baum

Ausdruck, 17Steiner, 363

Befehlszeile, 8Begleitmatrix, 176Bild, 85

lineare Abbildung, 168Bionomialkoezient, 10Bisektion, 261BLAS, 291Brdingungen, 51Brent-Verfahren, 271

CassiniFläche, 94

charakteristischer Wert, 169chinesischer Restsatz, 121Cholesky-Zerlegung, 279, 283CIF, 139Clique, 362Cliquer (Programm), 362CoCoA, 202Collatz-Problem, 51Comprehension, 62Cox, David A., 179Cramersche Regel, 276CSV (Comma Separated Values), 81

Denitionsmenge, 102Dekorator, 55Determinante, 162, 166, 169Dezimalpunkt, 10Diagonalisierung, 162Diagramm, 80, 90Dickson

Lemma, 206Dictionary, 72Diemension

einer Varietät, 210Dierentialgleichung, 86, 149, 297, 309

Bernoulli, 217Clairaut, 216exakt, 217Graph einer Lösung, 220homogen, 217, 222, 223konstante Koezienten, 224, 226Lagrange, 216linear 1. Ordnung, 84, 215Parameter, 223partiell, 215Riccati, 216System, 227Trennung der Variablen, 217, 222Verhulst, 223

Diktionär, 72, 350Dimension, 192

eines Ideals, 185, 198, 210Diskriminante, 137

Polynom, 141Division, 9, 134

ganze Zahlen, 10nach wachsenden Potenzen, 134Polynom, 132Polynome, 183, 209

Dokumentation, 12doppelte Genauigkeit, 239, 271Dreiecksform, 163Dreieckszerlegung

eines Ideals, 199

Edmonds, Jack, 380Eigenvektor, 162, 174Eigenwert, 162, 169, 174, 228Einrückung, 8, 44Elimination, 193

algebraisch, 196Elkadi, Mohamed, 179Endlosschleife, 65, 261erraten, 146

444

Page 461: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

ErzeugendeVektorraum, 155

Evolute, 88Evolvente

einer Familie von Kurven, 196Exponent, 237, 246Export

Bild, 357Export einer Abbildung, 76Exzentrizität, 360

FärbungGraph, 362, 365, 373

Faktorinvariant, 173

Faktorisierung, 136ganze Zahl, 96, 122, 137Polynom, 110, 115, 136, 137

Fakultät, 10Programmierung, 54

Farbe, 75, 355Faugère, Jean-Charles, 179Fehler, xFibonaccifolge, 54Fixpunkt, 149Fläche

Cassini, 94parametrisiert, 91

Fluss, 361, 381Folge

aliquot, 123alternierend, 49Fibonacci, 54gebrochen rational, 232gleichverteilt, 82hypergeometrisch, 232Krylow, 170logistisch, 229polynomial, 232rekursiv deniert, 45, 47, 135, 151, 229,

243Sturm, 258Zeichnung, 83

FormFrobenius, 170, 172Hermite, 165hermitesch, 394Jordan, 169

Fourier-ReihePartialsumme, 77

Fundamentalsatz der Algebra

Gauÿ-d'Alembert, 253Funktion, 52, 216, 248

anonym, 61Python, 43symbolisch, 19, 387trigonometriisch, 248trigonometrisch, 3Zeta (ζ), 51

Funktionsgleichung, 149

gebrochen-rational, 134Genauigkeit, 237, 244

doppelt, 239Einbuÿe, 242Reihe, 142

Generator, 123, 128, 261, 266Polynomring, 181

generisch, 97Geometrie, 195, 197geordnete Liste, 64geschlossene Formel, 187GF, 117ggT, 116, 118, 256Gleichung, 12

einer Kurve, 196Fläche, 93Kurve, 78, 79linear, 167mit partiellen Ableitungen, 216nichtlinear, 251polynomial, 141

Gleichungssystem, 179linear, 167

Gleichverteilung, 82Gleitpunktzahlen, 237GMP, 252GMRES, 294, 296GNU MPFR, 239Gröbner-Basen, 326Gröbnerbasis, 189, 192, 203

Aufwand, 212Denition, 206reduziert, 210

Gradientkonjugiert, 294

Grak, 15Graph, 349

Bezeichner, 350cordal, 360Familien, 352Funktion, 75, 90

445

Page 462: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

Intervall-, 364klein, 351Kneser, 352knoten-transitiv, 351knotentransitiv, 364komplexe Funktion, 79Lösung Dierentialgleichung, 311Lösung einer Dierentialgleichung, 220Petersen, 351planar, 351rekursiv denierte Folge, 230Tangente, 265Traversierung, 360vollkommen, 364vollständig, 353zirkulierend, 350Zufalls-, 353

Graphik, 75Grenzwert

numerische Approximation, 48Gruppe, 101

Galois, 137linear, 156

GSL, 84, 304, 305, 311, 423

Häufungspunkt, 230Hüllkurve, 89Hamiltonkreis, 362Hamiltonkrteis, 384Handbuch, 12Handlungsreisender, 362, 382Hilbertmatrix, 274Hilfe, 7, 12, 98Histogramm, 81, 90https://cloud.sagemath.com , 5

iimaginäre Einheit, 105

Ideal, 185Polynome, 188

IEEE-754, 238immutabel, 70, 71Inhalt, 131, 132Instanz, 95Integralkurve, 85, 90Integration, 297Interpolation

Cauchy, 146Introspektion, 98, 328Inverse

modular, 116

Iteration, 45Iterator, 333, 334, 337

Jacobi-Symbol, 122Jordanblock, 175Jordanmatrix, 176

Körper, 111, 134endlich, 96, 106, 115, 120endlich, zusammengesetzt, 117

Kante (Graph), 349kash, 98Kategorie, 99, 133Kern, 162, 168Klasse, 95, 99Knoten, 94Knoten (Graph), 349Koezient, 128, 180, 183

Binomial-, 10Leitkoezient, 181Polynom, 128, 181

kompensierte Summierung, 246Kondition, 274, 279281Konditionierung, 294Kongruenz, 106Konstante

Catalan, 8, 11Masser-Gramain, 124vordeniert, 11

Konvergenz, 50, 259, 269Konvergenzbeschleunigung, 270Konversion, 97, 240Kopplung, 350Kreiszahl, 11Kryptologie, 117Kurve

Parameterdarstellung, 78, 196parametrisiert, 88, 90parametrisiert, im Raum, 93

LösungDierentialgleichung, 84numerisch, 201, 251polynomiale Systeme, 184Wurzelausdruck, 254

Lapack, 287Laplace-Transformation, 226LattE, 343Leitkoezient, 181, 203Leitmonom, 181, 203Leitterm, 203

446

Page 463: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

LemmaDickson, 206

lexikographische Ordnung, 65Liste

geordnet, 64Listen, 58Little, John B., 179Logarithmus, 3

diskret, 122logisch, 105LU-Zerlegzng, 277

Macauley2, 202Magma, 127Magna, 98Magnus-Eekt, 88Mantisse, 237, 246Maple, 14, 127, 323Masche, 351Masser-Gramain

Konstante, 124Matching, 380Matrix, 36, 106, 155, 273, 375

Adjazenz-, 157Begleit-, 176Block-, 158Eintrag, 157Faktorisierung, 277Hilbert, 274identisch, 156Norm, 274, 280282unimodular, 165

Matrizenprodukt, 63Maxima, 14, 222, 256, 305, 313Mendès-France, Michel, 83Menge, 70

führend, 381unabhängig, 355, 368, 372

Methode, 96Minimalpolynom, 172, 186

lineare Rekursion, 136Matrix, 37, 162

Minor, 363Matrix, 162

ModellRäuber-Beute, 86

Modulkomplexe Zahl, 105

Mourrain, Bernard, 179MPFR, 239Muller, David. E., 267

Muller, Jean-Michel, 244Muller-Verfahren, 267Multiplikation

schnell, 152Multiplizität, 188, 251Multiplkation, 9MuPAD, 99MuPAD-Combinat, 323mutabel, 160, 350

Nenner, 142Newton-Verfahren, 265Norm

komplexe Zahl, 105Matrix, 274, 280282

NormaformMatrix, 160

normale Gleichung, 280, 281Normalform, 20, 102, 128

Ausdruck, 112Matrix, 172modulo eines Ideals, 190

Notebook, 7Nullstellensatz, 190numerische Algebra, 273numerische Approximation, 10, 273

Dierentialgleichung, 309Grenzwert, 48Integral, 297Lösung von Gleichungen, 201

NumPy, 86, 268

O'Shea, Donal, 179Objekt, 95Operation

arithmetisch, 9arithmetisch-harmonisch, 97

Operationen, 3Optimierung, 375Ordnung, 183

additiv, 116lexikographisch, 65Monome, 184multiplikativ, 116Variable, 181

Paarung, 380PALP, 343Parametrisierung, 88, 196PARI, 98, 268, 303, 305, 307Partialbruchzerlegung, 227

447

Page 464: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

partielle DierentialgleichungWärmeleitung, 225

PascalSchnecken, 79

Permutation, 366Phänomen

Gibbs, 77Runge, 300

Pivotstelle, 163Pocklington

Satz, 121Polarkoordinaten, 79Polymorphie, 97Polynom, 127, 181

charakteristisch, 162, 169, 172Legendre, 300Tschebyschow, 134Wurzel, 242

Polynomdarstellungdünn besetzt, 151rekursiv, 129voll besetzt, 151

Polynomdarszellungfaktorisiert, 109

Polynomdivision, 183Polynomring, 107, 127, 180

in unendlich vielen Unbestimmten, 182Potenz, 3

invers, 285iteriert, 284, 295, 296

Potenzierungmodular, 121

Potenzreihe, 107, 143, 406Präzision, 237Primzahl, 117Produkt

Graphen, 359kartesisch, 100Skalar-, 36Vektor-, 36

Programmierungganzzahlig linear, 376linear, 362, 375objektorientiert, 95

Projektion, 194Prompt, 8Prozedur, 52Pseudodivision, 132pseudoprim, 120Python, 4

QR-Zerlegung, 279QUADPACK, 305Quadratur, 299Quadratwurzel, 3Quotientenring, 189

Radikal, 191Raung, 62, 333Rang, 166

Matrix, 162, 166, 169Rangprol, 162, 166Reduktion

Endomorphismen, 162verzögert, 115

Regel von Descartes, 257Reihe, 107, 245

abgeschnitten, 142faul, 150Fourier, 78harmonisch, 245Potenz-, 107, 147Riemann, 50

Reihenentwicklungabbrechend, 108, 150

Rekonstruktionrational, 118, 125, 142, 143

Rekursion, 45rekursiv, 151rekursiv denierte Folge, 45, 47, 229

Graph, 230Relation, 135Rest

quadratisch, 122Restklassenring Z/nZ, 115Restsatz

chinesisch, 121Resultante, 139, 197Riemann-Reihe, 50Ring der ganzen Zahlen, 115, 120Rucksackproblem, 379Rundung, 238, 242

Fehler, 247

Safey El Din, Mohab, 179Sage

Cloud, 5Geschichte, 4

sage-support, xsagemath.org, 6Satz

Borsuk-Ulam, 352

448

Page 465: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

Caley-Hamilton, 172Kuratowski, 351Pocklington, 121

Schleifefor, 44while, 45

Schleifenabbruch, 47Schmiegkreis, 89schnelles Potenzieren, 55Schnitt

Graph, 363SciPy, 84, 85, 271, 293, 296Sekantenverfahren., 266Server

öentlich, 5Singulärwert, 280, 281, 283Singular, 181, 202Skalarprodukt, 36Spalte

Matrix, 158Spur, 274, 282Steensen-Verfahren, 270Stein, William, 4Struktur

algebraisch, 100Sturm

Folge, 258Summe

Programmierung, 48Teilmengen, 380

SVD engl. Singular Value Decomposition,282

SWZ für Singulärwertzerlegung, 282Sympy, 232Syracuse-Vermutung, 51

Tabellenkalkulation, 81Tangente

Graph, 265Taylor, 387Teilgraph

induziert, 353, 369Teilhabe an denselben Daten, 68Tenenbaum, Gérard, 83Test

Fermat, 120textttsin, 248trac.sagemath.org, xTreppe, 207Treppenlinie, 206Treppennormalform, 163, 164

Trigonalisierung, 163Trigonometrie, 211Tupel, 70

unendlich, 11Ungleichung, 375

polynomiale Systeme, 197unit in the last place, 241Untermatrix, 159Urbild, 73

VandermondeDeterminante, 109

Variable, 130abhängig, 216Deklaration, 15Python, 13symbolisch, 14, 15unabhängig, 216

Varietätalgebraisch, 188

VektorErzeugung, 157zyklisch, 171

Vektorprodukt, 36Vektorraum, 155

Basis, 156Eigenraum, 169Eigrenraum, 162invariant, 169

Vereinfachung, 11, 111Vereinigung, 353

Mengen, 321, 339Verfahren

Brent, 271doppelt exponentiell, 298, 301Dormand und Price, 310Euler, 310Gauÿ-Kronrod, 298, 300Gauÿ-Legendre, 300Gear, 310Muller, 267Newton, 265Newton-Cotes, 298Rechteck, 298Runge-Kutta, 310Steensen, 270Trapez, 301Trennung der Veränderlichen, 225

Verfahren der falschen Position, 263Vergleich, 20, 44

449

Page 466: Rechnen mit Sage - LORIA · Inhaltsverzeichnis I. Die Handhabung von Sage 1 1. Erste Schritte 3 1.1. Das Programm Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Index

Verkettung, 68Verschiebung, 162Vervollständigung

automatisch, 12Vielfachheit, 251, 256Vorfahr, 99, 102, 135Vorzeichenregel

Descartes, 257

Wärmeleitungsgleichung, 225Wahrheitswerte, 11, 105Wahrscheinlichkeit, 353worksheet, 7Wurzel

n-te, 9Polynom, 136, 242, 251

Wurzel eines PolynomsIsolation, 258

Zahlalgebraisch, 108, 131, 139, 185Carmichael, 121chromatisch, 351Flieÿpunkt, 105ganz, 105ganz modular, 115Gleitpunkt-, 237harmonisch, 118komplex, 105, 228Mersenne, 335p-adisch, 127rational, 104

Zariski-Abschluss, 195, 198Zeichenkette, 57, 67Zeichnung, 86, 90

Graph, 355Zeile

Matrix, 158Zerlegung

LU , 286QR, 281Cholesky, 279, 283Dreiecksform (eines Ideals), 199in einfache Elemente, 20LU, 277QR, 279quadratfrei, 138

Zerlegung (Matrix)Gauÿ-Jordan, 164LU, 164

Zeta-Funktion, 51

Zielfunktion, 376Zufallsgraph, 367, 369Zufallsweg, 82Zusammenhangskomponenten, 361Zuweisung, 13, 49, 68Zwangsmodell, 97

450