最初に疑似 C++ コードで私の状況を述べさせてください。
std:vector<double> sample(someFunctor f, double lower, double upper) {
double t = (lower + upper)/2;
double newval = f(t);
if (f(upper) - newval > epsilon)
subsample1 = sample(f, t, upper);
if (newval - f(lower) > epsilon)
subsample2 = sample(f, lower, t);
return concat(subsample2, newval, subsample1);
}
ここで、concat は返されたベクトルを連結します。基本的に、保存された 2 つの関数値の間にわずかな違いしかないような方法で関数をサンプリングしています。
すべての再帰ステップでかなりの量のメモリ割り当て (2 つのサブベクトルを割り当ててから、それらと別の要素を連結) があるように見えるため、上記の方法には満足できません。そのコードは、パフォーマンスに関して重要なアルゴリズムの一部で実行する必要があります。upper - lower
かなり小さい場合は、評価にf
それほど時間はかかりません。
だから私の質問:
すべての再帰呼び出しで同じデータ構造を使用し、そのベクトルの現在の部分を埋めるだけの巧妙な方法を見つけましたか? (必要な関数評価の数は前もってわからないことに注意してください)。これについての考え:
- ベクトルの代わりにリストを使用します。しかし、ダブルを格納するだけでは、メモリのオーバーホールは十分ではないと感じています。
- ベクトルの穴を保持し、どのエントリが埋められるかを示す別のベクトルを維持します。
subsample
再帰呼び出しの最後で、と の間に穴がないようにエントリをシフトしますnewval
。しかし今、2番目のベクトルの追加作業でシフトすることでコピーを切り替えます-おそらく悪い考えです。
再帰を完全に取り除く方法はありますか? ただし、正確さのために、上記の分割統治パターンを使用することが重要です。この関数
f
は上限と下限を多用し、これによってかなりのパフォーマンスが得られます。
ご感想ありがとうございます。
Space_C0wb0y の要求に従って、私の問題を言い換えてみます。おそらく最初の説明はあまり明確ではありませんでした。
特定の間隔でサンプリングする(たとえば、特定のポイントで評価する)関数(数学的な意味で)があります。
間隔が [0,100] であるとします。f(0)=0
関数の値が 0と100 であることはわかっていますf(100) = 40
。ここで、間隔の中間点である 50 で関数を評価します。たとえば、関数が を返しますf(50)=10
。としてf(0)-f(50) <= 10
、間隔 [0,50] にこれ以上のサンプルは必要ありません。ただし、間隔 [50,100] についてはさらに計算が必要です。したがって、次の (再帰的な) ステップで を評価しf(75)
ます。上記のロジックを再帰的に繰り返します。
最後に、次のような対応するパラメーターを持つ関数値を提供する (2 つの) ベクトルを使用したいと思います。
parameter = vector(0, 50, 56.25, 62.5, 75, 100)
value = vector(0, 10, 17.21, 25 34, 40)
これらのベクトルを再帰的に構築するための最良の(最もパフォーマンスの高い)アプローチを探しています。
これが物事を明確にすることを願っています。