它涉及给每个间隙一个接近度分数。
要计算间隙i的接近度得分,我只需对所有j!= i求和1 / {dist(gap_i,gap_j)+1}
我设置+1以避免被零除。这样,如果两个值几乎相等,则它们将获得1分,并且随着差距的增加,该得分将变为0
但是,如果间隙j几乎恰好是间隙i的两倍,则也应将其视为非常接近。所以我首先获得最接近gap_j / gap_i的整数(可能需要交换以使gap_j更大),然后将gap_j除以该整数,然后考虑dist(gap_i,fiddled_gap_j)
如果例如gap_j?= 2 * gap_i,那么我要小心提高Gap_i的得分,而不是gap_j
这样可以很好地获得合理准确的候选人。再经过两次处理应该可以很容易地改进该值。我想的第一件事是根据成功的候选人对价值进行平均。然后大概一秒钟创建一个泛函(f)函数,并使用从先前计算的点开始的某种Newton-Raphson过程来隔离局部最大值。
无论如何,下面是代码:
float ascertain_f0(PEAK * peaks, POTENTIAL_HARMONIC * pH, int phCount)
{
int gaps = phCount;
// enumerate GAPS
GAP gap [ MAX_POTENTIAL_HARMONICS ];
gap[0].len = peaks[pH[0].peakQ].freq;
for (int i=1; i < gaps; i++)
{
int a = pH[i-1].peakQ,
b = pH[i].peakQ;
gap[i].len = peaks[b].freq - peaks[a].freq;
}
for (int i=0; i < gaps; i++)
gap[i].score = 0.;
// find best scoring gap
for (int i=0; i < gaps; i++)
for (int j=0; j < gaps; j++)
{
if (i == j)
continue;
float a = gap[i].len;
float B_ = gap[j].len;
if (a > B_)
continue;
// a < B_
int multiplier = closestInt(B_ / a);
float b = B_ / multiplier;
float dist = fabs(b - a);
float sc = 1. / (dist + 1.);
gap[i].score += sc;
if (multiplier == 1)
gap[j].score += sc;
}
int best = 0;
for (int i=1; i < gaps; i++)
if (gap[i].score > gap[best].score)
best = i;
return gap[best].len;
}