1 """@namespace IMP.pmi.samplers
2 Sampling of the system.
10 class _SerialReplicaExchange:
11 """Dummy replica exchange class used in non-MPI builds.
12 It should act similarly to IMP.mpi.ReplicaExchange
13 on a single processor.
18 def get_number_of_replicas(self):
21 def create_temperatures(self, tmin, tmax, nrep):
24 def get_my_index(self):
27 def set_my_parameter(self, key, val):
28 self.__params[key] = val
30 def get_my_parameter(self, key):
31 return self.__params[key]
33 def get_friend_index(self, step):
36 def get_friend_parameter(self, key, findex):
37 return self.get_my_parameter(key)
39 def do_exchange(self, myscore, fscore, findex):
42 def set_was_used(self, was_used):
43 self.was_used = was_used
47 def __init__(self, model):
51 self.simulated_annealing =
False
53 def set_simulated_annealing(self, min_temp, max_temp, min_temp_time,
55 self.simulated_annealing =
True
56 self.tempmin = min_temp
57 self.tempmax = max_temp
58 self.timemin = min_temp_time
59 self.timemax = max_temp_time
61 def temp_simulated_annealing(self):
62 if self.nframe % (self.timemin + self.timemax) < self.timemin:
66 temp = self.tempmin + (self.tempmax - self.tempmin) * value
71 """Sample using Monte Carlo"""
80 def __init__(self, model, objects=None, temp=1.0, filterbyname=None,
81 score_moved=
False, use_jax=
False):
82 """Setup Monte Carlo sampling
83 @param model The IMP Model
84 @param objects What to sample (a list of Movers)
85 @param temp The MC temperature
86 @param filterbyname Not used
87 @param score_moved If True, attempt to speed up sampling by
88 caching scoring function terms on particles that didn't move
89 @param use_jax If set to True, sample the scoring function using
90 JAX instead of IMP's internal C++ implementation (requires
91 that all PMI restraints used have a JAX implementation).
101 self.selfadaptive =
False
106 self.movers_data = {}
107 self.use_jax = use_jax
108 self._jax_optimizer =
None
109 self._jax_state =
None
117 self.mc.set_scoring_function(get_restraint_set(self.model))
118 self.mc.set_return_best(
False)
119 self.mc.set_score_moved(score_moved)
120 self.mc.set_kt(self.temp)
121 self.mc.add_mover(self.smv)
123 def set_kt(self, temp):
126 if self._jax_state
is not None:
127 self._jax_state.temperature = temp
132 def set_scoring_function(self, objectlist):
134 for ob
in objectlist:
135 rs.add_restraint(ob.get_restraint())
137 self.mc.set_scoring_function(sf)
139 def set_self_adaptive(self, isselfadaptive=True):
140 self.selfadaptive = isselfadaptive
144 Return a dictionary with the mover parameters for nuisance parameters
147 for i
in range(self.get_number_of_movers()):
148 mv = self.smv.get_mover(i)
150 if "Nuisances" in name:
151 stepsize = IMP.core.NormalMover.get_from(mv).get_sigma()
152 output[name] = stepsize
155 def get_number_of_movers(self):
156 return len(self.smv.get_movers())
158 def get_particle_types(self):
161 def optimize(self, nstep):
164 if self._jax_optimizer
is None:
165 self._jax_optimizer = self.mc._get_jax_optimizer(
166 nstep * self.get_number_of_movers())
167 self._jax_state = self._jax_optimizer.get_initial_state()
168 score, self._jax_state = self._jax_optimizer.optimize(
171 score = self.mc.optimize(nstep * self.get_number_of_movers())
174 if self.simulated_annealing:
175 self.set_kt(self.temp_simulated_annealing())
178 if self.selfadaptive:
180 raise NotImplementedError(
181 "Adaptive protocol is not yet implemented for JAX")
182 for i, mv
in enumerate(self.mvs):
184 mvacc = mv.get_number_of_accepted()
185 mvprp = mv.get_number_of_proposed()
186 if mv
not in self.movers_data:
187 accept = float(mvacc) / float(mvprp)
188 self.movers_data[mv] = (mvacc, mvprp)
190 oldmvacc, oldmvprp = self.movers_data[mv]
191 accept = float(mvacc-oldmvacc) / float(mvprp-oldmvprp)
192 self.movers_data[mv] = (mvacc, mvprp)
199 stepsize = mv.get_sigma()
200 if 0.4 > accept
or accept > 0.6:
201 mv.set_sigma(stepsize * 2 * accept)
204 stepsize = mv.get_radius()
205 if 0.4 > accept
or accept > 0.6:
206 mv.set_radius(stepsize * 2 * accept)
209 mr = mv.get_maximum_rotation()
210 mt = mv.get_maximum_translation()
211 if 0.4 > accept
or accept > 0.6:
212 mv.set_maximum_rotation(mr * 2 * accept)
213 mv.set_maximum_translation(mt * 2 * accept)
216 mr = mv.get_maximum_rotation()
217 mt = mv.get_maximum_translation()
218 if 0.4 > accept
or accept > 0.6:
219 mv.set_maximum_rotation(mr * 2 * accept)
220 mv.set_maximum_translation(mt * 2 * accept)
224 if 0.4 > accept
or accept > 0.6:
225 mv.set_radius(mr * 2 * accept)
228 def get_nuisance_movers(self, nuisances, maxstep):
230 for nuisance
in nuisances:
231 print(nuisance, maxstep)
238 def get_rigid_body_movers(self, rbs, maxtrans, maxrot):
245 def get_super_rigid_body_movers(self, rbs, maxtrans, maxrot):
252 if isinstance(rb[2], tuple)
and len(rb[2]) == 3 \
253 and isinstance(rb[2][0], float) \
254 and isinstance(rb[2][1], float) \
255 and isinstance(rb[2][2], float):
262 "Setting up a super rigid body with wrong parameters")
266 srbm.add_xyz_particle(xyz)
268 srbm.add_rigid_body_particle(rb)
272 def get_floppy_body_movers(self, fbs, maxtrans):
281 fb.set_is_optimized(fk,
True)
291 def get_X_movers(self, fbs, maxtrans):
297 raise ValueError(
"particle is part of a rigid body")
303 def get_weight_movers(self, weights, maxstep):
305 for weight
in weights:
306 if weight.get_number_of_weights() > 1:
310 def get_surface_movers(self, surfaces, maxtrans, maxrot, refprob):
312 for surface
in surfaces:
317 def set_label(self, label):
320 def get_frame_number(self):
323 def get_output(self):
325 for i, mv
in enumerate(self.smv.get_movers()):
326 mvname = mv.get_name()
327 mvacc = mv.get_number_of_accepted()
328 mvprp = mv.get_number_of_proposed()
330 mvacr = float(mvacc) / float(mvprp)
333 output[
"MonteCarlo_Acceptance_" +
334 mvname +
"_" + str(i)] = str(mvacr)
335 if "Nuisances" in mvname:
336 output[
"MonteCarlo_StepSize_" + mvname +
"_" + str(i)] = \
337 str(IMP.core.NormalMover.get_from(mv).get_sigma())
338 if "Weights" in mvname:
339 output[
"MonteCarlo_StepSize_" + mvname +
"_" + str(i)] = \
340 str(IMP.isd.WeightMover.get_from(mv).get_radius())
341 output[
"MonteCarlo_Temperature"] = str(self.mc.get_kt())
342 output[
"MonteCarlo_Nframe"] = str(self.nframe)
347 """Sample using molecular dynamics"""
349 def __init__(self, model, objects, kt, gamma=0.01, maximum_time_step=1.0,
350 sf=
None, use_jax=
False):
352 @param model The IMP Model
353 @param objects What to sample. Use flat list of particles
354 @param kt Temperature
355 @param gamma Viscosity parameter
356 @param maximum_time_step MD max time step
357 @param use_jax If set to True, sample the scoring function using
358 JAX instead of IMP's internal C++ implementation (requires
359 that all PMI restraints used have a JAX implementation).
363 raise NotImplementedError(
"JAX currently only supported for MC")
368 psamp = obj.get_particles_to_sample()
369 to_sample = psamp[
'Floppy_Bodies_SimplifiedModel'][0]
374 self.model, to_sample, kt/0.0019872041, gamma)
376 self.md.set_maximum_time_step(maximum_time_step)
378 self.md.set_scoring_function(sf)
380 self.md.set_scoring_function(get_restraint_set(self.model))
381 self.md.add_optimizer_state(self.ltstate)
383 def set_kt(self, kt):
384 temp = kt/0.0019872041
385 self.ltstate.set_temperature(temp)
386 self.md.assign_velocities(temp)
388 def set_gamma(self, gamma):
389 self.ltstate.set_gamma(gamma)
391 def optimize(self, nsteps):
394 if self.simulated_annealing:
395 self.set_kt(self.temp_simulated_annealing())
396 return self.md.optimize(nsteps)
398 def get_output(self):
400 output[
"MolecularDynamics_KineticEnergy"] = \
401 str(self.md.get_kinetic_energy())
406 """Sample using conjugate gradients"""
408 def __init__(self, model, objects):
412 self.cg.set_scoring_function(get_restraint_set(self.model))
414 def set_label(self, label):
417 def get_frame_number(self):
420 def optimize(self, nstep):
422 self.cg.optimize(nstep)
424 def set_scoring_function(self, objectlist):
426 for ob
in objectlist:
427 rs.add_restraint(ob.get_restraint())
429 self.cg.set_scoring_function(sf)
431 def get_output(self):
433 output[
"ConjugatedGradients_Nframe"] = str(self.nframe)
438 """Sample using replica exchange"""
440 def __init__(self, model, tempmin, tempmax, samplerobjects, test=True,
441 replica_exchange_object=
None):
443 samplerobjects can be a list of MonteCarlo or MolecularDynamics
447 self.samplerobjects = samplerobjects
449 self.TEMPMIN_ = tempmin
450 self.TEMPMAX_ = tempmax
452 if replica_exchange_object
is None:
456 print(
'ReplicaExchange: MPI was found. '
457 'Using Parallel Replica Exchange')
460 print(
'ReplicaExchange: Could not find MPI. '
461 'Using Serial Replica Exchange')
462 self.rem = _SerialReplicaExchange()
466 print(
'got existing rex object')
467 self.rem = replica_exchange_object
470 nproc = self.rem.get_number_of_replicas()
472 if nproc % 2 != 0
and not test:
474 "number of replicas has to be even. "
475 "set test=True to run with odd number of replicas.")
477 temp = self.rem.create_temperatures(
482 self.temperatures = temp
484 myindex = self.rem.get_my_index()
486 self.rem.set_my_parameter(
"temp", [self.temperatures[myindex]])
487 for so
in self.samplerobjects:
488 so.set_kt(self.temperatures[myindex])
494 def get_temperatures(self):
495 return self.temperatures
497 def get_my_temp(self):
498 return self.rem.get_my_parameter(
"temp")[0]
500 def get_my_index(self):
501 return self.rem.get_my_index()
503 def swap_temp(self, nframe, score=None):
505 score = self.model.evaluate(
False)
507 _ = self.rem.get_my_index()
508 mytemp = self.rem.get_my_parameter(
"temp")[0]
510 if mytemp == self.TEMPMIN_:
513 if mytemp == self.TEMPMAX_:
517 myscore = score / mytemp
520 findex = self.rem.get_friend_index(nframe)
521 ftemp = self.rem.get_friend_parameter(
"temp", findex)[0]
523 fscore = score / ftemp
526 flag = self.rem.do_exchange(myscore, fscore, findex)
531 for so
in self.samplerobjects:
535 def get_output(self):
537 if self.nattempts != 0:
538 output[
"ReplicaExchange_SwapSuccessRatio"] = str(
539 float(self.nsuccess) / self.nattempts)
540 output[
"ReplicaExchange_MinTempFrequency"] = str(
541 float(self.nmintemp) / self.nattempts)
542 output[
"ReplicaExchange_MaxTempFrequency"] = str(
543 float(self.nmaxtemp) / self.nattempts)
545 output[
"ReplicaExchange_SwapSuccessRatio"] = str(0)
546 output[
"ReplicaExchange_MinTempFrequency"] = str(0)
547 output[
"ReplicaExchange_MaxTempFrequency"] = str(0)
548 output[
"ReplicaExchange_CurrentTemp"] = str(self.get_my_temp())
553 def __init__(self, replica_exchange_object=None):
554 """Query values (ie score, and others)
555 from a set of parallel jobs"""
557 if replica_exchange_object
is None:
561 print(
'MPI_values: MPI was found. '
562 'Using Parallel Replica Exchange')
565 print(
'MPI_values: Could not find MPI. '
566 'Using Serial Replica Exchange')
567 self.rem = _SerialReplicaExchange()
571 print(
'got existing rex object')
572 self.rem = replica_exchange_object
574 def set_value(self, name, value):
575 self.rem.set_my_parameter(name, [value])
577 def get_values(self, name):
579 for i
in range(self.rem.get_number_of_replicas()):
580 v = self.rem.get_friend_parameter(name, i)[0]
584 def get_percentile(self, name):
585 value = self.rem.get_my_parameter(name)[0]
586 values = sorted(self.get_values(name))
587 ind = values.index(value)
588 percentile = float(ind)/len(values)
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.
Modify the transformation of a rigid body.
Simple conjugate gradients optimizer.
Sample using conjugate gradients.
Create a scoring function on a list of restraints.
Move continuous particle variables by perturbing them within a ball.
Modify a surface orientation.
static FloatKeys get_internal_coordinate_keys()
Object used to hold a set of restraints.
Simple molecular dynamics simulator.
Code that uses the MPI parallel library.
A mover that perturbs a Weight particle.
def __init__
Setup Monte Carlo sampling.
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.
The general base class for IMP exceptions.
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.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
Sample using replica exchange.
Inferential scoring building on methods developed as part of the Inferential Structure Determination ...