朱莉娅的自我回避漫步
Self Avoiding Walk in Julia
我正在尝试编写 Julia 中的自我回避行走代码,这是我的代码:
这里我定义了NxN矩阵中的position函数
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 , 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,x,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]
我不知道walker遇到自己时如何重启进程
这里有一些您可能会觉得有用的东西。这是一个假设您的格子可能非常大的解决方案(因此按照您的方法存储矩阵将不适合内存)。为了简单起见,我没有优化它:
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, y) in path)
push!(valid, (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, (x, 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, 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
较小)
我正在尝试编写 Julia 中的自我回避行走代码,这是我的代码:
这里我定义了NxN矩阵中的position函数
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 , 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,x,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]
我不知道walker遇到自己时如何重启进程
这里有一些您可能会觉得有用的东西。这是一个假设您的格子可能非常大的解决方案(因此按照您的方法存储矩阵将不适合内存)。为了简单起见,我没有优化它:
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, y) in path)
push!(valid, (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, (x, 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, 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
较小)