我将在下面以我想要的精确形式说出问题:
鉴于:
相同长度N
的两个浮点列表D
和k
(k
是2的倍数)。
众所周知,对于所有i=0,...,k-1
,j != i
存在D[j]*D[i] == N[i]*N[j]
。 (我使用的是从零开始的索引)
返回:
一对(k/2
)对(i,j)
列表,D[j]*D[i] == N[i]*N[j]
。
返回的对可能不是唯一的(任何有效的对列表都可以)
该算法的应用是找到广义回文特征值问题的倒数对特征值。
平等条件等同于N[i]/D[i] == D[j]/N[j]
,但在分母为零时也是有效的(这是一种确定的可能性)。特征值问题中的简并导致这些对是非唯一的。
更一般地说,该算法相当于:
鉴于:
长度X
的列表k
(k
是2的倍数)。
众所周知,对于所有i=0,...,k-1
,存在j != i
,IsMatch(X[i],X[j])
返回true,其中IsMatch
是布尔匹配函数,保证至少返回一个所有j != i
都是i
。
返回:
一个(k/2
}对(i,j)
列表,列表中所有对的IsMatch(i,j) == true
。
返回的对可能不是唯一的(任何有效的对列表都可以)
显然,我的第一个问题可以用IsMatch(u,v) := { (u - 1/v) == 0 }
的第二个问题来表达。现在,由于浮点精度的限制,永远不会有完全相等,所以我想要最小化匹配误差的解决方案。换句话说,假设IsMatch(u,v)
返回值u - 1/v
,我希望算法返回一个列表,IsMatch返回最小的错误集。这是一个组合优化问题。我以为我可以先天真地计算所有可能的索引对i
和j
之间的匹配错误,但后来我需要选择最小错误集,我不知道我是怎么做的会这样做。
澄清
IsMatch
函数是自反的(IsMatch(a,b)
暗示IsMatch(b,a)
),但不是传递函数。但是,它是3-transitive:IsMatch(a,b) && IsMatch(b,c) && IsMatch(c,d)
隐含IsMatch(a,d)
。
附录
这个问题显然与图论中最小权重完美匹配问题相同。但是,在我的情况下,我知道应该有一个“良好”的完美匹配,因此边权重的分布不是完全随机的。我觉得应该以某种方式使用这些信息。现在的问题是,对于最小权重完美匹配问题是否有良好的实现,该问题使用我的先前知识在搜索早期达到解决方案。我也对指向任何此类算法的简单实现持开放态度。
答案 0 :(得分:1)
我希望我能解决你的问题。
好吧,如果是IsMatch(i, j) and IsMatch(j, l)
,那么IsMatch(i, l)
。更一般地说,IsMatch
关系是可传递的,可交换的和反身的,即。它是一种等价关系。该算法转换为列表中出现次数最多的元素(使用IsMatch而不是=)。
答案 1 :(得分:0)
(如果我理解这个问题......) 以下是匹配两个列表中每对产品的一种方法。
答案 2 :(得分:0)
嗯..将每对D相乘并将其保存到产品结构的第二个实例,以及构成产品的元素的下标。
答案 3 :(得分:0)
我刚问了我的CS朋友,他想出了下面的算法。他这里没有账户(显然不愿意创建账户),但我认为他的回答值得分享。
// We will find the best match in the minimax sense; we will minimize
// the maximum matching error among all pairs. Alpha maintains a
// lower bound on the maximum matching error. We will raise Alpha until
// we find a solution. We assume MatchError returns an L_1 error.
// This first part finds the set of all possible alphas (which are
// the pairwise errors between all elements larger than maxi-min
// error.
Alpha = 0
For all i:
min = Infinity
For all j > i:
AlphaSet.Insert(MatchError(i,j))
if MatchError(i,j) < min
min = MatchError(i,j)
If min > Alpha
Alpha = min
Remove all elements of AlphaSet smaller than Alpha
// This next part increases Alpha until we find a solution
While !AlphaSet.Empty()
Alpha = AlphaSet.RemoveSmallest()
sol = GetBoundedErrorSolution(Alpha)
If sol != nil
Return sol
// This is the definition of the helper function. It returns
// a solution with maximum matching error <= Alpha or nil if
// no such solution exists.
GetBoundedErrorSolution(Alpha) :=
MaxAssignments = 0
For all i:
ValidAssignments[i] = empty set;
For all j > i:
if MatchError <= Alpha
ValidAssignments[i].Insert(j)
ValidAssignments[j].Insert(i)
// ValidAssignments[i].Size() > 0 due to our choice of Alpha
// in the outer loop
If ValidAssignments[i].Size() > MaxAssignments
MaxAssignments = ValidAssignments[i].Size()
If MaxAssignments = 1
return ValidAssignments
Else
G = graph(ValidAssignments)
// G is an undirected graph whose vertices are all values of i
// and edges between vertices if they have match error less
// than or equal to Alpha
If G has a perfect matching
// Note that this part is NP-complete.
Return the matching
Else
Return nil
它依赖于能够计算完全匹配的图形,这是NP完全的,但至少它被简化为已知问题。预计解决方案是NP完全的,但这是可以的,因为在实践中给定列表的大小非常小。我会在几天内等待更好的答案,或者让某人扩展如何以合理的方式找到完美的匹配。
答案 4 :(得分:0)
你想找到j这样D(i)* D(j)= N(i)* N(j){我假设*是普通的实数乘法}
假设所有N(i)都非零,请
Z(i)= D(i)/ N(i)。
问题:找到j,使得Z(i)= 1 / Z(j)。
拆分设置为正数和负数并单独处理。
为了清晰起见,请记录日志。 z(i)= log Z(i)。
间接排序。然后在排序视图中,你应该有类似-5 -3 -1 +1 +3 +5的东西。读取+/-对,这应该给你原始索引。
我错过了什么,或问题很容易?
答案 5 :(得分:0)
好的,我最终使用this ported Fortran code,我只需使用以下命令指定密集的上三角距离矩阵:
complex_t num = N[i]*N[j] - D[i]*D[j];
complex_t den1 = N[j]*D[i];
complex_t den2 = N[i]*D[j];
if(std::abs(den1) < std::abs(den2)){
costs[j*(j-1)/2+i] = std::abs(-num/den2);
}else if(std::abs(den1) == 0){
costs[j*(j-1)/2+i] = std::sqrt(std::numeric_limits<double>::max());
}else{
costs[j*(j-1)/2+i] = std::abs(num/den1);
}
这很有效,并且足够快,可以达到我的目的。
答案 6 :(得分:0)
您应该能够对(D [i],N [i])对进行排序。您不需要除以零 - 您可以将其乘出,如下所示:
bool order(i,j) {
float ni= N[i]; float di= D[i];
if(di<0) { di*=-1; ni*=-1; }
float nj= N[j]; float dj= D[j];
if(dj<0) { dj*=-1; nj*=-1; }
return ni*dj < nj*di;
}
然后,扫描排序列表以找到两个分离点:(N == D)和(N == -D);你可以从那里开始匹配互惠对,使用:
abs(D[i]*D[j]-N[i]*N[j])<epsilon
作为有效性检查。保留(N == 0)和(D == 0)点为最后一个;无论你认为它们是消极还是积极都没关系,因为它们都会相互匹配。
编辑:或者,您可以单独处理(N == 0)和(D == 0)个案,将其从列表中删除。然后,您可以使用(N [i] / D [i])对其余索引进行排序。您仍然可能希望从1.0和-1.0开始,以确保您可以将接近零的情况与完全为零的情况匹配。