是否有使用用户提供的提示的最近邻居数据结构?

时间:2013-08-23 07:02:07

标签: c++ algorithm data-structures computational-geometry nearest-neighbor

我正在寻找一个在R^n中保存向量的数据结构,它可以使用用户提供的关于哪个向量可能接近查询的提示来执行最近邻居查询。例如:

class NearestNeighborStructure;
...
NearestNeighborStructure structure;
Vector vec1 = {1,0,0};
Vector vec2 = {1,1,0};
Vector vec3 = {1,1,1};
structure.insert(vec1);
structure.insert(vec2);
structure.insert(vec3);

现在让我们假设我想找到

的最近邻居
Vector query = {0,0,0};

出于某种神秘的原因,我认为vec2非常接近query。所以我打电话给:

Vector nn = structure.findNNusingHint(query, vec2);  // vec2 is a hint
assert(nn == vec1); // vec1 is the correct nearest neighbor

数据结构应该使用我提供的提示。它应该改进它,直到它得到真正的最近邻居。

如果结构支持插入和删除,则为奖励点。

编辑:

我正在寻找能够在次线性时间内计算最近邻居的结构。至少在某些情况下。类似于k-d treescover trees

我的问题有这些特点:

  1. k-d树的维度太高(5 - 50维)
  2. 经常插入和删除
  3. 我总是很好地猜测哪个向量靠近查询
  4. 我想在用于连续evolutionary algorithmmathematical optimization中使用此结构。该算法包含大量候选解决方案。每个解决方案都应该了解此算法中的周围环境。

    通过略微修改现有解决方案来创建新的候选解决方案。这就是创建新解决方案的现有解决方案是我想要使用的提示。

4 个答案:

答案 0 :(得分:1)

我相信你应该尝试瞄准R-TreeM-Tree

在这两种情况下,我们的想法是使用边界卷方法。例如,如果构建二叉树,则使用超级计划(表示为Vector)将空间分成两半。超级计划可能未在特定轴上对齐,并且带有向量的点积的符号表示是继续向左或向右看(放置/删除向量时)。

对于最近邻搜索,您必须:

  • 在与节点本身相同的边界卷中找到最近邻居,这是候选者
  • 如果候选人比卷的边界更近,那么你就完成了。
  • 如果不是,那么您需要搜索比候选人更近的邻近卷。

我意识到这是非常高级的......具体来说,我不知道有效的分区或更新策略。 R-Tree文章引用了几种方法。

答案 1 :(得分:0)

你可以这样做:

#include <vector>
#include <iostream>

struct Point { int x; int y; int z; };

inline std::ostream& operator << (std::ostream& stream, const Point& p) {
    return stream << p.x << ", " << p.y << ", " << p.z;
}

struct NearestNeighborStructure
{
    NearestNeighborStructure(std::size_t num_points) {
        m_points.reserve(num_points);
    }

    void insert(const Point& p) {
        m_points.push_back(p);
    }

    int manhattan_distance(const Point& a, const Point& b) const {
        using std::abs;
        return abs(b.x - a.x) + abs(b.y - a.y)  + abs(b.z - a.z);
    }

    const Point& find(const Point& query /* ignored hint*/) const {
        std::size_t result = 0;
        int distance = std::numeric_limits<int>::max();
        for(std::size_t i = 0; i < m_points.size(); ++i) {
            int d = manhattan_distance(query, m_points[i]);
            if(d < distance) {
                result = i;
                distance = d;
            }
        }
        return m_points[result];
    }

    private:
    std::vector<Point> m_points;
};

int main()
{
    Point p[3] = { {1,0,0}, {1,1,0},  {1,1,1} };
    NearestNeighborStructure structure(3);
    structure.insert(p[0]);
    structure.insert(p[1]);
    structure.insert(p[2]);

    Point query = {0,0,0};
    std::cout << "Nearest: " << structure.find(query) << std::endl;
    return 0;
}

如果您不知道要插入的点数,可以使用不同的容器(例如双端队列)。

答案 2 :(得分:0)

有最近邻图。您可以通过查找该点的最近边缘以及delaunay三角剖分中的所有最近边缘,即三角形来找到它。或者您可以使用空间索引,例如空间填充曲线。你可以在phpclasses.org下载我的php类hilbert曲线。它使用希尔伯特曲线找到哈密顿路径。

答案 3 :(得分:0)