gpt4 book ai didi

haskell - Haskell 中的惯用向量代数

转载 作者:行者123 更新时间:2023-12-04 01:11:18 32 4
gpt4 key购买 nike

作为在 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])。

一种解决方案是实现某种向量空间类型类或使用更具体的线性代数库,但由于这些是常见的操作,我想知道是否有更惯用的“直接”解决方案。

最佳答案

我会从 dfeuer 的 +1 开始;一个更具体的库几乎肯定会更干净、更高效。

但是,如果您正在寻找的是您的 centroid 的更惯用的实现。功能,我喜欢这个:

centroid' :: Simplex -> Int -> Node
centroid' s iz = let t = foldl1 (V.zipWith (+)) (V.drop iz s)
n = fromIntegral (V.length t - 1)
in V.map (/ n) t

对您的版本的一般评论:创建“只写”Haskell 代码非常容易。您的第一行内容太多,难以解析。您的 where block 是朝着正确的方向迈出的一步,但我会进一步打破概念组件。

另外, Hoogle .我不知道有函数 drop ,但我知道如果它存在,它需要一个 IntVector到一个新的 Vector . Hoogle 没有索引 Vector ,但向量的 API 与列表的 API 非常相似。我搜索了“[a] -> Int -> [a]”和“Int -> [a] -> [a]”,发现 drop .

( Stackage 没有索引 Vector ,所以在那里搜索“Int -> Vector a -> Vector a”有效)

关于haskell - Haskell 中的惯用向量代数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30634449/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com