Skip to content

Function optimization #11372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions genetic_algorithm/function_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
Genetic algorithm for function optimization.

Author: kpuyam
"""

import random
from collections.abc import Callable
from typing import Sequence

Check failure on line 9 in genetic_algorithm/function_optimization.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (UP035)

genetic_algorithm/function_optimization.py:9:1: UP035 Import from `collections.abc` instead: `Sequence`

# Define the parameters for the genetic algorithm
N_POPULATION = 100
N_SELECTED = 20
MUTATION_PROBABILITY = 0.1
NUM_GENERATIONS = 50


def evaluate(func: Callable, params: list[float]) -> float:
"""
Evaluate the fitness of an individual based on the provided function.

Example:
>>> evaluate(lambda x, y: x ** 2 + y ** 2, [3, 4])
25
>>> evaluate(lambda x, y: x + y, [3, 4])
7
"""
return func(*params)


def crossover(parent_1: list[float], parent_2: list[float]) -> list[float]:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file genetic_algorithm/function_optimization.py, please provide doctest for the function crossover

"""Perform crossover between two parents."""
crossover_point = random.randint(1, len(parent_1) - 1)
child = parent_1[:crossover_point] + parent_2[crossover_point:]
return child


def mutate(individual: list[float], mutation_rate: float) -> list[float]:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file genetic_algorithm/function_optimization.py, please provide doctest for the function mutate

"""Mutate an individual with a certain probability."""
mutated_individual = []
for gene in individual:
if random.random() < mutation_rate:
# Add some noise to the gene's value
mutated_gene = gene + random.uniform(-0.1, 0.1)
mutated_individual.append(mutated_gene)
else:
mutated_individual.append(gene)
return mutated_individual


def select(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file genetic_algorithm/function_optimization.py, please provide doctest for the function select

population: list[tuple[list[float], float]], num_selected: int
) -> list[list[float]]:
"""Select individuals based on their fitness scores."""
sorted_population = sorted(population, key=lambda x: x[1])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide descriptive name for the parameter: x

selected_parents = [
individual[0] for individual in sorted_population[:num_selected]
]
return selected_parents


def optimize(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file genetic_algorithm/function_optimization.py, please provide doctest for the function optimize

func: Callable,
param_ranges: Sequence[tuple[float, float]],
) -> tuple[Sequence[float], float]:
"""Optimize the given function using a genetic algorithm."""
# Initialize the population
population = [
[random.uniform(param_range[0], param_range[1]) for param_range in param_ranges]
for _ in range(N_POPULATION)
]

# Main optimization loop
for _generation in range(NUM_GENERATIONS):
# Evaluate the fitness of each individual in the population
population_fitness = [
(individual, evaluate(func, individual)) for individual in population
]

# Select parents for crossover
selected_parents = select(population_fitness, N_SELECTED)

# Generate offspring through crossover and mutation
offspring = []
for _i in range(N_POPULATION):
parent_1 = random.choice(selected_parents)
parent_2 = random.choice(selected_parents)
child = crossover(parent_1, parent_2)
child = mutate(child, MUTATION_PROBABILITY)
offspring.append(child)

# Replace the old population with the offspring
population = offspring

# Find the best individual in the final population
best_individual, best_fitness = max(population_fitness, key=lambda x: x[1])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide descriptive name for the parameter: x


return best_individual, best_fitness


if __name__ == "__main__":
# Set random seed for reproducibility
random.seed(123)

# Example usage:
def quadratic_function(x, y):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide return type hint for the function: quadratic_function. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file genetic_algorithm/function_optimization.py, please provide doctest for the function quadratic_function

Please provide descriptive name for the parameter: x

Please provide type hint for the parameter: x

Please provide descriptive name for the parameter: y

Please provide type hint for the parameter: y

"""Example function to optimize."""
return x**2 + y**2

param_ranges = [(-10, 10), (-10, 10)]
best_params, best_fitness = optimize(quadratic_function, param_ranges)
print("Best parameters:", best_params)
print("Best fitness:", best_fitness)
Loading