4

離散信号を離散フィルタで畳み込みたいと思います。シグナルとフィルターは、F# の float のシーケンスです。

その方法を理解できる唯一の方法は、ネストされた 2 つの for ループと、結果を格納する可変配列を使用することですが、あまり機能的ではありません。

機能しないようにする方法は次のとおりです。

conv = double[len(signal) + len(filter) - 1]
for i = 1 to len(signal)
  for j = 1 to len(filter)
    conv[i + j] = conv[i + j] + signal(i) * filter(len(filter) - j) 
4

4 に答える 4

3

この機能を試してください:

let convolute signal filter =
    [|0 .. Array.length signal + Array.length filter - 1|] |> Array.map (fun i ->
        [|0 .. i|] |> Array.sum_by (fun j -> signal.[i] * filter.[Array.length filter - (i - j) - 1]))

これはおそらく最も優れた関数ソリューションではありませんが、機能するはずです。しかし、速度のために不可欠なものに匹敵する純粋に機能的なソリューションが存在するとは思えません。

それが役立つことを願っています。

注: この関数は現在テストされていません (ただし、コンパイルできることは確認済みです)。それがすべきことを完全に行わない場合は、私に知らせてください。また、変数ij変数が元の投稿と同じものを参照していないことに注意してください。

于 2009-04-29T19:41:41.600 に答える
2

原則として、(高速) フーリエ変換または関連する (離散) コサイン変換を使用して、2 つの関数の畳み込みを合理的に効率的に計算できるはずです。両方の関数の FFT を計算して乗算し、結果に逆 FFT を適用します。

数学的背景

それが理論です。実際には、それを実装する数学ライブラリを見つけるのがおそらく最善でしょう。

于 2009-04-29T17:16:29.170 に答える
2

実際、通常、ループ (プレーン、ネストなど) や関数型プログラミングで変更可能なものは避けたいと考えています。

F# (およびおそらく他のほぼすべての関数型言語) には、非常に単純な解決策があります。

let convolution = Seq.zip seq1 seq2

関数はzip単純に 2 つのシーケンスを結合して、要素 fromseq1と要素 from を含むペアの 1 つにしseq2ます。List注意として、とモジュールの同様の zip 関数、およびArray3 つのリストをトリプルに結合するバリアント ( zip3) もあります。通常、n 個のリストを n 個のタプルのリストに圧縮 (または「畳み込み」) したい場合は、独自の関数を作成する必要がありますが、それは非常に簡単です。

(ちなみに、私は畳み込みについてこの説明を行ってきました- 何か他のことを意味する場合は教えてください。)

于 2009-04-29T16:12:18.607 に答える