github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/experiments/xor/XOR_test.go (about) 1 package xor 2 3 import ( 4 "testing" 5 "time" 6 "os" 7 "fmt" 8 "github.com/yaricom/goNEAT/neat" 9 "github.com/yaricom/goNEAT/neat/genetics" 10 "math/rand" 11 "github.com/yaricom/goNEAT/experiments" 12 ) 13 14 // The integration test running over multiple iterations in order to detect if any random errors occur. 15 func TestXOR(t *testing.T) { 16 // the numbers will be different every time we run. 17 rand.Seed(time.Now().Unix()) 18 19 out_dir_path, context_path, genome_path := "../../out/XOR_test", "../../data/xor.neat", "../../data/xorstartgenes" 20 21 // Load context configuration 22 configFile, err := os.Open(context_path) 23 if err != nil { 24 t.Error("Failed to load context", err) 25 return 26 } 27 context := neat.LoadContext(configFile) 28 neat.LogLevel = neat.LogLevelInfo 29 30 // Load Genome 31 fmt.Println("Loading start genome for XOR experiment") 32 genomeFile, err := os.Open(genome_path) 33 if err != nil { 34 t.Error("Failed to open genome file") 35 return 36 } 37 start_genome, err := genetics.ReadGenome(genomeFile, 1) 38 if err != nil { 39 t.Error("Failed to read start genome") 40 return 41 } 42 43 // Check if output dir exists 44 if _, err := os.Stat(out_dir_path); err == nil { 45 // clear it 46 os.RemoveAll(out_dir_path) 47 } 48 // create output dir 49 err = os.MkdirAll(out_dir_path, os.ModePerm) 50 if err != nil { 51 t.Errorf("Failed to create output directory, reason: %s", err) 52 return 53 } 54 55 // The 100 runs XOR experiment 56 context.NumRuns = 100 57 experiment := experiments.Experiment { 58 Id:0, 59 Trials:make(experiments.Trials, context.NumRuns), 60 } 61 err = experiment.Execute(context, start_genome, XORGenerationEvaluator{OutputPath:out_dir_path}) 62 if err != nil { 63 t.Error("Failed to perform XOR experiment:", err) 64 return 65 } 66 67 // Find winner statistics 68 avg_nodes, avg_genes, avg_evals, _ := experiment.AvgWinner() 69 70 // check results 71 if avg_nodes < 5 { 72 t.Error("avg_nodes < 5", avg_nodes) 73 } else if avg_nodes > 15 { 74 t.Error("avg_nodes > 15", avg_nodes) 75 } 76 77 if avg_genes < 7 { 78 t.Error("avg_genes < 7", avg_genes) 79 } else if avg_genes > 20 { 80 t.Error("avg_genes > 20", avg_genes) 81 } 82 83 max_evals := float64(context.PopSize * context.NumGenerations) 84 if avg_evals > max_evals { 85 t.Error("avg_evals > max_evals", avg_evals, max_evals) 86 } 87 88 t.Logf("avg_nodes: %.1f, avg_genes: %.1f, avg_evals: %.1f\n", avg_nodes, avg_genes, avg_evals) 89 mean_complexity, mean_diversity, mean_age := 0.0, 0.0, 0.0 90 for _, t := range experiment.Trials { 91 mean_complexity += t.BestComplexity().Mean() 92 mean_diversity += t.Diversity().Mean() 93 mean_age += t.BestAge().Mean() 94 } 95 count := float64(len(experiment.Trials)) 96 mean_complexity /= count 97 mean_diversity /= count 98 mean_age /= count 99 t.Logf("Mean best organisms: complexity=%.1f, diversity=%.1f, age=%.1f", mean_complexity, mean_diversity, mean_age) 100 } 101 102 103 // The XOR integration test for disconnected inputs running over multiple iterations in order to detect if any random errors occur. 104 func TestXOR_disconnected(t *testing.T) { 105 // the numbers will be different every time we run. 106 rand.Seed(time.Now().Unix()) 107 108 out_dir_path, context_path, genome_path := "../../out/XOR_disconnected_test", "../../data/xor.neat", "../../data/xordisconnectedstartgenes" 109 110 // Load context configuration 111 configFile, err := os.Open(context_path) 112 if err != nil { 113 t.Error("Failed to load context", err) 114 return 115 } 116 context := neat.LoadContext(configFile) 117 neat.LogLevel = neat.LogLevelInfo 118 119 // Load Genome 120 fmt.Println("Loading start genome for XOR disconnected experiment") 121 genomeFile, err := os.Open(genome_path) 122 if err != nil { 123 t.Error("Failed to open genome file") 124 return 125 } 126 start_genome, err := genetics.ReadGenome(genomeFile, 1) 127 if err != nil { 128 t.Error("Failed to read start genome") 129 return 130 } 131 132 // Check if output dir exists 133 if _, err := os.Stat(out_dir_path); err == nil { 134 // clear it 135 os.RemoveAll(out_dir_path) 136 } 137 // create output dir 138 err = os.MkdirAll(out_dir_path, os.ModePerm) 139 if err != nil { 140 t.Errorf("Failed to create output directory, reason: %s", err) 141 return 142 } 143 144 // The 100 runs XOR experiment 145 context.NumRuns = 40//100 reduce to shorten test time 146 experiment := experiments.Experiment { 147 Id:0, 148 Trials:make(experiments.Trials, context.NumRuns), 149 } 150 err = experiment.Execute(context, start_genome, XORGenerationEvaluator{OutputPath:out_dir_path}) 151 if err != nil { 152 t.Error("Failed to perform XOR experiment:", err) 153 return 154 } 155 156 // Find winner statistics 157 avg_nodes, avg_genes, avg_evals, _ := experiment.AvgWinner() 158 159 // check results 160 if avg_nodes < 5 { 161 t.Error("avg_nodes < 5", avg_nodes) 162 } else if avg_nodes > 15 { 163 t.Error("avg_nodes > 15", avg_nodes) 164 } 165 166 if avg_genes < 7 { 167 t.Error("avg_genes < 7", avg_genes) 168 } else if avg_genes > 20 { 169 t.Error("avg_genes > 20", avg_genes) 170 } 171 172 max_evals := float64(context.PopSize * context.NumGenerations) 173 if avg_evals > max_evals { 174 t.Error("avg_evals > max_evals", avg_evals, max_evals) 175 } 176 177 t.Logf("avg_nodes: %.1f, avg_genes: %.1f, avg_evals: %.1f\n", avg_nodes, avg_genes, avg_evals) 178 mean_complexity, mean_diversity, mean_age := 0.0, 0.0, 0.0 179 for _, t := range experiment.Trials { 180 mean_complexity += t.BestComplexity().Mean() 181 mean_diversity += t.Diversity().Mean() 182 mean_age += t.BestAge().Mean() 183 } 184 count := float64(len(experiment.Trials)) 185 mean_complexity /= count 186 mean_diversity /= count 187 mean_age /= count 188 t.Logf("Mean best organisms: complexity=%.1f, diversity=%.1f, age=%.1f", mean_complexity, mean_diversity, mean_age) 189 }