1 """
2 Various Monte Carlo equilibrium sampling algorithms, which simulate only one Markov chain.
3
4 Here is how to sample from a PDF using the L{HMCSampler} class. In the following
5 snippet we draw 5000 samples from a 1D normal distribution and plot them:
6
7
8 >>> import numpy
9 >>> from csb.io.plots import Chart
10 >>> from csb.statistics.pdf import Normal
11 >>> from csb.statistics.samplers import State
12 >>> from csb.statistics.samplers.mc.singlechain import HMCSampler
13
14 >>> initial_state = State(numpy.array([1.]))
15 >>> grad = lambda q, t: q
16 >>> timestep = 1.5
17 >>> nsteps = 30
18 >>> nsamples = 5000
19
20 >>> sampler = HMCSampler(Normal(), initial_state, grad, timestep, nsteps)
21
22 >>> states = []
23 >>> for i in range(nsamples):
24 sampler.sample()
25 states.append(sampler.state)
26
27 >>> print('acceptance rate:', sampler.acceptance_rate)
28 0.8
29
30 >>> states = [state.position[0]for state in states]
31 >>> chart = Chart()
32 >>> chart.plot.hist([numpy.random.normal(size=5000), states], bins=20, normed=True)
33 >>> chart.plot.legend(['numpy.random.normal', 'HMC'])
34 >>> chart.show()
35
36
37 First, several things which are being needed are imported.
38 As every sampler in this module implements a Markov Chain, an initial state has to be
39 chosen. In the following lines, several parameters are set:
40 - the gradient of the negative log-probability of the PDF under consideration
41 - the integration timestep
42 - the number of integration steps to be performed in each iteration, that is, the HMC
43 trajectory length
44 - the number of samples to be drawn
45
46 The empty list states is initialized. It will serve to store the samples drawn.
47 In the loop, C{sampler.sample()} is repeatedly called. After each call of C{sampler.sample()},
48 the current state of the Markov Chain is stored in sampler.state and this state is appended
49 to the sample storage list.
50
51 Then the acceptance rate is printed, the numeric values are being extracted from the
52 L{State} objects in states, a histogram is created and finally plotted.
53 """
54
55 import numpy
56 import csb.numeric
57 import csb.core
58
59 from abc import ABCMeta, abstractmethod
60
61 from csb.statistics.samplers import State
62 from csb.statistics.samplers.mc import AbstractMC, MCCollection, augment_state
63 from csb.statistics.samplers.mc.propagators import MDPropagator
64 from csb.statistics.samplers.mc.neqsteppropagator import NonequilibriumStepPropagator
65 from csb.numeric.integrators import FastLeapFrog
66 from csb.numeric import InvertibleMatrix
70 """
71 Abstract class for Monte Carlo sampling algorithms simulating
72 only one ensemble.
73
74 @param pdf: probability density function to sample from
75 @type pdf: subclass of L{csb.statistics.pdf.AbstractDensity}
76
77 @param state: Initial state
78 @type state: L{State}
79
80 @param temperature: Pseudo-temperature of the Boltzmann ensemble
81 M{p(x) = 1/N * exp(-1/T * E(x))} with the
82 pseudo-energy defined as M{E(x) = -log(p(x))}
83 where M{p(x)} is the PDF under consideration
84 @type temperature: float
85 """
86
87 __metaclass__ = ABCMeta
88
89 - def __init__(self, pdf, state, temperature=1.):
98
102
104 """
105 Draw a sample.
106
107 @rtype: L{State}
108 """
109
110 proposal_communicator = self._propose()
111 pacc = self._calc_pacc(proposal_communicator)
112
113 accepted = None
114 if numpy.random.random() < pacc:
115 accepted = True
116 else:
117 accepted = False
118
119 if accepted == True:
120 self._accept_proposal(proposal_communicator.proposal_state)
121
122 self._update_statistics(accepted)
123 self._last_move_accepted = accepted
124
125 return self.state
126
127 @abstractmethod
129 """
130 Calculate a new proposal state and gather additional information
131 needed to calculate the acceptance probability.
132
133 @rtype: L{SimpleProposalCommunicator}
134 """
135 pass
136
137 @abstractmethod
139 """
140 Calculate probability with which to accept the proposal.
141
142 @param proposal_communicator: Contains information about the proposal
143 and additional information needed to
144 calculate the acceptance probability
145 @type proposal_communicator: L{SimpleProposalCommunicator}
146 """
147 pass
148
150 """
151 Accept the proposal state by setting it as the current state of the sampler
152 object
153
154 @param proposal_state: The proposal state
155 @type proposal_state: L{State}
156 """
157
158 self.state = proposal_state
159
161 """
162 Update the sampling statistics.
163
164 @param accepted: Whether or not the proposal state has been accepted
165 @type accepted: boolean
166 """
167
168 self._nmoves += 1
169 self._accepted += int(accepted)
170
171 @property
173 """
174 Log-likelihood of the current state.
175 @rtype: float
176 """
177 return self._pdf.log_prob(self.state.position)
178
179 @property
181 """
182 Acceptance rate.
183 """
184 return float(self._accepted) / float(self._nmoves)
185
186 @property
188 """
189 Information whether the last MC move was accepted or not.
190 """
191 return self._last_move_accepted
192
193 @property
195 return self._temperature
196
199 """
200 Hamilton Monte Carlo (HMC, also called Hybrid Monte Carlo by the inventors,
201 Duane, Kennedy, Pendleton, Duncan 1987).
202
203 @param pdf: Probability density function to be sampled from
204 @type pdf: L{csb.statistics.pdf.AbstractDensity}
205
206 @param state: Inital state
207 @type state: L{State}
208
209 @param gradient: Gradient of the negative log-probability
210 @type gradient: L{AbstractGradient}
211
212 @param timestep: Timestep used for integration
213 @type timestep: float
214
215 @param nsteps: Number of integration steps to be performed in
216 each iteration
217 @type nsteps: int
218
219 @param mass_matrix: Mass matrix
220 @type mass_matrix: n-dimensional L{InvertibleMatrix} with n being the dimension
221 of the configuration space, that is, the dimension of
222 the position / momentum vectors
223
224 @param integrator: Subclass of L{AbstractIntegrator} to be used for
225 integrating Hamiltionian equations of motion
226 @type integrator: L{AbstractIntegrator}
227
228 @param temperature: Pseudo-temperature of the Boltzmann ensemble
229 M{p(x) = 1/N * exp(-1/T * E(x))} with the
230 pseudo-energy defined as M{E(x) = -log(p(x))}
231 where M{p(x)} is the PDF under consideration
232 @type temperature: float
233 """
234
235 - def __init__(self, pdf, state, gradient, timestep, nsteps,
236 mass_matrix=None, integrator=FastLeapFrog, temperature=1.):
259
267
286
287 @property
289 return self._timestep
290
291 @timestep.setter
293 self._timestep = float(value)
294 if "_propagator" in dir(self):
295 self._propagator.timestep = self._timestep
296
297 @property
300
301 @nsteps.setter
303 self._nsteps = int(value)
304
305 @property
307 return self._mass_matrix
308 @mass_matrix.setter
310 self._mass_matrix = value
311 if "_propagator" in dir(self):
312 self._propagator.mass_matrix = self._mass_matrix
313
316 """
317 Random Walk Metropolis Monte Carlo implementation
318 (Metropolis, Rosenbluth, Teller, Teller 1953; Hastings, 1970).
319
320 @param pdf: Probability density function to be sampled from
321 @type pdf: L{csb.statistics.pdf.AbstractDensity}
322
323 @param state: Inital state
324 @type state: L{State}
325
326 @param stepsize: Serves to set the step size in
327 proposal_density, e.g. for automatic acceptance
328 rate adaption
329 @type stepsize: float
330
331 @param proposal_density: The proposal density as a function f(x, s)
332 of the current state x and the stepsize s.
333 By default, the proposal density is uniform,
334 centered around x, and has width s.
335 @type proposal_density: callable
336
337 @param temperature: Pseudo-temperature of the Boltzmann ensemble
338 M{p(x) = 1/N * exp(-1/T * E(x))} with the
339 pseudo-energy defined as M{E(x) = -log(p(x))}
340 where M{p(x)} is the PDF under consideration
341 @type temperature: float
342 """
343
344 - def __init__(self, pdf, state, stepsize=1., proposal_density=None, temperature=1.):
354
362
372
373 @property
375 return self._stepsize
376
377 @stepsize.setter
379 self._stepsize = float(value)
380
383 """
384 Implementation of the NCMC sampling algorithm (Nilmeier et al., "Nonequilibrium candidate Monte
385 Carlo is an efficient tool for equilibrium simulation", PNAS 2011) for sampling from one
386 ensemble only.
387 Subclasses have to specify the acceptance probability, which depends on the kind of
388 perturbations and propagations in the protocol.
389
390 @param state: Inital state
391 @type state: L{State}
392
393 @param protocol: Nonequilibrium protocol with alternating perturbations and propagations
394 @type protocol: L{Protocol}
395
396 @param reverse_protocol: The reversed version of the protocol, that is, the order of
397 perturbations and propagations in each step is reversed
398 @type reverse_protocol: L{Protocol}
399 """
400
401 __metaclass__ = ABCMeta
402
403 - def __init__(self, state, protocol, reverse_protocol):
414
416 """
417 Picks either the protocol or the reversed protocol with equal probability.
418
419 @return: Either the protocol or the reversed protocol
420 @rtype: L{Protocol}
421 """
422
423 if numpy.random.random() < 0.5:
424 return self.protocol
425 else:
426 return self.reverse_protocol
427
437
446
447 @property
449 return self._protocol
450 @protocol.setter
452 self._protocol = value
453
454 @property
456 return self._reverse_protocol
457 @reverse_protocol.setter
459 self._reverse_protocol = value
460
463 """
464 This holds all the information needed to calculate the acceptance
465 probability in both the L{RWMCSampler} and L{HMCSampler} classes,
466 that is, only the proposal state.
467 For more advanced algorithms, one may derive classes capable of
468 holding the neccessary additional information from this class.
469
470 @param current_state: Current state
471 @type current_state: L{State}
472
473 @param proposal_state: Proposal state
474 @type proposal_state: L{State}
475 """
476
477 __metaclass__ = ABCMeta
478
479 - def __init__(self, current_state, proposal_state):
483
484 @property
486 return self._current_state
487
488 @property
490 return self._proposal_state
491
494 """
495 Holds all information (that is, the trajectory with heat, work, Hamiltonian difference
496 and jacbian) needed to calculate the acceptance probability in the AbstractNCMCSampler class.
497
498 @param traj: Non-equilibrium trajectory stemming from a stepwise protocol
499 @type traj: NCMCTrajectory
500 """
501
508