python - Project Euler 461 - Genetic Algorithm -
someone told me this problem should easy solve genetic algorithm.
i read stuff topic (i hadn't heard before), , wrote (and copied) code.
results close optimum, not close enough.
i'd have it:
import time import math import random def f(n, k): return math.exp(k / n) - 1 def individual(length, min, max): 'create member of population.' return [random.randint(min, max) x in range(length)] def population(count, length, min, max): """ create number of individuals (i.e. population). count: number of individuals in population length: number of values per individual min: minimum possible value in individual's list of values max: maximum possible value in individual's list of values """ return [individual(length, min, max) x in range(count)] def fitness(individual, target): def get_best_last_element(a, b, c): s = math.pi - f(eu461.base, a) - f(eu461.base, b) - f(eu461.base, c) s += 1 if s > 1: return round(math.log(s) * eu461.base) else: return 0 def getg(): return get_best_last_element """ determine fitness of individual. higher better. individual: individual evaluate target: target number individuals aiming """ l = get_best_last_element(individual[0], individual[1], individual[2]) return abs(target - sum([f(eu461.base, k) k in individual]) - f(eu461.base, l)) def grade(pop, target): 'find average fitness population.' return sum([fitness(x, target) x in pop]) / (len(pop)) def evolve(pop, target, retain=0.2, random_select=0.05, mutate=0.01): graded = [(fitness(x, target), x) x in pop] graded = [x[1] x in sorted(graded)] retain_length = int(len(graded) * retain) parents = graded[:retain_length] # randomly add other individuals # promote genetic diversity individual in graded[retain_length:]: if random_select > random.random(): parents.append(individual) # mutate individuals individual in parents: if mutate > random.random(): pos_to_mutate = random.randint(0, len(individual) - 1) # mutation not ideal, because # restricts range of possible values, # function unaware of min/max # values used create individuals, individual[pos_to_mutate] = random.randint(min(individual), max(individual)) # crossover parents create children parents_length = len(parents) desired_length = len(pop) - parents_length children = [] while len(children) < desired_length: male = random.randint(0, parents_length - 1) female = random.randint(0, parents_length - 1) if male != female: male = parents[male] female = parents[female] half = len(male) // 2 if random.randint(0, 1): child = male[:half] + female[half:] else: child = female[:half] + male[half:] children.append(child) parents.extend(children) return parents def get_best_last_element(a, b, c): s = math.pi - f(eu461.base, a) - f(eu461.base, b) - f(eu461.base, c) s += 1 if s > 0: return round(math.log(s) * eu461.base) else: return 0 def eu461(): target = math.pi p_count = 10000 i_length = 3 i_min = 0 i_max = round(eu461.base * math.log(math.pi + 1)) p = population(p_count, i_length, i_min, i_max) fitness_history = [grade(p, target),] in range(150): p = evolve(p, target) fitness_history.append(grade(p, target)) datum in fitness_history: pass #print (datum) return p[0], get_best_last_element(p[0][0], p[0][1], p[0][2]), sum([f(eu461.base, k) k in p[0]]) + f(eu461.base, get_best_last_element(p[0][0], p[0][1], p[0][2])) eu461.base = 200 if __name__ == "__main__": starttime = time.clock() print (eu461()) elapsedtime = time.clock() - starttime print ("time spent in (", __name__, ") is: ", elapsedtime, " sec")
Comments
Post a Comment