用python模拟和绘制SAW路径(自回避随机行走问题)

自回避随机行走问题(SAW),即在格点上不与历史轨迹相撞的随机行走,本文简要说明一种利用python模拟和绘制SAW路径的方法。(完整代码在文章末尾,文字部分是按思考的顺序,代码是最终版本,中间部分代码会出现和文字有出入的内容,建议先看思路)

该路径生成碰到的主要问题是锁死,原因在于路径闭合后随机走向了空间有限的一侧,导致在达到设定步数前出现无路可走的情况。该方法的核心就是在路径闭合时选择闭合圈的外侧,避免进入圈内锁死。

为简单起见所用的是标准的方形网格,可能的前进方向只有4种,排除上一步的落点对应方向,除第一步外(第一步四向随机)可能前进的方向至多三种。设定一个每步更新的可行方向集合,接下来的限制条件均是从中去除某些项。

(Tips:方向可设为ev=[(1,0),(0,1),(-1,0),(0,-1)],行进用坐标相加,某方向的取反%4,向右(-1)%4,向左(+1)%4,后面会用上)

ev=[(1,0),(0,1),(-1,0),(0,-1)]

为了避免判断历史轨迹需要遍历,将网格赋值为零矩阵,每一步的落点赋值为1,仅需判断周围格点的值,不为0可把对应方向排除。边界设为-1,避免和路径混淆。

order=np.zeros((2*s+3,2*s+3),dtype=int)       #顺序矩阵
direc=[]                            #方向矩阵
for i in np.arange(2*s+3):          #设定边界为-1
    order[0][i]=-1
    order[-1][i]=-1
    order[i][0]=-1
    order[i][-1]=-1       
nucx=[s+1]                           #路径位置记录
nucy=[s+1]
new=(s+1,s+1)                        #暂时位置
order[s+1][s+1]=1                    #设定起点

经简单推导可知,仅路径前端的前、左、右,斜前方5格内出现1才会出现锁死的可能,故就此进行分类讨论。(示意图如下,红色为路径,黄色为讨论区块)

垂直方向(五角星处)优先判断,出现一个1记一个“wall”(每步清零),且在可行方向集合中除去该方向。

wall=0
avi=[0,1,2,3]
ju=0
if k!=0:                         #第一步完全随机
    avi.remove((direc[-1]+2)%4)
    for i in np.arange(3):
        ju=order[new[0]+ev[(direc[-1]-1+i)%4][0]][new[1]+ev[(direc[-1]-1+i)%4][1]]
        if ju!=0:
            wall+=1
            avi.remove((direc[-1]-1+i)%4)

wall==3即为锁死,可输出锁死时的步数和位置,输出图进行比对,检查出现锁死的原因。(在前期用于修正和添加限制条件,认图找端点困难时步数也一般很大,出现锁死的几率不大,算法接近完整后可换成归零条件,即重新计算至能跑到规定步数为止)

 if wall==3:
     #print(k)
     #print(new)
     restart=True
     break

wall==2即只有一个方向可走,下一步方向唯一,无需再做排除。

wall==1即有一个方向被堵,此时分为两种情况:前方被堵和侧面被堵。其中前方被堵必定出现了路径闭合,只能选择一个方向。经推导易知在闭合圈不包围原点时,应排除与"wall"所在格前一步或后一步相同的方向(在可行方向内);包围原点时,应排除相反的方向。

 

此时发现原本的数值矩阵不能用于该判断,再引入一个方向集合和顺序矩阵,顺序矩阵可以代替数值矩阵。方向集合记录每一步 的方向(ev集合的序号),顺序矩阵初始也是零矩阵,每步的落点赋值该步的顺序。判断某点前后的方向只需以该点顺序作为索引调取方向集合的值。

判断闭合圈是否包围原点则从发生闭合的端点开始(此处是从"wall"所在格开始),沿路径检查其经过象限。新增一个判断集合,若新元素和集合内已有的倒数第二个元素相同(如出现1 4 1),则该元素和倒数第一个元素都可弃置(对是否围住原点没有影响

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值