我喜欢这样的想法,即这将在数学上捕捉到正在发生的事情。
恐怕您的前提是错误的:管道运算符通过一系列函数将值线程化,并且与函数组合密切相关。然而,在n维域上积分类似于n嵌套循环,即在您的情况下类似于
for x in x_grid_nodes do
for y in y_grid_nodes do
for z in z_grid_nodes do
integral <- integral + ... // details depend on integration scheme
您无法轻松地将其映射到对某个Integrate
函数的三个独立调用链,因此组合integrate x1 x2 >> integrate y1 y2 >> integrate z1 z2
实际上不是您在集成时所做的f
。这就是为什么 Tomas 的解决方案——如果我理解正确(我对此不确定......)——本质上是在隐式定义的 3D 网格上评估您的函数并将其传递给集成函数。我怀疑这与您最初的问题一样接近。
您没有要求,但如果您确实想在实践中评估n维积分,请查看 Monte Carlo 积分,它避免了另一个通常称为“维度诅咒”的问题,即所需的数量使用经典积分方案,样本点随n呈指数增长。
更新
您可以实现迭代集成,但不能使用单个integrate
函数,因为要集成的函数的类型对于集成的每个步骤都不同(即每个步骤将n元函数转换为 ( n - 1) 元函数):
let f = fun x y z -> 8.0 * x * y * z
// numerically integrate f on [x1, x2]
let trapRule f x1 x2 = (x2 - x1) * (f x1 + f x2) / 2.0
// uniform step size for simplicity
let h = 0.1
// integrate an unary function f on a given discrete grid
let integrate grid f =
let mutable integral = 0.0
for x1, x2 in Seq.zip grid (Seq.skip 1 grid) do
integral <- integral + trapRule f x1 x2
integral
// integrate a 3-ary function f with respect to its last argument
let integrate3 lower upper f =
let grid = seq { lower .. h .. upper }
fun x y -> integrate grid (f x y)
// integrate a 2-ary function f with respect to its last argument
let integrate2 lower upper f =
let grid = seq { lower .. h .. upper }
fun x -> integrate grid (f x)
// integrate an unary function f on [lower, upper]
let integrate1 lower upper f =
integrate (seq { lower .. h .. upper }) f
使用您的示例功能f
f |> integrate3 0.0 1.0 |> integrate2 0.0 1.0 |> integrate1 0.0 1.0
产生 1.0。