问题描述
我正在尝试编写 Julia 中的自我避免步行,这是我的代码:
这里我定义了 NxN 矩阵中的位置函数
function position(vertical,horizontal,N)
ud = BitArray(a == vertical for a = 1:N ) # Goes up or down
lr = transpose(BitArray(a == horizontal for a = 1:N )) # Goes left or right
return ud * lr
end
这是描述矩阵内部运动的步行者的代码,其中 1 表示步行者已经在该位置上,0 表示从未去过。 (此外,walker 不允许斜向移动。这部分我设法正确编码)
using StatsBase,Linearalgebra
function SAW(N,Iterations=5) # SAW,Self Avoiding Walk
x = ceil(N/2)
y = ceil(N/2)
Mat = zeros(Int8,N,N)
pos = zeros(Int8,N)
for i in 1:Iterations
RandomOnes = sample(-1:2:1,2,replace = false)[1] #gives the values -1 or 1
ZeroOne = sample(0:1,1,replace = false)[1] #gives the values 0 or 1
# In order to avoid moving diagonally,only one of the two variables (x,y)
# can have the values 1 or -1,the other one has to be 0 (e.g. if x = 1 then y = 0)
if ZeroOne == 1
x += RandomOnes
y += 0
else
x += 0
y += RandomOnes
end
Mat += position(y,x,N)
pos = position(y,N)
end
for i in 1:N
for j in 1:N
if Mat[i,j] > 1
Mat[i,j] += 1 # Here the process should restart,because the walker ran into itself
end
end
end
return Mat,pos
end
SAW(7)[1]
当步行者遇到自己时,我不确定如何重新启动该过程
解决方法
这里有一些你可能会觉得有用的东西。这是一个假设您的晶格可能非常大的解决方案(因此在您的方法中存储矩阵将不适合内存)。我没有针对速度进行优化,但为了简单起见:
function SAW(N::Integer,Iterations::Integer)
@assert N >= 1
@assert Iterations >= 0
# this will store the path we have traversed
path = Tuple{Int,Int}[]
cur = ((N+1) ÷ 2,(N+1) ÷ 2)
push!(path,cur)
for i in 1:Iterations
x,y = cur
# now check the four possible movement directions
# store moves that are allowed in valid vector
valid = Tuple{Int,Int}[]
if x > 1 && !((x-1,y) in path)
push!(valid,(x-1,y))
end
if x < N && !((x+1,(x+1,y))
end
if y > 1 && !((x,y-1) in path)
push!(valid,(x,y-1))
end
if y < N && !((x,y+1) in path)
push!(valid,y+1))
end
if isempty(valid)
# we are stuck and failed to generate a walk of length N
# no moves are possible and we still have not made N moves
return nothing
end
# randomly pick a move from valid moves
cur = rand(valid)
push!(path,cur)
end
# we have successfully generated the walk - return it
return path
end
很明显,这段代码可以很容易地变得更快,但我不想让它复杂化。此外,您可能希望生成的游走具有不同的分布(即,此代码可能会生成所有可能的游走,但模拟过程假定它们具有一个特定的分布)- 同样可以更改。
编辑:
将结果存储在矩阵中的最简单方法是:
julia> N = 10
10
julia> Iterations = 5
5
julia> path = SAW(N,Iterations)
6-element Vector{Tuple{Int64,Int64}}:
(5,5)
(4,5)
(3,6)
(3,7)
(4,7)
julia> m = zeros(Int,N,N)
10×10 Matrix{Int64}:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
julia> foreach(p -> m[p...] = 1,path)
julia> m
10×10 Matrix{Int64}:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
(假设 N
很小)