Skip to content

Commit 51338c2

Browse files
committed
Initial commit. Working implementation of FHMC.
0 parents  commit 51338c2

File tree

7 files changed

+490
-0
lines changed

7 files changed

+490
-0
lines changed

main_unimodal.m

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
function main_unimodal(option,varargin)
2+
3+
switch option
4+
case 'plot_only'
5+
plot_unimodal(varargin{1},[0 2]);
6+
return
7+
case 'analysis_only'
8+
post_process_unimodal(varargin{1});
9+
return
10+
otherwise
11+
gen_raw_data_unimodal;
12+
end
13+
end
14+
15+
16+
function gen_raw_data_unimodal(~)
17+
18+
p.ntrials = 8*3; %for parallel processing,use multiples of 8
19+
p.target = 'unimodal';
20+
p.sigma = 1;
21+
p.dt = 1e-3; %1e-2 is no good for calculating Riesz derivative
22+
T = 1e3;
23+
24+
%AIM: 1. Sample trajectory. 2. histogram 2. ACF. 3. MSE
25+
%For FHMC,HMC,
26+
27+
a = [1.2 2];
28+
solver = {'Hamiltonian2','Langevin'}; %'Hamiltonian','Underdamped'};
29+
%for accurate results don't need the other two... too slow
30+
31+
X = zeros(T/p.dt,p.ntrials,length(solver),length(a));
32+
33+
disp('Generating raw data...')
34+
for i = 1:length(a) %group fractional/nonfractional together as this is less familiar to people
35+
aa = a(i);
36+
tic
37+
for j = 1:length(solver)
38+
p.methods.solver = solver{j};
39+
temp = zeros(T/p.dt,p.ntrials);
40+
parfor k = 1:p.ntrials
41+
[temp(:,k),t] = fHMC(T,aa,p);
42+
end
43+
clc
44+
fprintf('Solver: %u/%u\n',j,length(solver))
45+
fprintf('alpha: %u/%u\n',i,length(a))
46+
toc
47+
X(:,:,j,i) = temp;
48+
end
49+
50+
51+
52+
end
53+
54+
n = floor(T/p.dt); %number of samples
55+
t = (0:n-1)*p.dt;
56+
57+
save main_unimodal_raw_data.mat T a solver X t p
58+
end
59+
60+
function post_process_unimodal(Z)
61+
n=50;
62+
binedge = linspace(-5,5,n+1);
63+
bin = binedge(1:end-1) + 0.5*(binedge(2)-binedge(1));
64+
disp('Evaluating histogram, ACF, and MSE')
65+
H = zeros(n,length(Z.solver),length(Z.a));
66+
67+
m = 10/Z.p.dt;%1e4;
68+
tau = (0:m)*Z.p.dt;
69+
ACF = zeros(length(tau),length(Z.solver),length(Z.a));
70+
MSE = zeros(length(tau),length(Z.solver),length(Z.a));
71+
72+
t = (0:5e4)*Z.p.dt;
73+
X = zeros(length(t),length(Z.solver),length(Z.a)); %sample X for visualization
74+
75+
tic
76+
for i = 1:length(Z.a)
77+
for j = 1:length(Z.solver)
78+
x = Z.X(:,:,j,i); x = x(:);
79+
H(:,j,i) = histcounts(x,binedge,'normalization','pdf');
80+
temp_acf = 0;
81+
temp_mse = 0;
82+
for k = 1:Z.p.ntrials
83+
temp_acf = temp_acf + autocorr(Z.X(:,k,j,i),m);
84+
temp_mse = temp_mse + myMSE(Z.X(:,k,j,i),m);
85+
end
86+
ACF(:,j,i) = temp_acf/Z.p.ntrials;
87+
MSE(:,j,i) = temp_mse/Z.p.ntrials;
88+
X(:,j,i) = Z.X(1:length(t),1,j,i);
89+
clc
90+
toc
91+
fprintf('%u / %u\n',i,length(Z.a))
92+
fprintf('%u / %u\n',j,length(Z.solver))
93+
end
94+
end
95+
save main_unimodal_post_process.mat H ACF MSE tau bin binedge t X
96+
end
97+
98+
99+
function plot_unimodal(Q,index)
100+
101+
close all
102+
if any(index == 0) %sample trajectory
103+
f0 = myfigure;
104+
ttl = {'Fractional Hamiltonian Monte Carlo','Fractional Langevin Monte Carlo','Hamiltonian Monte Carlo','Langevin Monte Carlo'};
105+
for k = 1:4
106+
subplot(4,1,k)
107+
[j,i]=ind2sub([2 2],k);
108+
plot(Q.t(1:10:end),Q.X(1:10:end,j,i),'.','color',mycolor(1,k),'markersize',1);
109+
title(ttl(k))
110+
if k<4
111+
set(gca,'xtick',[],'XColor','none');
112+
else
113+
xlabel('t')
114+
end
115+
ylabel('x_t')
116+
%subplotmod;
117+
box off
118+
set(gca,'TickDir','out')
119+
%hold on
120+
%plot(xx,yy,'k--','linewidth',1.5)
121+
ylim([-4 4])
122+
xlim([Q.t(1) Q.t(end)])
123+
end
124+
pos =get(f0,'Position');
125+
set(gcf,'position',[pos(1) pos(2) pos(3) 600])
126+
export_fig(f0,'figures/fig_main_unimodal_postprocess_sample_path.pdf','-pdf','-nocrop','-transparent','-painters');
127+
end
128+
129+
if any(index == 1) %ACF
130+
f1 = myfigure;
131+
% plot(Q.tau,Q.ACF(:,1,1),'-','color',mycolor(1,2),'linewidth',1.5)
132+
% hold on
133+
% plot(Q.tau,Q.ACF(:,2,1),'-','color',mycolor(1,1),'linewidth',1.5)
134+
% plot(Q.tau,Q.ACF(:,1,2),'--','color',mycolor(1,2) ,'linewidth',1.5)
135+
% plot(Q.tau,Q.ACF(:,2,2),'--','color',mycolor(1,1),'linewidth',1.5)
136+
137+
%color scheme default
138+
plot(Q.tau,Q.ACF(:,1:2,1),Q.tau,Q.ACF(:,1:2,2),'--','linewidth',1.5)
139+
hold on
140+
plot(Q.tau([1 end]),[0 0],'color',[0.4 0.4 0.4],'HandleVisibility','off')
141+
142+
xlim([0 8])
143+
xlabel('Time Lag')
144+
ylabel('Autocorrelation function')
145+
legend('FHMC','FLMC','HMC','LMC','box','off')
146+
subplotmod;
147+
offsetAxes;
148+
149+
export_fig(f1,'figures/fig_main_unimodal_postprocess_acf.pdf','-pdf','-nocrop','-transparent','-painters');
150+
end
151+
if any(index == 2)
152+
f2 = myfigure;
153+
gs = makedist('normal');
154+
xx = linspace(-3,3,51);
155+
yy = pdf(gs,xx);
156+
157+
for k = 1:4
158+
subplot(4,1,k)
159+
[j,i]=ind2sub([2 2],k);
160+
bar(Q.bin,Q.H(:,j,i),1,'FaceColor',mycolor(1,k),'EdgeColor',mycolor(1,k),'FaceAlpha',0.5);
161+
%bar(bins,hc,1,'FaceColor',mycolor(2),'EdgeColor',mycolor(0));hold on
162+
set(gca,'xtick',[])
163+
set(gca,'ytick',[])
164+
hold on
165+
plot(xx,yy,'k--','linewidth',1.5)
166+
ylim([0 0.5])
167+
xlim([-4 4])
168+
set(gcf,'position',[100 100 200 600])
169+
end
170+
%export_fig(f2,'figures/fig_main_unimodal_postprocess_histogram.pdf','-pdf','-nocrop','-transparent','-painters');
171+
print(gcf, '-dpdf', 'figures\fig_main_unimodal_postprocess_histogram.pdf');
172+
end
173+
174+
175+
end

