def apply_localsearch(name, method, fitness_fun, bounds, current_best, current_best_fitness, maxevals, fid): global SR_MTS global SR_global_MTS lower = bounds[0][0] upper = bounds[0][1] if method == 'grad': sol, fit, info = fmin_l_bfgs_b(fitness_fun, x0=current_best, approx_grad=1, bounds=bounds, maxfun=maxevals, disp=False) funcalls = info['funcalls'] elif method == 'mts': # import ipdb # ipdb.set_trace() if name.lower() == "global": SR = SR_global_MTS else: SR = SR_MTS res, SR_MTS = mtsls(fitness_fun, current_best, current_best_fitness, lower, upper, maxevals, SR) sol = res.solution fit = res.fitness funcalls = maxevals else: raise NotImplementedError(method) if fit <= current_best_fitness: fid.write( get_improvement("{0} {1}".format(method.upper(), name), current_best_fitness, fit)) return EAresult(solution=np.array(sol), fitness=fit, evaluations=funcalls) else: return EAresult(solution=current_best, fitness=current_best_fitness, evaluations=funcalls)
def _mtsls_improve_dim(function, sol, best_fitness, i, check, SR): newsol = copy(sol) newsol[i] -= SR[i] newsol = check(newsol) fitness_newsol = function(newsol) evals = 1 if fitness_newsol < best_fitness: best_fitness = fitness_newsol sol = newsol elif fitness_newsol > best_fitness: newsol = copy(sol) newsol[i] += 0.5 * SR[i] newsol = check(newsol) fitness_newsol = function(newsol) evals += 1 if (fitness_newsol < best_fitness): best_fitness = fitness_newsol sol = newsol return EAresult(solution=sol, fitness=best_fitness, evaluations=evals)
def improve(fun, run_info, dimension, check_evals, name_output=None, replace=True, popsize=100, H=100, population=None, population_fitness=None, initial_solution=None, MemF=None, MemCR=None, times=1, ignoreLimits=False): """ It applies the DE elements. Params ------ fun function of the problem to optimize. run_info is a dictionary with the following information: lower: double lower bounds upper: double upper bounds threshold: minimum optim value dimension of the problem. max_evals maximum_evaluations_numbers. name_output name of the output file run number of evaluations replace replace the file debug show the debug info if it is true PS population size times the number of runs to carry out. ignoreLimits ignore the limits in the run. """ assert isinstance(dimension, int), 'dimension should be integer' assert (dimension > 0), 'dimension must be positive' final, fid = get_experiments_file(name_output, replace, times=times) if final is not None: return final for attr in ['lower', 'upper', 'threshold', 'best']: assert attr in run_info.keys( ), "'{}' info not provided for benchmark".format(attr) # Added in a array the max evaluations if not isinstance(check_evals, list): check_evals = [check_evals] domain = (run_info['lower'], run_info['upper']) fun_best = run_info['best'] maxEval = check_evals[-1] check_eval = check_evals.pop() if population is None: population = random_population(domain, dimension, popsize) else: popsize = population.shape[0] if initial_solution is not None: population[0] = initial_solution if population_fitness is None: population_fitness = np.array([fun(ind) for ind in population]) currentEval = popsize else: currentEval = 0 # Init memory with population memory = population.tolist() # Init F and CR memorySize = popsize * 2 if MemF is None: MemF = np.ones(H) * 0.5 if MemCR is None: MemCR = np.ones(H) * 0.5 k = 0 pmin = 2.0 / popsize while currentEval < maxEval: SCR = [] SF = [] F = np.zeros(popsize) CR = np.zeros(popsize) u = np.zeros((popsize, dimension)) best_fitness = np.min(population_fitness) numEvalFound = currentEval for (i, xi) in enumerate(population): # Getting F and CR for that solution index_H = np.random.randint(0, H) meanF = MemF[index_H] meanCR = MemCR[index_H] Fi = np.random.normal(meanF, 0.1) CRi = np.random.normal(meanCR, 0.1) p = np.random.rand() * (0.2 - pmin) + pmin # Get two random values r1 = random_indexes(1, popsize, ignore=[i]) # Get the second from the memory r2 = random_indexes(1, len(memory), ignore=[i, r1]) xr1 = population[r1] xr2 = memory[r2] # Get one of the p best values maxbest = int(p * popsize) bests = np.argsort(population_fitness)[:maxbest] pbest = np.random.choice(bests) xbest = population[pbest] # Mutation v = xi + Fi * (xbest - xi) + Fi * (xr1 - xr2) # Special clipping if not ignoreLimits: v = shade_clip(domain, v, xi) # Crossover idxchange = np.random.rand(dimension) < CRi u[i] = np.copy(xi) u[i, idxchange] = v[idxchange] F[i] = Fi CR[i] = CRi # Update population and SF, SCR weights = [] for i, fitness in enumerate(population_fitness): fitness_u = fun(u[i]) if math.isnan(fitness_u): print(i) print(domain) print(u[i]) print(fitness_u) assert not math.isnan(fitness_u) if fitness_u <= fitness: # Add to memory if fitness_u < fitness: memory.append(population[i]) SF.append(F[i]) SCR.append(CR[i]) weights.append(fitness - fitness_u) if (fitness_u < best_fitness): best_fitness = fitness_u numEvalFound = currentEval population[i] = u[i] population_fitness[i] = fitness_u currentEval += popsize # Check the memory memory = limit_memory(memory, memorySize) # Update MemCR and MemF if len(SCR) > 0 and len(SF) > 0: Fnew, CRnew = update_FCR(SF, SCR, weights) MemF[k] = Fnew MemCR[k] = CRnew k = (k + 1) % H if fid is not None and currentEval >= check_eval: bestFitness = np.min(population_fitness) #print("bestFitness: {}".format(bestFitness)) fid.write("[%.0e]: %e,%d\n" % (check_eval, abs(bestFitness - fun_best), numEvalFound)) fid.flush() if check_evals: check_eval = check_evals.pop(0) if fid is not None: fid.close() bestIndex = np.argmin(population_fitness) #print("SHADE Mean[F,CR]: ({0:.2f}, {1:.2f})".format(MemF.mean(), MemCR.mean())) return EAresult(fitness=population_fitness[bestIndex], solution=population[bestIndex], evaluations=numEvalFound), bestIndex
def ihshadels(fitness_fun, funinfo, dim, evals, evals_index, fid, start_time, info_de, popsize=100, debug=False, threshold=0.05): """ Implementation of the proposal for CEC2015 """ lower = funinfo['lower'] upper = funinfo['upper'] evals = evals[:] initial_sol = np.ones(dim) * ((lower + upper) / 2.0) current_best_fitness = fitness_fun(initial_sol) maxevals = evals[evals_index - 1] totalevals = 1 bounds = list(zip(np.ones(dim) * lower, np.ones(dim) * upper)) bounds_partial = list(zip(np.ones(dim) * lower, np.ones(dim) * upper)) popsize = min(popsize, 100) population = reset_de(popsize, dim, lower, upper, info_de) populationFitness = [fitness_fun(ind) for ind in population] bestId = np.argmin(populationFitness) initial_sol = np.ones(dim) * (lower + upper) / 2.0 initial_fitness = fitness_fun(initial_sol) if initial_fitness < populationFitness[bestId]: fid.write("Best initial_sol\n") population[bestId] = initial_sol populationFitness[bestId] = initial_fitness current_best = EAresult(solution=population[bestId, :], fitness=populationFitness[bestId], evaluations=totalevals) crossover = DEcrossover.SADECrossover(2) best_global_solution = current_best.solution best_global_fitness = current_best.fitness current_best_solution = best_global_solution apply_de = apply_ls = True applyDE = applySHADE reset_ls(dim, lower, upper) methods = ['mts', 'grad'] pool_global = PoolLast(methods) pool = PoolLast(methods) num_worse = 0 evals_gs = min(50 * dim, 25000) evals_de = min(50 * dim, 25000) evals_ls = min(10 * dim, 5000) num_restarts = 0 while totalevals < maxevals: method = "" if not pool_global.is_empty(): previous_fitness = current_best.fitness method_global = pool_global.get_new() current_best = apply_localsearch("Global", method_global, fitness_fun, bounds, current_best_solution, current_best.fitness, evals_gs, fid) totalevals += current_best.evaluations fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) improvement = get_ratio_improvement(previous_fitness, current_best.fitness) pool_global.improvement(method_global, improvement, 2) evals = check_evals(totalevals, evals, current_best.fitness, best_global_fitness, fid) current_best_solution = current_best.solution current_best_fitness = current_best.fitness if current_best_fitness < best_global_fitness: best_global_solution = np.copy(current_best_solution) best_global_fitness = fitness_fun(best_global_solution) for i in range(1): current_best = EAresult(solution=current_best_solution, fitness=current_best_fitness, evaluations=0) set_region_ls() method = pool.get_new() fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) if apply_de: result, bestInd = applyDE(crossover, fitness_fun, funinfo, dim, evals_de, population, populationFitness, bestId, current_best, fid, info_de) improvement = current_best.fitness - result.fitness totalevals += result.evaluations fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) evals = check_evals(totalevals, evals, result.fitness, best_global_fitness, fid) current_best = result if apply_ls: result = apply_localsearch("Local", method, fitness_fun, bounds_partial, current_best.solution, current_best.fitness, evals_ls, fid) improvement = get_ratio_improvement(current_best.fitness, result.fitness) totalevals += result.evaluations fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) evals = check_evals(totalevals, evals, result.fitness, best_global_fitness, fid) current_best = result pool.improvement(method, improvement, 10, .25) current_best_solution = current_best.solution current_best_fitness = current_best.fitness if current_best_fitness < best_global_fitness: best_global_fitness = current_best_fitness best_global_solution = np.copy(current_best_solution) # Restart if it is not improved if (previous_fitness == 0): ratio_improvement = 1 else: ratio_improvement = (previous_fitness - result.fitness) / previous_fitness #fid.write("TotalImprovement[{:d}%] {:.3e} => {:.3e} ({})\tRestart: {}\n".format( #int(100*ratio_improvement), previous_fitness, result.fitness, #num_worse, num_restarts)) if ratio_improvement >= threshold: num_worse = 0 else: num_worse += 1 imp_str = ",".join([ "{}:{}".format(m, val) for m, val in pool.improvements.items() ]) #fid.write("Pools Improvements: {}".format(imp_str)) # Random the LS reset_ls(dim, lower, upper, method) if num_worse >= 3: num_worse = 0 # import ipdb; ipdb.set_trace() #fid.write("Restart:{0:.2e} for {1:.2f}: with {2:d} evaluations\n".format(current_best.fitness, ratio_improvement, totalevals)) # Increase a 1% of values posi = np.random.choice(popsize) new_solution = np.random.uniform( -0.01, 0.01, dim) * (upper - lower) + population[posi] new_solution = np.clip(new_solution, lower, upper) current_best = EAresult(solution=new_solution, fitness=fitness_fun(new_solution), evaluations=0) current_best_solution = current_best.solution current_best_fitness = current_best.fitness # Init DE population = reset_de(popsize, dim, lower, upper, info_de) populationFitness = [fitness_fun(ind) for ind in population] totalevals += popsize fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) totalevals += popsize fid.write("Best: %f - Evals: %f\n" % (best_global_fitness, totalevals)) # Random the LS pool_global.reset() pool.reset() reset_ls(dim, lower, upper) num_restarts += 1 #fid.write("{0:.2e}({1:.2e}): with {2:d} evaluations\n".format(current_best_fitness, best_global_fitness, totalevals)) # fid.write("improvement_group[{}] : {:.2e}\n".format(i, (initial_fitness - result.fitness))) fid.flush() if totalevals >= maxevals: break # Time stamp elapsed_time = time.clock() - start_time fid.write("\n\nSummary: Results\n\n") fid.write("Best global fitness: %e\n" % (abs(best_global_fitness))) fid.write("Time %f\n" % elapsed_time) fid.write("Total evals: %d\n" % totalevals) fid.write("BEST: \n%s" % (' '.join(map(str, best_global_solution)))) fid.flush() return result
def mtsls(function, sol, fitness, lower, upper, maxevals, SR): """ Implements the MTS LS parameters :function: to optimize. :sol: solution to improves. :lower: lower domain. :upper: upper domain. :maxevals: maximum evaluations. :SR: step size. :improved: indicate the ratio of previous improvement. """ dim = len(sol) improve.init(dim) improved_dim = zeros(dim, dtype=bool) check = partial(clip, a_min=lower, a_max=upper) current_best = EAresult(solution=sol, fitness=fitness, evaluations=0) totalevals = 0 improvement = zeros(dim) if totalevals < maxevals: dims = arange(dim) dim_sorted = improve.getDimensionsByProb(dims, 0.95, int(0.025 * dim)) print("Redux size: ", len(dim_sorted)) for i in dim_sorted: result = _mtsls_improve_dim(function, current_best.solution, current_best.fitness, i, check, SR) totalevals += result.evaluations improvement[i] = max(current_best.fitness - result.fitness, 0) if improvement[i]: improved_dim[i] = True current_best = result else: SR[i] /= 2 dim_sorted = improvement.argsort()[::-1] d = 0 while totalevals < maxevals: i = dim_sorted[d] result = _mtsls_improve_dim(function, current_best.solution, current_best.fitness, i, check, SR) totalevals += result.evaluations improvement[i] = max(current_best.fitness - result.fitness, 0) next_d = (d + 1) % dim if improvement[i]: improved_dim[i] = True current_best = result improve.updateValue(i, improvement[i]) else: SR[i] /= 2 d = next_d # Check lower value initial_SR = 0.2 * (upper - lower) SR[SR < 1e-15] = initial_SR return current_best, SR