尝试制作遗传算法
Trying to make a genetic algorithm
我最近一直在研究遗传算法,我决定自己使用 Python。我将在下面分享我所做的工作。
这些是我在我的驱动函数中使用的一些帮助函数:
注意:这些功能我觉得没问题,可以照原样使用。
# Generates Random Population
def generate_random_population(npop, limits=list(zip(np.zeros(5),np.ones(5))), ngenes=5):
def new_ind():
return [random.uniform(limits[i][0], limits[i][1]) for i in range(ngenes)]
return np.array([new_ind() for n in range(npop)])
# Function to evaluate all individuals and give them a score
# fopt1 only has a minimum (unimodal) at x = (0,0, ..., 0) in which fopt1 = 0.
def fopt1(ind):
x0 = [ind[len(ind)-1]]
xlast = [ind[0]]
working_array = np.concatenate((x0,ind,xlast))
res = 0
for j in range(1, len(ind)+1):
res += (2*working_array[j-1] + (working_array[j]**2)*working_array[j+1] - working_array[j+1])**2
return res
# Receives a certain population of individuals and an evaluation function (usually called * fitness function *) and returns an ordered list of tuples
def eval_pop(pop, f):
# Returns a list of tuples in descending order of the goodness of f. Shape of tuples are (individual, score), e.g., ([2.3,0.004,1,8.2,6], 0.361).
list = []
for i in pop:
j = (pop, f(pop))
list.append(j)
return list
# Function to produce a next generation of individuals is to select the pairs that will interbreed to have offspring
def couples_selection(ordered_pop, n_elitism):
if len(ordered_pop) < 10:
print("Error: population's size should be higher than 9")
return
len_a = int(len(ordered_pop)/10)
len_b = len_a * 3
len_c = len_a * 4
a = np.ones(len_a) * 0.5 / len_a
b = np.ones(len_b) * 0.3 / len_b
c = np.ones(len_c) * 0.15 / len_c
d = np.ones(len(ordered_pop) - len_a*8)
d = d * 0.05 / len(d)
prob = np.concatenate((a,b,c,d))
indices = range(len(ordered_pop))
selected_indices = [choice(indices, 2, p=prob) for i in range(len(ordered_pop) - n_elitism)]
couples = [[ordered_pop[i1], ordered_pop[i2]] for [i1,i2] in selected_indices]
return np.array(couples)
def mutate(ind, limits):
# print("Mutating individual ", ind)
factor = 1 + (0.2 * choice([-1,1], 1))
gene_index = choice(range(len(ind)), 1)[0]
mutated_val = ind.item(gene_index) * factor
if mutated_val < limits[gene_index][0]:
mutated_val = limits[gene_index][0]
elif mutated_val > limits[gene_index][1]:
mutated_val = limits[gene_index][1]
ind[gene_index] = mutated_val
return
def crossover(couple):
ancestor1 = couple[0]
ancestor2 = couple[1]
c1, c2 = ancestor1.copy(), ancestor2.copy()
pt = randint(1, len(ancestor1)-2)
# perform crossover
c1 = ancestor1[:pt] + ancestor2[pt:]
c2 = ancestor2[:pt] + ancestor1[pt:]
return [c1, c2]
def get_offspring(couples, mutp, limits):
children = [crossover(couple) for couple in couples]
mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
children_roulette = list(zip(children, mutation_roulette))
for child in children_roulette:
if child[1][0]:
mutate(child[0], limits)
# print("Mutated: ",child[0])
return np.array([child[0] for child in children_roulette])
问题:
当我运行下面的驱动函数调用下面的函数时:
runGA(100, 5, list(zip(np.ones(5)*-2,np.ones(5)*2)), fopt13, 4, 0.4, 25)
def runGA(npop, ngenes, limits, fitness, nelitism, mutp, ngenerations):
pop = generate_random_population(npop, limits, ngenes)
sorted_pop_with_score = eval_pop(pop, fitness)
new_pop = np.array([p[0] for p in sorted_pop_with_score])
for g in range(ngenerations):
# TO DO: Complete your GA!
couples = couples_selection(new_pop, nelitism)
popp = get_offspring(couples,mutp, limits)
eval_pop_result = eval_pop(pop,fitness)
# END OF TO DO
print("Winner after generation", g, ":", eval_pop_result[0])
print("Absolute winner:")
return sorted_pop_with_score[0]
我在交叉函数中遇到这个错误:
ValueError Traceback (most recent call last)
<ipython-input-20-375adbb7b149> in <module>
----> 1 runGA(100, 5, list(zip(np.ones(5)*-2,np.ones(5)*2)), fopt13, 4, 0.4, 25)
<ipython-input-12-6619b9c7d476> in runGA(npop, ngenes, limits, fitness, nelitism, mutp, ngenerations)
8 # TO DO: Complete your GA!
9 couples = couples_selection(new_pop, nelitism)
---> 10 popp = get_offspring(couples,mutp, limits)
11 eval_pop_result = eval_pop(pop,fitness)
12
<ipython-input-16-5e8ace236573> in get_offspring(couples, mutp, limits)
34 def get_offspring(couples, mutp, limits):
35
---> 36 children = [crossover(couple) for couple in couples]
37 mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
38 children_roulette = list(zip(children, mutation_roulette))
<ipython-input-16-5e8ace236573> in <listcomp>(.0)
34 def get_offspring(couples, mutp, limits):
35
---> 36 children = [crossover(couple) for couple in couples]
37 mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
38 children_roulette = list(zip(children, mutation_roulette))
<ipython-input-16-5e8ace236573> in crossover(couple)
25 print(len(ancestor1))
26 print(len(ancestor2))
---> 27 c1 = ancestor1[:pt] + ancestor2[pt:]
28 c2 = ancestor2[:pt] + ancestor1[pt:]
29
ValueError: operands could not be broadcast together with shapes (39,5) (61,5)
注:
我也尝试了 np.concatenate 函数,但它在同一步骤中给出了以下错误:
TypeError: only integer scalar arrays can be converted to a scalar index
任何帮助将不胜感激!
我的评论变成了答案:
所以看起来你需要 运行 couples_selection()
每代的人口,然后 运行 get_offspring()
从 couples_selection()
返回的夫妇,然后 运行 eval_pop()
从 get_offspring()
返回的人口。然后,那一代的获胜者将是 eval_pop()
返回列表中得分最高的个人。看起来 eval_pop()
应该按分数的降序对返回的列表进行排序,但似乎没有;否则,返回列表的 [0]
索引将是得分最高的索引,即获胜者。
此外,如果您返回 sorted_pop_with_score[0]
作为绝对赢家,那么您似乎需要将每一代的赢家添加到某个列表中,然后 运行 eval_pop()
在你完成所有世代之后在该列表上,并将 sorted_pop_with_score
设置为最终 eval_pop()
.
的结果
我最近一直在研究遗传算法,我决定自己使用 Python。我将在下面分享我所做的工作。
这些是我在我的驱动函数中使用的一些帮助函数:
注意:这些功能我觉得没问题,可以照原样使用。
# Generates Random Population
def generate_random_population(npop, limits=list(zip(np.zeros(5),np.ones(5))), ngenes=5):
def new_ind():
return [random.uniform(limits[i][0], limits[i][1]) for i in range(ngenes)]
return np.array([new_ind() for n in range(npop)])
# Function to evaluate all individuals and give them a score
# fopt1 only has a minimum (unimodal) at x = (0,0, ..., 0) in which fopt1 = 0.
def fopt1(ind):
x0 = [ind[len(ind)-1]]
xlast = [ind[0]]
working_array = np.concatenate((x0,ind,xlast))
res = 0
for j in range(1, len(ind)+1):
res += (2*working_array[j-1] + (working_array[j]**2)*working_array[j+1] - working_array[j+1])**2
return res
# Receives a certain population of individuals and an evaluation function (usually called * fitness function *) and returns an ordered list of tuples
def eval_pop(pop, f):
# Returns a list of tuples in descending order of the goodness of f. Shape of tuples are (individual, score), e.g., ([2.3,0.004,1,8.2,6], 0.361).
list = []
for i in pop:
j = (pop, f(pop))
list.append(j)
return list
# Function to produce a next generation of individuals is to select the pairs that will interbreed to have offspring
def couples_selection(ordered_pop, n_elitism):
if len(ordered_pop) < 10:
print("Error: population's size should be higher than 9")
return
len_a = int(len(ordered_pop)/10)
len_b = len_a * 3
len_c = len_a * 4
a = np.ones(len_a) * 0.5 / len_a
b = np.ones(len_b) * 0.3 / len_b
c = np.ones(len_c) * 0.15 / len_c
d = np.ones(len(ordered_pop) - len_a*8)
d = d * 0.05 / len(d)
prob = np.concatenate((a,b,c,d))
indices = range(len(ordered_pop))
selected_indices = [choice(indices, 2, p=prob) for i in range(len(ordered_pop) - n_elitism)]
couples = [[ordered_pop[i1], ordered_pop[i2]] for [i1,i2] in selected_indices]
return np.array(couples)
def mutate(ind, limits):
# print("Mutating individual ", ind)
factor = 1 + (0.2 * choice([-1,1], 1))
gene_index = choice(range(len(ind)), 1)[0]
mutated_val = ind.item(gene_index) * factor
if mutated_val < limits[gene_index][0]:
mutated_val = limits[gene_index][0]
elif mutated_val > limits[gene_index][1]:
mutated_val = limits[gene_index][1]
ind[gene_index] = mutated_val
return
def crossover(couple):
ancestor1 = couple[0]
ancestor2 = couple[1]
c1, c2 = ancestor1.copy(), ancestor2.copy()
pt = randint(1, len(ancestor1)-2)
# perform crossover
c1 = ancestor1[:pt] + ancestor2[pt:]
c2 = ancestor2[:pt] + ancestor1[pt:]
return [c1, c2]
def get_offspring(couples, mutp, limits):
children = [crossover(couple) for couple in couples]
mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
children_roulette = list(zip(children, mutation_roulette))
for child in children_roulette:
if child[1][0]:
mutate(child[0], limits)
# print("Mutated: ",child[0])
return np.array([child[0] for child in children_roulette])
问题:
当我运行下面的驱动函数调用下面的函数时:
runGA(100, 5, list(zip(np.ones(5)*-2,np.ones(5)*2)), fopt13, 4, 0.4, 25)
def runGA(npop, ngenes, limits, fitness, nelitism, mutp, ngenerations):
pop = generate_random_population(npop, limits, ngenes)
sorted_pop_with_score = eval_pop(pop, fitness)
new_pop = np.array([p[0] for p in sorted_pop_with_score])
for g in range(ngenerations):
# TO DO: Complete your GA!
couples = couples_selection(new_pop, nelitism)
popp = get_offspring(couples,mutp, limits)
eval_pop_result = eval_pop(pop,fitness)
# END OF TO DO
print("Winner after generation", g, ":", eval_pop_result[0])
print("Absolute winner:")
return sorted_pop_with_score[0]
我在交叉函数中遇到这个错误:
ValueError Traceback (most recent call last)
<ipython-input-20-375adbb7b149> in <module>
----> 1 runGA(100, 5, list(zip(np.ones(5)*-2,np.ones(5)*2)), fopt13, 4, 0.4, 25)
<ipython-input-12-6619b9c7d476> in runGA(npop, ngenes, limits, fitness, nelitism, mutp, ngenerations)
8 # TO DO: Complete your GA!
9 couples = couples_selection(new_pop, nelitism)
---> 10 popp = get_offspring(couples,mutp, limits)
11 eval_pop_result = eval_pop(pop,fitness)
12
<ipython-input-16-5e8ace236573> in get_offspring(couples, mutp, limits)
34 def get_offspring(couples, mutp, limits):
35
---> 36 children = [crossover(couple) for couple in couples]
37 mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
38 children_roulette = list(zip(children, mutation_roulette))
<ipython-input-16-5e8ace236573> in <listcomp>(.0)
34 def get_offspring(couples, mutp, limits):
35
---> 36 children = [crossover(couple) for couple in couples]
37 mutation_roulette = [choice([True, False], 1, p=[mutp, 1-mutp]) for _ in children]
38 children_roulette = list(zip(children, mutation_roulette))
<ipython-input-16-5e8ace236573> in crossover(couple)
25 print(len(ancestor1))
26 print(len(ancestor2))
---> 27 c1 = ancestor1[:pt] + ancestor2[pt:]
28 c2 = ancestor2[:pt] + ancestor1[pt:]
29
ValueError: operands could not be broadcast together with shapes (39,5) (61,5)
注:
我也尝试了 np.concatenate 函数,但它在同一步骤中给出了以下错误:
TypeError: only integer scalar arrays can be converted to a scalar index
任何帮助将不胜感激!
我的评论变成了答案:
所以看起来你需要 运行 couples_selection()
每代的人口,然后 运行 get_offspring()
从 couples_selection()
返回的夫妇,然后 运行 eval_pop()
从 get_offspring()
返回的人口。然后,那一代的获胜者将是 eval_pop()
返回列表中得分最高的个人。看起来 eval_pop()
应该按分数的降序对返回的列表进行排序,但似乎没有;否则,返回列表的 [0]
索引将是得分最高的索引,即获胜者。
此外,如果您返回 sorted_pop_with_score[0]
作为绝对赢家,那么您似乎需要将每一代的赢家添加到某个列表中,然后 运行 eval_pop()
在你完成所有世代之后在该列表上,并将 sorted_pop_with_score
设置为最终 eval_pop()
.