#!/usr/bin/env python import sys import SA_IO as IO import Simulated_Annealing as ASA import SA_Print as SAPrint ### ### ### MAIN CODE ### ### ### """ Starting code. Procedure for input deck will be changed soon. """ # Input of argument: if len(sys.argv) < 3: SAPrint.HelpInput() sys.exit() else: Method = sys.argv[1] Task = sys.argv[2] if Task == 'Problem': ProblemFileName = sys.argv[3] """ Creating a file for general output """ IO.OutPut(Task, Method) """ Generating X_Opt array """ X_Opt = [] """ Calling the optimisation routine """ if (Method == 'SA'):
def ReadInCoolingSchedule(**kwargs): """ This function reads the contents of the cooling schedule file""" import csv # Using csv (comma separated values) module """ =========================================================== Set up Global variables used throughout the code =========================================================== """ global SA_Function, SA_Minimum, SA_N, SA_NS, SA_NT, SA_MaxEvl, SA_EPS, SA_RT, SA_Temp, \ SA_LowerBounds, SA_UpperBounds, SA_VM, SA_C, SA_Debugging, SA_X, BenchmarkSolution global SA_Xopt, SA_Fopt # These variables are defined here just for practicality """ Local variables: """ SA_Cooling = [] SA_Cooling_list = [] SA_Benchmarks = [] """Reading Input files """ if kwargs: for key in kwargs: if (key == 'File_Name'): # For Problems SA_Function = kwargs[key] Function = SA_Function + '.sa' elif (key == 'Test_Number'): # For Benchmark Test-Cases TestNumber = kwargs[key] dummy, SA_Function = CountingNumberOfTests( Test_Case=TestNumber) Function = os.path.abspath('./Tests/' + SA_Function + '.sa') else: sys.exit('In ReadInCoolingSchedule. Option not found') else: sys.exit('Option not found') Are_There_Dimensions = False """ Open input file containing Cooling Schedule: """ with open(Function, 'r') as file: reader = csv.reader(file, delimiter=' ', skipinitialspace=True) for row in reader: if row == [] or ListOfCommentsStrings( row): # List of comment strings that can be used Nothing_To_Be_Done = True elif row[ 0] == 'Number_Dimensions': # This MUST be the first variable declared in the input file SA_N = int(row[1]) Are_There_Dimensions = True elif Are_There_Dimensions: if row[0] == 'Minimum': # Maximum or Minimum SA_Minimum = to_bool(row[1]) elif row[0] == 'NS': # Maximum number of cycles SA_NS = int(row[1]) elif row[ 0] == 'NT': # Maximum number of iterations before the temperature reduction SA_NT = int(row[1]) elif row[ 0] == 'MaxEvl': # Maximum number of evaluations of the objective function SA_MaxEvl = int(row[1]) elif row[ 0] == 'EPS': # Minimum acceptable discrepancy (used throughout the SAA) SA_EPS = float(row[1]) elif row[0] == 'RT': # Parameter for temperature reduction SA_RT = float(row[1]) elif row[0] == 'Temp': # SAA temperature parameter SA_Temp = float(row[1]) elif row[ 0] == 'X_Init': # Initial guess for the solution-coordinate vector SA_X = ReadingRows_Float(row) elif row[ 0] == 'LowerBounds': # Lower bounds for the solution-coordinate vector SA_LowerBounds = ReadingRows_Float(row) elif row[ 0] == 'UpperBounds': # Upper bounds for the solution-coordinate vector SA_UpperBounds = ReadingRows_Float(row) elif row[ 0] == 'VM': # Stepping matrix (only the diagonal representing each direction SA_VM = ReadingRows_Float(row) elif row[ 0] == 'C': # Parameter for controlling the size of the stepping matrix SA_C = ReadingRows_Float(row) elif row[ 0] == 'Benchmark_Solution': # Solution of the Benchmark test-case BenchmarkSolution = ReadingRows_Float(row, Solution='yes') elif row[ 0] == 'Debugging': # Option to dump all intermediate results into the *.out file (True or False) SA_Debugging = to_bool(row[1]) else: sys.exit('Option not recognised') else: print 'Number_Dimensions was not defined in the FIRST line' sys.exit() file.close() Print.Print_SAA_Diagnostic(Initialisation='yes') if kwargs: for key in kwargs: if (key == 'File_Name' ): # For Problems we assign this array as zero. BenchmarkSolution = [0. in range(SA_N + 1)] return SA_Function, SA_Minimum, SA_N, SA_NS, SA_NT, SA_MaxEvl, SA_EPS, SA_RT, SA_Temp, \ SA_LowerBounds, SA_UpperBounds, SA_VM, SA_C, SA_Debugging, SA_X, BenchmarkSolution
def SimulatedAnnealing(Method, Task, **kwargs): if Task == 'Problem': import SpecialFunctions as SpFunc X_Optimum = [] F_Optimum = [] Time_temp = [] TestSolution = [] TestSolution_Name = [] TestSolution_Time = [] if kwargs: for key in kwargs: if key == 'FileName': FileName = kwargs[key] elif key == 'ProblemType': ProblemType = kwargs[key] (Test, N_Tests) = AssignSolvingProblem(Method, Task, FileName) jtest = 0 for itest in xrange(1, N_Tests + 1): """ ========================================================================= Initialising the SIMULATED ANNEALING ALGORITHM COOLING SCHEDULE ========================================================================= """ if Task == 'Benchmarks': if FileName != 'All': if itest == Test: SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( Test_Number = Test, Task = Task ) print '======================', SaT.Function_Name, '======================' else: continue else: SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( Test_Number = itest, Task = Task ) print '======================', SaT.Function_Name, '======================' elif Task == 'Problem': SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( File_Name = FileName, Task = Task ) else: sys.exit('In SimulatedAnnealing. Option not found') """ =================================================================== Initial Assessement of the Objective Function =================================================================== """ """ Calling the function for the first time before the SA main loop """ if Task == 'Benchmarks': Func = BTest.TestFunction(SaT.Function_Name, SaT.Ndim, SaT.SA_X) else: # Problems Func, X_Feed = ObF.ObjFunction(SaT.SA_X, Problem_Type=ProblemType, Status='InitialCalculations') #sys.exit( Func ) """ The function must be minimum """ if SaT.Minimum: Func = -Func """" Printing into the *out file """ IO.f_SAOutput.write('\n') IO.f_SAOutput.write( 'Initial evaluation of the function: {a:.4e}'.format(a=Func) + '\n') if Task == 'Problem' and ProblemType == 'PhaseEquilibria': SpFunc.CalcOtherPhase(SaT.SA_X, SaT.UpperBounds, SaT.LowerBounds, Diagnostics=True) """ =================================================================== Calling main SA loop: =================================================================== """ if Task == 'Benchmarks': X_OPT, F_OPT = ASA_Loops(Method, Task, Func) else: # Problems X_OPT, F_OPT = ASA_Loops(Method, Task, Func, Problem_Type=ProblemType, X_Feed=X_Feed) X_Optimum.append(X_OPT) F_Optimum.append(F_OPT) print X_Optimum, F_Optimum #sys.exit('---') """ ===================================================================== Assessing the solution (comparison against known solution) =====================================================================""" if Task == 'Benchmarks': TestSolution.append(BTest.AssessTests(X_OPT, SaT.BenchmarkSolution)) TestSolution_Name.append(SaT.Function_Name) TestTime = time.clock() Time_temp.append(TestTime) if FileName == 'All': if itest > 1: TestSolution_Time.append(TestTime - Time_temp[itest - 2]) else: TestSolution_Time.append(TestTime) IO.f_SAOutput.write('\n') IO.f_SAOutput.write( '===========================================================') IO.f_SAOutput.write('\n') IO.f_SAOutput.write( ' Assessment of the test-cases : ') IO.f_SAOutput.write('\n') IO.f_SAOutput.write('{a:}: {b:}'.format( a=SaT.Function_Name, b=TestSolution[jtest]) + '\n') IO.f_SAOutput.write('\n') jtest += 1 else: # Problem TestTime = time.clock() TestSolution_Time.append( time.clock() - SaT.Time_Init) # Measuring CPU time for the problem/test if (Task == 'Benchmarks') and (FileName == 'All'): Print.Print_SAA_Diagnostic(Bench_AllTestCases='yes', Solution=TestSolution, Solution_Name=TestSolution_Name, Solution_Time=TestSolution_Time) return X_Optimum, F_Optimum
def ASA_Loops(Method, Task, Func, **kwargs): """ For debugging """ #pdb.set_trace() TestName = SaT.Function_Name SVLE_Problem = False if kwargs: for key in kwargs: if (key == 'X_Feed'): X_Feed = kwargs[key] elif key == 'Thermodynamics': PhaseEquilibria = kwargs[key] SVLE_Problem = True else: sys.exit('In ASA_Loops. Option was not defined') IO.f_SAOutput.write('\n') IO.f_SAOutput.write('Initialising SA Algorithm for: {a:}'.format( a=TestName) + '\n') """ Initialisation of a few parameters. """ Try = False NAcc = 0 Nobds = 0 NFCNEV = 0 NEps = 4 MaxNum = 1.e20 NACP = [0 for i in range(SaT.Ndim)] XP = [0. for i in range(SaT.Ndim)] FStar = [MaxNum for i in range(NEps)] FStar[0] = Func FOpt = Func XOpt = SaT.SA_X X_Try = SaT.SA_X XOpt_f = [0. for i in range(SaT.Ndim)] """ The 'Fraction' variable assesses if the function to be optimised is a thermodynamic function (TRUE) and therefore the elements of the solution-coordinate needs to be bounded (0,1) and the summation of the N-1 elements must be smaller than 1. If FALSE then the above is neglected. """ if Task == 'Benchmarks': Fraction = False elif Task == 'Problem' and SVLE_Problem: #Problems Fraction = True """ ======================================================================= Beginning of the main outter loop: ======================================================================= """ kloop = 0 while kloop <= SaT.MaxEvl: NUp = 0 NRej = 0 NDown = 0 LNobds = 0 """ Beginning of the m loop: number of iterations """ mloop = 0 while mloop < SaT.NT: """ Beginning of j loop: number of cycles""" jloop = 0 while jloop < SaT.NS: """ Beginning of the h loop: """ hloop = 0 while hloop < SaT.Ndim: if Fraction: dim = SaT.Ndim - 1 else: dim = SaT.Ndim for i in range(SaT.Ndim): rand = RanGen.RandomNumberGenerator(SaT.Ndim) if (i == hloop): XP[i] = X_Try[i] + SaT.VM[i] * (2. * rand[i] - 1.) else: XP[i] = X_Try[i] #IO.f_SAOutput.write( 'XP(b4):{a:}'.format( a= XP ) + '\n' ) #pdb.set_trace() """ =========================================================== Feasibility Test: check is solution is bounded. =========================================================== """ #if Fraction: # XP[ dim ] = X_Try[ dim ] #XP[ SaT.Ndim ] = X_Try[ SaT.Ndim ] if Task == 'Benchmarks': BoxF.Envelope_Constraints( Method, Task, XP, NDim = SaT.Ndim, LBounds = SaT.LowerBounds, \ UBounds = SaT.UpperBounds, TryC = Try, IsNormalised = Fraction ) else: # Problems BoxF.Envelope_Constraints( Method, Task, XP, NDim = SaT.Ndim, LBounds = SaT.LowerBounds, \ UBounds = SaT.UpperBounds, TryC = Try, IsNormalised = Fraction, \ X_Feed = X_Feed ) #IO.f_SAOutput.write( 'XP(after):{a:}'.format( a= XP ) + '\n' ) #IO.f_SAOutput.write( '\n' ) #if kloop > 10: print XP sys.exit('fck') if Try: LNobds += 1 Nobds += 1 """ ============================================================ """ if Task == 'Benchmarks': FuncP = BTest.TestFunction(SaT.Function_Name, SaT.Ndim, XP) else: # Problems FuncP, dummy = ObF.ObjFunction( XP, Thermodynamics=PhaseEquilibria) """ The function must be minimum """ if SaT.Minimum: FuncP = -FuncP NFCNEV += 1 # Number of evaluation of the function """ ================================================================== If there were more than MAXEVL evaluations of the objective function, the SA algorithm will finish. ==================================================================""" if (NFCNEV >= SaT.MaxEvl): FOpt = -FOpt Print.Print_SAA_Diagnostic(MaxEval='yes', FOpt=FOpt, XOpt=XOpt_f, NFCNEV=NFCNEV) sys.exit( 'SAA did not converge. Too many evaluations of the function!' ) """" ================================================================== The new solution-coordinate is accepted and the objective function increases. ==================================================================""" if (FuncP > Func): for i in range(SaT.Ndim): X_Try[i] = XP[i] Func = FuncP if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} New vector-solution is accepted ( X: {a:}) with solution {b:.4f}' .format(s=' ', a=X_Try, b=FuncP) + '\n') NAcc += 1 NACP[hloop] = NACP[hloop] + 1 NUp += 1 """ If the new FP is larger than any other point, this will be chosen as the new optimum """ if (FuncP > FOpt): for i in range(SaT.Ndim): XOpt[i] = XP[i] FOpt = FuncP for i in range(SaT.Ndim): XOpt_f[i] = XP[i] if Task == 'Benchmarks': print 'NFCNEV(', NFCNEV, '), XOpt: ', XOpt_f, ' with FOpt: ', FOpt, '(Analytical:', -BTest.TestFunction( SaT.Function_Name, SaT.Ndim, SaT.BenchmarkSolution[0:SaT.Ndim]), ')' else: if (NFCNEV % 25) >= 24: print 'NFCNEV(', NFCNEV, '), XOpt: ', XOpt_f, ' with FOpt: ', FOpt if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} New XOpt: {a:} with FOpt: {b:}'. format(s=' ', a=XOpt_f, b=FOpt) + '\n') else: # if ( FuncP > Func ): """ However if FuncP is smaller than the others, thus the Metropolis criteria (Gaussian probability density function) - or any other density function that may be added latter - may be used to either accept or reject this coordinate. """ rand = RanGen.RandomNumberGenerator(SaT.Ndim) #Density = math.exp( ( FuncP - Func ) / SaT.Temp )#max( SaT.Temp, SaT.EPS ) ) if SaT.Temp < max(1.e-6, SaT.EPS): Density = math.exp( (FuncP - Func) / max(1.e-3 * SaT.EPS, rand[0])) else: Density = math.exp((FuncP - Func) / SaT.Temp) temp = 1. for i in range(SaT.Ndim): temp = temp * rand[i] Density_Gauss = math.sqrt(abs(temp)) if (Density_Gauss < Density): for i in range(SaT.Ndim): X_Try[i] = XP[i] Func = FuncP if SaT.Debugging == True: IO.f_SAOutput.write('\n \n ') IO.f_SAOutput.write( '{s:20} Metropolis Criteria; New vector-solution is generated ( X: {a:}) with solution {b:.4f}' .format(s=' ', a=X_Try, b=FuncP) + '\n') NAcc += 1 NACP[hloop] = NACP[hloop] + 1 NDown += 1 else: NRej += 1 """ End of h loop """ #pdb.set_trace() hloop += 1 """ End of j loop """ jloop += 1 """ ================================================================== As half of the evaluations may be accepted, thus the VM array may need to be adjusted. ================================================================== """ for i in range(SaT.Ndim): Ratio = float(NACP[i]) / float(SaT.NS) if (Ratio > 0.6): SaT.VM[i] = SaT.VM[i] * (1. + SaT.C[i] * (Ratio - 0.6) / 0.4) elif (Ratio < 0.4): SaT.VM[i] = SaT.VM[i] / (1. + SaT.C[i] * (0.4 - Ratio) / 0.4) if (SaT.VM[i] > (SaT.UpperBounds[i] - SaT.LowerBounds[i])): SaT.VM[i] = SaT.UpperBounds[i] - SaT.LowerBounds[i] if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} {a:3d} Points rejected. VM is adjusted to {b:}'. format(s=' ', a=NRej, b=SaT.VM) + '\n') NACP = [0 for i in range(SaT.Ndim)] """ End of m loop """ mloop += 1 """ ======================================================================= Diagnostics of the algorithm before the next temperature reduction ======================================================================= """ Print.Print_SAA_Diagnostic(Diagnostics='yes', FOpt=FOpt, NUp=NUp, NDown=NDown, NRej=NRej, NAcc=NAcc, LNobds=LNobds, NFCNEV=NFCNEV, XOpt=XOpt, FStar=FStar) # This will make the tests run faster as we know the solution, thus they do # not need to continue search if the solution if close enough if Task == 'Benchmarks': Quit = BTest.AssessTests(XOpt_f, SaT.BenchmarkSolution) if Quit: if SaT.Minimum: FOpt = -FOpt Print.Print_SAA_Diagnostic(Termination='yes', FOpt=FOpt, NRej=NRej, XOpt=XOpt_f, NFCNEV=NFCNEV) return XOpt_f, FOpt #stop """ ========================================================== Checking the stoppage criteria ========================================================== """ Quit = True FStar[0] = Func #print '--------------------------------------' #print ' FOpt, FStar, Func', FOpt, FStar, Func #print '--------------------------------------' if FOpt - FStar[0] <= SaT.EPS: Quit = False for i in range(NEps): if abs(Func - FStar[i]) > SaT.EPS: Quit = False if Quit: if Task == 'Benchmarks': Quit = BTest.AssessTests(XOpt_f, SaT.BenchmarkSolution) elif Task == 'Problem' and IO.to_bool( SaT.BenchmarkSolution[0]): # For validation Solution = np.arange(float(SaT.Ndim)) for i in range(SaT.Ndim): Solution[i] = IO.num(SaT.BenchmarkSolution[i + 1]) FuncValid, dummy = ObF.ObjFunction( Solution, Thermodynamics=PhaseEquilibria) FuncOpt, dummy = ObF.ObjFunction( XOpt, Thermodynamics=PhaseEquilibria) print 'Gibbs Function (Validation, Optimum):', FuncValid, FuncOpt Pass = True if abs(FuncValid - FuncOpt) >= SaT.EPS: Pass = Pass and False for i in range(SaT.Ndim): if abs(XOpt[i] - Solution[i]) >= SaT.EPS: Pass = Pass and False if Pass: print 'Error Associated with: ' print ' (a) Function: ', abs( FuncValid - FuncOpt) / FuncValid * 100., '%' print ' (b) Solution Variables:' for i in range(SaT.Ndim): print 'X[', i, ']', abs( XOpt[i] - Solution[i]) / Solution[i] * 100., '%' Quit == True #print '===>', SaT.BenchmarkSolution #print assert(SaT.BenchmarkSolution) #sys.exit('fck11') #if assert(SaT.BenchmarkSolution): # sys.exit('fck11') #else: # sys.exit('fck--') #elif Quit and ( Task == 'Problem' ) and """ ========================================================== Termination of the Simulated Annealing algorithm ========================================================== """ if Quit: #X_Try = XOpt if SaT.Minimum: FOpt = -FOpt Print.Print_SAA_Diagnostic(Termination='yes', FOpt=FOpt, NRej=NRej, XOpt=XOpt_f, NFCNEV=NFCNEV) if Task == 'Problem': SpFunc.CalcOtherPhase(XP, SaT.UpperBounds, SaT.LowerBounds, Diagnostics=True) return XOpt_f, FOpt #print ' XOpt_f, FOpt ', XOpt_f, FOpt """ ========================================================== If the stoppage criteria can not be reached, then continue the K-LOOP ========================================================== """ SaT.Temp = SaT.RT * SaT.Temp for i in xrange(NEps - 1, 0, -1): FStar[i] = FStar[i - 1] #print 'FStar[ i ]',FStar[ i ] Func = FOpt for i in range(SaT.Ndim): X_Try[i] = XOpt[i] #print 'X_Try[ i ]',X_Try[ i ] """ End of k loop """ kloop += 1
def SimulatedAnnealing(Method, Task, **kwargs): X_Optimum = [] F_Optimum = [] TestSolution = [] TestSolution_Name = [] TestSolution_Time = [] Time_temp = [] """" =================================================================== If we are undertaken model validation through benchmarks, we may opt to run all benchmark test-cases or a specific one controlled in the original command line as: a) python Optimiser.py SAA Benchmarks All or b) python Optimiser.py SAA Benchmarks N respectively, where N is the number of the required test-case as defined in the 'Benchmarks.in' file. =================================================================== """ N_Tests, dummy = IO.CountingNumberOfTests( ) # Checking the total number of test-cases. if (Task == 'Benchmarks'): if kwargs: for key in kwargs: if (key == 'FileName'): TestCases = kwargs[key] if TestCases == 'All': Test = 100 * N_Tests else: Test = int(TestCases) elif (Task == 'Problem'): if kwargs: for key in kwargs: if (key == 'FileName'): ProblemFileName = kwargs[key] Test = 0 N_Tests = 0 else: sys.exit('In SimulatedAnnealing function. Option not found') """" =================================================================== Now, depending on the case, 'Benchmarks' or 'Problem' we proceed the optimisation, if: a) 'Problem': then N_Tests = 0 and we run SAA just once or b) 'Benchmarks': there are 2 options here, b.1 ) 'All': it will read each cooling schedule file for all test-cases and proceed with the optimisation. b.2 ) 'N': where 1 <= N <= N_Tests. It will read only the cooling schedule of test-case N and proceed with the optimisation. =================================================================== """ jtest = 0 for itest in xrange(1, N_Tests + 1): if (Task == 'Benchmarks'): if TestCases != 'All': # Dealing with test-case N if itest == Test: SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( Test_Number = Test ) print '======================', SaT.Function_Name, '======================' else: continue else: SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( Test_Number = itest ) print '======================', SaT.Function_Name, '======================' elif (Task == 'Problem'): SaT.Function_Name, SaT.Minimum, SaT.Ndim, SaT.NS, SaT.NT, SaT.MaxEvl, SaT.EPS, SaT.RT, SaT.Temp, \ SaT.LowerBounds, SaT.UpperBounds, SaT.VM, SaT.C, SaT.Debugging, \ SaT.SA_X, SaT.BenchmarkSolution = IO.ReadInCoolingSchedule( File_Name = ProblemFileName ) else: sys.exit('In SimulatedAnnealing. Option not found') """ =================================================================== Initial Assessemnt of the Objective Function =================================================================== """ """ Calling the function for the first time before the SA main loop """ if Task == 'Benchmarks': Func = BTest.TestFunction(SaT.Function_Name, SaT.Ndim, SaT.SA_X) else: # Problems Func = ObF.ObjFunction(SaT.Function_Name, SaT.Ndim, SaT.SA_X) """ The function must be minimum """ if SaT.Minimum: Func = -Func """" Printing into the *out file """ IO.f_SAOutput.write('\n') IO.f_SAOutput.write( 'Initial evaluation of the function: {a:.4e}'.format(a=Func) + '\n') """ =================================================================== Calling main SA loop: =================================================================== """ X_OPT, F_OPT = ASA_Loops(Task, Func) X_Optimum.append(X_OPT) F_Optimum.append(F_OPT) """ ===================================================================== Assessing the solution (comparison against known solution) =====================================================================""" if Task == 'Benchmarks': TestSolution.append(BTest.AssessTests(X_OPT, SaT.BenchmarkSolution)) TestSolution_Name.append(SaT.Function_Name) TestTime = time.clock() Time_temp.append(TestTime) if TestCases == 'All': if itest > 1: TestSolution_Time.append(TestTime - Time_temp[itest - 1]) else: TestSolution_Time.append(TestTime) IO.f_SAOutput.write('\n') IO.f_SAOutput.write( '===========================================================') IO.f_SAOutput.write('\n') IO.f_SAOutput.write( ' Assessment of the test-cases : ') IO.f_SAOutput.write('\n') IO.f_SAOutput.write('{a:}: {b:}'.format( a=SaT.Function_Name, b=TestSolution[jtest]) + '\n') IO.f_SAOutput.write('\n') jtest += 1 else: # Problem TestTime = time.clock() TestSolution_Time.append( time.clock() - SaT.Time_Init) # Measuring CPU time for the problem/test print 'TestSolutionTime_all:', TestSolution_Time if (Task == 'Benchmarks') and (TestCases == 'All'): Print.Print_SAA_Diagnostic(Bench_AllTestCases='yes', Solution=TestSolution, Solution_Name=TestSolution_Name, Solution_Time=TestSolution_Time) #return X_OPT, F_OPT return X_Optimum, F_Optimum
def ASA_Loops(Task, Func): """ For debugging """ #pdb.set_trace() TestName = SaT.Function_Name IO.f_SAOutput.write('\n') IO.f_SAOutput.write('Initialising SA Algorithm for: {a:}'.format( a=TestName) + '\n') """ Initialisation of a few parameters. """ Try = False NAcc = 0 Nobds = 0 NFCNEV = 0 NEps = 4 MaxNum = 1.e20 NACP = [0 for i in range(SaT.Ndim)] XP = [0. for i in range(SaT.Ndim)] FStar = [MaxNum for i in range(NEps)] FStar[0] = Func FOpt = Func XOpt = SaT.SA_X X_Try = SaT.SA_X XOpt_f = [0. for i in range(SaT.Ndim)] """ The 'Fraction' variable assess if the function to be optimised is a thermodynamic function (TRUE) and therefore the elements of the solution-coordinate needs to be bounded (0,1) and the summation of the N-1 elements must be smaller than 1. If FALSE then the above is neglected. """ if Task == 'Benchmarks': Fraction = False else: Fraction = True kloop = 0 """ Beginning of the main outter loop: """ while kloop <= SaT.MaxEvl: NUp = 0 NRej = 0 NDown = 0 LNobds = 0 """ Beginning of the m loop: """ mloop = 0 while mloop < SaT.NT: """ Beginning of j loop: """ jloop = 0 while jloop < SaT.NS: """ Beginning of the h loop: """ hloop = 0 while hloop < SaT.Ndim: if Fraction: dim = SaT.Ndim - 1 else: dim = SaT.Ndim for i in range(dim): rand = RanGen.RandomNumberGenerator(dim) if (i == hloop): XP[i] = X_Try[i] + SaT.VM[i] * (2. * rand[i] - 1.) else: XP[i] = X_Try[i] """ =========================================================== Feasibility Test (only for Thermod problems) -- check for compositional constraints. =========================================================== """ if Fraction: XP[dim - 1] = 1. - SpFunc.ListSum(XP[0:dim]) SpFunc.Envelope_Constraints(XP, NDim=SaT.Ndim, LBounds=SaT.LowerBounds, UBounds=SaT.UpperBounds, TryC=Try, IsNormalised=Fraction) if Try: LNobds += 1 Nobds += 1 """ ============================================================ """ if Task == 'Benchmarks': FuncP = BTest.TestFunction(SaT.Function_Name, SaT.Ndim, XP) else: # Problems FuncP = ObF.ObjFunction(SaT.Function_Name, SaT.Ndim, XP) """ The function must be minimum """ if SaT.Minimum: FuncP = -FuncP NFCNEV += 1 # Number of evaluation of the function """ ================================================================== If there were more than MAXEVL evaluations of the objective function, the SA algorithm will finish. ==================================================================""" if (NFCNEV >= SaT.MaxEvl): FOpt = -FOpt Print.Print_SAA_Diagnostic(MaxEval='yes', FOpt=FOpt, XOpt=XOpt_f, NFCNEV=NFCNEV) sys.exit( 'SAA did not converge. Too many evaluations of the function!' ) """" ================================================================== The new solution-coordinate is accepted and the objective function increases. ==================================================================""" if (FuncP >= Func): for i in range(SaT.Ndim): X_Try[i] = XP[i] Func = FuncP if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} New vector-solution is accepted ( X: {a:}) with solution {b:.4f}' .format(s=' ', a=X_Try, b=FuncP) + '\n') NAcc += 1 NACP[hloop] = NACP[hloop] + 1 NUp += 1 """ If the new FP is larger than any other point, this will be chosen as the new optimum """ if (FuncP > FOpt): for i in range(SaT.Ndim): XOpt[i] = XP[i] FOpt = FuncP for i in range(SaT.Ndim): XOpt_f[i] = XP[i] print 'NFCNEV(', NFCNEV, '), XOpt: ', XOpt_f, ' with FOpt: ', FOpt, '(Analytical:', -BTest.TestFunction( SaT.Function_Name, SaT.Ndim, SaT.BenchmarkSolution[0:SaT.Ndim]), ')' if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} New XOpt: {a:} with FOpt: {b:}'. format(s=' ', a=XOpt_f, b=FOpt) + '\n') else: """ However if FuncP is smaller than the others, thus the Metropolis criteria (Gaussian probability density function) - or any other density function that may be added latter - may be used to either accept or reject this coordinate. """ rand = RanGen.RandomNumberGenerator(SaT.Ndim) #Density = math.exp( ( FuncP - Func ) / SaT.Temp )#max( SaT.Temp, SaT.EPS ) ) if SaT.Temp < max(1.e-6, SaT.EPS): Density = math.exp( (FuncP - Func) / max(1.e-3 * SaT.EPS, rand[0])) else: Density = math.exp((FuncP - Func) / SaT.Temp) temp = 1. for i in range(SaT.Ndim): temp = temp * rand[i] Density_Gauss = math.sqrt(abs(temp)) if (Density_Gauss < Density): for i in range(SaT.Ndim): X_Try[i] = XP[i] Func = FuncP if SaT.Debugging == True: IO.f_SAOutput.write('\n \n ') IO.f_SAOutput.write( '{s:20} Metropolis Criteria; New vector-solution is generated ( X: {a:}) with solution {b:.4f}' .format(s=' ', a=X_Try, b=FuncP) + '\n') NAcc += 1 NACP[hloop] = NACP[hloop] + 1 NDown += 1 else: NRej += 1 """ End of h loop """ hloop += 1 """ End of j loop """ jloop += 1 """ ================================================================== As half of the evaluations may be accepted, thus the VM array may need to be adjusted. ================================================================== """ for i in range(SaT.Ndim): Ratio = float(NACP[i]) / float(SaT.NS) if (Ratio > 0.6): SaT.VM[i] = SaT.VM[i] * (1. + SaT.C[i] * (Ratio - 0.6) / 0.4) elif (Ratio < 0.4): SaT.VM[i] = SaT.VM[i] / (1. + SaT.C[i] * (0.4 - Ratio) / 0.4) if (SaT.VM[i] > (SaT.UpperBounds[i] - SaT.LowerBounds[i])): SaT.VM[i] = SaT.UpperBounds[i] - SaT.LowerBounds[i] if SaT.Debugging == True: IO.f_SAOutput.write( '{s:20} {a:3d} Points rejected. VM is adjusted to {b:}'. format(s=' ', a=NRej, b=SaT.VM) + '\n') NACP = [0 for i in range(SaT.Ndim)] """ End of m loop """ mloop += 1 """ ======================================================================= Diagnostics of the algorithm before the next temperature reduction ======================================================================= """ Print.Print_SAA_Diagnostic(Diagnostics='yes', FOpt=FOpt, NUp=NUp, NDown=NDown, NRej=NRej, NAcc=NAcc, LNobds=LNobds, NFCNEV=NFCNEV, XOpt=XOpt, FStar=FStar) # This will make the tests run faster as we know the solution, thus they do # not need to continue search if the solution if close enough if Task == 'Benchmarks': Quit = BTest.AssessTests(XOpt_f, SaT.BenchmarkSolution) if Quit: if SaT.Minimum: FOpt = -FOpt Print.Print_SAA_Diagnostic(Termination='yes', FOpt=FOpt, NRej=NRej, XOpt=XOpt_f, NFCNEV=NFCNEV) return XOpt_f, FOpt """ ========================================================== Checking the stoppage criteria ========================================================== """ Quit = False FStar[0] = Func if FOpt - FStar[0] <= SaT.EPS: Quit = True for i in range(NEps): if abs(Func - FStar[i]) > SaT.EPS: Quit = False if Quit and (Task == 'Benchmarks'): Quit = BTest.AssessTests(XOpt_f, SaT.BenchmarkSolution) """ ========================================================== Termination of the Simulated Annealing algorithm ========================================================== """ if Quit: #X_Try = XOpt if SaT.Minimum: FOpt = -FOpt Print.Print_SAA_Diagnostic(Termination='yes', FOpt=FOpt, NRej=NRej, XOpt=XOpt_f, NFCNEV=NFCNEV) return XOpt_f, FOpt """ ========================================================== If the stoppage criteria can not be reached, then continue the K-LOOP ========================================================== """ SaT.Temp = SaT.RT * SaT.Temp for i in xrange(NEps - 1, 0, -1): FStar[i] = FStar[i - 1] Func = FOpt for i in range(SaT.Ndim): X_Try[i] = XOpt[i] """ End of k loop """ kloop += 1