【发布时间】:2011-09-15 07:45:00
【问题描述】:
也许让我先用伪 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 将不会花费大量时间。
所以我的问题:
-
您是否发现了一种在所有递归调用中使用相同数据结构并仅填充该向量的当前部分的巧妙方法? (请记住,所需的函数评估数量是未知的)。对此的想法:
- 使用列表而不是向量。但我觉得内存大修不足以存储双打。
- 在向量中保留孔并维护另一个向量,说明哪些条目已被填充。递归调用的结束移动条目,以便
subsamples 和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)
我正在寻找递归构建这些向量的最佳(性能最高)方法。
希望这可以澄清事情。
【问题讨论】:
-
我不太明白你的问题。你能举一个输入和预期输出的例子吗?
-
这里的“性能关键”是指时间关键还是空间关键?大多数时候它们是矛盾的。
-
@Space_C0wb0y:为问题添加了另一种方法。希望这会有所帮助。
-
@Eric:就算法期间所需的空间而言,空间是一个次要问题。然而,结果应该尽可能紧凑。时间最优性是我的主要关注点。
标签: c++ recursion vector divide-and-conquer