I need a random rotation matrix that rotates random vectors by $\approx \arccos 0.9$
RandomVariate[CircularRealMatrixDistribution[n]]
gives rotation matrices that are unrestricted- Orthogonalizing
IdentityMatrix[n] + small_noise
gives a small rotation, but for larger $n$, this gives a large rotation even for small amount of noise.
Any tips?
Below is a heuristic attempt which adjusts amount of noise until arccos[0.9] target is hit, but it's too slow to run for $n=1000$
ClearAll["Global`*"];
randn[i_] := RandomVariate[NormalDistribution[], i];
randn[i_, j_] := RandomVariate[NormalDistribution[], {i, j}];
(*Generate rotation matrix by orthogonalizing Identity with eps \
perturbation*)
epsRotation[n_, eps_] :=
Module[{M, z, q, r, d, ph, indices},
z = IdentityMatrix[n] + eps randn[n, n];
{q, r} = QRDecomposition[z];
d = Diagonal[r];
ph = d/Abs[d];
M = q*ph;
(*determinant may be -1 corresponding to reflection,
switch 2 rows of the matrix to guarantee true rotation*)
indices = If[Det[M] > 0, Range[n], {2, 1}~Join~Range[3, n]];
M[[indices]]
];
(* Finds eps such that average rotation is about arccos(0.9) *)
On[Assert];
getEps[d_] := Module[{},
x0 = {1}~Join~ConstantArray[0, d - 1];
target = 0.9;
{epsHist, cosHist} = {{}, {}};
eps = 0.001;
For[i = 1, i < 1000, i += 1,
cos = First[x0 . epsRotation[d, eps]];
If[cos < target, eps *= 0.9, eps *= 1.1];
AppendTo[epsHist, eps];
AppendTo[cosHist, cos];];
Assert[0.5 < Mean[cosHist[[-500 ;;]]] < 0.95];
Mean[epsHist[[-500 ;;]]]
];
With[{d = 100},
mat = epsRotation[d, getEps[d]];
vec = randn[d];
angle = vec . mat . vec/Norm[vec]^2;
Print["rotation angle cos: ", angle]
]
RandomPoint[Sphere[1000], 5000]
help?vecs = RandomPoint[Sphere[1000], 10000]; // AbsoluteTiming
is very fast. $\endgroup$Select[vecs, # . v == 0.9 &]
returns an empty list forv = {1,0,0,...,0}
and the max dot product I got was 0.125... so it seems rejection sampling won't work :( $\endgroup$With[{n = 3}, RotationMatrix[ArcCos[0.9], RandomPoint[Sphere[n], 2]]]
Or perhaps I'm misunderstanding from what kind of underlying distribution you want to sample ... $\endgroup$CircularRealMatrixDistribution
which represent rotation matrices.RotationMatrix
is a "simple rotation", and general rotation matrices correspond to combinations of simple rotations (ie, yaw+pitch+roll) $\endgroup$