【发布时间】:2015-06-04 03:28:04
【问题描述】:
作为在 Haskell 中练习向量库的一种方式,我正在尝试重写我之前用 C 编写的 Nelder-Mead 最小化算法。 到目前为止,我在翻译一些惯用的向量操作时遇到了一些麻烦。
例如,考虑一个函数,它从 n+1 的列表中找到 n 个向量的质心(过滤掉一个索引),
在 C 中,这可以写成
static void get_centroid(double **s, int n, int iz,
double *C)
{
for (int i = 0; i < n+1; i++) {
if (i != iz) {
for (int j = 0; j < n; j++)
C[j] += s[i][j];
}
}
for (int j = 0; j < n; j++)
C[j] /= n;
}
我尝试将其翻译成 Haskell,结果如下
import Data.Vector
import qualified Data.Vector as V
type Node = Vector Double
type Simplex = Vector Node
centroid :: Simplex -> Int -> Node
centroid s iz = V.map (/ (fromIntegral $ V.length s)) $ V.zipWith (-) v (s ! iz)
where v = V.foldl go V.empty s
where go a b = V.zipWith (+) a b
我发现这段代码很不优雅,因为它没有捕捉到正在发生的向量代数的本质(而且效率也更低,因为我正在加减 S[iz])。
一种解决方案是实现某种向量空间类型类或使用更具体的线性代数库,但由于这些是常见的操作,我想知道是否有更惯用的“直接”解决方案。
【问题讨论】:
-
为什么要使用
Data.Vector?一个更具体的库几乎肯定是要走的路。但是,如果您想尝试使用这些向量,您应该 1. 切换到“未装箱”版本以提高速度,以及 2. 查看向量切片操作以跳过行/列。
标签: haskell