你如何乘以两个生成系列?

时间:2015-07-28 18:16:06

标签: haskell combinatorics

请原谅我,如果这更适合MathOverflow,但我的问题可能太简单了。

我正在阅读SK Lando关于生成函数的讲座,它给出了两个生成函数 A B 的乘积的定义:

A(s)*B(s) = a0*b0 + (a0*b1 + a1*b0)*s + (a0*b2 + a1*b1 + a2*b0)*s^2 ...

我了解 s 只是正式的。但是 - 我知道它对我很迟钝 - 我无法理解组合系数的术语模式应该如何继续。如果有人可以将定义扩展到一个或两个以上的术语,它可能会对我有很大的帮助。非常感谢!

对于奖励积分,Haskell中用于乘以两个系列(表示为系数列表)的算法也将非常受欢迎 - 但仅仅理解上述定义就足够了。

2 个答案:

答案 0 :(得分:4)

请注意,系数指数的总和在每个项中都是常数。例如a0*b0 -> 0+0=0a0*b1 -> 0+1=1a1*b0 -> 1+0=1

回想一下story of young Gauss,他发现通过将一个连续数字列表与其反向相加,我们得到一个常量的列表。同样的技巧适用于此。我们将采用第一个k a_ib_i系数,反转b_i系数列表,并采用列表中的分量产品。

以下是一些Haskell代码,为s^i生成系数i>=0,给定i以及as=[a0,a1,...]bs=[b0,b1,...]列表:

genCoeff :: [Double] -> [Double] -> Int -> Double
genCoeff as bs i = sum $ zipWith (*) (take (i+1) as) (reverse (take (i+1) bs))

要生成所有系数,我们只需将部分应用的函数genCoeff as bs映射到列表[0,1,...],即

genAllCeoffs :: [Double] -> [Double] -> [Double]
genAllCoeffs as bs = map (genCoeff as bs) [0..]

答案 1 :(得分:3)

这是一个不使用reverse的解决方案:

add [] bs = bs
add as [] = as
add (a:as) (b:bs) = (a+b) : add as bs

mult :: [Int] -> [Int] -> [Int]
mult [] bs = []   -- note: [] = 0
mult as [] = []
mult (a:as) (b:bs) = (a*b) : add (add (map (*a) bs) (map (*b) as)) (0:mult as bs)

test1 = do
  let as = [1,2,3]
      bs = [4,5]
  putStrLn $ "as      = " ++ show as
  putStrLn $ "bs      = " ++ show bs
  putStrLn $ "as * bs = " ++ show (mult as bs)

输出:

as      = [1,2,3]
bs      = [4,5]
as * bs = [4,13,22,15]

它来自以下身份:

(a0+a1*x) * (b0 + b1*x) = a0*b0 + a0*b1*x + b0*a1*x + a1*b1*x^2

对应关系是:

a0*b0          <-> a*b
a0*b1*x        <-> map (*a) bs
b0*a1*x        <-> map (*b) as
a1*b1*x^2      <-> (0:mult as bs)