これが数学的に起こっていることをどれだけ厳密に捉えるかという考えが好きです。
あなたの前提は間違っていると思います。パイプ演算子は、関数のチェーンを介して値をスレッド化し、関数の合成に密接に関連しています。ただし、 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
これを、ある関数への3つの独立した呼び出しのチェーンに簡単にマッピングすることはできません。integrate x1 x2 >> integrate y1 y2 >> integrate z1 z2
したがって、実際には、統合するときに構成が実行されることはありません。そのため、Tomasのソリューションは、正しく理解していれば(そして、それについてはよくわかりませんが...)、基本的に、暗黙的に定義された3Dグリッドで関数を評価し、それを積分関数に渡します。私はあなたがあなたの元の質問に到達することができるのと同じくらい近いと思います。f
あなたはそれを求めませんでしたが、実際にn次元積分を評価したい場合は、モンテカルロ積分を調べてください。これにより、一般に「次元の呪い」として知られる別の問題、つまり、必要な数が必要になるという事実を回避できます。サンプルポイントは、従来の積分スキームではnとともに指数関数的に増加します。
アップデート
integrate
積分の各ステップで積分される関数のタイプが異なるため、反復積分を実装できますが、単一の関数では実装できません(つまり、各ステップでn - ary関数が(n-1)-ary関数に変わります。 )::
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を生成します。