β¨ μλ³Έ μ½λ
import random
from typing import List
import numpy as np
import matplotlib.pyplot as plt
def constraints(g, min_=-10, max_=10):
if max_ and g > max_:
g = max_
if min_ and g < min_:
g = min_
return g
def crossover_blend(g1, g2, alpha):
shift = (1 + 2 * alpha) * random.random() - alpha
new_g1 = (1 - shift) * g1 + shift * g2
new_g2 = shift * g1 + (1 - shift) * g2
return constraints(new_g1), constraints(new_g2)
def mutate_gaussian(g, mu, sigma):
mutated_gene = g + random.gauss(mu, sigma)
return constraints(mutated_gene)
def select_tournament(population, size):
new_offspring = []
for _ in range(len(population)):
candidates = [random.choice(population) for _ in range(size)]
new_offspring.append(max(candidates, key=lambda ind: ind.fitness))
return new_offspring
def func(x):
return np.sin(x) - .2 * abs(x)
def get_best(population):
best = population[0]
for ind in population:
if ind.fitness > best.fitness:
best = ind
return best
def plot_population(population, number_of_population):
best = get_best(population)
x = np.linspace(-10, 10)
plt.plot(x, func(x), '--', color='blue')
plt.plot(
[ind.get_gene() for ind in population],
[ind.fitness for ind in population],
'o', color='orange'
)
plt.plot([best.get_gene()], [best.fitness], 's', color='green')
plt.title(f"Generation number {number_of_population}")
plt.show()
plt.close()
class Individual:
def __init__(self, gene_list: List[float]) -> None:
self.gene_list = gene_list
self.fitness = func(self.gene_list[0])
def get_gene(self):
return self.gene_list[0]
def crossover(parent1, parent2):
child1_gene, child2_gene = crossover_blend(parent1.get_gene(), parent2.get_gene(), 1)
return Individual([child1_gene]), Individual([child2_gene])
def mutate(ind):
mutated_gene = mutate_gaussian(ind.get_gene(), 0, 1)
return Individual([mutated_gene])
def select(population):
return select_tournament(population, size=3)
def create_random():
return Individual([random.uniform(-10, 10)])
random.seed(52)
# random.seed(16) # local maximum
POPULATION_SIZE = 10
CROSSOVER_PROBABILITY = .8
MUTATION_PROBABILITY = .1
MAX_GENERATIONS = 10
first_population = [create_random() for _ in range(POPULATION_SIZE)]
plot_population(first_population, 0)
generation_number = 0
population = first_population.copy()
while generation_number < MAX_GENERATIONS:
generation_number += 1
# SELECTION
offspring = select(population)
# CROSSOVER
crossed_offspring = []
for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CROSSOVER_PROBABILITY:
kid1, kid2 = crossover(ind1, ind2)
crossed_offspring.append(kid1)
crossed_offspring.append(kid2)
else:
crossed_offspring.append(ind1)
crossed_offspring.append(ind2)
# MUTATION
mutated_offspring = []
for mutant in crossed_offspring:
if random.random() < MUTATION_PROBABILITY:
new_mutant = mutate(mutant)
mutated_offspring.append(new_mutant)
else:
mutated_offspring.append(mutant)
population = mutated_offspring.copy()
plot_population(population, generation_number)β¨ λ©μΈν¨μ 1νλ
random.seed(52)
# random.seed(16) # local maximum
POPULATION_SIZE = 10
CROSSOVER_PROBABILITY = .8
MUTATION_PROBABILITY = .1
MAX_GENERATIONS = 10- 0οΈβ£ GA Parameters μ μ
first_population = [create_random() for _ in range(POPULATION_SIZE)]-
0οΈβ£ μ΄κΈ° λͺ¨μ§λ¨(κ°μ²΄κ΅°) μμ±
-
1οΈβ£ μ ν©λ νκ°λ μ΄λμμκΉ? : μ°μ pass
plot_population(first_population, 0)
generation_number = 0
population = first_population.copy()while generation_number < MAX_GENERATIONS:
generation_number += 1- π λ°λ³΅λ¬Έ
- μ’
λ£μ‘°κ±΄μ
generation_numberκ°MAX_GENERATIONSμ λλ¬ν λκΉμ§ (generation_number=MAX_GENERATIONSκ° λλ©΄ μ’ λ£)
# SELECTION
offspring = select(population)- 2οΈβ£ μ ν μ°μ°
# CROSSOVER
crossed_offspring = []
for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CROSSOVER_PROBABILITY:
kid1, kid2 = crossover(ind1, ind2)
crossed_offspring.append(kid1)
crossed_offspring.append(kid2)
else:
crossed_offspring.append(ind1)
crossed_offspring.append(ind2)- 3οΈβ£ κ΅μ°¨ μ°μ°
# MUTATION
mutated_offspring = []
for mutant in crossed_offspring:
if random.random() < MUTATION_PROBABILITY:
new_mutant = mutate(mutant)
mutated_offspring.append(new_mutant)
else:
mutated_offspring.append(mutant)- 4οΈβ£ λμ°λ³μ΄ μ°μ°
population = mutated_offspring.copy()- 5οΈβ£ μλ‘μ΄ λͺ¨μ§λ¨ μ λ°μ΄νΈ
plot_population(population, generation_number)β¨ λ©μΈν¨μ 2νλ
random.seed(52)
# random.seed(16) # local maximum
POPULATION_SIZE = 10
CROSSOVER_PROBABILITY = .8
MUTATION_PROBABILITY = .1
MAX_GENERATIONS = 10- 0οΈβ£ GA Parameters μ μ
βΈ
POPULATION_SIZE: κ°μ²΄κ΅° ν¬κΈ°
βΈCROSSOVER_PROBABILITY: κ΅μ°¨ νλ₯
βΈMUTATION_PROBABILITY: λ³μ΄ νλ₯
βΈMAX_GENERATIONS: μ΅λ μΈλ λ²νΈ (μκ³ λ¦¬μ¦ λ°λ³΅ νμμ΄μ μ’ λ£ μ‘°κ±΄)
first_population = [create_random() for _ in range(POPULATION_SIZE)]- 0οΈβ£ μ΄κΈ° λͺ¨μ§λ¨(κ°μ²΄κ΅°) μμ±
POPULATION_SIZEλ§νΌ λ°λ³΅λ¬Έμ μ€ν- κ° λ°λ³΅μμ
create_random()ν¨μλ₯Ό νΈμΆνμ¬ μλ‘μ΄ κ°μ²΄(Individual κ°μ²΄)λ₯Ό μμ± - μμ±λ κ°μ²΄λ€μ 리μ€νΈμ μ μ₯νμ¬
first_populationμΌλ‘ λ°ν
- 1οΈβ£ μ ν©λ νκ°λ μ΄λμμκΉ? : μ°μ pass
plot_population(first_population, 0)- μ΄κΈ° λͺ¨μ§λ¨ μκ°ν
generation_number = 0- νμ¬ μΈλ λ²νΈ(Generation Number)λ₯Ό μ μ₯νλ μν μ ν λ³μ
generation_numberμ μΈ λ° μ΄κΈ°ν
population = first_population.copy()- μ΄κΈ° λͺ¨μ§λ¨μ 볡μ¬νμ¬
populationλ³μμ μ μ₯
π‘ μ
.copy()λ₯Ό μ¬μ©ν κΉ?
- μ μ μκ³ λ¦¬μ¦μ μ¬λ°λ₯Έ μ€νμ 보μ₯νκ³ , μ€νμ μ¬νμ±μ μ μ§νκΈ° μν΄μ
- μ΄κΈ° μΈλμ μ΄ν μΈλ κ°μ λΉκ΅λ₯Ό ν΅ν μκ³ λ¦¬μ¦μ λμ νμΈμ μν΄μ
- λ¨μν
population = first_populationμ νλ©΄, λ λ³μκ° κ°μ 리μ€νΈλ₯Ό μ°Έμ‘°νκΈ° λλ¬Έμpopulationμ΄ λ°λλ©΄first_populationλ μν₯μ λ°μ.copy()λ₯Ό μ¬μ©νλ©΄ μλ‘μ΄ λ¦¬μ€νΈκ° μμ±λμ΄first_populationκ³Ό λ 립μ μΈ κ°μ²΄κ΅°μΌλ‘ μλ
π‘
.copy()vs.deepcopy()
.copy(): μμ λ³΅μ¬ (리μ€νΈλ μλ‘ μμ±λμ§λ§, λ΄λΆ κ°μ²΄λ€μ κΈ°μ‘΄ κ°μ²΄λ₯Ό μ°Έμ‘°)copy.deepcopy(): κΉμ λ³΅μ¬ (리μ€νΈλΏλ§ μλλΌ λ΄λΆ κ°μ²΄λ μλ‘ μμ±λμ΄ μμ ν λ 립μ )- μ½λμμ .copy()(μμ 볡μ¬)λ§ μ¬μ©ν μ΄μ λ κ°μ²΄κ΅° 리μ€νΈλ₯Ό λ 립μ μΌλ‘ μ μ§ν νμλ μμ§λ§, κ°μ²΄(Individual) μ체λ μλ‘ λ§λ€ νμκ° μκΈ° λλ¬Έ
- μ μ μκ³ λ¦¬μ¦μμ λ§€ μΈλλ§λ€ κ°μ²΄κ΅°μ μμ ν μλ‘μ΄ κ°μ²΄λ€λ‘ κ΅μ²΄νλ κ²μ΄ μλλΌ, κΈ°μ‘΄ κ°μ²΄λ€μ λ³ν(μ ν, κ΅μ°¨, λμ°λ³μ΄)νμ¬ μ λ°μ΄νΈνκΈ° λλ¬Έ
while generation_number < MAX_GENERATIONS:- μ μ μκ³ λ¦¬μ¦μ μΈλ μ§νμ μ μ΄νλ π λ°λ³΅λ¬Έ
- generation_number : νμ¬ μ§ν μ€μΈ μΈλ λ²νΈ (0λΆν° μμ)
- MAX_GENERATIONS : μ΅λ μΈλ μ (10)
- whileλ¬Έ : νμ¬ μΈλ λ²νΈκ° MAX_GENERATIONSλ³΄λ€ μμΌλ©΄ λ°λ³΅ μ€ν (= μ μ μκ³ λ¦¬μ¦μ μ΅λ MAX_GENERATIONS μΈλκΉμ§ μ€ν)
generation_number += 1- λ°λ³΅λ¬Έμ΄ μ€νλ λλ§λ€ μΈλ λ²νΈλ₯Ό 1 μ¦κ°μν΄
# SELECTION
offspring = select(population)- 2οΈβ£ μ ν μ°μ° μν
select(population)ν¨μ : νμ¬ κ°μ²΄κ΅°(population)μμ λ€μ μΈλλ‘ μ λ¬ν κ°μ²΄λ€μ μ νoffspring: μ νλ κ°μ²΄λ€μ 리μ€νΈ β κ΅μ°¨(Crossover)μ λμ°λ³μ΄(Mutation)μ μ¬μ©λ¨
π‘
offspringλ³μμ λνμ¬
- μ κ°μΈμ μΈ μκ°μ΄μ§λ§ μ ν μ°μ°μ λΆλͺ¨(Parent)λ₯Ό μ ννλ κ³Όμ μΈλ°, offspring(μμ) μ΄λΌλ μ΄λ¦μ μ¬μ©νκ³ μκΈ° λλ¬Έμ μ΄μνλ€κ³ λκΌμ΅λλ€.
- μ½λ μμ±μλ λ€μ μΈλλ‘ μ λ¬λ κ°μ²΄ λΌλ μλ―Έλ‘ μ¬μ©ν κ²μΌλ‘ 보μ΄λ, μλ°ν λ§νλ©΄ select()μμ λ°νλ κ°μ²΄λ€μ μμ§ λΆλͺ¨(Parent)μ΄λ©°, μμ(offspring)μ΄ μλμ μ μνμ μΌ ν©λλ€.
# CROSSOVER
crossed_offspring = []
for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CROSSOVER_PROBABILITY:
kid1, kid2 = crossover(ind1, ind2)
crossed_offspring.append(kid1)
crossed_offspring.append(kid2)
else:
crossed_offspring.append(ind1)
crossed_offspring.append(ind2)-
3οΈβ£ κ΅μ°¨ μ°μ° μν
crossed_offspring = []: μλ‘μ΄ κ°μ²΄κ΅°(κ΅μ°¨ ν μμλ€)μ μ μ₯ν λΉ λ¦¬μ€νΈ μμ±for ind1, ind2 in zip(offspring[::2], offspring[1::2]):offspring[::2]: μ§μ λ²μ§Έ μΈλ±μ€μ κ°μ²΄ β 첫 λ²μ§Έ λΆλͺ¨(ind1) κ·Έλ£Ήoffspring[1::2]: νμ λ²μ§Έ μΈλ±μ€μ κ°μ²΄ β λ λ²μ§Έ λΆλͺ¨(ind2) κ·Έλ£Ήzip()μ μ¬μ©νμ¬ λΆλͺ¨ μ μμ±for루νλ λͺ¨λ λΆλͺ¨ μμ λν΄ λ°λ³΅ μ€ν
if random.random() < CROSSOVER_PROBABILITY:random.random()β 0~1 μ¬μ΄μ λμ μμ±CROSSOVER_PROBABILITYβ κ΅μ°¨ νλ₯ (μ : 0.8 β 80% νλ₯ λ‘ κ΅λ°° μν)- λμ κ°μ΄
CROSSOVER_PROBABILITYλ³΄λ€ μμΌλ©΄ κ΅μ°¨ μν, ν¬λ©΄ κ΅μ°¨ μμ΄ λΆλͺ¨λ₯Ό κ·Έλλ‘ μ μ§
kid1, kid2 = crossover(ind1, ind2)- crossover() ν¨μλ₯Ό μ¬μ©ν΄ λΆλͺ¨ κ°μ²΄ λ κ°(
ind1,ind2)λ₯Ό κ΅μ°¨νμ¬ μλ‘μ΄ λ κ°μ μμ(kid1,kid2) μμ±
- crossover() ν¨μλ₯Ό μ¬μ©ν΄ λΆλͺ¨ κ°μ²΄ λ κ°(
crossed_offspring.append(kid1) crossed_offspring.append(kid2)- μμ±λ λ κ°μ μμ(
kid1,kid2)μ 리μ€νΈμ μΆκ° - μλ‘μ΄ κ°μ²΄κ΅°(
crossed_offspring)μ μ μ₯
- μμ±λ λ κ°μ μμ(
else: crossed_offspring.append(ind1) crossed_offspring.append(ind2)-
κ΅μ°¨κ° λ°μνμ§ μμ κ²½μ° (80% νλ₯ μ λκΈ΄ κ²½μ°)
-
λΆλͺ¨ κ°μ²΄(
ind1,ind2)λ₯Ό κ·Έλλ‘ λ€μ μΈλμ μ λ¬
-
π‘ 리μ€νΈ μ¬λΌμ΄μ± :
[start:stop:step]π‘ zip()
- μ¬λ¬ κ°μ iterable(리μ€νΈ, νν λ±)μ λμμ λ¬Άμ΄μ£Όλ ν¨μ
- μ¬λ¬ 리μ€νΈμμ κ°κ° κ°μ μΈλ±μ€μ μλ μμλ€μ ννλ‘ λ¬Άμ΄μ λ°ν
list1 = [1, 2, 3] list2 = ['a', 'b', 'c'] zipped = zip(list1, list2) print(list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c')]
# MUTATION
mutated_offspring = []
for mutant in crossed_offspring:
if random.random() < MUTATION_PROBABILITY:
new_mutant = mutate(mutant)
mutated_offspring.append(new_mutant)
else:
mutated_offspring.append(mutant)- 4οΈβ£ λμ°λ³μ΄ μ°μ° μν
mutated_offspring = []: λμ°λ³μ΄κ° μ μ©λ κ°μ²΄λ€μ μ μ₯ν λΉ λ¦¬μ€νΈ μμ±for mutant in crossed_offspring:: κ΅μ°¨(Crossover) μ΄ν μμ±λ κ°μ²΄κ΅°(crossed_offspring)μ λͺ¨λ κ°μ²΄λ₯Ό νλμ© μνif random.random() < MUTATION_PROBABILITY:- νλ₯ (
MUTATION_PROBABILITY)μ λ°λΌ λμ°λ³μ΄ μν μ¬λΆ κ²°μ random.random()β 0~1 μ¬μ΄μ λμλ₯Ό μμ±MUTATION_PROBABILITYλ³΄λ€ μμΌλ©΄ λμ°λ³μ΄ λ°μ
- νλ₯ (
new_mutant = mutate(mutant)mutate()ν¨μλ₯Ό νΈμΆνμ¬ μ νλ κ°μ²΄(mutant)μ λμ°λ³μ΄λ₯Ό μ μ©- λμ°λ³μ΄κ° λ°μν κ²½μ°, μλ‘μ΄ λ³μ΄λ κ°μ²΄(
new_mutant) μμ±
mutated_offspring.append(new_mutant)- λμ°λ³μ΄κ° μ μ©λ κ°μ²΄λ₯Ό μλ‘μ΄ λ¦¬μ€νΈ(
mutated_offspring)μ μΆκ°
- λμ°λ³μ΄κ° μ μ©λ κ°μ²΄λ₯Ό μλ‘μ΄ λ¦¬μ€νΈ(
else: mutated_offspring.append(mutant)- λμ°λ³μ΄κ° λ°μνμ§ μμ κ²½μ°, κΈ°μ‘΄ κ°μ²΄(
mutant)λ₯Ό κ·Έλλ‘ μ μ§νμ¬ λ¦¬μ€νΈμ μΆκ°
- λμ°λ³μ΄κ° λ°μνμ§ μμ κ²½μ°, κΈ°μ‘΄ κ°μ²΄(
population = mutated_offspring.copy()- 5οΈβ£ μλ‘μ΄ λͺ¨μ§λ¨ ꡬμ±
- κ΅μ°¨(Crossover)μ λμ°λ³μ΄(Mutation)μ κ±°μΉ κ°μ²΄κ΅°(mutated_offspring)μ μλ‘μ΄ κ°μ²΄κ΅°(population)μΌλ‘ μ λ°μ΄νΈ
plot_population(population, generation_number)- μλ‘ μμ±λ λͺ¨μ§λ¨ μκ°ν
- π λ°λ³΅λ¬ΈμΌλ‘ λμκ° μ’ λ£ μ‘°κ±΄μ λ§μ‘±ν λ κΉμ§ μ κ³Όμ λ°λ³΅
β¨ ν¨μ μ΄ν΄λ³΄κΈ°
# Import part
import random # λμ μμ± λΌμ΄λΈλ¬λ¦¬
from typing import List # 리μ€νΈ νμ
ννΈλ₯Ό μ 곡νλ λΌμ΄λΈλ¬λ¦¬
import numpy as np # νλ ¬ λ° μν μ°μ°μ μ§μνλ λΌμ΄λΈλ¬λ¦¬
import matplotlib.pyplot as plt # λ°μ΄ν° μκ°νλ₯Ό μν λΌμ΄λΈλ¬λ¦¬π‘ typing λͺ¨λ
- νμ νν μ μν΄ μ¬μ©λλ λͺ¨λ
- νμ νν μ΄λ νμ΄μ¬ μ½λλ₯Ό μμ±ν λ νμ μ λν λ©ν μ 보λ₯Ό μ 곡νλ κ²
- Pythonμ λμ νμ μΈμ΄λΌμ λ³μμ νμ μ λͺ μνμ§ μμλ λμ§λ§, νμ νν μ νλ©΄ μ¬λ¬ κ°μ§ μ€μ©μ μΈ μ₯μ μ΄ μμ
βΈ μ½λ κ°λ μ± ν₯μ
βΈ μ€λ₯ λ°©μ§ λ° μ μ λΆμ κ°λ₯
βΈ ν νμ & μ½λ μ μ§λ³΄μμ λμ
βΈ κ°λ° λꡬ μ§μ (IDE μλμμ±, μ½λ λΆμ λ±)- Python 3.9λΆν°λ νμ μ΄λ Έν μ΄μ μ μ¬μ©μ±μ΄ λν κ°μ λμ΄ μ΄μ typing λͺ¨λμμ List, Dict, Tuple, Setλ₯Ό λΆλ¬μ€μ§ μκ³ , list, dict, tuple, set λ΄μ₯ νμ μ ν΅ν΄ λ°λ‘ μμμ νμ κΉμ§ λͺ μν΄μ€ μ μμ΅λλ€.
def func(x): # μ
λ ₯ κ° `x`λ₯Ό κΈ°λ°μΌλ‘ ν¨μλ₯Ό κ³μ°νμ¬ λ°ν
return np.sin(x) - .2 * abs(x) # μ ν©λ ν¨μ(Fitness Function)
class Individual:
def __init__(self, gene_list: List[float]) -> None: # μ΄κΈ°ν λ©μλ / λ§€κ°λ³μλ gene_list / νμ
νν
μ ν΅ν μΈμ½λ© λ°©λ² μ μ
self.gene_list = gene_list # μ λ¬λ°μ μ μ μ 보λ₯Ό self.gene_listμ μ μ₯
self.fitness = func(self.gene_list[0]) # 첫 λ²μ§Έ μ μ μλ₯Ό κΈ°λ°μΌλ‘ μ ν©λ(fitness)λ₯Ό νκ°
def get_gene(self):
return self.gene_list[0] # κ°μ²΄μ 첫 λ²μ§Έ μ μ μλ₯Ό λ°ννλ λ©μλIndividualν΄λμ€μ μν : μ μ μκ³ λ¦¬μ¦μμ νλμ κ°μ²΄(Individual)λ₯Ό νν / μ μ μ 보(μ μ μ)μ μ ν©λ(Fitness)λ₯Ό μ μ₯νκ³ κ΄λ¦¬
π‘νμ΄μ¬ Class
- ν΄λμ€ Class : κ°μ²΄λ₯Ό λ§λ€κΈ° μν μ€κ³λ
- μΈμ€ν΄μ€ Instance : ν΄λμ€λ₯Ό κΈ°λ°μΌλ‘ μμ±λ μ€μ κ°μ²΄ / κ°μ ν΄λμ€λ₯Ό μ¬μ©νμ¬ λ§λ μ¬λ¬ μΈμ€ν΄μ€λ€μ ν΄λμ€λ λμΌνμ§λ§, κ° μΈμ€ν΄μ€λ λ©λͺ¨λ¦¬μμ λ 립μ μΌλ‘ μ‘΄μ¬ν¨
- λ©μλ Method : ν΄λμ€λ₯Ό λ§λ€λ©΄μ κ·Έ μμ λ£μ ν¨μ / μ¬μ©νλ €λ©΄ κ°μ²΄.λ©μλ()μ κ°μ νμμΌλ‘ νΈμΆ
__init__λ©μλ : μ΄κΈ°ν(Initialize)λ©μλλ‘, μ΄λ€ ν΄λμ€μ κ°μ²΄κ° λ§λ€μ΄μ§ λ μλμΌλ‘ νΈμΆλμ΄ κ·Έ κ°μ²΄κ° κ°κ² λ μ¬λ¬ μ±μ§μ μ ν΄μ€ (μμ±μ)selfν€μλ : ν΄λμ€ λ΄λΆμμ μκΈ° μμ (μΈμ€ν΄μ€)μ κ°λ¦¬ν΄ / selfλ₯Ό μ¬μ©νλ©΄__init__λ©μλλΏλ§ μλλΌ κ°μ ν΄λμ€ λ΄ λ€λ₯Έ λ©μλμμλ μμ±μ λ³κ²½νκ±°λ μ κ·Όν μ μμ
def get_best(population): # μ£Όμ΄μ§ κ°μ²΄ μ§λ¨(population)μμ κ°μ₯ λμ fitness κ°μ κ°μ§ κ°μ²΄λ₯Ό μ°Ύμ λ°ννλ ν¨μ (μκ°νμ ν)
best = population[0] # 첫 λ²μ§Έ κ°μ²΄λ₯Ό μ΄κΈ° μ΅μ κ°μ²΄λ‘ μ€μ
for ind in population: # λͺ¨λ κ°μ²΄μ λν΄ λ°λ³΅
if ind.fitness > best.fitness: # νμ¬ bestλ³΄λ€ fitness κ°μ΄ λ ν¬λ€λ©΄
best = ind # bestλ₯Ό νμ¬ κ°μ²΄λ‘ μ
λ°μ΄νΈ
return best # μ΅μ’
μ μΌλ‘ κ°μ₯ fitnessκ° λμ κ°μ²΄ λ°νdef plot_population(population, number_of_population): # μκ°ν ν¨μ
best = get_best(population) # get_best ν¨μλ₯Ό μ¬μ©ν΄ μ£Όμ΄μ§ κ°μ²΄κ΅°μμ κ°μ₯ μ°μν κ°μ²΄λ₯Ό μ ν
x = np.linspace(-10, 10) # -10μμ 10κΉμ§μ κ°μ μΌμ κ°κ²©μΌλ‘ λλ λ°°μ΄μ μμ±
plt.plot(x, func(x), '--', color='blue') # λ°°μ΄μ μ ν©λ ν¨μμ λμ
ν΄ κ·Έλν 그리기 / νλμ μ
plt.plot(
[ind.get_gene() for ind in population], # XμΆ : κ°μ²΄μ μ μ μ κ°(`get_gene` λ©μλ νμ©)
[ind.fitness for ind in population], # YμΆ : κ°μ²΄μ μ ν©λ
'o', color='orange' # μ£Όν©μ μμΌλ‘ νμ
)
plt.plot([best.get_gene()], [best.fitness], 's', color='green') # μ΅μ κ°μ²΄(best)μ μμΉ μκ°ν
plt.title(f"Generation number {number_of_population}") # κ·Έλν μ λͺ© μ€μ
plt.show() # κ·Έλνλ₯Ό νλ©΄μ μΆλ ₯
plt.close() # κ·Έλνλ₯Ό λ«μ λ©λͺ¨λ¦¬λ₯Ό ν보- λ§€κ°λ³μ
βΈ
population: νμ¬ μΈλμ κ°μ²΄κ΅°(리μ€νΈ νν)
βΈnumber_of_population: νμ¬ μΈλμ λ²νΈ (μΈλ μ)
def create_random(): # μ΄κΈ° λͺ¨μ§λ¨ μμ±μ νμ©λλ ν¨μ
return Individual([random.uniform(-10, 10)]) -
create_randomν¨μμ μν : μλ‘μ΄ κ°μ²΄(Individual)λ₯Ό 무μμλ‘ μμ±νμ¬ λ°ν -
λμ
random.uniform(-10, 10): -10μμ 10 μ¬μ΄μ 무μμ μ€μλ₯Ό μμ±Individual([random_value]): μμμ μμ±λ λλ€ κ°μΌλ‘ Individual κ°μ²΄λ₯Ό μμ± / λ§λ€μ΄μ§ κ°μ²΄λ μ μ μλ₯Ό 리μ€νΈ ννλ‘ κ°μ§- μμ±λ κ°μ²΄λ₯Ό λ°ν
def select_tournament(population, size): # ν λλ¨ΌνΈ λ°©μμΌλ‘ μ ν μ°μ°μ μ§ννλ ν¨μ
new_offspring = [] # μλ‘μ΄ κ°μ²΄λ€μ μ μ₯ν 리μ€νΈ μ΄κΈ°ν
for _ in range(len(population)): # κΈ°μ‘΄ λͺ¨μ§λ¨μ ν¬κΈ°λ₯Ό λ§μ‘±ν λ κΉμ§ μλ‘μ΄ κ°μ²΄ μμ±
candidates = [random.choice(population) for _ in range(size)]
new_offspring.append(max(candidates, key=lambda ind: ind.fitness))
return new_offspring # μ νλ κ°μ²΄λ€λ‘ ꡬμ±λ μλ‘μ΄ κ°μ²΄κ΅°μ λ°ν-
select_tournamentν¨μμ μν : ν λλ¨ΌνΈ μ ν λ°©μ(Tournament Selection)μ μ¬μ©νμ¬ μλ‘μ΄ κ°μ²΄κ΅°μ μ ν -
λ§€κ°λ³μ
βΈ
population: νμ¬ κ°μ²΄κ΅°(리μ€νΈ νν)
βΈsize: ν λλ¨ΌνΈμ μ°Έκ°ν ν보 κ°μ²΄μ μ -
μΆκ° μ£Όμ
βΈ
candidates = [random.choice(population) for _ in range(size)]
Β Β Β νμ¬ κ°μ²΄κ΅° populationμμ size κ°λ§νΌ 무μμλ‘ ν보λ₯Ό μ ννμ¬ candidates 리μ€νΈλ₯Ό μμ±βΈ
new_offspring.append(max(candidates, key=lambda ind: ind.fitness))
Β Β Β candidates 리μ€νΈμμ κ°μ₯ λμ μ ν©λλ₯Ό κ°μ§ κ°μ²΄λ₯Ό μ ννμ¬ new_offspringμ μΆκ°.π‘ max(iterable, key=function)
- μ£Όμ΄μ§ 리μ€νΈ(iterable)μμ κ°μ₯ ν° κ°μ μ°Ύλ ν¨μ
- key=functionμ μ¬μ©νλ©΄, 리μ€νΈμ κ° μμμμ νΉμ μμ±μ΄λ κΈ°μ€μ κΈ°λ°μΌλ‘ λΉκ΅ν μ μμ
π‘ Lambda
- μ΄λ¦ μμ΄ μ¬μ©ν μ μλ μ΅λͺ ν¨μ(Anonymous Function)
- μΌλ°μ μΈ def ν€μλλ₯Ό μ¬μ©ν ν¨μμ λ¬λ¦¬, ν μ€λ‘ κ°κ²°νκ² νν
lambda λ§€κ°λ³μ: λ°νκ°ννλ‘ μ μΈ- return ν€μλλ μ¬μ©νμ§ μμΌλ©°, ν μ€λ§ μμ±ν μ μμ
- λ©μΈ ν¨μμμ μ¬μ©
def select(population):
return select_tournament(population, size=3)selectν¨μλ₯Ό μ€ννλ©΄ βselect_tournamentβμ μ€ν κ²°κ³Όλ₯Ό λ°ν- ν보λ 3κ°
def constraints(g, min_ = -10, max_ = 10): # μ μ½ν¨μ / constraints = μ μ½
if max_ and g > max_: # λ§μ½ max_κ° Noneμ΄ μλκ³ gκ° max_λ³΄λ€ ν¬λ€λ©΄, gλ₯Ό max_λ‘ μ€μ (μν μ ν)
g = max_
if min_ and g < min_: # λ§μ½ min_μ΄ Noneμ΄ μλκ³ gκ° min_λ³΄λ€ μλ€λ©΄, gλ₯Ό min_μΌλ‘ μ€μ (νν μ ν)
g = min_
return g # μ νμ΄ μ μ©λ gλ₯Ό λ°ν-
constraintsν¨μμ μν : μ£Όμ΄μ§ κ° gλ₯Ό νΉμ λ²μ λ΄λ‘ μ ν -
λ§€κ°λ³μ
βΈ
g: μ νμ μ μ©ν κ°
βΈmin_: g κ°μ νν (μ΅μκ°), κΈ°λ³Έκ° -10
βΈmax_: g κ°μ μν (μ΅λκ°), κΈ°λ³Έκ° 10
def crossover_blend(g1, g2, alpha):
shift = (1 + 2 * alpha) * random.random() - alpha # [-alpha, 1 + alpha] λ²μμμ λλ€ν νΌν© λΉμ¨ μμ±
new_g1 = (1 - shift) * g1 + shiμ©
```python
def mutate(ind):
mutated_gene = mutate_gaussian(ind.get_gene(), 0, 1) # νκ· μ΄ 0μ΄κ³ νμ€ νΈμ°¨κ° 1μΈ μ κ· λΆν¬μμ μνμ μΆμΆνμ¬ indμ μ μ μ κ°μ λν¨
return Individual([mutated_gene]) # λ³μ΄κ° μ μ©λ μλ‘μ΄ μ μ μλ‘ μλ‘μ΄ Individual κ°μ²΄λ₯Ό μμ±νμ¬ λ°νmutateν¨μλ₯Ό μ€ννλ©΄mutate_gaussianν¨μλ₯Ό μ¬μ©νμ¬ λμ°λ³μ΄λ₯Ό μ μ©νκ³ λ³μ΄κ° μ μ©λ μλ‘μ΄ μ μ μλ₯Ό λ°ν
β¨ λ©μΈν¨μ 3νλ
- 2νλ , ν¨μ μ΄ν΄νκΈ°λ₯Ό μ½κ³ λ©μΈ μ½λλ₯Ό λ€μ μ½μ΄λ³΄κΈ°
- μμ (λ―Έμ)