21 KiB
21 KiB
Лабораторная 10¶
Датасет: Knapsack Problem Data (https://www.kaggle.com/datasets/warcoder/knapsack-problem)
In [2]:
import pandas as pd
df = pd.read_csv(".//static//csv//knapsack_5_items.csv")
df
Out[2]:
Хромосома - набор 0 и 1, 1 - предмет выбран, 0 - не выбран. Ген - одно значение в хромосоме.
Функция генерации начальной популяции
In [4]:
import random
def create_individual(length):
individual = []
for _ in range(length):
individual.append(random.randint(0, 1))
return individual
def create_population(length, size):
population = []
for _ in range(size):
population.append(create_individual(length))
return population
create_population(5, 10)
Out[4]:
Фитнес-функция
In [5]:
def evaluate_fitness(individual, weights, prices, capacity):
total_value = 0
total_weight = 0
for selected, weight, price in zip(individual, weights, prices):
if selected:
total_value += price
total_weight += weight
if total_weight > capacity:
return 0
return total_value
evaluate_fitness([0, 1, 1, 1, 0], [7, 12, 19, 13, 20], [10, 11, 18, 15, 5], 50)
Out[5]:
Оператор кроссинговера
In [6]:
def crossover(parent1, parent2):
point = random.randint(1, len(parent1) - 1)
return (parent1[:point] + parent2[point:], parent2[:point] + parent1[point:])
crossover([0, 1, 1, 1, 0], [1, 0, 1, 0, 0])
Out[6]:
Операторы мутации
In [7]:
import random
def mutate_flip_bits(individual, mutation_rate):
for i in range(len(individual)):
chance = random.random()
if chance < mutation_rate:
individual[i] = 1 - individual[i]
def mutate_swap_genes(individual, mutation_rate):
chance = random.random()
if chance < mutation_rate and len(individual) >= 2:
i, j = random.sample(range(len(individual)), 2)
individual[i], individual[j] = individual[j], individual[i]
individual = [0, 1, 1, 1, 0]
print("До мутации:", individual)
mutate_flip_bits(individual, 0.5)
print("После побитовой мутации:", individual)
mutate_swap_genes(individual, 1)
print("После свапа генов:", individual)
Реализация генетического алгоритма и его применение
In [8]:
import ast
import re
population_size = 100
num_generations = 10
mutation_rate = 0.1
mutation_strategy = 'flip'
def select_parents(population, weights, prices, capacity):
fitness_list = [evaluate_fitness(ind, weights, prices, capacity) for ind in population]
total_fitness = sum(fitness_list)
if total_fitness == 0:
return random.choice(population), random.choice(population)
selection_probs = [fitness / total_fitness for fitness in fitness_list]
selected = random.choices(population, weights=selection_probs, k=2)
return selected[0], selected[1]
def genetic_algorithm(weights, prices, capacity,
population_size=100, num_generations=10,
mutation_rate=0.1, mutation_strategy='flip'):
num_elements = len(weights)
population = create_population(num_elements, population_size)
for generation in range(num_generations):
next_population = []
for _ in range(population_size // 2):
parent1, parent2 = select_parents(population, weights, prices, capacity)
child1, child2 = crossover(parent1, parent2)
if mutation_strategy == 'flip':
mutate_flip_bits(child1, mutation_rate)
mutate_flip_bits(child2, mutation_rate)
elif mutation_strategy == 'swap':
mutate_swap_genes(child1, mutation_rate)
mutate_swap_genes(child2, mutation_rate)
next_population.append(child1)
next_population.append(child2)
population = next_population
best_individual = None
best_fitness = -1
for individual in population:
fitness = evaluate_fitness(individual, weights, prices, capacity)
if fitness > best_fitness:
best_fitness = fitness
best_individual = individual
return best_individual, best_fitness
picks = []
best_prices = []
def fix_list_string(s):
s = re.sub(r'\[\s*', '[', s)
s = re.sub(r'\s*\]', ']', s)
s = re.sub(r'\s+', ',', s)
return s
for _, row in df.iterrows():
weights = ast.literal_eval(fix_list_string(row['Weights']))
prices = ast.literal_eval(fix_list_string(row['Prices']))
capacity = row['Capacity']
best_individual, best_value = genetic_algorithm(
weights, prices, capacity,
population_size, num_generations,
mutation_rate, mutation_strategy
)
picks.append(best_individual)
best_prices.append(best_value)
df['algorithmPicks'] = picks
df['algorithmPrice'] = best_prices
pd.concat([df.head(5), df.tail(5)])
Out[8]:
Ответы алгоритма совпадают с теми ответами, которые уже имелись в наборе данных