github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/genetics/genome.go (about)

     1  package genetics
     2  
     3  import (
     4  	"github.com/yaricom/goNEAT/neat/utils"
     5  	"github.com/yaricom/goNEAT/neat/network"
     6  	"github.com/yaricom/goNEAT/neat"
     7  	"math/rand"
     8  	"io"
     9  	"fmt"
    10  	"errors"
    11  	"math"
    12  	"reflect"
    13  )
    14  
    15  // A Genome is the primary source of genotype information used to create  a phenotype.
    16  // It contains 3 major constituents:
    17  // 	1) A Vector of Traits
    18  // 	2) A List of NNodes pointing to a Trait from (1)
    19  // 	3) A List of Genes with Links that point to Traits from (1)
    20  // 	4) A List of MIMO Control Genes with Links to different genome modules
    21  //
    22  // (1) Reserved parameter space for future use.
    23  // (2) NNode specifications.
    24  // (3) Is the primary source of innovation in the evolutionary Genome.
    25  // (4) Control genes allows to receive inputs from multiple independent genome modules and output processed signal to the
    26  //     multitude of output locations
    27  //
    28  // Each Gene in (3) has a marker telling when it arose historically. Thus, these Genes can be used to speciate the
    29  // population, and the list of Genes provide an evolutionary history of innovation and link-building.
    30  type Genome struct {
    31  	// The genome ID
    32  	Id           int
    33  	// The parameters conglomerations
    34  	Traits       []*neat.Trait
    35  	// List of NNodes for the Network
    36  	Nodes        []*network.NNode
    37  	// List of innovation-tracking genes
    38  	Genes        []*Gene
    39  	// List of MIMO control genes
    40  	ControlGenes []*MIMOControlGene
    41  
    42  	// Allows Genome to be matched with its Network
    43  	Phenotype    *network.Network
    44  }
    45  
    46  // Constructor which takes full genome specs and puts them into the new one
    47  func NewGenome(id int, t []*neat.Trait, n []*network.NNode, g []*Gene) *Genome {
    48  	return &Genome{
    49  		Id:id,
    50  		Traits:t,
    51  		Nodes:n,
    52  		Genes:g,
    53  	}
    54  }
    55  
    56  // Constructs new modular genome
    57  func NewModularGenome(id int, t []*neat.Trait, n []*network.NNode, g []*Gene, mimoG []*MIMOControlGene) *Genome {
    58  	return &Genome{
    59  		Id:id,
    60  		Traits:t,
    61  		Nodes:n,
    62  		Genes:g,
    63  		ControlGenes:mimoG,
    64  	}
    65  }
    66  
    67  // This special constructor creates a Genome with in inputs, out outputs, n out of nmax hidden units, and random
    68  // connectivity.  If rec is true then recurrent connections will be included. The last input is a bias
    69  // link_prob is the probability of a link. The created genome is not modular.
    70  func newGenomeRand(new_id, in, out, n, nmax int, recurrent bool, link_prob float64) *Genome {
    71  	total_nodes := in + out + nmax
    72  	matrix_dim := total_nodes * total_nodes
    73  	// The connection matrix which will be randomized
    74  	cm := make([]bool, matrix_dim)  //Dimension the connection matrix
    75  
    76  	// No nodes above this number for this genome
    77  	max_node := in + n
    78  	first_output := total_nodes - out + 1
    79  
    80  	// For creating the new genes
    81  	var new_node, in_node, out_node *network.NNode
    82  	var new_gene *Gene
    83  	var new_trait *neat.Trait
    84  
    85  	// Create a dummy trait (this is for future expansion of the system)
    86  	new_trait = neat.NewTrait()
    87  	new_trait.Id = 1
    88  	new_trait.Params = make([]float64, neat.Num_trait_params)
    89  
    90  	// Create empty genome
    91  	gnome := Genome{
    92  		Id:new_id,
    93  		Traits:[]*neat.Trait{new_trait},
    94  		Nodes:make([]*network.NNode, 0),
    95  		Genes:make([]*Gene, 0),
    96  	}
    97  
    98  	// Step through the connection matrix, randomly assigning bits
    99  	for count := 0; count < matrix_dim; count++ {
   100  		cm[count] = (rand.Float64() < link_prob)
   101  	}
   102  
   103  	// Build the input nodes
   104  	for ncount := 1; ncount <= in; ncount++ {
   105  		if ncount < in {
   106  			new_node = network.NewNNode(ncount, network.InputNeuron)
   107  		} else {
   108  			new_node = network.NewNNode(ncount, network.BiasNeuron)
   109  		}
   110  		new_node.Trait = new_trait
   111  		gnome.Nodes = append(gnome.Nodes, new_node)
   112  	}
   113  
   114  	// Build the hidden nodes
   115  	for ncount := in + 1; ncount <= in + n; ncount++ {
   116  		new_node = network.NewNNode(ncount, network.HiddenNeuron)
   117  		new_node.Trait = new_trait
   118  		gnome.Nodes = append(gnome.Nodes, new_node)
   119  	}
   120  
   121  	// Build the output nodes
   122  	for ncount := first_output; ncount <= total_nodes; ncount++ {
   123  		new_node = network.NewNNode(ncount, network.OutputNeuron)
   124  		new_node.Trait = new_trait
   125  		gnome.Nodes = append(gnome.Nodes, new_node)
   126  	}
   127  
   128  	//
   129  	//    i i i n n n n n n n n n n n n n n n n . . . . . . . . o o o o
   130  	//    |                                   |                 ^     |
   131  	//    |<----------- max_node ------------>|                 |     |
   132  	//    |                                                     |     |
   133  	//    |<-----------------------total_nodes -----------------|---->|
   134  	//                                                          |
   135  	//                                                          |
   136  	//     first_output ----------------------------------------+
   137  	//
   138  	//
   139  
   140  	// Step through the connection matrix, creating connection genes
   141  	count := 0
   142  	var create_gene, flag_recurrent bool
   143  	for col := 1; col <= total_nodes; col++ {
   144  		for row := 1; row <= total_nodes; row++ {
   145  			// Only try to create a link if it is in the matrix and not leading into a sensor
   146  			if cm[count] && col > in &&
   147  				(col <= max_node || col >= first_output) &&
   148  				(row <= max_node || row >= first_output) {
   149  
   150  				// If it's recurrent, create the connection (gene) no matter what
   151  				create_gene = true
   152  				if col > row {
   153  					flag_recurrent = false
   154  				} else {
   155  					flag_recurrent = true
   156  					if !recurrent {
   157  						// skip recurrent connections
   158  						create_gene = false
   159  					}
   160  				}
   161  
   162  				// Introduce new connection (gene) into genome
   163  				if create_gene {
   164  					// Retrieve in_node and out_node
   165  					for i := 0; i < len(gnome.Nodes) && (in_node == nil || out_node == nil); i++ {
   166  						node_id := gnome.Nodes[i].Id
   167  						if node_id == row {
   168  							in_node = gnome.Nodes[i]
   169  						}
   170  						if node_id == col {
   171  							out_node = gnome.Nodes[i]
   172  						}
   173  					}
   174  
   175  					// Create the gene
   176  					new_weight := float64(utils.RandSign()) * rand.Float64()
   177  					new_gene = NewGeneWithTrait(new_trait, new_weight, in_node, out_node, flag_recurrent, int64(count), new_weight)
   178  
   179  					//Add the gene to the genome
   180  					gnome.Genes = append(gnome.Genes, new_gene)
   181  				}
   182  
   183  			}
   184  
   185  			count++ //increment counter
   186  			// reset nodes
   187  			in_node, out_node = nil, nil
   188  		}
   189  	}
   190  	return &gnome
   191  }
   192  
   193  // Reads Genome from reader
   194  func ReadGenome(ir io.Reader, id int) (*Genome, error) {
   195  	// stub for backward compatibility
   196  	// the new implementations should use GenomeReader to decode genome data in variety of formats
   197  	r, err := NewGenomeReader(ir, PlainGenomeEncoding)
   198  	if err != nil {
   199  		return nil, err
   200  	}
   201  	gnome, err := r.Read()
   202  	return gnome, err
   203  }
   204  
   205  // Writes this genome into provided writer
   206  func (g *Genome) Write(w io.Writer) error {
   207  	// stub for backward compatibility
   208  	// the new implementations should use GenomeWriter to decode genome data in variety of formats
   209  	wr, err := NewGenomeWriter(w, PlainGenomeEncoding)
   210  	if err == nil {
   211  		err = wr.WriteGenome(g)
   212  	}
   213  
   214  	return err
   215  }
   216  
   217  // Stringer
   218  func (g *Genome) String() string {
   219  	str := "GENOME START\nNodes:\n"
   220  	for _, n := range g.Nodes {
   221  		n_type := ""
   222  		switch n.NeuronType {
   223  		case network.InputNeuron:
   224  			n_type = "I"
   225  		case network.OutputNeuron:
   226  			n_type = "O"
   227  		case network.BiasNeuron:
   228  			n_type = "B"
   229  		case network.HiddenNeuron:
   230  			n_type = "H"
   231  		}
   232  		str += fmt.Sprintf("\t%s%s \n", n_type, n)
   233  	}
   234  	str += "Genes:\n"
   235  	for _, gn := range g.Genes {
   236  		str += fmt.Sprintf("\t%s\n", gn)
   237  	}
   238  	str += "Traits:\n"
   239  	for _, t := range g.Traits {
   240  		str += fmt.Sprintf("\t%s\n", t)
   241  	}
   242  	str += "GENOME END"
   243  	return str
   244  }
   245  
   246  // Return # of non-disabled genes
   247  func (g *Genome) Extrons() int {
   248  	total := 0
   249  	for _, gene := range g.Genes {
   250  		if gene.IsEnabled {
   251  			total++
   252  		}
   253  	}
   254  	return total
   255  }
   256  
   257  // Tests if given genome is equal to this one genetically and phenotypically. This method will check that both genomes has the same traits, nodes and genes.
   258  // If mismatch detected the error will be returned with mismatch details.
   259  func (g *Genome) IsEqual(og *Genome) (bool, error) {
   260  	if len(g.Traits) != len(og.Traits) {
   261  		return false, errors.New(fmt.Sprintf("traits count mismatch: %d != %d",
   262  			len(g.Traits), len(og.Traits)))
   263  	}
   264  	for i, tr := range og.Traits {
   265  		if !reflect.DeepEqual(tr, g.Traits[i]) {
   266  			return false, errors.New(
   267  				fmt.Sprintf("traits mismatch, expected: %s, but found: %s", tr, g.Traits[i]))
   268  		}
   269  	}
   270  
   271  	if len(g.Nodes) != len(og.Nodes) {
   272  		return false, errors.New(fmt.Sprintf("nodes count mismatch: %d != %d",
   273  			len(g.Nodes), len(og.Nodes)))
   274  	}
   275  	for i, nd := range og.Nodes {
   276  		if !reflect.DeepEqual(nd, g.Nodes[i]) {
   277  			return false, errors.New(
   278  				fmt.Sprintf("node mismatch, expected: %s\nfound: %s", nd, g.Nodes[i]))
   279  		}
   280  	}
   281  
   282  	if len(g.Genes) != len(og.Genes) {
   283  		return false, errors.New(fmt.Sprintf("genes count mismatch: %d != %d",
   284  			len(g.Genes), len(og.Genes)))
   285  	}
   286  	for i, gen := range og.Genes {
   287  		if !reflect.DeepEqual(gen, g.Genes[i]) {
   288  			return false, errors.New(
   289  				fmt.Sprintf("gene mismatch, expected: %s\nfound: %s", gen, g.Genes[i]))
   290  		}
   291  	}
   292  
   293  	if len(g.ControlGenes) != len(og.ControlGenes) {
   294  		return false, errors.New(fmt.Sprintf("control genes count mismatch: %d != %d",
   295  			len(g.ControlGenes), len(og.ControlGenes)))
   296  	}
   297  	for i, cg := range og.ControlGenes {
   298  		if !reflect.DeepEqual(cg, g.ControlGenes[i]) {
   299  			return false, errors.New(
   300  				fmt.Sprintf("control gene mismatch, expected: %s\nfound: %s", cg, g.ControlGenes[i]))
   301  		}
   302  	}
   303  
   304  	return true, nil
   305  }
   306  
   307  // Return id of final NNode in Genome
   308  func (g *Genome) getLastNodeId() (int, error) {
   309  	if len(g.Nodes) == 0 {
   310  		return -1, errors.New("Genome has no nodes")
   311  	}
   312  	id := g.Nodes[len(g.Nodes) - 1].Id
   313  	// check control genes
   314  	for _, cg := range g.ControlGenes {
   315  		if cg.ControlNode.Id > id {
   316  			id = cg.ControlNode.Id
   317  		}
   318  	}
   319  	return id, nil
   320  }
   321  
   322  // Return innovation number of last gene in Genome + 1
   323  func (g *Genome) getNextGeneInnovNum() (int64, error) {
   324  	inn_num := int64(0)
   325  	// check connection genes
   326  	if len(g.Genes) > 0 {
   327  		inn_num = g.Genes[len(g.Genes) - 1].InnovationNum
   328  	} else {
   329  		return -1, errors.New("Genome has no Genes")
   330  	}
   331  	// check control genes if any
   332  	if len(g.ControlGenes) > 0 {
   333  		c_inn_num := g.ControlGenes[len(g.ControlGenes) - 1].InnovationNum
   334  		if c_inn_num > inn_num {
   335  			inn_num = c_inn_num
   336  		}
   337  	}
   338  	return inn_num + int64(1), nil
   339  }
   340  
   341  // Returns true if this Genome already includes provided node
   342  func (g *Genome) hasNode(node *network.NNode) bool {
   343  	if id, _ := g.getLastNodeId(); node.Id > id {
   344  		return false // not found
   345  	}
   346  	for _, n := range g.Nodes {
   347  		if n.Id == node.Id {
   348  			return true
   349  		}
   350  	}
   351  	return false
   352  }
   353  
   354  // Returns true if this Genome already includes provided gene
   355  func (g *Genome) hasGene(gene *Gene) bool {
   356  	if inn, _ := g.getNextGeneInnovNum(); gene.InnovationNum >= inn {
   357  		return false
   358  	}
   359  
   360  	// Find genetically equal link in this genome to the provided gene
   361  	for _, g := range g.Genes {
   362  		if g.Link.IsEqualGenetically(gene.Link) {
   363  			return true
   364  		}
   365  	}
   366  	return false
   367  }
   368  
   369  // Generate a Network phenotype from this Genome with specified id
   370  func (g *Genome) Genesis(net_id int) (*network.Network, error) {
   371  	// Inputs and outputs will be collected here for the network.
   372  	// All nodes are collected in an all_list -
   373  	// this is useful for network traversing routines
   374  	in_list := make([]*network.NNode, 0)
   375  	out_list := make([]*network.NNode, 0)
   376  	all_list := make([]*network.NNode, 0)
   377  
   378  	var new_node *network.NNode
   379  	// Create the network nodes
   380  	for _, n := range g.Nodes {
   381  		new_node = network.NewNNodeCopy(n, n.Trait)
   382  
   383  		// Check for input or output designation of node
   384  		if n.NeuronType == network.InputNeuron || n.NeuronType == network.BiasNeuron {
   385  			in_list = append(in_list, new_node)
   386  		} else if n.NeuronType == network.OutputNeuron {
   387  			out_list = append(out_list, new_node)
   388  		}
   389  
   390  		// Keep track of all nodes in one place for convenience
   391  		all_list = append(all_list, new_node)
   392  
   393  		// Have the node specifier point to the node it generated
   394  		n.PhenotypeAnalogue = new_node
   395  	}
   396  
   397  	if len(g.Genes) == 0 {
   398  		return nil, errors.New("The network built whitout GENES; the result can be unpredictable")
   399  	}
   400  
   401  	if len(out_list) == 0 {
   402  		return nil, errors.New(fmt.Sprintf("The network whitout OUTPUTS; the result can be unpredictable. Genome: %s", g))
   403  	}
   404  
   405  	var in_node, out_node *network.NNode
   406  	var cur_link, new_link *network.Link
   407  	// Create the links by iterating through the genes
   408  	for _, gn := range g.Genes {
   409  		// Only create the link if the gene is enabled
   410  		if gn.IsEnabled {
   411  			cur_link = gn.Link
   412  			in_node = cur_link.InNode.PhenotypeAnalogue
   413  			out_node = cur_link.OutNode.PhenotypeAnalogue
   414  
   415  			// NOTE: This line could be run through a recurrency check if desired
   416  			// (no need to in the current implementation of NEAT)
   417  			new_link = network.NewLinkWithTrait(cur_link.Trait, cur_link.Weight, in_node, out_node, cur_link.IsRecurrent)
   418  
   419  			// Add link to the connected nodes
   420  			out_node.Incoming = append(out_node.Incoming, new_link)
   421  			in_node.Outgoing = append(in_node.Outgoing, new_link)
   422  		}
   423  	}
   424  
   425  	var new_net *network.Network
   426  	if len(g.ControlGenes) == 0 {
   427  		// Create the new network
   428  		new_net = network.NewNetwork(in_list, out_list, all_list, net_id)
   429  	} else {
   430  		// Create MIMO control genes
   431  		c_nodes := make([]*network.NNode, 0)
   432  		for _, cg := range g.ControlGenes {
   433  			// Only process enabled genes
   434  			if cg.IsEnabled {
   435  				new_c_node := network.NewNNodeCopy(cg.ControlNode, cg.ControlNode.Trait)
   436  
   437  				// connect inputs
   438  				for _, l := range cg.ControlNode.Incoming {
   439  					in_node = l.InNode.PhenotypeAnalogue
   440  					out_node = new_c_node
   441  					new_link = network.NewLink(l.Weight, in_node, out_node, false)
   442  					// only incoming to control node
   443  					out_node.Incoming = append(out_node.Incoming, new_link)
   444  				}
   445  
   446  				// connect outputs
   447  				for _, l := range cg.ControlNode.Outgoing {
   448  					in_node = new_c_node
   449  					out_node = l.OutNode.PhenotypeAnalogue
   450  					new_link = network.NewLink(l.Weight, in_node, out_node, false)
   451  					// only outgoing from control node
   452  					in_node.Outgoing = append(in_node.Outgoing, new_link)
   453  				}
   454  
   455  				// store control node
   456  				c_nodes = append(c_nodes, new_c_node)
   457  			}
   458  		}
   459  		new_net = network.NewModularNetwork(in_list, out_list, all_list, c_nodes, net_id)
   460  	}
   461  
   462  	// Attach genotype and phenotype together:
   463  	// genotype points to owner phenotype (new_net)
   464  	g.Phenotype = new_net
   465  
   466  	return new_net, nil
   467  }
   468  
   469  // Duplicate this Genome to create a new one with the specified id
   470  func (g *Genome) duplicate(new_id int) (*Genome, error) {
   471  
   472  	// Duplicate the traits
   473  	traits_dup := make([]*neat.Trait, 0)
   474  	for _, tr := range g.Traits {
   475  		new_trait := neat.NewTraitCopy(tr)
   476  		traits_dup = append(traits_dup, new_trait)
   477  	}
   478  
   479  	// Duplicate NNodes
   480  	nodes_dup := make([]*network.NNode, 0)
   481  	for _, nd := range g.Nodes {
   482  		// First, find the duplicate of the trait that this node points to
   483  		assoc_trait := nd.Trait
   484  		if assoc_trait != nil {
   485  			assoc_trait = traitWithId(assoc_trait.Id, traits_dup)
   486  		}
   487  		new_node := network.NewNNodeCopy(nd, assoc_trait)
   488  
   489  		nodes_dup = append(nodes_dup, new_node)
   490  	}
   491  
   492  	// Duplicate Genes
   493  	genes_dup := make([]*Gene, 0)
   494  	for _, gn := range g.Genes {
   495  		// First find the nodes connected by the gene's link
   496  		in_node := nodeWithId(gn.Link.InNode.Id, nodes_dup)
   497  		if in_node == nil {
   498  			return nil, errors.New(
   499  				fmt.Sprintf("incoming node: %d not found for gene %s",
   500  					gn.Link.InNode.Id, gn.String()))
   501  		}
   502  		out_node := nodeWithId(gn.Link.OutNode.Id, nodes_dup)
   503  		if out_node == nil {
   504  			return nil, errors.New(
   505  				fmt.Sprintf("outgoing node: %d not found for gene %s",
   506  					gn.Link.OutNode.Id, gn.String()))
   507  		}
   508  
   509  		// Find the duplicate of trait associated with this gene
   510  		assoc_trait := gn.Link.Trait
   511  		if assoc_trait != nil {
   512  			assoc_trait = traitWithId(assoc_trait.Id, traits_dup)
   513  		}
   514  
   515  		new_gene := NewGeneCopy(gn, assoc_trait, in_node, out_node)
   516  		genes_dup = append(genes_dup, new_gene)
   517  	}
   518  
   519  	if len(g.ControlGenes) == 0 {
   520  		// If no MIMO control genes return plain genome
   521  		return NewGenome(new_id, traits_dup, nodes_dup, genes_dup), nil
   522  	} else {
   523  		// Duplicate MIMO Control Genes and build modular genome
   524  		control_genes_dup := make([]*MIMOControlGene, 0)
   525  		for _, cg := range g.ControlGenes {
   526  			// duplicate control node
   527  			c_node := cg.ControlNode
   528  			// find duplicate of trait associated with control node
   529  			assoc_trait := c_node.Trait
   530  			if assoc_trait != nil {
   531  				assoc_trait = traitWithId(assoc_trait.Id, traits_dup)
   532  			}
   533  			new_c_node := network.NewNNodeCopy(c_node, assoc_trait)
   534  			// add incoming links
   535  			for _, l := range c_node.Incoming {
   536  				in_node := nodeWithId(l.InNode.Id, nodes_dup)
   537  				if in_node == nil {
   538  					return nil, errors.New(
   539  						fmt.Sprintf("incoming node: %d not found for control node: %d",
   540  							l.InNode.Id, c_node.Id))
   541  				}
   542  				new_in_link := network.NewLinkCopy(l, in_node, new_c_node)
   543  				new_c_node.Incoming = append(new_c_node.Incoming, new_in_link)
   544  			}
   545  
   546  			// add outgoing links
   547  			for _, l := range c_node.Outgoing {
   548  				out_node := nodeWithId(l.OutNode.Id, nodes_dup)
   549  				if out_node == nil {
   550  					return nil, errors.New(
   551  						fmt.Sprintf("outgoing node: %d not found for control node: %d",
   552  							l.InNode.Id, c_node.Id))
   553  				}
   554  				new_out_link := network.NewLinkCopy(l, new_c_node, out_node)
   555  				new_c_node.Outgoing = append(new_c_node.Outgoing, new_out_link)
   556  			}
   557  
   558  			// add MIMO control gene
   559  			new_cg := NewMIMOGeneCopy(cg, new_c_node)
   560  			control_genes_dup = append(control_genes_dup, new_cg)
   561  		}
   562  
   563  		return NewModularGenome(new_id, traits_dup, nodes_dup, genes_dup, control_genes_dup), nil
   564  	}
   565  }
   566  
   567  // For debugging: A number of tests can be run on a genome to check its integrity.
   568  // Note: Some of these tests do not indicate a bug, but rather are meant to be used to detect specific system states.
   569  func (g *Genome) verify() (bool, error) {
   570  	if len(g.Genes) == 0 {
   571  		return false, errors.New("Genome has no Genes")
   572  	}
   573  	if len(g.Nodes) == 0 {
   574  		return false, errors.New("Genome has no Nodes")
   575  	}
   576  	if len(g.Traits) == 0 {
   577  		return false, errors.New("Genome has no Traits")
   578  	}
   579  
   580  
   581  	// Check each gene's nodes
   582  	for _, gn := range g.Genes {
   583  		inode := gn.Link.InNode
   584  		onode := gn.Link.OutNode
   585  		i_found, o_found := false, false
   586  		for i := 0; i < len(g.Nodes) && (!i_found || !o_found); i++ {
   587  			if inode.Id == g.Nodes[i].Id {
   588  				i_found = true
   589  			}
   590  			if onode.Id == g.Nodes[i].Id {
   591  				o_found = true
   592  			}
   593  		}
   594  
   595  		// check results
   596  		if !i_found {
   597  			return false, errors.New("Missing input node of gene in the genome nodes")
   598  		}
   599  		if !o_found {
   600  			return false, errors.New("Missing output node of gene in the genome nodes")
   601  		}
   602  	}
   603  
   604  	// Check for NNodes being out of order
   605  	last_id := 0
   606  	for _, n := range g.Nodes {
   607  		if n.Id < last_id {
   608  			return false, errors.New("Nodes out of order in genome")
   609  		}
   610  		last_id = n.Id
   611  	}
   612  
   613  	// Make sure there are no duplicate genes
   614  	for _, gn := range g.Genes {
   615  		for _, gn2 := range g.Genes {
   616  			if gn != gn2 && gn.Link.IsEqualGenetically(gn2.Link) {
   617  				return false, errors.New(fmt.Sprintf("Duplicate genes found. %s == %s", gn, gn2))
   618  			}
   619  		}
   620  	}
   621  	// Check for 2 disables in a row
   622  	// Note: Again, this is not necessarily a bad sign
   623  	if len(g.Nodes) > 500 {
   624  		disab := false
   625  		for _, gn := range g.Genes {
   626  			if gn.IsEnabled == false && disab {
   627  				return false, errors.New("Two gene disables in a row")
   628  			}
   629  			disab = !gn.IsEnabled
   630  		}
   631  	}
   632  	return true, nil
   633  }
   634  
   635  // Inserts a NNode into a given ordered list of NNodes in ascending order by NNode ID
   636  func nodeInsert(nodes[]*network.NNode, n *network.NNode) []*network.NNode {
   637  	index := len(nodes)
   638  	// quick insert at the end or beginning (we assume that nodes is already ordered)
   639  	if index == 0 || n.Id >= nodes[index - 1].Id {
   640  		// append last
   641  		nodes = append(nodes, n)
   642  		return nodes
   643  	} else if n.Id <= nodes[0].Id {
   644  		// insert first
   645  		index = 0
   646  	}
   647  	// find split index
   648  	for i := index - 1; i >= 0; i-- {
   649  		if n.Id == nodes[i].Id {
   650  			index = i
   651  			break
   652  		} else if n.Id > nodes[i].Id {
   653  			index = i + 1 // previous
   654  			break
   655  		}
   656  	}
   657  	first := make([]*network.NNode, index + 1)
   658  	copy(first, nodes[0:index])
   659  	first[index] = n
   660  	second := nodes[index:]
   661  
   662  	nodes = append(first, second...)
   663  	return nodes
   664  }
   665  
   666  // Inserts a new gene that has been created through a mutation in the
   667  // *correct order* into the list of genes in the genome, i.e. ordered by innovation number ascending
   668  func geneInsert(genes[]*Gene, g *Gene) []*Gene {
   669  	index := len(genes) // to make sure that greater IDs appended at the end
   670  	// quick insert at the end or beginning (we assume that nodes is already ordered)
   671  	if index == 0 || g.InnovationNum >= genes[index - 1].InnovationNum {
   672  		// append last
   673  		genes = append(genes, g)
   674  		return genes
   675  	} else if g.InnovationNum <= genes[0].InnovationNum {
   676  		// insert first
   677  		index = 0
   678  	}
   679  	// find split index
   680  	for i := index - 1; i >= 0; i-- {
   681  		if g.InnovationNum == genes[i].InnovationNum {
   682  			index = i
   683  			break
   684  		} else if g.InnovationNum > genes[i].InnovationNum {
   685  			index = i + 1 // previous
   686  			break
   687  		}
   688  	}
   689  
   690  	first := make([]*Gene, index + 1)
   691  	copy(first, genes[0:index])
   692  	first[index] = g
   693  	second := genes[index:]
   694  	genes = append(first, second...)
   695  	return genes
   696  
   697  }
   698  
   699  /* ******* MUTATORS ******* */
   700  
   701  // Mutate the genome by adding connections to disconnected sensors (input, bias type neurons).
   702  // The reason this mutator is important is that if we can start NEAT with some inputs disconnected,
   703  // then we can allow NEAT to decide which inputs are important.
   704  // This process has two good effects:
   705  // 	(1) You can start minimally even in problems with many inputs and
   706  // 	(2) you don't need to know a priori what the important features of the domain are.
   707  // If all sensors already connected than do nothing.
   708  func (g *Genome) mutateConnectSensors(pop *Population, context *neat.NeatContext) (bool, error) {
   709  
   710  	if len(g.Genes) == 0 {
   711  		return false, errors.New("Genome has no genes")
   712  	}
   713  
   714  	// Find all the sensors and outputs
   715  	sensors := make([]*network.NNode, 0)
   716  	outputs := make([]*network.NNode, 0)
   717  	for _, n := range g.Nodes {
   718  		if n.IsSensor() {
   719  			sensors = append(sensors, n)
   720  		} else {
   721  			outputs = append(outputs, n)
   722  		}
   723  	}
   724  
   725  	// Find not connected sensors if any
   726  	disconnected_sensors := make([]*network.NNode, 0)
   727  	for _, sensor := range sensors {
   728  		connected := false
   729  
   730  		// iterate over all genes and count number of output connections from given sensor
   731  		for _, gene := range g.Genes {
   732  			if gene.Link.InNode.Id == sensor.Id {
   733  				connected = true
   734  				break
   735  			}
   736  		}
   737  
   738  		if !connected {
   739  			// store found disconnected sensor
   740  			disconnected_sensors = append(disconnected_sensors, sensor)
   741  		}
   742  	}
   743  
   744  	// if all sensors are connected - stop
   745  	if len(disconnected_sensors) == 0 {
   746  		return false, nil
   747  	}
   748  
   749  	// pick randomly from disconnected sensors
   750  	sensor := disconnected_sensors[rand.Intn(len(disconnected_sensors))]
   751  	// add new links to chosen sensor, avoiding redundancy
   752  	link_added := false
   753  	for _, output := range outputs {
   754  		found := false
   755  		for _, gene := range g.Genes {
   756  			if gene.Link.InNode == sensor && gene.Link.OutNode == output {
   757  				found = true
   758  				break
   759  			}
   760  		}
   761  
   762  		if !found {
   763  			var new_gene *Gene
   764  			// Check to see if this innovation already occurred in the population
   765  			innovation_found := false
   766  			for _, inn := range pop.Innovations {
   767  				if inn.innovationType == newLinkInnType &&
   768  					inn.InNodeId == sensor.Id &&
   769  					inn.OutNodeId == output.Id &&
   770  					inn.IsRecurrent == false {
   771  
   772  					new_gene = NewGeneWithTrait(g.Traits[inn.NewTraitNum], inn.NewWeight,
   773  						sensor, output, false, inn.InnovationNum, 0)
   774  
   775  					innovation_found = true
   776  					break
   777  				}
   778  			}
   779  
   780  			// The innovation is totally novel
   781  			if !innovation_found {
   782  				// Choose a random trait
   783  				trait_num := rand.Intn(len(g.Traits))
   784  				// Choose the new weight
   785  				new_weight := float64(utils.RandSign()) * rand.Float64() * 10.0
   786  				// read next innovation id
   787  				next_innov_id := pop.getNextInnovationNumberAndIncrement()
   788  
   789  
   790  				// Create the new gene
   791  				new_gene = NewGeneWithTrait(g.Traits[trait_num], new_weight, sensor, output,
   792  					false, next_innov_id, new_weight)
   793  
   794  				// Add the innovation for created link
   795  				new_innov := NewInnovationForLink(sensor.Id, output.Id, next_innov_id,
   796  					new_weight, trait_num)
   797  				pop.addInnovationSynced(new_innov)
   798  			} else if g.hasGene(new_gene) {
   799  				// The gene for already occurred innovation already in this genome.
   800  				// This may happen as result of parent genome mutation in current epoch which is
   801  				// repeated in the child after parent's genome transferred to child during mating
   802  				neat.InfoLog(
   803  					fmt.Sprintf("GENOME: Connect sensors innovation found [%t] in the same genome [%d] for gene: %s\n%s",
   804  						innovation_found, g.Id, new_gene, g))
   805  				return false, nil
   806  			}
   807  
   808  			// Now add the new Gene to the Genome
   809  			g.Genes = geneInsert(g.Genes, new_gene)
   810  			link_added = true
   811  		}
   812  	}
   813  	return link_added, nil
   814  }
   815  
   816  // Mutate the genome by adding a new link between two random NNodes,
   817  // if NNodes are already connected, keep trying conf.NewLinkTries times
   818  func (g *Genome) mutateAddLink(pop *Population, context *neat.NeatContext) (bool, error) {
   819  	// If the phenotype does not exist, exit on false, print error
   820  	// Note: This should never happen - if it does there is a bug
   821  	if g.Phenotype == nil {
   822  		return false, errors.New("Attempt to add link to genome with no phenotype")
   823  	} else if len(g.Nodes) == 0 {
   824  		return false, errors.New("Genome has no nodes to be connected by new link")
   825  	}
   826  
   827  	nodes_len := len(g.Nodes)
   828  
   829  	// Decide whether to make link recurrent
   830  	do_recur := false
   831  	if rand.Float64() < context.RecurOnlyProb {
   832  		do_recur = true
   833  	}
   834  
   835  	// Find the first non-sensor so that the to-node won't look at sensors as possible destinations
   836  	first_non_sensor := 0
   837  	for _, n := range g.Nodes {
   838  		if n.IsSensor() {
   839  			first_non_sensor++
   840  		} else {
   841  			break
   842  		}
   843  	}
   844  
   845  	// Made attempts to find an unconnected pair
   846  	try_count := 0
   847  
   848  	// Iterate over nodes and try to add new link
   849  	var node_1, node_2 *network.NNode
   850  	found := false
   851  	for try_count < context.NewLinkTries {
   852  		node_num_1, node_num_2 := 0, 0
   853  		if do_recur {
   854  			// 50% of prob to decide create a recurrent link (node X to node X)
   855  			// 50% of a normal link (node X to node Y)
   856  			loop_recur := false
   857  			if rand.Float64() > 0.5 {
   858  				loop_recur = true
   859  			}
   860  			if loop_recur {
   861  				node_num_1 = first_non_sensor + rand.Intn(nodes_len - first_non_sensor) // only NON SENSOR
   862  				node_num_2 = node_num_1
   863  			} else {
   864  				for node_num_1 == node_num_2 {
   865  					node_num_1 = rand.Intn(nodes_len)
   866  					node_num_2 = first_non_sensor + rand.Intn(nodes_len - first_non_sensor) // only NON SENSOR
   867  				}
   868  			}
   869  		} else {
   870  			for node_num_1 == node_num_2 {
   871  				node_num_1 = rand.Intn(nodes_len)
   872  				node_num_2 = first_non_sensor + rand.Intn(nodes_len - first_non_sensor) // only NON SENSOR
   873  			}
   874  		}
   875  
   876  		// get corresponding nodes
   877  		node_1 = g.Nodes[node_num_1]
   878  		node_2 = g.Nodes[node_num_2]
   879  
   880  		// See if a link already exists  ALSO STOP AT END OF GENES!!!!
   881  		link_exists := false
   882  		if node_2.IsSensor() {
   883  			// Don't allow SENSORS to get input
   884  			link_exists = true
   885  		} else {
   886  			for _, gene := range g.Genes {
   887  				if gene.Link.InNode.Id == node_1.Id &&
   888  					gene.Link.OutNode.Id == node_2.Id &&
   889  					gene.Link.IsRecurrent == do_recur {
   890  					// link already exists
   891  					link_exists = true;
   892  					break;
   893  				}
   894  
   895  			}
   896  		}
   897  
   898  		if !link_exists {
   899  			// These are used to avoid getting stuck in an infinite loop checking for recursion
   900  			// Note that we check for recursion to control the frequency of adding recurrent links rather
   901  			// than to prevent any particular kind of error
   902  			thresh := nodes_len * nodes_len
   903  			count := 0
   904  			recur_flag := g.Phenotype.IsRecurrent(node_1.PhenotypeAnalogue, node_2.PhenotypeAnalogue, &count, thresh)
   905  
   906  			// NOTE: A loop doesn't really matter - just debug output it
   907  			if count > thresh {
   908  				neat.DebugLog(
   909  					fmt.Sprintf("GENOME: LOOP DETECTED DURING A RECURRENCY CHECK -> " +
   910  						"node in: %s <-> node out: %s", node_1.PhenotypeAnalogue, node_2.PhenotypeAnalogue))
   911  			}
   912  
   913  			// Make sure it finds the right kind of link (recurrent or not)
   914  			if (!recur_flag && do_recur) || (recur_flag && !do_recur) {
   915  				try_count++
   916  			} else {
   917  				// The open link found
   918  				try_count = context.NewLinkTries
   919  				found = true
   920  			}
   921  		} else {
   922  			try_count++
   923  		}
   924  
   925  	}
   926  	// Continue only if an open link was found
   927  	if found {
   928  		var new_gene *Gene
   929  		// Check to see if this innovation already occurred in the population
   930  		innovation_found := false
   931  		for _, inn := range pop.Innovations {
   932  			// match the innovation in the innovations list
   933  			if inn.innovationType == newLinkInnType &&
   934  				inn.InNodeId == node_1.Id &&
   935  				inn.OutNodeId == node_2.Id &&
   936  				inn.IsRecurrent == do_recur {
   937  
   938  				// Create new gene
   939  				new_gene = NewGeneWithTrait(g.Traits[inn.NewTraitNum], inn.NewWeight, node_1, node_2, do_recur, inn.InnovationNum, 0)
   940  
   941  				innovation_found = true
   942  				break
   943  			}
   944  		}
   945  		// The innovation is totally novel
   946  		if !innovation_found {
   947  			// Choose a random trait
   948  			trait_num := rand.Intn(len(g.Traits))
   949  			// Choose the new weight
   950  			new_weight := float64(utils.RandSign()) * rand.Float64() * 10.0
   951  			// read next innovation id
   952  			next_innov_id := pop.getNextInnovationNumberAndIncrement()
   953  
   954  			// Create the new gene
   955  			new_gene = NewGeneWithTrait(g.Traits[trait_num], new_weight, node_1, node_2,
   956  				do_recur, next_innov_id, new_weight)
   957  
   958  			// Add the innovation
   959  			new_innov := NewInnovationForRecurrentLink(node_1.Id, node_2.Id, next_innov_id,
   960  				new_weight, trait_num, do_recur)
   961  			pop.addInnovationSynced(new_innov)
   962  		} else if g.hasGene(new_gene) {
   963  			// The gene for already occurred innovation already in this genome.
   964  			// This may happen as result of parent genome mutation in current epoch which is
   965  			// repeated in the child after parent's genome transferred to child during mating
   966  			neat.InfoLog(
   967  				fmt.Sprintf("GENOME: Mutate add link innovation found [%t] in the same genome [%d] for gene: %s\n%s",
   968  					innovation_found, g.Id, new_gene, g))
   969  			return false, nil
   970  		}
   971  
   972  		// sanity check
   973  		if new_gene.Link.InNode.Id == new_gene.Link.OutNode.Id && !do_recur {
   974  			neat.DebugLog(fmt.Sprintf("Recurent link created when recurency is not enabled: %s", new_gene))
   975  			return false, errors.New(fmt.Sprintf("GENOME: Wrong gene created!\n%s", g))
   976  		}
   977  
   978  		// Now add the new Gene to the Genome
   979  		g.Genes = geneInsert(g.Genes, new_gene)
   980  	}
   981  
   982  	return found, nil
   983  }
   984  
   985  // This mutator adds a node to a Genome by inserting it in the middle of an existing link between two nodes.
   986  // This broken link will be disabled and now represented by two links with the new node between them.
   987  // The innovations list from population is used to compare the innovation with other innovations in the list and see
   988  // whether they match. If they do, the same innovation numbers will be assigned to the new genes. If a disabled link
   989  // is chosen, then the method just exits with false.
   990  func (g *Genome) mutateAddNode(pop *Population, context *neat.NeatContext) (bool, error) {
   991  	if len(g.Genes) == 0 {
   992  		return false, nil // it's possible to have such a network without any link
   993  	}
   994  
   995  	// First, find a random gene already in the genome
   996  	found := false
   997  	var gene *Gene
   998  
   999  	// For a very small genome, we need to bias splitting towards older links to avoid a "chaining" effect which is likely
  1000  	// to occur when we keep splitting between the same two nodes over and over again (on newer and newer connections)
  1001  	if len(g.Genes) < 15 {
  1002  		for _, gn := range g.Genes {
  1003  			// Now randomize which gene is chosen.
  1004  			if gn.IsEnabled && gn.Link.InNode.NeuronType != network.BiasNeuron && rand.Float32() >= 0.3 {
  1005  				gene = gn
  1006  				found = true
  1007  				break
  1008  			}
  1009  		}
  1010  	} else {
  1011  		try_count := 0
  1012  		// Alternative uniform random choice of genes. When the genome is not tiny, it is safe to choose randomly.
  1013  		for try_count < 20 && !found {
  1014  			gene_num := rand.Intn(len(g.Genes))
  1015  			gene = g.Genes[gene_num]
  1016  			if gene.IsEnabled && gene.Link.InNode.NeuronType != network.BiasNeuron {
  1017  				found = true
  1018  			}
  1019  			try_count++
  1020  		}
  1021  	}
  1022  	if !found {
  1023  		// Failed to find appropriate gene
  1024  		return false, nil
  1025  	}
  1026  
  1027  	gene.IsEnabled = false;
  1028  
  1029  	// Extract the link
  1030  	link := gene.Link
  1031  	// Extract the weight
  1032  	old_weight := link.Weight
  1033  	// Get the old link's trait
  1034  	trait := link.Trait
  1035  
  1036  	// Extract the nodes
  1037  	in_node, out_node := link.InNode, link.OutNode
  1038  	if in_node == nil || out_node == nil {
  1039  		return false, errors.New(
  1040  			fmt.Sprintf("Genome:mutateAddNode: Anomalous link found with either IN or OUT node not set. %s", link))
  1041  	}
  1042  
  1043  	var new_gene_1, new_gene_2 *Gene
  1044  	var new_node *network.NNode
  1045  
  1046  	// Check to see if this innovation already occurred in the population
  1047  	innovation_found := false
  1048  	for _, inn := range pop.Innovations {
  1049  		/* We check to see if an innovation already occurred that was:
  1050  		 	-A new node
  1051  		 	-Stuck between the same nodes as were chosen for this mutation
  1052  		 	-Splitting the same gene as chosen for this mutation
  1053  		 If so, we know this mutation is not a novel innovation in this generation
  1054  		 so we make it match the original, identical mutation which occurred
  1055  		 elsewhere in the population by coincidence */
  1056  		if inn.innovationType == newNodeInnType &&
  1057  			inn.InNodeId == in_node.Id &&
  1058  			inn.OutNodeId == out_node.Id &&
  1059  			inn.OldInnovNum == gene.InnovationNum {
  1060  
  1061  			// Create the new NNode
  1062  			new_node = network.NewNNode(inn.NewNodeId, network.HiddenNeuron)
  1063  			// By convention, it will point to the first trait
  1064  			// Note: In future may want to change this
  1065  			new_node.Trait = g.Traits[0]
  1066  
  1067  			// Create the new Genes
  1068  			new_gene_1 = NewGeneWithTrait(trait, 1.0, in_node, new_node, link.IsRecurrent, inn.InnovationNum, 0)
  1069  			new_gene_2 = NewGeneWithTrait(trait, old_weight, new_node, out_node, false, inn.InnovationNum2, 0)
  1070  
  1071  			innovation_found = true
  1072  			break
  1073  		}
  1074  	}
  1075  	// The innovation is totally novel
  1076  	if !innovation_found {
  1077  		// Get the current node id with post increment
  1078  		new_node_id := int(pop.getNextNodeIdAndIncrement())
  1079  
  1080  		// Create the new NNode
  1081  		new_node = network.NewNNode(new_node_id, network.HiddenNeuron)
  1082  		// By convention, it will point to the first trait
  1083  		new_node.Trait = g.Traits[0]
  1084  		// Set node activation function as random from a list of types registered with context
  1085  		if act_type, err := context.RandomNodeActivationType(); err != nil {
  1086  			return false, err
  1087  		} else {
  1088  			new_node.ActivationType = act_type
  1089  		}
  1090  
  1091  		// get the next innovation id for gene 1
  1092  		gene_innov_1 := pop.getNextInnovationNumberAndIncrement()
  1093  		// create gene with the current gene innovation
  1094  		new_gene_1 = NewGeneWithTrait(trait, 1.0, in_node, new_node, link.IsRecurrent, gene_innov_1, 0);
  1095  
  1096  		// get the next innovation id for gene 2
  1097  		gene_innov_2 := pop.getNextInnovationNumberAndIncrement()
  1098  		// create the second gene with this innovation incremented
  1099  		new_gene_2 = NewGeneWithTrait(trait, old_weight, new_node, out_node, false, gene_innov_2, 0);
  1100  
  1101  		// Store innovation
  1102  		innov := NewInnovationForNode(in_node.Id, out_node.Id, gene_innov_1, gene_innov_2, new_node.Id, gene.InnovationNum)
  1103  		pop.addInnovationSynced(innov)
  1104  	} else if g.hasNode(new_node) {
  1105  		// The same add node innovation occurred in the same genome (parent) - just skip.
  1106  		// This may happen when parent of this organism experienced the same mutation in current epoch earlier
  1107  		// and after that parent's genome was duplicated to child by mating and the same mutation parameters
  1108  		// was selected again (in_node.Id, out_node.Id, gene.InnovationNum). As result the innovation with given
  1109  		// parameters will be found and new node will be created with ID which alredy exists in child genome.
  1110  		// If proceed than we will have duplicated Node and genes - so we're skipping this.
  1111  		neat.InfoLog(
  1112  			fmt.Sprintf("GENOME: Add node innovation found [%t] in the same genome [%d] for node [%d]\n%s",
  1113  				innovation_found, g.Id, new_node.Id, g))
  1114  		return false, nil
  1115  	}
  1116  
  1117  
  1118  	// Now add the new NNode and new Genes to the Genome
  1119  	g.Genes = geneInsert(g.Genes, new_gene_1)
  1120  	g.Genes = geneInsert(g.Genes, new_gene_2)
  1121  	g.Nodes = nodeInsert(g.Nodes, new_node)
  1122  
  1123  	return true, nil
  1124  }
  1125  
  1126  // Adds Gaussian noise to link weights either GAUSSIAN or COLD_GAUSSIAN (from zero).
  1127  // The COLD_GAUSSIAN means ALL connection weights will be given completely new values
  1128  func (g *Genome) mutateLinkWeights(power, rate float64, mutation_type mutatorType) (bool, error) {
  1129  	if len(g.Genes) == 0 {
  1130  		return false, errors.New("Genome has no genes")
  1131  	}
  1132  
  1133  	// Once in a while really shake things up
  1134  	severe := false
  1135  	if rand.Float64() > 0.5 {
  1136  		severe = true
  1137  	}
  1138  
  1139  	// Go through all the Genes and perturb their link's weights
  1140  	num, gene_total := 0.0, float64(len(g.Genes))
  1141  	end_part := gene_total * 0.8
  1142  	var gauss_point, cold_gauss_point float64
  1143  
  1144  	for _, gene := range g.Genes {
  1145  		// The following if determines the probabilities of doing cold gaussian
  1146  		// mutation, meaning the probability of replacing a link weight with
  1147  		// another, entirely random weight. It is meant to bias such mutations
  1148  		// to the tail of a genome, because that is where less time-tested genes
  1149  		// reside. The gauss_point and cold_gauss_point represent values above
  1150  		// which a random float will signify that kind of mutation.
  1151  		if severe {
  1152  			gauss_point = 0.3
  1153  			cold_gauss_point = 0.1
  1154  		} else if gene_total >= 10.0 && num > end_part {
  1155  			gauss_point = 0.5  // Mutate by modification % of connections
  1156  			cold_gauss_point = 0.3 // Mutate the rest by replacement % of the time
  1157  		} else {
  1158  			// Half the time don't do any cold mutations
  1159  			if rand.Float64() > 0.5 {
  1160  				gauss_point = 1.0 - rate
  1161  				cold_gauss_point = gauss_point - 0.1
  1162  			} else {
  1163  				gauss_point = 1.0 - rate
  1164  				cold_gauss_point = gauss_point // no cold mutation possible (see later)
  1165  			}
  1166  		}
  1167  
  1168  		rand_val := float64(utils.RandSign()) * rand.Float64() * power
  1169  		if mutation_type == gaussianMutator {
  1170  			rand_choice := rand.Float64()
  1171  			if rand_choice > gauss_point {
  1172  				gene.Link.Weight += rand_val
  1173  			} else if rand_choice > cold_gauss_point {
  1174  				gene.Link.Weight = rand_val
  1175  			}
  1176  		} else if mutation_type == goldGaussianMutator {
  1177  			gene.Link.Weight = rand_val
  1178  		}
  1179  
  1180  		// Record the innovation
  1181  		gene.MutationNum = gene.Link.Weight
  1182  
  1183  		num += 1.0
  1184  	}
  1185  
  1186  	return true, nil
  1187  }
  1188  
  1189  // Perturb params in one trait
  1190  func (g *Genome) mutateRandomTrait(context *neat.NeatContext) (bool, error) {
  1191  	if len(g.Traits) == 0 {
  1192  		return false, errors.New("Genome has no traits")
  1193  	}
  1194  	// Choose a random trait number
  1195  	trait_num := rand.Intn(len(g.Traits))
  1196  
  1197  	// Retrieve the trait and mutate it
  1198  	g.Traits[trait_num].Mutate(context.TraitMutationPower, context.TraitParamMutProb)
  1199  
  1200  	return true, nil
  1201  }
  1202  
  1203  // This chooses a random gene, extracts the link from it and re-points the link to a random trait
  1204  func (g *Genome) mutateLinkTrait(times int) (bool, error) {
  1205  	if len(g.Traits) == 0 || len(g.Genes) == 0 {
  1206  		return false, errors.New("Genome has either no traits od genes")
  1207  	}
  1208  	for loop := 0; loop < times; loop++ {
  1209  		// Choose a random trait number
  1210  		trait_num := rand.Intn(len(g.Traits))
  1211  
  1212  		// Choose a random link number
  1213  		gene_num := rand.Intn(len(g.Genes))
  1214  
  1215  		// set the link to point to the new trait
  1216  		g.Genes[gene_num].Link.Trait = g.Traits[trait_num]
  1217  
  1218  	}
  1219  	return true, nil
  1220  }
  1221  
  1222  // This chooses a random node and re-points the node to a random trait specified number of times
  1223  func (g *Genome) mutateNodeTrait(times int) (bool, error) {
  1224  	if len(g.Traits) == 0 || len(g.Nodes) == 0 {
  1225  		return false, errors.New("Genome has either no traits or nodes")
  1226  	}
  1227  	for loop := 0; loop < times; loop++ {
  1228  		// Choose a random trait number
  1229  		trait_num := rand.Intn(len(g.Traits))
  1230  
  1231  		// Choose a random node number
  1232  		node_num := rand.Intn(len(g.Nodes))
  1233  
  1234  		// set the node to point to the new trait
  1235  		g.Nodes[node_num].Trait = g.Traits[trait_num]
  1236  	}
  1237  	return true, nil
  1238  }
  1239  
  1240  // Toggle genes from enable on to enable off or vice versa.  Do it specified number of times.
  1241  func (g *Genome) mutateToggleEnable(times int) (bool, error) {
  1242  	if len(g.Genes) == 0 {
  1243  		return false, errors.New("Genome has no genes to toggle")
  1244  	}
  1245  	for loop := 0; loop < times; loop++ {
  1246  		// Choose a random gene number
  1247  		gene_num := rand.Intn(len(g.Genes))
  1248  
  1249  		gene := g.Genes[gene_num]
  1250  		if gene.IsEnabled {
  1251  			// We need to make sure that another gene connects out of the in-node.
  1252  			// Because if not a section of network will break off and become isolated.
  1253  			for _, check_gene := range g.Genes {
  1254  				if check_gene.Link.InNode.Id == gene.Link.InNode.Id &&
  1255  					check_gene.IsEnabled && check_gene.InnovationNum != gene.InnovationNum {
  1256  					gene.IsEnabled = false
  1257  					break
  1258  				}
  1259  			}
  1260  		} else {
  1261  			gene.IsEnabled = true
  1262  		}
  1263  
  1264  	}
  1265  	return true, nil
  1266  }
  1267  // Finds first disabled gene and enable it
  1268  func (g *Genome) mutateGeneReenable() (bool, error) {
  1269  	if len(g.Genes) == 0 {
  1270  		return false, errors.New("Genome has no genes to re-enable")
  1271  	}
  1272  	for _, gene := range g.Genes {
  1273  		if !gene.IsEnabled {
  1274  			gene.IsEnabled = true
  1275  			break
  1276  		}
  1277  	}
  1278  	return true, nil
  1279  }
  1280  
  1281  // Applies all non-structural mutations to this genome
  1282  func (g *Genome) mutateAllNonstructural(context *neat.NeatContext) (bool, error) {
  1283  	res := false
  1284  	var err error
  1285  	if rand.Float64() < context.MutateRandomTraitProb {
  1286  		// mutate random trait
  1287  		res, err = g.mutateRandomTrait(context)
  1288  	}
  1289  
  1290  	if err == nil && rand.Float64() < context.MutateLinkTraitProb {
  1291  		// mutate link trait
  1292  		res, err = g.mutateLinkTrait(1)
  1293  	}
  1294  
  1295  	if err == nil && rand.Float64() < context.MutateNodeTraitProb {
  1296  		// mutate node trait
  1297  		res, err = g.mutateNodeTrait(1)
  1298  	}
  1299  
  1300  	if err == nil && rand.Float64() < context.MutateLinkWeightsProb {
  1301  		// mutate link weight
  1302  		res, err = g.mutateLinkWeights(context.WeightMutPower, 1.0, gaussianMutator)
  1303  	}
  1304  
  1305  	if err == nil && rand.Float64() < context.MutateToggleEnableProb {
  1306  		// mutate toggle enable
  1307  		res, err = g.mutateToggleEnable(1)
  1308  	}
  1309  
  1310  	if err == nil && rand.Float64() < context.MutateGeneReenableProb {
  1311  		// mutate gene reenable
  1312  		res, err = g.mutateGeneReenable();
  1313  	}
  1314  	return res, err
  1315  }
  1316  
  1317  /* ****** MATING METHODS ***** */
  1318  
  1319  // This method mates this Genome with another Genome g. For every point in each Genome, where each Genome shares
  1320  // the innovation number, the Gene is chosen randomly from either parent.  If one parent has an innovation absent in
  1321  // the other, the baby may inherit the innovation if it is from the more fit parent.
  1322  // The new Genome is given the id in the genomeid argument.
  1323  func (gen *Genome) mateMultipoint(og *Genome, genomeid int, fitness1, fitness2 float64) (*Genome, error) {
  1324  	// Check if genomes has equal number of traits
  1325  	if len(gen.Traits) != len(og.Traits) {
  1326  		return nil, errors.New(fmt.Sprintf("Genomes has different traits count, %d != %d", len(gen.Traits), len(og.Traits)))
  1327  	}
  1328  
  1329  	// First, average the Traits from the 2 parents to form the baby's Traits. It is assumed that trait vectors are
  1330  	// the same length. In the future, may decide on a different method for trait mating.
  1331  	new_traits, err := gen.mateTraits(og)
  1332  	if err != nil {
  1333  		return nil, err
  1334  	}
  1335  
  1336  	// The new genes and nodes created
  1337  	new_genes := make([]*Gene, 0)
  1338  	new_nodes := make([]*network.NNode, 0)
  1339  	child_nodes_map := make(map[int]*network.NNode)
  1340  
  1341  	// NEW: Make sure all sensors and outputs are included (in case some inputs are disconnected)
  1342  	for _, curr_node := range og.Nodes {
  1343  		if curr_node.NeuronType == network.InputNeuron ||
  1344  			curr_node.NeuronType == network.BiasNeuron ||
  1345  			curr_node.NeuronType == network.OutputNeuron {
  1346  			node_trait_num := 0
  1347  			if curr_node.Trait != nil {
  1348  				node_trait_num = curr_node.Trait.Id - gen.Traits[0].Id
  1349  			}
  1350  			// Create a new node off the sensor or output
  1351  			new_onode := network.NewNNodeCopy(curr_node, new_traits[node_trait_num])
  1352  
  1353  			// Add the new node
  1354  			new_nodes = nodeInsert(new_nodes, new_onode)
  1355  			child_nodes_map[new_onode.Id] = new_onode
  1356  		}
  1357  	}
  1358  
  1359  	// Figure out which genome is better. The worse genome should not be allowed to add extra structural baggage.
  1360  	// If they are the same, use the smaller one's disjoint and excess genes only.
  1361  	p1better := false // Tells if the first genome (this one) has better fitness or not
  1362  	if fitness1 > fitness2 ||
  1363  		(fitness1 == fitness2 && len(gen.Genes) < len(og.Genes)) {
  1364  		p1better = true
  1365  	}
  1366  
  1367  	// Now loop through the Genes of each parent
  1368  	i1, i2, size1, size2 := 0, 0, len(gen.Genes), len(og.Genes)
  1369  	var chosen_gene *Gene
  1370  	for i1 < size1 || i2 < size2 {
  1371  		skip, disable := false, false
  1372  
  1373  		// choose best gene
  1374  		if i1 >= size1 {
  1375  			chosen_gene = og.Genes[i2]
  1376  			i2++
  1377  			if p1better {
  1378  				skip = true // Skip excess from the worse genome
  1379  			}
  1380  		} else if i2 >= size2 {
  1381  			chosen_gene = gen.Genes[i1]
  1382  			i1++
  1383  			if !p1better {
  1384  				skip = true // Skip excess from the worse genome
  1385  			}
  1386  		} else {
  1387  			p1gene := gen.Genes[i1]
  1388  			p2gene := og.Genes[i2]
  1389  
  1390  			// Extract current innovation numbers
  1391  			p1innov := p1gene.InnovationNum
  1392  			p2innov := p2gene.InnovationNum
  1393  
  1394  			if p1innov == p2innov {
  1395  				if rand.Float64() < 0.5 {
  1396  					chosen_gene = p1gene
  1397  				} else {
  1398  					chosen_gene = p2gene
  1399  				}
  1400  
  1401  				// If one is disabled, the corresponding gene in the offspring will likely be disabled
  1402  				if !p1gene.IsEnabled || !p2gene.IsEnabled && rand.Float64() < 0.75 {
  1403  					disable = true
  1404  				}
  1405  				i1++
  1406  				i2++
  1407  			} else if p1innov < p2innov {
  1408  				chosen_gene = p1gene
  1409  				i1++
  1410  				if !p1better {
  1411  					skip = true // Skip excess from the worse genome
  1412  				}
  1413  			} else {
  1414  				chosen_gene = p2gene
  1415  				i2++
  1416  				if p1better {
  1417  					skip = true // Skip excess from the worse genome
  1418  				}
  1419  			}
  1420  		}
  1421  
  1422  		// Uncomment this line to let growth go faster (from both parents excesses)
  1423  		// skip=false
  1424  
  1425  		// Check to see if the chosen gene conflicts with an already chosen gene i.e. do they represent the same link
  1426  		for _, new_gene := range new_genes {
  1427  			if new_gene.Link.IsEqualGenetically(chosen_gene.Link) {
  1428  				skip = true;
  1429  				break;
  1430  			}
  1431  		}
  1432  
  1433  		// Now add the chosen gene to the baby
  1434  		if (!skip) {
  1435  			// Check for the nodes, add them if not in the baby Genome already
  1436  			in_node := chosen_gene.Link.InNode
  1437  			out_node := chosen_gene.Link.OutNode
  1438  
  1439  			// Checking for inode's existence
  1440  			var new_in_node *network.NNode
  1441  			for _, node := range new_nodes {
  1442  				if node.Id == in_node.Id {
  1443  					new_in_node = node
  1444  					break
  1445  				}
  1446  			}
  1447  			if new_in_node == nil {
  1448  				// Here we know the node doesn't exist so we have to add it normalized trait
  1449  				// number for new NNode
  1450  				in_node_trait_num := 0
  1451  				if in_node.Trait != nil {
  1452  					in_node_trait_num = in_node.Trait.Id - gen.Traits[0].Id
  1453  				}
  1454  				new_in_node = network.NewNNodeCopy(in_node, new_traits[in_node_trait_num])
  1455  				new_nodes = nodeInsert(new_nodes, new_in_node)
  1456  				child_nodes_map[new_in_node.Id] = new_in_node
  1457  			}
  1458  
  1459  			// Checking for onode's existence
  1460  			var new_out_node *network.NNode
  1461  			for _, node := range new_nodes {
  1462  				if node.Id == out_node.Id {
  1463  					new_out_node = node
  1464  					break
  1465  				}
  1466  			}
  1467  			if new_out_node == nil {
  1468  				// Here we know the node doesn't exist so we have to add it normalized trait
  1469  				// number for new NNode
  1470  				out_node_trait_num := 0
  1471  				if out_node.Trait != nil {
  1472  					out_node_trait_num = out_node.Trait.Id - gen.Traits[0].Id
  1473  				}
  1474  				new_out_node = network.NewNNodeCopy(out_node, new_traits[out_node_trait_num])
  1475  				new_nodes = nodeInsert(new_nodes, new_out_node)
  1476  				child_nodes_map[new_out_node.Id] = new_out_node
  1477  			}
  1478  
  1479  
  1480  			// Add the Gene
  1481  			gene_trait_num := 0
  1482  			if chosen_gene.Link.Trait != nil {
  1483  				// The subtracted number normalizes depending on whether traits start counting at 1 or 0
  1484  				gene_trait_num = chosen_gene.Link.Trait.Id - gen.Traits[0].Id
  1485  			}
  1486  			newgene := NewGeneCopy(chosen_gene, new_traits[gene_trait_num], new_in_node, new_out_node)
  1487  			if disable {
  1488  				newgene.IsEnabled = false
  1489  			}
  1490  			new_genes = append(new_genes, newgene)
  1491  		} // end SKIP
  1492  	} // end FOR
  1493  	// check if parent's MIMO control genes should be inherited
  1494  	if len(gen.ControlGenes) != 0 || len(og.ControlGenes) != 0 {
  1495  		// MIMO control genes found at least in one parent - append it to child if appropriate
  1496  		if extra_nodes, modules := gen.mateModules(child_nodes_map, og); modules != nil {
  1497  			if len(extra_nodes) > 0 {
  1498  				// append extra IO nodes of MIMO genes not found in child
  1499  				new_nodes = append(new_nodes, extra_nodes...)
  1500  			}
  1501  
  1502  			// Return modular baby genome
  1503  			return NewModularGenome(genomeid, new_traits, new_nodes, new_genes, modules), nil
  1504  		}
  1505  	}
  1506  	// Return plain baby Genome
  1507  	return NewGenome(genomeid, new_traits, new_nodes, new_genes), nil
  1508  }
  1509  
  1510  // This method mates like multipoint but instead of selecting one or the other when the innovation numbers match,
  1511  // it averages their weights.
  1512  func (gen *Genome) mateMultipointAvg(og *Genome, genomeid int, fitness1, fitness2 float64) (*Genome, error) {
  1513  	// Check if genomes has equal number of traits
  1514  	if len(gen.Traits) != len(og.Traits) {
  1515  		return nil, errors.New(fmt.Sprintf("Genomes has different traits count, %d != %d", len(gen.Traits), len(og.Traits)))
  1516  	}
  1517  
  1518  	// First, average the Traits from the 2 parents to form the baby's Traits. It is assumed that trait vectors are
  1519  	// the same length. In the future, may decide on a different method for trait mating.
  1520  	new_traits, err := gen.mateTraits(og)
  1521  	if err != nil {
  1522  		return nil, err
  1523  	}
  1524  
  1525  
  1526  	// The new genes and nodes created
  1527  	new_genes := make([]*Gene, 0)
  1528  	new_nodes := make([]*network.NNode, 0)
  1529  	child_nodes_map := make(map[int]*network.NNode)
  1530  
  1531  	// NEW: Make sure all sensors and outputs are included (in case some inputs are disconnected)
  1532  	for _, curr_node := range og.Nodes {
  1533  		if curr_node.NeuronType == network.InputNeuron ||
  1534  			curr_node.NeuronType == network.BiasNeuron ||
  1535  			curr_node.NeuronType == network.OutputNeuron {
  1536  			node_trait_num := 0
  1537  			if curr_node.Trait != nil {
  1538  				node_trait_num = curr_node.Trait.Id - gen.Traits[0].Id
  1539  			}
  1540  			// Create a new node off the sensor or output
  1541  			new_onode := network.NewNNodeCopy(curr_node, new_traits[node_trait_num])
  1542  
  1543  			// Add the new node
  1544  			new_nodes = nodeInsert(new_nodes, new_onode)
  1545  			child_nodes_map[new_onode.Id] = new_onode
  1546  		}
  1547  	}
  1548  
  1549  	// Figure out which genome is better. The worse genome should not be allowed to add extra structural baggage.
  1550  	// If they are the same, use the smaller one's disjoint and excess genes only.
  1551  	p1better := false // Tells if the first genome (this one) has better fitness or not
  1552  	if fitness1 > fitness2 ||
  1553  		(fitness1 == fitness2 && len(gen.Genes) < len(og.Genes)) {
  1554  		p1better = true
  1555  	}
  1556  
  1557  	// Set up the avgene - this Gene is used to hold the average of the two genes to be averaged
  1558  	avg_gene := NewGeneWithTrait(nil, 0.0, nil, nil, false, 0, 0.0);
  1559  
  1560  	// Now loop through the Genes of each parent
  1561  	i1, i2, size1, size2 := 0, 0, len(gen.Genes), len(og.Genes)
  1562  	var chosen_gene *Gene
  1563  	for i1 < size1 || i2 < size2 {
  1564  		skip := false
  1565  		avg_gene.IsEnabled = true // Default to enabled
  1566  
  1567  		// choose best gene
  1568  		if i1 >= size1 {
  1569  			chosen_gene = og.Genes[i2]
  1570  			i2++
  1571  			if p1better {
  1572  				skip = true // Skip excess from the worse genome
  1573  			}
  1574  		} else if i2 >= size2 {
  1575  			chosen_gene = gen.Genes[i1]
  1576  			i1++
  1577  			if !p1better {
  1578  				skip = true // Skip excess from the worse genome
  1579  			}
  1580  		} else {
  1581  			p1gene := gen.Genes[i1]
  1582  			p2gene := og.Genes[i2]
  1583  
  1584  			// Extract current innovation numbers
  1585  			p1innov := p1gene.InnovationNum
  1586  			p2innov := p2gene.InnovationNum
  1587  
  1588  			if p1innov == p2innov {
  1589  				// Average them into the avg_gene
  1590  				if rand.Float64() > 0.5 {
  1591  					avg_gene.Link.Trait = p1gene.Link.Trait
  1592  				} else {
  1593  					avg_gene.Link.Trait = p2gene.Link.Trait
  1594  				}
  1595  				avg_gene.Link.Weight = (p1gene.Link.Weight + p2gene.Link.Weight) / 2.0 // WEIGHTS AVERAGED HERE
  1596  
  1597  				if rand.Float64() > 0.5 {
  1598  					avg_gene.Link.InNode = p1gene.Link.InNode
  1599  				} else {
  1600  					avg_gene.Link.InNode = p2gene.Link.InNode
  1601  				}
  1602  				if rand.Float64() > 0.5 {
  1603  					avg_gene.Link.OutNode = p1gene.Link.OutNode
  1604  				} else {
  1605  					avg_gene.Link.OutNode = p2gene.Link.OutNode
  1606  				}
  1607  				if rand.Float64() > 0.5 {
  1608  					avg_gene.Link.IsRecurrent = p1gene.Link.IsRecurrent
  1609  				} else {
  1610  					avg_gene.Link.IsRecurrent = p2gene.Link.IsRecurrent
  1611  				}
  1612  
  1613  				avg_gene.InnovationNum = p1innov
  1614  				avg_gene.MutationNum = (p1gene.MutationNum + p2gene.MutationNum) / 2.0
  1615  				if !p1gene.IsEnabled || !p2gene.IsEnabled && rand.Float64() < 0.75 {
  1616  					avg_gene.IsEnabled = false
  1617  				}
  1618  
  1619  				chosen_gene = avg_gene
  1620  				i1++
  1621  				i2++
  1622  			} else if p1innov < p2innov {
  1623  				chosen_gene = p1gene
  1624  				i1++
  1625  				if !p1better {
  1626  					skip = true // Skip excess from the worse genome
  1627  				}
  1628  			} else {
  1629  				chosen_gene = p2gene
  1630  				i2++
  1631  				if p1better {
  1632  					skip = true // Skip excess from the worse genome
  1633  				}
  1634  			}
  1635  		}
  1636  
  1637  		// Uncomment this line to let growth go faster (from both parents excesses)
  1638  		// skip=false
  1639  
  1640  		// Check to see if the chosen gene conflicts with an already chosen gene i.e. do they represent the same link
  1641  		for _, new_gene := range new_genes {
  1642  			if new_gene.Link.IsEqualGenetically(chosen_gene.Link) {
  1643  				skip = true;
  1644  				break;
  1645  			}
  1646  		}
  1647  
  1648  		if (!skip) {
  1649  			// Now add the chosen gene to the baby
  1650  
  1651  			// Check for the nodes, add them if not in the baby Genome already
  1652  			in_node := chosen_gene.Link.InNode
  1653  			out_node := chosen_gene.Link.OutNode
  1654  
  1655  			// Checking for inode's existence
  1656  			var new_in_node *network.NNode
  1657  			for _, node := range new_nodes {
  1658  				if node.Id == in_node.Id {
  1659  					new_in_node = node
  1660  					break
  1661  				}
  1662  			}
  1663  			if new_in_node == nil {
  1664  				// Here we know the node doesn't exist so we have to add it normalized trait
  1665  				// number for new NNode
  1666  				in_node_trait_num := 0
  1667  				if in_node.Trait != nil {
  1668  					in_node_trait_num = in_node.Trait.Id - gen.Traits[0].Id
  1669  				}
  1670  				new_in_node = network.NewNNodeCopy(in_node, new_traits[in_node_trait_num])
  1671  				new_nodes = nodeInsert(new_nodes, new_in_node)
  1672  				child_nodes_map[new_in_node.Id] = new_in_node
  1673  			}
  1674  
  1675  			// Checking for onode's existence
  1676  			var new_out_node *network.NNode
  1677  			for _, node := range new_nodes {
  1678  				if node.Id == out_node.Id {
  1679  					new_out_node = node
  1680  					break
  1681  				}
  1682  			}
  1683  			if new_out_node == nil {
  1684  				// Here we know the node doesn't exist so we have to add it normalized trait
  1685  				// number for new NNode
  1686  				out_node_trait_num := 0
  1687  				if out_node.Trait != nil {
  1688  					out_node_trait_num = out_node.Trait.Id - gen.Traits[0].Id
  1689  				}
  1690  				new_out_node = network.NewNNodeCopy(out_node, new_traits[out_node_trait_num])
  1691  				new_nodes = nodeInsert(new_nodes, new_out_node)
  1692  				child_nodes_map[new_out_node.Id] = new_out_node
  1693  			}
  1694  
  1695  			// Add the Gene
  1696  			gene_trait_num := 0
  1697  			if chosen_gene.Link.Trait != nil {
  1698  				// The subtracted number normalizes depending on whether traits start counting at 1 or 0
  1699  				gene_trait_num = chosen_gene.Link.Trait.Id - gen.Traits[0].Id
  1700  			}
  1701  			new_gene := NewGeneCopy(chosen_gene, new_traits[gene_trait_num], new_in_node, new_out_node)
  1702  			new_genes = append(new_genes, new_gene)
  1703  		} // end SKIP
  1704  	} // end FOR
  1705  	// check if parent's MIMO control genes should be inherited
  1706  	if len(gen.ControlGenes) != 0 || len(og.ControlGenes) != 0 {
  1707  		// MIMO control genes found at least in one parent - append it to child if appropriate
  1708  		if extra_nodes, modules := gen.mateModules(child_nodes_map, og); modules != nil {
  1709  			if len(extra_nodes) > 0 {
  1710  				// append extra IO nodes of MIMO genes not found in child
  1711  				new_nodes = append(new_nodes, extra_nodes...)
  1712  			}
  1713  
  1714  			// Return modular baby genome
  1715  			return NewModularGenome(genomeid, new_traits, new_nodes, new_genes, modules), nil
  1716  		}
  1717  	}
  1718  	// Return plain baby Genome
  1719  	return NewGenome(genomeid, new_traits, new_nodes, new_genes), nil
  1720  }
  1721  
  1722  // This method is similar to a standard single point CROSSOVER operator. Traits are averaged as in the previous two
  1723  // mating methods. A Gene is chosen in the smaller Genome for splitting. When the Gene is reached, it is averaged with
  1724  // the matching Gene from the larger Genome, if one exists. Then every other Gene is taken from the larger Genome.
  1725  func (gen *Genome) mateSinglepoint(og *Genome, genomeid int) (*Genome, error) {
  1726  	// Check if genomes has equal number of traits
  1727  	if len(gen.Traits) != len(og.Traits) {
  1728  		return nil, errors.New(fmt.Sprintf("Genomes has different traits count, %d != %d", len(gen.Traits), len(og.Traits)))
  1729  	}
  1730  
  1731  	// First, average the Traits from the 2 parents to form the baby's Traits. It is assumed that trait vectors are
  1732  	// the same length. In the future, may decide on a different method for trait mating.
  1733  	new_traits, err := gen.mateTraits(og)
  1734  	if err != nil {
  1735  		return nil, err
  1736  	}
  1737  
  1738  	// The new genes and nodes created
  1739  	new_genes := make([]*Gene, 0)
  1740  	new_nodes := make([]*network.NNode, 0)
  1741  	child_nodes_map := make(map[int]*network.NNode)
  1742  
  1743  	// NEW: Make sure all sensors and outputs are included (in case some inputs are disconnected)
  1744  	for _, curr_node := range og.Nodes {
  1745  		if curr_node.NeuronType == network.InputNeuron ||
  1746  			curr_node.NeuronType == network.BiasNeuron ||
  1747  			curr_node.NeuronType == network.OutputNeuron {
  1748  			node_trait_num := 0
  1749  			if curr_node.Trait != nil {
  1750  				node_trait_num = curr_node.Trait.Id - gen.Traits[0].Id
  1751  			}
  1752  			// Create a new node off the sensor or output
  1753  			new_onode := network.NewNNodeCopy(curr_node, new_traits[node_trait_num])
  1754  
  1755  			// Add the new node
  1756  			new_nodes = nodeInsert(new_nodes, new_onode)
  1757  			child_nodes_map[new_onode.Id] = new_onode
  1758  		}
  1759  	}
  1760  
  1761  	// Set up the avg_gene - this Gene is used to hold the average of the two genes to be averaged
  1762  	avg_gene := NewGeneWithTrait(nil, 0.0, nil, nil, false, 0, 0.0);
  1763  
  1764  	p1stop, p2stop, stopper, crosspoint := 0, 0, 0, 0
  1765  	var p1genes, p2genes []*Gene
  1766  	size1, size2 := len(gen.Genes), len(og.Genes)
  1767  	if size1 < size2 {
  1768  		crosspoint = rand.Intn(size1)
  1769  		p1stop = size1
  1770  		p2stop = size2
  1771  		stopper = size2
  1772  		p1genes = gen.Genes
  1773  		p2genes = og.Genes
  1774  	} else {
  1775  		crosspoint = rand.Intn(size2)
  1776  		p1stop = size2
  1777  		p2stop = size1
  1778  		stopper = size1
  1779  		p1genes = og.Genes
  1780  		p2genes = gen.Genes
  1781  	}
  1782  
  1783  	var chosen_gene *Gene
  1784  	gene_counter, i1, i2 := 0, 0, 0
  1785  	// Now move through the Genes of each parent until both genomes end
  1786  	for i2 < stopper {
  1787  		skip := false
  1788  		avg_gene.IsEnabled = true  // Default to true
  1789  		if i1 == p1stop {
  1790  			chosen_gene = p2genes[i2]
  1791  			i2++
  1792  		} else if i2 == p2stop {
  1793  			chosen_gene = p1genes[i1]
  1794  			i1++
  1795  		} else {
  1796  			p1gene := p1genes[i1]
  1797  			p2gene := p2genes[i2]
  1798  
  1799  			// Extract current innovation numbers
  1800  			p1innov := p1gene.InnovationNum
  1801  			p2innov := p2gene.InnovationNum
  1802  
  1803  			if p1innov == p2innov {
  1804  				//Pick the chosen gene depending on whether we've crossed yet
  1805  				if gene_counter < crosspoint {
  1806  					chosen_gene = p1gene
  1807  				} else if gene_counter > crosspoint {
  1808  					chosen_gene = p2gene
  1809  				} else {
  1810  					// We are at the crosspoint here - average genes into the avgene
  1811  					if rand.Float64() > 0.5 {
  1812  						avg_gene.Link.Trait = p1gene.Link.Trait
  1813  					} else {
  1814  						avg_gene.Link.Trait = p2gene.Link.Trait
  1815  					}
  1816  					avg_gene.Link.Weight = (p1gene.Link.Weight + p2gene.Link.Weight) / 2.0 // WEIGHTS AVERAGED HERE
  1817  
  1818  					if rand.Float64() > 0.5 {
  1819  						avg_gene.Link.InNode = p1gene.Link.InNode
  1820  					} else {
  1821  						avg_gene.Link.InNode = p2gene.Link.InNode
  1822  					}
  1823  					if rand.Float64() > 0.5 {
  1824  						avg_gene.Link.OutNode = p1gene.Link.OutNode
  1825  					} else {
  1826  						avg_gene.Link.OutNode = p2gene.Link.OutNode
  1827  					}
  1828  					if rand.Float64() > 0.5 {
  1829  						avg_gene.Link.IsRecurrent = p1gene.Link.IsRecurrent
  1830  					} else {
  1831  						avg_gene.Link.IsRecurrent = p2gene.Link.IsRecurrent
  1832  					}
  1833  
  1834  					avg_gene.InnovationNum = p1innov
  1835  					avg_gene.MutationNum = (p1gene.MutationNum + p2gene.MutationNum) / 2.0
  1836  					if !p1gene.IsEnabled || !p2gene.IsEnabled && rand.Float64() < 0.75 {
  1837  						avg_gene.IsEnabled = false
  1838  					}
  1839  
  1840  					chosen_gene = avg_gene
  1841  				}
  1842  				i1++
  1843  				i2++
  1844  				gene_counter++
  1845  			} else if p1innov < p2innov {
  1846  				if (gene_counter < crosspoint) {
  1847  					chosen_gene = p1gene
  1848  					i1++
  1849  					gene_counter++
  1850  				} else {
  1851  					chosen_gene = p2gene
  1852  					i2++
  1853  				}
  1854  			} else {
  1855  				// p2innov < p1innov
  1856  				i2++
  1857  				// Special case: we need to skip to the next iteration
  1858  				// because this Gene is before the crosspoint on the wrong Genome
  1859  				skip = true
  1860  			}
  1861  		}
  1862  		// Check to see if the chosen gene conflicts with an already chosen gene i.e. do they represent the same link
  1863  		for _, new_gene := range new_genes {
  1864  			if new_gene.Link.IsEqualGenetically(chosen_gene.Link) {
  1865  				skip = true;
  1866  				break;
  1867  			}
  1868  		}
  1869  
  1870  		//Now add the chosen gene to the baby
  1871  		if (!skip) {
  1872  			// Check for the nodes, add them if not in the baby Genome already
  1873  			in_node := chosen_gene.Link.InNode
  1874  			out_node := chosen_gene.Link.OutNode
  1875  
  1876  			// Checking for inode's existence
  1877  			var new_in_node *network.NNode
  1878  			for _, node := range new_nodes {
  1879  				if node.Id == in_node.Id {
  1880  					new_in_node = node
  1881  					break
  1882  				}
  1883  			}
  1884  			if new_in_node == nil {
  1885  				// Here we know the node doesn't exist so we have to add it normalized trait
  1886  				// number for new NNode
  1887  				in_node_trait_num := 0
  1888  				if in_node.Trait != nil {
  1889  					in_node_trait_num = in_node.Trait.Id - gen.Traits[0].Id
  1890  				}
  1891  				new_in_node = network.NewNNodeCopy(in_node, new_traits[in_node_trait_num])
  1892  				new_nodes = nodeInsert(new_nodes, new_in_node)
  1893  				child_nodes_map[new_in_node.Id] = new_in_node
  1894  			}
  1895  
  1896  			// Checking for onode's existence
  1897  			var new_out_node *network.NNode
  1898  			for _, node := range new_nodes {
  1899  				if node.Id == out_node.Id {
  1900  					new_out_node = node
  1901  					break
  1902  				}
  1903  			}
  1904  			if new_out_node == nil {
  1905  				// Here we know the node doesn't exist so we have to add it normalized trait
  1906  				// number for new NNode
  1907  				out_node_trait_num := 0
  1908  				if out_node.Trait != nil {
  1909  					out_node_trait_num = out_node.Trait.Id - gen.Traits[0].Id
  1910  				}
  1911  				new_out_node = network.NewNNodeCopy(out_node, new_traits[out_node_trait_num])
  1912  				new_nodes = nodeInsert(new_nodes, new_out_node)
  1913  				child_nodes_map[new_out_node.Id] = new_out_node
  1914  			}
  1915  
  1916  			// Add the Gene
  1917  			gene_trait_num := 0
  1918  			if chosen_gene.Link.Trait != nil {
  1919  				// The subtracted number normalizes depending on whether traits start counting at 1 or 0
  1920  				gene_trait_num = chosen_gene.Link.Trait.Id - gen.Traits[0].Id
  1921  			}
  1922  			new_gene := NewGeneCopy(chosen_gene, new_traits[gene_trait_num], new_in_node, new_out_node)
  1923  			new_genes = append(new_genes, new_gene)
  1924  		}// end SKIP
  1925  	} // end FOR
  1926  	// check if parent's MIMO control genes should be inherited
  1927  	if len(gen.ControlGenes) != 0 || len(og.ControlGenes) != 0 {
  1928  		// MIMO control genes found at least in one parent - append it to child if appropriate
  1929  		if extra_nodes, modules := gen.mateModules(child_nodes_map, og); modules != nil {
  1930  			if len(extra_nodes) > 0 {
  1931  				// append extra IO nodes of MIMO genes not found in child
  1932  				new_nodes = append(new_nodes, extra_nodes...)
  1933  			}
  1934  
  1935  			// Return modular baby genome
  1936  			return NewModularGenome(genomeid, new_traits, new_nodes, new_genes, modules), nil
  1937  		}
  1938  	}
  1939  	// Return plain baby Genome
  1940  	return NewGenome(genomeid, new_traits, new_nodes, new_genes), nil
  1941  }
  1942  
  1943  // Builds an array of modules to be added to the child during crossover.
  1944  // If any or both parents has module and at least one modular endpoint node already inherited by child genome than make
  1945  // sure that child get all associated module nodes
  1946  func (g *Genome) mateModules(child_nodes map[int]*network.NNode, og *Genome) ([]*network.NNode, []*MIMOControlGene) {
  1947  	parent_modules := make([]*MIMOControlGene, 0)
  1948  	g_modules := findModulesIntersection(child_nodes, g.ControlGenes)
  1949  	if len(g_modules) > 0 {
  1950  		parent_modules = append(parent_modules, g_modules...)
  1951  	}
  1952  	og_modules := findModulesIntersection(child_nodes, og.ControlGenes)
  1953  	if len(og_modules) > 0 {
  1954  		parent_modules = append(parent_modules, og_modules...)
  1955  	}
  1956  	if len(parent_modules) == 0 {
  1957  		return nil, nil
  1958  	}
  1959  
  1960  	// collect IO nodes from all included modules and add return it as extra ones
  1961  	extra_nodes := make([]*network.NNode, 0)
  1962  	for _, cg := range parent_modules {
  1963  		for _, n := range cg.ioNodes {
  1964  			if _, ok := child_nodes[n.Id]; !ok {
  1965  				// not found in known child nodes - collect it
  1966  				extra_nodes = append(extra_nodes, n)
  1967  			}
  1968  		}
  1969  	}
  1970  
  1971  	return extra_nodes, parent_modules
  1972  }
  1973  
  1974  // Finds intersection of provided nodes with IO nodes from control genes and returns list of control genes found.
  1975  // If no intersection found empty list returned.
  1976  func findModulesIntersection(nodes map[int]*network.NNode, genes []*MIMOControlGene) []*MIMOControlGene {
  1977  	modules := make([]*MIMOControlGene, 0)
  1978  	for _, cg := range genes {
  1979  		if cg.hasIntersection(nodes) {
  1980  			modules = append(modules, cg)
  1981  		}
  1982  	}
  1983  	return modules
  1984  }
  1985  
  1986  // Builds array of traits for child genome during crossover
  1987  func (g *Genome) mateTraits(og *Genome) ([]*neat.Trait, error) {
  1988  	new_traits := make([]*neat.Trait, len(g.Traits))
  1989  	var err error
  1990  	for i, tr := range g.Traits {
  1991  		new_traits[i], err = neat.NewTraitAvrg(tr, og.Traits[i]) // construct by averaging
  1992  		if err != nil {
  1993  			return nil, err
  1994  		}
  1995  	}
  1996  	return new_traits, nil
  1997  }
  1998  
  1999  /* ******** COMPATIBILITY CHECKING METHODS * ********/
  2000  
  2001  // This function gives a measure of compatibility between two Genomes by computing a linear combination of three
  2002  // characterizing variables of their compatibility. The three variables represent PERCENT DISJOINT GENES,
  2003  // PERCENT EXCESS GENES, MUTATIONAL DIFFERENCE WITHIN MATCHING GENES. So the formula for compatibility
  2004  // is:  disjoint_coeff * pdg + excess_coeff * peg + mutdiff_coeff * mdmg
  2005  // The three coefficients are global system parameters.
  2006  // The bigger returned value the less compatible the genomes. Fully compatible genomes has 0.0 returned.
  2007  func (g *Genome) compatibility(og *Genome, context *neat.NeatContext) float64 {
  2008  	if context.GenCompatMethod == 0 {
  2009  		return g.compatLinear(og, context)
  2010  	} else {
  2011  		return g.compatFast(og, context)
  2012  	}
  2013  }
  2014  
  2015  // The compatibility checking method with linear performance depending on the size of the lognest genome in comparison.
  2016  // When genomes are small this method is compatible in performance with Genome#compatFast method.
  2017  // The compatibility formula remains the same: disjoint_coeff * pdg + excess_coeff * peg + mutdiff_coeff * mdmg
  2018  // where: pdg - PERCENT DISJOINT GENES, peg - PERCENT EXCESS GENES, and mdmg - MUTATIONAL DIFFERENCE WITHIN MATCHING GENES
  2019  func (g *Genome) compatLinear(og *Genome, context *neat.NeatContext) float64 {
  2020  	num_disjoint, num_excess, mut_diff_total, num_matching := 0.0, 0.0, 0.0, 0.0
  2021  	size1, size2 := len(g.Genes), len(og.Genes)
  2022  	max_genome_size := size2
  2023  	if size1 > size2 {
  2024  		max_genome_size = size1
  2025  	}
  2026  	var gene1, gene2 *Gene
  2027  	for i, i1, i2 := 0, 0, 0; i < max_genome_size; i++ {
  2028  		if i1 >= size1 {
  2029  			num_excess += 1.0
  2030  			i2++
  2031  		} else if i2 >= size2 {
  2032  			num_excess += 1.0
  2033  			i1++
  2034  		} else {
  2035  			gene1 = g.Genes[i1]
  2036  			gene2 = og.Genes[i2]
  2037  			p1innov := gene1.InnovationNum
  2038  			p2innov := gene2.InnovationNum
  2039  
  2040  			if p1innov == p2innov {
  2041  				num_matching += 1.0
  2042  				mut_diff := math.Abs(gene1.MutationNum - gene2.MutationNum)
  2043  				mut_diff_total += mut_diff
  2044  				i1++
  2045  				i2++
  2046  			} else if p1innov < p2innov {
  2047  				i1++
  2048  				num_disjoint += 1.0
  2049  			} else if p2innov < p1innov {
  2050  				i2++
  2051  				num_disjoint += 1.0
  2052  			}
  2053  		}
  2054  	}
  2055  
  2056  	//fmt.Printf("num_disjoint: %.f num_excess: %.f mut_diff_total: %.f num_matching: %.f\n", num_disjoint, num_excess, mut_diff_total, num_matching)
  2057  
  2058  	// Return the compatibility number using compatibility formula
  2059  	// Note that mut_diff_total/num_matching gives the AVERAGE difference between mutation_nums for any two matching
  2060  	// Genes in the Genome. Look at disjointedness and excess in the absolute (ignoring size)
  2061  	comp := context.DisjointCoeff * num_disjoint + context.ExcessCoeff * num_excess +
  2062  		context.MutdiffCoeff * (mut_diff_total / num_matching)
  2063  
  2064  	return comp
  2065  }
  2066  
  2067  
  2068  // The faster version of genome compatibility checking. The compatibility check will start from the end of genome where
  2069  // the most of disparities are located - the novel genes with greater innovation ID are always attached at the end (see geneInsert).
  2070  // This has the result of complicating the routine because we must now invoke additional logic to determine which genes
  2071  // are excess and when the first disjoint gene is found. This is done with an extra integer:
  2072  // * excessGenesSwitch=0 // indicates to the loop that it is handling the first gene.
  2073  // * excessGenesSwitch=1 // Indicates that the first gene was excess and on genome 1.
  2074  // * excessGenesSwitch=2 // Indicates that the first gene was excess and on genome 2.
  2075  // * excessGenesSwitch=3 // Indicates that there are no more excess genes.
  2076  //
  2077  // The compatibility formula remains the same: disjoint_coeff * pdg + excess_coeff * peg + mutdiff_coeff * mdmg
  2078  // where: pdg - PERCENT DISJOINT GENES, peg - PERCENT EXCESS GENES, and mdmg - MUTATIONAL DIFFERENCE WITHIN MATCHING GENES
  2079  func (g *Genome) compatFast(og *Genome, context *neat.NeatContext) float64 {
  2080  	list1_count, list2_count := len(g.Genes), len(og.Genes)
  2081  	// First test edge cases
  2082  	if list1_count == 0 && list2_count == 0 {
  2083  		// Both lists are empty! No disparities, therefore the genomes are compatible!
  2084  		return 0.0
  2085  	}
  2086  	if list1_count == 0 {
  2087  		// All list2 genes are excess.
  2088  		return float64(list2_count) * context.ExcessCoeff
  2089  	}
  2090  
  2091  	if list2_count == 0 {
  2092  		// All list1 genes are excess.
  2093  		return float64(list1_count) * context.ExcessCoeff
  2094  	}
  2095  
  2096  	excess_genes_switch, num_matching := 0, 0
  2097  	compatibility, mut_diff := 0.0, 0.0
  2098  	list1_idx, list2_idx := list1_count - 1, list2_count - 1
  2099  	gene1, gene2 := g.Genes[list1_idx], og.Genes[list2_idx]
  2100  
  2101  	for {
  2102  		if gene2.InnovationNum > gene1.InnovationNum {
  2103  			// Most common test case(s) at top for efficiency.
  2104  			if excess_genes_switch == 3 {
  2105  				// No more excess genes. Therefore this mismatch is disjoint.
  2106  				compatibility += context.DisjointCoeff
  2107  			} else if excess_genes_switch == 2 {
  2108  				// Another excess gene on genome 2.
  2109  				compatibility += context.ExcessCoeff
  2110  			} else if excess_genes_switch == 1 {
  2111  				// We have found the first non-excess gene.
  2112  				excess_genes_switch = 3
  2113  				compatibility += context.DisjointCoeff
  2114  			} else {
  2115  				// First gene is excess, and is on genome 2.
  2116  				excess_genes_switch = 2
  2117  				compatibility += context.ExcessCoeff
  2118  			}
  2119  
  2120  			// Move to the next gene in list2.
  2121  			list2_idx--
  2122  		} else if gene1.InnovationNum == gene2.InnovationNum {
  2123  			// No more excess genes. It's quicker to set this every time than to test if is not yet 3.
  2124  			excess_genes_switch = 3
  2125  
  2126  			// Matching genes. Increase compatibility by MutationNum difference * coeff.
  2127  			mut_diff += math.Abs(gene1.MutationNum - gene2.MutationNum)
  2128  			num_matching++
  2129  
  2130  			// Move to the next gene in both lists.
  2131  			list1_idx--
  2132  			list2_idx--
  2133  		} else {
  2134  			// Most common test case(s) at top for efficiency.
  2135  			if excess_genes_switch == 3 {
  2136  				// No more excess genes. Therefore this mismatch is disjoint.
  2137  				compatibility += context.DisjointCoeff
  2138  			} else if (excess_genes_switch == 1) {
  2139  				// Another excess gene on genome 1.
  2140  				compatibility += context.ExcessCoeff
  2141  			} else if excess_genes_switch == 2 {
  2142  				// We have found the first non-excess gene.
  2143  				excess_genes_switch = 3
  2144  				compatibility += context.DisjointCoeff
  2145  			} else {
  2146  				// First gene is excess, and is on genome 1.
  2147  				excess_genes_switch = 1
  2148  				compatibility += context.ExcessCoeff
  2149  			}
  2150  
  2151  			// Move to the next gene in list1.
  2152  			list1_idx--
  2153  		}
  2154  
  2155  		// Check if we have reached the end of one (or both) of the lists. If we have reached the end of both then
  2156  		// we execute the first 'if' block - but it doesn't matter since the loop is not entered if both lists have
  2157  		// been exhausted.
  2158  		if list1_idx < 0 {
  2159  			// All remaining list2 genes are disjoint.
  2160  			compatibility += float64(list2_idx + 1) * context.DisjointCoeff
  2161  			break
  2162  
  2163  		}
  2164  
  2165  		if list2_idx < 0 {
  2166  			// All remaining list1 genes are disjoint.
  2167  			compatibility += float64(list1_idx + 1) * context.DisjointCoeff
  2168  			break
  2169  		}
  2170  
  2171  		gene1, gene2 = g.Genes[list1_idx], og.Genes[list2_idx]
  2172  	}
  2173  	if num_matching > 0 {
  2174  		compatibility += mut_diff * context.MutdiffCoeff / float64(num_matching)
  2175  	}
  2176  	return compatibility
  2177  }
  2178