mains/subroutines/TrapTime.m

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function T = TrapTime(t)
2+
%INPUT: t = binary variable
3+
%OUTPUT: Time spent in one mode
4+
%t = x < 0;
5+
dt = diff(t);
6+
t_in = find(dt == 1);
7+
t_out = find(dt == -1);
8+
9+
T = zeros(size(t_in));
10+
for j =1 :length(T)
11+
if t_in(j)==1 %ignore influence from initial condition
12+
T(j)=NaN;
13+
continue
14+
end
15+
16+
jj = find(t_out>t_in(j),1);
17+
if isempty(jj) %ignore terminal condition
18+
T(j) = NaN;
19+
else
20+
T(j) = t_out(jj)-t_in(j);
21+
end
22+
end
23+
T(isnan(T))=[];

mains/subroutines/fHMC.m

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
function [X,t] = fHMC(T,a,p)
2+
%Levy Monte Carlo
3+
%INPUT: T = time span (s), a = Levy characteristic exponent
4+
% p = other parameters
5+
%OUTPUT: X = samples, t = time
6+
%
7+
p.depth = 1/p.sigma/p.sigma;
8+
p.rmax = 5; %cutoff
9+
p.xmax = 5; %cutoff
10+
p.x0 = 0;
11+
p.r0 = 1;
12+
13+
%p.methods.drift = 'approx'; %exact (numerically unstable)
14+
15+
16+
%
17+
dt = p.dt;%1e-3; %integration time step (s)
18+
dta = dt.^(1/a); %fractional integration step
19+
20+
n = floor(T/dt); %number of samples
21+
t = (0:n-1)*dt;
22+
x = p.x0; %initial condition
23+
r = p.r0;
24+
X = zeros(n,1); %position
25+
%R = zeros(n,1); %momentum
26+
27+
switch p.target
28+
case 'unimodal'
29+
U = @(x) p.depth*x.*x/2;
30+
dU = @(x) p.depth*x;
31+
case 'bimodal'
32+
s1 = p.location;%2.5;
33+
s2 = -s1;
34+
w = 0.5;
35+
sigma2 = p.sigma.*p.sigma;%0.32;%*(0.32/0.54);
36+
U = @(x) -log( 1e-8 +w*exp(-(x-s1).*(x-s1)/2/sigma2) + (1-w)*exp(-(x-s2).*(x-s2)/2/sigma2))+0.5;
37+
dx = 1e-3;
38+
dU = @(x) (U(x+dx)-U(x-dx))/dx/2;
39+
end
40+
41+
if a<2 %approximation of drift term
42+
ba = @(x) frac_drift(U,dU,x,a); %approximate full Riesz D with partial Dx
43+
else
44+
ba = @(x) -dU(x); %approximation
45+
end
46+
47+
c = gamma(a-1)*(gamma(a/2).^(-2)); %<--should be this!
48+
% if a < 2 %use this for a=1.2 as it seems to give better result???
49+
% c = gamma(a+1)*(gamma(a/2+1).^(-2)); %a = a-2;
50+
% end
51+
%tic
52+
switch p.methods.solver
53+
case 'Hamiltonian'
54+
for i = 1:n
55+
while true
56+
%diffusion term
57+
g = stblrnd(a,0,1,0); %Levy r.v. wt expo a and scale 1
58+
xnew = x + c*r*dt;
59+
rnew = r -c*dU(x)*dt - c*r*dt + g*dta;
60+
%accept criterion
61+
if abs(rnew)<p.rmax %5
62+
x = xnew;
63+
r = rnew;
64+
break %accept
65+
end
66+
end
67+
X(i) = x;
68+
end
69+
case 'Langevin'
70+
for i = 1:n
71+
while true
72+
%diffusion term
73+
g = stblrnd(a,0,1,0); %Levy r.v. wt expo a and scale 1
74+
%NB. when a=2, g~sqrt(2)*gaussian r.v. as it should be
75+
xnew = x + ba(x)*dt + g*dta;
76+
%accept criterion
77+
if abs(xnew)<p.xmax %5
78+
x = xnew;
79+
break %accept
80+
end
81+
end
82+
X(i) = x;
83+
end
84+
case 'Hamiltonian2'
85+
for i = 1:n
86+
while true
87+
%diffusion term
88+
g = stblrnd(a,0,1,0); %Levy r.v. wt expo a and scale 1
89+
xnew = x + ba(x)*dt + r*dt + g*dta;
90+
rnew = r + ba(x)*dt;
91+
%accept criterion
92+
if abs(xnew)<p.xmax %5
93+
x = xnew;
94+
r = rnew;
95+
break %accept
96+
end
97+
end
98+
X(i) = x;
99+
end
100+
case 'Underdamped'
101+
sas = makedist('Stable','alpha',1/a,'beta',0,'gam',1,'delta',0);
102+
dv = 1e-3;
103+
G = @(v) (pdf(sas,v+dv)-pdf(sas,v-dv))/dv/2; %rough approximation
104+
for i = 1:n
105+
while true
106+
%diffusion term
107+
g = stblrnd(a,0,1,0); %Levy r.v. wt expo a and scale 1
108+
109+
rnew = r - dU(x)*dt - r*dt + g*dta;
110+
xnew = x + G(rnew)*dt;
111+
112+
%accept criterion
113+
if abs(rnew)<p.rmax %5
114+
x = xnew;
115+
r = rnew;
116+
break %accept
117+
end
118+
end
119+
X(i) = x;
120+
end
121+
122+
end
123+
%toc

