jpellegrini / spartns

Spartns is a SPARse TeNSor representation library. This project moved to Gitlab
http://gitlab.com/jpellegrini/spartns
GNU Lesser General Public License v2.1
10 stars 1 forks source link

traversal macro not working #1

Closed jpellegrini closed 7 years ago

jpellegrini commented 7 years ago

There is a bug in the *-traverse macro. Consider this code:

(defspartn sym-mat
      :representation (cvector cvector)
      :non-zero       (500 500)
      :element-type   single-float
      :sparse-element 0.0
      :def t)

(defun test-traverse ()
    (let ((final ())
         (j 2))  ; col = 2 only
      (traverse-sym-mat ((i j) v *x* :dont-bind (j))
      (push v final))
 (print final)))

(progn (setf *x* (make-sym-mat)) t)

(set-sym-mat *x*  0 1 1.0)
(set-sym-mat *x* 0 2 2.0)
(set-sym-mat *x*  0 3 3.0)
(set-sym-mat *x*  1 1 4.0)
(set-sym-mat *x*  1 2 5.0)
(set-sym-mat *x*  5 5 7.0)
(set-sym-mat *x*  250 2 8.0)
(set-sym-mat *x*  250 3 9.0)

Now,

* (test-traverse)
==> (8.0 7.0 5.0 2.0)

* (let ((j 0)) (traverse-sym-mat ((i j) v *x* :dont-bind (j)) (format t "~a ~a ~a~%" i j v)))
==> 0 0 1.0
==> 0 0 2.0
==> 0 0 3.0 
==> 1 0 4.0
==> 1 0 5.0
==> 5 0 7.0
==> 250 0 8.0
==> 250 0 9.0

This macro needs to be reworked.

jpellegrini commented 7 years ago

and it seems to be related to the :dont-bind parameter.

jpellegrini commented 7 years ago

more -- this seems to be some bad interaction between cvector and :don't bind; using (hash hash) as representation scheme gives the correct result.

jpellegrini commented 7 years ago
(defspartn sym-mat2
:representation (hash hash)
 :non-zero       (500 500)
      :element-type   single-float
      :sparse-element 0.0
      :def t)

(defun test-traverse2 ()
(let ((final ())
         (j 2))  ; col = 2 only
      (traverse-sym-mat2 ((i j) v *y* :dont-bind (j))
      (push v final))
 (print final)))
(progn (setf y (make-sym-mat2)) t)

(set-sym-mat2 y  0 1 1.0)
(set-sym-mat2 y 0 2 2.0)
(set-sym-mat2 y  0 3 3.0)
(set-sym-mat2 y  1 1 4.0)
(set-sym-mat2 y  1 2 5.0)
(set-sym-mat2 y  5 5 7.0)
(set-sym-mat2 y  250 2 8.0)
(set-sym-mat2 y  250 3 9.0)

Now...

* (test-traverse2)
==> (8.0 5.0 2.0) 
==> (8.0 5.0 2.0)

yay!

And

(let ((j 0)) (traverse-sym-mat2 ((i j) v y :dont-bind (j)) (format t "~a ~a ~a~%" i j v)))

returns no results!

However, there is one more issue:

* (let ((j -1)) (traverse-sym-mat2 ((i j) v y :dont-bind (j)) (format t "~a ~a ~a~%" i j v)))
==> 0 -1 1.0
==> 0 -1 2.0
==> 0 -1 3.0
==> 1 -1 4.0
==> 1 -1 5.0
==> 5 -1 7.0
==> 250 -1 8.0
==> 250 -1 9.0

Need to fix that...

jpellegrini commented 7 years ago

do-traverse-cvector is broken. Basically, it's miscalculating indexes:

(defspartn sym-mat1
  :representation (cvector)
  :non-zero       (500)
  :element-type   single-float
  :sparse-element 0.0
  :def t)

(defvar *x1*)

(progn (setf *x1* (make-sym-mat1))
       (set-sym-mat1 *x1*    0 1.0)
       (set-sym-mat1 *x1*    1 2.0)
       (set-sym-mat1 *x1*    5 7.0)
       (set-sym-mat1 *x1*  250 8.0))

* (do-traverse-cvector (ii v *x1* :start 3 :end 5 :element-type single-float)
    (print v))

==> 1.0 
==> 2.0 
==> 7.0 

It did not find the correct start index, and used zero.

Now:

*  (do-traverse-cvector (ii v *x1* :start 11 :end 12 :element-type single-float)
     (print v))
1.0 
2.0 
7.0 
8.0 

Found neither start neither end indices, so both were set wrong.

But if both indices are present,

*  (do-traverse-cvector (ii v *x1* :start 1 :end 5 :element-type single-float)
     (print v))
==> 2.0 
==> 7.0 

everything works!

This seems to happen also with traversals with :dont-bind.

jpellegrini commented 7 years ago

do-traverse-cvector was using indices in a completely broken way. fixed in version 1.4.5