【发布时间】:2019-04-04 04:35:18
【问题描述】:
我是 Clojure 的新手,并试图通过在其中实现一些算法来学习。我正在编写的算法用于计算图数据结构的节点 betweenness centrality 指标。
我尝试实现的算法(Brandes 算法)中的函数如下所示:
这里,V 是图的顶点,s 是我们尝试计算并返回最短路径度量的起始节点S, Pred and sigma
这是我通过使用loom 为每个起始节点g 创建初始图start 所设法提出的:
(defn ss-shortest-path
[g start]
(let [nodeset (disj (nodes g) start)
pred (apply assoc {} (interleave (nodes g) (repeat nil)))
dist (apply assoc {start 0} (interleave nodeset (repeat -1)))
sigma (apply assoc {start 1} (interleave nodeset (repeat 0)))
stack []]
(loop [queue (conj clojure.lang.PersistentQueue/EMPTY start)]
(if (empty? queue)
{:sigma sigma
:pred pred
:stack stack}
(let [v (peek queue)
stack (conj stack v)]
(doseq [w (successors g v)]
(when (= (dist w) -1)
(do
(conj queue w)
(assoc dist w (+ 1 (dist v)))))
(when (= (dist w) (+ 1 (dist v)))
(do
(assoc sigma w (+ (sigma w) (sigma v)))
(assoc pred w v))))
(recur (pop queue)))))))
我知道 Clojure 数据结构是不可变的,因此每次我在变量 pred, sigma, stack, dist 中调用 conj 或 assoc 时都会创建一个新副本,并且原始变量保持不变。
但是,我不想使用像atoms、refs 这样的可变状态,因为我觉得这只是在复制我已经知道的命令式样式。
因此,我正在寻求一些经验丰富的 Clojurists 的帮助,以帮助我以惯用的方式创建此功能。
提前致谢。
【问题讨论】:
标签: algorithm recursion clojure functional-programming immutability