1

The assignment I'm struggling with is based around a problem called the knight's tour and this Numberphile video: https://www.youtube.com/watch?v=G1m7goLCJDY

Basically, what I'm trying to do here is to write a helper function that recursively computes a Hamiltonian path in a given graph (V, E). It should return a list of the elements in V in the order of that path, or nil if no such path exists. But it only returns an empty list for the path P.

My attempt so far (further down): (and formatting is a bit weird)

(defn- H'
;; 
;;     "This is the helper function for computing the Hamiltonian path. 
;;      E is the relation, i.e. the graph, we are looking for a path in.
;;      a is the current node.
;;      S is the set of nodes we haven't visited yet.
;;      P is the path we have traveled so far.
;;      
;;      H' should return a Hamiltonian path through E
;;      that begins with P, then goes through a, and then visits every vertex 
;;      in the set S.
;;      If no such path exists, it should return nil."
;; 
    [E a S P]
;;     
 { 
 :pre [
         (not (contains? S a))
         (not (contains? (set P) a))
         (empty? (intersection S (set P)))
     ]
 :post [
         (or (empty? %) (= (set %) (union S (set P) #{a})))
         (or (empty? %) (= (count %) (+ (count S) (count P) 1)))
       ]
 }

;; (image-of E a) returns the set of edges leading away from the current vertex 

;;     MY ATTEMPT:
    (if-not (empty? S)
        (if (some #(H' E % (disj S %) P) (intersection (image-of E a) S))
            (concat P [a])
        )
    )

)
(defn H
   "compute a Hamiltonian path in the graph (V, E); returns a list of the elements in V in the
   order of that path, or nil if no such path exists"

 [V E]

     (some #(H' E % (disj V %) '()) V)
)

I don't understand why I'm not getting any path P at all in return here from H, just an empty list? Am I terminating the recursion under the wrong conditions or something similar? Is the predicate to the some-function wrongly formulated?

Tell me if anything needs further clarification or more code is needed.

false
  • 10,264
  • 13
  • 101
  • 209
  • 5
    Huh? There are lots of problems with this function, but its name is not one of them. – amalloy Aug 17 '20 at 00:52
  • The name is part of the code skeleton in the assignment and it works and is runnable. I just posted snippets here, as I didn't want to post a wall of code. – sweatspaghettios Aug 17 '20 at 10:50

1 Answers1

0

What's wrong?

Stripped to the minimum,

(defn- H' [E a S P]
  (if (seq S)
    (if (some #(H' E % (disj S %) P) (intersection (image-of E a) S))
      (concat P [a]))))

... where (if-not (empty? S) ... ) is simplified to (if (seq S) ... ).

Consider n, the number of elements in S.

  • If n is zero, H' returns nil.
  • If n is positive, the result is an or-ing of H' calls where the number of elements of S is n-1.

It follows, by induction, that H' returns nil for all S.

In the words of Don Knuth, "I haven't tried this. I have merely proved it."

Putting it right

(H' E a S P) is supposed to return a hamiltonian path starting at a through the vertices S. The function above calculates such a path through S:

(some #(H' E % (disj S %) P) (intersection (image-of E a) S))

... then throws it away.

What we have to do is tack a onto the front of it to keep the inductive promise:

(defn- H' [E a S P]
  (if (seq S)
    (let [tail (some #(H' E % (disj S %) P) (intersection (image-of E a) S))]
      (and tail (cons a tail)))
    (list a)))

... where the and takes care of failure to find a path.

Note ...

  • I haven't tried this.
  • There are better ways to express it that I have tried.
Thumbnail
  • 13,293
  • 2
  • 29
  • 37