Implementação dos Algoritmos
Este exemplo utiliza um algoritmo genético para resolver o problema de agendamento de aluguel de quadras de pickleball, onde o objetivo é alocar quadras e horários para diferentes grupos de jogadores, garantindo que:
- Nenhuma quadra seja usada por mais de um grupo ao mesmo tempo.
- Cada grupo respeite as restrições de disponibilidade das quadras e dos jogadores.
Definição do Problema
No problema, temos as seguintes variáveis:
- Quadras: Quadra 1, Quadra 2, Quadra 3
- Horários: 9:00-10:00, 10:00-11:00, 11:00-12:00
- Grupos: Grupo A, Grupo B, Grupo C, Grupo D
Os grupos têm restrições sobre quais quadras e horários estão disponíveis. A solução busca alocar cada grupo em uma quadra e horário disponíveis, respeitando as restrições.
Exemplo de Execução
Após executar o algoritmo genético, a solução final é apresentada, onde cada grupo está alocado em uma quadra e horário válidos:
Grupo A: Quadra 1 às 9:00-10:00 Grupo B: Quadra 2 às 10:00-11:00 Grupo C: Quadra 3 às 11:00-12:00 Grupo D: Quadra 1 às 10:00-11:00
O algoritmo genético continua iterando até que uma solução válida seja encontrada ou o número máximo de gerações seja alcançado.
import random
# Parâmetros do Algoritmo Genético
POPULATION_SIZE = 500
MUTATION_RATE = 0.1
GENERATIONS = 1000
# Problema de Agendamento de Quadras
AVAILABILITY = {
"Quadra 1": ["9:00-10:00", "10:00-11:00", "11:00-12:00"],
"Quadra 2": ["9:00-10:00", "10:00-11:00", "11:00-12:00"],
"Quadra 3": ["9:00-10:00", "10:00-11:00", "11:00-12:00"]
}
GROUPS = ["Grupo A", "Grupo B", "Grupo C", "Grupo D"]
# Função para criar uma solução inicial aleatória
def create_individual():
individual = []
for group in GROUPS:
quadra = random.choice(list(AVAILABILITY.keys()))
horario = random.choice(AVAILABILITY[quadra])
individual.append((group, quadra, horario))
return individual
# Função de avaliação (fitness)
def fitness(individual):
score = 0
# Penaliza se duas reuniões ocorrerem no mesmo horário em uma mesma quadra
for i, (group1, quadra1, horario1) in enumerate(individual):
for j, (group2, quadra2, horario2) in enumerate(individual):
if i != j and quadra1 == quadra2 and horario1 == horario2:
score -= 1
return score
# Função de cruzamento
def crossover(parent1, parent2):
point = random.randint(1, len(parent1) - 1)
child = parent1[:point] + parent2[point:]
return child
# Função de mutação
def mutate(individual):
if random.random() < MUTATION_RATE:
idx = random.randint(0, len(individual) - 1)
group, quadra, horario = individual[idx]
new_quadra = random.choice(list(AVAILABILITY.keys()))
new_horario = random.choice(AVAILABILITY[new_quadra])
individual[idx] = (group, new_quadra, new_horario)
# Algoritmo Genético Principal
def genetic_algorithm():
population = [create_individual() for _ in range(POPULATION_SIZE)]
for generation in range(GENERATIONS):
population = sorted(population, key=fitness, reverse=True)
if fitness(population[0]) == 0: # Nenhum conflito
print(f"Solução encontrada na geração {generation}")
return population[0]
next_generation = population[:POPULATION_SIZE // 2]
for i in range(POPULATION_SIZE // 2):
parent1, parent2 = random.sample(next_generation, 2)
child = crossover(parent1, parent2)
mutate(child)
next_generation.append(child)
population = next_generation
print("Nenhuma solução encontrada")
return None
# Resolver o problema de agendamento
solution = genetic_algorithm()
if solution:
for group, quadra, horario in solution:
print(f"{group}: {quadra} às {horario}")
Explicação do Algoritmo
O algoritmo genético é utilizado para encontrar uma solução ótima para o problema de agendamento. Ele funciona da seguinte forma:
1. Criação Inicial: A função create_individual() cria uma solução inicial aleatória, onde cada grupo é atribuído a uma quadra e horário disponíveis.
2. Avaliação (Fitness): A função fitness() calcula a qualidade de uma solução, penalizando soluções que causam conflitos, ou seja, quando mais de um grupo tenta usar a mesma quadra no mesmo horário.
3. Cruzamento: O cruzamento ocorre na função crossover(), onde duas soluções "pais" são combinadas para gerar uma nova solução "filha".
4. Mutação: A função mutate() faz alterações aleatórias em uma solução, trocando a quadra ou o horário de uma reunião, a fim de explorar novas soluções.
5. Iterações: O algoritmo genético é executado na função genetic_algorithm(), que gera uma população inicial de soluções e aplica o processo de cruzamento e mutação por várias gerações até que uma solução válida seja encontrada.