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)