Package csb :: Package statistics :: Package samplers :: Package mc
[frames] | no frames]

Source Code for Package csb.statistics.samplers.mc

   1  """ 
   2  Abstract Monte Carlo samplers. 
   3  """ 
   4   
   5  import numpy.random 
   6   
   7  import csb.numeric 
   8  import csb.core 
   9   
  10  from abc import ABCMeta, abstractmethod, abstractproperty 
  11  from csb.statistics.samplers import AbstractSampler, AbstractState, State, EnsembleState 
12 13 -class AbstractMC(AbstractSampler):
14 """ 15 Abstract Monte Carlo sampler class. Subclasses implement various 16 Monte carlo equilibrium sampling schemes. 17 18 @param state: Initial state 19 @type state: L{AbstractState} 20 """ 21 22 __metaclass__ = ABCMeta 23
24 - def __init__(self, state):
25 26 self._state = None 27 self.state = state
28
29 - def _checkstate(self, state):
30 31 if not isinstance(state, AbstractState): 32 raise TypeError(state)
33 34 @abstractproperty
35 - def energy(self):
36 """ 37 Energy of the current state. 38 """ 39 pass
40 41 @property
42 - def state(self):
43 """ 44 Current state. 45 """ 46 return self._state
47 @state.setter
48 - def state(self, value):
49 self._checkstate(value) 50 self._state = value
51 52 @abstractmethod
53 - def sample(self):
54 """ 55 Draw a sample. 56 @rtype: L{AbstractState} 57 """ 58 pass
59
60 -class AbstractPropagationResult(object):
61 """ 62 Abstract class providing the interface for the result 63 of a deterministic or stochastic propagation of a state. 64 """ 65 66 __metaclass__ = ABCMeta 67 68 @abstractproperty
69 - def initial(self):
70 """ 71 Initial state 72 """ 73 pass
74 75 @abstractproperty
76 - def final(self):
77 """ 78 Final state 79 """ 80 pass
81 82 @abstractproperty
83 - def heat(self):
84 """ 85 Heat produced during propagation 86 @rtype: float 87 """ 88 pass
89
90 -class PropagationResult(AbstractPropagationResult):
91 """ 92 Describes the result of a deterministic or stochastic 93 propagation of a state. 94 95 @param initial: Initial state from which the 96 propagation started 97 @type initial: L{State} 98 99 @param final: Final state in which the propagation 100 resulted 101 @type final: L{State} 102 103 @param heat: Heat produced during propagation 104 @type heat: float 105 """ 106 107
108 - def __init__(self, initial, final, heat=0.0, ):
109 110 if not isinstance(initial, AbstractState): 111 raise TypeError(initial) 112 113 if not isinstance(final, AbstractState): 114 raise TypeError(final) 115 116 self._initial = initial 117 self._final = final 118 self._heat = None 119 self._work = None 120 121 self.heat = heat
122 123 @property
124 - def initial(self):
125 return self._initial
126 127 @property
128 - def final(self):
129 return self._final
130 131 @property
132 - def heat(self):
133 return self._heat
134 @heat.setter
135 - def heat(self, value):
136 self._heat = float(value)
137
138 -class Trajectory(csb.core.CollectionContainer, AbstractPropagationResult):
139 """ 140 Ordered collection of states, representing a phase-space trajectory. 141 142 @param items: list of states defining a phase-space trajectory 143 @type items: list of L{AbstractState} 144 @param heat: heat produced during the trajectory 145 @type heat: float 146 @param work: work produced during the trajectory 147 @type work: float 148 """ 149
150 - def __init__(self, items, heat=0.0, work=0.0):
151 152 super(Trajectory, self).__init__(items, type=AbstractState) 153 154 self._heat = heat 155 self._work = work
156 157 @property
158 - def initial(self):
159 return self[0]
160 161 @property
162 - def final(self):
163 return self[self.last_index]
164 165 @property
166 - def heat(self):
167 return self._heat
168 @heat.setter
169 - def heat(self, value):
170 self._heat = float(value)
171 172 @property
173 - def work(self):
174 return self._work
175 @work.setter
176 - def work(self, value):
177 self._work = float(value)
178
179 -class TrajectoryBuilder(object):
180 """ 181 Allows to build a Trajectory object step by step. 182 183 @param heat: heat produced over the trajectory 184 @type heat: float 185 @param work: work produced during the trajectory 186 @type work: float 187 """ 188
189 - def __init__(self, heat=0.0, work=0.0):
190 self._heat = heat 191 self._work = work 192 self._states = []
193 194 @staticmethod
195 - def create(full=True):
196 """ 197 Trajectory builder factory. 198 199 @param full: if True, a TrajectoryBuilder instance designed 200 to build a full trajectory with initial state, 201 intermediate states and a final state. If False, 202 a ShortTrajectoryBuilder instance designed to 203 hold only the initial and the final state is 204 returned 205 @type full: boolean 206 """ 207 208 if full: 209 return TrajectoryBuilder() 210 else: 211 return ShortTrajectoryBuilder()
212 213 @property
214 - def product(self):
215 """ 216 The L{Trajectory} instance build by a specific instance of 217 this class 218 """ 219 return Trajectory(self._states, heat=self._heat, work=self._work)
220
221 - def add_initial_state(self, state):
222 """ 223 Inserts a state at the beginning of the trajectory 224 225 @param state: state to be added 226 @type state: L{State} 227 """ 228 self._states.insert(0, state.clone())
229
230 - def add_intermediate_state(self, state):
231 """ 232 Adds a state to the end of the trajectory 233 234 @param state: state to be added 235 @type state: L{State} 236 """ 237 self._states.append(state.clone())
238
239 - def add_final_state(self, state):
240 """ 241 Adds a state to the end of the trajectory 242 243 @param state: state to be added 244 @type state: L{State} 245 """ 246 self._states.append(state.clone())
247
248 -class ShortTrajectoryBuilder(TrajectoryBuilder):
249
250 - def add_intermediate_state(self, state):
251 pass
252 253 @property
254 - def product(self):
255 """ 256 The L{PropagationResult} instance built by a specific instance of 257 this class 258 """ 259 260 if len(self._states) != 2: 261 raise ValueError("Can't create a product, two states required") 262 263 initial, final = self._states 264 return PropagationResult(initial, final, heat=self._heat)
265
266 -class SimpleProposalCommunicator(object):
267 """ 268 With the exception of the current state of the Markov chain, this 269 holds all the information needed to calculate the acceptance 270 probability in both the L{RWMCSampler} and L{HMCSampler} classes, 271 that is, only the proposal state. 272 For more advanced algorithms, one may derive classes capable of 273 holding the neccessary additional information from this class. 274 275 @param proposal: Proposal state 276 @type proposal: L{State} 277 """ 278 279 __metaclass__ = ABCMeta 280
281 - def __init__(self, proposal):
282 283 self._proposal = proposal
284 285 @property
286 - def proposal(self):
287 return self._proposal
288
289 -class AbstractSingleChainMC(AbstractMC):
290 """ 291 Abstract class for Monte Carlo sampling algorithms simulating 292 only one ensemble. 293 294 @param pdf: probability density function to sample from 295 @type pdf: subclass of L{csb.statistics.pdf.AbstractDensity} 296 297 @param state: Initial state 298 @type state: L{State} 299 300 @param temperature: Pseudo-temperature of the Boltzmann ensemble 301 M{p(x) = 1/N * exp(-1/T * E(x))} with the 302 pseudo-energy defined as M{E(x) = -log(p(x))} 303 where M{p(x)} is the PDF under consideration 304 @type temperature: float 305 """ 306 307 __metaclass__ = ABCMeta 308
309 - def __init__(self, pdf, state, temperature=1.):
310 311 super(AbstractSingleChainMC, self).__init__(state) 312 313 self._pdf = pdf 314 self._temperature = temperature 315 self._nmoves = 0 316 self._accepted = 0 317 self._last_move_accepted = None
318
319 - def _checkstate(self, state):
320 if not isinstance(state, State): 321 raise TypeError(state)
322
323 - def sample(self):
324 """ 325 Draw a sample. 326 @rtype: L{State} 327 """ 328 329 proposal_communicator = self._propose() 330 pacc = self._calc_pacc(proposal_communicator) 331 self._accept(proposal_communicator.proposal, pacc) 332 333 return self.state
334 335 @abstractmethod
336 - def _propose(self):
337 """ 338 Calculate a new proposal state and gather additional information 339 needed to calculate the acceptance probability. 340 341 @rtype: L{AbstractProposalCommunicator} 342 """ 343 pass
344 345 @abstractmethod
346 - def _calc_pacc(self, proposal_communicator):
347 """ 348 Calculate probability with which to accept the proposal. 349 350 @param proposal_communicator: Contains information about the proposal 351 and additional information needed to 352 calculate the acceptance probability 353 @type proposal_communicator: L{AbstractProposalCommunicator} 354 """ 355 pass
356
357 - def _accept(self, proposal, pacc):
358 """ 359 Accept / reject proposal with given acceptance probability pacc. 360 361 @param proposal: proposal state 362 @type proposal: L{State} 363 364 @param pacc: acceptance probability 365 @type pacc: float 366 """ 367 368 self._nmoves += 1 369 370 if numpy.random.random() < pacc: 371 self.state = proposal 372 self._accepted += 1 373 self._last_move_accepted = True 374 return True 375 else: 376 self._last_move_accepted = False 377 return False
378 379 @property
380 - def energy(self):
381 """ 382 Log-likelihood of the current state. 383 @rtype: float 384 """ 385 return self._pdf.log_prob(self.state.position)
386 387 @property
388 - def acceptance_rate(self):
389 """ 390 Acceptance rate. 391 """ 392 return float(self._accepted) / float(self._nmoves)
393 394 @property
395 - def last_move_accepted(self):
396 """ 397 Information whether the last MC move was accepted or not. 398 """ 399 return self._last_move_accepted
400 401 @property
402 - def temperature(self):
403 return self._temperature
404
405 -class MCCollection(csb.core.BaseCollectionContainer):
406 """ 407 Collection of single-chain samplers. 408 409 @param items: samplers 410 @type items: list of L{AbstractSingleChainMC} 411 """ 412
413 - def __init__(self, items):
416
417 -class AbstractEnsembleMC(AbstractMC):
418 """ 419 Abstract class for Monte Carlo sampling algorithms simulating several ensembles. 420 421 @param samplers: samplers which sample from their respective equilibrium distributions 422 @type samplers: list of L{AbstractSingleChainMC} 423 """ 424 425 __metaclass__ = ABCMeta 426
427 - def __init__(self, samplers):
428 429 self._samplers = MCCollection(samplers) 430 state = EnsembleState([x.state for x in self._samplers]) 431 432 super(AbstractEnsembleMC, self).__init__(state)
433
434 - def sample(self):
435 """ 436 Draw an ensemble sample. 437 438 @rtype: L{EnsembleState} 439 """ 440 441 sample = EnsembleState([sampler.sample() for sampler in self._samplers]) 442 self.state = sample 443 444 return sample
445 446 @property
447 - def energy(self):
448 """ 449 Total ensemble energy. 450 """ 451 return sum([x.energy for x in self._samplers])
452
453 -class AbstractSwapParameterInfo(object):
454 """ 455 Subclass instances hold all parameters necessary for performing a swap 456 between two given samplers. 457 """ 458 459 __metaclass__ = ABCMeta 460
461 - def __init__(self, sampler1, sampler2):
462 """ 463 @param sampler1: First sampler 464 @type sampler1: L{AbstractSingleChainMC} 465 466 @param sampler2: Second sampler 467 @type sampler2: L{AbstractSingleChainMC} 468 """ 469 470 self._sampler1 = sampler1 471 self._sampler2 = sampler2
472 473 @property
474 - def sampler1(self):
475 return self._sampler1
476 477 @property
478 - def sampler2(self):
479 return self._sampler2 480
481 -class RESwapParameterInfo(AbstractSwapParameterInfo):
482 """ 483 Holds parameters for a standard Replica Exchange swap. 484 """ 485 pass
486
487 -class MDRENSSwapParameterInfo(RESwapParameterInfo):
488 """ 489 Holds parameters for a MDRENS swap. 490 491 @param sampler1: First sampler 492 @type sampler1: L{AbstractSingleChainMC} 493 494 @param sampler2: Second sampler 495 @type sampler2: L{AbstractSingleChainMC} 496 497 @param timestep: Integration timestep 498 @type timestep: float 499 500 @param traj_length: Trajectory length in number of timesteps 501 @type traj_length: int 502 503 @param gradient: Gradient which determines the dynamics during a trajectory 504 @type gradient: L{AbstractGradient} 505 """ 506
507 - def __init__(self, sampler1, sampler2, timestep, traj_length, gradient):
508 509 super(MDRENSSwapParameterInfo, self).__init__(sampler1, sampler2) 510 511 self._timestep = timestep 512 self._traj_length = traj_length 513 self._gradient = gradient
514 515 @property
516 - def timestep(self):
517 """ 518 Integration timestep. 519 """ 520 return self._timestep
521 @timestep.setter
522 - def timestep(self, value):
523 self._timestep = float(value)
524 525 @property
526 - def traj_length(self):
527 """ 528 Trajectory length in number of integration steps. 529 """ 530 return self._traj_length
531 @traj_length.setter
532 - def traj_length(self, value):
533 self._traj_length = int(value)
534 535 @property
536 - def gradient(self):
537 """ 538 Gradient which governs the equations of motion. 539 """ 540 return self._gradient
541
542 -class ThermostattedMDRENSSwapParameterInfo(MDRENSSwapParameterInfo):
543 """ 544 @param sampler1: First sampler 545 @type sampler1: subclass instance of L{AbstractSingleChainMC} 546 547 @param sampler2: Second sampler 548 @type sampler2: subclass instance of L{AbstractSingleChainMC} 549 550 @param timestep: Integration timestep 551 @type timestep: float 552 553 @param traj_length: Trajectory length in number of timesteps 554 @type traj_length: int 555 556 @param gradient: Gradient which determines the dynamics during a trajectory 557 @type gradient: subclass instance of L{AbstractGradient} 558 559 @param temperature: Temperature interpolation function. 560 @type temperature: Real-valued function mapping from [0,1] to R. 561 T(0) = temperature of the ensemble sampler1 samples from, T(1) = temperature 562 of the ensemble sampler2 samples from 563 564 @param collision_probability: Probability for a collision with the heatbath during one timestep 565 @type collision_probability: float 566 567 @param collision_interval: Interval during which collision may occur with probability 568 collision_probability 569 @type collision_interval: int 570 """ 571
572 - def __init__(self, sampler1, sampler2, timestep, traj_length, gradient, 573 temperature=lambda l: 1., collision_probability=0.1, collision_interval=1):
574 575 super(ThermostattedMDRENSSwapParameterInfo, self).__init__( 576 sampler1, sampler2, timestep, traj_length, gradient) 577 578 self._collision_probability = None 579 self._collision_interval = None 580 self._temperature = temperature 581 582 self.collision_probability = collision_probability 583 self.collision_interval = collision_interval
584 585 @property
586 - def collision_probability(self):
587 """ 588 Probability for a collision with the heatbath during one timestep. 589 """ 590 return self._collision_probability
591 @collision_probability.setter
592 - def collision_probability(self, value):
593 self._collision_probability = float(value)
594 595 @property
596 - def collision_interval(self):
597 """ 598 Interval during which collision may occur with probability 599 C{collision_probability}. 600 """ 601 return self._collision_interval
602 @collision_interval.setter
603 - def collision_interval(self, value):
604 self._collision_interval = int(value)
605 606 @property
607 - def temperature(self):
608 return self._temperature
609
610 -class AbstractSwapCommunicator(object):
611 """ 612 Holds all the information which needs to be communicated between 613 distinct swap substeps. 614 615 @param param_info: ParameterInfo instance holding swap parameters 616 @type param_info: L{AbstractSwapParameterInfo} 617 618 @param proposal1: Proposal state for first sampler 619 @type proposal1: L{State} 620 621 @param proposal2: Proposal state for second sampler 622 @type proposal2: L{State} 623 """ 624 625 __metaclass__ = ABCMeta 626
627 - def __init__(self, param_info, proposal1, proposal2):
628 629 self._sampler1 = param_info.sampler1 630 self._sampler2 = param_info.sampler2 631 632 self._state1 = self.sampler1.state 633 self._state2 = self.sampler2.state 634 635 self._proposal1 = proposal1 636 self._proposal2 = proposal2 637 638 self._param_info = param_info 639 640 self._acceptance_probability = None 641 self._accepted = False
642 643 @property
644 - def sampler1(self):
645 return self._sampler1
646 647 @property
648 - def sampler2(self):
649 return self._sampler2
650 651 @property
652 - def state1(self):
653 return self._state1
654 655 @property
656 - def state2(self):
657 return self._state2
658 659 @property
660 - def proposal1(self):
661 return self._proposal1
662 663 @property
664 - def proposal2(self):
665 return self._proposal2
666 667 @property
668 - def acceptance_probability(self):
669 return self._acceptance_probability
670 @acceptance_probability.setter
671 - def acceptance_probability(self, value):
672 self._acceptance_probability = value
673 674 @property
675 - def accepted(self):
676 return self._accepted
677 @accepted.setter
678 - def accepted(self, value):
679 self._accepted = value
680 681 @property
682 - def param_info(self):
683 return self._param_info
684
685 -class RESwapCommunicator(AbstractSwapCommunicator):
686 """ 687 Holds all the information which needs to be communicated between distinct 688 RE swap substeps. 689 690 See L{AbstractSwapCommunicator} for constructor signature. 691 """ 692 pass
693
694 -class RENSSwapCommunicator(AbstractSwapCommunicator):
695 """ 696 Holds all the information which needs to be communicated between distinct 697 RENS swap substeps. 698 699 @param param_info: ParameterInfo instance holding swap parameters 700 @type param_info: L{AbstractSwapParameterInfo} 701 702 @param proposal1: Proposal state for first sampler 703 @type proposal1: L{State} 704 705 @param proposal2: Proposal state for second sampler 706 @type proposal2: L{State} 707 708 @param heat12: Heat generated during the forward trajectory 709 @type heat12: float 710 711 @param heat21: Heat generated during the reverse trajectory 712 @type heat21: float 713 """ 714
715 - def __init__(self, param_info, proposal1, proposal2, heat12, heat21):
716 717 super(RENSSwapCommunicator, self).__init__(param_info, proposal1, proposal2) 718 self._heat12 = heat12 719 self._heat21 = heat21
720 721 @property
722 - def heat12(self):
723 return self._heat12
724 725 @property
726 - def heat21(self):
727 return self._heat21
728
729 -class SingleSwapStatistics(object):
730 """ 731 Tracks swap statistics of a single sampler pair. 732 733 @param param_info: ParameterInfo instance holding swap parameters 734 @type param_info: L{AbstractSwapParameterInfo} 735 """ 736
737 - def __init__(self, param_info):
738 self._total_swaps = 0 739 self._accepted_swaps = 0
740 741 @property
742 - def total_swaps(self):
743 return self._total_swaps
744 745 @property
746 - def accepted_swaps(self):
747 return self._accepted_swaps
748 749 @property
750 - def acceptance_rate(self):
751 """ 752 Acceptance rate of the sampler pair. 753 """ 754 if self.total_swaps > 0: 755 return float(self.accepted_swaps) / float(self.total_swaps) 756 else: 757 return 0.
758
759 - def update(self, accepted):
760 """ 761 Updates swap statistics. 762 """ 763 self._total_swaps += 1 764 self._accepted_swaps += int(accepted)
765
766 -class SwapStatistics(object):
767 """ 768 Tracks swap statistics for an AbstractExchangeMC subclass instance. 769 770 @param param_infos: list of ParameterInfo instances providing information 771 needed for performing swaps 772 @type param_infos: list of L{AbstractSwapParameterInfo} 773 """ 774
775 - def __init__(self, param_infos):
776 self._stats = [SingleSwapStatistics(x) for x in param_infos]
777 778 @property
779 - def stats(self):
780 return tuple(self._stats)
781 782 @property
783 - def acceptance_rates(self):
784 """ 785 Returns acceptance rates for all swaps. 786 """ 787 return [x.acceptance_rate for x in self._stats]
788
789 -class AbstractExchangeMC(AbstractEnsembleMC):
790 """ 791 Abstract class for Monte Carlo sampling algorithms employing some replica exchange method. 792 793 @param samplers: samplers which sample from their respective equilibrium distributions 794 @type samplers: list of L{AbstractSingleChainMC} 795 796 @param param_infos: list of ParameterInfo instances providing information needed 797 for performing swaps 798 @type param_infos: list of L{AbstractSwapParameterInfo} 799 """ 800 801 __metaclass__ = ABCMeta 802
803 - def __init__(self, samplers, param_infos):
804 super(AbstractExchangeMC, self).__init__(samplers) 805 806 self._swaplist1 = [] 807 self._swaplist2 = [] 808 self._currentswaplist = self._swaplist1 809 810 self._param_infos = param_infos 811 self._statistics = SwapStatistics(self._param_infos)
812
813 - def _checkstate(self, state):
814 if not isinstance(state, EnsembleState): 815 raise TypeError(state)
816
817 - def swap(self, index):
818 """ 819 Perform swap between sampler pair described by param_infos[index] 820 and return outcome (true = accepted, false = rejected). 821 822 @param index: index of swap pair in param_infos 823 @type index: int 824 825 @rtype: boolean 826 """ 827 param_info = self._param_infos[index] 828 swapcom = self._propose_swap(param_info) 829 swapcom = self._calc_pacc_swap(swapcom) 830 result = self._accept_swap(swapcom) 831 832 self.state = EnsembleState([x.state for x in self._samplers]) 833 self.statistics.stats[index].update(result) 834 835 return result
836 837 @abstractmethod
838 - def _propose_swap(self, param_info):
839 """ 840 Calculate proposal states for a swap between two samplers. 841 842 @param param_info: ParameterInfo instance holding swap parameters 843 @type param_info: L{AbstractSwapParameterInfo} 844 845 @rtype: L{AbstractSwapCommunicator} 846 """ 847 pass
848 849 @abstractmethod
850 - def _calc_pacc_swap(self, swapcom):
851 """ 852 Calculate probability to accept a swap given initial and proposal states. 853 854 @param swapcom: SwapCommunicator instance holding information to be communicated 855 between distinct swap substeps 856 @type swapcom: L{AbstractSwapCommunicator} 857 858 @rtype: L{AbstractSwapCommunicator} 859 """ 860 pass
861
862 - def _accept_swap(self, swapcom):
863 """ 864 Accept / reject an exchange between two samplers given proposal states and 865 the acceptance probability and returns the outcome (true = accepted, false = rejected). 866 867 @param swapcom: SwapCommunicator instance holding information to be communicated 868 between distinct swap substeps 869 @type swapcom: L{AbstractSwapCommunicator} 870 871 @rtype: boolean 872 """ 873 874 if numpy.random.random() < swapcom.acceptance_probability: 875 swapcom.sampler1.state = swapcom.proposal1 876 swapcom.sampler2.state = swapcom.proposal2 877 return True 878 else: 879 return False
880 881 @property
882 - def acceptance_rates(self):
883 """ 884 Return swap acceptance rates. 885 886 @rtype: list of floats 887 """ 888 return self.statistics.acceptance_rates
889 890 @property
891 - def param_infos(self):
892 """ 893 List of SwapParameterInfo instances holding all necessary parameters. 894 895 @rtype: list of L{AbstractSwapParameterInfo} 896 """ 897 return self._param_infos
898 899 @property
900 - def statistics(self):
901 return self._statistics
902
903 - def _update_statistics(self, index, accepted):
904 """ 905 Update statistics of a given swap process. 906 907 @param index: position of swap statistics to be updated 908 @type index: int 909 910 @param accepted: outcome of the swap 911 @type accepted: boolean 912 """ 913 914 self._stats[index][0] += 1 915 self._stats[index][1] += int(accepted)
916
917 -class RENSTrajInfo(object):
918 """ 919 Holds information necessary for calculating a RENS trajectory. 920 921 @param param_info: ParameterInfo instance holding swap parameters 922 @type param_info: L{AbstractSwapParameterInfo} 923 924 @param init_state: state from which the trajectory is supposed to start 925 @type init_state: L{State} 926 927 @param protocol: Protocol to be used to generate nonequilibrium trajectories 928 @type protocol: Real-valued function that maps [0, switching time] to [0, 1] 929 """ 930
931 - def __init__(self, param_info, init_state, protocol):
932 933 self._param_info = param_info 934 self._protocol = protocol 935 self._init_state = init_state
936 937 @property
938 - def param_info(self):
939 return self._param_info
940 941 @property
942 - def protocol(self):
943 return self._protocol
944 945 @property
946 - def init_state(self):
947 return self._init_state
948
949 -class AbstractRENS(AbstractExchangeMC):
950 """ 951 Abstract Replica Exchange with Nonequilibrium Switches 952 (RENS, Ballard & Jarzynski 2009) class. 953 Subclasses implement various ways of generating trajectories 954 (deterministic or stochastic). 955 """ 956 957 __metaclass__ = ABCMeta 958
959 - def _propose_swap(self, param_info):
960 961 T1 = param_info.sampler1.temperature 962 T2 = param_info.sampler2.temperature 963 964 init_state1 = State(param_info.sampler1.state.position, 965 numpy.random.normal(size=param_info.sampler1.state.position.shape, 966 scale=numpy.sqrt(T1))) 967 init_state2 = State(param_info.sampler2.state.position, 968 numpy.random.normal(size=param_info.sampler2.state.position.shape, 969 scale=numpy.sqrt(T2))) 970 971 param_info.sampler1.state = init_state1 972 param_info.sampler2.state = init_state2 973 974 trajinfo12 = RENSTrajInfo(param_info, init_state1, protocol=lambda t, tau: t / tau) 975 trajinfo21 = RENSTrajInfo(param_info, init_state2, protocol=lambda t, tau: (tau - t) / tau) 976 977 traj12 = self._run_traj_generator(trajinfo12) 978 traj21 = self._run_traj_generator(trajinfo21) 979 980 return RENSSwapCommunicator(param_info, traj21.final, traj12.final, traj12.heat, traj21.heat)
981
982 - def _calc_pacc_swap(self, swapcom):
983 984 T1 = swapcom.param_info.sampler1.temperature 985 T2 = swapcom.param_info.sampler2.temperature 986 987 heat12 = swapcom.heat12 988 heat21 = swapcom.heat21 989 990 proposal1 = swapcom.proposal1 991 proposal2 = swapcom.proposal2 992 993 state1 = swapcom.state1 994 state2 = swapcom.state2 995 996 E1 = lambda x:-swapcom.sampler1._pdf.log_prob(x) 997 E2 = lambda x:-swapcom.sampler2._pdf.log_prob(x) 998 999 w12 = (0.5 * sum(proposal2.momentum ** 2) + E2(proposal2.position)) \ 1000 / T2 - \ 1001 (0.5 * sum(state1.momentum ** 2) + E1(state1.position)) \ 1002 / T1 - heat12 1003 w21 = (0.5 * sum(proposal1.momentum ** 2) + E1(proposal1.position)) \ 1004 / T1 - \ 1005 (0.5 * sum(state2.momentum ** 2) + E2(state2.position)) \ 1006 / T2 - heat21 1007 1008 swapcom.acceptance_probability = csb.numeric.exp(-w12 - w21) 1009 1010 return swapcom
1011 1012 @abstractmethod
1013 - def _run_traj_generator(self, traj_info):
1014 """ 1015 Run the trajectory generator which generates a trajectory 1016 of a given length between the states of two samplers. 1017 1018 @param traj_info: TrajectoryInfo instance holding information 1019 needed to generate a nonequilibrium trajectory 1020 @type traj_info: L{RENSTrajInfo} 1021 1022 @rtype: L{Trajectory} 1023 """ 1024 pass
1025
1026 -class AbstractSwapScheme(object):
1027 """ 1028 Provides the interface for classes defining schemes according to which swaps in 1029 Replica Exchange-like simulations are performed. 1030 1031 @param algorithm: Exchange algorithm that performs the swaps 1032 @type algorithm: L{AbstractExchangeMC} 1033 """ 1034 1035 __metaclass__ = ABCMeta 1036
1037 - def __init__(self, algorithm):
1038 1039 self._algorithm = algorithm
1040 1041 @abstractmethod
1042 - def swap_all(self):
1043 """ 1044 Advises the Replica Exchange-like algorithm to perform swaps according to 1045 the some schedule defined here. 1046 """ 1047 1048 pass
1049
1050 -class AlternatingAdjacentSwapScheme(AbstractSwapScheme):
1051 """ 1052 Provides a swapping scheme in which tries exchanges between neighbours only 1053 following the scheme 1 <-> 2, 3 <-> 4, ... and after a sampling period 2 <-> 3, 4 <-> 5, ... 1054 1055 @param algorithm: Exchange algorithm that performs the swaps 1056 @type algorithm: L{AbstractExchangeMC} 1057 """ 1058
1059 - def __init__(self, algorithm):
1060 1061 super(AlternatingAdjacentSwapScheme, self).__init__(algorithm) 1062 1063 self._current_swap_list = None 1064 self._swap_list1 = [] 1065 self._swap_list2 = [] 1066 self._create_swap_lists()
1067
1068 - def _create_swap_lists(self):
1069 1070 i = 0 1071 while i < len(self._algorithm.param_infos): 1072 self._swap_list1.append(i) 1073 i += 2 1074 1075 i = 1 1076 while i < len(self._algorithm.param_infos): 1077 self._swap_list2.append(i) 1078 i += 2 1079 1080 self._current_swap_list = self._swap_list1
1081
1082 - def swap_all(self):
1083 1084 for x in self._current_swap_list: 1085 self._algorithm.swap(x) 1086 1087 if self._current_swap_list == self._swap_list1: 1088 self._current_swap_list = self._swap_list2 1089 else: 1090 self._current_swap_list = self._swap_list1
1091