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

     1  package genetics
     2  
     3  import (
     4  	"github.com/yaricom/goNEAT/neat/network"
     5  	"fmt"
     6  )
     7  
     8  // The Multiple-Input Multiple-Output (MIMO) control Gene allows to create modular genomes, in which several groups of genes
     9  // connected through single MIMO Gene and corresponding control function is applied to all inputs in order to produce
    10  // outputs. This allows to build modular hierarchical genomes which can be considered as sum of constituent components
    11  // and evolved as a whole and as a concrete parts simultaneously.
    12  type MIMOControlGene struct {
    13  	// The current innovation number for this gene
    14  	InnovationNum int64
    15  	// Used to see how much mutation has changed the link
    16  	MutationNum   float64
    17  	// If true the gene is enabled
    18  	IsEnabled     bool
    19  
    20  	// The control node with control/activation function
    21  	ControlNode   *network.NNode
    22  
    23  	// The list of associated IO nodes for fast traversal
    24  	ioNodes       []*network.NNode
    25  }
    26  
    27  // Creates new MIMO gene
    28  func NewMIMOGene(control_node *network.NNode, innov_num int64, mut_num float64, enabled bool) *MIMOControlGene {
    29  	gene := &MIMOControlGene{
    30  		ControlNode:control_node,
    31  		InnovationNum:innov_num,
    32  		MutationNum:mut_num,
    33  		IsEnabled:enabled,
    34  	}
    35  	// collect IO nodes list
    36  	gene.ioNodes = make([]*network.NNode, 0)
    37  	for _, l := range control_node.Incoming {
    38  		gene.ioNodes = append(gene.ioNodes, l.InNode)
    39  	}
    40  	for _, l := range control_node.Outgoing {
    41  		gene.ioNodes = append(gene.ioNodes, l.OutNode)
    42  	}
    43  
    44  	return gene
    45  }
    46  
    47  // The copy constructor taking parameters from provided control gene for given control node
    48  func NewMIMOGeneCopy(g *MIMOControlGene, control_node *network.NNode) *MIMOControlGene {
    49  	cg := NewMIMOGene(control_node, g.InnovationNum, g.MutationNum, g.IsEnabled)
    50  	return cg
    51  }
    52  
    53  // Tests whether this gene has intersection with provided map of nodes, i.e. any of it's IO nodes included into list
    54  func (g *MIMOControlGene) hasIntersection(nodes map[int]*network.NNode) bool {
    55  	for _, nd := range g.ioNodes {
    56  		if _, Ok := nodes[nd.Id]; Ok {
    57  			// found
    58  			return true
    59  		}
    60  	}
    61  	return false
    62  }
    63  
    64  // The stringer
    65  func (g *MIMOControlGene) String() string {
    66  	enabl_str := ""
    67  	if !g.IsEnabled {
    68  		enabl_str = " -DISABLED-"
    69  	}
    70  	return fmt.Sprintf("[MIMO Gene INNOV (%4d, % .3f) %s control node: %s]",
    71  		g.InnovationNum, g.MutationNum, enabl_str, g.ControlNode.String())
    72  }