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

Are there any nearest neighbor data structures using a user provided hint?

本文关键字:提示 最近 邻居 数据结构 存在 用户 是否      更新时间:2023-10-16

我正在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};

由于某种神秘的原因,我认为CCD_ 2与CCD_。所以我打电话给:

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

数据结构应该利用我提供的提示。它应该改进它,直到找到真正的近邻。

如果结构支持插入和删除,则可获得加分。

编辑:

我正在寻找能够在亚线性时间内计算最近邻居的结构。至少在某些情况下是这样。类似k-d树或覆盖树的东西。

我的问题有以下特点:

  1. k-d树的维度过高(5-50个维度)
  2. 频繁插入和删除
  3. 关于哪个向量靠近查询,我总是有一个很好的猜测

我想在一个用于连续数学优化的进化算法中使用这种结构。该算法包含大量候选解。在该算法中,每个解决方案都应该了解其周围环境。

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

我认为您应该尝试并瞄准R-树或M-树。

在这两种情况下,想法都是使用边界体积方法。例如,如果您构建了一个二叉树,则可以使用超平面(表示为Vector)将空间一分为二。超平面可能没有在特定的轴上对齐,点积与矢量的符号指示是继续向左看还是向右看(放置/删除矢量时)。

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

  • 在与节点本身相同的边界体积中定位最近的邻居,这是候选
  • 如果这个候选者比体积的边界更近,那么就完成了
  • 如果不是,则需要在比候选卷更近的相邻卷中进行搜索

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

您可以这样做:

#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;
}

如果你不知道要插入的点数,你可能会使用不同的容器(例如deque)。

存在最近邻图。你可以通过寻找离点最近的边和所有最近的边来找到它,即delaunay三角测量中的三角形。或者可以使用空间索引,例如空间填充曲线。你可以在phpclasses.org下载我的php类hilbert曲线。它使用hilbert曲线来找到哈密尔顿路径。

您可能需要考虑ball树:http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=54F6006443B8E4623DF398158E3284FF?doi=10.1.1.91.8209&rep=rep1&type=pdf