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