File size: 8,658 Bytes
8e35b08 |
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 182 183 184 185 186 187 188 189 |
import neat
import numpy as np
import os
import logging
import pickle # En iyi genomu kaydetmek/yüklemek için
import random
import math
import datetime # Log dosyası ismi için
# --- Loglama Ayarları ---
log_filename = f"quanta_log_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
logging.basicConfig(
level=logging.INFO, # Log seviyesi (INFO, DEBUG, WARNING, ERROR, CRITICAL)
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s', # Log formatı
handlers=[
logging.FileHandler(log_filename), # Dosyaya loglama
logging.StreamHandler() # Konsola (ekrana) loglama
]
)
logger = logging.getLogger(__name__)
logger.info("="*50)
logger.info("Quanta Simülatörü Başlatılıyor (Görselleştirme Olmadan)")
logger.info("="*50)
# --- Simülasyon Parametreleri ---
TARGET_PROB_0 = 0.7 # Hedef: %70 olasılıkla 0 üretmek
TARGET_PROB_1 = 1.0 - TARGET_PROB_0 # Hedef: %30 olasılıkla 1 üretmek
NUM_TRIALS_PER_GENOME = 100 # Her genomu değerlendirmek için yapılacak deneme sayısı
MAX_GENERATIONS = 50 # Maksimum evrim nesli (Donanımınıza göre artırılabilir)
FITNESS_THRESHOLD = 0.99 # Evrimin durması için ulaşılması gereken minimum fitness
logger.info(f"Hedef P(0): {TARGET_PROB_0:.2f}, Hedef P(1): {TARGET_PROB_1:.2f}")
logger.info(f"Genom Başına Deneme Sayısı: {NUM_TRIALS_PER_GENOME}")
logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
# --- Basit Kuantum Benzeri Davranış (Taklit) ---
# Bu fonksiyon, kuantum ölçümünün olasılıksal sonucunu basitçe taklit eder.
def simulate_simple_qubit_measurement(prob0=TARGET_PROB_0):
if random.random() < prob0:
return 0
else:
return 1
# --- NEAT Fitness Fonksiyonu ---
# Genomları (sinir ağlarını) değerlendirir.
# Hedef: Ağın çıktısı TARGET_PROB_0'a yakın olasılıkla 0 olmalı.
def eval_genomes(genomes, config):
"""
Popülasyondaki tüm genomların fitness değerlerini hesaplar.
"""
for genome_id, genome in genomes:
genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
try:
net = neat.nn.FeedForwardNetwork.create(genome, config)
except Exception as e:
logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
genome.fitness = -1.0 # Geçersiz genomları cezalandır
continue
count_0 = 0
# Her genomu N kez test ederek istatistiksel olarak değerlendir
for _ in range(NUM_TRIALS_PER_GENOME):
# Ağ Girdisi: Şimdilik sabit bir değer (1.0) kullanıyoruz.
# Gelecekte bu girdi, simülasyonun durumunu veya kontrol parametrelerini yansıtabilir.
net_input = (1.0,)
try:
output = net.activate(net_input)
# Ağın çıktısını (genellikle 0-1 arası) yorumla
# Çıktı < 0.5 ise 0, >= 0.5 ise 1 kabul edelim
if output[0] < 0.5:
count_0 += 1
except Exception as e:
logger.warning(f"Genome {genome_id} ağ aktivasyonunda hata: {e}")
# Hata durumunda bu denemeyi atla veya penaltı ver
pass # Şimdilik sadece atlıyoruz
# Gözlemlenen olasılıkları hesapla
observed_prob_0 = count_0 / NUM_TRIALS_PER_GENOME
# Fitness Hesaplama: Hedef olasılıklara ne kadar yakın?
# Ortalama Karesel Hata (MSE) benzeri bir yaklaşım, ama ters çevrilmiş.
# Hata ne kadar küçükse, fitness o kadar yüksek olmalı.
error = (observed_prob_0 - TARGET_PROB_0) ** 2
# Fitness = 1 / (hata + epsilon) -> Hata sıfıra yaklaştıkça fitness sonsuza yaklaşır.
# Daha stabil bir fitness için: Fitness = 1.0 - hata (0 ile 1 arasında)
# Veya hedef eşiğe göre normalize edilebilir. Şimdilik basit tutalım:
fitness = max(0.0, 1.0 - math.sqrt(error)) # Hatanın karekökünü 1'den çıkaralım (0-1 arası)
genome.fitness = fitness
# logger.debug(f"Genome {genome_id}: Fitness = {fitness:.4f}, Gözlenen P(0) = {observed_prob_0:.2f}")
# --- NEAT Çalıştırma Fonksiyonu ---
def run_neat(config_file):
"""
NEAT evrimini başlatır ve yönetir.
"""
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
try:
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
config_file)
# Fitness eşiğini config dosyasından değil, koddan alalım
config.fitness_threshold = FITNESS_THRESHOLD
logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
except Exception as e:
logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
return None # Hata durumunda None döndür
logger.info("Yeni popülasyon oluşturuluyor...")
p = neat.Population(config)
# İstatistikleri ve loglamayı ayarlama (Sadece konsol çıktısı)
p.add_reporter(neat.StdOutReporter(True))
# Görselleştirme için istatistik toplayıcıya gerek yok.
# stats = neat.StatisticsReporter()
# p.add_reporter(stats)
# Periyodik olarak checkpoint (yedek) alma
checkpoint_prefix = 'neat-checkpoint-'
p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix)) # Her 10 nesilde bir kaydet
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
try:
winner = p.run(eval_genomes, MAX_GENERATIONS)
logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
except Exception as e:
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
# Belki son checkpoint'ten devam etme mantığı eklenebilir.
return None
# En iyi genomu göster/kaydet
logger.info(f'En iyi genom bulundu:')
logger.info(f' {winner}') # Konsola detaylı genom bilgisini yazdırır
# En iyi genomu dosyaya kaydet (pickle ile)
winner_filename = "winner_genome.pkl"
try:
with open(winner_filename, 'wb') as f:
pickle.dump(winner, f)
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
except Exception as e:
logger.error(f"En iyi genom kaydedilemedi: {e}")
# En iyi genomdan ağı oluştur ve son bir kez test et
logger.info(" " + "="*20 + " En İyi Genom Testi " + "="*20)
if winner:
try:
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
test_count_0 = 0
test_trials = 1000 # Daha fazla deneme ile güvenilirliği artır
logger.info(f"En iyi ağ {test_trials} kez test ediliyor...")
for _ in range(test_trials):
net_input = (1.0,)
output = winner_net.activate(net_input)
if output[0] < 0.5:
test_count_0 += 1
observed_prob_0 = test_count_0 / test_trials
logger.info(f"Final Test Sonucu: Gözlenen P(0) = {observed_prob_0:.4f} (Hedef: {TARGET_PROB_0:.3f})")
logger.info(f"Final Test Sonucu: Gözlenen P(1) = {1.0 - observed_prob_0:.4f} (Hedef: {TARGET_PROB_1:.3f})")
final_error = (observed_prob_0 - TARGET_PROB_0) ** 2
logger.info(f"Final Test Hatası (Karesel): {final_error:.6f}")
except Exception as e:
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
else:
logger.warning("Test edilecek bir kazanan genom bulunamadı.")
logger.info("="*50)
logger.info("Quanta Simülatörü Adım 1 (Görselleştirmesiz) tamamlandı.")
logger.info("="*50)
return winner # Kazanan genomu döndür
if __name__ == '__main__':
# Yapılandırma dosyasının yolu (Python betiği ile aynı klasörde olduğunu varsayar)
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt')
if not os.path.exists(config_path):
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
else:
# NEAT'i çalıştır
run_neat(config_path) |