class SimulatedAnnealing: ''' 1. easy to dump the object as a resulting model, and the trajectory? 2. linear cooling rate ''' def __init__( self, scorefxn, steps, temp, cooling_rate ): ''' ''' assert isScoreFxn( scorefxn ) self._log = "" self._scorefxn = scorefxn self._steps = steps # MC steps per annealing cycle self._temperature = temp # declare objects self.__fragidx_pose = FragIdxPose() self._initialization = "random" self._cooling_rate = cooling_rate self._anneal_temp = 0.0 # recover_low ( quench ) self._quench = False self._lowest_score_pose = FragIdxPose() self._record_trajectory = False def set_annealing_temperature( self ): ''' ''' self._anneal_temp = round( self._temperature*self._cooling_rate, 1 ) self._temperature -= self._anneal_temp def run( self, runid ): ''' run id is a identification for a model to dump ''' self.__fragidx_pose.clear() self.__fragidx_pose.initialization( self._scorefxn.get_density_score_dict(), self._initialization ) # default initialize by random #print self.__fragidx_pose.show_state( "initialization" ) mc = MonteCarlo( self._scorefxn, self._temperature ) mc.apply( self.__fragidx_pose, self._steps ) # to prevent a silly bug that at the very first state SCORE==0, such that you wouldn't lower than that during high temperatures sampling self._lowest_score_pose = self.__fragidx_pose.clone() tracker = TrajectoryTracker( runid ) tag = "model_" + str( runid ) while self._temperature >=0 : # it would never reach this criteria if self._quench: self.recover_low() # retrieve the lowest-score pose from previous runs mc.apply( self.__fragidx_pose, self._steps ) residual_pose = self._scorefxn.residualize_pose() # residual_pose will be filled with #print residual_pose.show_state( tag + "_" + str( self._temperature ) ) self.set_annealing_temperature() # update self._temperature if self._temperature == mc.get_temperature(): break mc.set_temperature( self._temperature ) if self._record_trajectory: tracker.save( self._temperature, self.__fragidx_pose ) tracker.save( self._temperature, self._scorefxn.residualize_pose() ) tracker.dump_pickle( tag ) residual_pose.show_state( tag + "_final", True ) # True for verbose showing all residues states def set_to_quench( self ): self._quench = True def record_trajectory( self ): self._record_trajectory = True def recover_low( self ): # recover_low ''' last accept score pose, and lowest score pose; the MC.recover_low has this is because it uses Metropolis to thermally accept pose ''' # this is for the first around # need to think about a better way to initiate it if not self._lowest_score_pose._initialized: self._lowest_score_pose._initialized = self.__fragidx_pose # .total_score() method will re-evaluate pose whenever it is called if self.__fragidx_pose.total_score() > self._lowest_score_pose.total_score(): stdout.write("recover previous found lowest-score pose with score: %s\n" % self._lowest_score_pose.total_score() ) self.__fragidx_pose = self._lowest_score_pose.clone() else: stdout.write("found a newer lowest-score pose\n") self._lowest_score_pose = self.__fragidx_pose.clone() def dump( self, id ): return def quench( self ): return