|
|
| import pygame
|
| import sys
|
| import os
|
| import neat
|
| import numpy as np
|
| import pickle
|
| import random
|
| import time
|
| import settings as s
|
| from environment import Environment
|
| from agent_coev import AgentCoEv
|
|
|
|
|
| def eval_simulation(genome_red, config_red, genome_blue, config_blue):
|
| """
|
| Bir kırmızı ve bir mavi genom arasındaki tek bir maçı simüle eder.
|
| Her iki koloninin topladığı yem miktarını döndürür.
|
| """
|
|
|
| net_red = neat.nn.FeedForwardNetwork.create(genome_red, config_red)
|
| net_blue = neat.nn.FeedForwardNetwork.create(genome_blue, config_blue)
|
|
|
|
|
| environment = Environment(s.SCREEN_WIDTH, s.SCREEN_HEIGHT)
|
|
|
|
|
| agents_red = [AgentCoEv(genome_red, config_red, environment, s.COLONY_ID_RED) for _ in range(s.NUM_AGENTS_PER_COLONY)]
|
| agents_blue = [AgentCoEv(genome_blue, config_blue, environment, s.COLONY_ID_BLUE) for _ in range(s.NUM_AGENTS_PER_COLONY)]
|
| all_agents = agents_red + agents_blue
|
|
|
|
|
| for step in range(s.SIMULATION_STEPS_PER_GEN):
|
| environment.update()
|
|
|
| random.shuffle(all_agents)
|
| for agent in all_agents:
|
|
|
| agent.update(all_agents)
|
|
|
|
|
| food_red = sum(agent.food_collected_count for agent in agents_red)
|
| food_blue = sum(agent.food_collected_count for agent in agents_blue)
|
|
|
| return food_red, food_blue
|
|
|
|
|
| def run_coev(config_file):
|
| """
|
| İki popülasyon için NEAT ko-evrim sürecini yönetir.
|
| """
|
|
|
| config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| config_file)
|
|
|
|
|
| checkpoint_dir_red = 'swarm_mind_v4/checkpoints_red'
|
| checkpoint_dir_blue = 'swarm_mind_v4/checkpoints_blue'
|
| os.makedirs(checkpoint_dir_red, exist_ok=True)
|
| os.makedirs(checkpoint_dir_blue, exist_ok=True)
|
|
|
| try:
|
| p_red = neat.Checkpointer.restore_checkpoint(os.path.join(checkpoint_dir_red, 'neat-checkpoint-'))
|
| print("Kırmızı popülasyon checkpoint'ten yüklendi.")
|
| except Exception:
|
| print("Kırmızı popülasyon checkpoint bulunamadı, yeni oluşturuluyor.")
|
| p_red = neat.Population(config)
|
|
|
| try:
|
| p_blue = neat.Checkpointer.restore_checkpoint(os.path.join(checkpoint_dir_blue, 'neat-checkpoint-'))
|
| print("Mavi popülasyon checkpoint'ten yüklendi.")
|
| except Exception:
|
| print("Mavi popülasyon checkpoint bulunamadı, yeni oluşturuluyor.")
|
| p_blue = neat.Population(config)
|
|
|
|
|
|
|
| p_red.add_reporter(neat.StdOutReporter(True))
|
| stats_red = neat.StatisticsReporter()
|
| p_red.add_reporter(stats_red)
|
| p_red.add_reporter(neat.Checkpointer(generation_interval=5, filename_prefix=os.path.join(checkpoint_dir_red, 'neat-checkpoint-')))
|
|
|
|
|
|
|
| stats_blue = neat.StatisticsReporter()
|
| p_blue.add_reporter(stats_blue)
|
| p_blue.add_reporter(neat.Checkpointer(generation_interval=5, filename_prefix=os.path.join(checkpoint_dir_blue, 'neat-checkpoint-')))
|
|
|
|
|
| for generation in range(s.NUM_GENERATIONS):
|
| start_time = time.time()
|
| print(f"\n****** Ko-Evrim Nesil {generation} Başladı ******")
|
|
|
|
|
| genomes_red_dict = p_red.population
|
| genomes_blue_dict = p_blue.population
|
|
|
| genomes_red_list = list(genomes_red_dict.items())
|
| genomes_blue_list = list(genomes_blue_dict.items())
|
|
|
|
|
|
|
| genome_scores_red = {gid: [] for gid, _ in genomes_red_list}
|
| genome_scores_blue = {gid: [] for gid, _ in genomes_blue_list}
|
|
|
|
|
| eval_count = 0
|
|
|
| for gid_r, genome_r in genomes_red_list:
|
|
|
| num_opponents = min(s.NUM_OPPONENTS_PER_EVAL, len(genomes_blue_list))
|
| opponents = random.sample(genomes_blue_list, num_opponents)
|
|
|
| for gid_b, genome_b in opponents:
|
|
|
| food_r, food_b = eval_simulation(genome_r, config, genome_b, config)
|
| eval_count += 1
|
|
|
|
|
| genome_scores_red[gid_r].append((food_r, food_b))
|
| genome_scores_blue[gid_b].append((food_b, food_r))
|
|
|
| print(f"Nesil {generation}: {eval_count} eşleşme değerlendirildi.")
|
|
|
|
|
|
|
| for gid, genome in genomes_red_dict.items():
|
| scores = genome_scores_red[gid]
|
| if not scores:
|
| genome.fitness = 0.0
|
| continue
|
| avg_my_food = np.mean([s[0] for s in scores])
|
| avg_opp_food = np.mean([s[1] for s in scores])
|
|
|
| if s.FITNESS_METHOD == 'competitive':
|
| genome.fitness = avg_my_food - avg_opp_food
|
| else:
|
| genome.fitness = avg_my_food
|
|
|
|
|
| for gid, genome in genomes_blue_dict.items():
|
| scores = genome_scores_blue[gid]
|
| if not scores:
|
| genome.fitness = 0.0
|
| continue
|
| avg_my_food = np.mean([s[0] for s in scores])
|
| avg_opp_food = np.mean([s[1] for s in scores])
|
|
|
| if s.FITNESS_METHOD == 'competitive':
|
| genome.fitness = avg_my_food - avg_opp_food
|
| else:
|
| genome.fitness = avg_my_food
|
|
|
|
|
|
|
| best_genome_red = max(genomes_red_dict.values(), key=lambda g: g.fitness)
|
| best_genome_blue = max(genomes_blue_dict.values(), key=lambda g: g.fitness)
|
|
|
| p_red.reporters.post_evaluate(config, genomes_red_dict, p_red.species, best_genome_red)
|
| p_blue.reporters.post_evaluate(config, genomes_blue_dict, p_blue.species, best_genome_blue)
|
|
|
| p_red.reporters.end_generation(config, genomes_red_dict, p_red.species)
|
| p_blue.reporters.end_generation(config, genomes_blue_dict, p_blue.species)
|
|
|
|
|
| p_red.population = p_red.reproduction.reproduce(config, p_red.species, config.pop_size, generation)
|
| p_blue.population = p_blue.reproduction.reproduce(config, p_blue.species, config.pop_size, generation)
|
|
|
|
|
| if not p_red.species or not p_blue.species:
|
| p_red.species = config.species_set_type(config, p_red.reporters)
|
| p_blue.species = config.species_set_type(config, p_blue.reporters)
|
| p_red.species.speciate(config, p_red.population, generation)
|
| p_blue.species.speciate(config, p_blue.population, generation)
|
|
|
|
|
| p_red.reporters.start_generation(generation + 1)
|
| p_blue.reporters.start_generation(generation + 1)
|
|
|
| end_time = time.time()
|
| print(f"Nesil {generation} tamamlandı. Süre: {end_time - start_time:.2f} saniye")
|
|
|
|
|
|
|
| print('\nKo-Evrim tamamlandı.')
|
|
|
|
|
|
|
|
|
| try:
|
| winner_red = max(p_red.population.values(), key=lambda g: g.fitness if g.fitness is not None else -float('inf'))
|
| winner_blue = max(p_blue.population.values(), key=lambda g: g.fitness if g.fitness is not None else -float('inf'))
|
|
|
| print('\nEn İyi Kırmızı Genom:')
|
| print(winner_red)
|
| print('\nEn İyi Mavi Genom:')
|
| print(winner_blue)
|
|
|
|
|
| os.makedirs('swarm_mind_v4/best_genomes', exist_ok=True)
|
| with open('swarm_mind_v4/best_genomes/winner_red.pkl', 'wb') as f:
|
| pickle.dump(winner_red, f)
|
| with open('swarm_mind_v4/best_genomes/winner_blue.pkl', 'wb') as f:
|
| pickle.dump(winner_blue, f)
|
| print("En iyi genomlar 'best_genomes' klasörüne kaydedildi.")
|
|
|
|
|
| if s.VISUALIZE_BEST_GENOMES:
|
| visualize_simulation(winner_red, config, winner_blue, config)
|
|
|
| except Exception as e:
|
| print(f"\nEvrim sonrası hata (En iyi genom bulunamadı veya kaydedilemedi): {e}")
|
|
|
|
|
|
|
| def visualize_simulation(genome_red, config_red, genome_blue, config_blue):
|
| """
|
| İki rakip genomun davranışını Pygame ile görselleştirir.
|
| """
|
| print("\nEn iyi Kırmızı ve Mavi genomların maçı görselleştiriliyor...")
|
| pygame.init()
|
| screen = pygame.display.set_mode((s.SCREEN_WIDTH, s.SCREEN_HEIGHT))
|
| pygame.display.set_caption(f"{s.WINDOW_TITLE} - Best Genomes Match")
|
| clock = pygame.time.Clock()
|
|
|
| environment = Environment(s.SCREEN_WIDTH, s.SCREEN_HEIGHT)
|
| net_red = neat.nn.FeedForwardNetwork.create(genome_red, config_red)
|
| net_blue = neat.nn.FeedForwardNetwork.create(genome_blue, config_blue)
|
| agents_red = [AgentCoEv(genome_red, config_red, environment, s.COLONY_ID_RED) for _ in range(s.NUM_AGENTS_PER_COLONY)]
|
| agents_blue = [AgentCoEv(genome_blue, config_blue, environment, s.COLONY_ID_BLUE) for _ in range(s.NUM_AGENTS_PER_COLONY)]
|
| all_agents = agents_red + agents_blue
|
|
|
| running = True
|
| sim_step = 0
|
| max_vis_steps = s.SIMULATION_STEPS_PER_GEN * 2
|
| while running and sim_step < max_vis_steps:
|
| for event in pygame.event.get():
|
| if event.type == pygame.QUIT: running = False; break
|
| if event.type == pygame.KEYDOWN:
|
| if event.key == pygame.K_p: s.DEBUG_DRAW_PHEROMONES = not s.DEBUG_DRAW_PHEROMONES
|
| if event.key == pygame.K_ESCAPE: running = False; break
|
| if not running: break
|
|
|
| environment.update()
|
| random.shuffle(all_agents)
|
| for agent in all_agents:
|
| agent.update(all_agents)
|
|
|
| screen.fill(s.COLOR_BACKGROUND)
|
| environment.draw(screen)
|
| for agent in all_agents:
|
| agent.draw(screen)
|
|
|
|
|
| font = pygame.font.SysFont(None, 24)
|
| food_r = sum(a.food_collected_count for a in agents_red)
|
| food_b = sum(a.food_collected_count for a in agents_blue)
|
| info_text = font.render(f"Adım: {sim_step}/{max_vis_steps} | Kırmızı Yem: {food_r} | Mavi Yem: {food_b}", True, (255, 255, 255))
|
| screen.blit(info_text, (10, 10))
|
|
|
| pygame.display.flip()
|
| clock.tick(s.VISUALIZATION_FPS)
|
| sim_step += 1
|
|
|
| pygame.quit()
|
| print("Görselleştirme tamamlandı.")
|
|
|
|
|
|
|
| if __name__ == '__main__':
|
| local_dir = os.path.dirname(__file__)
|
| config_path = os.path.join(local_dir, 'neat_config_v4.txt')
|
|
|
| if not os.path.exists(config_path):
|
| print(f"HATA: NEAT config dosyası bulunamadı: {config_path}")
|
| sys.exit(1)
|
|
|
| print("SwarmMind V4.0 - Co-evolutionary Competition başlatılıyor...")
|
| print(f"NEAT Yapılandırması: {config_path}")
|
| print(f"Jenerasyon Sayısı: {s.NUM_GENERATIONS}")
|
| print(f"Popülasyon Büyüklüğü/Koloni: (config dosyasında belirtilir)")
|
| print(f"Simülasyon Adım Sayısı/Eşleşme: {s.SIMULATION_STEPS_PER_GEN}")
|
| print(f"Ajan Sayısı/Koloni: {s.NUM_AGENTS_PER_COLONY}")
|
| print(f"Rakip Sayısı/Değerlendirme: {s.NUM_OPPONENTS_PER_EVAL}")
|
| print(f"Fitness Yöntemi: {s.FITNESS_METHOD}")
|
|
|
|
|
| os.makedirs('swarm_mind_v4/checkpoints_red', exist_ok=True)
|
| os.makedirs('swarm_mind_v4/checkpoints_blue', exist_ok=True)
|
| os.makedirs('swarm_mind_v4/best_genomes', exist_ok=True)
|
|
|
| run_coev(config_path) |