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  }