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 301 __metaclass__ = ABCMeta 302
303 - def __init__(self, pdf, state):
304 305 super(AbstractSingleChainMC, self).__init__(state) 306 307 self._pdf = pdf 308 self._nmoves = 0 309 self._accepted = 0 310 self._last_move_accepted = None
311
312 - def _checkstate(self, state):
313 if not isinstance(state, State): 314 raise TypeError(state)
315
316 - def sample(self):
317 """ 318 Draw a sample. 319 @rtype: L{State} 320 """ 321 322 proposal_communicator = self._propose() 323 pacc = self._calc_pacc(proposal_communicator) 324 self._accept(proposal_communicator.proposal, pacc) 325 326 return self.state
327 328 @abstractmethod
329 - def _propose(self):
330 """ 331 Calculate a new proposal state and gather additional information 332 needed to calculate the acceptance probability. 333 334 @rtype: L{AbstractProposalCommunicator} 335 """ 336 pass
337 338 @abstractmethod
339 - def _calc_pacc(self, proposal_communicator):
340 """ 341 Calculate probability with which to accept the proposal. 342 343 @param proposal_communicator: Contains information about the proposal 344 and additional information needed to 345 calculate the acceptance probability 346 @type proposal_communicator: L{AbstractProposalCommunicator} 347 """ 348 pass
349
350 - def _accept(self, proposal, pacc):
351 """ 352 Accept / reject proposal with given acceptance probability pacc. 353 354 @param proposal: proposal state 355 @type proposal: L{State} 356 357 @param pacc: acceptance probability 358 @type pacc: float 359 """ 360 361 self._nmoves += 1 362 363 if numpy.random.random() < pacc: 364 self.state = proposal 365 self._accepted += 1 366 self._last_move_accepted = True 367 return True 368 else: 369 self._last_move_accepted = False 370 return False
371 372 @property
373 - def energy(self):
374 """ 375 Log-likelihood of the current state. 376 @rtype: float 377 """ 378 return self._pdf.log_prob(self.state.position)
379 380 @property
381 - def acceptance_rate(self):
382 """ 383 Acceptance rate. 384 """ 385 return float(self._accepted) / float(self._nmoves)
386 387 @property
388 - def last_move_accepted(self):
389 """ 390 Information whether the last MC move was accepted or not. 391 """ 392 return self._last_move_accepted
393
394 -class MCCollection(csb.core.BaseCollectionContainer):
395 """ 396 Collection of single-chain samplers. 397 398 @param items: samplers 399 @type items: list of L{AbstractSingleChainMC} 400 """ 401
402 - def __init__(self, items):
405
406 -class AbstractEnsembleMC(AbstractMC):
407 """ 408 Abstract class for Monte Carlo sampling algorithms simulating several ensembles. 409 410 @param samplers: samplers which sample from their respective equilibrium distributions 411 @type samplers: list of L{AbstractSingleChainMC} 412 """ 413 414 __metaclass__ = ABCMeta 415
416 - def __init__(self, samplers):
417 418 self._samplers = MCCollection(samplers) 419 state = EnsembleState([x.state for x in self._samplers]) 420 421 super(AbstractEnsembleMC, self).__init__(state)
422
423 - def sample(self):
424 """ 425 Draw an ensemble sample. 426 427 @rtype: L{EnsembleState} 428 """ 429 430 sample = EnsembleState([sampler.sample() for sampler in self._samplers]) 431 self.state = sample 432 433 return sample
434 435 @property
436 - def energy(self):
437 """ 438 Total ensemble energy. 439 """ 440 return sum([x.energy for x in self._samplers])
441
442 -class AbstractSwapParameterInfo(object):
443 """ 444 Subclass instances hold all parameters necessary for performing a swap 445 between two given samplers. 446 """ 447 448 __metaclass__ = ABCMeta 449
450 - def __init__(self, sampler1, sampler2):
451 """ 452 @param sampler1: First sampler 453 @type sampler1: L{AbstractSingleChainMC} 454 455 @param sampler2: Second sampler 456 @type sampler2: L{AbstractSingleChainMC} 457 """ 458 459 self._sampler1 = sampler1 460 self._sampler2 = sampler2
461 462 @property
463 - def sampler1(self):
464 return self._sampler1
465 466 @property
467 - def sampler2(self):
468 return self._sampler2 469
470 -class RESwapParameterInfo(AbstractSwapParameterInfo):
471 """ 472 Holds parameters for a standard Replica Exchange swap. 473 """ 474 pass
475
476 -class MDRENSSwapParameterInfo(RESwapParameterInfo):
477 """ 478 Holds parameters for a MDRENS swap. 479 480 @param sampler1: First sampler 481 @type sampler1: L{AbstractSingleChainMC} 482 483 @param sampler2: Second sampler 484 @type sampler2: L{AbstractSingleChainMC} 485 486 @param timestep: Integration timestep 487 @type timestep: float 488 489 @param traj_length: Trajectory length in number of timesteps 490 @type traj_length: int 491 492 @param gradient: Gradient which determines the dynamics during a trajectory 493 @type gradient: L{AbstractGradient} 494 """ 495
496 - def __init__(self, sampler1, sampler2, timestep, traj_length, gradient):
497 498 super(MDRENSSwapParameterInfo, self).__init__(sampler1, sampler2) 499 500 self._timestep = timestep 501 self._traj_length = traj_length 502 self._gradient = gradient
503 504 @property
505 - def timestep(self):
506 """ 507 Integration timestep. 508 """ 509 return self._timestep
510 @timestep.setter
511 - def timestep(self, value):
512 self._timestep = float(value)
513 514 @property
515 - def traj_length(self):
516 """ 517 Trajectory length in number of integration steps. 518 """ 519 return self._traj_length
520 @traj_length.setter
521 - def traj_length(self, value):
522 self._traj_length = int(value)
523 524 @property
525 - def gradient(self):
526 """ 527 Gradient which governs the equations of motion. 528 """ 529 return self._gradient
530
531 -class ThermostattedMDRENSSwapParameterInfo(MDRENSSwapParameterInfo):
532 """ 533 @param sampler1: First sampler 534 @type sampler1: subclass instance of L{AbstractSingleChainMC} 535 536 @param sampler2: Second sampler 537 @type sampler2: subclass instance of L{AbstractSingleChainMC} 538 539 @param timestep: Integration timestep 540 @type timestep: float 541 542 @param traj_length: Trajectory length in number of timesteps 543 @type traj_length: int 544 545 @param gradient: Gradient which determines the dynamics during a trajectory 546 @type gradient: subclass instance of L{AbstractGradient} 547 548 @param temperature: Temperature interpolation function. 549 @type temperature: Real-valued function mapping from [0,1] to R. 550 T(0) = temperature of the ensemble sampler1 samples from, T(1) = temperature 551 of the ensemble sampler2 samples from 552 553 @param collision_probability: Probability for a collision with the heatbath during one timestep 554 @type collision_probability: float 555 556 @param collision_interval: Interval during which collision may occur with probability 557 collision_probability 558 @type collision_interval: int 559 """ 560
561 - def __init__(self, sampler1, sampler2, timestep, traj_length, gradient, 562 temperature=lambda l: 1., collision_probability=0.1, collision_interval=1):
563 564 super(ThermostattedMDRENSSwapParameterInfo, self).__init__( 565 sampler1, sampler2, timestep, traj_length, gradient) 566 567 self._collision_probability = None 568 self._collision_interval = None 569 self._temperature = temperature 570 571 self.collision_probability = collision_probability 572 self.collision_interval = collision_interval
573 574 @property
575 - def collision_probability(self):
576 """ 577 Probability for a collision with the heatbath during one timestep. 578 """ 579 return self._collision_probability
580 @collision_probability.setter
581 - def collision_probability(self, value):
582 self._collision_probability = float(value)
583 584 @property
585 - def collision_interval(self):
586 """ 587 Interval during which collision may occur with probability 588 C{collision_probability}. 589 """ 590 return self._collision_interval
591 @collision_interval.setter
592 - def collision_interval(self, value):
593 self._collision_interval = int(value)
594 595 @property
596 - def temperature(self):
597 return self._temperature
598
599 -class AbstractSwapCommunicator(object):
600 """ 601 Holds all the information which needs to be communicated between 602 distinct swap substeps. 603 604 @param param_info: ParameterInfo instance holding swap parameters 605 @type param_info: L{AbstractSwapParameterInfo} 606 607 @param proposal1: Proposal state for first sampler 608 @type proposal1: L{State} 609 610 @param proposal2: Proposal state for second sampler 611 @type proposal2: L{State} 612 """ 613 614 __metaclass__ = ABCMeta 615
616 - def __init__(self, param_info, proposal1, proposal2):
617 618 self._sampler1 = param_info.sampler1 619 self._sampler2 = param_info.sampler2 620 621 self._state1 = self.sampler1.state 622 self._state2 = self.sampler2.state 623 624 self._proposal1 = proposal1 625 self._proposal2 = proposal2 626 627 self._acceptance_probability = None 628 self._accepted = False
629 630 @property
631 - def sampler1(self):
632 return self._sampler1
633 634 @property
635 - def sampler2(self):
636 return self._sampler2
637 638 @property
639 - def state1(self):
640 return self._state1
641 642 @property
643 - def state2(self):
644 return self._state2
645 646 @property
647 - def proposal1(self):
648 return self._proposal1
649 650 @property
651 - def proposal2(self):
652 return self._proposal2
653 654 @property
655 - def acceptance_probability(self):
656 return self._acceptance_probability
657 @acceptance_probability.setter
658 - def acceptance_probability(self, value):
659 self._acceptance_probability = value
660 661 @property
662 - def accepted(self):
663 return self._accepted
664 @accepted.setter
665 - def accepted(self, value):
666 self._accepted = value
667
668 -class RESwapCommunicator(AbstractSwapCommunicator):
669 """ 670 Holds all the information which needs to be communicated between distinct 671 RE swap substeps. 672 673 See L{AbstractSwapCommunicator} for constructor signature. 674 """ 675 pass
676
677 -class RENSSwapCommunicator(AbstractSwapCommunicator):
678 """ 679 Holds all the information which needs to be communicated between distinct 680 RENS swap substeps. 681 682 @param param_info: ParameterInfo instance holding swap parameters 683 @type param_info: L{AbstractSwapParameterInfo} 684 685 @param proposal1: Proposal state for first sampler 686 @type proposal1: L{State} 687 688 @param proposal2: Proposal state for second sampler 689 @type proposal2: L{State} 690 691 @param heat12: Heat generated during the forward trajectory 692 @type heat12: float 693 694 @param heat21: Heat generated during the reverse trajectory 695 @type heat21: float 696 """ 697
698 - def __init__(self, param_info, proposal1, proposal2, heat12, heat21):
699 700 super(RENSSwapCommunicator, self).__init__(param_info, proposal1, proposal2) 701 self._heat12 = heat12 702 self._heat21 = heat21
703 704 @property
705 - def heat12(self):
706 return self._heat12
707 708 @property
709 - def heat21(self):
710 return self._heat21
711
712 -class SingleSwapStatistics(object):
713 """ 714 Tracks swap statistics of a single sampler pair. 715 716 @param param_info: ParameterInfo instance holding swap parameters 717 @type param_info: L{AbstractSwapParameterInfo} 718 """ 719
720 - def __init__(self, param_info):
721 self._total_swaps = 0 722 self._accepted_swaps = 0
723 724 @property
725 - def total_swaps(self):
726 return self._total_swaps
727 728 @property
729 - def accepted_swaps(self):
730 return self._accepted_swaps
731 732 @property
733 - def acceptance_rate(self):
734 """ 735 Acceptance rate of the sampler pair. 736 """ 737 if self.total_swaps > 0: 738 return float(self.accepted_swaps) / float(self.total_swaps) 739 else: 740 return 0.
741
742 - def update(self, accepted):
743 """ 744 Updates swap statistics. 745 """ 746 self._total_swaps += 1 747 self._accepted_swaps += int(accepted)
748
749 -class SwapStatistics(object):
750 """ 751 Tracks swap statistics for an AbstractExchangeMC subclass instance. 752 753 @param param_infos: list of ParameterInfo instances providing information 754 needed for performing swaps 755 @type param_infos: list of L{AbstractSwapParameterInfo} 756 """ 757
758 - def __init__(self, param_infos):
759 self._stats = [SingleSwapStatistics(x) for x in param_infos]
760 761 @property
762 - def stats(self):
763 return tuple(self._stats)
764 765 @property
766 - def acceptance_rates(self):
767 """ 768 Returns acceptance rates for all swaps. 769 """ 770 return [x.acceptance_rate for x in self._stats]
771
772 -class AbstractExchangeMC(AbstractEnsembleMC):
773 """ 774 Abstract class for Monte Carlo sampling algorithms employing some replica exchange method. 775 776 @param samplers: samplers which sample from their respective equilibrium distributions 777 @type samplers: list of L{AbstractSingleChainMC} 778 779 @param param_infos: list of ParameterInfo instances providing information needed 780 for performing swaps 781 @type param_infos: list of L{AbstractSwapParameterInfo} 782 """ 783 784 __metaclass__ = ABCMeta 785
786 - def __init__(self, samplers, param_infos):
787 super(AbstractExchangeMC, self).__init__(samplers) 788 789 self._swaplist1 = [] 790 self._swaplist2 = [] 791 self._currentswaplist = self._swaplist1 792 793 self._param_infos = param_infos 794 self._statistics = SwapStatistics(self._param_infos)
795
796 - def _checkstate(self, state):
797 if not isinstance(state, EnsembleState): 798 raise TypeError(state)
799
800 - def swap(self, index):
801 """ 802 Perform swap between sampler pair described by param_infos[index] 803 and return outcome (true = accepted, false = rejected). 804 805 @param index: index of swap pair in param_infos 806 @type index: int 807 808 @rtype: boolean 809 """ 810 param_info = self._param_infos[index] 811 swapcom = self._propose_swap(param_info) 812 swapcom = self._calc_pacc_swap(swapcom) 813 result = self._accept_swap(swapcom) 814 815 self.state = EnsembleState([x.state for x in self._samplers]) 816 self.statistics.stats[index].update(result) 817 818 return result
819 820 @abstractmethod
821 - def _propose_swap(self, param_info):
822 """ 823 Calculate proposal states for a swap between two samplers. 824 825 @param param_info: ParameterInfo instance holding swap parameters 826 @type param_info: L{AbstractSwapParameterInfo} 827 828 @rtype: L{AbstractSwapCommunicator} 829 """ 830 pass
831 832 @abstractmethod
833 - def _calc_pacc_swap(self, swapcom):
834 """ 835 Calculate probability to accept a swap given initial and proposal states. 836 837 @param swapcom: SwapCommunicator instance holding information to be communicated 838 between distinct swap substeps 839 @type swapcom: L{AbstractSwapCommunicator} 840 841 @rtype: L{AbstractSwapCommunicator} 842 """ 843 pass
844
845 - def _accept_swap(self, swapcom):
846 """ 847 Accept / reject an exchange between two samplers given proposal states and 848 the acceptance probability and returns the outcome (true = accepted, false = rejected). 849 850 @param swapcom: SwapCommunicator instance holding information to be communicated 851 between distinct swap substeps 852 @type swapcom: L{AbstractSwapCommunicator} 853 854 @rtype: boolean 855 """ 856 857 if numpy.random.random() < swapcom.acceptance_probability: 858 swapcom.sampler1.state = swapcom.proposal1 859 swapcom.sampler2.state = swapcom.proposal2 860 return True 861 else: 862 return False
863 864 @property
865 - def acceptance_rates(self):
866 """ 867 Return swap acceptance rates. 868 869 @rtype: list of floats 870 """ 871 return self.statistics.acceptance_rates
872 873 @property
874 - def param_infos(self):
875 """ 876 List of SwapParameterInfo instances holding all necessary parameters. 877 878 @rtype: list of L{AbstractSwapParameterInfo} 879 """ 880 return self._param_infos
881 882 @property
883 - def statistics(self):
884 return self._statistics
885
886 - def _update_statistics(self, index, accepted):
887 """ 888 Update statistics of a given swap process. 889 890 @param index: position of swap statistics to be updated 891 @type index: int 892 893 @param accepted: outcome of the swap 894 @type accepted: boolean 895 """ 896 897 self._stats[index][0] += 1 898 self._stats[index][1] += int(accepted)
899
900 -class RENSTrajInfo(object):
901 """ 902 Holds information necessary for calculating a RENS trajectory. 903 904 @param param_info: ParameterInfo instance holding swap parameters 905 @type param_info: L{AbstractSwapParameterInfo} 906 907 @param init_state: state from which the trajectory is supposed to start 908 @type init_state: L{State} 909 910 @param protocol: Protocol to be used to generate nonequilibrium trajectories 911 @type protocol: Real-valued function that maps [0, switching time] to [0, 1] 912 """ 913
914 - def __init__(self, param_info, init_state, protocol):
915 916 self._param_info = param_info 917 self._protocol = protocol 918 self._init_state = init_state
919 920 @property
921 - def param_info(self):
922 return self._param_info
923 924 @property
925 - def protocol(self):
926 return self._protocol
927 928 @property
929 - def init_state(self):
930 return self._init_state
931
932 -class AbstractRENS(AbstractExchangeMC):
933 """ 934 Abstract Replica Exchange with Nonequilibrium Switches 935 (RENS, Ballard & Jarzynski 2009) class. 936 Subclasses implement various ways of generating trajectories 937 (deterministic or stochastic). 938 """ 939 940 __metaclass__ = ABCMeta 941
942 - def _propose_swap(self, param_info):
943 944 init_state1 = State(param_info.sampler1.state.position, 945 numpy.random.normal(size=param_info.sampler1.state.position.shape)) 946 init_state2 = State(param_info.sampler2.state.position, 947 numpy.random.normal(size=param_info.sampler2.state.position.shape)) 948 949 param_info.sampler1.state = init_state1 950 param_info.sampler2.state = init_state2 951 952 trajinfo12 = RENSTrajInfo(param_info, init_state1, protocol=lambda t, tau: t / tau) 953 trajinfo21 = RENSTrajInfo(param_info, init_state2, protocol=lambda t, tau: (tau - t) / tau) 954 955 traj12 = self._run_traj_generator(trajinfo12) 956 traj21 = self._run_traj_generator(trajinfo21) 957 958 return RENSSwapCommunicator(param_info, traj21.final, traj12.final, traj21.heat, traj12.heat)
959
960 - def _calc_pacc_swap(self, swapcom):
961 962 heat12 = swapcom.heat12 963 heat21 = swapcom.heat21 964 965 proposal1 = swapcom.proposal1 966 proposal2 = swapcom.proposal2 967 968 state1 = swapcom.state1 969 state2 = swapcom.state2 970 971 E1 = lambda x:-swapcom.sampler1._pdf.log_prob(x) 972 E2 = lambda x:-swapcom.sampler2._pdf.log_prob(x) 973 974 w12 = 0.5 * sum(proposal2.momentum ** 2) + E2(proposal2.position) - \ 975 0.5 * sum(state1.momentum ** 2) - E1(state1.position) - heat12 976 w21 = 0.5 * sum(proposal1.momentum ** 2) + E1(proposal1.position) - \ 977 0.5 * sum(state2.momentum ** 2) - E2(state2.position) - heat21 978 979 swapcom.acceptance_probability = csb.numeric.exp(-w12 - w21) 980 981 return swapcom
982 983 @abstractmethod
984 - def _run_traj_generator(self, traj_info):
985 """ 986 Run the trajectory generator which generates a trajectory 987 of a given length between the states of two samplers. 988 989 @param traj_info: TrajectoryInfo instance holding information 990 needed to generate a nonequilibrium trajectory 991 @type traj_info: L{RENSTrajInfo} 992 993 @rtype: L{Trajectory} 994 """ 995 pass
996
997 -class AbstractSwapScheme(object):
998 """ 999 Provides the interface for classes defining schemes according to which swaps in 1000 Replica Exchange-like simulations are performed. 1001 1002 @param algorithm: Exchange algorithm that performs the swaps 1003 @type algorithm: L{AbstractExchangeMC} 1004 """ 1005 1006 __metaclass__ = ABCMeta 1007
1008 - def __init__(self, algorithm):
1009 1010 self._algorithm = algorithm
1011 1012 @abstractmethod
1013 - def swap_all(self):
1014 """ 1015 Advises the Replica Exchange-like algorithm to perform swaps according to 1016 the some schedule defined here. 1017 """ 1018 1019 pass
1020
1021 -class AlternatingAdjacentSwapScheme(AbstractSwapScheme):
1022 """ 1023 Provides a swapping scheme in which tries exchanges between neighbours only 1024 following the scheme 1 <-> 2, 3 <-> 4, ... and after a sampling period 2 <-> 3, 4 <-> 5, ... 1025 1026 @param algorithm: Exchange algorithm that performs the swaps 1027 @type algorithm: L{AbstractExchangeMC} 1028 """ 1029
1030 - def __init__(self, algorithm):
1031 1032 super(AlternatingAdjacentSwapScheme, self).__init__(algorithm) 1033 1034 self._current_swap_list = None 1035 self._swap_list1 = [] 1036 self._swap_list2 = [] 1037 self._create_swap_lists()
1038
1039 - def _create_swap_lists(self):
1040 1041 i = 0 1042 while i < len(self._algorithm.param_infos): 1043 self._swap_list1.append(i) 1044 i += 2 1045 1046 i = 1 1047 while i < len(self._algorithm.param_infos): 1048 self._swap_list2.append(i) 1049 i += 2 1050 1051 self._current_swap_list = self._swap_list1
1052
1053 - def swap_all(self):
1054 1055 for x in self._current_swap_list: 1056 self._algorithm.swap(x) 1057 1058 if self._current_swap_list == self._swap_list1: 1059 self._current_swap_list = self._swap_list2 1060 else: 1061 self._current_swap_list = self._swap_list1
1062