The goal of these changes is to provide users with more granular control over the NEAT algorithm's parameters, improve the usability of these controls, and ensure that the settings chosen by the user are effectively applied to the evolution process. This involves:
- Adding new UI sliders for specific NEAT parameters.
- Grouping related settings for clarity.
- Implementing logic to lock settings during an "Auto-Evolve" run.
- Ensuring the NEAT system re-initializes with user-defined parameters before each run.
- Enhancing the statistics display.
- A
QGroupBoxtitled "Evolution Settings" will be created in the left control pane. - It will contain all NEAT parameter sliders, their descriptions, and the Auto-Evolve button.
- An instructional
QLabelwill be added within this group: "Configure parameters before starting. Settings are locked during auto-evolution."
The following sliders will be implemented or updated within the "Evolution Settings" group. Each will have a QLabel for its name and another QLabel for its description.
-
Population Size (
pop_size):- Slider Range: 10-100, Step: 10.
- Description: "Number of neural networks (genomes) in each generation."
-
Fitness Threshold (
fitness_threshold):- Slider Range: 80-100 (representing 0.80 to 1.00).
- Description: "Target fitness score; evolution stops if a genome reaches this."
-
Evaluation Trials per Network:
- Slider Range: 1-100, Step: 1.
- Description: "Number of random letters each network is tested on per generation to calculate its fitness."
-
Weight Mutate Rate (
weight_mutate_rate):- Slider Range: 0-100 (representing 0.0 to 1.0).
- Description: "Probability that existing connection weights are perturbed."
-
Weight Replace Rate (
weight_replace_rate):- Slider Range: 0-100 (representing 0.0 to 1.0).
- Description: "Probability that a connection weight is replaced with a new random value."
-
Connection Add Probability (
conn_add_prob):- Slider Range: 0-100 (representing 0.0 to 1.0).
- Description: "Probability of adding a new connection between neurons."
-
Node Add Probability (
node_add_prob):- Slider Range: 0-100 (representing 0.0 to 1.0).
- Description: "Probability of adding a new neuron (node) to the network."
- The current "Auto-Evolve"
QCheckBoxwill be replaced with aQPushButton. - Button Text: Will toggle between "Start Auto-Evolve" and "Stop Auto-Evolve".
- This button will be located within the "Evolution Settings" group.
- When "Start Auto-Evolve" is clicked:
- All sliders within the "Evolution Settings" group will be disabled (
setEnabled(False)). - The button text changes to "Stop Auto-Evolve".
- The auto-evolution process begins.
- All sliders within the "Evolution Settings" group will be disabled (
- When "Stop Auto-Evolve" is clicked (or evolution finishes):
- All sliders in the group will be re-enabled (
setEnabled(True)). - The button text changes back to "Start Auto-Evolve".
- All sliders in the group will be re-enabled (
- In
src/app.py:- When "Start Auto-Evolve" is clicked (before
self.run_evolution()is called for the new sequence):- Read current values from all parameter sliders (Population Size, Fitness Threshold, Evaluation Trials, all mutation sliders).
- Convert UI slider values (e.g., 0-100) to the actual scales required by
neat-python(e.g., 0.0-1.0 for probabilities, integers for counts). - Pass these processed values to a method in
NEATLogic(e.g.,reconfigure_neat(params)or pass tosetup_neatif it's called anew).
- When "Start Auto-Evolve" is clicked (before
- In
src/neat_logic.py:NEATLogicwill store thenum_evaluation_trialsvalue (e.g., asself.num_evaluation_trials).- The
setup_neat()method (or a new reconfiguration method) will:- Load the base configuration from
src/neat_config. - Override specific values in the loaded
self.configobject using the parameters passed fromapp.pybeforeself.p = neat.Population(self.config)is called. - Example overrides:
self.config.pop_size = params['population_size'] self.config.fitness_threshold = params['fitness_threshold'] self.config.genome_config.weight_mutate_rate = params['weight_mutate_rate'] # ... and so on for other mutation params.
- The
self.num_evaluation_trialswill be stored locally inNEATLogicfor use by theevaluatemethod. - A new
neat.Population(self.p) will be created with these updated settings, effectively restarting evolution from Generation 0 with the new parameters.
- Load the base configuration from
- The
evaluate(self, genomes, config)method inNEATLogicwill be updated to implement the "Evaluation Trials per Network":# In NEATLogic class # self.num_evaluation_trials will be set from app.py def evaluate(self, genomes, config): for genome_id, genome in genomes: # Outer loop: iterates through each network successful_trials = 0.0 for _ in range(self.num_evaluation_trials): # Inner loop: ALL trials for CURRENT genome current_challenge_letter = self.generate_letter() letter_pattern, actual_letter = self.generate_letter_pattern(current_challenge_letter) if letter_pattern is None: continue input_data = letter_pattern.flatten().astype(float) if len(input_data) != config.genome_config.num_inputs: continue try: net = neat.nn.FeedForwardNetwork.create(genome, config) output_activations = net.activate(input_data) predicted_idx = output_activations.index(max(output_activations)) predicted_letter = ['A', 'B', 'C'][predicted_idx % 3] if predicted_letter == actual_letter: successful_trials += 1.0 except Exception: pass # Error during activation # Calculate average fitness genome.fitness = successful_trials / self.num_evaluation_trials if self.num_evaluation_trials > 0 else 0.0
- In
create_stats_panel():- Add a
QLabelfor "Average Population Fitness:" and a corresponding valueQLabel(e.g.,self.avg_fitness_label).
- Add a
- In
update_stats_display():- Fetch the mean fitness of the latest generation from
self.neat_logic.stats_reporter.get_fitness_mean()[-1](if available). - Update
self.avg_fitness_labelwith this value, formatted to two decimal places. - The "Training Samples" label will be repurposed or renamed. Suggestion: Rename to "Total Evaluations (Last Gen)" and display
population_size * evaluation_trials.
- Fetch the mean fitness of the latest generation from
- User adjusts sliders in the "Evolution Settings" group.
- User clicks "Start Auto-Evolve".
app.pyreads slider values and passes them toNEATLogic.NEATLogicre-initializes its NEATconfigand creates a newPopulation(Generation 0).- UI sliders are locked.
- Auto-evolution begins:
- For each generation:
- For each genome in the population:
- The genome is evaluated on
N(Evaluation Trials) random letters. - Its fitness is the average success rate over these trials.
- The genome is evaluated on
- Statistics (best fitness, average fitness) are updated.
- A new generation is produced.
- For each genome in the population:
- For each generation:
- Process continues until "Stop Auto-Evolve" is clicked or fitness threshold is met. Sliders unlock.