具有滞后的简单加权随机游动

时间:2011-02-06 15:50:08

标签: algorithm

我已经为此编写了一个解决方案,但感觉并不“正确”,所以我想要其他人的一些意见。

规则是:

  • 移动位于2D网格上(方向任意标记为N,NE,E,SE,S,SW,W,NW)
  • 在给定方向上移动的概率是相对于行进方向(即40%代表前方)和加权:

[14%] [40%] [14%]
[8%] [4%] [8%]
[4%] [4%] [4%]

这意味着以极大的概率,旅行将沿着当前的轨迹继续前进。中间值表示停止。例如,如果最后一次移动是NW,那么绝对概率将为:

[40%] [14%] [8%]
[14%] [4%] [4%]
[8%] [4%] [4%]

  • 概率是近似的 - 我玩弄的一件事就是在主要计算之外停止了5%的静态概率,这会改变任何其他操作的可能性。

我目前的算法如下(简化伪码):

int[] probabilities = [4,40,14,8,4,4,4,8,14]

if move.previous == null:
    move.previous = STOPPED

if move.previous != STOPPED:
    // Cycle probabilities[1:8] array until indexof(move.previous) = 40%

r = Random % 99

if r < probabilities.sum[0:0]:
    move.current = STOPPED
elif r < probabilities.sum[0:1]:
    move.current = NW
elif r < probabilities.sum[0:2]:
    move.current = NW
...

我真的不喜欢这种方法的原因:
*它迫使我为数组索引分配特定的角色:[0] =停止,[1] =北...
*它强制我在循环时对阵列的子集进行操作(即STOPPED始终保持在原位)
*它非常迭代,因此很慢。它必须依次检查每个值,直到它到达正确的值。循环阵列最多需要4次操作 * 9个if-block(大多数语言不允许动态切换) *停止必须在所有东西都特别包装。

我考虑过的事情:
*循环链表:简化循环(使枢轴始终等于北)但需要维护一组指针,并且仍然需要为特定索引分配角色。
*向量:真的不确定我怎么去加权这个,加上我需要担心幅度 *矩阵:旋转矩阵不能像那样工作:)
*使用众所周知的随机游走算法:Overkill?虽然考虑了建议。 *树木:刚想到这一点,所以没有给它真正的想法......

因此。有没有人有任何好主意?

2 个答案:

答案 0 :(得分:2)

在算法中使用更直接的方向表示,例如(dx,dy)对。 这样您就可以通过x += dx; y += dy;移动 (如果您愿意,您仍然可以使用“方向ENUM”+查找表。)

您的下一个问题是找到“概率表”的良好表示。由于r的范围仅为1到99,因此只需执行一个哑数组并直接使用prob_table[r]即可。

然后,使用您选择的方法计算这些概率表的3x3矩阵。如果它很慢是没关系的,因为你只做了一次。

只需

即可获得下一个方向
prob_table = dir_table[curr_dx][curr_dy];
(curr_dx, curr_dy) = get_next_dir(prob_table, random_number());

答案 1 :(得分:2)

8你有8个方向,当你指向某个方向时,你必须“旋转这个矩阵”

但这仅仅是有限域的模数。

由于你只有100个整数来从中挑选概率,你可以将列表中的所有整数和每个整数点的值推到你方向的索引。

你旋转的方向(模数加法)指向你必须移动的方式。

并且你拥有一个不同的数组,你必须应用于你的行动。

像这样的事情。

                   40 numbers    14 numbers   8 numbers
 int[100] probab={0,0,0,0,0,0,....,1,1,1,.......,2,2,2,...};

然后

                    N      NE    E     SE       STOP   
int[9] next_move={{0,1},{ 1,1},{1,1},{1,-1}...,{0,0}}; //in circle

所以你选择

move=probab[randint(100)]

if(move != 8)//if 8 you got stop
{
   move=(prevous_move+move)%8;
}

move_x=next_move[move][0];
move_y=next_move[move][1];