-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrandlangevin.m
66 lines (59 loc) · 2.01 KB
/
randlangevin.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
function Z = randlangevin(n, kappa)
% function Z = randlangevin(n, kappa)
%
% n is an integer >= 2; kappa is a nonnegative vector of length N.
% Z is an n-by-n-by-N matrix such that each n-by-n slice Z(:,:,i) is a
% random matrix on SO(n) distributed according to the isotropic Langevin
% distribution with concentration kappa(i)*eye(n) around the mean eye(n):
%
% pdf: (1/c) * exp( kappa(i) * trace( Z(:,:,i) ) )
% with c as obtained from langevinnormalization(n, kappa(i))
%
% To generate matrices around a mean R in SO(n), simply multiply each slice
% by R (on the left or on the right).
%
% This is a simple acceptance/rejection algorithm with poor performance,
% based on Chikuse's notes in the book Statistics on Special Manifolds
% (where the description is given for O(n) and not for SO(n)). Perhaps a
% better algorithm would be based on the Metropolis-Hastings algorithm,
% like they mention in Chiuso's paper 'Wide sense estimation on the special
% orthogonal group'.
%
% Test code for n = 2:
%
% N = 10000;
% Z = randlangevin(2, 3.5*ones(N,1));
% x = zeros(N, 1);
% for i = 1 : N
% x(i) = angle(Z(1,1,i)+1i*Z(2,1,i));
% end
% lims = linspace(-pi, pi, 51);
% freq = histc(x, lims);
% bar(lims/pi*180, freq, 'histc');
%
% See also: randrot langevinnormalization
%
% Nicolas Boumal, UCLouvain, April 30, 2012.
kappa = kappa(:);
N = length(kappa);
Z = zeros(n, n, N);
exact = isinf(kappa);
Z(:, :, exact) = repmat(eye(n), [1, 1, nnz(exact)]);
todo = find(~exact);
ntodo = length(todo);
while ntodo > 0
Z(:, :, todo) = randrot(n, ntodo);
intodo = rand(ntodo, 1) >= ...
exp(kappa(todo).*(multitrace(Z(:, :, todo))-n));
todo = todo(intodo);
ntodo = length(todo);
end
end
% Recursive implementation ... but matlab does not do tail recursion :(
%
% Z = randrot(n, N);
%
% reject = rand(N, 1) >= exp(kappa.*(diagsum(Z, 1, 2)-n));
% if any(reject)
% Z(:, :, reject) = randlangevin(kappa(reject), n, nnz(reject));
% end