C++ 找到向量中所有值之间的相似距离并将其子集

C++ 找到向量中所有值之间的相似距离并将其子集,c++,algorithm,opencv,vector,distance,C++,Algorithm,Opencv,Vector,Distance,给定的是一个具有双值的向量。我想知道这个向量的任何元素之间的哪些距离彼此有相似的距离。在最佳情况下,结果是原始值子集的向量,其中子集应至少有n个成员 //given vector<double> values = {1,2,3,4,8,10,12}; //with simple values as example //some algorithm //desired result as: vector<vector<double> > subset; //

给定的是一个具有双值的向量。我想知道这个向量的任何元素之间的哪些距离彼此有相似的距离。在最佳情况下,结果是原始值子集的向量,其中子集应至少有n个成员

//given
vector<double> values = {1,2,3,4,8,10,12}; //with simple values as example

//some algorithm

//desired result as:
vector<vector<double> > subset;
//in case of above example I would expect some result like:
//subset[0] = {1,2,3,4}; //distance 1
//subset[1] = {8,10,12}; //distance 2
//subset[2] = {4,8,12}; // distance 4
//subset[3] = {2,4};    //also distance 2 but not connected with subset[1]
//subset[4] = {1,3};    //also distance 2 but not connected with subset[1] or subset[3]
//many others if n is just 2. If n is 3 (normally the minimum) these small subsets should be excluded.
//给定
向量值={1,2,3,4,8,10,12}//以简单值为例
//一些算法
//预期结果如下:
向量子集;
//在上述示例中,我希望得到如下结果:
//子集[0]={1,2,3,4}//距离1
//子集[1]={8,10,12}//距离2
//子集[2]={4,8,12};//距离4
//子集[3]={2,4}//也是距离2,但不与子集[1]相连
//子集[4]={1,3}//距离2,但不与子集[1]或子集[3]相连
//如果n仅为2,则还有许多其他情况。如果n为3(通常为最小值),则应排除这些小子集。
这个例子被简化为整数的距离可以被迭代并测试向量,而不是double或float的情况

到目前为止我的想法

我想到了一些类似于计算距离并将它们存储在向量中的东西。创建差分距离矩阵,并对该矩阵设置阈值,以获得类似距离的公差

//计算距离:结果是一个向量
矢量距离;
对于(int i=0;i=j)
继续;
距离。推回(abs(值[i]-值[j]);
}
//计算这些距离的差:结果是一个矩阵
Mat DiffDistances=Mat::零(大小(distance.Size(),distance.Size()),CV_32FC1);
对于(int i=0;i=j)
继续;
距离(i,j)=abs(距离[i],距离[j]);
}
//阈值此矩阵在不同距离上具有一定公差
阈值(DiffDistances、DiffDistances、maxDistTol、255、CV\u THRESH\u BINARY\u INV);
//获取具有相似距离的点
向量扩散点;
findNonZero(DiffDistances,DiffDistancesPoints);

在这一点上,我陷入了寻找与相似距离对应的原始值的困境。应该可以找到它们,但追溯索引似乎非常复杂,我想知道是否有更简单的方法来解决这个问题。

这里有一个算法与您的算法略有不同,它是向量长度
n
O(n^3)
,效率不高

它基于这样一个前提,即您希望子集的大小至少为2。因此,你可以考虑向量的所有两个元素子集,然后找到所有匹配的元素。

给定一个函数

std::vector<int> findSubset(std::vector<int> v, int baseValue, int distance) {
  // Find the subset of all elements in v that differ by a multiple of 
  // distance from the base value
}
std::vector findSubset(std::vector v,int baseValue,int distance){
//查找v中所有元素的子集,这些元素的差值为
//距离基准值的距离
}
你能行

