Kapitel Fünf:
Lineare Algebra, Analytische Geometrie und Kombinatorik

Inhalt

Für diese mathematischen Themenbereiche stehen hauptsächlich die Pakete linalg, geometry, geom3d und combinat zur Verfügung, welche alle vor ihrer Nutzung durch den Befehl with aktiviert werden müssen. Das Paket geom3d fehlt in Release 4, es steht aber im MapleArchive zum Download zur Verfügung.

Vektoren

evalm
linalg/add (R3)
linalg/angle
linalg/crossprod
linalg/dotprod
linalg/norm
linalg/normalize
linalg/scalarmul
linalg/vector

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 c2

Ein 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
                                 14

Winkel zweier Vektoren mit angle:

> angle(v1, v2);

                                 1/2 Pi

Die Radianten werden in Grad umgerechnet, v1 und v2 stehen aufeinander senkrecht:

> "*180/Pi; 

                                   90

normalize 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

linalg/add
linalg/addrow
linalg/augment
linalg/backsub
linalg/col
linalg/det
linalg/eigenvals
linalg/entermatrix
linalg/gausselim
linalg/genmatrix
linalg/inverse
linalg/linsolve
linalg/matrix
linalg/matrixplot
linalg/mulrow
linalg/multiply
linalg/rank
linalg/submatrix
linalg/swaprow
linalg/transpose

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 c

Den Rang einer Matrix ermittelt rank:

> rank(A);

                                   2

Die 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: Ein Beispiel für unendlich viele Lösungen:

> 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:

det(A - t*E) = 0

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, 1

oder ganz einfach durch:

> eigenvals(A);

                               0, 1, -2

Geometrie der Ebene

geometry/are_parallel
geometry/are_perpendicular
geometry/circle
geometry/coordinates
geometry/detailf
geometry/distance
geometry/inter
geometry/line
geometry/on_line
geometry/point

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);

                                   p2

Punkte, 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, 3


Da 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 = 0

Der 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)]); 

                                   g2

are_perpendicular prüft, ob zwei Geraden aufeinander senkrecht stehen, also orthogonal sind.

> are_perpendicular(g1, g2);

                                  true

Parallelität zweier Geraden:

> are_parallel(g1, g2);

                                 false

distance 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
                                 13

Zur Prüfung, ob ein Punkt (oder eine Liste von Punkten) auf einer Geraden liegt, nutzt man on_line.

> on_line(b1, g1);

                                  true

Geometrie des Raumes

geom3d/line3d
geom3d/plane
geom3d/point3d
geom3d/sphere

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]);

                                    c

Geraden 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]]);

                                 gerade1

Hinweis: 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]]);

                                 ebene2

Eine 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]]
           ])

Kombinatorik

combinat/bell
combinat/cartprod
combinat/choose
nops
combinat/numbcomb
combinat/numbpart
combinat/numbperm
combinat/partition
combinat/permute
combinat/stirling2

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("); 

                                    4

Fü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);

                                    6

Das 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);

                                    7

oder für n < k (immer gleich Null)

> stirling2(1, 2);

                                    0

Die Bell-Zahlen bn:

> bell(4);

                                    15

Fü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


last back next