Bewaffnet mit einer Simulation aller Möglichkeiten, wie uns unser Zeitplan in die Quere kommen könnte, wusste ich, dass es an der Zeit struggle, einige wirkungsvolle Optimierungstechniken einzusetzen. Hier kamen genetische Algorithmen ins Spiel – eine von der natürlichen Selektion inspirierte Optimierungsmethode, die durch die iterative Entwicklung einer Inhabitants von Kandidatenlösungen die beste Lösung findet.
In diesem Fall struggle jeder „Kandidat“ ein potenzieller Satz von Nanny-Eigenschaften, wie etwa deren Verfügbarkeit und Flexibilität. Der Algorithmus wertet verschiedene Nanny-Eigenschaften aus und verbessert diese Eigenschaften schrittweise, um diejenige zu finden, die den Bedürfnissen unserer Familie entspricht. Das Ergebnis? Eine hochoptimierte Nanny mit Planungspräferenzen, die unsere Lücken in der elterlichen Betreuung mit der Verfügbarkeit der Nanny in Einklang bringen.
Im Mittelpunkt dieses Ansatzes steht das, was ich gerne als „Nanny-Chromosom“ bezeichne. In der Sprache genetischer Algorithmen ist ein Chromosom einfach eine Möglichkeit, mögliche Lösungen darzustellen – in unserem Fall verschiedene Nanny-Eigenschaften. Jedes „Nanny-Chromosom“ hatte eine Reihe von Merkmalen, die seinen Zeitplan definierten: die Anzahl der Tage professional Woche, an denen das Nanny arbeiten konnte, die maximale Anzahl an Stunden, die es professional Tag abdecken konnte, und seine Flexibilität, sich an unterschiedliche Anfangszeiten anzupassen. Diese Merkmale waren die Bausteine jedes möglichen Nanny-Zeitplans, den der Algorithmus in Betracht zog.
Definition des Nanny-Chromosoms
In genetischen Algorithmen stellt ein „Chromosom“ eine mögliche Lösung dar. In diesem Fall handelt es sich um eine Reihe von Merkmalen, die den Zeitplan eines Kindermädchens definieren. So definieren wir die Merkmale eines Kindermädchens:
# Perform to generate nanny traits
def generate_nanny_characteristics():
return {
'versatile': np.random.alternative((True, False)), # Nanny's flexibility
'days_per_week': np.random.alternative((3, 4, 5)), # Days accessible per week
'hours_per_day': np.random.alternative((6, 7, 8, 9, 10, 11, 12)) # Hours accessible per day
}
Der Zeitplan jedes Kindermädchens wird durch seine Flexibilität (ob es die Anfangszeiten anpassen kann), die Anzahl der Tage, an denen es professional Woche verfügbar ist, und die maximale Anzahl an Stunden, die es professional Tag arbeiten kann, definiert. Dies gibt dem Algorithmus die Flexibilität, eine Vielzahl potenzieller Zeitpläne zu bewerten.
Erstellen des Zeitplans für jedes Kindermädchen
Sobald die Merkmale des Kindermädchens definiert sind, müssen wir einen Wochenplan erstellen, der diesen Einschränkungen entspricht:
# Perform to calculate a weekly schedule primarily based on nanny's traits
def calculate_nanny_schedule(traits, num_days=5):
shifts = ()
for _ in vary(num_days):
start_hour = np.random.randint(6, 12) if traits('versatile') else 9 # Versatile nannies have various begin occasions
end_hour = start_hour + traits('hours_per_day') # Calculate finish hour primarily based on hours per day
shifts.append((start_hour, end_hour))
return shifts # Return the generated weekly schedule
Diese Funktion erstellt den Zeitplan eines Kindermädchens basierend auf der definierten Flexibilität und Arbeitszeit. Versatile Kindermädchen können zwischen 6 Uhr morgens und 12 Uhr mittags anfangen, während andere feste Zeitpläne haben, die zu festgelegten Zeiten beginnen und enden. Dadurch kann der Algorithmus eine Reihe möglicher Wochenpläne auswerten.
Auswahl der besten Kandidaten
Nachdem wir eine erste Inhabitants von Nanny-Plänen erstellt haben, verwenden wir eine Fitnessfunktion, um zu ermitteln, welche unseren Kinderbetreuungsbedürfnissen am besten entsprechen. Die am besten geeigneten Pläne werden für die nächste Technology ausgewählt:
# Perform for choice in genetic algorithm
def choice(inhabitants, fitness_scores, num_parents):
# Normalize health scores and choose dad and mom primarily based on chance
min_fitness = np.min(fitness_scores)
if min_fitness < 0:
fitness_scores = fitness_scores - min_fitnessfitness_scores_sum = np.sum(fitness_scores)
possibilities = fitness_scores / fitness_scores_sum if fitness_scores_sum != 0 else np.ones(len(fitness_scores)) / len(fitness_scores)
# Choose dad and mom primarily based on their health scores
selected_parents = np.random.alternative(inhabitants, dimension=num_parents, p=possibilities)
return selected_parents
Im Auswahlschritt bewertet der Algorithmus die Anzahl der Nanny-Zeitpläne mithilfe einer Fitnessfunktion, die misst, wie intestine die Verfügbarkeit der Nanny mit den Bedürfnissen der Familie übereinstimmt. Die am besten passenden Zeitpläne, die die erforderlichen Stunden am besten abdecken, werden als „Eltern“ für die nächste Technology ausgewählt.
Mutation hinzufügen, um die Dinge interessant zu halten
Um nicht bei suboptimalen Lösungen steckenzubleiben, fügen wir durch Mutation ein wenig Zufälligkeit hinzu. Dadurch kann der Algorithmus neue Möglichkeiten erkunden, indem er den Zeitplan des Kindermädchens gelegentlich anpasst:
# Perform to mutate nanny traits
def mutate_characteristics(traits, mutation_rate=0.1):
if np.random.rand() < mutation_rate:
traits('versatile') = not traits('versatile')
if np.random.rand() < mutation_rate:
traits('days_per_week') = np.random.alternative((3, 4, 5))
if np.random.rand() < mutation_rate:
traits('hours_per_day') = np.random.alternative((6, 7, 8, 9, 10, 11, 12))
return traits
Durch die Einführung kleiner Mutationen kann der Algorithmus neue Zeitpläne erkunden, die sonst möglicherweise nicht in Betracht gezogen worden wären. Diese Vielfalt ist wichtig, um lokale Optima zu vermeiden und die Lösung über mehrere Generationen hinweg zu verbessern.
Auf dem Weg zum perfekten Zeitplan
Der letzte Schritt struggle die Evolution. Nach der Selektion und Mutation iteriert der genetische Algorithmus über mehrere Generationen und entwickelt mit jeder Runde bessere Pläne für die Kinderfrau. So implementieren wir den Evolutionsprozess:
# Perform to evolve nanny traits over a number of generations
def evolve_nanny_characteristics(all_childcare_weeks, population_size=1000, num_generations=10):
inhabitants = (generate_nanny_characteristics() for _ in vary(population_size)) # Initialize the inhabitantsfor technology in vary(num_generations):
print(f"n--- Technology {technology + 1} ---")
fitness_scores = ()
hours_worked_collection = ()
for traits in inhabitants:
fitness_score, yearly_hours_worked = fitness_function_yearly(traits, all_childcare_weeks)
fitness_scores.append(fitness_score)
hours_worked_collection.append(yearly_hours_worked)
fitness_scores = np.array(fitness_scores)
# Discover and retailer the very best particular person of this technology
max_fitness_idx = np.argmax(fitness_scores)
best_nanny = inhabitants(max_fitness_idx)
best_nanny('actual_hours_worked') = hours_worked_collection(max_fitness_idx)
# Choose dad and mom and generate a brand new inhabitants
dad and mom = choice(inhabitants, fitness_scores, num_parents=population_size // 2)
new_population = ()
for i in vary(0, len(dad and mom), 2):
parent_1, parent_2 = dad and mom(i), dad and mom(i + 1)
baby = {
'versatile': np.random.alternative((parent_1('versatile'), parent_2('versatile'))),
'days_per_week': np.random.alternative((parent_1('days_per_week'), parent_2('days_per_week'))),
'hours_per_day': np.random.alternative((parent_1('hours_per_day'), parent_2('hours_per_day')))
}
baby = mutate_characteristics(baby)
new_population.append(baby)
inhabitants = new_population # Substitute the inhabitants with the brand new technology
return best_nanny # Return the very best nanny in any case generations
Hier entwickelt sich der Algorithmus über mehrere Generationen hinweg weiter, wählt die besten Nanny-Pläne auf der Grundlage ihrer Fitnesswerte aus und ermöglicht durch Mutation die Entstehung neuer Lösungen. Nach mehreren Generationen nähert sich der Algorithmus dem bestmöglichen Nanny-Plan an und optimiert so die Betreuung unserer Familie.
Abschließende Gedanken
Mit diesem Ansatz haben wir genetische Algorithmen angewendet, um die Zeitpläne der Kindermädchen schrittweise zu verbessern und sicherzustellen, dass der ausgewählte Zeitplan das Chaos der unvorhersehbaren Arbeitsschichten von Elternteil 2 bewältigen und gleichzeitig die Bedürfnisse unserer Familie ausgleichen kann. Genetische Algorithmen waren für diese Aufgabe vielleicht übertrieben, aber sie ermöglichten es uns, verschiedene Möglichkeiten zu erkunden und die Lösung im Laufe der Zeit zu optimieren.
Die folgenden Bilder beschreiben die Entwicklung der Nanny-Fitnesswerte im Laufe der Zeit. Der Algorithmus konnte bereits nach wenigen Generationen schnell das beste Nanny-Chromosom finden.