How can one generate a random vector $v=[v_1, v_2, v_3]^T$ satisfying $\sqrt{v_1v_1^* + v_2 v_2^* + v_3 v_3^*} = 1$, where $T$ and $*$ denote the transpose and complex-conjugate, respectively?
2 Answers
This is a very simple 1-liner giving a list of n
such random vectors
sphericalrandom[n_] := Normalize /@ RandomVariate[NormalDistribution[0, 1], {n, 3}]
Note that these are uniformly distributed on the sphere, since the multivariate normal distribution is invariant under rotation (consider the covariance matrix, R.I.Transpose[R] = I
)
We can easily verify that the requirement is met
sphericalrandom[6]
(* {{-0.277119, -0.913442, -0.298042}, {0.784793,
0.124294, -0.607166}, {0.0794014, -0.138744, 0.98714}, {0.477633,
0.578417, -0.661287}, {0.182014, -0.443811,
0.877441}, {-0.967141, -0.236544, 0.0931965}} *)
# . # & /@ %
(* {1., 1., 1., 1., 1., 1.} *)
The question seems to request complex numbers subject to the same criteria. This is very easily done
sphericalrandomcomplex[n_] :=
Normalize /@ (RandomVariate[
NormalDistribution[0, 1], {n, 3, 2}] . {1, I})
Again, the normalisation checks
sphericalrandomcomplex[6]
(* {{0.0291155 + 0.299873 I, 0.118097 + 0.105762 I,
0.872673 + 0.350054 I}, {-0.476609 - 0.271261 I,
0.762756 + 0.326494 I,
0.0928805 - 0.0473263 I}, {0.482045 + 0.36627 I, -0.627184 -
0.11854 I,
0.183277 + 0.438722 I}, {-0.445669 - 0.472578 I, -0.0542457 +
0.260653 I, 0.129732 + 0.700241 I}, {0.398994 + 0.191309 I,
0.147118 - 0.353526 I, -0.455474 - 0.670913 I}, {-0.157891 +
0.0766977 I, 0.66208 + 0.28717 I, -0.261425 + 0.616465 I}} *)
# . Conjugate[#] & /@ %
(* {1. + 0. I, 1. + 0. I, 1. + 0. I, 1. + 0. I, 1. + 0. I,
1. + 0. I} *)
Generate a single such vector:
Complex @@@ Partition[RandomPoint@Sphere[{0, 0, 0, 0, 0, 0}], 2]
Generate n
of them with good performance:
n = 100;
#1 + I #2 & @@ Transpose[
ArrayReshape[RandomPoint[Sphere[{0, 0, 0, 0, 0, 0}], n], {n, 3, 2}],
{2, 3, 1}
]
This method will sample uniformly from the 3-dimensional complex sphere.
At this point, it is appropriate to discuss why one of the suggestions in the comments will not work. The suggestion is the following for reals:
lst=Normalize /@ RandomReal[{}, {n, 3}]
or the same with RandomComplex
for complexes.
This will not sample uniformly from the sphere. It sampled from the unit cube, then normalized each element. That leads to a biased distribution, first, because we are restricted to the first octant. This fault is easily fixed by extending to all octants:
lst = Normalize /@ RandomReal[{-1, 1}, {10000, 3}];
However, the sampling is still not uniform, as vectors in the direction of the cube edges will appear more frequently. This is plainly visible in a plot:
Graphics3D[{Opacity[0.5], Point[lst]}]
This can be saved by restricting the sampling to the unit ball before normalizing each vector:
n = 100;
eps = 0.001;
result = Normalize /@ Select[RandomReal[{-1, 1}, {n, 3}], eps < Norm[#] <= 1 &];
eps
here is an abirtrary small number that helps avoid numerical imprecision for points very close to the origin. Extension to complexes is possible with RandomComplex[{-1-I, 1+I}, ...]
.
However, this method does not generate n
points, but fewer.
Length[result]
(* 53 *)
One needs to do a bit more work to get precisely n
points. This is why I chose to use RandomPoint
for my answer.
Update: See @mikado's answer which starts with the normal distribution (which is isotropic) instead of uniform distribution in a cube, and thus avoids the need for the Select
above, and makes it easy to generate precisely the desired number of points.
lst=Normalize /@ RandomReal[{}, {n, 3}]
where instead ofn
you should put the desired number of vectors. By evaluationlst /. {x_, y_, z_} -> x^2 + y^2 + z^2
you can make sure that they all have a unit length. $\endgroup$RandomComplex
and uselst /. {x_, y_, z_} -> x*Conjugate[x] + y*Conjugate[y] + z*Conjugate[z] // Chop
for the check. $\endgroup${1,0,0}
and zero to everything else. You might that that that is not random, but why? It is a valid distribution. Then I would ask you to define what you mean by "random". $\endgroup$