1 """
2 Propagator class employing stepwise trajectories as used in the NCMC
3 algorithm (Nilmeier et al., "Nonequilibrium candidate Monte Carlo is
4 an efficient tool for equilibrium simulation", PNAS 2011)
5 """
6
7 import csb
8
9 import numpy
10
11 from abc import ABCMeta, abstractmethod
12 from csb.statistics.samplers.mc import TrajectoryBuilder, Trajectory, augment_state, PropagationResult
13 from csb.statistics.samplers.mc.propagators import AbstractPropagator, MDPropagator, HMCPropagator
14 from csb.numeric import InvertibleMatrix
15 from csb.numeric.integrators import FastLeapFrog
18 """
19 Trajectory holding additional information about energy difference
20 the Jacobian.
21
22 @param items: sequence of trajectory states
23 @type items: list of L{State}s
24
25 @param heat: heat produced during the trajectory
26 @type heat: float
27
28 @param work: work expended during the trajectory
29 @type work: float
30
31 @param deltaH: energy difference between initial and final states
32 @type deltaH: float
33
34 @param jacobian: product of Jacobians of perturbations applied in the
35 calculation of the trajectory
36 @type jacobian: float
37 """
38
39 - def __init__(self, items, heat=0.0, work=0.0, deltaH=0.0, jacobian=1.0, stats=None):
49
50 @property
53 @jacobian.setter
55 self._jacobian = value
56
57 @property
60 @deltaH.setter
63
64 @property
67 @stats.setter
70
73 """
74 Subclasses hold all information describing a current system setup
75 (Hamiltonian, boundaries, ...)
76 """
77
78 pass
79
81 """
82 Instances hold the result of a perturbation.
83
84 @param items: list of states defining a phase-space trajectory
85 @type items: list of L{AbstractState}s
86
87 @param work: work performed on the system during perturbation
88 @type work: float
89
90 @param jacobian: jacobian of the perturbation
91 @type jacobian: float
92
93 @param perturbed_sys: L{AbstractSystemInfo} instance
94 describing the perturbed system
95 @type perturbed_sys: L{AbstractSystemInfo}
96 """
97
98 - def __init__(self, items, perturbed_sys, work, heat=0.0, jacobian=1.0):
106
107 @property
109 return self._jacobian
110 @jacobian.setter
112 self._jacobian = value
113
114 @property
116 return self._perturbed_sys
117 @perturbed_sys.setter
119 self._perturbed_sys = value
120
123 """
124 Describes a stepwise protocol as in Nilmeier et al. (2011).
125
126 @param steps: the steps making up the protocol
127 @type steps: list of L{Step}s
128 """
129
134
135 @property
137 """
138 The steps making up the protocol
139 """
140 return self._steps
141 @steps.setter
144
146 """
147 Defines a step in an NCMC-like stepwise protocol.
148
149 @param perturbation: The perturbation of the system
150 @type perturbation: L{AbstractPerturbation}
151
152 @param propagation: The propagation of the perturbed system
153 @type propagation: L{AbstractPropagation}
154 """
155
156 - def __init__(self, perturbation, propagation):
164
195
226
228 """
229 Perform first perturbation, then propagation
230 """
231
232 self.perform = self._perform_pert_prop
233
235 """
236 Perform first propagation, then perturbation
237 """
238
239 self.perform = self._perform_prop_pert
240
241 @property
243 return self._perturbation
244 @perturbation.setter
246 self._perturbation = value
247
248 @property
250 return self._propagation
251 @propagation.setter
253 self._propagation = value
254
257 """
258 Describes a reduced Hamiltonian (Hamiltonian, its position gradient
259 and the system temperature)
260
261 @param log_prob: log probability of the PDF under consideration, that is,
262 the negative potential energy of the system
263 @type log_prob: callable
264
265 @param gradient: gradient of the negative log probability of the PDF under
266 consideration, that is, the gradient of the potential energy;
267 function of position array and time
268 @type gradient: callable
269
270 @param temperature: system temperature
271 @type temperature: float
272
273 @param mass_matrix: system mass matrix
274 @type mass_matrix: L{InvertibleMatrix}
275 """
276
277 - def __init__(self, log_prob, gradient=None, temperature=1.0, mass_matrix=None):
286
288 """
289 Potential energy of the system, aka negative log probability
290
291 @param x: position vector
292 @type x: 1D numpy array
293 """
294
295 return -self.log_prob(x)
296
298 """
299 Kinetic energy of the system
300
301 @param p: system momentum vector
302 @type p: 1D numpy array
303 """
304
305 if p is not None:
306 if self.mass_matrix is None:
307 return 0.5 * sum(p ** 2)
308 else:
309 if self.mass_matrix.is_unity_multiple:
310 return 0.5 * sum(p ** 2) / self.mass_matrix[0][0]
311 else:
312 return 0.5 * numpy.dot(p, numpy.dot(self.mass_matrix.inverse, p))
313 else:
314 return 0.0
315
317 """
318 Reduced log probability
319
320 @param x: position vector
321 @type x: 1D numpy array
322 """
323
324 return self.log_prob(x) / self.temperature
325
327 """
328 Reduced kinetic energy
329
330 @param p: system momentum vector
331 @type p: 1D numpy array
332 """
333
334 return self.kinetic_energy(p) / self.temperature
335
345
346 @property
348 return self._log_prob
349 @log_prob.setter
351 self._log_prob = value
352
353 @property
355 return self._gradient
356 @gradient.setter
358 self._gradient = value
359
360 @property
362 return self._temperature
363 @temperature.setter
365 self._temperature = value
366
367 @property
369 return self._mass_matrix
370 @mass_matrix.setter
372 self._mass_matrix = value
373
376 """
377 Describes an abstract system perturbation
378
379 @param sys_before: information about the system before the perturbation
380 @type sys_before: L{AbstractSystemInfo}
381
382 @param sys_after: information about the system after the perturbation
383 @type sys_after: L{AbstractSystemInfo}
384
385 @param param: parameters neccessary for system perturbation
386 @type param: L{AbstractPerturbationParam}
387
388 @param evaluate_work: Allows to switch off the work evaluation,
389 which might not always be needed, in order to
390 save computation time.
391 @type evaluate_work: boolean
392 """
393
394 __metaclass__ = ABCMeta
395
396 - def __init__(self, sys_before, sys_after, param=None, evaluate_work=True):
404
405 @abstractmethod
407 """
408 Calculates the trajectory of the system while it is being perturbed.
409
410 @param state: The initial system state
411 @type state: L{State}
412
413 @return: The trajectory of the system while it is being perturbed
414 @rtype: L{Trajectory}
415 """
416
417 pass
418
419 @abstractmethod
421 """
422 Calculates the work expended during perturbation of the system.
423
424 @param traj: The trajectory of the system while being perturbed
425 @type traj: L{Trajectory}
426
427 @return: The work expended during perturbation
428 @rtype: float
429 """
430
431 pass
432
433 @abstractmethod
435 """
436 Calculates the Jacobian determinant which reflects phase
437 space compression during perturbation.
438
439 @param traj: The trajectory of the system while being perturbed
440 @type traj: L{Trajectory}
441
442 @return: The Jacobian determinant
443 @rtype: float
444 """
445
446 pass
447
462
464 """
465 Performs the perturbation of the system and / or the state
466
467 @param state: system state
468 @type state: L{State}
469 """
470
471 return self._evaluate(state)
472
473 @property
475 return self._sys_before
476 @sys_before.setter
478 self._sys_before = value
479
480 @property
482 return self._sys_after
483 @sys_after.setter
485 self._sys_after = value
486
487 @property
490 @param.setter
493
494 @property
496 return self._evaluate_work
497 @evaluate_work.setter
499 self._evaluate_work = value
500
503 """
504 Describes an abstract system propagation
505
506 @param sys: information about the current system setup
507 @type sys: L{AbstractSystemInfo}
508
509 @param param: parameters neccessary for propagating the system
510 @type param: L{AbstractPropagationParam}
511
512 @param evaluate_heat: Allows to switch off the heat evaluation,
513 which might not always be needed, in order to
514 save computation time.
515 @type evaluate_heat: boolean
516 """
517
518 __metaclass__ = ABCMeta
519
520 - def __init__(self, sys, param, evaluate_heat=True):
528
529 @abstractmethod
531 """
532 Factory method which returns the propagator to be used for
533 propagating the system.
534
535 @return: Some propagator object
536 @rtype: L{AbstractPropagator}
537 """
538
539 @abstractmethod
541 """
542 Propagates the system using the propagator instance returned
543 by _propagator_factory().
544
545 @param state: Initial state
546 @type state: L{State}
547
548 @return: The result of the propagation
549 @rtype: L{PropagationResult}
550 """
551
552 pass
553
554 @abstractmethod
556 """
557 Calculates the heat resulting from system propagation.
558
559 @param traj: The trajectory of the system during propagation
560 @type traj: L{Trajectory}
561
562 @return: The heat resulting from system propagation.
563 @rtype: float
564 """
565
566 pass
567
569 """
570 Performs the propagation of a state in the specified system
571
572 @param state: system state
573 @type state: L{State}
574 """
575
576 traj = self._run_propagator(state)
577 heat = self._calculate_heat(traj)
578
579 return PropagationResult(traj.initial, traj.final, heat=heat)
580
582 """
583 Performs the propagation of a state in the specified system
584
585 @param state: system state
586 @type state: L{State}
587 """
588
589 return self._evaluate(state)
590
591 @property
594 @sys.setter
595 - def sys(self, value):
597
598 @property
601 @param.setter
604
605 @property
607 return self._evaluate_heat
608 @evaluate_heat.setter
610 self._evaluate_heat = value
611
614 """
615 System perturbation by changing the reduced Hamiltonian
616
617 @param sys_before: information about the system before the perturbation
618 @type sys_before: L{AbstractSystemInfo}
619
620 @param sys_after: information about the system after the perturbation
621 @type sys_after: L{AbstractSystemInfo}
622
623 @param evaluate_work: Allows to switch off the work evaluation,
624 which might not always be needed, in order to
625 save computation time.
626 @type evaluate_work: boolean
627 """
628
629 - def __init__(self, sys_before, sys_after, evaluate_work=True):
633
642
646
650
653 """
654 System propagation by some MC algorithm.
655
656 @param sys: information about the current system setup
657 @type sys: L{AbstractSystemInfo}
658
659 @param param: parameters neccessary for propagating the system
660 @type param: L{AbstractPropagationParam}
661
662 @param evaluate_heat: Allows to switch off the heat evaluation,
663 which might not always be needed, in order to
664 save computation time.
665 @type evaluate_heat: boolean
666 """
667
668
669 - def __init__(self, sys, param, evaluate_heat=True):
672
681
687
690 """
691 System propagation by HMC
692
693 @param sys: information about the current system setup
694 @type sys: L{AbstractSystemInfo}
695
696 @param param: parameters neccessary for propagating the system
697 @type param: L{HMCPropagationParam}
698
699 @param evaluate_heat: Allows to switch off the heat evaluation,
700 which might not always be needed, in order to
701 save computation time.
702 @type evaluate_heat: boolean
703 """
704
705 - def __init__(self, sys, param, evaluate_heat=True):
711
713 """
714 Sets the mass matrix in the param object.
715
716 @param state: The initial state which is used to determine the dimension
717 of the mass matrix
718 @type state: L{State}
719 """
720
721 if self.param.mass_matrix is None:
722 d = len(state.position)
723 self.param.mass_matrix = InvertibleMatrix(numpy.eye(d))
724
734
740
741 @property
744 @param.setter
747
750 """
751 System propagation by some MD algorithm
752
753 @param sys: information about the current system setup
754 @type sys: L{AbstractSystemInfo}
755
756 @param param: parameters neccessary for propagating the system
757 @type param: L{MDPropagationParam}
758
759 @param evaluate_heat: Allows to switch off the heat evaluation,
760 which might not always be needed, in order to
761 save computation time.
762 @type evaluate_heat: boolean
763 """
764
765 __metaclass__ = ABCMeta
766
767
768 - def __init__(self, sys, param, evaluate_heat=True):
771
773 """
774 Sets the mass matrix in the param object.
775
776 @param state: The initial state which is used to determine the dimension
777 of the mass matrix
778 @type state: L{State}
779 """
780
781 if self.param.mass_matrix is None:
782 d = len(state.position)
783 self.param.mass_matrix = InvertibleMatrix(numpy.eye(d))
784
798
806
809 """
810 System propagation by plain, microcanonical MD
811
812 @param sys: information about the current system setup
813 @type sys: L{AbstractSystemInfo}
814
815 @param param: parameters neccessary for propagating the system
816 @type param: L{PlainMDPropagationParam}
817
818 @param evaluate_heat: Allows to switch off the heat evaluation,
819 which might not always be needed, in order to
820 save computation time.
821 @type evaluate_heat: boolean
822 """
823
824
825 - def __init__(self, sys, param, evaluate_heat=True):
828
834
842
848
851 """
852 Subclasses hold informations required for different kinds
853 of system perturbation
854 """
855
856 pass
857
860 """
861 Subclasses hold informations required for different kinds
862 of system propagation
863 """
864
865 pass
866
869 """
870 Holds all required information for calculating a MD trajectory.
871
872 @param timestep: integration timestep
873 @type timestep: float
874
875 @param traj_length: MD trajectory length
876 @type traj_length: int
877
878 @param gradient: gradient governing the equations of motion, function of
879 position array and time
880 @type gradient: callable
881
882 @param temperature: System temperature for drawing momenta from the
883 Maxwell distribution
884 @type temperature: float
885
886 @param integrator: Integration scheme to be utilized
887 @type integrator: L{AbstractIntegrator}
888
889 @param mass_matrix: mass matrix for kinetic energy definition
890 @type mass_matrix: L{InvertibleMatrix}
891 """
892
893 - def __init__(self, timestep, traj_length, gradient, temperature=1.0,
894 integrator=FastLeapFrog, mass_matrix=None):
908
909 @property
911 return self._timestep
912 @timestep.setter
914 self._timestep = value
915
916 @property
918 return self._traj_length
919 @traj_length.setter
921 self._traj_length = value
922
923 @property
925 return self._gradient
926 @gradient.setter
928 self._gradient = value
929
930 @property
932 return self._temperature
933 @temperature.setter
935 self._temperature = value
936
937 @property
939 return self._integrator
940 @integrator.setter
942 self._integrator = value
943
944 @property
946 return self._mass_matrix
947 @mass_matrix.setter
949 self._mass_matrix = value
950
953 """
954 Holds all required information for propagating a system by HMC.
955 The system temperature is taken from the
956 HMCPropagation.sys.hamiltonian.temperature property.
957
958 @param timestep: integration timestep
959 @type timestep: float
960
961 @param traj_length: MD trajectory length
962 @type traj_length: int
963
964 @param gradient: gradient governing the equations of motion, function of
965 position array and time
966 @type gradient: callable
967
968 @param iterations: number of HMC iterations to be performed
969 @type iterations: int
970
971 @param integrator: Integration scheme to be utilized
972 @type integrator: l{AbstractIntegrator}
973
974 @param mass_matrix: mass matrix for kinetic energy definition
975 @type mass_matrix: L{InvertibleMatrix}
976 """
977
978 - def __init__(self, timestep, traj_length, gradient, iterations=1,
979 integrator=FastLeapFrog, mass_matrix=None):
986
987 @property
989 return self._iterations
990 @iterations.setter
992 self._iterations = value
993
998
1001 """
1002 Holds all required information for propagating a system by MD.
1003 The system temperature is taken from the
1004 MDPropagation.sys.hamiltonian.temperature property.
1005
1006 @param timestep: integration timestep
1007 @type timestep: float
1008
1009 @param traj_length: MD trajectory length
1010 @type traj_length: int
1011
1012 @param gradient: gradient governing the equations of motion, function of
1013 position array and time
1014 @type gradient: callable
1015
1016 @param integrator: Integration scheme to be utilized
1017 @type integrator: l{AbstractIntegrator}
1018
1019 @param mass_matrix: mass matrix for kinetic energy definition
1020 @type mass_matrix: L{InvertibleMatrix}
1021 """
1022
1023 - def __init__(self, timestep, traj_length, gradient,
1024 integrator=FastLeapFrog, mass_matrix=None):
1028
1031 """
1032 Holds information describing a system by its Hamiltonian only.
1033
1034 @param hamiltonian: the Hamiltonian of the system to be described
1035 @type hamiltonian: L{ReducedHamiltonian}
1036 """
1037
1042
1043 @property
1045 return self._hamiltonian
1046 @hamiltonian.setter
1048 self._hamiltonian = value
1049
1052 '''
1053 Abstract class defining a minimal interface for objects allowing to store statistics
1054 of what happens in L{Step} instances.
1055 '''
1056
1057 @abstractmethod
1058 - def update(self, step_index, shorttraj, stats_data):
1060
1063
1064 - def update(self, step_index, shorttraj, stats_data):
1066
1069 '''
1070 Abstract class defining the interface for objects keeping track of and accumulating
1071 heat, work and the Jacobian during a nonequilibrium trajectory.
1072 '''
1073
1075
1076 self._heat = 0.0
1077 self._work = 0.0
1078 self._jacobian = 1.0
1079
1080 @abstractmethod
1081 - def accumulate(self, heat=0.0, work=0.0, jacobian=1.0):
1082 '''
1083 Adds heat and work contribution to the so far accumulated values and
1084 "multiply-accumulates" the Jacobian to the so far "multiply-accumulated" values.
1085 '''
1086 pass
1087
1088 @property
1091
1092 @property
1095
1096 @property
1098 return self._jacobian
1099
1102
1103 - def accumulate(self, heat=0.0, work=0.0, jacobian=1.0):
1104
1105 self._heat += heat
1106 self._work += work
1107 self._jacobian *= jacobian
1108
1111 """
1112 Propagator class which propagates a system using NCMC-like
1113 stepwise trajectories
1114
1115 @param protocol: stepwise protocol to be followed
1116 @type protocol: L{Protocol}
1117 """
1118
1123
1136
1138 '''
1139 Factory method for the L{AbstractHeatWorkJacobianLogger} subclass instance
1140 which keeps track of work, heat and Jacobian contributions during the nonequilibrium
1141 trajectory.
1142
1143 @rtype: instance of an L{AbstractHeatWorkJacobianLogger}-derived class
1144 '''
1145
1146 return TrivialHeatWorkJacobianLogger()
1147
1149 '''
1150 Factory method for the L{AbstractStepStatistics} subclass instance
1151 which can be used to collect statistics of what happens during steps.
1152
1153 @rtype: instance of an L{AbstractStepStatistics}-derived class
1154 '''
1155
1156 return DummyStepStatistics()
1157
1159 '''
1160 Provides additional information for the first step in the protocol.
1161
1162 @rtype: any type
1163 '''
1164
1165 return None
1166
1205
1206
1207 - def generate(self, init_state, return_trajectory=False):
1233
1234 @property
1236 return self._protocol
1237 @protocol.setter
1239 self._protocol = value
1240