Skip to main content
Code Review

Return to Answer

Add versions using np.linalg.norm
Source Link
mjolka
  • 16.3k
  • 2
  • 30
  • 73

If you just want to do this for the unit circle, you can use numpy.random.uniform to choose the angle \$\theta\$ defining the unit vector.

If you want to deal with the more general case of the \$n\$-sphere, there is a method mentioned on Wikipedia.

To generate uniformly distributed random points on the \$(n − 1)\$-sphere (i.e., the surface of the \$n\$-ball), Marsaglia (1972) gives the following algorithm.

Generate an \$n\$-dimensional vector of normal deviates (it suffices to use \$N(0, 1)\$, although in fact the choice of the variance is arbitrary), \$\mathbf{x}=(x_1,x_2,\ldots,x_n)\$.

Now calculate the "radius" of this point, \$r=\sqrt{x_1^2+x_2^2+\cdots+x_n^2}\$.

The vector \$\frac{1}{r} \mathbf{x}\$ is uniformly distributed over the surface of the unit n-ball.

My attempt at translating that into Python would be

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 r = np.sqrt((x*x).sum())
 return x / r
def gen_rand_vecs(dims, number):
 return [get_rand_vec(dims) for _ in xrange(number)]

@Veedrac's answer alerted me to the existence of np.linalg.norm, which gives us

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 return x / np.linalg.norm(x)

Or

def gen_rand_vecs(dims, number):
 return map(lambda x: x / np.linalg.norm(x),
 [np.random.standard_normal(dims) for _ in xrange(number)])

If you just want to do this for the unit circle, you can use numpy.random.uniform to choose the angle \$\theta\$ defining the unit vector.

If you want to deal with the more general case of the \$n\$-sphere, there is a method mentioned on Wikipedia.

To generate uniformly distributed random points on the \$(n − 1)\$-sphere (i.e., the surface of the \$n\$-ball), Marsaglia (1972) gives the following algorithm.

Generate an \$n\$-dimensional vector of normal deviates (it suffices to use \$N(0, 1)\$, although in fact the choice of the variance is arbitrary), \$\mathbf{x}=(x_1,x_2,\ldots,x_n)\$.

Now calculate the "radius" of this point, \$r=\sqrt{x_1^2+x_2^2+\cdots+x_n^2}\$.

The vector \$\frac{1}{r} \mathbf{x}\$ is uniformly distributed over the surface of the unit n-ball.

My attempt at translating that into Python would be

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 r = np.sqrt((x*x).sum())
 return x / r
def gen_rand_vecs(dims, number):
 return [get_rand_vec(dims) for _ in xrange(number)]

If you just want to do this for the unit circle, you can use numpy.random.uniform to choose the angle \$\theta\$ defining the unit vector.

If you want to deal with the more general case of the \$n\$-sphere, there is a method mentioned on Wikipedia.

To generate uniformly distributed random points on the \$(n − 1)\$-sphere (i.e., the surface of the \$n\$-ball), Marsaglia (1972) gives the following algorithm.

Generate an \$n\$-dimensional vector of normal deviates (it suffices to use \$N(0, 1)\$, although in fact the choice of the variance is arbitrary), \$\mathbf{x}=(x_1,x_2,\ldots,x_n)\$.

Now calculate the "radius" of this point, \$r=\sqrt{x_1^2+x_2^2+\cdots+x_n^2}\$.

The vector \$\frac{1}{r} \mathbf{x}\$ is uniformly distributed over the surface of the unit n-ball.

My attempt at translating that into Python would be

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 r = np.sqrt((x*x).sum())
 return x / r
def gen_rand_vecs(dims, number):
 return [get_rand_vec(dims) for _ in xrange(number)]

@Veedrac's answer alerted me to the existence of np.linalg.norm, which gives us

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 return x / np.linalg.norm(x)

Or

def gen_rand_vecs(dims, number):
 return map(lambda x: x / np.linalg.norm(x),
 [np.random.standard_normal(dims) for _ in xrange(number)])
Source Link
mjolka
  • 16.3k
  • 2
  • 30
  • 73

If you just want to do this for the unit circle, you can use numpy.random.uniform to choose the angle \$\theta\$ defining the unit vector.

If you want to deal with the more general case of the \$n\$-sphere, there is a method mentioned on Wikipedia.

To generate uniformly distributed random points on the \$(n − 1)\$-sphere (i.e., the surface of the \$n\$-ball), Marsaglia (1972) gives the following algorithm.

Generate an \$n\$-dimensional vector of normal deviates (it suffices to use \$N(0, 1)\$, although in fact the choice of the variance is arbitrary), \$\mathbf{x}=(x_1,x_2,\ldots,x_n)\$.

Now calculate the "radius" of this point, \$r=\sqrt{x_1^2+x_2^2+\cdots+x_n^2}\$.

The vector \$\frac{1}{r} \mathbf{x}\$ is uniformly distributed over the surface of the unit n-ball.

My attempt at translating that into Python would be

def get_rand_vec(dims):
 x = np.random.standard_normal(dims)
 r = np.sqrt((x*x).sum())
 return x / r
def gen_rand_vecs(dims, number):
 return [get_rand_vec(dims) for _ in xrange(number)]
lang-py

AltStyle によって変換されたページ (->オリジナル) /