【发布时间】:2015-11-18 16:14:33
【问题描述】:
我有一个 (d) 维度的网格,所有维度都使用 delta = 0.25 进行分区
这个网格的一个例子就是这个图(d这里是2,每个维度归一化0-1):
每个交点代表1个点,例如中间的点表示为:
double[] A={0.5, 0.5};
我的问题是: 我想搜索这个网格,从输入点 A 及其邻居开始。然后继续这样做。有一个条件:每个点只被访问一次。
为了更清楚,请考虑以下示例: 起点是:
double[] A={0.5, 0.5};
因此,首先检查 A,然后生成其邻居并将其插入队列(队列基于函数 f 排序)。
这里的A点是黑圈。它的邻居是绿色圆圈:
{0.25, 0.25}
{0.25, 0.5}
{0.25, 0.75}
..
..
..
{0.75, 0.75}
现在,算法循环,直到队列变空。 在循环中,顶点被移除(pop()),然后被检查,然后它的邻居被添加到队列中。
例如,在第一个循环中,蓝色圆圈恰好是队列中的最高点。 它从队列中移除,然后检查,然后生成它的邻居(红色圆圈)并添加到队列中。
这里的问题是,我生成邻居点的代码不知道之前是否访问过前一个点。
而且我无法保留以前访问过的点的列表,并且每次生成新点时都要检查它(具有高维度和高分辨率,例如 d=8 和 delta= 0.03125,这将永远需要!)
这是搜索算法:
public void search(int d, double delta, double[] inpoint)
{
Queue queue = new Queue();
queue.push(inpoint);
while( !queue.isEmpty() )
{
// remove top point from Queue
double[] a = queue.pop();
// Check point a and do some calculations
// ;;;;;;;;;;;;;;;;
// Generate neighbours of current point:
ArrayList<double[]> neighbors = new ArrayList<double[]>();
nextMoves(a, new double[d], delta, d, neighbors);
// For each point in neighbors, push to Queue:
for( int i=0 ; i < neighbors.size(), i++ )
queue.push(neighbors.get(i));
}
}
这是生成邻居的算法,它是一种递归算法。
public static void nextMoves(double[] inatt, double[] outatt, double delta, int d, ArrayList<double[]> neighbors)
{
if( d == inatt.length )
{
if( !outOfBound(outatt,d) )
{
moves.add(outatt);
}
}
else
{
// first case: add delta:
outatt[d] = inatt[d]+delta;
nextMoves( inatt, outatt, delta, d+1, moves);
// second case: subtract delta:
outatt[d] = inatt[d]-delta;
nextMoves( inatt, outatt, delta, d+1, moves);
// third case: no change:
outatt[d] = inatt[d];
nextMoves( inatt, outatt, delta, d+1, moves);
}
}
正如我之前提到的,保留以前访问过的点的列表不是一个可行的解决方案。 如果我这样做,那么当我具有高维度和高分辨率时,列表会变得非常大。 并且每次创建一个点时都必须线性搜索此列表!
也许我应该在空间索引中组织这个列表?我不知道... 非常感谢您的意见。
【问题讨论】:
-
您能告诉我们您打算在每个点执行什么操作吗?我怀疑是否存在您计划“访问”每个点而不在那里做某事的任何现实世界问题。
-
And this list will have to be searched linearly each time a point is created... 不,如果您可以简单地 access 使用数组中的点,则不必搜索整个列表来检查重复点问题。 -
您的队列类是 FIFO(先进先出)吗?它是否允许检查元素是否已经存在于队列中?
-
@TarunGupta 是的,它是 FIFO。当前代码不检查队列是否已经有要添加的点。这实际上是我要添加的支票所在的位置。如果查看 nextMoves() 函数,在检查该点是否在边界内之后,这里我应该检查它是否已经在队列中,以及之前是否已访问过。
-
@TimBiegeleisen 相信我,如果你设置 d=10 和 delta = 0.03125,你最终会得到大量的分数,这将需要很长时间来检查!