home *** CD-ROM | disk | FTP | other *** search
- ;; Berechnung des Volumens konvexer Polytope
- ;; Bruno Haible 5.9.1990, 31.5.1991
-
- ;; Ein Polytop sei als konvexe Hülle endlich vieler Punkte (z.B. seiner Ecken)
- ;; gegeben. Es wird eine Triangulation und das Volumen berechnet.
-
- #|
- (require 'lgs_Q) ; Funktion solve-homLGS
- |#
- ;; Lösen linearer Gleichungssysteme über Q
- ;; Bruno Haible 25.4.1989
-
- ; Elimination:
- ; Löst ein homogenes LGS, d.h. bestimmt den Kern einer Matrix.
- ; > A: eine mxn-Matrix rationaler Zahlen
- ; < eine Liste der Basisvektoren des Kernes von A,
- ; das sind jeweils Vektoren der Länge n aus teilerfremden ganzen Zahlen
- ; < 2.Wert: Anzahl der eliminierten Zeilen (>=0, <=m)
- (defun solve-homLGS (A)
- (let ((m (array-dimension A 0))
- (n (array-dimension A 1)))
- ; A kopieren:
- (setq A
- (let ((B (make-array `(,m ,n))))
- (dotimes (i m) (dotimes (j n) (setf (aref B i j) (aref A i j))))
- B
- ) )
- (let ((spaltenabsätze nil) 2.Wert)
- ; A auf Treppennormalform bringen:
- (let ((i 0)) ; i = Zeile, ab der noch ausgeräumt werden muß
- (dotimes (j n) ; j = untersuchte Spalte
- ; Suche betragsgrößtes Element unterhalb (i,j):
- (let ((i0 nil))
- (do ((i1 i (1+ i1))
- (v 0))
- ((= i1 m))
- (if (> (abs (aref A i1 j)) v)
- (setq i0 i1 v (abs (aref A i1 j)))
- ) )
- ; i0 = Zeile des betragsgrößten Elements, oder
- ; i0 = nil falls alle fraglichen Elemente =0 sind.
- (if i0
- (progn
- ; Zeilen i und i0 vertauschen
- (unless (= i i0)
- (dotimes (j0 n) (rotatef (aref A i j0) (aref A i0 j0)))
- )
- ; Zeile i normalisieren
- (let ((x (/ (aref A i j))))
- (dotimes (j0 n) (setf (aref A i j0) (* (aref A i j0) x)))
- )
- ; Zeilen unterhalb von Zeile i ausräumen durch Subtraktion
- ; eines Vielfaches von Zeile i:
- (do ((i1 (1+ i) (1+ i1)))
- ((= i1 m))
- (let ((x (aref A i1 j)))
- (dotimes (j1 n)
- (setf (aref A i1 j1) (- (aref A i1 j1) (* x (aref A i j1))))
- ) ) )
- ; Spaltenabsatz
- (push i spaltenabsätze)
- (incf i)
- )
- (push nil spaltenabsätze)
- ) ) )
- (setq 2.Wert (- m i))
- )
- ; A hat Treppennormalform, z.B.:
- ; 1 .............
- ; 0 1 ...........
- ; 0 0 0 0 1 .....
- ; 0 0 0 0 0 0 0 0
- ; Dann enthält die Liste der Spaltenabsätze, in umgekehrter Reihenfolge:
- ; 0 1 n n 2 n n n
- ; (also die Zeilennummer beim Absatzanfang, n=NIL sonst)
- ; Nun den Kern aufbauen:
- (let ((Kern nil))
- (do ((j (1- n) (1- j))
- (L spaltenabsätze (cdr L)))
- ((< j 0))
- (if (car L)
- ; Spaltenabsatz in Spalte j
- (dolist (B Kern)
- (do ((i (car L))
- (s 0)
- (j1 (1+ j) (1+ j1)))
- ((= j1 n) (setf (aref B j) (- s)))
- (setq s (+ s (* (aref A i j1) (aref B j1))))
- ) )
- ; kein Spaltenabsatz in Spalte j
- (progn
- (dolist (B Kern) (setf (aref B j) 0)) ; Komponente j frei wählbar
- (let ((B (make-array n)))
- (setf (aref B j) 1)
- (do ((j1 (1+ j) (1+ j1)))
- ((= j1 n))
- (setf (aref B j1) 0)
- )
- (push B Kern) ; neues Basiselement #(..... 1 0 ... 0) im Kern
- ) ) ) )
- ; alle Vektoren des Kerns ganzzahlig und teilerfremd machen:
- (dolist (B Kern)
- (let ((nenner (do ((j 0 (1+ j))
- (x 1 (lcm x (denominator (aref B j)))))
- ((= j n) x)
- )) )
- (dotimes (j n) (setf (aref B j) (* (aref B j) nenner)))
- )
- (let ((faktor (do ((j 0 (1+ j))
- (x 0 (gcd x (aref B j))))
- ((= j n) x)
- )) )
- ; faktor /=0, da sonst B der Nullvektor wäre.
- (dotimes (j n) (setf (aref B j) (/ (aref B j) faktor)))
- ) )
- (values Kern 2.Wert)
- ) ) ) )
-
- ; Determinante:
- ; Bestimmt die Determinante einer quadratischen Matrix.
- ; > A: eine nxn-Matrix rationaler Zahlen
- ; < deren Determinante
- (defun det (A)
- (let ((n (array-dimension A 0)))
- (assert (= n (array-dimension A 1)))
- ; A kopieren:
- (setq A
- (let ((B (make-array `(,n ,n))))
- (dotimes (i n) (dotimes (j n) (setf (aref B i j) (aref A i j))))
- B
- ) )
- ; A auf Treppennormalform bringen:
- (let ((det 1)) ; det = bisherige Faktoren der Determinante
- (dotimes (i n) ; i = Zeile, ab der noch ausgeräumt werden muß
- (let ((j i)) ; j = untersuchte Spalte
- ; Suche betragsgrößtes Element unterhalb (i,j):
- (let ((i0 nil))
- (do ((i1 i (1+ i1))
- (v 0))
- ((= i1 n))
- (if (> (abs (aref A i1 j)) v)
- (setq i0 i1 v (abs (aref A i1 j)))
- ) )
- ; i0 = Zeile des betragsgrößten Elements, oder
- ; i0 = nil falls alle fraglichen Elemente =0 sind.
- (if i0
- (progn
- ; Zeilen i und i0 vertauschen
- (unless (= i i0)
- (dotimes (j0 n) (rotatef (aref A i j0) (aref A i0 j0)))
- (setq det (- det))
- )
- ; Zeile i normalisieren
- (let ((x (aref A i j)))
- (setq det (* det x))
- (setq x (/ x))
- (dotimes (j0 n) (setf (aref A i j0) (* (aref A i j0) x)))
- )
- ; Zeilen unterhalb von Zeile i ausräumen durch Subtraktion
- ; eines Vielfaches von Zeile i:
- (do ((i1 (1+ i) (1+ i1)))
- ((= i1 n))
- (let ((x (aref A i1 j)))
- (dotimes (j1 n)
- (setf (aref A i1 j1) (- (aref A i1 j1) (* x (aref A i j1))))
- ) ) ) )
- (return-from det 0)
- ) ) ) )
- det
- ) ) )
-
- (require 'simplex)
- ; Simplex-Algorithmus:
- ; Input: A, eine mxn-Matrix von Zahlen,
- ; b, ein m-Vektor von Zahlen,
- ; c, ein n-Vektor von Zahlen.
- ; Löst eine kanonische Optimierungsaufgabe :
- ; ( C ) Finde unter den y ∈ R^n mit A*y=b, y≥0 diejenigen mit <c,y> = Min
- ; ( C* ) Finde unter den z ∈ R^m mit x=A`*z+c≥0 diejenigen mit <b,z> = Min
- ; Siehe Koulikov, Algèbre et théorie des nombres, Chap. 6.1.
- ; Output: 1. Wert: ob lösbar, NIL oder T,
- ; falls lösbar:
- ; 2. Wert: Lösung von ( C ), dem LP: Liste, bestehend aus
- ; - der Lösung y
- ; - dem optimalen Wert von <c,y>
- ; 3. Wert: Lösung von ( C* ), dem Dualproblem DP: Liste, bestehend aus
- ; - der Lösung x
- ; - den konstanten Gliedern Z für die z's
- ; - den Abhängigkeiten ZZ zwischen den z's
- ; - dem optimalen Wert von <b,z>
- ; Die allgemeine Lösung ist so aufgebaut:
- ; Falls ZZ[i,i]=T, ist die Variable z_i frei wählbar.
- ; Sonst ist ZZ[i,i]=NIL, und die Variable z_i errechnet sich als
- ; z_i = Z[i] + Summe(j=1,...,m mit Z[j,j]=T , ZZ[i,j]*z_j) .
- ; 4. Wert: ob die angegebenen Lösungen die gesamte Lösungsmenge
- ; ausmachen (T) oder ob möglicherweise noch eine andere
- ; Lösung existiert.
- ; In jedem Fall ist die Lösungsmenge konvex.
-
- ;; Wir bewegen uns im R^d, d>=0. Ein Punkt ist ein Vektor aus seinen d
- ;; Koordinaten (rationale Zahlen).
-
- ; Gleichheit von Punkten:
- (defun punkt= (p1 p2)
- (equalp p1 p2) ; Vergleich aller Koordinaten
- )
-
- ;; Ein Simplex ist eine (ungeordnete) Liste von k Punkten, k>=1, deren
- ;; konvexe Hülle die Dimension k-1 hat.
-
- ; Dimension eines Simplex:
- (defun simplex-dim (simplex)
- (1- (length simplex))
- )
-
- ; Gleichheit von Simplizes:
- (defun simplex= (simplex1 simplex2)
- (and (= (simplex-dim simplex1) (simplex-dim simplex2)) ; müssen gleiche Dimension haben
- (dolist (punkt1 simplex1 t) ; und jede Ecke von simplex1
- (unless (position punkt1 simplex2 :test #'punkt=) ; muß auch Ecke von simplex2 sein
- (return nil)
- ) )
- ) )
-
- ; Bildet ein (k-1)-dimensionales Simplex aus k Punkten:
- (defun make-simplex (punkte)
- (if (endp punkte)
- (error "Zu wenig Punkte für ein Simplex.")
- (if ; Löse das LGS x1*p1 + ... + xk*pk = 0, x1+...+xk=0
- (let* ((d (length (first punkte)))
- (k (length punkte))
- (A (make-array (list (+ d 1) k))))
- ; LGS aufstellen:
- (dotimes (j k)
- (let ((punkt (elt punkte j)))
- (assert (= (length punkt) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- ; LGS lösen. Der Kern muß leer sein, also (p1,1), ..., (pk,1) linear
- ; unabhängig, also p1,...,pk affin unabhängig.
- (null (solve-homLGS A))
- )
- punkte
- (error "Punkte für ein Simplex sind affin abhängig: ~S" punkte)
- ) ) )
-
- ; Stellt fest, ob ein Punkt in der affinen Hülle eines Simplex liegt.
- (defun on-affine-p (punkt simplex)
- ; Löse das LGS x1*p1 + ... + xk*pk + x*p = 0, x1+...+xk+x=0
- (let* ((d (length punkt))
- (k (length simplex))
- (A (make-array (list (+ d 1) (+ k 1)))))
- ; LGS aufstellen:
- (dotimes (j k)
- (let ((punkt (elt simplex j)))
- (assert (= (length punkt) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- (dotimes (i d) (setf (aref A i k) (aref punkt i)))
- (setf (aref A d k) 1)
- ; LGS lösen:
- (let ((kern (solve-homLGS A)))
- (assert (<= (length kern) 1)) ; LGS durfte nicht mehrdeutig lösbar sein
- (not (endp kern)) ; falls es unlösbar war, liegt der Punkt nicht drin.
- ) ) )
-
- ; Stellt fest, ob zwei Punkte auf derselben Seite der affinen Hülle eines
- ; Simplex liegen.
- (defun on-same-side-p (punkt1 punkt2 simplex)
- ; Löse das LGS x1*p1 + ... + xk*pk + y1*punkt1 + y2*punkt2 = 0, x1+...+xk+y1+y2=0
- (let* ((d (length punkt1))
- (k (length simplex))
- (A (make-array (list (+ d 1) (+ k 2)))))
- ; LGS aufstellen:
- (dotimes (j k)
- (let ((punkt (elt simplex j)))
- (assert (= (length punkt) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- (let ((j k))
- (assert (= (length punkt1) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt1 i)))
- (setf (aref A d j) 1)
- )
- (let ((j (+ k 1)))
- (assert (= (length punkt2) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt2 i)))
- (setf (aref A d j) 1)
- )
- ; LGS lösen:
- (let ((kern (solve-homLGS A)))
- (ecase (length kern)
- (0 (error "Simplex und zwei Punkte sind windschief."))
- (1 (let ((lsg (first kern))) ; Lösungvektor #(x1 ... xk y1 y2)
- ; y1*y2>0 -> eine echte Konvexkombination von punkt1 und punkt2
- ; liegt in der Ebene, also liegen die Punkte in
- ; verschiedenen Halbebenen der Ebene.
- (<= (* (signum (aref lsg k)) (signum (aref lsg (+ k 1)))) 0)
- ) )
- (2 t) ; beide Punkte liegen in der affinen Hülle des Simplex
- ) ) ) )
-
- ; Liefert den Mittelpunkt eines Simplex:
- (defun simplex-mittelpunkt (simplex)
- (let ((k (length simplex))) ; Anzahl der Punkte
- (map 'vector #'(lambda (x) (/ x k)) ; durch sie dividieren, nachdem man
- (apply #'map 'vector #'+ simplex) ; alle Koordinaten addiert hat
- ) ) )
-
- ; Liefert das Volumen eines Simplex der Dimension d:
- (defun simplex-vol (simplex)
- (let* ((d (length (first simplex)))
- (d+1 (+ d 1)))
- (if (= (length simplex) d+1)
- ; volldimensionaler Simplex conv({p0,...,pd}) hat Volumen
- ; 1 | p00 ... p0d 1 |
- ; --- abs det | ............. |
- ; d ! | pd0 ... pdd 1 |
- (let ((A (make-array (list d+1 d+1))))
- (dotimes (i d+1)
- (let ((punkt (elt simplex i)))
- (dotimes (j d) (setf (aref A i j) (aref punkt j)))
- (setf (aref A i d) 1)
- ) )
- (/ (abs (det A)) (! d))
- )
- ; niederdimensionaler Simplex hat d-Volumen 0
- 0
- ) ) )
-
- ; Stellt fest, ob ein Punkt in einem Simplex liegt.
- (defun on-simplex-p (punkt simplex)
- ; Löse das LGS x1*p1 + ... + xk*pk + x*p = 0, x1+...+xk+x=0
- (let* ((d (length punkt))
- (k (length simplex))
- (A (make-array (list (+ d 1) (+ k 1)))))
- ; LGS aufstellen:
- (dotimes (j k)
- (let ((punkt (elt simplex j)))
- (assert (= (length punkt) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- (dotimes (i d) (setf (aref A i k) (aref punkt i)))
- (setf (aref A d k) 1)
- ; LGS lösen:
- (let ((kern (solve-homLGS A)))
- (assert (<= (length kern) 1)) ; LGS durfte nicht mehrdeutig lösbar sein
- (if (endp kern) ; falls es unlösbar war, liegt der Punkt nicht drin.
- nil
- (let ((lsg (first kern)))
- ; x auf -1 normieren:
- (let ((-x (- (aref lsg k))))
- (dotimes (j k) (setf (aref lsg j) (/ (aref lsg j) -x)))
- )
- ; Nun ist x1*p1 + ... + xk*pk = p .
- ; Falls hierbei alle xi>=0 sind, liegt p im Simplex.
- (dotimes (j k t)
- (unless (>= (aref lsg j) 0) (return nil))
- )
- ) ) ) ) )
-
- ; Stellt fest, ob ein Punkt im Innern eines Simplex liegt.
- (defun in-simplex-p (punkt simplex)
- ; Löse das LGS x1*p1 + ... + xk*pk + x*p = 0, x1+...+xk+x=0
- (let* ((d (length punkt))
- (k (length simplex))
- (A (make-array (list (+ d 1) (+ k 1)))))
- ; LGS aufstellen:
- (dotimes (j k)
- (let ((punkt (elt simplex j)))
- (assert (= (length punkt) d))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- (dotimes (i d) (setf (aref A i k) (aref punkt i)))
- (setf (aref A d k) 1)
- ; LGS lösen:
- (let ((kern (solve-homLGS A)))
- (assert (<= (length kern) 1)) ; LGS durfte nicht mehrdeutig lösbar sein
- (if (endp kern) ; falls es unlösbar war, liegt der Punkt nicht drin.
- nil
- (let ((lsg (first kern)))
- ; x auf -1 normieren:
- (let ((-x (- (aref lsg k))))
- (dotimes (j k) (setf (aref lsg j) (/ (aref lsg j) -x)))
- )
- ; Nun ist x1*p1 + ... + xk*pk = p .
- ; Falls hierbei alle xi>0 sind, liegt p im Innern des Simplex.
- (dotimes (j k t)
- (unless (> (aref lsg j) 0) (return nil))
- )
- ) ) ) ) )
-
- ;; Eine Triangulation eines Polytops P der Dimension k ist eine Liste von
- ;; Simplizes der Dimension k, deren Vereinigung = P und deren paarweiser
- ;; Durchschnitt jeweils höchstens (k-1)-dimensional ist.
- ;; Ein allgemeines Polytop wird als Eckenliste und als Triangulation
- ;; dargestellt.
-
- (defstruct (polytop (:type list))
- (ecken nil :type list)
- (triang nil :type list)
- )
-
- ; Dimension eines Polytops:
- (defun polytop-dim (polytop)
- (let ((triang (polytop-triang polytop)))
- (if (endp triang)
- -1 ; leeres Polytop hat Dimension -1
- (simplex-dim (first triang)) ; sonst die Dimension aller Simplizes
- ) ) )
-
- ; Simplex als Polytop:
- (defun simplex-polytop (simplex)
- (make-polytop :ecken simplex
- :triang (list simplex) ; Triangulation besteht als dem Simplex selbst
- ) )
-
- ; Stellt fest, ob ein Punkt in der konvexen Hülle einer Punktmenge liegt.
- (defun on-conv-p (punkt punkte)
- ; Läßt sich der Punkt aus den "Ecken" konvex kombinieren?
- ; Simplex-Algorithmus anwenden:
- (let* ((d (length punkt))
- (m (1+ d))
- (n (length punkte))
- (A (make-array `(,m ,n)))
- (b (make-array m))
- (c (make-array n :initial-element 0)))
- (dotimes (j n)
- (let ((punkt (pop punkte)))
- (dotimes (i d) (setf (aref A i j) (aref punkt i)))
- (setf (aref A d j) 1)
- ) )
- (dotimes (i d) (setf (aref b i) (aref punkt i)))
- (setf (aref b d) 1)
- (values (simplex A b c))
- ) )
-
- ; Stellt fest, ob ein Punkt in einem Polytop liegt.
- (defun on-polytop-p (punkt polytop)
- ; Läßt sich der Punkt aus den Ecken konvex kombinieren?
- (on-conv-p punkt (polytop-ecken polytop))
- )
-
- ; Liefert zu einem Polytop der Dimension k eine Liste aller Randsimplizes,
- ; alle derselben Dimension k-1.
- (defun simplex-rand (simplex)
- (if (zerop (simplex-dim simplex)) ; Hat Dimension 0 ?
- nil ; Rand ist leer
- ; P = conv{p0,...,pk} mit k>0 -> Die Randsimplizes sind die Simplizes
- ; conv{p0,...,pj-1,pj+1,...,pk} (pj fehlt) für j=0,...,k.
- (let ((rand nil))
- (do ((L1 nil (cons (car L2) L1))
- (L2 simplex (cdr L2)))
- ((endp L2))
- (push (revappend L1 (cdr L2)) rand)
- )
- (nreverse rand)
- ) ) )
-
- ; Liefert zu einer Triangulation eines Polytops eine Liste der Randsimplizes.
- ; Sie haben alle eine um 1 geringere Dimension als das Polytop selbst.
- (defun triang-rand (triang)
- ; Der Rand setzt sich zusammen aus den Randsimplizes der Triangulierung.
- ; Solche Randsimplizes, die dabei doppelt vorkommen, liegen im Innern des
- ; Polytops und werden daher gestrichen.
- (let ((rand nil))
- (dolist (simplex triang)
- (let ((rand-neu (simplex-rand simplex)))
- (dolist (rand-simplex rand-neu)
- (if (member rand-simplex rand :test #'simplex=)
- (setq rand (delete rand-simplex rand :test #'simplex=))
- (setq rand (cons rand-simplex rand))
- ) ) ) )
- (nreverse rand)
- ) )
-
- ; Stellt fest, ob ein Punkt im Innern eines Polytops liegt.
- (defun in-polytop-p (punkt polytop)
- ; Liegt der Punkt im Polytop, aber nicht auf dem Rand?
- (and (on-polytop-p punkt polytop)
- (not (some #'(lambda (randsimplex) (on-simplex-p punkt randsimplex))
- (triang-rand (polytop-triang polytop))
- ) ) ) )
-
- ; Liefert die Liste der Ecken der konvexen Hülle von endlich vielen Punkten.
- (defun conv-ecken (punkte)
- (setq punkte (remove-duplicates punkte :test #'punkt=))
- (remove-if
- #'(lambda (punkt)
- (on-conv-p punkt (remove punkt punkte :test #'punkt=))
- )
- punkte
- ) )
-
- ; Liefert die konvexe Hülle einer Liste von Punkten als Polytop.
- (defun conv (punkte)
- (setq punkte (conv-ecken punkte)) ; unnötige Punkte streichen
- (make-polytop
- :ecken punkte
- :triang
- ; Triangulation durch schrittweise Erweiterung um je einen der Punkte
- ; gewinnen:
- (let ((triang nil)) ; leere Triangulation
- (dolist (punkt punkte)
- (setq triang
- ; punkt zu triang dazunehmen:
- (if (endp triang) ; Polytop leer?
- (list (make-simplex (list punkt))) ; gibt einpunktiges Polytop
- ; liegt der Punkt in der affinen Hülle des Polytops (= der affinen
- ; Hülle eines beliebigen Simplex der Triangulation) ?
- (if (on-affine-p punkt (first triang))
- ; Dimension vergrößert sich nicht: Bilde die Randsimplizes des Polytops,
- ; die den Punkt vom Polytop trennen, und verbinde sie jeweils mit dem
- ; Punkt. Diese neuen Simplizes kommen zur Triangulation dazu.
- (let ((einpunkt (simplex-mittelpunkt (first triang))) ; Ein Punkt im Polytop
- (neue-simplizes nil))
- (dolist (rand (triang-rand triang))
- (unless (on-same-side-p punkt einpunkt rand)
- (push (make-simplex (cons punkt rand)) neue-simplizes)
- ) )
- (append triang (nreverse neue-simplizes))
- )
- ; Dimension vergrößert sich um 1: Verbinde den Punkt mit allen
- ; Simplizes des Polytops. Dies liefert die neue Triangulation.
- (mapcar #'(lambda (simplex) (make-simplex (cons punkt simplex))) triang)
- ) ) ) )
- triang
- ) ) )
-
- ; Liefert das Volumen (der Dimension d) eines Polytops.
- (defun polytop-vol (polytop)
- (apply #'+ (mapcar #'simplex-vol (polytop-triang polytop)))
- )
-
-
- ;; Beispiel: Hn(r) bei festem n.
- ;; Ecken sind die n! Permutationsmatrizen, aufgefaßt im R^(n^2), durch
- ;; Weglassen der rechten und unteren Spalte projiziert in den R^((n-1)^2).
-
- ; Permutation von {0,...,n-1} in Punkt umwandeln:
- (defun perm-als-punkt (perm)
- (let* ((n (length perm))
- (n-1 (- n 1))
- (A (make-array `(,n-1 ,n-1) :initial-element 0))
- (p (make-array (* n-1 n-1) :displaced-to A)))
- (dotimes (i n)
- (let ((j (elt perm i)))
- (when (array-in-bounds-p A i j)
- (setf (aref A i j) 1)
- ) ) )
- p
- ) )
-
- ; Liste aller Permutationen von {0,...,n-1} produzieren:
- (defun alle-perm (n)
- (if (zerop n)
- (list '())
- (let ((perm_n-1 (alle-perm (- n 1)))
- (perm_n nil))
- ; produziere die Permutationen von {0,...,n-1} aus denen von {0,...,n-2}:
- ; (n-1)-Liste unverändert. Vorne n-1 anfügen.
- ; In der (n-1)-Liste alle n-2 in n-1 umwandeln. Vorne n-2 anfügen.
- ; In der (n-1)-Liste alle n-3 in n-2 umwandeln. Vorne n-3 anfügen.
- ; ...
- ; In der (n-1)-Liste alle 0 in 1 umwandeln. Vorne 0 anfügen.
- (let ((i (- n 1)))
- (loop
- (setq perm_n
- (append (mapcar #'(lambda (p_n-1) (cons i p_n-1)) perm_n-1)
- perm_n
- ) )
- (when (zerop i) (return))
- (decf i)
- (setq perm_n-1 (subst (+ i 1) i perm_n-1))
- ) )
- perm_n
- ) ) )
-
- (defun H-ecken (n) (mapcar #'perm-als-punkt (alle-perm n)))
- ; n=1
- (setq H1 (conv (H-ecken 1)))
- ; n=2
- (setq H2 (conv (H-ecken 2)))
- ; n=3
- (setq H3 (conv (H-ecken 3)))
-
-