也许让我先用伪 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 只是连接返回的向量。基本上,我以一种方式对函数进行采样,使得两个保存的函数值之间只有很小的差异。
我对上述方式不满意,因为在每个递归步骤中似乎都有相当多的内存分配(分配两个子向量,然后连接这些子向量和另一个元素)。那段代码必须在我的算法的一部分中运行,这对性能至关重要。一旦upper - lower
相当小,评估f
将不会花费大量时间。
所以我的问题:
您是否看到在所有递归调用中使用相同数据结构并仅填充该向量的当前部分的巧妙方法?(请记住,所需的函数评估数量是未知的)。对此的想法:
- 使用列表而不是向量。但我觉得内存大修不足以存储双打。
- 在向量中保留孔并维护另一个向量,说明哪些条目已填充。递归调用的结束移动条目,以便
subsample
s 和newval
. 但是现在我通过为第二个向量转移额外的工作来切换复制——这可能是个坏主意。
您是否看到完全摆脱递归的方法?但是,为了正确起见,我使用上述分而治之的模式很重要。该函数
f
大量使用了上限和下限,并由此获得了相当大的性能。
谢谢你的想法。
根据 Space_C0wb0y 的要求,让我尝试重新表述我的问题。也许第一个解释不是很清楚。
我有一些函数(在数学意义上)我想在给定的时间间隔内采样(例如在某些点进行评估)。
假设区间为 [0,100]。我知道函数值在 0 和 100。也许是f(0)=0
和f(100) = 40
。现在我在间隔中点(即 50)处评估函数。比如说,我的函数返回f(50)=10
. 因为f(0)-f(50) <= 10
,我不需要区间 [0,50] 中的更多样本。但是,我需要进一步计算区间 [50,100]。因此,在下一个(递归)步骤中,我评估f(75)
. 现在递归地重复上面的逻辑。
最后,我想(两个)向量给我带有相应参数的函数值,如下所示:
parameter = vector(0, 50, 56.25, 62.5, 75, 100)
value = vector(0, 10, 17.21, 25 34, 40)
我正在寻找递归构建这些向量的最佳(性能最高)方法。
希望这可以澄清事情。