mains/subroutines/frac_drift.m

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function b = frac_drift(U,dU,x,a)
2+
% Method from the paper <Fractional Langevin Monte Carlo...>
3+
% Stable implementation of drift term to avoid 0/0 error for large x
4+
% INPUT: x = scalar or column vector; a = noise expo; type = well type
5+
% U,dU are function handles
6+
7+
a = a - 2; %Levy exponent converted to that used for Riesz derivative
8+
9+
h = 0.1; %discretization
10+
L = 8; %spatial range
11+
K = floor(L/h+1);
12+
k = -K:K; %row vector
13+
g = (-1).^k.*gamma(a+1)./gamma(a/2 -k+1)./gamma(a/2 +k +1);
14+
15+
l = U(x)-U(x-k*h);
16+
l2 = max(l,[],2);
17+
f = -dU(x-k*h).*exp(l-l2);
18+
%f(f<0)=0;
19+
b = sum(g.*f,2)/(h^a).*exp(l2);
20+
21+
%clipping
22+
b(b>1e3) = 500;%1e3; %limit the height of the well
23+
b(b<-1e3) = -500;%1e3; % this is set such that abs(b*dt) = 1

mains/subroutines/myMSE.m

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function MSE = myMSE(s,dT)
2+
%calculate MSE of a sampler from true mean
3+
4+
%dT = 1e4; %ms
5+
dT=dT+1; %to be consistent with matlab autocorr
6+
%if ~exist('MSE','var')
7+
MSE = 0;
8+
k = 1;
9+
for i=1:1e3:length(s)-dT
10+
%ss = angle(cumsum( exp(1i*s(i + (1:dT)-1)) ));
11+
%dss = wrapToPi(ss - true_mean);
12+
dss = cumsum(s(i + (1:dT)-1))./(1:dT)'; %cum mean
13+
MSE = MSE + dss.*dss;
14+
k = k+1;
15+
end
16+
MSE = MSE/k;%(length(s)-dT);
17+
%end
18+
%t = 1:dT;

0 commit comments

Comments
 (0)