1

For a project, I need to be able to sample random points uniformly from linear subspaces (ie. lines and hyperplanes) within a certain radius. Since these are linear subspaces, they must go through the origin. This should work for any dimension n from which we draw our subspaces for in Rn.

I want my range of values to be from -0.5 to 0.5 (ie, all the points should fall within a hypercube whose center is at the origin and length is 1). I have tried to do the following to generate random subspaces and then points from those subspaces but I don't think it's exactly correct (I think I'm missing some form of normalization for the points):

def make_pd_line_in_rn(p, n, amount=1000):
   # n is the dimension we draw our subspaces from
   # p is the dimension of the subspace we want to draw (eg p=2 => line, p=3 => plane, etc)
   # assume that n >= p
   coeffs = np.random.rand(n, p) - 0.5
   t = np.random.rand(amount, p)-0.5
   return np.matmul(t, coeffs.T)

I'm not really good at visualizing the 3D stuff and have been banging my head against the wall for a couple of days.

Here is a perfect example of what I'm trying to achieve:

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
  • 2
    Could you elaborate on what distribution of subspaces you want and what is incorrect with your above code? – Kyle Parsons Sep 02 '21 at 20:52
  • 1
    I'm guessing you intend `coeffs` to be a basis of your subspace, and `t` to be the coordinates of `amount` points in that basis. However, note that the basis `coeff` is **not** going to be an orthonormal basis. So the points are not going to be taken uniformly at random in a hypercube. They're going to be taken randomly in the parallelepiped defined by the basis. – Stef Sep 02 '21 at 22:28
  • 1
    See this useful question: [How to create random orthonormal matrix in python numpy?](https://stackoverflow.com/questions/38426349/how-to-create-random-orthonormal-matrix-in-python-numpy) – Stef Sep 02 '21 at 22:31

1 Answers1

3

I think I'm missing some form of normalization for the points

Yes, you identified the issue correctly. Let me sum up your algorithm as it stands:

  • Generate a random subspace basis coeffs made of p random vectors in dimension n;
  • Generate coordinates t for amount points in the basis coeffs
  • Return the coordinates of the amount points in R^n, which is the matrix product of t and coeffs.

This works, except for one detail: the basis coeffs is not an orthonormal basis. The vectors of coeffs do not define a hypercube of side length 1; instead, they define a random parallelepiped.

To fix your code, you need to generate a random orthonormal basis instead of coeffs. You can do that using scipy.stats.ortho_group.rvs, or if you don't want to import scipy.stats, refer to the accepted answer to that question: How to create a random orthonormal matrix in python numpy?

from scipy.stats import ortho_group  # ortho_group.rvs random orthogonal matrix
import numpy as np                   # np.random.rand  random matrix

def make_pd_line_in_rn(p, n, amount=1000):
   # n is the dimension we draw our subspaces from
   # p is the dimension of the subspace we want to draw (eg p=2 => line, p=3 => plane, etc)
   # assume that n >= p
   coeffs = ortho_group.rvs(n)[:p]
   t = np.random.rand(amount, p) - 0.5
   return np.matmul(t, coeffs)

Please note that this method returns a rotated hypercube, aligned with the subspace. This makes sense; for instance, if you want to draw a square on a plane embed in R^3, then the square has to be aligned with the plane (otherwise it's not in the plane).

If what you wanted instead, is the intersection of a dimension-n hypercube with the dimension-p subspace, as suggested in the comments, then please do clarify your question.

Stef
  • 13,242
  • 2
  • 17
  • 28
  • 1
    I'm not sure shifting `coeffs` by `-0.5` is such a good idea. Also, this method effectively rotates the hypercube, so that it is aligned with the random subspace. It seems worthwhile clarifying whether this is really what OP wants. – loopy walt Sep 03 '21 at 03:11
  • @loopywalt You're right - it's the coordinates `t` which should be shifted. `coeffs` is the subspace basis and shouldn't be shifted. – Stef Sep 03 '21 at 08:37
  • @loopywalt As for the rotation, it's the way I understood the question, but most importantly it's the only way that can make sense - if you want to draw a square in a plane embed in R^3, then the square has to be aligned with the plane. Otherwise it's not in the plane. – Stef Sep 03 '21 at 08:40
  • 1
    You may well be right, but perhaps OP means the intersection of the random subspace with the hypercube in standard coordinates. I read it that way the first time. It's not entirely clear from the way it is written. – loopy walt Sep 03 '21 at 08:53
  • Ah yes this is exactly what I was looking to do. I see now that the coefficient matrix has to be orthonormal as, correct if I'm wrong, normal as to not scale the points and ensure uniformity and orthogonal as to define a hypercube. I sincerely appreciate your help! – Falafel Fedayi Sep 03 '21 at 21:45
  • @FalafelFedayi The coefficient matrix defines a parallelepiped. The coefficient matrix has to be orthogonal to define a [**rectangular** parallelepiped](https://en.wikipedia.org/wiki/Cuboid), and it has to be normal so that the edges of the parallelepiped all have equal length (a parallelepiped with equal length edges is called a [rhombohedron](https://en.wikipedia.org/wiki/Rhombohedron)). A parallelepiped which is both a rhombohedron and rectangular is a cube. (just like in the plane, a parallelogram which is both a rectangle and a rhombus is a square). – Stef Sep 03 '21 at 22:18