Source code for sim_anneal
'''
General implementation of multi-objective simulated annealing
See June 22 "Implemented optimization" commit
'''
import numpy as np
import random
import time
[docs]def optimize(eval_obj, total_steps = 1000, initial_T = 0.7, n_record = 100):
    
    '''
    Use simulated annealing to optimize defects on the surface
    
    :param eval_obj: Object to be optimized. Must have get_OF(), rand_move(), and revert_last() methods.
    
    :param total_steps: Number of Metropolis steps to run
    
    :param initial_T: Initial temperature (dimensionless). A linear cooling schedule is used
    
    :param n_record: number of steps to print out (not counting initial state)
    '''
    
    # Evaluate initial structure
    OF = eval_obj.get_OF()     
    print  str(0) + ' steps elapsed:       ' + str(OF)
    
    CPU_start = time.time()        
    
    for step in range( total_steps ):
        
        Metro_temp = initial_T * (1 - float(step) / total_steps)            # Set temperature
        OF_prev = OF                                                        # Record data before changing structure
        eval_obj.rand_move()                                                # Do a Metropolis move
        OF = eval_obj.get_OF()                  # Evaluate the new structure and determine whether or not to accept
        
        if OF - OF_prev < 0:                # Downhill move
            accept = True
        else:                               # Uphill move
            if Metro_temp > 0:              # Finite temperature, may accept uphill moves
                accept = np.exp( - ( OF - OF_prev ) / Metro_temp ) > random.random()
            else:                           # Zero temperature, never accept uphill moves
                accept = False
        
        # Reverse the change if the move is not accepted
        if not accept:
            eval_obj.revert_last()
            OF = OF_prev            # Use previous values for evaluations
        
        # Record data
        if (step+1) % (total_steps / n_record) == 0:
            print  str(step+1) + ' steps elapsed:       ' + str(OF)
        
            
    CPU_end = time.time()
    print('Time elapsed: ' + str(CPU_end - CPU_start) )