std::vector<std::vector<int>> findSubsets(std::vector<int> v) {
  for(int i = 0; i < v.size(); i++) {
    for(int j = i + 1; j < v.size(); j++) {
      subsets.push_back(findSubset(v, v[i], abs(v[i] - v[j])));
    }
  }

  return subsets;
}
std::vector findSubsets(std::vector v){
对于(int i=0;i

唯一剩下的问题是跟踪重复项,也许您可以为已经找到的所有子集保留(
baseValue%distance
distance
)对的哈希列表。

这里有一个与您的算法稍有不同的算法,即
O(n^3)
在向量的长度
n
中-效率不高

它基于这样一个前提,即您希望子集的大小至少为2。因此,你可以考虑向量的所有两个元素子集,然后找到所有匹配的元素。

给定一个函数

std::vector<int> findSubset(std::vector<int> v, int baseValue, int distance) {
  // Find the subset of all elements in v that differ by a multiple of 
  // distance from the base value
}
std::vector findSubset(std::vector v,int baseValue,int distance){
//查找v中所有元素的子集,这些元素的差值为
//距离基准值的距离
}
你能行

std::vector<std::vector<int>> findSubsets(std::vector<int> v) {
  for(int i = 0; i < v.size(); i++) {
    for(int j = i + 1; j < v.size(); j++) {
      subsets.push_back(findSubset(v, v[i], abs(v[i] - v[j])));
    }
  }

  return subsets;
}
std::vector findSubsets(std::vector v){
对于(int i=0;i

唯一剩下的问题是跟踪重复项,也许您可以为已经找到的所有子集保留(
baseValue%distance
distance
)对的哈希列表。

这里有一个可行的解决方案,只要没有分支,没有比
2*阈值
更接近的值。这是有效的邻域,因为如果我正确理解@Phann,相邻键的差值应该小于阈值

这个解决方案肯定既不是最快也不是最好的解决方案。但您可以将其作为起点:

#include <iostream>
#include <vector>
#include <algorithm>

int main(){
    std::vector< double > values = {1,2,3,4,8,10,12};
    const unsigned int nValues = values.size();
    std::vector< std::vector< double > > distanceMatrix(nValues - 1);
    // The distanceMatrix has a triangular shape
    // First vector contains all distances to value zero
    // Second row all distances to value one for larger values
    // nth row all distances to value n-1 except those already covered
    std::vector< std::vector< double > > similarDistanceSubsets;
    double threshold = 0.05;

    std::sort(values.begin(), values.end());

    for (unsigned int i = 0; i < nValues-1; ++i) {
        distanceMatrix.at(i).resize(nValues-i-1);
        for (unsigned j = i+1; j < nValues; ++j){
            distanceMatrix.at(i).at(j-i-1) = values.at(j) - values.at(i);
        }
    }

    for (unsigned int i = 0; i < nValues-1; ++i) {
        for (unsigned int j = i+1; j < nValues; ++j) {
            std::vector< double > thisSubset;
            double thisDist = distanceMatrix.at(i).at(j-i-1);

            // This distance already belongs to another cluster
            if (thisDist < 0) continue;

            double minDist  = thisDist - threshold;
            double maxDist  = thisDist + threshold;
            thisSubset.push_back(values.at(i));
            thisSubset.push_back(values.at(j));
            //Indicate that this is already clustered
            distanceMatrix.at(i).at(j-i-1) = -1;

            unsigned int lastIndex = j;
            for (unsigned int k = j+1; k < nValues; ++k) {
                thisDist = distanceMatrix.at(lastIndex).at(k-lastIndex-1);

                // This distance already belongs to another cluster
                if (thisDist < 0) continue;

                // Check if you found a new valid pair
                if ((thisDist > minDist) && (thisDist < maxDist)){
                    // Update the valid distance interval
                    minDist = thisDist - threshold;
                    minDist = thisDist - threshold;
                    // Add the newly found point
                    thisSubset.push_back(values.at(k));
                    // Indicate that this is already clustered
                    distanceMatrix.at(lastIndex).at(k-lastIndex-1) = -1;
                    // Continue the search from here 
                    lastIndex = k;
                }
            }
            if (thisSubset.size() > 2) {
                similarDistanceSubsets.push_back(thisSubset);
            }
        }
    }
    for (unsigned int i = 0; i < similarDistanceSubsets.size(); ++i) {
        for (unsigned int j = 0; j < similarDistanceSubsets.at(i).size(); ++j) {
            std::cout << similarDistanceSubsets.at(i).at(j);
            if (j != similarDistanceSubsets.at(i).size()-1) {
                std::cout << " ";
            }
            else {
                std::cout << std::endl;
            }
        }
    }
}
#包括
#包括
#包括
int main(){
向量值={1,2,3,4,8,10,12};
常量unsigned int nValues=values.size();
std::vector>距离矩阵(nvalue-1);
//距离矩阵是三角形的
//第一个向量包含值为零的所有距离
//第二行“所有距离”值为1表示更大的值
//第n行所有距离值n-1,已覆盖的距离除外
std::vector>相似距离子集;
双阈值=0.05;
排序(values.begin(),values.end());
for(无符号整数i=0;i这个子集;
加倍此距离=距离