title: More efficient self-avoiding freely-jointed chain in 3D?
body: <p>I am trying to create a simple self-avoiding <a href="https://en.wikipedia.org/wiki/Ideal_chain" rel="nofollow noreferrer">freely-jointed chain</a>. The chain part is already completed, it starts at a given point in 3D space (e.g. [0,0,0]). I then generate a new point by randomizing two spherical coordinates θ, φ (the radius is given). Giving me a new point.</p>
  <p>Since the points are randomly placed (as opposed to integers a normal 3D walk on a 3D grid), I cannot check if the exact point has been visited before (i.e., iterate over an array of visited points). Instead I have to check if the point lies within a certain radius of previously visited points (small spheres created by every visited point).</p>
  <p>I have tried extracting the part of my code I need help with, and adjusted it so it runs by itself. This is with step length 1, and the &quot;avoid radius&quot; = 0.5 (chosen arbitrarily)</p>
  <pre><code>import numpy as np
  import random
  
  # Generating new point in spherical coordinates, convert to cartesian coordinates
  steps = 10
  visited = np.zeros([steps,3],dtype=float) # &quot;array of all visited points&quot;
  
  steplength= 1
  costheta = random.uniform(-1,1)
  theta = np.arccos(costheta)
  phi = random.random() * 2 * np.pi
  
  newpos = numpy.copy(visited[-1]) # copy of &quot;previous point&quot;
  newpos[0] += steplength* np.cos(phi) * np.sin(theta)
  newpos[1] += steplength* np.sin(phi) * np.sin(theta)
  newpos[2] += steplength* np.cos(theta)
  
  # Self-avoid condition (part I need help with)
  tooclose = False
  for i in range(steps): #For every visited position, check if newpos is too close
      diff = np.subtract(pos, self.visited[i])
      dist = np.sqrt(diff.dot(diff))
      if dist &lt; avoidradius ** 2:
          tooclose = True
          break
  </code></pre>
  <p>As shown in the code, I simply check the distance from every point and check if it's smaller than the allowed radius. This approach works to make it &quot;self-avoiding&quot;, but it is slow. Is there a better way to do it? Perhaps using a different coordinate system, different numpy code (I am not very good at numpy), a different library or a different setup altogether?</p>