Skip to content

Instantly share code, notes, and snippets.

@reborg
Created December 18, 2013 11:29
Show Gist options
  • Save reborg/8020830 to your computer and use it in GitHub Desktop.
Save reborg/8020830 to your computer and use it in GitHub Desktop.
An implementation of the travel salesman problem as clojure lazy seq
;; An implementation of a lazy seq that given a graph in the form of a list
;; of edges (e.g. ["AB" "BC" "CD"] can be de-queued of any number
;; of valid paths (in the above example ["AB" "BC" "CD" "ABC" "BCD"] only).
;; Returns nils for acyclic graphs after the number of all
;; available paths have been exhausted. So if you take 100 from the above,
;; the returned collection will have nils after 5 elements. For cyclic graphs
;; it will follow the cycles infintely. To prevent infinte loops, it will
;; exit after a threshold anyway.
;; The approach is definitely brute-force. Optimisations can be done by
;; introducing weight for edges and operating on less costly paths first.
;; See http://en.wikipedia.org/wiki/Travelling_salesman_problem
(defn join [r1 r2]
"Join routes when r2 starts where r1 ends."
(if (and (not (nil? r1)) (not (nil? r2)) (connected? r1 r2))
(str r1 (.substring r2 1))))
(defn all [c1 c2]
"Produce a list of connected paths given an initial set of connecting points.
Invoke first with c1=[] and c2=[\"AB\" \"BC\"] for example."
(lazy-seq
(let [c1+c2 (concat c1 c2)
comb (mapcat #(map (fn [r] [% r]) c1+c2) c1+c2)
connected (map #(join (first %) (last %)) comb)]
(concat c2 (all c2 connected)))))
(defn take* [n coll]
"Take a batch of items from coll until the required number
of distinct not-nil items (or the threshold) has been reached."
(loop [i 10e5]
(let [fetch (distinct (remove nil? (clojure.core/take i coll)))]
(if (and (< (count fetch) n) (< i 10e12))
(recur (+ 10e5 i))
(clojure.core/take n fetch)))))
(defn take [n edges]
"Fetch first n valid paths starting from the initial set of edges"
(take* n (all '() edges)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment