Moortiii icon

Genetic Algorithm

Moortiii | PRO | 01/17/21 04:48:51 PM UTC | 0 ⭐ | 1101 👁️ | Never ⏰ | []
Python |

3.05 KB

|

None

|

0 👍

/

0 👎

import random
 
def calculate_fitness(bits, items, threshold):
    total_cost = 0
    total_weight = 0
 
    #print("Items in fitness check:", items)
 
    for i, bit in enumerate(bits):
        if bit == 1:
            item = items[i]
            total_cost += item[1][0]
            total_weight += item[1][1]
    
    if total_weight <= threshold:
        return total_cost
    
    return 0
 
def perform_selection(items):
    backpack = []
 
    for _ in range(len(items)):
        if random.random() > 0.5:
            backpack.append(1)
        else:
            backpack.append(0)
 
    return backpack
 
def crossover_split(parent_a, parent_b):
    """ Single point crossover split """
    split_index = 3
 
    parent_1, splice_1 = parent_a[:split_index], parent_a[split_index:]
    parent_2, splice_2 = parent_b[:split_index], parent_b[split_index:]
    parent_1.extend(splice_2)
    parent_2.extend(splice_1)
 
    return parent_1, parent_2
 
def mutate(bits):
    """ Mutate by flipping bits pseudo-randomly """
    output = ''
    threshold = 0.9
 
    for bit in bits:
        if random.random() > threshold:
            if bit == 1:
                output += '0'
            else:
                output += '1'
        else:
            output += str(bit)
 
    #print("I:", ''.join([str(bit) for bit in bits]))
    #print("O:", output)
    return [int(bit) for bit in output]
 
def generate_population(items, n):
    selections = []
 
    for _ in range(n):
        selections.append(perform_selection(items))
 
    return selections
 
generations = 5
population_size = 10
 
items = {
    0: ("laptop", (500, 2200)),
    1: ("headphones", (150, 160)),
    2: ("coffee mug", (60, 350)),
    3: ("notepad", (40, 333)),
    4: ("water bottle", (30, 192))
}
 
# The initial population is entirely random
population = generate_population(items, 10)
 
# Apply the algorithm
for generation in range(generations):
    print(f"Generation {generation + 1}.")
 
    # calculate the fitness score for each of the members of the population
    fitness_scores = []
 
    for entry in population:
        fitness_scores.append((entry, calculate_fitness(entry, items, 3000))) 
 
    best = sorted(fitness_scores, key=lambda xy: xy[1])[::-1]
    
    elitism_count = 2
    elite = best[0:elitism_count]
    next_population = []
 
    for entry in elite:
        bits, score = entry
        next_population.append(bits)
 
    while len(next_population) < population_size:
        index_a = random.randint(0, len(items))
        index_b = random.randint(0, len(items))
 
        while index_b == index_a:
            index_b = random.randint(0, len(items))
 
        results = crossover_split(
            population[index_a], population[index_b])
 
        next_population.extend(results)
 
    print("Next population:", next_population)
    mutated_population = []
 
    for entry in next_population:
        mutation = mutate(entry)
        mutated_population.append(mutation)
 
    population = mutated_population
 
print("Finished.")

Comments