Skip to content

Commit f43a0e4

Browse files
author
Christopher Fonnesbeck
committed
Raise error for sparse matrix without scikits.sparse installed in hmc
1 parent 6f1f5ba commit f43a0e4

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

pymc/step_methods/hmc.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
Created on Mar 7, 2011
33
44
@author: johnsalvatier
5-
'''
5+
'''
66
from numpy import floor
77
from quadpotential import *
88
from arraystep import *
9-
from ..core import *
9+
from ..core import *
1010
import numpy as np
11+
from scipy.sparse import issparse
1112

1213
__all__ = ['HamiltonianMC']
1314

14-
#TODO:
15+
#TODO:
1516
#add constraint handling via page 37 of Radford's http://www.cs.utoronto.ca/~radford/ham-mcmc.abstract.html
1617

1718
def unif(step_size, elow = .85, ehigh = 1.15):
@@ -30,59 +31,62 @@ def __init__(self, vars, C, step_scale = .25, path_length = 2., is_cov = False,
3031
step_scale : float, default=.25
3132
Size of steps to take, automatically scaled down by 1/n**(1/4) (defaults to .25)
3233
path_length : float, default=2
33-
total length to travel
34+
total length to travel
3435
is_cov : bool, default=False
3536
Treat C as a covariance matrix/vector if True, else treat it as a precision matrix/vector
36-
step_rand : function float -> float, default=unif
37-
A function which takes the step size and returns an new one used to randomize the step size at each iteration.
38-
state
37+
step_rand : function float -> float, default=unif
38+
A function which takes the step size and returns an new one used to randomize the step size at each iteration.
39+
state
3940
State object
4041
model : Model
4142
"""
4243
model = modelcontext(model)
4344
n = C.shape[0]
44-
45+
4546
self.step_size = step_scale / n**(1/4.)
46-
47+
48+
if issparse(C):
49+
raise ValueError("Cannot use sparse matrix for scaling without scikits.sparse installed")
4750
self.potential = quad_potential(C, is_cov)
51+
4852
self.path_length = path_length
4953
self.step_rand = step_rand
5054

5155
if state is None:
5256
state = SamplerHist()
5357
self.state = state
5458

55-
ArrayStep.__init__(self,
59+
ArrayStep.__init__(self,
5660
vars, [model.logpc, model.dlogpc(vars)]
5761
)
5862

5963
def astep(self, q0, logp, dlogp):
60-
61-
64+
65+
6266
#randomize step size
63-
e = self.step_rand(self.step_size)
67+
e = self.step_rand(self.step_size)
6468
nstep = int(floor(self.path_length / self.step_size))
65-
66-
q = q0
69+
70+
q = q0
6771
p = p0 = self.potential.random()
68-
72+
6973
#use the leapfrog method
7074
p = p - (e/2) * -dlogp(q) # half momentum update
71-
72-
for i in range(nstep):
75+
76+
for i in range(nstep):
7377
#alternate full variable and momentum updates
7478
q = q + e * self.potential.velocity(p)
7579
if i != nstep - 1:
7680
p = p - e * -dlogp(q)
77-
81+
7882
p = p - (e/2) * -dlogp(q) # do a half step momentum update to finish off
79-
80-
p = -p
81-
83+
84+
p = -p
85+
8286
# - H(q*, p*) + H(q, p) = -H(q, p) + H(q0, p0) = -(- logp(q) + K(p)) + (-logp(q0) + K(p0))
8387
mr = (-logp(q0)) + self.potential.energy(p0) - ((-logp(q)) + self.potential.energy(p))
8488

8589
self.state.metrops.append(mr)
86-
90+
8791
return metrop_select(mr, q, q0)
88-
92+

0 commit comments

Comments
 (0)