3

Apparently my teacher believes that even if we don't have time to learn stuff (nor enough examples) we should move on, so I now need to know how to make Floyd-Warshall's and Warshall's algorithms in clisp.

As I did with prolog, my problem is to generate the adjacency matrix from the graph, in this case it would be a list of lists, e.g.:

((A B) (A C) (A D) (B C) (C D))

That should generate:

((0 1 1 1) (1 0 1 9) (1 1 0 1) (1 9 1 0))

I've got this:

(defun floyd(graph)
    (setf l (length graph)) 
    (setf mat (matrix l graph))
)

(defun matrix(l graph)
    (setf matrix (make-array (list l l)))
    (dotimes (i l)
        (dotimes (j l)
            (if (= i j)
                (setf (aref matrix i j) 0)
                (setf (aref matrix i j) ???)
            )
        )
    )
    matrix
)

Any help is greatly appreciated.

Also, and kind of off-topic: If I could solve my own question, should I reply myself for the sake of having an answered question?

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Kirby
  • 455
  • 6
  • 23
  • There is a [Self Learner badge](http://stackoverflow.com/badges/14/self-learner) if you answer your own question with a score of 3 or more. I'd take that as a hint regarding whether it is acceptable to reply with a solution yourself. – Terje Norderhaug May 24 '11 at 22:49
  • As a start for more idiomatic code, use [`let`](http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm) instead of `setf` for `l`, `mat` and `matrix`. – Terje Norderhaug May 24 '11 at 22:54
  • CLISP is an implementation, the language is called Common Lisp or short CL. You also need to declare variables (for example using LET). Setting arbitrary undefined variables is not a good idea. Also don't format code with single parentheses on a line. – Rainer Joswig May 24 '11 at 23:21
  • As a warm up exercise, consider writing a function that returns the nodes for the graph, e.g `(A B C D)`. – Terje Norderhaug May 24 '11 at 23:38
  • Your teacher will be much more impressed with your brilliance if you solve it with [pure functions](http://en.wikipedia.org/wiki/Pure_function) rather than rely on side effects. See if you can eliminate the use of `SETF`. – Terje Norderhaug May 24 '11 at 23:55
  • @Terje thank you very much for all of your comments, I'll try the warm up exercise, and if I have time I'll try to understand pure functions xD problem is, I have like 36 hours now. – Kirby May 25 '11 at 04:57

1 Answers1

1

I converted the Wikipedia pseudo-code into Common Lisp with type declarations. The return type declaration is non-standard, I used SBCL. I guess this won't run but it might give you an idea how Lisp code is supposed to look like.

(defparameter *n* 5)
(defparameter *path*
  (make-array (list *n* *n*)
          :element-type '(unsigned-byte 64)))


(defun floyd-warshall (path)
  (declare (type (simple-array (unsigned-byte 64) 2) path)
       (values (simple-array (unsigned-byte 64) 2) &optional))
  (destructuring-bind (y x) (array-dimensions path)
    (unless (= y x)
      (break "I expect a square matrix, not ~ax~a." x y))
    (macrolet ((p (j i)
         `(aref path ,j ,i)))
      (dotimes (k x)
    (dotimes (i x)
      (dotimes (j x)
        (setf (p j i)
          (min (p j i) (+ (p k i)
                  (p j k)))))))))
  path)

Note 1: If you have a 3D volume image you should have your indices like this (aref vol k j i) where k indexes z, j y and i the x-direction. That way in SBCL and presumably all other implementations the slices are consecutive in memory.

Note 2: macrolet can save quite a lot of typing. Also look at the implementation of with-arrays in this beautiful library: git://github.com/nikodemus/raylisp.git/objects/box.lisp

whoplisp
  • 2,508
  • 16
  • 19