TroglodyteDerivations
commited on
Create tf_ga_algo.txt
Browse files- tf_ga_algo.txt +181 -0
tf_ga_algo.txt
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Updated Implementation includes RandomSearch, Best Individual .npy save
|
2 |
+
|
3 |
+
import numpy as np
|
4 |
+
import tensorflow as tf
|
5 |
+
import tensorflow_probability as tfp
|
6 |
+
import plotly.graph_objs as go
|
7 |
+
from keras_tuner import HyperModel, RandomSearch
|
8 |
+
from tqdm import tqdm
|
9 |
+
|
10 |
+
# Define the target X-shape pattern
|
11 |
+
target_pattern = np.array([
|
12 |
+
[25.76815, -80.1868],
|
13 |
+
[25.7743, -80.1937],
|
14 |
+
[25.762, -80.18],
|
15 |
+
[25.76815, -80.1868],
|
16 |
+
[25.7743, -80.18],
|
17 |
+
[25.762, -80.1937]
|
18 |
+
])
|
19 |
+
|
20 |
+
# Convert target pattern to TensorFlow tensor
|
21 |
+
target_pattern_tf = tf.constant(target_pattern, dtype=tf.float32)
|
22 |
+
|
23 |
+
# Define the GA parameters ranges
|
24 |
+
population_sizes = [30, 50, 70]
|
25 |
+
num_generations = 100000
|
26 |
+
mutation_rates = [0.05, 0.1, 0.15]
|
27 |
+
crossover_rates = [0.7, 0.8, 0.9]
|
28 |
+
elitism_counts = [3, 5, 7]
|
29 |
+
|
30 |
+
# Define the fitness function using TensorFlow
|
31 |
+
def fitness_function(positions):
|
32 |
+
return tf.reduce_sum((positions - target_pattern_tf) ** 2, axis=[1, 2])
|
33 |
+
|
34 |
+
# Selection function (tournament selection) using TensorFlow
|
35 |
+
def selection(population, fitness_values):
|
36 |
+
selected = []
|
37 |
+
for _ in range(len(population)):
|
38 |
+
idx1, idx2 = tf.random.uniform(shape=(2,), minval=0, maxval=len(population), dtype=tf.int32)
|
39 |
+
if fitness_values[idx1] < fitness_values[idx2]:
|
40 |
+
selected.append(population[idx1])
|
41 |
+
else:
|
42 |
+
selected.append(population[idx2])
|
43 |
+
return tf.stack(selected)
|
44 |
+
|
45 |
+
# Crossover function (single-point crossover) using TensorFlow
|
46 |
+
def crossover(parent1, parent2, crossover_rate):
|
47 |
+
if tf.random.uniform(()) < crossover_rate:
|
48 |
+
crossover_point = tf.random.uniform((), minval=1, maxval=len(parent1), dtype=tf.int32)
|
49 |
+
child1 = tf.concat([parent1[:crossover_point], parent2[crossover_point:]], axis=0)
|
50 |
+
child2 = tf.concat([parent2[:crossover_point], parent1[crossover_point:]], axis=0)
|
51 |
+
return child1, child2
|
52 |
+
else:
|
53 |
+
return parent1, parent2
|
54 |
+
|
55 |
+
# Mutation function using TensorFlow Probability
|
56 |
+
def mutate(individual, mutation_rate):
|
57 |
+
mutation_mask = tfp.distributions.Bernoulli(probs=mutation_rate).sample(sample_shape=tf.shape(individual))
|
58 |
+
mutation_noise = tfp.distributions.Normal(loc=0.0, scale=0.1).sample(sample_shape=tf.shape(individual))
|
59 |
+
return individual + tf.cast(mutation_mask, tf.float32) * mutation_noise
|
60 |
+
|
61 |
+
# GA algorithm using TensorFlow
|
62 |
+
def genetic_algorithm(population_size, mutation_rate, crossover_rate, elitism_count, num_generations):
|
63 |
+
population = tf.random.uniform((population_size, len(target_pattern), 2), dtype=tf.float32)
|
64 |
+
|
65 |
+
best_fitness_overall = float('inf')
|
66 |
+
best_individual_overall = None
|
67 |
+
|
68 |
+
for generation in tqdm(range(num_generations), desc="Generations"):
|
69 |
+
fitness_values = fitness_function(population)
|
70 |
+
|
71 |
+
# Track the best fitness and individual overall
|
72 |
+
best_fitness_current_gen = tf.reduce_min(fitness_values).numpy()
|
73 |
+
best_individual_current_gen = population[tf.argmin(fitness_values)].numpy()
|
74 |
+
|
75 |
+
if best_fitness_current_gen < best_fitness_overall:
|
76 |
+
best_fitness_overall = best_fitness_current_gen
|
77 |
+
best_individual_overall = best_individual_current_gen
|
78 |
+
|
79 |
+
# Elitism: Preserve the best individuals
|
80 |
+
elite_indices = tf.argsort(fitness_values)[:elitism_count]
|
81 |
+
elites = tf.gather(population, elite_indices)
|
82 |
+
|
83 |
+
# Select parents
|
84 |
+
parents = selection(population, fitness_values)
|
85 |
+
|
86 |
+
# Create offspring through crossover and mutation
|
87 |
+
offspring = []
|
88 |
+
for i in range(0, len(parents) - 1, 2):
|
89 |
+
child1, child2 = crossover(parents[i], parents[i + 1], crossover_rate)
|
90 |
+
offspring.append(mutate(child1, mutation_rate))
|
91 |
+
offspring.append(mutate(child2, mutation_rate))
|
92 |
+
|
93 |
+
# Ensure offspring size matches population size - elitism count
|
94 |
+
num_offspring_needed = population_size - elitism_count
|
95 |
+
offspring = offspring[:num_offspring_needed]
|
96 |
+
|
97 |
+
# Replace the population with the offspring and elites
|
98 |
+
population = tf.concat([tf.stack(offspring), elites], axis=0)
|
99 |
+
|
100 |
+
return best_fitness_overall, best_individual_overall
|
101 |
+
|
102 |
+
# HyperModel for Keras Tuner
|
103 |
+
class GAHyperModel(HyperModel):
|
104 |
+
def __init__(self, num_generations):
|
105 |
+
self.num_generations = num_generations
|
106 |
+
|
107 |
+
def build(self, hp):
|
108 |
+
population_size = hp.Choice('population_size', values=population_sizes)
|
109 |
+
mutation_rate = hp.Choice('mutation_rate', values=mutation_rates)
|
110 |
+
crossover_rate = hp.Choice('crossover_rate', values=crossover_rates)
|
111 |
+
elitism_count = hp.Choice('elitism_count', values=elitism_counts)
|
112 |
+
|
113 |
+
final_fitness, _ = genetic_algorithm(
|
114 |
+
population_size, mutation_rate, crossover_rate, elitism_count, self.num_generations
|
115 |
+
)
|
116 |
+
|
117 |
+
return final_fitness
|
118 |
+
|
119 |
+
# Hyperparameter tuning using Keras Tuner
|
120 |
+
tuner = RandomSearch(
|
121 |
+
GAHyperModel(num_generations),
|
122 |
+
objective='val_loss',
|
123 |
+
max_trials=50,
|
124 |
+
executions_per_trial=1,
|
125 |
+
directory='ga_tuning',
|
126 |
+
project_name='genetic_algorithm'
|
127 |
+
)
|
128 |
+
|
129 |
+
tuner.search(x=None, y=None, epochs=1, verbose=1)
|
130 |
+
|
131 |
+
# Get the best hyperparameters
|
132 |
+
best_hyperparams = tuner.get_best_hyperparameters(num_trials=1)[0]
|
133 |
+
best_population_size = best_hyperparams.get('population_size')
|
134 |
+
best_mutation_rate = best_hyperparams.get('mutation_rate')
|
135 |
+
best_crossover_rate = best_hyperparams.get('crossover_rate')
|
136 |
+
best_elitism_count = best_hyperparams.get('elitism_count')
|
137 |
+
|
138 |
+
# Run the GA with the best hyperparameters
|
139 |
+
best_fitness, best_individual = genetic_algorithm(
|
140 |
+
best_population_size, best_mutation_rate, best_crossover_rate, best_elitism_count, num_generations
|
141 |
+
)
|
142 |
+
|
143 |
+
# Output the best hyperparameters and the corresponding best individual
|
144 |
+
print(f"Best hyperparameters: population_size={best_population_size}, mutation_rate={best_mutation_rate}, crossover_rate={best_crossover_rate}, elitism_count={best_elitism_count}")
|
145 |
+
print(f"Best fitness: {best_fitness}")
|
146 |
+
|
147 |
+
# Save the best individual
|
148 |
+
np.save('best_individual.npy', best_individual)
|
149 |
+
|
150 |
+
# Validate the flight path trajectory
|
151 |
+
def plot_trajectory(positions):
|
152 |
+
fig = go.Figure()
|
153 |
+
|
154 |
+
# Plot target pattern
|
155 |
+
fig.add_trace(go.Scatter(
|
156 |
+
x=target_pattern[:, 0],
|
157 |
+
y=target_pattern[:, 1],
|
158 |
+
mode='markers+lines',
|
159 |
+
name='Target Pattern',
|
160 |
+
marker=dict(size=10, color='red')
|
161 |
+
))
|
162 |
+
|
163 |
+
# Plot optimized pattern
|
164 |
+
fig.add_trace(go.Scatter(
|
165 |
+
x=positions[:, 0],
|
166 |
+
y=positions[:, 1],
|
167 |
+
mode='markers+lines',
|
168 |
+
name='Optimized Pattern',
|
169 |
+
marker=dict(size=10, color='blue')
|
170 |
+
))
|
171 |
+
|
172 |
+
fig.update_layout(
|
173 |
+
title='UAV Swarm Intelligence: X-Shape Pattern',
|
174 |
+
xaxis_title='X',
|
175 |
+
yaxis_title='Y'
|
176 |
+
)
|
177 |
+
|
178 |
+
fig.show()
|
179 |
+
|
180 |
+
# Plot the final optimized pattern
|
181 |
+
plot_trajectory(best_individual)
|