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

     1  package network
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/yaricom/goNEAT/neat"
     6  )
     7  
     8  // A LINK is a connection from one node to another with an associated weight.
     9  // It can be marked as recurrent.
    10  type Link struct {
    11  	// Weight of connection
    12  	Weight float64
    13  	// NNode inputting into the link
    14  	InNode *NNode
    15  	// NNode that the link affects
    16  	OutNode *NNode
    17  	// If TRUE the link is recurrent
    18  	IsRecurrent bool
    19  	// If TRUE the link is time delayed
    20  	IsTimeDelayed bool
    21  
    22  	// Points to a trait of parameters for genetic creation
    23  	Trait *neat.Trait
    24  
    25  	/* ************ LEARNING PARAMETERS *********** */
    26  	// The following parameters are for use in neurons that learn through habituation,
    27  	// sensitization, or Hebbian-type processes
    28  	Params []float64
    29  	// The amount of weight adjustment
    30  	AddedWeight float64
    31  }
    32  
    33  // Creates new link with specified weight, input and output neurons connected recurrently or not.
    34  func NewLink(weight float64, inputNode, outNode *NNode, recurrent bool) *Link {
    35  	link := newLink(weight)
    36  	link.InNode = inputNode
    37  	link.OutNode = outNode
    38  	link.IsRecurrent = recurrent
    39  	return link
    40  }
    41  
    42  // Creates new Link with specified Trait
    43  func NewLinkWithTrait(trait *neat.Trait, weight float64, inputNode, outNode *NNode, recurrent bool) *Link {
    44  	link := newLink(weight)
    45  	link.InNode = inputNode
    46  	link.OutNode = outNode
    47  	link.IsRecurrent = recurrent
    48  	link.Trait = trait
    49  	link.deriveTrait(trait)
    50  	return link
    51  }
    52  
    53  // The copy constructor to create new link with parameters taken from provided ones and connecting specified nodes
    54  func NewLinkCopy(l *Link, inputNode, outNode *NNode) *Link {
    55  	link := newLink(l.Weight)
    56  	link.InNode = inputNode
    57  	link.OutNode = outNode
    58  	link.Trait = l.Trait
    59  	link.deriveTrait(l.Trait)
    60  	link.IsRecurrent = l.IsRecurrent
    61  	return link
    62  }
    63  
    64  // The private default constructor
    65  func newLink(weight float64) *Link {
    66  	return &Link{
    67  		Weight: weight,
    68  	}
    69  }
    70  
    71  // Checks if this link is genetically equal to provided one, i.e. connects nodes with the same IDs and has equal
    72  // recurrent flag. I.e. if both links represent the same Gene.
    73  func (l *Link) IsEqualGenetically(ol *Link) bool {
    74  	sameInNode := l.InNode.Id == ol.InNode.Id
    75  	sameOutNode := l.OutNode.Id == ol.OutNode.Id
    76  	sameRecurrent := l.IsRecurrent == ol.IsRecurrent
    77  
    78  	return sameInNode && sameOutNode && sameRecurrent
    79  }
    80  
    81  // The Link methods implementation
    82  func (l *Link) String() string {
    83  	return fmt.Sprintf("[Link: (%s <-> %s), weight: %.3f, recurrent: %t, time delayed: %t]",
    84  		l.InNode, l.OutNode, l.Weight, l.IsRecurrent, l.IsTimeDelayed)
    85  }
    86  
    87  // Copy trait parameters into this link's parameters
    88  func (l *Link) deriveTrait(t *neat.Trait) {
    89  	if t != nil {
    90  		l.Params = make([]float64, len(t.Params))
    91  		for i, p := range t.Params {
    92  			l.Params[i] = p
    93  		}
    94  	}
    95  }