【问题标题】:Uniform cost search in clojureclojure 中的统一成本搜索
【发布时间】:2015-08-09 08:19:34
【问题描述】:

此程序中似乎存在错误,如果有人可以提供帮助,我将不胜感激

(defn findmincostindex [frontier]
  (loop [i 0 n 0]
    (if (< i (count frontier))
      (if (< (:cost (get frontier i)) (:cost (get frontier n)))
        (recur (inc i) i)
        (recur (inc i) n))
      n)))


(defn uniformcostsearch [graph start end]
  ((fn [frontier explored]
    (if (empty? frontier)
      "Failure"
      (let [pathwithmincost (findmincostindex (into [] frontier))
      ;(let [pathwithmincost (findmincostindex frontier)
            path (:path (get frontier pathwithmincost))
            cost (:cost (get frontier pathwithmincost))
            node (peek path)
            childs (keys (graph node))]
        (if (= node end)
          path
          (recur 
            (concat (subvec frontier 0 pathwithmincost) (subvec frontier (inc pathwithmincost))
              (map (fn [c] {:path (conj path c) :cost (+ cost ((graph node) c))})
                (filter #(not (contains? explored %)) childs)))
            (conj explored node))))))
    [{:path [start] :cost 0}] #{}))



(def graph {
        "Oradea" {
            "Zerind" 71,
            "Sibiu" 151
        },
        "Zerind" {
            "Oradea" 71,
            "Arad" 75
        },
        "Arad" {
            "Zerind" 75,
            "Sibiu" 140,
            "Timisoara" 118
        },
        "Sibiu" {
            "Oradea" 151,
            "Arad" 140,
            "Fagaras" 99,
            "Rimnicu Vilcea" 80
        },
        "Fagaras" {
            "Sibiu" 99,
            "Bucharest" 211
        },
        "Rimnicu Vilcea" {
            "Sibiu" 80,
            "Pitesti" 97,
            "Craiova" 146
        },
        "Timisoara" {
            "Arad" 118,
            "Lugoj" 111
        },
        "Lugoj" {
            "Timisoara" 111,
            "Mehadia" 70
        },
        "Pitesti" {
            "Rimnicu Vilcea" 97,
            "Craiova" 138,
            "Bucharest" 101
        },
        "Mehadia" {
            "Lugoj" 70,
            "Drobeta" 75
        },
        "Drobeta" {
            "Mehadia" 75,
            "Craiova" 120
        },
        "Craiova" {
            "Drobeta" 120,
            "Rimnicu Vilcea" 146,
            "Pitesti" 138
        },
        "Bucharest" {
            "Pitesti" 101,
            "Fagaras" 211,
            "Giurgiu" 90,
            "Urziceni" 85
        },
        "Giurgiu" {
            "Bucharest" 90
        },
        "Urziceni" {
            "Bucharest" 85,
            "Vaslui" 142,
            "Hirsova" 98
        },
        "Hirsova" {
            "Urziceni" 98,
            "Eforie" 86
        },
        "Eforie" {
            "Hirsova" 86
        },
        "Vaslui" {
            "Iasi" 92,
            "Urziceni" 142
        },
        "Iasi" {
            "Neamt" 87,
            "Vaslui" 92
        },
        "Neamt" {
            "Iasi" 87
        }})

(println (uniformcostsearch graph "Neamt" "Iasi"))
(println (uniformcostsearch graph "Neamt" "Vaslui"))
(println (uniformcostsearch graph "Bucharest" "Arad"))

它应该输出这些行

['Neamt', 'Iasi']
['Neamt', 'Iasi', 'Vaslui']
['Bucharest', 'Pitesti', 'Rimnicu Vilcea', 'Sibiu', 'Arad']

但它却说:

clojure.lang.LazySeq 不能转换为 clojure.lang.IPersistentVector

当我使用时

(into [] frontier)

如果我单独使用前沿,它会说

java.lang.NullPointerException

【问题讨论】:

    标签: clojure


    【解决方案1】:

    异常发生在您的recur 中的第一个subvec。你会重复concat 的结果,这是一个惰性序列,你不能取一个惰性序列的子向量。一个快速的解决方法是将其包裹在 vec:

    (vec (concat (subvec frontier 0 pathwithmincost) (subvec frontier (inc pathwithmincost))
                  (map (fn [c] {:path (conj path c) :cost (+ cost ((graph node) c))})
                    (remove explored childs))))
    

    其他一些提示:

    1. findmincostindex 本质上是对不太通用的 min-key 的重新实现,您可能可以通过使用它来使其更简洁。
    2. 集合也是函数,如果它是集合的成员,则返回参数(真实值)。您可以使用它来改进(filter #(not (contains? explored %)) childs))) - 例如(remove explored childs)
    3. 您的let 可以使用destructuring 缩短一点。

    这是我的尝试:

    (let [[idx {:keys [path cost]}] (apply min-key (comp :cost second) (map-indexed vector frontier))
          node (peek path)
          childs (keys (graph node))] 
    

    这里的过程是

    1. (map-indexed vector frontier) 使 frontier 成为索引和节点对。
    2. min-key 查找具有最低 (:cost (second pair)) 值的对。
    3. let 将名称 idx 绑定到该对的索引,并将 pathcost 绑定到节点的 :path:cost 键。

    【讨论】:

      猜你喜欢
      • 2015-10-08
      • 2017-09-07
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-12
      • 1970-01-01
      相关资源
      最近更新 更多