I believe main problem here would be that self avoiding walk does not always have a fixed number of points it can go to. By definition any point can be visited only once, thus on each step the number of viable directions vary, and in your current code it is fixed.
You definitely should store the history of visited points in more friendly way. I would say a list of tuples in form (x, y, z) is a way to go. This allows you to check easier whether a direction you are considering to choose has been already visited. Generally in each step you should go as follow:
- determine which way the walker can go.
- choose the direction randomly with equal probability.
- save the position in history, as to not visit it again.
A simple code for this you can find below:
import random
def get_possible_directions(point):
"""Point is in form (x, y, z)"""
directions = [
(point[0]+1, point[1], point[2]), # right
(point[0]-1, point[1], point[2]), # left
(point[0], point[1]+1, point[2]), # forward
(point[0], point[1]-1, point[2]), # backward
(point[0], point[1], point[2]+1), # up
(point[0], point[1], point[2]-1) # down
]
return directions
def random_walk_3D(N):
Nsteps = range(N)
current_position = (0, 0, 0)
visited_points = []
for _ in Nsteps:
visited_points.append(current_position)
all_directions = get_possible_directions(current_position)
not_visited_directions = [direction for direction in all_directions if direction not in visited_points]
current_position = random.choice(not_visited_directions)
xp, yp, zp = zip(*visited_points)
return xp, yp, zp # returns tuples. If you want lists, just do list(xp), ...
if __name__ == "__main__":
x, y, z = random_walk_3D(10)
print(x)
print(y)
print(z)
You might want to take a look at random documentation. As for the last step in function this could help you.