Algorithm 在列表中查找匹配对的算法
我将用下面我想要的精确形式来表达这个问题: 给定的: 两个长度相同的浮点列表Algorithm 在列表中查找匹配对的算法,algorithm,optimization,math,combinatorics,Algorithm,Optimization,Math,Combinatorics,我将用下面我想要的精确形式来表达这个问题: 给定的: 两个长度相同的浮点列表N和D(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],但在分母为零时也有效(这
N
和D
(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]
,但在分母为零时也有效(这是一种确定的可能性)。本征值问题中的简并导致对是非唯一的
更一般地说,该算法相当于:
给定的:
长度为k
的列表X
(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-传递的:IsMatch(a,b)&&IsMatch(b,c)&&IsMatch(c,d)
意味着IsMatch(a,d)
附录
这个问题显然是图论中的最小权完全匹配问题。然而,在我的例子中,我知道应该有一个“好的”完美匹配,所以边权重的分布不是完全随机的。我觉得应该以某种方式利用这些信息。现在的问题是,是否有一个很好的实现最小权重完美匹配的问题,它使用我的先验知识在搜索的早期找到一个解决方案。我也乐于接受关于任何此类算法的简单实现的建议。我希望我了解您的问题 如果
IsMatch(i,j)和IsMatch(j,l)
那么IsMatch(i,l)
。更一般地说,IsMatch
关系是传递的、交换的和自反的,即它是一种等价关系。该算法将转换为列表中出现次数最多的元素(使用IsMatch而不是=)。(如果我理解问题的话…)
这里有一种方法可以匹配两个列表中的每一对产品
嗯..将每对D相乘,并将其与乘积和构成乘积的元素的下标一起保存到结构的第二个实例中。我刚刚问了我的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
//我们将在极小极大意义上找到最佳匹配;我们会尽量减少
//所有对之间的最大匹配错误。阿尔法维持着一个
//最大匹配错误的下限。我们将提高阿尔法直到
//我们找到了解决办法。我们假设MatchError返回一个L_1错误。
//第一部分查找所有可能的字母(如下所示
//所有元素之间的成对误差大于最大最小值
//错误。
α=0
我谨此陈辞:
最小值=无穷大
对于所有j>i:
AlphaSet.Insert(匹配错误(i,j))
如果匹配错误(i,j)Alpha
α=最小值
删除小于Alpha的AlphaSet的所有元素
//下一部分增加Alpha,直到找到解决方案
While!AlphaSet.Empty()
Alpha=AlphaSet.RemoveSmallest()
sol=GetBoundedErrorSolution(Alpha)
如果sol!=nil
返回溶胶
//这是helper函数的定义。它返回
//具有最大匹配错误i的解决方案:
如果由于我们选择Alpha而导致匹配错误0
//外环
如果有效分配[i].Size()>MaxAssignments
MaxAssignments=ValidAssignments[i].Si
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);
}
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;
}
abs(D[i]*D[j]-N[i]*N[j])<epsilon