这个程序中似乎有一个错误,如果有人可以提供帮助我很感激
(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
答案 0 :(得分:2)
例外情况发生在您subvec
的第一个recur
中。你重复使用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))))
其他一些提示:
findmincostindex
基本上是min-key
的重新实现,不太通用,你可以使用它来使它更干净。(filter #(not (contains? explored %)) childs)))
上进行一些改进 - 例如(remove explored childs)
let
。 这是我的尝试:
(let [[idx {:keys [path cost]}] (apply min-key (comp :cost second) (map-indexed vector frontier))
node (peek path)
childs (keys (graph node))]
这里的过程是
(map-indexed vector frontier)
将frontier
转换为索引和节点对。min-key
找到(:cost (second pair))
值最小的对。 let
将名称idx
绑定到该对的索引,将path
和cost
绑定到:path
和:cost
键节点。