Exemplo n.º 1
0
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