NextGenC commited on
Commit
8e35b08
·
verified ·
1 Parent(s): 1fcdd4f

Upload 11 files

Browse files
config-classification-v6.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config-classification-v6.txt - Quanta Classifier V6 için Yapılandırma
2
+ # Veri Seti Üzerinde Sınıflandırma
3
+
4
+ [NEAT]
5
+ fitness_criterion = max
6
+ fitness_threshold = 0.98 # Hedef doğruluk oranı (%98) - Veriye göre ayarlanabilir
7
+ pop_size = 300 # Daha zor görev ve iyi CPU için artırıldı
8
+ reset_on_extinction = False
9
+
10
+ [DefaultGenome]
11
+ # node activation options
12
+ activation_default = sigmoid # Çıkış katmanı dahil sigmoid uygun
13
+ activation_mutate_rate = 0.1 # Aktivasyon mutasyonunu hafifçe açabiliriz (isteğe bağlı)
14
+ activation_options = sigmoid relu tanh clamped # Daha fazla seçenek ekleyebiliriz
15
+
16
+ # node aggregation options
17
+ aggregation_default = sum
18
+ aggregation_mutate_rate = 0.0
19
+ aggregation_options = sum
20
+
21
+ # node bias options (önceki gibi)
22
+ bias_init_mean = 0.0
23
+ bias_init_stdev = 1.0
24
+ bias_max_value = 30.0
25
+ bias_min_value = -30.0
26
+ bias_mutate_power = 0.5
27
+ bias_mutate_rate = 0.7
28
+ bias_replace_rate = 0.1
29
+
30
+ # genome compatibility options (önceki gibi)
31
+ compatibility_disjoint_coefficient = 1.0
32
+ compatibility_weight_coefficient = 0.5
33
+
34
+ # connection add/remove rates (önceki gibi)
35
+ conn_add_prob = 0.5
36
+ conn_delete_prob = 0.5
37
+
38
+ # connection enable options (önceki gibi)
39
+ enabled_default = True
40
+ enabled_mutate_rate = 0.01
41
+
42
+ feed_forward = True
43
+ initial_connection = full_nodirect
44
+
45
+ # node add/remove rates (önceki gibi)
46
+ node_add_prob = 0.2
47
+ node_delete_prob = 0.2
48
+
49
+ # network parameters
50
+ num_hidden = 0
51
+ num_inputs = 2 # Örnek veri setimiz için 2 özellik (feature)
52
+ num_outputs = 1 # Binary sınıflandırma için 1 sigmoid çıktı
53
+
54
+ # species options (önceki gibi)
55
+ species_fitness_func = max
56
+ max_stagnation = 25 # Stagnasyonu biraz artırabiliriz
57
+ species_set_size = 40 # Tür sayısını artırabiliriz
58
+
59
+ # weight options (önceki gibi)
60
+ weight_init_mean = 0.0
61
+ weight_init_stdev = 1.0
62
+ weight_max_value = 30
63
+ weight_min_value = -30
64
+ weight_mutate_power = 0.5
65
+ weight_mutate_rate = 0.8
66
+ weight_replace_rate = 0.1
67
+
68
+ [DefaultSpeciesSet]
69
+ compatibility_threshold = 3.0
70
+
71
+ [DefaultStagnation]
72
+ species_fitness_func = max
73
+ max_stagnation = 20 # Türler için stagnasyon (globalden farklı)
74
+ species_elitism = 2
config-feedforward-v3.txt ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config-feedforward-v3.txt
2
+
3
+ [NEAT]
4
+ fitness_criterion = max
5
+ fitness_threshold = 0.98 # V3 için eşik, ayarlanabilir
6
+ pop_size = 150
7
+ reset_on_extinction = False
8
+
9
+ [DefaultGenome]
10
+ # node activation options
11
+ activation_default = sigmoid
12
+ activation_mutate_rate = 0.0
13
+ activation_options = sigmoid
14
+
15
+ # node aggregation options
16
+ aggregation_default = sum
17
+ aggregation_mutate_rate = 0.0
18
+ aggregation_options = sum
19
+
20
+ # node bias options
21
+ bias_init_mean = 0.0
22
+ bias_init_stdev = 1.0
23
+ bias_max_value = 30.0
24
+ bias_min_value = -30.0
25
+ bias_mutate_power = 0.5
26
+ bias_mutate_rate = 0.7
27
+ bias_replace_rate = 0.1
28
+
29
+ # genome compatibility options
30
+ compatibility_disjoint_coefficient = 1.0
31
+ compatibility_weight_coefficient = 0.5
32
+
33
+ # connection add/remove rates
34
+ conn_add_prob = 0.5
35
+ conn_delete_prob = 0.5
36
+
37
+ # connection enable options
38
+ enabled_default = True
39
+ enabled_mutate_rate = 0.01
40
+
41
+ feed_forward = True
42
+ initial_connection = full_nodirect # Başlangıçta girdilerle çıktılar arası bağlantı
43
+
44
+ # node add/remove rates
45
+ node_add_prob = 0.2
46
+ node_delete_prob = 0.2
47
+
48
+ # network parameters
49
+ num_hidden = 0
50
+ num_inputs = 2 # <-- YENİ DEĞER: Artık 2 girdimiz var
51
+ num_outputs = 1
52
+
53
+ # species options
54
+ species_fitness_func = max
55
+ max_stagnation = 20
56
+ species_set_size = 30
57
+
58
+ # weight options
59
+ weight_init_mean = 0.0
60
+ weight_init_stdev = 1.0
61
+ weight_max_value = 30
62
+ weight_min_value = -30
63
+ weight_mutate_power = 0.5
64
+ weight_mutate_rate = 0.8
65
+ weight_replace_rate = 0.1
66
+
67
+ [DefaultSpeciesSet]
68
+ compatibility_threshold = 3.0
69
+
70
+ [DefaultStagnation]
71
+ species_fitness_func = max
72
+ max_stagnation = 15
73
+ species_elitism = 2
config-feedforward-v4.txt ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config-feedforward-v4.txt
2
+
3
+ [NEAT]
4
+ fitness_criterion = max
5
+ fitness_threshold = 0.96 # V4 için eşik, zorluk arttı, ayarlanabilir
6
+ pop_size = 200 # Daha zor problem için popülasyonu artırabiliriz
7
+ reset_on_extinction = False
8
+
9
+ [DefaultGenome]
10
+ # ... (V3'teki bias, activation, aggregation, compatibility, connection, enabled ayarları aynı kalabilir) ...
11
+ bias_init_mean = 0.0
12
+ bias_init_stdev = 1.0
13
+ bias_max_value = 30.0
14
+ bias_min_value = -30.0
15
+ bias_mutate_power = 0.5
16
+ bias_mutate_rate = 0.7
17
+ bias_replace_rate = 0.1
18
+ compatibility_disjoint_coefficient = 1.0
19
+ compatibility_weight_coefficient = 0.5
20
+ conn_add_prob = 0.5
21
+ conn_delete_prob = 0.5
22
+ enabled_default = True
23
+ enabled_mutate_rate = 0.01
24
+ feed_forward = True
25
+ initial_connection = full_nodirect
26
+
27
+ # node add/remove rates
28
+ node_add_prob = 0.3 # Biraz daha fazla yapısal çeşitlilik için artırılabilir
29
+ node_delete_prob = 0.2
30
+
31
+ # network parameters
32
+ num_hidden = 0
33
+ num_inputs = 2 # V3'teki gibi
34
+ num_outputs = 2 # <-- YENİ DEĞER: Artık 2 çıktımız var
35
+
36
+ # ... (V3'teki species, stagnation, weight ayarları aynı kalabilir) ...
37
+ species_fitness_func = max
38
+ max_stagnation = 20
39
+ species_set_size = 30
40
+ weight_init_mean = 0.0
41
+ weight_init_stdev = 1.0
42
+ weight_max_value = 30
43
+ weight_min_value = -30
44
+ weight_mutate_power = 0.5
45
+ weight_mutate_rate = 0.8
46
+ weight_replace_rate = 0.1
47
+
48
+
49
+ [DefaultSpeciesSet]
50
+ compatibility_threshold = 3.0
51
+
52
+ [DefaultStagnation]
53
+ species_fitness_func = max
54
+ max_stagnation = 15
55
+ species_elitism = 2
config-feedforward-v5.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config-feedforward-v5.txt - Quanta Simulator V5 için Yapılandırma
2
+ # Non-Linear Hedefler + Karmaşıklık Cezası
3
+
4
+ [NEAT]
5
+ fitness_criterion = max
6
+ fitness_threshold = 0.95 # V5 için hedef eşik (zorluk nedeniyle biraz düşük)
7
+ pop_size = 250 # Donanım (i7-12700H) için artırılmış popülasyon
8
+ reset_on_extinction = False
9
+
10
+ [DefaultGenome]
11
+ # node activation options
12
+ activation_default = sigmoid
13
+ activation_mutate_rate = 0.0
14
+ activation_options = sigmoid
15
+
16
+ # node aggregation options
17
+ aggregation_default = sum
18
+ aggregation_mutate_rate = 0.0
19
+ aggregation_options = sum
20
+
21
+ # node bias options
22
+ bias_init_mean = 0.0
23
+ bias_init_stdev = 1.0
24
+ bias_max_value = 30.0
25
+ bias_min_value = -30.0
26
+ bias_mutate_power = 0.5
27
+ bias_mutate_rate = 0.7
28
+ bias_replace_rate = 0.1
29
+
30
+ # genome compatibility options
31
+ compatibility_disjoint_coefficient = 1.0
32
+ compatibility_weight_coefficient = 0.5
33
+
34
+ # connection add/remove rates
35
+ conn_add_prob = 0.5
36
+ conn_delete_prob = 0.5
37
+
38
+ # connection enable options
39
+ enabled_default = True
40
+ enabled_mutate_rate = 0.01
41
+
42
+ feed_forward = True
43
+ initial_connection = full_nodirect
44
+
45
+ # node add/remove rates
46
+ node_add_prob = 0.3 # Yapısal çeşitlilik için biraz artırıldı
47
+ node_delete_prob = 0.2
48
+
49
+ # network parameters
50
+ num_hidden = 0 # Başlangıçta gizli düğüm yok
51
+ num_inputs = 2 # V5 için 2 girdi
52
+ num_outputs = 2 # V5 için 2 çıktı
53
+
54
+ # species options
55
+ species_fitness_func = max
56
+ max_stagnation = 20 # Türlerin gelişmeden kalabileceği max nesil
57
+ species_set_size = 30
58
+
59
+ # weight options
60
+ weight_init_mean = 0.0
61
+ weight_init_stdev = 1.0
62
+ weight_max_value = 30
63
+ weight_min_value = -30
64
+ weight_mutate_power = 0.5
65
+ weight_mutate_rate = 0.8
66
+ weight_replace_rate = 0.1
67
+
68
+ [DefaultSpeciesSet]
69
+ compatibility_threshold = 3.0
70
+
71
+ [DefaultStagnation]
72
+ species_fitness_func = max
73
+ max_stagnation = 15 # Türler için max_stagnation (globalden farklı olabilir)
74
+ species_elitism = 2 # Her türden sonraki nesle aktarılacak en iyi birey sayısı
config-feedforward.txt ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [NEAT]
2
+ fitness_criterion = max
3
+ fitness_threshold = 0.99 # Hedef fitness değeri (1.0'a ne kadar yakınsa o kadar iyi)
4
+ pop_size = 150 # Popülasyon büyüklüğü (Donanımına göre artırılabilir)
5
+ reset_on_extinction = False
6
+
7
+ [DefaultGenome]
8
+ # node activation options
9
+ activation_default = sigmoid
10
+ activation_mutate_rate = 0.0
11
+ activation_options = sigmoid
12
+
13
+ # node aggregation options
14
+ aggregation_default = sum
15
+ aggregation_mutate_rate = 0.0
16
+ aggregation_options = sum
17
+
18
+ # node bias options
19
+ bias_init_mean = 0.0
20
+ bias_init_stdev = 1.0
21
+ bias_max_value = 30.0
22
+ bias_min_value = -30.0
23
+ bias_mutate_power = 0.5
24
+ bias_mutate_rate = 0.7
25
+ bias_replace_rate = 0.1
26
+
27
+ # genome compatibility options
28
+ compatibility_disjoint_coefficient = 1.0
29
+ compatibility_weight_coefficient = 0.5
30
+
31
+ # connection add/remove rates
32
+ conn_add_prob = 0.5
33
+ conn_delete_prob = 0.5
34
+
35
+ # connection enable options
36
+ enabled_default = True
37
+ enabled_mutate_rate = 0.01
38
+
39
+ feed_forward = True # İleri beslemeli ağ
40
+ initial_connection = full_nodirect # Başlangıçta tam bağlı (girdi-çıktı arası)
41
+
42
+ # node add/remove rates
43
+ node_add_prob = 0.2 # Yeni düğüm ekleme olasılığı
44
+ node_delete_prob = 0.2 # Düğüm silme olasılığı
45
+
46
+ # network parameters
47
+ num_hidden = 0 # Başlangıçta gizli katman yok
48
+ num_inputs = 1 # Ağ girdisi sayısı (Şimdilik basit, tek sabit girdi)
49
+ num_outputs = 1 # Ağ çıktısı sayısı (Olasılığı temsil eden tek bir değer)
50
+
51
+ # species options
52
+ species_fitness_func = max
53
+ max_stagnation = 20 # Türlerin gelişmeden kalabileceği maksimum nesil sayısı
54
+ species_set_size = 30
55
+
56
+ # weight options
57
+ weight_init_mean = 0.0
58
+ weight_init_stdev = 1.0
59
+ weight_max_value = 30
60
+ weight_min_value = -30
61
+ weight_mutate_power = 0.5 # Mutasyonun ağırlığı ne kadar değiştireceği
62
+ weight_mutate_rate = 0.8 # Ağırlıkların mutasyona uğrama olasılığı
63
+ weight_replace_rate = 0.1 # Ağırlığın tamamen yeni bir değerle değişme olasılığı
64
+
65
+ [DefaultSpeciesSet]
66
+ compatibility_threshold = 3.0
67
+
68
+ [DefaultStagnation]
69
+ species_fitness_func = max
70
+ max_stagnation = 15
71
+ species_elitism = 2 # Her türden sonraki nesle aktarılacak en iyi birey sayısı
quanta_classifier_v6.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # quanta_classifier_v6.py
2
+
3
+ import neat
4
+ import numpy as np
5
+ import os
6
+ import logging
7
+ import pickle
8
+ import datetime
9
+ import traceback
10
+
11
+ # --- YENİ: Scikit-learn importları ---
12
+ from sklearn.datasets import make_classification
13
+ from sklearn.model_selection import train_test_split
14
+ from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
15
+
16
+ # --- Loglama Ayarları ---
17
+ log_filename = f"quanta_log_v6_classifier_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
18
+ logging.basicConfig(
19
+ level=logging.INFO,
20
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
21
+ handlers=[
22
+ logging.FileHandler(log_filename),
23
+ logging.StreamHandler()
24
+ ]
25
+ )
26
+ logger = logging.getLogger(__name__)
27
+
28
+ logger.info("="*70)
29
+ logger.info("Quanta Classifier Başlatılıyor (Sürüm 6 - Veri Seti ile Sınıflandırma)")
30
+ logger.info(f"Başlangıç Zamanı: {datetime.datetime.now()}")
31
+ logger.info("="*70)
32
+
33
+ # --- Global Değişkenler (Veri Seti) ---
34
+ # Not: Global değişkenler büyük projelerde önerilmez, ancak NEAT'in
35
+ # fitness fonksiyonuna kolayca veri aktarmak için bu örnekte kullanılmıştır.
36
+ # Daha büyük projelerde sınıf yapısı veya functools.partial tercih edilebilir.
37
+ X_train, X_test, y_train, y_test = None, None, None, None
38
+
39
+ # --- Veri Seti Oluşturma ve Hazırlama ---
40
+ def prepare_data(n_samples=500, n_features=2, n_informative=2, n_redundant=0, random_state=42):
41
+ """
42
+ Scikit-learn kullanarak sentetik bir sınıflandırma veri seti oluşturur ve böler.
43
+ """
44
+ global X_train, X_test, y_train, y_test
45
+ logger.info(f"{n_samples} örnekli, {n_features} özellikli sentetik veri seti oluşturuluyor...")
46
+
47
+ X, y = make_classification(
48
+ n_samples=n_samples,
49
+ n_features=n_features,
50
+ n_informative=n_informative,
51
+ n_redundant=n_redundant,
52
+ n_clusters_per_class=1, # Sınıf başına küme sayısı
53
+ flip_y=0.05, # Gürültü ekle (etiketlerin %5'ini ters çevir)
54
+ random_state=random_state
55
+ )
56
+
57
+ X_train, X_test, y_train, y_test = train_test_split(
58
+ X, y, test_size=0.3, random_state=random_state, stratify=y # Sınıf oranlarını koru
59
+ )
60
+ logger.info(f"Veri seti bölündü: {len(X_train)} eğitim, {len(X_test)} test örneği.")
61
+ logger.info(f"Girdi Boyutu (Özellik Sayısı): {X_train.shape[1]}")
62
+ logger.info(f"Sınıf Dağılımı (Eğitim): {np.bincount(y_train)}")
63
+
64
+
65
+ # --- NEAT Fitness Fonksiyonu (Sınıflandırma için) ---
66
+ def eval_genomes_classification(genomes, config):
67
+ """
68
+ Genomları eğitim verisi üzerindeki sınıflandırma doğruluğuna göre değerlendirir.
69
+ """
70
+ global X_train, y_train # Global eğitim verisini kullan
71
+
72
+ if X_train is None or y_train is None:
73
+ logger.error("Eğitim verisi yüklenmemiş! Fitness hesaplanamıyor.")
74
+ # Tüm genomlara düşük fitness ver
75
+ for genome_id, genome in genomes:
76
+ genome.fitness = -1.0
77
+ return
78
+
79
+ for genome_id, genome in genomes:
80
+ genome.fitness = 0.0 # Başlangıç fitness
81
+ try:
82
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
83
+ except Exception as e:
84
+ logger.error(f"Genome {genome_id} ağ oluşturma hatası: {e}")
85
+ genome.fitness = -1.0 # Ceza
86
+ continue
87
+
88
+ correct_predictions = 0
89
+ # Eğitim verisi üzerinde tahmin yap
90
+ for xi, yi in zip(X_train, y_train):
91
+ try:
92
+ output = net.activate(xi)
93
+ # Binary sınıflandırma: Tek sigmoid çıkışı 0.5 eşiği ile yorumla
94
+ prediction = 1 if output[0] >= 0.5 else 0
95
+ if prediction == yi:
96
+ correct_predictions += 1
97
+ except Exception as e:
98
+ # logger.warning(f"G:{genome_id} Aktivasyon hatası: {e}")
99
+ pass # Hatalı aktivasyonları sayma
100
+
101
+ # Fitness = Doğruluk Oranı (Accuracy)
102
+ accuracy = correct_predictions / len(y_train)
103
+ genome.fitness = accuracy
104
+ # logger.debug(f"Genome {genome_id}: Accuracy = {accuracy:.4f}, Fitness = {genome.fitness:.4f}")
105
+
106
+
107
+ # --- NEAT Çalıştırma Fonksiyonu ---
108
+ def run_neat(config_file, generations=100):
109
+ """
110
+ NEAT evrimini başlatır, yönetir ve sonucu değerlendirir.
111
+ """
112
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
113
+ config = None
114
+ try:
115
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
116
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
117
+ config_file)
118
+ logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
119
+ # Yapılandırmadaki girdi sayısı ile veri setinin özellik sayısını kontrol et
120
+ if config.genome_config.num_inputs != X_train.shape[1]:
121
+ logger.error(f"Yapılandırma hatası: Config'deki girdi sayısı ({config.genome_config.num_inputs}) veri özelliği sayısı ({X_train.shape[1]}) ile eşleşmiyor!")
122
+ return None
123
+ # Binary sınıflandırma için çıktı sayısını kontrol et
124
+ if config.genome_config.num_outputs != 1:
125
+ logger.warning(f"Yapılandırma uyarısı: Binary sınıflandırma için çıktı sayısı ({config.genome_config.num_outputs}) genellikle 1 olmalıdır.")
126
+
127
+ except Exception as e:
128
+ logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
129
+ return None
130
+
131
+ logger.info("Yeni popülasyon oluşturuluyor...")
132
+ p = neat.Population(config)
133
+
134
+ # Raporlayıcılar
135
+ p.add_reporter(neat.StdOutReporter(True)) # Konsola detaylı raporlama
136
+ stats = neat.StatisticsReporter() # İstatistikleri toplar (ileride görselleştirme için)
137
+ p.add_reporter(stats)
138
+ checkpoint_prefix = 'neat-checkpoint-v6-'
139
+ p.add_reporter(neat.Checkpointer(generation_interval=20, filename_prefix=checkpoint_prefix)) # 20 nesilde bir checkpoint
140
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
141
+
142
+ logger.info(f"Evrim başlıyor (Maksimum {generations} nesil)...")
143
+ winner = None
144
+ try:
145
+ # Fitness fonksiyonunu (eval_genomes_classification) çalıştır
146
+ winner = p.run(eval_genomes_classification, generations)
147
+ logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
148
+ except Exception as e:
149
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
150
+ logger.error(traceback.format_exc())
151
+ if not winner and p and p.best_genome:
152
+ logger.warning("Evrim hata ile durdu, bulunan son en iyi genom kullanılıyor.")
153
+ winner = p.best_genome
154
+
155
+ # En iyi genomu işle
156
+ if winner:
157
+ logger.info(f'En iyi genom bulundu/kullanıldı (Fitness - Eğitim Doğruluğu: {winner.fitness:.6f}):')
158
+ num_nodes = len(winner.nodes)
159
+ num_connections = len(winner.connections)
160
+ logger.info(f'Kazanan Karmaşıklığı: {num_nodes} Düğüm, {num_connections} Bağlantı')
161
+
162
+ # En iyi genomu kaydet
163
+ winner_filename = "winner_classifier_v6.pkl"
164
+ try:
165
+ with open(winner_filename, 'wb') as f:
166
+ pickle.dump(winner, f)
167
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
168
+ except Exception as e:
169
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
170
+
171
+ # --- YENİ: En İyi Genomun TEST SETİ Üzerinde Değerlendirilmesi ---
172
+ logger.info(" " + "="*20 + " En İyi Genomun Test Seti Performansı " + "="*20)
173
+ try:
174
+ if config is None:
175
+ logger.error("Yapılandırma yüklenemediği için final test atlanıyor.")
176
+ raise RuntimeError("Config object is None.")
177
+
178
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
179
+
180
+ # Test seti üzerinde tahmin yap
181
+ y_pred = []
182
+ logger.info(f"Test seti ({len(X_test)} örnek) üzerinde tahminler yapılıyor...")
183
+ for xi in X_test:
184
+ output = winner_net.activate(xi)
185
+ prediction = 1 if output[0] >= 0.5 else 0
186
+ y_pred.append(prediction)
187
+
188
+ # Performans metriklerini hesapla ve raporla
189
+ accuracy_test = accuracy_score(y_test, y_pred)
190
+ conf_matrix = confusion_matrix(y_test, y_pred)
191
+ class_report = classification_report(y_test, y_pred)
192
+
193
+ logger.info(f"\n--- Test Seti Sonuçları ---")
194
+ logger.info(f"Doğruluk (Accuracy): {accuracy_test:.4f}")
195
+ logger.info(f"\nKarışıklık Matrisi (Confusion Matrix):\n{conf_matrix}")
196
+ logger.info(f"\nSınıflandırma Raporu:\n{class_report}")
197
+ logger.info("---------------------------\n")
198
+
199
+ except Exception as e:
200
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
201
+ logger.error(traceback.format_exc())
202
+ else:
203
+ logger.warning("Evrim sonunda test edilecek bir kazanan genom bulunamadı.")
204
+
205
+ logger.info("="*70)
206
+ logger.info("Quanta Classifier Adım 6 (Veri Seti ile Sınıflandırma) tamamlandı.")
207
+ logger.info(f"Bitiş Zamanı: {datetime.datetime.now()}")
208
+ logger.info("="*70)
209
+ # return winner
210
+
211
+
212
+ if __name__ == '__main__':
213
+ # Betiğin bulunduğu dizini al
214
+ local_dir = os.path.dirname(os.path.abspath(__file__))
215
+ # V6 config dosyasının tam yolunu oluştur
216
+ config_path = os.path.join(local_dir, 'config-classification-v6.txt')
217
+
218
+ if not os.path.exists(config_path):
219
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
220
+ else:
221
+ try:
222
+ # 1. Veri setini hazırla
223
+ prepare_data(n_samples=1000, n_features=2, n_informative=2, random_state=123)
224
+
225
+ # 2. NEAT evrimini çalıştır (Config'deki eşiğe ulaşana kadar veya max nesil)
226
+ # MAX_GENERATIONS sabitini burada da tanımlayabiliriz:
227
+ MAX_GENERATIONS_RUN = 150 # Deneme için 150 nesil, gerekirse artırılır
228
+ run_neat(config_path, generations=MAX_GENERATIONS_RUN)
229
+
230
+ except ImportError as ie:
231
+ logger.critical(f"Gerekli kütüphane bulunamadı: {ie}")
232
+ logger.critical("Lütfen 'pip install scikit-learn numpy neat-python' komutu ile kurun.")
233
+ except Exception as main_e:
234
+ logger.critical(f"Ana program akışında beklenmedik bir hata oluştu: {main_e}")
235
+ logger.error(traceback.format_exc())
quanta_sim_v1_no_viz.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import neat
2
+ import numpy as np
3
+ import os
4
+ import logging
5
+ import pickle # En iyi genomu kaydetmek/yüklemek için
6
+ import random
7
+ import math
8
+ import datetime # Log dosyası ismi için
9
+
10
+ # --- Loglama Ayarları ---
11
+ log_filename = f"quanta_log_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
12
+ logging.basicConfig(
13
+ level=logging.INFO, # Log seviyesi (INFO, DEBUG, WARNING, ERROR, CRITICAL)
14
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s', # Log formatı
15
+ handlers=[
16
+ logging.FileHandler(log_filename), # Dosyaya loglama
17
+ logging.StreamHandler() # Konsola (ekrana) loglama
18
+ ]
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ logger.info("="*50)
23
+ logger.info("Quanta Simülatörü Başlatılıyor (Görselleştirme Olmadan)")
24
+ logger.info("="*50)
25
+
26
+ # --- Simülasyon Parametreleri ---
27
+ TARGET_PROB_0 = 0.7 # Hedef: %70 olasılıkla 0 üretmek
28
+ TARGET_PROB_1 = 1.0 - TARGET_PROB_0 # Hedef: %30 olasılıkla 1 üretmek
29
+ NUM_TRIALS_PER_GENOME = 100 # Her genomu değerlendirmek için yapılacak deneme sayısı
30
+ MAX_GENERATIONS = 50 # Maksimum evrim nesli (Donanımınıza göre artırılabilir)
31
+ FITNESS_THRESHOLD = 0.99 # Evrimin durması için ulaşılması gereken minimum fitness
32
+
33
+ logger.info(f"Hedef P(0): {TARGET_PROB_0:.2f}, Hedef P(1): {TARGET_PROB_1:.2f}")
34
+ logger.info(f"Genom Başına Deneme Sayısı: {NUM_TRIALS_PER_GENOME}")
35
+ logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
36
+ logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
37
+
38
+ # --- Basit Kuantum Benzeri Davranış (Taklit) ---
39
+ # Bu fonksiyon, kuantum ölçümünün olasılıksal sonucunu basitçe taklit eder.
40
+ def simulate_simple_qubit_measurement(prob0=TARGET_PROB_0):
41
+ if random.random() < prob0:
42
+ return 0
43
+ else:
44
+ return 1
45
+
46
+ # --- NEAT Fitness Fonksiyonu ---
47
+ # Genomları (sinir ağlarını) değerlendirir.
48
+ # Hedef: Ağın çıktısı TARGET_PROB_0'a yakın olasılıkla 0 olmalı.
49
+ def eval_genomes(genomes, config):
50
+ """
51
+ Popülasyondaki tüm genomların fitness değerlerini hesaplar.
52
+ """
53
+ for genome_id, genome in genomes:
54
+ genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
55
+ try:
56
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
57
+ except Exception as e:
58
+ logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
59
+ genome.fitness = -1.0 # Geçersiz genomları cezalandır
60
+ continue
61
+
62
+ count_0 = 0
63
+ # Her genomu N kez test ederek istatistiksel olarak değerlendir
64
+ for _ in range(NUM_TRIALS_PER_GENOME):
65
+ # Ağ Girdisi: Şimdilik sabit bir değer (1.0) kullanıyoruz.
66
+ # Gelecekte bu girdi, simülasyonun durumunu veya kontrol parametrelerini yansıtabilir.
67
+ net_input = (1.0,)
68
+ try:
69
+ output = net.activate(net_input)
70
+ # Ağın çıktısını (genellikle 0-1 arası) yorumla
71
+ # Çıktı < 0.5 ise 0, >= 0.5 ise 1 kabul edelim
72
+ if output[0] < 0.5:
73
+ count_0 += 1
74
+ except Exception as e:
75
+ logger.warning(f"Genome {genome_id} ağ aktivasyonunda hata: {e}")
76
+ # Hata durumunda bu denemeyi atla veya penaltı ver
77
+ pass # Şimdilik sadece atlıyoruz
78
+
79
+ # Gözlemlenen olasılıkları hesapla
80
+ observed_prob_0 = count_0 / NUM_TRIALS_PER_GENOME
81
+
82
+ # Fitness Hesaplama: Hedef olasılıklara ne kadar yakın?
83
+ # Ortalama Karesel Hata (MSE) benzeri bir yaklaşım, ama ters çevrilmiş.
84
+ # Hata ne kadar küçükse, fitness o kadar yüksek olmalı.
85
+ error = (observed_prob_0 - TARGET_PROB_0) ** 2
86
+ # Fitness = 1 / (hata + epsilon) -> Hata sıfıra yaklaştıkça fitness sonsuza yaklaşır.
87
+ # Daha stabil bir fitness için: Fitness = 1.0 - hata (0 ile 1 arasında)
88
+ # Veya hedef eşiğe göre normalize edilebilir. Şimdilik basit tutalım:
89
+ fitness = max(0.0, 1.0 - math.sqrt(error)) # Hatanın karekökünü 1'den çıkaralım (0-1 arası)
90
+
91
+ genome.fitness = fitness
92
+ # logger.debug(f"Genome {genome_id}: Fitness = {fitness:.4f}, Gözlenen P(0) = {observed_prob_0:.2f}")
93
+
94
+
95
+ # --- NEAT Çalıştırma Fonksiyonu ---
96
+ def run_neat(config_file):
97
+ """
98
+ NEAT evrimini başlatır ve yönetir.
99
+ """
100
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
101
+ try:
102
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
103
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
104
+ config_file)
105
+ # Fitness eşiğini config dosyasından değil, koddan alalım
106
+ config.fitness_threshold = FITNESS_THRESHOLD
107
+ logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
108
+
109
+ except Exception as e:
110
+ logger.critical(f"Yapılandırma dosyası y��klenemedi veya geçersiz: {config_file} - Hata: {e}")
111
+ return None # Hata durumunda None döndür
112
+
113
+ logger.info("Yeni popülasyon oluşturuluyor...")
114
+ p = neat.Population(config)
115
+
116
+ # İstatistikleri ve loglamayı ayarlama (Sadece konsol çıktısı)
117
+ p.add_reporter(neat.StdOutReporter(True))
118
+ # Görselleştirme için istatistik toplayıcıya gerek yok.
119
+ # stats = neat.StatisticsReporter()
120
+ # p.add_reporter(stats)
121
+
122
+ # Periyodik olarak checkpoint (yedek) alma
123
+ checkpoint_prefix = 'neat-checkpoint-'
124
+ p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix)) # Her 10 nesilde bir kaydet
125
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
126
+
127
+ logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
128
+ try:
129
+ winner = p.run(eval_genomes, MAX_GENERATIONS)
130
+ logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
131
+ except Exception as e:
132
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
133
+ # Belki son checkpoint'ten devam etme mantığı eklenebilir.
134
+ return None
135
+
136
+ # En iyi genomu göster/kaydet
137
+ logger.info(f'En iyi genom bulundu:')
138
+ logger.info(f' {winner}') # Konsola detaylı genom bilgisini yazdırır
139
+
140
+ # En iyi genomu dosyaya kaydet (pickle ile)
141
+ winner_filename = "winner_genome.pkl"
142
+ try:
143
+ with open(winner_filename, 'wb') as f:
144
+ pickle.dump(winner, f)
145
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
146
+ except Exception as e:
147
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
148
+
149
+ # En iyi genomdan ağı oluştur ve son bir kez test et
150
+ logger.info(" " + "="*20 + " En İyi Genom Testi " + "="*20)
151
+ if winner:
152
+ try:
153
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
154
+ test_count_0 = 0
155
+ test_trials = 1000 # Daha fazla deneme ile güvenilirliği artır
156
+ logger.info(f"En iyi ağ {test_trials} kez test ediliyor...")
157
+ for _ in range(test_trials):
158
+ net_input = (1.0,)
159
+ output = winner_net.activate(net_input)
160
+ if output[0] < 0.5:
161
+ test_count_0 += 1
162
+
163
+ observed_prob_0 = test_count_0 / test_trials
164
+ logger.info(f"Final Test Sonucu: Gözlenen P(0) = {observed_prob_0:.4f} (Hedef: {TARGET_PROB_0:.3f})")
165
+ logger.info(f"Final Test Sonucu: Gözlenen P(1) = {1.0 - observed_prob_0:.4f} (Hedef: {TARGET_PROB_1:.3f})")
166
+ final_error = (observed_prob_0 - TARGET_PROB_0) ** 2
167
+ logger.info(f"Final Test Hatası (Karesel): {final_error:.6f}")
168
+ except Exception as e:
169
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
170
+ else:
171
+ logger.warning("Test edilecek bir kazanan genom bulunamadı.")
172
+
173
+ logger.info("="*50)
174
+ logger.info("Quanta Simülatörü Adım 1 (Görselleştirmesiz) tamamlandı.")
175
+ logger.info("="*50)
176
+ return winner # Kazanan genomu döndür
177
+
178
+
179
+ if __name__ == '__main__':
180
+ # Yapılandırma dosyasının yolu (Python betiği ile aynı klasörde olduğunu varsayar)
181
+ local_dir = os.path.dirname(__file__)
182
+ config_path = os.path.join(local_dir, 'config-feedforward.txt')
183
+
184
+ if not os.path.exists(config_path):
185
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
186
+ logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
187
+ else:
188
+ # NEAT'i çalıştır
189
+ run_neat(config_path)
quanta_sim_v2_input_dep.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # quanta_sim_v2_input_dep.py
2
+
3
+ import neat
4
+ import numpy as np
5
+ import os
6
+ import logging
7
+ import pickle
8
+ import random
9
+ import math
10
+ import datetime
11
+ # Görselleştirme importları YOKTUR.
12
+
13
+ # --- Loglama Ayarları ---
14
+ log_filename = f"quanta_log_v2_input_dep_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V2 için dosya adı
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler(log_filename),
20
+ logging.StreamHandler()
21
+ ]
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+ logger.info("="*50)
26
+ logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 2 - Girdiye Bağlı Olasılık)") # <-- GÜNCELLENDİ
27
+ logger.info("="*50)
28
+
29
+ # --- Simülasyon Parametreleri ---
30
+ # TARGET_PROB_0 artık sabit değil, girdiye göre hesaplanacak.
31
+ # Bu yüzden aşağıdaki satırları kaldırabilir veya yorum satırı yapabiliriz.
32
+ # TARGET_PROB_0 = 0.7
33
+ # TARGET_PROB_1 = 1.0 - TARGET_PROB_0
34
+
35
+ NUM_TEST_INPUTS = 6 # Farklı girdi değerlerini test etmek için kullanılacak girdi sayısı
36
+ NUM_TRIALS_PER_INPUT = 20 # Her bir girdi değeri için yapılacak deneme sayısı
37
+ # Toplam deneme sayısı = NUM_TEST_INPUTS * NUM_TRIALS_PER_INPUT (örn: 6 * 20 = 120)
38
+
39
+ MAX_GENERATIONS = 100 # <-- Gerekirse artırılabilir, problem biraz daha zorlaştı.
40
+ FITNESS_THRESHOLD = 0.98 # <-- Hedef biraz daha zor olduğu için eşiği hafifçe düşürebiliriz (isteğe bağlı)
41
+
42
+ logger.info(f"Test Edilecek Girdi Sayısı: {NUM_TEST_INPUTS}")
43
+ logger.info(f"Girdi Başına Deneme Sayısı: {NUM_TRIALS_PER_INPUT}")
44
+ logger.info(f"Toplam Değerlendirme Denemesi/Genom: {NUM_TEST_INPUTS * NUM_TRIALS_PER_INPUT}")
45
+ logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
46
+ logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
47
+
48
+ # --- YENİ: Hedef Olasılık Fonksiyonu ---
49
+ def calculate_target_prob0(input_value):
50
+ """
51
+ Verilen girdiye göre hedef P(0) olasılığını hesaplar.
52
+ Lineer Fonksiyon: target_P0(x) = 0.1 + 0.8 * x
53
+ """
54
+ return 0.1 + 0.8 * input_value
55
+
56
+ logger.info(f"Hedef P(0) Fonksiyonu: P(0|x) = 0.1 + 0.8 * x")
57
+
58
+ # --- NEAT Fitness Fonksiyonu ---
59
+ # (Bu fonksiyon Sürüm 2 için önemli ölçüde güncellendi)
60
+ def eval_genomes(genomes, config):
61
+ """
62
+ Popülasyondaki tüm genomların fitness değerlerini hesaplar.
63
+ Fitness, ağın farklı girdiler için hedeflenen olasılıkları
64
+ ne kadar iyi üretebildiğine göre belirlenir.
65
+ """
66
+ # Test edilecek girdi değerlerini belirleyelim (0 ile 1 arasında eşit aralıklı)
67
+ test_inputs = np.linspace(0.0, 1.0, NUM_TEST_INPUTS)
68
+ # Örnek: NUM_TEST_INPUTS=6 ise -> [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
69
+
70
+ for genome_id, genome in genomes:
71
+ genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
72
+ try:
73
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
74
+ except Exception as e:
75
+ logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
76
+ genome.fitness = -10.0 # Daha büyük ceza verilebilir
77
+ continue
78
+
79
+ total_squared_error = 0.0
80
+
81
+ # Her bir test girdisi için ağı değerlendir
82
+ for net_input_val in test_inputs:
83
+ net_input = (net_input_val,) # Girdiyi tuple formatına getir
84
+ target_prob_0 = calculate_target_prob0(net_input_val) # Bu girdi için hedef P(0)
85
+
86
+ count_0 = 0
87
+ # Her girdi için N kez test et
88
+ for _ in range(NUM_TRIALS_PER_INPUT):
89
+ try:
90
+ output = net.activate(net_input)
91
+ # Ağın çıktısını yorumla (< 0.5 ise 0)
92
+ if output[0] < 0.5:
93
+ count_0 += 1
94
+ except Exception as e:
95
+ logger.warning(f"Genome {genome_id}, Input {net_input_val:.2f} ağ aktivasyonunda hata: {e}")
96
+ # Hata durumunda bu denemeyi atla veya penaltı ver
97
+ pass # Şimdilik sadece atlıyoruz
98
+
99
+ # Gözlemlenen olasılığı hesapla
100
+ if NUM_TRIALS_PER_INPUT > 0:
101
+ observed_prob_0 = count_0 / NUM_TRIALS_PER_INPUT
102
+ else:
103
+ observed_prob_0 = 0.5 # Sıfıra bölme hatasını önle (pek olası değil ama güvenli)
104
+
105
+ # Bu girdi için hatanın karesini hesapla
106
+ error = (observed_prob_0 - target_prob_0) ** 2
107
+ total_squared_error += error
108
+
109
+ # logger.debug(f" Genome {genome_id}, Input {net_input_val:.2f}: TargetP0={target_prob_0:.3f}, ObsP0={observed_prob_0:.3f}, Error^2={error:.4f}")
110
+
111
+ # Ortalama Karesel Hatayı (Mean Squared Error - MSE) hesapla
112
+ average_squared_error = total_squared_error / NUM_TEST_INPUTS
113
+
114
+ # Fitness'ı hesapla: Hata ne kadar küçükse, fitness o kadar yüksek (Maks 1.0)
115
+ # Hatanın karekökünü (RMSE gibi) 1'den çıkaralım
116
+ fitness = max(0.0, 1.0 - math.sqrt(average_squared_error))
117
+
118
+ genome.fitness = fitness
119
+ # logger.info(f"Genome {genome_id}: AvgError^2 = {average_squared_error:.4f}, Fitness = {fitness:.4f}")
120
+
121
+
122
+ # --- NEAT Çalıştırma Fonksiyonu ---
123
+ def run_neat(config_file):
124
+ """
125
+ NEAT evrimini başlatır ve yönetir.
126
+ """
127
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
128
+ try:
129
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
130
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
131
+ config_file)
132
+ # Fitness eşiğini config dosyasından değil, koddan alalım
133
+ config.fitness_threshold = FITNESS_THRESHOLD # <-- V2 için güncel eşik
134
+ logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
135
+
136
+ except Exception as e:
137
+ logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
138
+ return None
139
+
140
+ logger.info("Yeni popülasyon oluşturuluyor...")
141
+ p = neat.Population(config)
142
+
143
+ # İstatistikleri ve loglamayı ayarlama
144
+ p.add_reporter(neat.StdOutReporter(True)) # Konsola raporlama
145
+ # stats = neat.StatisticsReporter() # Görselleştirme YOK, bu yüzden buna gerek yok
146
+ # p.add_reporter(stats)
147
+
148
+ # Checkpoint (yedek) alma
149
+ checkpoint_prefix = 'neat-checkpoint-v2-' # <-- V2 için farklı prefix
150
+ p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix))
151
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
152
+
153
+ logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
154
+ try:
155
+ winner = p.run(eval_genomes, MAX_GENERATIONS)
156
+ logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
157
+ except Exception as e:
158
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
159
+ return None
160
+
161
+ # En iyi genomu göster/kaydet
162
+ if winner:
163
+ logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
164
+ logger.info(f' {winner}') # Konsola detaylı genom bilgisini yazdırır
165
+
166
+ # En iyi genomu dosyaya kaydet (pickle ile)
167
+ winner_filename = "winner_genome_v2.pkl" # <-- V2 için farklı dosya adı
168
+ try:
169
+ with open(winner_filename, 'wb') as f:
170
+ pickle.dump(winner, f)
171
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
172
+ except Exception as e:
173
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
174
+
175
+ # --- YENİ: En İyi Genomu Farklı Girdilerle Test Etme ---
176
+ logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi " + "="*20)
177
+ try:
178
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
179
+ test_trials_final = 1000 # Her girdi için final test deneme sayısı
180
+ logger.info(f"En iyi ağ, farklı girdilerle {test_trials_final} kez test ediliyor...")
181
+
182
+ test_inputs_final = np.linspace(0.0, 1.0, 11) # Daha fazla ara noktayla test edelim (0.0, 0.1, ..., 1.0)
183
+ final_total_error_sq = 0.0
184
+ results = []
185
+
186
+ for net_input_val in test_inputs_final:
187
+ target_p0 = calculate_target_prob0(net_input_val)
188
+ net_input = (net_input_val,)
189
+ count_0 = 0
190
+ for _ in range(test_trials_final):
191
+ output = winner_net.activate(net_input)
192
+ if output[0] < 0.5:
193
+ count_0 += 1
194
+
195
+ observed_p0 = count_0 / test_trials_final
196
+ error_sq = (observed_p0 - target_p0) ** 2
197
+ final_total_error_sq += error_sq
198
+ results.append({
199
+ "input": net_input_val,
200
+ "target_p0": target_p0,
201
+ "observed_p0": observed_p0,
202
+ "error_sq": error_sq
203
+ })
204
+ logger.info(f" Input={net_input_val: <4.2f} -> TargetP(0)={target_p0: <5.3f}, ObservedP(0)={observed_p0: <5.3f}, Error^2={error_sq:.5f}")
205
+
206
+ final_avg_error_sq = final_total_error_sq / len(test_inputs_final)
207
+ final_rmse = math.sqrt(final_avg_error_sq)
208
+ logger.info("-" * 40)
209
+ logger.info(f"Final Ortalama Karesel Hata (MSE): {final_avg_error_sq:.6f}")
210
+ logger.info(f"Final Kök Ortalama Karesel Hata (RMSE): {final_rmse:.6f}")
211
+ logger.info(f"Final Fitness Yaklaşımı (1 - RMSE): {1.0 - final_rmse:.6f}")
212
+ logger.info("-" * 40)
213
+
214
+ except Exception as e:
215
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
216
+
217
+ else:
218
+ logger.warning("Test edilecek bir kazanan genom bulunamadı.")
219
+
220
+ logger.info("="*50)
221
+ logger.info("Quanta Simülatörü Adım 2 (Girdiye Bağlı Olasılık) tamamlandı.")
222
+ logger.info("="*50)
223
+ return winner
224
+
225
+
226
+ if __name__ == '__main__':
227
+ # Yapılandırma dosyasının yolu (Python betiği ile aynı klasörde olduğunu varsayar)
228
+ local_dir = os.path.dirname(__file__)
229
+ # V1'deki config dosyasını kullanıyoruz, ismi aynı kalabilir.
230
+ config_path = os.path.join(local_dir, 'config-feedforward.txt')
231
+
232
+ if not os.path.exists(config_path):
233
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
234
+ logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
235
+ else:
236
+ # NEAT'i çalıştır
237
+ run_neat(config_path)
quanta_sim_v3_multi_input.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # quanta_sim_v3_multi_input.py
2
+
3
+ import neat
4
+ import numpy as np
5
+ import os
6
+ import logging
7
+ import pickle
8
+ import random
9
+ import math
10
+ import datetime
11
+ import itertools # <-- YENİ: Girdi kombinasyonları için
12
+
13
+ # --- Loglama Ayarları ---
14
+ log_filename = f"quanta_log_v3_multi_input_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V3 için dosya adı
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler(log_filename),
20
+ logging.StreamHandler()
21
+ ]
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+ logger.info("="*50)
26
+ logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 3 - Çoklu Girdi)") # <-- GÜNCELLENDİ
27
+ logger.info("="*50)
28
+
29
+ # --- Simülasyon Parametreleri ---
30
+ NUM_TEST_VALUES_PER_AXIS = 3 # Her bir girdi ekseni için test edilecek değer sayısı (örn: 0.0, 0.5, 1.0)
31
+ NUM_TRIALS_PER_INPUT_PAIR = 20 # Her bir girdi çifti için yapılacak deneme sayısı
32
+ # Toplam test noktası sayısı = NUM_TEST_VALUES_PER_AXIS * NUM_TEST_VALUES_PER_AXIS
33
+ # Toplam değerlendirme denemesi/Genom = NUM_TEST_POINTS * NUM_TRIALS_PER_INPUT_PAIR
34
+
35
+ MAX_GENERATIONS = 150 # <-- Problem zorlaştığı için artırılabilir
36
+ FITNESS_THRESHOLD = 0.97 # <-- Hedef zorlaştığı için eşik ayarlanabilir
37
+
38
+ num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2 # İki girdi olduğu için karesi
39
+ total_trials_per_genome = num_test_points * NUM_TRIALS_PER_INPUT_PAIR
40
+
41
+ logger.info(f"Eksen Başına Test Değeri Sayısı: {NUM_TEST_VALUES_PER_AXIS}")
42
+ logger.info(f"Toplam Test Girdi Çifti Sayısı: {num_test_points}")
43
+ logger.info(f"Girdi Çifti Başına Deneme Sayısı: {NUM_TRIALS_PER_INPUT_PAIR}")
44
+ logger.info(f"Toplam Değerlendirme Denemesi/Genom: {total_trials_per_genome}")
45
+ logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
46
+ logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
47
+
48
+ # --- YENİ: İki Girdi İçin Hedef Olasılık Fonksiyonu ---
49
+ def calculate_target_prob0(input1, input2):
50
+ """
51
+ Verilen iki girdiye göre hedef P(0) olasılığını hesaplar.
52
+ Lineer Fonksiyon: target_P0(x1, x2) = 0.1 + 0.5*x1 + 0.3*x2
53
+ """
54
+ # Değerlerin 0-1 aralığında kalmasını sağlayalım (isteğe bağlı, fonksiyona göre)
55
+ target = 0.1 + 0.5 * input1 + 0.3 * input2
56
+ return max(0.0, min(1.0, target)) # Güvenlik önlemi
57
+
58
+ logger.info(f"Hedef P(0) Fonksiyonu: P(0|x1, x2) = 0.1 + 0.5*x1 + 0.3*x2")
59
+
60
+ # --- NEAT Fitness Fonksiyonu ---
61
+ # (Bu fonksiyon Sürüm 3 için önemli ölçüde güncellendi)
62
+ def eval_genomes(genomes, config):
63
+ """
64
+ Popülasyondaki tüm genomların fitness değerlerini hesaplar.
65
+ Fitness, ağın farklı girdi çiftleri için hedeflenen olasılıkları
66
+ ne kadar iyi üretebildiğine göre belirlenir.
67
+ """
68
+ # Test edilecek girdi değerlerini her eksen için belirleyelim
69
+ axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
70
+ # Örnek: NUM_TEST_VALUES_PER_AXIS=3 ise -> [0.0, 0.5, 1.0]
71
+
72
+ # Tüm girdi çiftlerini (kombinasyonlarını) oluşturalım
73
+ # Örnek: [(0.0, 0.0), (0.0, 0.5), (0.0, 1.0), (0.5, 0.0), ..., (1.0, 1.0)]
74
+ test_input_pairs = list(itertools.product(axis_values, repeat=2))
75
+
76
+ for genome_id, genome in genomes:
77
+ genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
78
+ try:
79
+ # İki girdili config ile ağı oluştur
80
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
81
+ except Exception as e:
82
+ logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
83
+ genome.fitness = -10.0
84
+ continue
85
+
86
+ total_squared_error = 0.0
87
+
88
+ # Her bir test girdi çifti için ağı değerlendir
89
+ for input_pair in test_input_pairs:
90
+ x1, x2 = input_pair # Girdi çiftini ayır
91
+ target_prob_0 = calculate_target_prob0(x1, x2) # Bu çift için hedef P(0)
92
+
93
+ count_0 = 0
94
+ # Her girdi çifti için N kez test et
95
+ for _ in range(NUM_TRIALS_PER_INPUT_PAIR):
96
+ try:
97
+ # Ağı iki girdi ile aktive et
98
+ output = net.activate(input_pair)
99
+ # Ağın çıktısını yorumla (< 0.5 ise 0)
100
+ if output[0] < 0.5:
101
+ count_0 += 1
102
+ except Exception as e:
103
+ logger.warning(f"Genome {genome_id}, Input {input_pair} ağ aktivasyonunda hata: {e}")
104
+ pass
105
+
106
+ # Gözlemlenen olasılığı hesapla
107
+ if NUM_TRIALS_PER_INPUT_PAIR > 0:
108
+ observed_prob_0 = count_0 / NUM_TRIALS_PER_INPUT_PAIR
109
+ else:
110
+ observed_prob_0 = 0.5
111
+
112
+ # Bu girdi çifti için hatanın karesini hesapla
113
+ error = (observed_prob_0 - target_prob_0) ** 2
114
+ total_squared_error += error
115
+
116
+ # Ortalama Karesel Hatayı (Mean Squared Error - MSE) hesapla
117
+ average_squared_error = total_squared_error / len(test_input_pairs)
118
+
119
+ # Fitness'ı hesapla (1 - RMSE)
120
+ fitness = max(0.0, 1.0 - math.sqrt(average_squared_error))
121
+ genome.fitness = fitness
122
+ # logger.info(f"Genome {genome_id}: AvgError^2 = {average_squared_error:.4f}, Fitness = {fitness:.4f}")
123
+
124
+
125
+ # --- NEAT Çalıştırma Fonksiyonu ---
126
+ def run_neat(config_file):
127
+ """
128
+ NEAT evrimini başlatır ve yönetir.
129
+ """
130
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
131
+ try:
132
+ # V3 config dosyasını kullanarak config nesnesini oluştur
133
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
134
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
135
+ config_file) # <-- config_file şimdi v3 dosyasını gösteriyor
136
+ config.fitness_threshold = FITNESS_THRESHOLD
137
+ logger.info(f"Yapılandırma yüklendi. Giriş Sayısı: {config.genome_config.num_inputs}, Fitness Eşiği: {config.fitness_threshold}")
138
+
139
+ except Exception as e:
140
+ logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
141
+ return None
142
+
143
+ logger.info("Yeni popülasyon oluşturuluyor...")
144
+ p = neat.Population(config)
145
+
146
+ # Raporlayıcılar
147
+ p.add_reporter(neat.StdOutReporter(True))
148
+ # Checkpoint
149
+ checkpoint_prefix = 'neat-checkpoint-v3-' # <-- V3 için prefix
150
+ p.add_reporter(neat.Checkpointer(15, filename_prefix=checkpoint_prefix)) # Daha seyrek kaydedilebilir
151
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
152
+
153
+ logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
154
+ try:
155
+ winner = p.run(eval_genomes, MAX_GENERATIONS)
156
+ logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
157
+ except Exception as e:
158
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
159
+ return None
160
+
161
+ # En iyi genomu işle
162
+ if winner:
163
+ logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
164
+ logger.info(f' {winner}')
165
+
166
+ # En iyi genomu kaydet
167
+ winner_filename = "winner_genome_v3.pkl" # <-- V3 için dosya adı
168
+ try:
169
+ with open(winner_filename, 'wb') as f:
170
+ pickle.dump(winner, f)
171
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
172
+ except Exception as e:
173
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
174
+
175
+ # --- YENİ: En İyi Genomu Çoklu Girdi İle Detaylı Test Etme ---
176
+ logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi (Çoklu Girdi) " + "="*20)
177
+ try:
178
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
179
+ test_trials_final = 500 # Final test için deneme sayısı
180
+ logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
181
+
182
+ # Daha hassas bir girdi ızgarası oluşturalım (örn: 5x5 = 25 nokta)
183
+ final_axis_values = np.linspace(0.0, 1.0, 5)
184
+ final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
185
+ final_total_error_sq = 0.0
186
+
187
+ logger.info(f"{'Input (x1,x2)': <15} {'Target P(0)': <12} {'Observed P(0)': <14} {'Error^2': <10}")
188
+ logger.info("-" * 60)
189
+
190
+ for input_pair in final_test_pairs:
191
+ x1, x2 = input_pair
192
+ target_p0 = calculate_target_prob0(x1, x2)
193
+ count_0 = 0
194
+ for _ in range(test_trials_final):
195
+ output = winner_net.activate(input_pair)
196
+ if output[0] < 0.5:
197
+ count_0 += 1
198
+
199
+ observed_p0 = count_0 / test_trials_final
200
+ error_sq = (observed_p0 - target_p0) ** 2
201
+ final_total_error_sq += error_sq
202
+
203
+ logger.info(f"({x1:.2f}, {x2:.2f}) {target_p0:<12.3f} {observed_p0:<14.3f} {error_sq:<10.5f}")
204
+
205
+ final_avg_error_sq = final_total_error_sq / len(final_test_pairs)
206
+ final_rmse = math.sqrt(final_avg_error_sq)
207
+ logger.info("-" * 60)
208
+ logger.info(f"Final Ortalama Karesel Hata (MSE): {final_avg_error_sq:.6f}")
209
+ logger.info(f"Final Kök Ortalama Karesel Hata (RMSE): {final_rmse:.6f}")
210
+ logger.info(f"Final Fitness Yaklaşımı (1 - RMSE): {1.0 - final_rmse:.6f}")
211
+ logger.info("-" * 60)
212
+
213
+ except Exception as e:
214
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
215
+
216
+ else:
217
+ logger.warning("Test edilecek bir kazanan genom bulunamadı.")
218
+
219
+ logger.info("="*50)
220
+ logger.info("Quanta Simülatörü Adım 3 (Çoklu Girdi) tamamlandı.")
221
+ logger.info("="*50)
222
+ return winner
223
+
224
+
225
+ if __name__ == '__main__':
226
+ # V3 için yeni yapılandırma dosyasının yolu
227
+ local_dir = os.path.dirname(__file__)
228
+ config_path = os.path.join(local_dir, 'config-feedforward-v3.txt') # <-- YENİ Config Dosyası
229
+
230
+ if not os.path.exists(config_path):
231
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
232
+ logger.critical("Lütfen 'config-feedforward-v3.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
233
+ else:
234
+ # NEAT'i çalıştır
235
+ run_neat(config_path)
quanta_sim_v4_correlated_outputs.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # quanta_sim_v4_correlated_outputs.py
2
+
3
+ import neat
4
+ import numpy as np
5
+ import os
6
+ import logging
7
+ import pickle
8
+ import random
9
+ import math
10
+ import datetime
11
+ import itertools
12
+
13
+ # --- Loglama Ayarları ---
14
+ log_filename = f"quanta_log_v4_corr_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V4 için dosya adı
15
+ logging.basicConfig(
16
+ level=logging.INFO, # DEBUG seviyesi daha fazla bilgi verir ama yavaşlatabilir
17
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler(log_filename),
20
+ logging.StreamHandler()
21
+ ]
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+ logger.info("="*70)
26
+ logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 4 - Korelasyonlu Çıktılar)") # <-- GÜNCELLENDİ
27
+ logger.info("="*70)
28
+
29
+ # --- Simülasyon Parametreleri ---
30
+ NUM_TEST_VALUES_PER_AXIS = 3 # Değerlendirme için ızgara boyutu (3x3=9 nokta)
31
+ NUM_TRIALS_PER_PAIR = 30 # Her girdi çifti için deneme sayısı (artırıldı)
32
+
33
+ MAX_GENERATIONS = 250 # <-- Problem çok daha zor, nesil sayısı artırıldı
34
+ FITNESS_THRESHOLD = 0.97 # <-- Hedef zor, eşik ayarlanabilir
35
+
36
+ num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2
37
+ total_trials_per_genome = num_test_points * NUM_TRIALS_PER_PAIR
38
+
39
+ # Fitness fonksiyonundaki hata ağırlıkları
40
+ W_PA0 = 1.0 # P(A=0) hatasının ağırlığı
41
+ W_PB0 = 1.0 # P(B=0) hatasının ağırlığı
42
+ W_CORR = 1.5 # Korelasyon hatasının ağırlığı (genellikle daha zordur, ağırlığı artırılabilir)
43
+ TOTAL_WEIGHT = W_PA0 + W_PB0 + W_CORR
44
+
45
+ logger.info(f"Eksen Başına Test Değeri: {NUM_TEST_VALUES_PER_AXIS} ({num_test_points} test noktası)")
46
+ logger.info(f"Girdi Çifti Başına Deneme: {NUM_TRIALS_PER_PAIR} (Toplam {total_trials_per_genome} deneme/genom)")
47
+ logger.info(f"Maksimum Nesil: {MAX_GENERATIONS}")
48
+ logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
49
+ logger.info(f"Fitness Hata Ağırlıkları: P(A=0)={W_PA0:.1f}, P(B=0)={W_PB0:.1f}, Corr={W_CORR:.1f}")
50
+
51
+ # --- YENİ: Hedef Fonksiyonları (P(A=0), P(B=0), Korelasyon) ---
52
+ def target_PA0(x1, x2):
53
+ return 0.2 + 0.6 * x1
54
+
55
+ def target_PB0(x1, x2):
56
+ return 0.7 - 0.5 * x2
57
+
58
+ def target_Corr(x1, x2):
59
+ # Hedef korelasyon (-1 ile +1 arasında olmalı)
60
+ return -0.8 * x1 * x2
61
+
62
+ logger.info(f"Hedef P(A=0|x1,x2) = 0.2 + 0.6*x1")
63
+ logger.info(f"Hedef P(B=0|x1,x2) = 0.7 - 0.5*x2")
64
+ logger.info(f"Hedef Corr(A,B|x1,x2) = -0.8 * x1 * x2")
65
+
66
+ # --- Korelasyon Hesaplama Yardımcı Fonksiyonu ---
67
+ def calculate_correlation(pA0, pB0, pA0B0, epsilon=1e-9):
68
+ """ Verilen olasılıklardan korelasyonu hesaplar. """
69
+ pA1 = 1.0 - pA0
70
+ pB1 = 1.0 - pB0
71
+
72
+ # Kovaryans = P(A=0,B=0) - P(A=0)*P(B=0)
73
+ covariance = pA0B0 - pA0 * pB0
74
+
75
+ # Standart sapmaların karesi (varyanslar)
76
+ varA = pA0 * pA1
77
+ varB = pB0 * pB1
78
+
79
+ # Sıfıra bölme hatasını önlemek için epsilon ekle
80
+ denominator = math.sqrt((varA + epsilon) * (varB + epsilon))
81
+
82
+ if denominator < epsilon: # Eğer varyans çok küçükse (olasılıklar 0 veya 1'e çok yakınsa)
83
+ return 0.0 # Korelasyon anlamsızdır veya sıfırdır
84
+
85
+ correlation = covariance / denominator
86
+ # Korelasyonun teorik olarak -1 ile 1 arasında kalmasını sağla (küçük hatalar olabilir)
87
+ return max(-1.0, min(1.0, correlation))
88
+
89
+ # --- NEAT Fitness Fonksiyonu ---
90
+ # (Bu fonksiyon Sürüm 4 için önemli ölçüde güncellendi)
91
+ def eval_genomes(genomes, config):
92
+ """
93
+ Popülasyondaki genomların fitness'ını hesaplar. Fitness, ağın
94
+ P(A=0), P(B=0) ve Corr(A,B) hedeflerini farklı girdilerde
95
+ ne kadar iyi yakaladığına göre belirlenir.
96
+ """
97
+ axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
98
+ test_input_pairs = list(itertools.product(axis_values, repeat=2))
99
+
100
+ for genome_id, genome in genomes:
101
+ genome.fitness = 0.0
102
+ try:
103
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
104
+ except Exception as e:
105
+ logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
106
+ genome.fitness = -20.0 # Daha büyük ceza
107
+ continue
108
+
109
+ total_weighted_error_sum = 0.0
110
+
111
+ for input_pair in test_input_pairs:
112
+ x1, x2 = input_pair
113
+ targ_pA0 = target_PA0(x1, x2)
114
+ targ_pB0 = target_PB0(x1, x2)
115
+ targ_corr = target_Corr(x1, x2)
116
+
117
+ count_A0 = 0
118
+ count_B0 = 0
119
+ count_A0B0 = 0 # Hem A=0 hem B=0 olan durumların sayısı
120
+
121
+ # Denemeleri yap
122
+ for _ in range(NUM_TRIALS_PER_PAIR):
123
+ try:
124
+ output1, output2 = net.activate(input_pair)
125
+ # Çıktıları ikili sonuçlara çevir
126
+ res_A = 1 if output1 >= 0.5 else 0 # A=0 veya A=1
127
+ res_B = 1 if output2 >= 0.5 else 0 # B=0 veya B=1
128
+
129
+ if res_A == 0: count_A0 += 1
130
+ if res_B == 0: count_B0 += 1
131
+ if res_A == 0 and res_B == 0: count_A0B0 += 1
132
+
133
+ except Exception as e:
134
+ logger.warning(f"Genome {genome_id}, Input {input_pair} aktivasyon hatası: {e}")
135
+ # Hata durumunda bu denemeyi geçebiliriz veya penaltı verebiliriz
136
+ pass
137
+
138
+ # Gözlemlenen olasılıkları hesapla
139
+ if NUM_TRIALS_PER_PAIR > 0:
140
+ obs_pA0 = count_A0 / NUM_TRIALS_PER_PAIR
141
+ obs_pB0 = count_B0 / NUM_TRIALS_PER_PAIR
142
+ obs_pA0B0 = count_A0B0 / NUM_TRIALS_PER_PAIR
143
+ else:
144
+ obs_pA0, obs_pB0, obs_pA0B0 = 0.5, 0.5, 0.25 # Varsayılan
145
+
146
+ # Gözlemlenen korelasyonu hesapla
147
+ obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
148
+
149
+ # Hataları hesapla
150
+ error_pA0 = (obs_pA0 - targ_pA0) ** 2
151
+ error_pB0 = (obs_pB0 - targ_pB0) ** 2
152
+ error_corr = (obs_corr - targ_corr) ** 2
153
+
154
+ # Ağırlıklı toplam hatayı hesapla
155
+ weighted_error = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
156
+ total_weighted_error_sum += weighted_error
157
+
158
+ # logger.debug(f" G:{genome_id} In:{input_pair} Tgt:({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f}) Obs:({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f}) Err:{weighted_error:.4f}")
159
+
160
+ # Ortalama ağırlıklı hatayı hesapla
161
+ average_weighted_error = total_weighted_error_sum / len(test_input_pairs)
162
+
163
+ # Fitness (1 - sqrt(AvgError))
164
+ fitness = max(0.0, 1.0 - math.sqrt(average_weighted_error))
165
+ genome.fitness = fitness
166
+ # logger.info(f"Genome {genome_id}: AvgWeightedError = {average_weighted_error:.4f}, Fitness = {fitness:.4f}")
167
+
168
+
169
+ # --- NEAT Çalıştırma Fonksiyonu ---
170
+ def run_neat(config_file):
171
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
172
+ try:
173
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
174
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
175
+ config_file)
176
+ config.fitness_threshold = FITNESS_THRESHOLD
177
+ logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
178
+ except Exception as e:
179
+ logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
180
+ return None
181
+
182
+ logger.info("Yeni popülasyon oluşturuluyor...")
183
+ p = neat.Population(config)
184
+
185
+ # Raporlayıcılar
186
+ p.add_reporter(neat.StdOutReporter(True))
187
+ checkpoint_prefix = 'neat-checkpoint-v4-'
188
+ p.add_reporter(neat.Checkpointer(20, filename_prefix=checkpoint_prefix)) # Daha seyrek checkpoint
189
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
190
+
191
+ logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
192
+ try:
193
+ winner = p.run(eval_genomes, MAX_GENERATIONS)
194
+ logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
195
+ except Exception as e:
196
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
197
+ # Hata durumunda son checkpoint'i yüklemeyi deneyebiliriz (ileriki sürüm?)
198
+ return None # Şimdilik None dönelim
199
+
200
+ # En iyi genomu işle
201
+ if winner:
202
+ logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
203
+ # logger.info(f' {winner}') # Çok uzun olabilir, log dosyasında kalsın
204
+
205
+ # En iyi genomu kaydet
206
+ winner_filename = "winner_genome_v4.pkl"
207
+ try:
208
+ with open(winner_filename, 'wb') as f:
209
+ pickle.dump(winner, f)
210
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
211
+ except Exception as e:
212
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
213
+
214
+ # --- YENİ: En İyi Genomu Korelasyon İçin Detaylı Test Etme ---
215
+ logger.info(" " + "="*25 + " En İyi Genom Detaylı Testi (Korelasyon) " + "="*25)
216
+ try:
217
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
218
+ test_trials_final = 1000 # Final test için daha fazla deneme
219
+ logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
220
+
221
+ final_axis_values = np.linspace(0.0, 1.0, 5) # 5x5 = 25 nokta
222
+ final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
223
+ final_total_weighted_error_sq_sum = 0.0
224
+
225
+ hdr = f"{'Input (x1,x2)': <14} {'Tgt(PA0,PB0,Corr)': <22} {'Obs(PA0,PB0,Corr)': <22} {'Err^2(Comb)': <10}"
226
+ logger.info(hdr)
227
+ logger.info("-" * len(hdr))
228
+
229
+ for input_pair in final_test_pairs:
230
+ x1, x2 = input_pair
231
+ targ_pA0 = target_PA0(x1, x2)
232
+ targ_pB0 = target_PB0(x1, x2)
233
+ targ_corr = target_Corr(x1, x2)
234
+
235
+ count_A0, count_B0, count_A0B0 = 0, 0, 0
236
+ for _ in range(test_trials_final):
237
+ output1, output2 = winner_net.activate(input_pair)
238
+ res_A = 0 if output1 < 0.5 else 1
239
+ res_B = 0 if output2 < 0.5 else 1
240
+ if res_A == 0: count_A0 += 1
241
+ if res_B == 0: count_B0 += 1
242
+ if res_A == 0 and res_B == 0: count_A0B0 += 1
243
+
244
+ obs_pA0 = count_A0 / test_trials_final
245
+ obs_pB0 = count_B0 / test_trials_final
246
+ obs_pA0B0 = count_A0B0 / test_trials_final
247
+ obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
248
+
249
+ error_pA0 = (obs_pA0 - targ_pA0) ** 2
250
+ error_pB0 = (obs_pB0 - targ_pB0) ** 2
251
+ error_corr = (obs_corr - targ_corr) ** 2
252
+ weighted_error_sq = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
253
+ final_total_weighted_error_sq_sum += weighted_error_sq
254
+
255
+ tgt_str = f"({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f})"
256
+ obs_str = f"({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f})"
257
+ logger.info(f"({x1:.2f}, {x2:.2f}) {tgt_str: <22} {obs_str: <22} {weighted_error_sq:<10.5f}")
258
+
259
+ final_avg_weighted_error_sq = final_total_weighted_error_sq_sum / len(final_test_pairs)
260
+ final_rmse_equivalent = math.sqrt(final_avg_weighted_error_sq)
261
+ logger.info("-" * len(hdr))
262
+ logger.info(f"Final Ortalama Ağırlıklı Karesel Hata (MSE ~): {final_avg_weighted_error_sq:.6f}")
263
+ logger.info(f"Final Kök Ort. Karesel Hata (~RMSE): {final_rmse_equivalent:.6f}")
264
+ logger.info(f"Final Fitness Yaklaşımı (1 - ~RMSE): {1.0 - final_rmse_equivalent:.6f}")
265
+ logger.info("-" * len(hdr))
266
+
267
+ except Exception as e:
268
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
269
+ import traceback
270
+ logger.error(traceback.format_exc()) # Hatanın detayını logla
271
+ else:
272
+ logger.warning("Test edilecek bir kazanan genom bulunamadı.")
273
+
274
+ logger.info("="*70)
275
+ logger.info("Quanta Simülatörü Adım 4 (Korelasyonlu Çıktılar) tamamlandı.")
276
+ logger.info("="*70)
277
+ return winner
278
+
279
+
280
+ if __name__ == '__main__':
281
+ local_dir = os.path.dirname(os.path.abspath(__file__)) # Daha sağlam yol bulma
282
+ config_path = os.path.join(local_dir, 'config-feedforward-v4.txt') # <-- V4 Config Dosyası
283
+
284
+ if not os.path.exists(config_path):
285
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
286
+ else:
287
+ run_neat(config_path)
quanta_sim_v5_nonlinear_simple.py ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # quanta_sim_v5_nonlinear_simple.py
2
+
3
+ import neat
4
+ import numpy as np
5
+ import os
6
+ import logging
7
+ import pickle
8
+ import random
9
+ import math
10
+ import datetime
11
+ import itertools
12
+ import traceback # Hata ayıklama için
13
+
14
+ # --- Loglama Ayarları ---
15
+ log_filename = f"quanta_log_v5_nonsimple_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
19
+ handlers=[
20
+ logging.FileHandler(log_filename),
21
+ logging.StreamHandler()
22
+ ]
23
+ )
24
+ logger = logging.getLogger(__name__)
25
+
26
+ logger.info("="*70)
27
+ logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 5 - Non-Linear Hedefler + Basitlik)")
28
+ logger.info(f"Başlangıç Zamanı: {datetime.datetime.now()}")
29
+ logger.info("="*70)
30
+
31
+ # --- Simülasyon Parametreleri ---
32
+ NUM_TEST_VALUES_PER_AXIS = 4 # Değerlendirme için ızgara boyutu (4x4=16 nokta)
33
+ NUM_TRIALS_PER_PAIR = 30 # Her girdi çifti için deneme sayısı
34
+
35
+ MAX_GENERATIONS = 300 # Zor problem için artırılmış nesil sayısı
36
+
37
+ # Fitness fonksiyonundaki hata ağırlıkları
38
+ W_PA0 = 1.0
39
+ W_PB0 = 1.0
40
+ W_CORR = 1.5 # Korelasyon genellikle daha zordur
41
+ TOTAL_WEIGHT = W_PA0 + W_PB0 + W_CORR
42
+
43
+ # Karmaşıklık Cezası Ağırlıkları (Deneme yanılma ile ayarlanabilir!)
44
+ COMPLEXITY_PENALTY_WEIGHT_NODE = 0.001
45
+ COMPLEXITY_PENALTY_WEIGHT_CONN = 0.0005
46
+
47
+ num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2
48
+ total_trials_per_genome = num_test_points * NUM_TRIALS_PER_PAIR
49
+
50
+ logger.info(f"Eksen Başına Test Değeri: {NUM_TEST_VALUES_PER_AXIS} ({num_test_points} test noktası)")
51
+ logger.info(f"Girdi Çifti Başına Deneme: {NUM_TRIALS_PER_PAIR} (Toplam {total_trials_per_genome} deneme/genom)")
52
+ logger.info(f"Maksimum Nesil: {MAX_GENERATIONS}")
53
+ logger.info(f"Fitness Hata Ağırlıkları: P(A0)={W_PA0:.1f}, P(B0)={W_PB0:.1f}, Corr={W_CORR:.1f}")
54
+ logger.info(f"Karmaşıklık Ceza Ağırlıkları: Düğüm={COMPLEXITY_PENALTY_WEIGHT_NODE}, Bağlantı={COMPLEXITY_PENALTY_WEIGHT_CONN}")
55
+
56
+ # --- Doğrusal Olmayan Hedef Fonksiyonları ---
57
+ def target_PA0(x1, x2):
58
+ # P(A=0) hedefi (0.1 ile 0.9 arasında salınır)
59
+ return 0.5 + 0.4 * math.sin(math.pi * x1)
60
+
61
+ def target_PB0(x1, x2):
62
+ # P(B=0) hedefi (0.1 ile 0.9 arasında salınır)
63
+ return 0.5 + 0.4 * math.cos(math.pi * x2)
64
+
65
+ def target_Corr(x1, x2):
66
+ # Hedef Korelasyon (0 ile -0.8 arasında salınır)
67
+ return -0.8 * math.sin(math.pi * x1 * x2)
68
+
69
+ logger.info(f"Hedef P(A=0|x1,x2) = 0.5 + 0.4*sin(pi*x1)")
70
+ logger.info(f"Hedef P(B=0|x1,x2) = 0.5 + 0.4*cos(pi*x2)")
71
+ logger.info(f"Hedef Corr(A,B|x1,x2) = -0.8*sin(pi*x1*x2)")
72
+
73
+ # --- Korelasyon Hesaplama Yardımcı Fonksiyonu ---
74
+ def calculate_correlation(pA0, pB0, pA0B0, epsilon=1e-9):
75
+ pA1 = 1.0 - pA0
76
+ pB1 = 1.0 - pB0
77
+ covariance = pA0B0 - pA0 * pB0
78
+ varA = pA0 * pA1
79
+ varB = pB0 * pB1
80
+ denominator = math.sqrt((varA + epsilon) * (varB + epsilon))
81
+ if denominator < epsilon: return 0.0
82
+ correlation = covariance / denominator
83
+ return max(-1.0, min(1.0, correlation))
84
+
85
+ # --- NEAT Fitness Fonksiyonu ---
86
+ def eval_genomes(genomes, config):
87
+ axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
88
+ test_input_pairs = list(itertools.product(axis_values, repeat=2))
89
+
90
+ for genome_id, genome in genomes:
91
+ genome.fitness = 0.0 # Başlangıç fitness
92
+ try:
93
+ net = neat.nn.FeedForwardNetwork.create(genome, config)
94
+ except Exception as e:
95
+ logger.error(f"Genome {genome_id} ağ oluşturma hatası: {e}")
96
+ genome.fitness = -30.0
97
+ continue
98
+
99
+ total_weighted_error_sum = 0.0
100
+
101
+ # Performans Değerlendirme
102
+ for input_pair in test_input_pairs:
103
+ x1, x2 = input_pair
104
+ targ_pA0 = target_PA0(x1, x2)
105
+ targ_pB0 = target_PB0(x1, x2)
106
+ targ_corr = target_Corr(x1, x2)
107
+
108
+ count_A0, count_B0, count_A0B0 = 0, 0, 0
109
+ for _ in range(NUM_TRIALS_PER_PAIR):
110
+ try:
111
+ output1, output2 = net.activate(input_pair)
112
+ res_A = 0 if output1 < 0.5 else 1
113
+ res_B = 0 if output2 < 0.5 else 1
114
+ if res_A == 0: count_A0 += 1
115
+ if res_B == 0: count_B0 += 1
116
+ if res_A == 0 and res_B == 0: count_A0B0 += 1
117
+ except Exception as e:
118
+ # Aktivasyon hatalarını loglamak çok fazla çıktı üretebilir
119
+ pass
120
+
121
+ # Gözlemlenen değerler
122
+ if NUM_TRIALS_PER_PAIR > 0:
123
+ obs_pA0 = count_A0 / NUM_TRIALS_PER_PAIR
124
+ obs_pB0 = count_B0 / NUM_TRIALS_PER_PAIR
125
+ obs_pA0B0 = count_A0B0 / NUM_TRIALS_PER_PAIR
126
+ else:
127
+ obs_pA0, obs_pB0, obs_pA0B0 = 0.5, 0.5, 0.25
128
+
129
+ obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
130
+
131
+ # Hatalar
132
+ error_pA0 = (obs_pA0 - targ_pA0) ** 2
133
+ error_pB0 = (obs_pB0 - targ_pB0) ** 2
134
+ error_corr = (obs_corr - targ_corr) ** 2
135
+ weighted_error = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
136
+ total_weighted_error_sum += weighted_error
137
+
138
+ # Temel fitness
139
+ average_weighted_error = total_weighted_error_sum / len(test_input_pairs)
140
+ base_fitness = max(0.0, 1.0 - math.sqrt(average_weighted_error))
141
+
142
+ # Karmaşıklık Cezası
143
+ num_nodes = len(genome.nodes)
144
+ num_connections = len(genome.connections)
145
+ complexity_penalty = (COMPLEXITY_PENALTY_WEIGHT_NODE * num_nodes +
146
+ COMPLEXITY_PENALTY_WEIGHT_CONN * num_connections)
147
+
148
+ # Final fitness
149
+ final_fitness = max(0.0, base_fitness - complexity_penalty)
150
+ genome.fitness = final_fitness
151
+
152
+ # --- NEAT Çalıştırma Fonksiyonu ---
153
+ def run_neat(config_file):
154
+ logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
155
+ config = None # Önce None olarak tanımla
156
+ try:
157
+ config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
158
+ neat.DefaultSpeciesSet, neat.DefaultStagnation,
159
+ config_file)
160
+ logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
161
+ except Exception as e:
162
+ logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
163
+ return None
164
+
165
+ logger.info("Yeni popülasyon oluşturuluyor...")
166
+ p = neat.Population(config)
167
+
168
+ # Raporlayıcılar
169
+ p.add_reporter(neat.StdOutReporter(True))
170
+ checkpoint_prefix = 'neat-checkpoint-v5-'
171
+ # Checkpointer her 25 nesilde bir kaydetsin
172
+ p.add_reporter(neat.Checkpointer(25, filename_prefix=checkpoint_prefix))
173
+ logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
174
+
175
+ logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
176
+ winner = None # Önce None olarak tanımla
177
+ try:
178
+ winner = p.run(eval_genomes, MAX_GENERATIONS)
179
+ logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
180
+ except Exception as e:
181
+ logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
182
+ logger.error(traceback.format_exc()) # Tam hata izini logla
183
+ # Hata durumunda bile popülasyonun en iyisini almayı deneyebiliriz (checkpoint yoksa)
184
+ if not winner and p and p.best_genome:
185
+ logger.warning("Evrim hata ile durdu, bulunan son en iyi genom kullanılıyor.")
186
+ winner = p.best_genome
187
+ # return None # Hata durumunda çıkmak yerine devam etmeyi deneyelim
188
+
189
+ # En iyi genomu işle (hata olsa bile 'winner' dolu olabilir)
190
+ if winner:
191
+ logger.info(f'En iyi genom bulundu/kullanıldı (Final Fitness: {winner.fitness:.6f}):')
192
+ num_nodes = len(winner.nodes)
193
+ num_connections = len(winner.connections)
194
+ logger.info(f'Kazanan Karmaşıklığı: {num_nodes} Düğüm, {num_connections} Bağlantı')
195
+
196
+ # En iyi genomu kaydet
197
+ winner_filename = "winner_genome_v5.pkl"
198
+ try:
199
+ with open(winner_filename, 'wb') as f:
200
+ pickle.dump(winner, f)
201
+ logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
202
+ except Exception as e:
203
+ logger.error(f"En iyi genom kaydedilemedi: {e}")
204
+
205
+ # --- Final Test ---
206
+ logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi (Non-Linear) " + "="*20)
207
+ try:
208
+ # Eğer config yüklenmemişse (ilk hatada), testi atla
209
+ if config is None:
210
+ logger.error("Yapılandırma yüklenemediği için final test atlanıyor.")
211
+ raise RuntimeError("Config object is None, cannot create network.")
212
+
213
+ winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
214
+ test_trials_final = 1000 # Final test için deneme sayısı
215
+ logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
216
+
217
+ final_axis_values = np.linspace(0.0, 1.0, 6) # 6x6 = 36 nokta test
218
+ final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
219
+ final_total_weighted_error_sq_sum = 0.0
220
+
221
+ hdr = f"{'Input (x1,x2)': <14} {'Tgt(PA0,PB0,Corr)': <22} {'Obs(PA0,PB0,Corr)': <22} {'Err^2(Comb)': <10}"
222
+ logger.info(hdr)
223
+ logger.info("-" * len(hdr))
224
+
225
+ for input_pair in final_test_pairs:
226
+ x1, x2 = input_pair
227
+ targ_pA0 = target_PA0(x1, x2)
228
+ targ_pB0 = target_PB0(x1, x2)
229
+ targ_corr = target_Corr(x1, x2)
230
+
231
+ count_A0, count_B0, count_A0B0 = 0, 0, 0
232
+ for _ in range(test_trials_final):
233
+ output1, output2 = winner_net.activate(input_pair)
234
+ res_A = 0 if output1 < 0.5 else 1
235
+ res_B = 0 if output2 < 0.5 else 1
236
+ if res_A == 0: count_A0 += 1
237
+ if res_B == 0: count_B0 += 1
238
+ if res_A == 0 and res_B == 0: count_A0B0 += 1
239
+
240
+ obs_pA0 = count_A0 / test_trials_final
241
+ obs_pB0 = count_B0 / test_trials_final
242
+ obs_pA0B0 = count_A0B0 / test_trials_final
243
+ obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
244
+
245
+ error_pA0 = (obs_pA0 - targ_pA0) ** 2
246
+ error_pB0 = (obs_pB0 - targ_pB0) ** 2
247
+ error_corr = (obs_corr - targ_corr) ** 2
248
+ weighted_error_sq = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
249
+ final_total_weighted_error_sq_sum += weighted_error_sq
250
+
251
+ tgt_str = f"({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f})"
252
+ obs_str = f"({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f})"
253
+ logger.info(f"({x1:.2f}, {x2:.2f}) {tgt_str: <22} {obs_str: <22} {weighted_error_sq:<10.5f}")
254
+
255
+ final_avg_weighted_error_sq = final_total_weighted_error_sq_sum / len(final_test_pairs)
256
+ final_rmse_equivalent = math.sqrt(final_avg_weighted_error_sq)
257
+ logger.info("-" * len(hdr))
258
+ logger.info(f"Final Ortalama Ağırlıklı Karesel Hata (MSE ~): {final_avg_weighted_error_sq:.6f}")
259
+ logger.info(f"Final Kök Ort. Karesel Hata (~RMSE): {final_rmse_equivalent:.6f}")
260
+ logger.info(f"Not: Bu RMSE, karmaşıklık cezasını içermez, sadece performans ölçümüdür.")
261
+ logger.info("-" * len(hdr))
262
+
263
+ except Exception as e:
264
+ logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
265
+ logger.error(traceback.format_exc())
266
+ else:
267
+ logger.warning("Evrim sonunda test edilecek bir kazanan genom bulunamadı.")
268
+
269
+ logger.info("="*70)
270
+ logger.info("Quanta Simülatörü Adım 5 (Non-Linear + Basitlik) tamamlandı.")
271
+ logger.info(f"Bitiş Zamanı: {datetime.datetime.now()}")
272
+ logger.info("="*70)
273
+ # return winner # Fonksiyondan bir şey döndürmeye gerek yoksa kaldırılabilir
274
+
275
+
276
+ if __name__ == '__main__':
277
+ # Betiğin bulunduğu dizini al
278
+ local_dir = os.path.dirname(os.path.abspath(__file__))
279
+ # V5 config dosyasının tam yolunu oluştur
280
+ config_path = os.path.join(local_dir, 'config-feedforward-v5.txt')
281
+
282
+ if not os.path.exists(config_path):
283
+ logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
284
+ logger.critical(f"Lütfen '{os.path.basename(config_path)}' dosyasını betikle aynı klasöre koyun.")
285
+ else:
286
+ try:
287
+ run_neat(config_path)
288
+ except Exception as main_e:
289
+ logger.critical(f"Ana program akışında beklenmedik bir hata oluştu: {main_e}")
290
+ logger.error(traceback.format_exc())