1 """@namespace IMP.pmi.samplers
2 Sampling of the system.
5 from __future__
import print_function
9 class _SerialReplicaExchange(object):
10 """Dummy replica exchange class used in non-MPI builds.
11 It should act similarly to IMP.mpi.ReplicaExchange on a single processor.
15 def get_number_of_replicas(self):
17 def create_temperatures(self, tmin, tmax, nrep):
19 def get_my_index(self):
21 def set_my_parameter(self, key, val):
22 self.__params[key] = val
23 def get_my_parameter(self, key):
24 return self.__params[key]
25 def get_friend_index(self, step):
27 def get_friend_parameter(self, key, findex):
28 return self.get_my_parameter(key)
29 def do_exchange(self, myscore, fscore, findex):
34 """Sample using Monte Carlo"""
43 def __init__(self, m, objects, temp, filterbyname=None):
54 self.simulated_annealing =
False
55 self.selfadaptive =
False
66 ob.get_particles_to_sample()
68 print(
"MonteCarlo: object ", ob,
" doesn't have get_particles_to_sample() method")
70 pts = ob.get_particles_to_sample()
73 if "Rigid_Bodies" in k:
74 mvs = self.get_rigid_body_movers(
84 mvs = self.get_super_rigid_body_movers(
92 if "Floppy_Bodies" in k:
93 mvs = self.get_floppy_body_movers(pts[k][0], pts[k][1])
99 mvs = self.get_X_movers(pts[k][0], pts[k][1])
105 if not self.isd_available:
106 raise ValueError(
"isd module needed to use nuisances")
107 mvs = self.get_nuisance_movers(pts[k][0], pts[k][1])
113 if not self.isd_available:
114 raise ValueError(
"isd module needed to use weights")
115 mvs = self.get_weight_movers(pts[k][0], pts[k][1])
124 self.mc.set_return_best(
False)
125 self.mc.set_kt(self.temp)
126 self.mc.add_mover(self.smv)
128 def set_kt(self, temp):
135 def set_scoring_function(self, objectlist):
137 for ob
in objectlist:
138 rs.add_restraint(ob.get_restraint())
140 self.mc.set_scoring_function(sf)
142 def set_simulated_annealing(
148 self.simulated_annealing =
True
149 self.tempmin = min_temp
150 self.tempmax = max_temp
151 self.timemin = min_temp_time
152 self.timemax = max_temp_time
154 def set_self_adaptive(self, isselfadaptive=True):
155 self.selfadaptive = isselfadaptive
159 Return a dictionary with the mover parameters for nuisance parameters
162 for i
in range(self.get_number_of_movers()):
163 mv = self.smv.get_mover(i)
165 if "Nuisances" in name:
166 stepsize = IMP.core.NormalMover.get_from(mv).get_sigma()
167 output[name] = stepsize
170 def get_number_of_movers(self):
171 return len(self.smv.get_movers())
173 def get_particle_types():
176 def optimize(self, nstep):
178 self.mc.optimize(nstep * self.get_number_of_movers())
181 if self.simulated_annealing:
182 self.temp = self.temp_simulated_annealing()
183 self.mc.set_kt(self.temp)
186 if self.selfadaptive:
187 for i, mv
in enumerate(self.smv.get_movers()):
190 if "Nuisances" in name:
191 mvacc = mv.get_number_of_accepted()
192 mvprp = mv.get_number_of_proposed()
193 accept = float(mvacc) / float(mvprp)
194 nmv = IMP.core.NormalMover.get_from(mv)
195 stepsize = nmv.get_sigma()
197 if 0.4 > accept
or accept > 0.6:
198 nmv.set_sigma(stepsize * 2 * accept)
201 nmv.set_sigma(stepsize * 2 * accept)
204 nmv.set_sigma(stepsize * 2 * accept)
206 if "Weights" in name:
208 mvacc = mv.get_number_of_accepted()
209 mvprp = mv.get_number_of_proposed()
210 accept = float(mvacc) / float(mvprp)
211 wmv = IMP.isd.WeightMover.get_from(mv)
212 stepsize = wmv.get_radius()
214 if 0.4 > accept
or accept > 0.6:
215 wmv.set_radius(stepsize * 2 * accept)
218 wmv.set_radius(stepsize * 2 * accept)
221 wmv.set_radius(stepsize * 2 * accept)
223 def run(self, *args, **kwargs):
224 IMP.pmi.tools.print_deprecation_warning(
226 "MonteCarlo.optimize")
227 self.optimize(*args, **kwargs)
229 def get_nuisance_movers(self, nuisances, maxstep):
231 for nuisance
in nuisances:
232 print(nuisance, maxstep)
239 def get_rigid_body_movers(self, rbs, maxtrans, maxrot):
245 def get_super_rigid_body_movers(self, rbs, maxtrans, maxrot):
259 srbm.add_xyz_particle(xyz)
261 srbm.add_rigid_body_particle(rb)
265 def get_floppy_body_movers(self, fbs, maxtrans):
273 fb.set_is_optimized(fk,
True)
283 def get_X_movers(self, fbs, maxtrans):
289 raise ValueError(
"particle is part of a rigid body")
295 def get_weight_movers(self, weights, maxstep):
297 for weight
in weights:
298 if(weight.get_number_of_states() > 1):
302 def temp_simulated_annealing(self):
303 if self.nframe % (self.timemin + self.timemax) < self.timemin:
307 temp = self.tempmin + (self.tempmax - self.tempmin) * value
310 def set_label(self, label):
313 def get_frame_number(self):
316 def get_output(self):
319 for i, mv
in enumerate(self.smv.get_movers()):
320 mvname = mv.get_name()
321 mvacc = mv.get_number_of_accepted()
322 mvprp = mv.get_number_of_proposed()
324 mvacr = float(mvacc) / float(mvprp)
327 output[
"MonteCarlo_Acceptance_" +
328 mvname +
"_" + str(i)] = str(mvacr)
329 if "Nuisances" in mvname:
330 output[
"MonteCarlo_StepSize_" + mvname +
"_" +
331 str(i)] = str(IMP.core.NormalMover.get_from(mv).get_sigma())
332 if "Weights" in mvname:
333 output[
"MonteCarlo_StepSize_" + mvname +
"_" +
334 str(i)] = str(IMP.isd.WeightMover.get_from(mv).get_radius())
335 output[
"MonteCarlo_Temperature"] = str(self.mc.get_kt())
336 output[
"MonteCarlo_Nframe"] = str(self.nframe)
341 """Sample using molecular dynamics"""
343 def __init__(self,m,objects,kt,gamma=0.01,maximum_time_step=1.0):
347 to_sample+=obj.get_particles_to_sample()[
'Floppy_Bodies_SimplifiedModel'][0]
352 self.md.set_maximum_time_step(maximum_time_step)
353 self.md.add_optimizer_state(self.ltstate)
354 self.simulated_annealing =
False
358 self.ltstate.set_temperature(temp)
359 self.md.assign_velocities(temp)
361 def set_simulated_annealing(self, min_temp, max_temp, min_temp_time,
363 self.simulated_annealing =
True
364 self.tempmin = min_temp
365 self.tempmax = max_temp
366 self.timemin = min_temp_time
367 self.timemax = max_temp_time
369 def temp_simulated_annealing(self):
370 if self.nframe % (self.timemin + self.timemax) < self.timemin:
374 temp = self.tempmin + (self.tempmax - self.tempmin) * value
377 def set_gamma(self,gamma):
378 self.ltstate.set_gamma(gamma)
380 def optimize(self,nsteps):
383 if self.simulated_annealing:
384 self.temp = self.temp_simulated_annealing()
385 self.set_kt(self.temp)
386 self.md.optimize(nsteps)
388 def get_output(self):
390 output[
"MolecularDynamics_KineticEnergy"]=str(self.md.get_kinetic_energy())
394 """Sample using conjugate gradients"""
396 def __init__(self, m, objects):
401 def set_label(self, label):
404 def get_frame_number(self):
407 def run(self, nstep):
409 self.cg.optimize(nstep)
411 def set_scoring_function(self, objectlist):
413 for ob
in objectlist:
414 rs.add_restraint(ob.get_restraint())
416 self.cg.set_scoring_function(sf)
418 def get_output(self):
421 output[
"ConjugatedGradients_Nframe"] = str(self.nframe)
426 """Sample using replica exchange"""
435 replica_exchange_object=
None):
437 samplerobjects can be a list of MonteCarlo or MolecularDynamics
442 self.samplerobjects = samplerobjects
444 self.TEMPMIN_ = tempmin
445 self.TEMPMAX_ = tempmax
447 if replica_exchange_object
is None:
451 print(
'ReplicaExchange: MPI was found. Using Parallel Replica Exchange')
454 print(
'ReplicaExchange: Could not find MPI. Using Serial Replica Exchange')
455 self.rem = _SerialReplicaExchange()
459 print(
'got existing rex object')
460 self.rem = replica_exchange_object
463 nproc = self.rem.get_number_of_replicas()
465 if nproc % 2 != 0
and test ==
False:
466 raise Exception(
"number of replicas has to be even. set test=True to run with odd number of replicas.")
468 temp = self.rem.create_temperatures(
473 self.temperatures = temp
475 myindex = self.rem.get_my_index()
477 self.rem.set_my_parameter(
"temp", [self.temperatures[myindex]])
478 for so
in self.samplerobjects:
479 so.set_kt(self.temperatures[myindex])
485 def get_temperatures(self):
486 return self.temperatures
488 def get_my_temp(self):
489 return self.rem.get_my_parameter(
"temp")[0]
491 def get_my_index(self):
492 return self.rem.get_my_index()
494 def swap_temp(self, nframe, score=None):
496 score = self.m.evaluate(
False)
498 myindex = self.rem.get_my_index()
499 mytemp = self.rem.get_my_parameter(
"temp")[0]
501 if mytemp == self.TEMPMIN_:
504 if mytemp == self.TEMPMAX_:
508 myscore = score / mytemp
511 findex = self.rem.get_friend_index(nframe)
512 ftemp = self.rem.get_friend_parameter(
"temp", findex)[0]
514 fscore = score / ftemp
517 flag = self.rem.do_exchange(myscore, fscore, findex)
522 for so
in self.samplerobjects:
526 def get_output(self):
529 if self.nattempts != 0:
530 output[
"ReplicaExchange_SwapSuccessRatio"] = str(
531 float(self.nsuccess) / self.nattempts)
532 output[
"ReplicaExchange_MinTempFrequency"] = str(
533 float(self.nmintemp) / self.nattempts)
534 output[
"ReplicaExchange_MaxTempFrequency"] = str(
535 float(self.nmaxtemp) / self.nattempts)
537 output[
"ReplicaExchange_SwapSuccessRatio"] = str(0)
538 output[
"ReplicaExchange_MinTempFrequency"] = str(0)
539 output[
"ReplicaExchange_MaxTempFrequency"] = str(0)
540 output[
"ReplicaExchange_CurrentTemp"] = str(self.get_my_temp())
544 class PyMCMover(object):
547 def __init__(self, representation, mcchild, n_mc_steps):
552 self.rbs = representation.get_rigid_bodies()
555 self.n_mc_steps = n_mc_steps
557 def store_move(self):
560 for copy
in self.rbs:
563 crd.append(rb.get_reference_frame())
564 self.oldcoords.append(crd)
566 def propose_move(self, prob):
567 self.mc.run(self.n_mc_steps)
569 def reset_move(self):
571 for copy, crd
in zip(self.rbs, self.oldcoords):
572 for rb, ref
in zip(copy, crd):
573 rb.set_reference_frame(ref)
575 def get_number_of_steps(self):
576 return self.n_mc_steps
578 def set_number_of_steps(self, nsteps):
579 self.n_mc_steps = nsteps
589 self.restraints =
None
590 self.first_call =
True
593 def add_mover(self, mv):
596 def set_kt(self, kT):
599 def set_return_best(self, thing):
602 def set_move_probability(self, thing):
605 def get_energy(self):
607 pot = sum([r.evaluate(
False)
for r
in self.restraints])
609 pot = self.m.evaluate(
False)
612 def metropolis(self, old, new):
614 print(
": old %f new %f deltaE %f new_epot: %f" % (old, new, deltaE,
621 return exp(-deltaE / kT) > random.uniform(0, 1)
623 def optimize(self, nsteps):
626 print(
"=== new MC call")
630 self.first_call =
False
631 for i
in range(nsteps):
632 print(
"MC step %d " % i, end=
' ')
634 old = self.get_energy()
636 self.mv.propose_move(1)
638 new = self.get_energy()
639 if self.metropolis(old, new):
649 def get_number_of_forward_steps(self):
652 def set_restraints(self, restraints):
653 self.restraints = restraints
655 def set_scoring_function(self, objects):
659 rs.add_restraint(ob.get_restraint())
660 self.set_restraints([rs])
662 def get_output(self):
665 output[
"PyMC_Temperature"] = str(self.kT)
666 output[
"PyMC_Nframe"] = str(self.nframe)
def __init__
samplerobjects can be a list of MonteCarlo or MolecularDynamics
A class to implement Hamiltonian Replica Exchange.
Maintains temperature during molecular dynamics.
Sample using molecular dynamics.
def get_nuisance_movers_parameters
Return a dictionary with the mover parameters for nuisance parameters.
Object used to hold a set of restraints.
Modify the transformation of a rigid body.
Simple conjugate gradients optimizer.
Sample using conjugate gradients.
Modify a set of continuous variables by perturbing them within a ball.
static bool get_is_setup(const IMP::kernel::ParticleAdaptor &p)
Simple molecular dynamics optimizer.
Code that uses the MPI parallel library.
Modify the transformation of a rigid body.
Modify a set of continuous variables using a normal distribution.
Basic functionality that is expected to be used by a wide variety of IMP users.
Sample using Monte Carlo.
static const FloatKeys & get_xyz_keys()
Get a vector containing the keys for x,y,z.
Applies a list of movers one at a time.
Sample using replica exchange.
Inferential scoring building on methods developed as part of the Inferential Structure Determination ...