【问题标题】:Clojure - functional relaxation algorithmClojure - 函数松弛算法
【发布时间】:2016-09-21 14:59:40
【问题描述】:

我正在尝试在 Clojure 中实现布偶物理。我的模型有一个多维坐标序列 x 和一个距离约束矩阵 M,这是松弛算法的一部分所需要的。

一般的想法是,如果矩阵条目 m_ij 不为零,我必须以这样的方式修改坐标 x_ix_j他们的距离等于M_ij。假设每个 x_n 都是 2D/3D 坐标,我知道如何正确计算。

现在,由于 M 的每个条目都会影响两个坐标,我想不出一种方法来使用mapreduce 来正确迭代坐标。我也许可以将两个 loop, recur 调用相互放在一起以模拟命令,但我希望有更好的方法(尤其是因为它会导致看起来非常混乱的代码)。

您知道迭代二维矩阵并在此过程中修改多个向量条目的函数式方法吗?

【问题讨论】:

  • 首先想到的是映射成对的相邻点,而不是点值,然后重新组合这些结果。
  • 你考虑过for 吗? (for [x (range 10) y (range 5)] ...)

标签: algorithm clojure functional-programming


【解决方案1】:

我认为reduce-kv 很好地抓住了这种模式的精髓:

(reduce-kv (fn [x' [i j] d] ;; x' — accumulator (vector of coordinates)
                            ;; [i j] — Matrix coordinates
                            ;; d — Matrix value (distance)
             (let [[x'ᵢ x'ⱼ] (update-distance (nth x' i)
                                              (nth x' j)
                                              d)]
               (assoc x' i x'ᵢ j x'ⱼ)))
           x  ;; Initial coordinates
           M) ;; Matrix

几点说明:

  • update-distance 从初始的一对坐标和距离计算出一对新的坐标
  • 我们使用assoc 来“更新”x。所以x 应该是一个向量(任何关联都可以,但向量似乎是自然的选择。
  • 矩阵M 必须满足clojure.core.protocols/IKVReduce 协议。 如果没有,您可以提供一个实现,或者您可以简单地编写一个生成适当键值对的函数,并在其上使用reduce。另一种选择是简单地将M 实现为使用持久映射的稀疏矩阵。
  • 代码不会过滤掉 0 值距离,但这应该很容易添加。

【讨论】:

  • 谢谢 Nathan Davis,我不知道 reduce-kv。我认为它完全符合我的需要。我将把它与 Charles Duffy 的仅迭代约束的想法结合起来——它将在不受约束的点上节省大量迭代,从而从 O(N^2) 变为 O(N)。只是出于好奇,除了实现 IKVReduce 协议之外,按照您的建议生成键值的另一种方法是什么?矩阵只是向量的向量,因此在不创建自己的类型的情况下,我只能以这种方式遍历行。
  • IKVReduce 是为向量实现的。所以你可以只使用一对嵌套的reduce-kv 调用——一个用于每个矩阵维度。或者,您可以在每个维度的range 上使用一对嵌套的fors,并生成[i j d] 元组的序列。一般来说,任何为所有感兴趣的矩阵坐标生成元组序列的方法都可以。如果您需要更多详细信息,请告诉我,我会将其添加到答案中。
  • 是的,嵌套的reduce-kv 电话首先出现在我的脑海中。我只是想知道是否有办法将生成的元组作为关键参数直接传递给 reducer 函数。
  • @waechtertroll,我不确定你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
相关资源
最近更新 更多