From a8f4d14f46110c12a9203fe547b5d608a2c6c75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Cuevas-Rozo?= Date: Mon, 15 Jul 2019 19:37:59 +0200 Subject: [PATCH] Function 'terme' in 'homology-groups' modified. Files 'finite-topological-spaces-aux.lisp' and 'finite-topological-spaces-class.lisp' added. --- kenzo.asd | 4 +- src/finite-topological-spaces-aux.lisp | 241 ++++++++++++ src/finite-topological-spaces-class.lisp | 450 +++++++++++++++++++++++ src/homology-groups.lisp | 4 +- src/kenzo.fas | Bin 0 -> 63208 bytes 5 files changed, 696 insertions(+), 3 deletions(-) create mode 100644 src/finite-topological-spaces-aux.lisp create mode 100644 src/finite-topological-spaces-class.lisp create mode 100755 src/kenzo.fas diff --git a/kenzo.asd b/kenzo.asd index 3237f25..f185647 100644 --- a/kenzo.asd +++ b/kenzo.asd @@ -57,7 +57,9 @@ (:file "cl-space-efhm") (:file "whitehead") (:file "smith") - (:file "sage-interface") + (:file "sage-interface") + (:file "finite-topological-spaces-aux") + (:file "finite-topological-spaces-class") (:module "anromero" :components ((:file "resolutions") diff --git a/src/finite-topological-spaces-aux.lisp b/src/finite-topological-spaces-aux.lisp new file mode 100644 index 0000000..a683f4e --- /dev/null +++ b/src/finite-topological-spaces-aux.lisp @@ -0,0 +1,241 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -* + +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES + +(IN-PACKAGE #:cat) + +(PROVIDE "finite-topological-spaces-aux") + +;; +;; Auxiliary functions (most of them in 'NewSmith') +;; + + +(DEFUN MAJTERME (pl pc val) + #| Same 'maj-terme' but changing '=' by 'eq' |# + (if (eq val 0) + (if (eq (left pl) (up pc)) (supprimer-terme pl pc)) + (if (eq (left pl) (up pc)) + (setf (val (left pl)) val) + (inserer-terme pl pc val)))) + + +(DEFUN EQUALMATRIX (mtrx1 mtrx2) + #| Same 'equal-matrix' but changing 'line-number' by 'nlig' and 'column-number' by 'ncol' |# + (declare (type matrice mtrx1 mtrx2)) + (the boolean + (let ((line-number (nlig mtrx1))) + (declare (type fixnum line-number)) + (unless (eql line-number (nlig mtrx2)) + (return-from equalmatrix +false+)) + (unless (eql (ncol mtrx1) (ncol mtrx2)) + (return-from equalmatrix +false+)) + (do ((il 1 (1+ il))) + ((> il line-number)) + (declare (type fixnum il)) + (let ((p10 (baselig mtrx1 il)) + (p20 (baselig mtrx2 il))) + (declare (type t-mat p10 p20)) + (do ((p1 (left p10) (left p1)) + (p2 (left p20) (left p2))) + (nil) + (declare (type t-mat p1 p2)) + (when (eq p1 p10) + (unless (eq p2 p20) + (return-from equalmatrix +false+)) + (return)) + (when (eq p2 p20) + (unless (eq p1 p10) + (return-from equalmatrix +false+))) + (unless (eql (icol p1) (icol p2)) + (return-from equalmatrix +false+)) + (unless (eql (val p1) (val p2)) + (return-from equalmatrix +false+))))) + (return-from equalmatrix +true+)))) + + +(DEFUN MTRX-PRDC (mtrx1 mtrx2) + #| Same 'mtrx-prdc' but changing 'line-number' by 'nlig' and 'column-number' by 'ncol' |# + (declare (type matrice mtrx1 mtrx2)) + (the matrice + (let ((nl (nlig mtrx1)) + (nc (ncol mtrx2)) + (n (ncol mtrx1))) + (declare (type fixnum nl nc n)) + (assert (eql n (nlig mtrx2))) + (let ((rslt (creer-matrice nl nc))) + (declare (type matrice rslt)) + (do ((il 1 (1+ il))) + ((> il nl)) + (declare (type fixnum il)) + (do ((pl01 (baselig mtrx1 il)) + (pl0r (baselig rslt il)) + (ic 1 (1+ ic))) + ((> ic nc)) + (declare (type t-mat pl01 pl0r) (type fixnum ic)) + (let ((pl (left pl01)) + (pc (up (basecol mtrx2 ic))) + (sum 0)) + (declare (type t-mat pl pc) (type fixnum sum)) + (loop + (let ((ilic (icol pl)) + (icil (ilig pc))) + (declare (type fixnum ilic icil)) + (when (zerop ilic) (return)) + (when (zerop icil) (return)) + (cond ((eql ilic icil) + (incf sum (safe-* (val pl) (val pc))) + (setf pl (left pl) pc (up pc))) + ((> ilic icil) + (setf pl (left pl))) + (t + (setf pc (up pc)))))) + (unless (zerop sum) + (inserer-terme pl0r (basecol rslt ic) sum))))) + rslt)))) + + +(DEFUN SAFE-* (arg1 arg2) + #| This is in 'NewSmith' |# + (declare (type fixnum arg1 arg2)) + (let ((rslt (* arg1 arg2))) + (declare (type integer rslt)) + (if (typep rslt 'fixnum) + rslt + (error "Fixnum-overflow in (safe-* ~D ~D)." arg1 arg2)))) + + +(DEFUN SAFE-+ (arg1 arg2) + #| This is in 'NewSmith' |# + (declare (type fixnum arg1 arg2)) + (let ((rslt (+ arg1 arg2))) + (declare (type integer rslt)) + (if (typep rslt 'fixnum) + rslt + (error "Fixnum-overflow in (safe-+ ~D ~D)." arg1 arg2)))) + + +(DEFUN SAFE-- (arg) + #| This is in 'NewSmith' |# + (declare (type fixnum arg)) + (let ((rslt (- arg))) + (declare (type integer rslt)) + (if (typep rslt 'fixnum) + rslt + (error "Fixnum-overflow in (SAFE-- ~D)." arg)))) + + +(DEFUN 0NEW-COLUMN (mtrx icol list) + #| This is 'new-column' in 'NewSmith' |# + (declare (type matrice mtrx) (type fixnum icol) (type list list)) + (the matrice + (let ((peigne (peigne-hor mtrx (baselig mtrx 0) icol)) + (pc0 (basecol mtrx icol))) + (declare (type list peigne) (type t-mat pc0)) + (map nil #'(lambda (item) + (declare (type t-mat item)) + (when (eq (up pc0) (left item)) + (supprimer-terme item pc0))) + peigne) + (do ((markp (nreverse peigne) (cdr markp)) + (ilig 1 (1+ ilig)) + (markc list)) + ((endp markc)) + (declare (type list markp markc) (type fixnum ilig)) + (when (eql (caar markc) ilig) + (inserer-terme (car markp) pc0 (cadar markc)) + (setf markc (cdr markc)))) + mtrx))) + + +(DEFUN 0COLUMN-OP (mtrx lambda icol1 icol2) + #| This is 'column-op' in 'NewSmith' |# + (declare + (type matrice mtrx) + (type fixnum lambda icol1 icol2)) + (the matrice + (let ((mark1 (extract-column mtrx icol1)) + (mark2 (extract-column mtrx icol2)) + (new-column2 +empty-list+)) + (declare (type list mark1 mark2 new-column2)) + (loop + (when (endp mark1) + (setf new-column2 (nreconc new-column2 mark2)) + (return)) + (when (endp mark2) + (setf new-column2 + (nreconc new-column2 + (mapcar #'(lambda (item) + (declare (type list item)) + (list (first item) + (safe-* lambda (second item)))) + mark1))) + (return)) + (let ((ilig1 (caar mark1)) + (ilig2 (caar mark2))) + (declare (type fixnum ilig1 ilig2)) + (cond ((< ilig1 ilig2) + (push (list ilig1 (safe-* lambda (second (pop mark1)))) + new-column2)) + ((> ilig1 ilig2) + (push (list ilig2 (second (pop mark2))) new-column2)) + (t (let ((new-val (safe-+ (safe-* lambda (second (pop mark1))) + (second (pop mark2))))) + (declare (type fixnum new-val)) + (unless (zerop new-val) + (push (list ilig1 new-val) new-column2))))))) + (0new-column mtrx icol2 new-column2) + mtrx))) + + +(DEFUN 0COLUMN-SWAP (mtrx icol1 icol2) + #| This is 'column-swap' in 'NewSmith' |# + (declare + (type matrice mtrx) (type fixnum icol1 icol2)) + (the matrice + (let ((new-column1 (extract-column mtrx icol2)) + (new-column2 (extract-column mtrx icol1))) + (declare (type list new-column1 new-column2)) + (0new-column mtrx icol1 new-column1) + (0new-column mtrx icol2 new-column2) + mtrx))) + + +(DEFUN 0COLUMN-MINUS (mtrx icol) + #| This is 'column-minus' in 'NewSmith' |# + (declare (type matrice mtrx) (type fixnum icol)) + (the matrice + (0new-column mtrx icol + (mapcar #'(lambda (item) + (declare (type list item)) + (the list + (list (first item) + (safe-- (second item))))) + (extract-column mtrx icol))))) + + +(DEFUN EXTRACT-COLUMN (mtrx icol) + #| This is in 'NewSmith' |# + (declare (type matrice mtrx) (type fixnum icol)) + (the list + (let ((pc0 (basecol mtrx icol))) + (declare (type t-mat pc0)) + (do ((pc (up pc0) (up pc)) + (rslt +empty-list+ (cons (list (ilig pc) (val pc)) rslt))) + ((eq pc pc0) rslt) + (declare (type t-mat pc) (type list rslt)))))) + + +(DEFUN EXTRACT-LINE (mtrx ilig) + #| This is in 'NewSmith' |# + (declare (type matrice mtrx) (type fixnum ilig)) + (the list + (let ((pl0 (baselig mtrx ilig))) + (declare (type t-mat pl0)) + (do ((pl (left pl0) (left pl)) + (rslt +empty-list+ (cons (list (icol pl) (val pl)) rslt))) + ((eq pl pl0) rslt) + (declare (type t-mat pl) (type list rslt)))))) + diff --git a/src/finite-topological-spaces-class.lisp b/src/finite-topological-spaces-class.lisp new file mode 100644 index 0000000..973c130 --- /dev/null +++ b/src/finite-topological-spaces-class.lisp @@ -0,0 +1,450 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -* + +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES +;; FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES FINITE-TOPOLOGICAL-SPACES + +(IN-PACKAGE #:cat) + +(PROVIDE "finite-topological-spaces-class") + +;; +;; Finite topological spaces +;; + + +(DEFMACRO INSERT-TERM (mat ilig icol val) + #| Insert the value 'val' in the ('ilig' 'icol')-entry of 'mat' |# + `(majterme (chercher-hor (baselig ,mat ,ilig) ,icol) + (chercher-ver (basecol ,mat ,icol) ,ilig) + ,val)) + + +(DEFUN CONVERTARRAY (array) + #| Convert an 'array' to a 'matrice' |# + (let* ((numfil (array-dimension array 0)) + (numcol (array-dimension array 1)) + (rslt (creer-matrice numfil numcol))) + (dotimes (j numcol) + (dotimes (i numfil) + (insert-term rslt (1+ i) (1+ j) (aref array i j)))) + rslt)) + + +(DEFUN CONVERTMATRICE (matrice) + #| Convert a 'matrice' to an 'array' |# + (let* ((numfil (nlig matrice)) + (numcol (ncol matrice)) + (rslt (make-array (list numfil numcol) :initial-element 0))) + (dotimes (i numfil) + (dotimes (j numcol) + (let ((Mij (terme matrice (1+ i) (1+ j)))) + (unless (zerop Mij) + (setf (aref rslt i j) Mij))))) + rslt)) + + +(DEFUN VER (matrix) + (let ((mat '())) + (typecase matrix + (matrice (setf mat matrix)) + (T (setf mat (convertarray matrix)))) + (format t "~%") + (format t " ========== MATRIX ~A row(s) + ~A column(s) ==========~%~%" (nlig mat) (ncol mat)) + (do ((i 1 (1+ i))) ((> i (nlig mat))) + (format t " ") + (do ((j 1 (1+ j))) ((> j (ncol mat))) + (if (< (terme mat i j) 0) + (format t " ~A " (terme mat i j)) + (format t " ~A " (terme mat i j)))) + (format t " ~%")))) + + +(DEFUN EXTRACT-COLUMN2 (mtrx icol list) + #| Modification of 'EXTRACT-COLUMN' in order to extract only the elements in the column 'icol' whose row indexes are in the list 'list' |# + (declare (type matrice mtrx) (type fixnum icol) (type list list)) + (the list + (let ((pc0 (basecol mtrx icol)) + (lst list)) + (declare (type t-mat pc0)) + (do ((pc (up pc0) (up pc)) + (rslt +empty-list+ (if (find (ilig pc) lst) + (progn + (setf lst (remove (ilig pc) lst)) + (cons (list (ilig pc) (val pc)) rslt)) + rslt))) + ((eq pc pc0) rslt) + (declare (type t-mat pc) (type list rslt)))))) + + +(DEFUN SUBMATRIX (mtrx rows cols) + #| Extract the submatrix of 'mtrx' formed by the rows whose indexes are in 'rows' and the columns whose indexes are in 'cols' |# + (declare (type matrice mtrx) + (type list rows cols)) + (let ((rslt (creer-matrice (length rows) (length cols)))) + (do ((k 1 (1+ k)) + (columnas cols (cdr columnas))) + ((endp columnas) rslt) + (0new-column rslt k (let ((valor NIL)) + (do ((j (length rows) (1- j)) + (rslt2 +empty-list+ (if (setf valor (second (find (nth (1- j) rows) (extract-column2 mtrx (car columnas) rows) :key #'first))) + (cons (list j valor) rslt2) + rslt2))) + ((< j 1) rslt2))))))) + + +(DEFUN NILPOT (matrix) + (declare (type matrice matrix)) + (let ((rslt (copier-matrice matrix))) + (loop for k from 1 to (nlig rslt) + do (insert-term rslt k k 0)) + rslt)) + + +(DEFUN NILPOT-1 (matrix) + (declare (type matrice matrix)) + (let ((rslt (copier-matrice matrix))) + (loop for k from 1 to (nlig rslt) + do (insert-term rslt k k 1)) + rslt)) + + +(DEFUN ADD-ROWS (matrice pos num) + #| Add 'num' rows from position 'pos' |# + (let ((rslt (creer-matrice (+ (n-lig matrice) num) (n-col matrice)))) + (do ((i 1 (1+ i))) + ((eq i pos)) + (do ((ptl1 (baselig matrice i)) + (pl1 (left (baselig matrice i)) (left pl1)) + (pl2 (baselig rslt i) (left pl2))) + ((eq pl1 ptl1)) + (inserer-terme pl2 (basecol rslt (icol pl1)) (val pl1)))) + + (do ((i pos (1+ i))) + ((> i (n-lig matrice)) rslt) + (do ((ptl1 (baselig matrice i)) + (pl1 (left (baselig matrice i)) (left pl1)) + (pl2 (baselig rslt (+ i num)) (left pl2))) + ((eq pl1 ptl1)) + (inserer-terme pl2 (basecol rslt (icol pl1)) (val pl1)))))) + + +(DEFUN ADD-COLS (matrice pos num) + #| Add 'num' columns from position 'pos' |# + (let ((rslt (creer-matrice (n-lig matrice) (+ (n-col matrice) num)))) + (do ((i 1 (1+ i))) + ((eq i pos)) + (do ((ptc1 (basecol matrice i)) + (pc1 (up (basecol matrice i)) (up pc1)) + (pc2 (basecol rslt i) (up pc2))) + ((eq pc1 ptc1)) + (inserer-terme (baselig rslt (ilig pc1)) pc2 (val pc1)))) + + (do ((i pos (1+ i))) + ((> i (n-col matrice)) rslt) + (do ((ptc1 (basecol matrice i)) + (pc1 (up (basecol matrice i)) (up pc1)) + (pc2 (basecol rslt (+ i num)) (up pc2))) + ((eq pc1 ptc1)) + (inserer-terme (baselig rslt (ilig pc1)) pc2 (val pc1)))))) + + +(DEFMACRO ADD-POINTS (matrice pos num) + #| Add 'num' points from position 'pos' |# + `(add-cols (add-rows ,matrice ,pos ,num) ,pos ,num)) + + +(DEFUN STONGMAT (topogenous) + #| Stong matrice from the topogenous matrice 'topogenous' |# + (declare (type matrice topogenous)) + (let* ((dim (nlig topogenous)) + (rslt (identite dim))) + (declare (type fixnum dim)) + (if (or (eq dim 1) (eq dim 2)) + (return-from stongmat topogenous) + + (do ((i 1 (1+ i))) ((> i dim) rslt) + (do ((j (1+ i) (1+ j))) ((> j dim)) + (cond ((eq j (1+ i)) (insert-term rslt i j (terme topogenous i j))) + ((eq (terme topogenous i j) 0)) + (T (let ((parada 0)) + (do ((k (1+ i) (1+ k))) ((or (> k (1- j)) (eq parada 1))) + (cond ((and (eq (terme topogenous i k) 1) (eq (terme topogenous k j) 1)) (setf parada 1)) + ((and (eq k (1- j)) (eq parada 0)) (insert-term rslt i j 1)))))))))))) + + +(DEFUN TOPMAT (stong) + #| Topogenous matrice from the Stong matrice 'stong' |# + (declare (type matrice stong)) + (let* ((dim (nlig stong)) + (rslt (identite dim))) + (declare (type fixnum dim)) + (if (or (eq dim 1) (eq dim 2)) + (return-from topmat stong) + + (do ((k 2 (1+ k))) ((> k dim) rslt) + (if (eq k 2) + (do ((i 1 (1+ i))) ((> i (1- dim))) + (insert-term rslt i (1+ i) (terme stong i (1+ i)))) + + (do ((i 1 (1+ i))) ((> i (1+ (- dim k)))) + + (if (eq (terme stong i (1- (+ i k))) 1) + (insert-term rslt i (1- (+ i k)) 1) + + (if (eq (let ((indicator 0)) + (do ((r (1+ i) (1+ r))) ((or (> r (- (+ i k) 2)) (eq indicator 1))) + (if (and (eq (terme rslt i r) 1) (eq (terme rslt r (1- (+ i k))) 1)) + (setf indicator 1))) indicator) 1) + (insert-term rslt i (1- (+ i k)) 1))))))))) + + +(DEFUN RANDOMTOP (dim dens) + #| A 'dim' x 'dim' random topogenous matrice |# + (declare (fixnum dim)) + (let ((limite (truncate (/ (* dens (- dim 2) (- dim 1)) 2))) + (rslt (identite dim)) + (contador 1) + (base (make-array dim))) + (unless (= dim 1) + (do () ((> contador limite)) + (let* ((j1 (1+ (random (1- dim)))) + (i1 (random j1))) + (if (find i1 (aref base j1)) + (incf contador) ; Avoiding an infinite loop... + (progn + (push i1 (aref base j1)) + (setf (aref base j1) (union (aref base j1) (aref base i1))) + (loop for k in (>a-b< j1 dim) + if (find j1 (aref base k)) + do (and (pushnew i1 (aref base k)) + (setf (aref base k) (union (aref base k) (aref base i1))) ; Improve... + (incf contador))))))) + (loop for j in ( 1 (ncol stong)))) + + +(DEFCLASS FINITE-SPACE () + ;; TOPogenous matrix + ((top :type matrice :initarg :top :reader top) + ;; STONG matrix + (stong :type matrice :initarg :stong :reader stong) + ;; HEIGHTS + (heights :type list :initarg :heights :reader heights) + ;; IDentification NuMber + (idnm :type fixnum :initform (incf *idnm-counter*) :reader idnm) + ;; ORiGiN + (orgn :type list :initarg :orgn :reader orgn))) + + +(DEFMETHOD SLOT-UNBOUND (class (finspace finite-space) (slot-name (eql 'heights))) + (declare (ignore class)) + (the list + (setf (slot-value finspace 'heights) (heights (stong finspace))))) + + +(DEFMETHOD SLOT-UNBOUND (class (finspace finite-space) (slot-name (eql 'top))) + (declare (ignore class)) + (the matrice + (setf (slot-value finspace 'top) (topmat (stong finspace))))) + + +(DEFMETHOD SLOT-UNBOUND (class (finspace finite-space) (slot-name (eql 'stong))) + (declare (ignore class)) + (the matrice + (setf (slot-value finspace 'stong) (stongmat (top finspace))))) + + +(DEFMETHOD SLOT-UNBOUND (class (finspace finite-space) (slot-name (eql 'orgn))) + (declare (ignore class)) + (the list + (setf (slot-value finspace 'orgn) `(FINITE-SPACE ,(idnm finspace))))) ;(1+ *idnm-counter*) + + +(DEFMETHOD INITIALIZE-INSTANCE :after ((finspace FINITE-SPACE) &rest rest) + (set (intern (format nil "K~D" (idnm finspace))) finspace)) + + +(DEFVAR *FINITE-SPACE-LIST*) +(SETF *FINITE-SPACE-LIST* +empty-list+) +(PUSHNEW '*FINITE-SPACE-LIST* *list-list*) + + +(DEFMETHOD PRINT-OBJECT ((finspace finite-space) stream) + (the finite-space + (progn + (format stream "[K~D Finite-Space]" (idnm finspace)) + finspace))) + + +(DEFUN BUILD-FINITE-SPACE (&key top stong heights orgn) + (the finite-space + (progn + (let ((already (find orgn *finite-space-list* :test #'equal :key #'orgn))) + (declare (type (or finite-space null) already)) + (when already + (return-from build-finite-space already))) + (let ((finspace (make-instance 'finite-space))) + (declare (type finite-space finspace)) + (if top (setf (slot-value finspace 'top) top)) + (if stong (setf (slot-value finspace 'stong) stong)) + (if heights (setf (slot-value finspace 'heights) heights)) + (if orgn (setf (slot-value finspace 'orgn) orgn)) + (push finspace *finite-space-list*) + finspace)))) + + +(DEFUN TOPOLOGY (dmns dens) + #| Random Finite-Space of size 'dmns' and density 'dens' |# + (declare (fixnum dmns)) + (unless (plusp dmns) + (error "In TOPOLOGY, the dimension ~D should be positive." dmns)) + (build-finite-space :top (randomtop dmns dens) + :orgn `(RANDOM-TOPOLOGY ,(1+ *idnm-counter*)))) + + +(DEFUN ADMISSIBLE (topogenous i j) + #| 'T' if Hat-Uj-{i} is contractible (the edge (i j) is admissible) |# + (if (and (> j i) (eq (terme topogenous i j) 1)) + (the boolean + (eq (length (core_list topogenous + (loop for k from 1 to (1- j) + unless (or (zerop (terme topogenous k j)) (eq k i)) + collect k))) 1)))) + + +(DEFMETHOD ADMISSIBLE-P ((topogenous matrice)) + + (the boolean + (let ((fin T) + (stong (stongmat topogenous))) + (do ((j 2 (1+ j))) ((or (null fin) (> j (ncol topogenous))) fin) + (do ((i 1 (1+ i))) ((or (null fin) (> i (1- j)))) + (if (= (terme stong i j) 1) + (if (null (admissible topogenous i j)) + (setf fin NIL)))))))) + + +(DEFMETHOD ADMISSIBLE-P ((finspace finite-space)) + + (the boolean + (let ((fin T)) + (do ((j 2 (1+ j))) ((or (null fin) (> j (ncol (top finspace)))) fin) + (do ((i 1 (1+ i))) ((or (null fin) (> i (1- j)))) + (if (= (terme (stong finspace) i j) 1) + (if (null (admissible (top finspace) i j)) + (setf fin NIL)))))))) + + +(DEFMETHOD DVFIELD ((finspace finite-space)) + #| Discrete vector field on 'finspace' |# + (declare (finite-space finspace)) + (let* ((m_stong (matrice-to-lmtrx (nilpot (stong finspace)))) + (m_top (matrice-to-lmtrx (nilpot (top finspace)))) + (rown (length m_stong)) + (status (make-array rown :initial-element '())) + (used nil) + (vf '())) + (dotimes (i rown) ; Here it is working on the columns. 'rown' is the dimension of the space + (unless (member i used) + (let ((coli_stong (svref m_stong i)) + (coli_top (svref m_top i))) + (when coli_stong + (let ((rowilist (mapcar #'car coli_stong)) + (rowilist_top (mapcar #'car coli_top))) + (declare (type list rowilist rowilist_top)) + (dolist (rowi rowilist) + (declare (type fixnum rowi)) + (let ((rowistatus (svref status rowi))) + (unless (eql 1 rowistatus) + (unless (member rowi used) + (when (and (admissible (top finspace) (1+ rowi) (1+ i)) + (null-intersection-p rowistatus rowilist)) + (setf (svref status rowi) 1) + (setf rowistatus (insert rowi rowistatus)) + (push (list (1+ rowi) (1+ i)) vf) + (push i used) + (push rowi used) + (dolist (item rowilist_top) + (unless (= item rowi) + (case (svref status item) + (1 (dotimes (rowj rown) + (let ((rowjstatus (svref status rowj))) + (unless (eql 1 rowjstatus) + (when (member item rowjstatus) + (setf (svref status rowj) + (union-merge rowistatus rowjstatus))))))) + (otherwise + (setf (svref status item) + (union-merge (member item rowilist_top) (union-merge rowistatus (svref status item)))))))) + (return))))))))))) + (return-from DVFIELD (nreverse vf)))) + + +(DEFMETHOD DVFIELD ((topogenous matrice)) + #| Discrete vector field on a matrice 'topogenous' |# + (dvfield (make-instance 'finite-space + :top topogenous))) + + +;; +;; Special examples of Finite topological spaces +;; + + +(DEFUN FINITE-MODEL-SPHERE (dmns) + #| Minimal finite model of the 'dmns'-dimensional sphere |# + (declare (fixnum dmns)) + (if (minusp dmns) + (error "In FINITE-MODEL-SPHERE, the dimension ~D must be non-negative integer." dmns)) + (build-finite-space + :stong (let ((rslt (identite (+ (* 2 dmns) 2)))) + (unless (= dmns 0) + (do ((i 1 (1+ i))) ((> i (* 2 dmns))) + (insert-term rslt i (+ i 2) 1) + (if (= (mod i 2) 0) + (insert-term rslt i (+ i 1) 1) + (insert-term rslt i (+ i 3) 1)))) + rslt) + :heights (let ((rslt ( 1 (+ (* 2 dmns) 2)))) + (dotimes (q (1+ dmns)) + (setf rslt (append (cddr rslt) (list (list (pop rslt) (pop rslt)))))) + rslt) + :orgn `(FINITE-MODEL-SPHERE ,dmns))) + + +(DEFMETHOD FINITE-SUSPENSION ((topogenous matrice)) + #| Non-Hausdorff suspension of 'topogenous' |# + (let* ((nlig+1 (1+ (nlig topogenous))) + (rslt (add-points topogenous nlig+1 2))) + (maj-colonne rslt nlig+1 (loop for x in ( 1 nlig+1) + collect (list x 1))) + (maj-colonne rslt (1+ nlig+1) (loop for x in ( 1 (1- nlig+1)) + collect (list x 1))) + (insert-term rslt (1+ nlig+1) (1+ nlig+1) 1) + rslt)) + + +(DEFMETHOD FINITE-SUSPENSION ((finspace finite-space)) + (build-finite-space :top (finite-suspension (top finspace)) + :orgn `(FINITE-SUSPENSION ,(idnm finspace)))) diff --git a/src/homology-groups.lisp b/src/homology-groups.lisp index efc1e4b..d2049bf 100644 --- a/src/homology-groups.lisp +++ b/src/homology-groups.lisp @@ -185,8 +185,8 @@ (defun terme (mat i j) (let ((p (left (chercher-hor (baselig mat i) j)))) (if (= j (icol p)) - (val (left p)) - nil))) + (val p) + 0))) (defun mat-aleat (n1 n2 dens x) (let ((mat (creer-matrice n1 n2)) diff --git a/src/kenzo.fas b/src/kenzo.fas new file mode 100755 index 0000000000000000000000000000000000000000..c2396a57206c3f7673fb1f7650cd9ebb6e3ddb8f GIT binary patch literal 63208 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
  • kYKqiTTEC<3UW44gF{}PFZ>C($#P% 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