Beginnen wir zunächst mit der Definition von Vektoren. Obschon sie mit dem Maple-Standardbefehl array definiert werden können, existiert im Paket linalg die Anweisung vector, welche benutzerfreundlicher ist. Ein Vektor besteht aus seinen Komponenten a1 .. an. Seine Dimension ist beliebig: es lassen sich nicht nur Vektoren der Ebene, sondern auch des Raumes und höherer Dimensionen deklarieren, entsprechen aber im mathematischen Sinne Spaltenvektoren.
Es folgt eine Vorstellung der verschiedenen in Maple vorhandenen Operationen anhand dreidimensionaler Vektoren.
> restart; > with(linalg): Warning: new definition for norm Warning: new definition for trace > vec1 := vector([a1, b1, c1]); vec1 := [ a1, b1, c1 ] > vec2 := vector([a2, b2, c2]); vec2 := [ a2, b2, c2 ]Die Addition zweier Vektoren geschieht mit add (in R4 benutzen Sie hierfür bitte die Funktion linalg/matadd):
> add(vec1, vec2); [ a1 + a2, b1 + b2, c1 + c2 ]Die Subtraktion zweier Vektoren erfolgt ebenfalls mit add (R4: linalg/matadd), aber mit negativem Vorzeichen eines der Vektoren:
> add(vec1, - vec2); [ a1 - a2, b1 - b2, c1 - c2 ]Hinweis: Vektoraddition und - subtraktion können auch mit dem Maple-Standardbefehl evalm durchgeführt werden.
> evalm(vec1 + vec2); > evalm(vec1 - vec2);S-Multiplikation (scalar multiplication):
> scalarmul(vec1, s); [ s a1, s b1, s c1 ]Vektor- oder Kreuzprodukt (cross product):
> crossprod(vec1, vec2); [ b1 c2 - c1 b2, c1 a2 - a1 c2, a1 b2 - b1 a2 ]Skalarprodukt (dot product) zweier Vektoren: a*b=|a|*|b|*cos(alpha):
> dotprod(vec1, vec2); a1 a2 + b1 b2 + c1 c2Ein Beispiel mit konkreten Vektoren; v1 und v2 sind zueinander orthogonal, wenn das Skalarprodukt 0 ist.
> v1 := vector([-3, 1, 2]); v1 := [ -3, 1, 2 ] > v2 := vector([2, -4, 5]); v2 := [ 2, -4, 5 ] > dotprod(v1, v2); 0 > add(v1, v2); [ -1, -3, 7 ] > scalarmul(v1, 2); [ -6, 2, 4 ] > crossprod(v1, v2); [ 13, 19, 10 ]Die Länge (2-Norm oder Euklidische Norm) eines Vektors wird mit norm(vektor, 2) bestimmt:
> norm(v1, 2); 1/2 14Winkel zweier Vektoren mit angle:
> angle(v1, v2); 1/2 PiDie Radianten werden in Grad umgerechnet, v1 und v2 stehen aufeinander senkrecht:
> "*180/Pi; 90normalize normiert einen Vektor auf die Länge 1:
> normalize(v1); 1/2 1/2 1/2 [ - 3/14 14 , 1/14 14 , 1/7 14 ]
Matrizen können mit dem Befehl matrix aus dem Paket 'linalg' auf zweierlei Weise definiert werden: Entweder man übergibt dem Befehl direkt eine verschachtelte Liste, also eine Liste von Listen, welche jeweils aus den einzelnen Zeilenelementen bestehen, oder aber man gibt dem Befehl den genauen Typ der Matrix an (bestehend aus dem Eintrag m für die Anzahl der Zeilen und n für die Anzahl der Spalten -> (m, n)-Matrix) und eine Liste aller Matrixelemente, die Maple dann selbständig einordnet.
> restart: with(linalg): > A := matrix([[a, b], [c, d]]); [ a b ] A := [ ] [ c d ] > A := matrix(2, 2, [a, b, c, d]); [ a b ] A := [ ] [ c d ]Benutzerfreundlicher ist der Befehl entermatrix, mit dem man interaktiv die einzelnen Matrixelemente in der Kommandozeile eingeben kann, die dann entsprechend zugewiesen werden. Vorher ist es nötig, den Typ der Matrix Maple mitzuteilen. Eine (2, 2)-Matrix wird also wie folgt deklariert:
> A := matrix(2, 2); A := array(1 .. 2, 1 .. 2, []) > entermatrix(A); enter element 1,1 > > a enter element 1,2 > > b enter element 2,1 > > c enter element 2,2 > > d [ a b ] [ ] [ c d ]Hinweis: Das Paket math enthält die Funktion math/mat, mit der Sie Matrizen ohne Zuhilfenahme von Listen (Trennung der Zeilen) bzw. Kommata (Abtrennung der Koeffizienten) definieren können.
Fundamentale Matrixarithmetik:
Das Paket linalg stellt eine ganze Reihe von Befehlen für die Matrizenrechnung zur Verfügung. Um deren Anwendung demonstrieren zu können, definieren wir noch kurz eine Matrix B:
> B := matrix(2, 2, [e, f, g, h]); [ e f ] B := [ ] [ g h ]Die Befehle add (R4: matadd) und multiply aus linalg führen Matrixadditionen und -multiplikationen durch. Die Differenz zweier Matrizen erhalten Sie, indem die zweite Matrix im Argument des Kommandos add mit negativem Vorzeichen versehen wird (wie bei den Vektoren im vorherigen Abschnitt).
> Cadd := add(A, B); [ a + e b + f ] Cadd := [ ] [ c + g d + h ] > Csub := add(A, -B); [ a - e b - f ] Csub := [ ] [ c - g d - h ] > Cmul := multiply(A, B); [ a e + b g a f + b h ] Cmul := [ ] [ c e + d g c f + d h ]Determinanten quadratischer Matrizen werden mit det bestimmt:
> det(A); a d - b cDen Rang einer Matrix ermittelt rank:
> rank(A); 2Die inverse Matrix:
> inverse(A); [ d b ] [ - ----------- ----------- ] [ - a d + b c - a d + b c ] [ ] [ c a ] [ ----------- - ----------- ] [ - a d + b c - a d + b c ]Um kurz den Effekt der Transposition zu verdeutlichen, wird die Matrix A neu definiert:
> A := matrix(2, 3, [a1, a2, a3, b1, b2, b3]): > evalm(A), transpose(A); [ a1 b1 ] [ a1 a2 a3 ] [ ] [ ], [ a2 b2 ] [ b1 b2 b3 ] [ ] [ a3 b3 ]Eine Einheitsmatrix (also vom Typ n x n) wird durch die Anweisung
> array(identity, 1 .. 3, 1 .. 3): evalm(Em); [ 1 0 0 ] [ ] [ 0 1 0 ] [ ] [ 0 0 1 ]erzeugt.
Matrizenmanipulationen erlauben u.a. addrow, swaprow und mulrow. Darüber hinaus können Matrizen aus Vektoren oder anderen Matrizen mit augment gebildet werden:
> restart: with(linalg): > v1 := vector([a1, a2, a3]); v1 := [ a1, a2, a3 ] > v2 := vector([b1, b2, b3]); v2 := [ b1, b2, b3 ] > v3 := vector([c1, c2, c3]); v3 := [ c1, c2, c3 ] > A1 := augment(v1, v2); # 2 Vektoren [ a1 b1 ] [ ] A1 := [ a2 b2 ] [ ] [ a3 b3 ] > A2 := augment(A1, v3); # Matrix und Vektor [ a1 b1 c1 ] [ ] A2 := [ a2 b2 c2 ] [ ] [ a3 b3 c3 ] > augment(A1, A2); # 2 Matrizen [ a1 b1 a1 b1 c1 ] [ ] [ a2 b2 a2 b2 c2 ] [ ] [ a3 b3 a3 b3 c3 ]addrow multipliziert in der Matrix (erstes Argument) A2 die erste Zeile (zweites Argument) mit der Zahl 3 (viertes Argument) und addiert das Ergebnis zur zweiten Zeile (drittes Argument).
> addrow(A2, 1, 2, 3); [ a1 b1 c1 ] [ ] [ 3 a1 + a2 3 b1 + b2 3 c1 + c2 ] [ ] [ a3 b3 c3 ]mulrow multipliziert in der Matrix A2 (erstes Argument) die erste Zeile (zweites Argument) mit dem Skalar 2 (drittes Argument).
> mulrow(A2, 1, 2); [ 2 a1 2 b1 2 c1 ] [ ] [ a2 b2 c2 ] [ ] [ a3 b3 c3 ]Zeilen werden mit swaprow vertauscht, hier in der Matrix A2 die erste mit der zweiten Zeile.
> swaprow(A2, 1, 2); [ a2 b2 c2 ] [ ] [ a1 b1 c1 ] [ ] [ a3 b3 c3 ]
Lineare Gleichungssysteme in Matrizenform:
Die Lösung eines Systemes der Art A*x = c, wobei A die Koeffizientenmatrix, x und c Spaltenvektoren sind, läßt sich mit linsolve berechnen. Werden unendlich viele Lösungen ermittelt, so werden in der Ausgabe Parameter verwendet, gibt es keine Lösung, so erfolgt keine Bildschirmausgabe.
> restart; with(linalg): > A := matrix([ > [1, -3, 1.5, -1], > [-2, 1, 3.5, 2], > [1, -2, 1.2, 2], > [3, 1, -1, -3]]); [ 1 -3 1.5 -1 ] [ ] [ -2 1 3.5 2 ] A := [ ] [ 1 -2 1.2 2 ] [ ] [ 3 1 -1 -3 ] > c := vector([-10.4, -16.5, 0, -0.7]); c := [ -10.4, -16.5, 0, -.7 ] > linsolve(A, c); [ .80800000000000000002, -.1839999999999999999, -5.8799999999999999999, 2.9400000000000000000 ]Man beachte die Rundungsfehler, die genauen Lösungen sind:
> A := matrix([ > [1, 1, -2], > [1, -1, -2], > [2, 3, -4]]); [ 1 1 -2 ] [ ] A := [ 1 -1 -2 ] [ ] [ 2 3 -4 ] > c := vector([0, 0, 0]); c := [ 0, 0, 0 ] > linsolve(A, c); [ 2 _t[1], 0, _t[1] ]Lineare Gleichungssysteme können Sie in Matrizenform umwandeln. Gegeben sei folgendes System:
> restart: with(linalg): > sys := { > -2*x+2*y+7*z=0, > x-y-3*z=1, > 3*x+2*y+2*z=5}:Mit genmatrix wird aus dem Gleichungssystem 'sys' mit den Unbekannten x, y und z eine Matrix erstellt. Als dritter Parameter muß irgendein Wort angegeben werden, damit die letzte Spalte nicht 'verschluckt' wird.
> temp := genmatrix(sys, [x, y, z], ausdruck); [ -2 2 7 0 ] [ ] temp := [ 1 -1 -3 1 ] [ ] [ 3 2 2 5 ]Mit gausselim wird das Gaußsche Eliminationsverfahren auf die erzeugte Matrix angewendet; das Ergebnis ist eine obere Dreiecksmatrix. backsub liefert die Lösung des reduzierten Systemes.
> gausselim(temp); [ -2 2 7 0 ] [ ] [ 0 5 25/2 5 ] [ ] [ 0 0 1/2 1 ] > backsub("); [ 3, -4, 2 ]Aus einer Matrix lassen sich mit submatrix auch Untermatrixen erzeugen. Der erste Parameter ist die zu bearbeitende Matrix (hier 'temp'), der zweite und dritte die Zeilen- bzw. Spaltenbereiche, die kopiert werden sollen.
> A := submatrix(temp, 1 .. 3, 1 .. 3); [ -2 2 7 ] [ ] A := [ 1 -1 -3 ] [ ] [ 3 2 2 ] > c := submatrix(temp, 1 .. 3, 4 .. 4); [ 0 ] [ ] c := [ 1 ] [ ] [ 5 ]Die vierte Spalte können Sie aber einfacher mittels col (columns) kopieren.
> c := col(temp, 4); c := [ 0, 1, 5 ] > linsolve(A, c); [ 3, -4, 2 ]Ein dreidimensionales Histogramm:
> matrixplot(temp, heights=histogram, gap=0.15, axes=frame);
Zuletzt wird noch die Eigenwertberechnung einer Matrix vorgestellt. Auch hier leistet Maple nützliche Hilfe, indem mehrere Schritte zur Berechnung von Eigenwerten durch einen einzigen Befehl durchgeführt werden: eigenvals. Die Eigenwerte sind definiert durch:
mit A als Matrix, t als Parameter und Em als Einheitsmatrix, wobei nach Ermittlung der Determinanten das entstehende Polynom gleich Null gesetzt wird:
> restart: with(linalg): > A := matrix(3, 3, [0, -1, 0, -1, -1, 1, 0, 1, 0]); [ 0 -1 0 ] [ ] A := [ -1 -1 1 ] [ ] [ 0 1 0 ] > Em := array(identity, 1 .. 3 ,1 .. 3): evalm(Em); [ 1 0 0 ] [ ] [ 0 1 0 ] [ ] [ 0 0 1 ] > solve(det(add(A, -t*Em))=0); 0, -2, 1oder ganz einfach durch:
> eigenvals(A); 0, 1, -2
Die zweidimensionale Geometrie kann mit Paket geometry erforscht werden, dessen Syntax aber gewöhnungsbedürftig ist.
> restart; > with(geometry):Definition zweier Punkte p1 und p2 mit point. Das erste Argument ist der Punkt, dem die Punktkoordinaten 2 und 3 als weitere Argumente zugewiesen werden.
> point(p1, 2, 3); p1 > point(p2, 0, 0); p2Punkte, Linien und Kreise werden mittels des Datentyps table gespeichert. Die Struktur ermittelt op (oder auch print) und enthält oft weitere nützliche Daten.
> op(p1); table([ form = point x = 2 y = 3 ])Es sind die Felder 'form', 'x' und 'y' eingetragen, auf deren Werte ('point', '2' bzw. '3') man auf folgende Weise zugreifen kann:
> p1[form], p1[x], p1[y]; point, 2, 3Da die Variablen x und y intern durch das Paket geometry genutzt werden (sie sind global), sollte man ihre Werte nicht verändern.
Etwas einfacher geht es mit dem Befehl detailf, welcher die wichtigsten Bestandteile der Punkte, Linien und Kreise anzeigt.
> detailf(p1); [2., 3.]Die Koordinaten eines Punktes bestimmt coordinates:
> coordinates(p1); [2, 3]Linien werden mit line definiert. Das erste Argument ist der Name der zu kreierenden Linie, gefolgt von der Angabe zweier Punkte in einer Liste.
> line(gerade, [p1, p2]); gerade > op(gerade); table([ equation = (3 x - 2 y = 0) form = line given = [p1, p2] ]) > geradengl := gerade[equation]; geradengl := 3 x - 2 y = 0 > detailf(gerade); [3. x - 2. y = 0]Eine Gerade können sie auch durch eine Gleichung der Form a*x+b*y+c=0 definieren:
> line(g, [3*x-2*y=0]); g > op(g); table([ form = line given = [3 x - 2 y = 0] equation = (3 x - 2 y = 0) ])Ein Kreis wird mit circle gebildet, dem der Name des Kreises sowie dessen Mittelpunkt und Radius in einer Liste übergeben werden:
> circle(kreis, [p1, 2]); kreis > op(kreis); table([ 2 2 equation = (x + y + 9 - 4 x - 6 y = 0) form = circle given = [p1, 2] center = p1 radius = 2 ]) > detailf(kreis); [center = [2., 3.], radius = 2.] > kreisgl := kreis[equation]; 2 2 kreisgl := x + y + 9 - 4 x - 6 y = 0Der Graph des Kreises 'kreis' und der Geraden 'gerade':
> implicitplot({kreisgl, geradengl}, x=-2 .. 6, y=-1 .. 6);
inter ermittelt die Schnittpunkte (intersections) zweier Geraden oder aber eines Kreises mit einer Geraden. Die unten angegebene Kombination von map und coordinates ermittelt die Koordinaten.
> inter(kreis, gerade); gerade_intersect1_kreis, gerade_intersect2_kreis > map(coordinates, ["]); 1/2 1/2 1/2 1/2 [[2 + 4/13 13 , 3 + 6/13 13 ], [2 - 4/13 13 , 3 - 6/13 13 ]] > restart: with(geometry): > line(g1, [point(a1, 0, 0), point(b1, -2, 3)]); g1 > line(g2, [point(a2, 0, 0), point(b2, 3, 2)]); g2are_perpendicular prüft, ob zwei Geraden aufeinander senkrecht stehen, also orthogonal sind.
> are_perpendicular(g1, g2); trueParallelität zweier Geraden:
> are_parallel(g1, g2); falsedistance ermittelt die Entfernung eines Punktes von einem anderen Punkt oder einer Geraden. Syntax: distance(Punkt, Punkt oder Gerade).
> distance(a1, b1); # Entfernung zweier Punkte 1/2 13 > distance(b2, g1); # Entfernung eines Punktes von einer Geraden 1/2 13Zur Prüfung, ob ein Punkt (oder eine Liste von Punkten) auf einer Geraden liegt, nutzt man on_line.
> on_line(b1, g1); true
Das Paket geom3d beinhaltet Anweisungen zur dreidimensionalen Vektorrechnung. Die Syntax der Befehle gleicht zum größten Teil der des Paketes geometry.
Definition von Punkten im Raum:
> restart: with(geom3d): > point3d(a, [1, 1, 1]); a > point3d(b, [3, 4, 1]); b > point3d(c, [4, 3, -1]); cGeraden werden durch zwei Punkte gebildet:
> line3d(gerade1, [a, b]); gerade1 > op(gerade1); table([ form = line3d equation = [1 + 2 _t, 1 + 3 _t, 1] direction_vector = [2, 3, 0] given = [a, b] ])oder durch Angabe eines Punktes und des Richtungsvektoren:
> line3d(gerade1, [a, [2, 3, 0]]); gerade1Hinweis: der Vektor kann leider nicht mit vector aus dem Paket 'linalg' definiert werden.
Drei Punkte definieren eine Ebene:
> plane(ebene1, [a, b, c]); ebene1 > op(ebene1); table([ form = plane normal_vector = [-6, 4, -5] equation = (- 6 x + 7 + 4 y - 5 z = 0) given = [a, b, c] ])Ebenso erzeugen ein Punkt und ein Normalenvektor eine Ebene.
> plane(ebene2, [a, [3, 2, 1]]); ebene2Eine Ebene aus einem Punkt und zwei Richtungsvektoren:
> plane(ebene3, [a, [1, 0, -3], [2, -3, 0]]); ebene3 > op(ebene3); table([ form = plane normal_vector = [-9, -6, -3] equation = (- 9 x + 18 - 6 y - 3 z = 0) given = [a, [1, 0, -3], [2, -3, 0]] ])Eine Kugel bestehend aus dem Mittelpunkt c und einem Radius (oder aus vier Punkten):
> sphere(kreis, [c, 5]); kreis > op(kreis); table([ form = sphere 2 2 2 equation = (x - 8 x + 1 + y - 6 y + z + 2 z = 0) given = [c, 5] radius = 5 center = c ])Schnittgeraden ('direction_vector' ist der Richtungsvektor), das Ergebnis wird im dritten Parameter gespeichert.
> inter(ebene1, ebene2, schnitt1); schnitt1 > op(schnitt1); table([ form = line3d 19 equation = [---- + 14 _t, 5/8 - 9 _t, - 24 _t] 12 direction_vector = [14, -9, -24] given = [ebene1_ebene2, [14, -9, -24]] ]) > inter(kreis, ebene1, schnitt2); > op(schnitt1); table([ form = line3d 19 equation = [---- + 14 _t, 5/8 - 9 _t, - 24 _t] 12 direction_vector = [14, -9, -24] given = [ebene1_ebene2, [14, -9, -24]] ])
Für diesen Themenbereich existiert das Paket combinat.
choose ermittelt alle Kombinationen einer Liste von Elementen, der zweite optionale Parameter n berechnet nur n-elementige Kombinationen.
> restart: with(combinat): > s := [a, b, c]: > choose(s); [[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]]numbcomb gibt die Anzahl der Kombinationen einer Liste an.
> numbcomb(s); 8 > choose(s, 2); [[a, b], [a, c], [b, c]]Die Anzahl von Möglichkeiten, aus n Elementen m auszuwählen, beträgt bekanntlich 'binomial(n, k)'. Beispielsweise mit n=4 und k=3:
> bi(4, 3); 4 > choose(4, 3); [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]Die Anzahl von Einträgen in eine Liste ermittelt nops, in diesem Falle die Anzahl der Unterlisten, welches mit 'binomial(4, 3)' identisch ist:
> nops("); 4Für Permutationen ist permute zuständig, wobei numbperm die Anzahl der Permutationen berechnet. Auch hier führt ein zweiter Parameter n wieder dazu, daß nur n-elementige Permutationen ausgegeben werden.
> permute(s); [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b, a]] > numbperm(s); 6 > permute(s, 2); [[a, b], [a, c], [b, a], [b, c], [c, a], [c, b]] > numbperm(s, 2); 6Das Cartesische Produkt wird auf eine etwas eigenwillige Weise ermittelt, da combinat/cartprod eine Tabelle zurückgibt, die eine Prozedur enthält, welche widerum mittels Aufruf durch eine while-Schleife alle Paare bestimmt. Solange (while) T[finished] nicht den Wert true annimmt, wird der nächste Wert ('nextvalue') berechnet (do). Siehe hierzu auch das Paket math, welches ein einfach zu bedienendes Interface math/cartprod für combinat/cartprod enthält.
> T := cartprod([[1,2], [a,b]]): > while not T[finished] do T[nextvalue]() od; [1, a] [1, b] [2, a] [2, b]In T wird folgender 'Wert' abgelegt:
> eval(T); table([ finished = true nextvalue = proc() local p,value,i; global c,t; if t['finished'] then ERROR(`attempt to call nextvalue on a finished iterator`) fi; value := ['op(c[i],l[i])' $ (i = 1 .. 2)]; p := 2; do c[p] := c[p]+1; if nops(l[p]) < c[p] then c[p] := 1; p := p-1; if p = 0 then t['finished'] := true; RETURN(value) fi else RETURN(value) fi od; value end ])Die Stirlingsche Zahlen zweiter Art (Stirling numbers of the second kind) können Sie mit stirling2 finden, für den Fall S(n, k) mit n > k z.B.:
> stirling2(4, 2); 7oder für n < k (immer gleich Null)
> stirling2(1, 2); 0Die Bell-Zahlen bn:
> bell(4); 15Für die Berechnung aller Partitionen einer natürlichen Zahl n steht partition bereit. Das Ergebnis ist eine 'Liste von Listen' (d.h eine Liste, in denen weitere Unterlisten enthalten sind). Die einzelne Elemente der jeweiligen Unterlisten ergeben als Summe die Zahl n. Optional und nicht dokumentiert ist ein zweiter Parameter p; hier werden alle Partitionen einer Zahl n mit den Elementen 1 .. p gebildet.
> partition(4); [[1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3], [4]] > partition(4, 2); [[1, 1, 1, 1], [1, 1, 2], [2, 2]] > numbpart(4); 5