clojure

时间:2015-05-23 17:43:49

标签: clojure

我正在尝试在clojure中实现A *搜索算法(尚未完成):

(ns typedclj.rhizome
  (:require [clojure.set :refer [union]]))


(use 'clojure.pprint)
(defmacro epprint [expr]
  `(do (pprint '~expr)
       (pprint ~expr)))
(defmacro epprints [& exprs]
  (list* 'do (map (fn [x] (list 'epprint x))
                  exprs)))

(epprints (inc 1) (inc 2))

(def world [[1 1 1 1 1]
            [999 999 999 999 1]
            [1 1 1 1 1]
            [1 999 999 999 999]
            [1 1 1 1 1]])

(def ^:dynamic *world-size* 5)
(def ^:dynamic *step-cost* 900)
;(alter-var-root #'*world-size* (constantly 5))

(defn neighbors
  ([yx]
   (neighbors [[-1 0] [1 0] [0 -1] [0 1]] *world-size* yx))
  ([deltas *world-size* yx]
   (filter (fn [new-yx] (every? #(< -1 % *world-size*)
                                new-yx))
           (map #(vec (map + yx %)) deltas))))

(defn heuristic-cost-estimate [[y x]]
  (* *step-cost*
     (- (+ *world-size* *world-size*) y x 2)))

(defn mapmat [f mat]
  (mapv (fn [row]
          (mapv f row))
        mat))
(defn mapmats [f & mats]
  (apply mapv (fn [& rows]
                (apply mapv f rows))
         mats))
(defn randmat []
  (repeatedly *world-size*
              (fn [] (repeatedly
                       *world-size*
                       #(rand-int 10)))))

(defn min-by [f coll]
  (when (seq coll)
    (reduce (fn [min this]
              (if (> (f min) (f this)) this min))
            coll)))

(pprint (randmat))
(let [m1 (randmat)
      m2 (randmat)
      m3 (randmat)]
  (epprints m1 m2 m3)
  (mapmats + m1 m2 m3))

(defn constant-matrix [c]
  (vec (repeat *world-size*
               (vec (repeat *world-size* c)))))

(let [coords (for [i (range *world-size*)]
               (for [j (range *world-size*)]
                 [i j]))
      h-score (mapmat heuristic-cost-estimate coords)
      start [0 0]
      goal-y *world-size*
      goal-x goal-y
      goal [goal-x goal-y]]
  (loop [closedset #{}
         openset #{[0 0]}
         came-from (constant-matrix [nil nil])
         g-score (assoc-in (constant-matrix 1e8) start 0)
         f-score (mapmats + g-score h-score)
         ]

    (let [
          current (min-by f-score openset)
          openset (disj openset current)
          closedset (conj closedset current)
          nbrs (filter (complement closedset)
                       (neighbors current))
          openset (union openset (set nbrs))
          ]
      (if (empty? openset)
        (if (= current goal)
          came-from
          false)
        (let [[came-from g-score f-score]
              (reduce (fn [[cf gs fs :as to-be-updated] nbr]
                        (let [current-g-score (get-in g-score current)
                              nbr-g-score (get-in g-score nbr)
                              nbr-cost (get-in world nbr)
                              tentative-g-score (+ current-g-score
                                                   nbr-cost)]
                          (if (>= tentative-g-score nbr-g-score)
                            to-be-updated
                            [(assoc-in cf nbr current)
                             (assoc-in gs nbr tentative-g-score  )
                             (assoc-in fs nbr (+ tentative-g-score
                                                 (get-in h-score nbr)))])))
                      [came-from g-score f-score]
                      nbrs)]
          (epprints nbrs
                    openset
                    came-from
                    g-score
                    f-score)
          (recur closedset openset came-from g-score f-score))))))

将此加载到repl中时出现了一些奇怪的错误:

CompilerException java.lang.IllegalArgumentException: Key must be integer, compiling:(/Users/kaiyin/personal_config_bin_files/workspace/typedclj/src/typedclj/rhizome.clj:70:48) 

我做错了什么?

这是我使用的伪代码(来自维基百科):

function A*(start,goal)
    closedset := the empty set    // The set of nodes already evaluated.
    openset := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
    came_from := the empty map    // The map of navigated nodes.


g_score[start] := 0    // Cost from start along best known path.
// Estimated total cost from start to goal through y.
f_score[start] := g_score[start] + heuristic_cost_estimate(start, goal)

while openset is not empty
    current := the node in openset having the lowest f_score[] value
    if current = goal
        return reconstruct_path(came_from, goal)

    remove current from openset
    add current to closedset
    for each neighbor in neighbor_nodes(current)
        if neighbor in closedset
            continue
        tentative_g_score := g_score[current] + dist_between(current,neighbor)

        if neighbor not in openset or tentative_g_score < g_score[neighbor] 
            came_from[neighbor] := current
            g_score[neighbor] := tentative_g_score
            f_score[neighbor] := g_score[neighbor] + heuristic_cost_estimate(neighbor, goal)
            if neighbor not in openset
                add neighbor to openset

return failure

1 个答案:

答案 0 :(得分:1)

(defn constant-matrix [c]
  (vec (repeat *world-size*
               (vec (repeat *world-size* c)))))

第一个repeat传递一个向量作为第二个参数,向量不是一个数字。