-
-
Notifications
You must be signed in to change notification settings - Fork 48.7k
kruskal_algorithm problems #1 #12039
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
Changes from all commits
acf4baf
04c83ef
6ef905b
8e4aa44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import numpy as np | ||
|
||
|
||
class GeneticAlgorithm: | ||
def __init__( | ||
self, | ||
func, | ||
bounds, | ||
pop_size=20, | ||
generations=100, | ||
mutation_rate=0.1, | ||
crossover_rate=0.8, | ||
selection_method="tournament", | ||
): | ||
self.func = func | ||
self.bounds = bounds | ||
self.pop_size = pop_size | ||
self.generations = generations | ||
self.mutation_rate = mutation_rate | ||
self.crossover_rate = crossover_rate | ||
self.selection_method = selection_method | ||
|
||
def initialize_population(self): | ||
# Create random population within the bounds | ||
dim = len(self.bounds) | ||
return np.array( | ||
[ | ||
np.random.uniform(self.bounds[d][0], self.bounds[d][1], self.pop_size) | ||
for d in range(dim) | ||
] | ||
).T | ||
|
||
def fitness(self, individual): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: |
||
# Calculate fitness (for minimization, return function value) | ||
return self.func(*individual) | ||
|
||
def selection(self, population, fitness_values): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
if self.selection_method == "tournament": | ||
return self.tournament_selection(population, fitness_values) | ||
elif self.selection_method == "roulette": | ||
return self.roulette_wheel_selection(population, fitness_values) | ||
|
||
def tournament_selection(self, population, fitness_values): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
indices = np.random.choice(len(population), size=2, replace=False) | ||
return ( | ||
population[indices[0]] | ||
if fitness_values[indices[0]] < fitness_values[indices[1]] | ||
else population[indices[1]] | ||
) | ||
|
||
def roulette_wheel_selection(self, population, fitness_values): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
fitness_sum = np.sum(1.0 / (1 + fitness_values)) # inverse for minimization | ||
pick = np.random.uniform(0, fitness_sum) | ||
current = 0 | ||
for individual, fitness in zip(population, fitness_values): | ||
current += 1.0 / (1 + fitness) | ||
if current > pick: | ||
return individual | ||
|
||
def crossover(self, parent1, parent2): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
if np.random.rand() < self.crossover_rate: | ||
# Uniform crossover | ||
mask = np.random.rand(len(parent1)) < 0.5 | ||
child = np.where(mask, parent1, parent2) | ||
return child | ||
return parent1 | ||
|
||
def mutate(self, individual): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: |
||
for i in range(len(individual)): | ||
if np.random.rand() < self.mutation_rate: | ||
individual[i] += np.random.uniform(-1, 1) | ||
individual[i] = np.clip( | ||
individual[i], self.bounds[i][0], self.bounds[i][1] | ||
) | ||
return individual | ||
|
||
def run(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file |
||
population = self.initialize_population() | ||
best_individual = None | ||
best_fitness = float("inf") | ||
|
||
for generation in range(self.generations): | ||
fitness_values = np.array([self.fitness(ind) for ind in population]) | ||
|
||
# Track the best solution | ||
current_best_index = np.argmin(fitness_values) | ||
if fitness_values[current_best_index] < best_fitness: | ||
best_fitness = fitness_values[current_best_index] | ||
best_individual = population[current_best_index] | ||
|
||
# Create new generation | ||
new_population = [] | ||
for _ in range(self.pop_size): | ||
parent1 = self.selection(population, fitness_values) | ||
parent2 = self.selection(population, fitness_values) | ||
child = self.crossover(parent1, parent2) | ||
child = self.mutate(child) | ||
new_population.append(child) | ||
|
||
population = np.array(new_population) | ||
|
||
# Termination Condition: Minimal improvement | ||
if ( | ||
generation > 1 | ||
and abs(best_fitness - self.fitness(best_individual)) < 1e-6 | ||
): | ||
break | ||
|
||
return best_individual, best_fitness | ||
|
||
|
||
# Example Usage: | ||
def my_function(x, y): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide descriptive name for the parameter: Please provide type hint for the parameter: Please provide descriptive name for the parameter: |
||
return x**2 + y**2 | ||
|
||
|
||
bounds = [(-10, 10), (-10, 10)] | ||
ga = GeneticAlgorithm(func=my_function, bounds=bounds, pop_size=30, generations=100) | ||
best_solution, best_value = ga.run() | ||
print(f"Optimized Solution: {best_solution}, Function Value: {best_value}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
class DisjointSet: | ||
def __init__(self, n): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: Please provide type hint for the parameter: Please provide descriptive name for the parameter: |
||
self.parent = list(range(n)) | ||
self.rank = [0] * n | ||
|
||
def find(self, u): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide descriptive name for the parameter: |
||
if self.parent[u] != u: | ||
self.parent[u] = self.find(self.parent[u]) | ||
return self.parent[u] | ||
|
||
def union(self, u, v): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide descriptive name for the parameter: Please provide type hint for the parameter: Please provide descriptive name for the parameter: |
||
root_u = self.find(u) | ||
if root_u != (root_v := self.find(v)): | ||
# Union by rank | ||
if self.rank[root_u] > self.rank[root_v]: | ||
self.parent[root_v] = root_u | ||
elif self.rank[root_u] < self.rank[root_v]: | ||
self.parent[root_u] = root_v | ||
else: | ||
self.parent[root_v] = root_u | ||
self.rank[root_u] += 1 | ||
|
||
|
||
def kruskal_algorithm(vertices, edges): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
# Step 1: Sort edges based on weight | ||
edges.sort(key=lambda x: x[2]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide descriptive name for the parameter: |
||
|
||
# Step 2: Initialize Disjoint Set | ||
ds = DisjointSet(vertices) | ||
|
||
mst = [] | ||
mst_weight = 0 | ||
|
||
# Step 3: Iterate through sorted edges | ||
for u, v, weight in edges: | ||
# Check if adding this edge creates a cycle | ||
if ds.find(u) != ds.find(v): | ||
ds.union(u, v) | ||
mst.append((u, v, weight)) | ||
mst_weight += weight | ||
|
||
return mst, mst_weight | ||
|
||
|
||
# Example usage: | ||
vertices = 4 | ||
edges = [(0, 1, 10), (0, 2, 6), (0, 3, 5), (1, 3, 15), (2, 3, 4)] | ||
|
||
mst, total_weight = kruskal_algorithm(vertices, edges) | ||
print("Edges in the MST:", mst) | ||
print("Total weight of the MST:", total_weight) |
There was a problem hiding this comment.
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:
initialize_population
. 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/ga_optimisation.py
, please provide doctest for the functioninitialize_population