github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/trait.go (about) 1 package neat 2 3 import ( 4 "fmt" 5 "math/rand" 6 "errors" 7 "github.com/yaricom/goNEAT/neat/utils" 8 ) 9 10 // The number of parameters used in neurons that learn through habituation, 11 // sensitization, or Hebbian-type processes 12 const Num_trait_params = 8 13 14 var ( 15 ErrTraitsParametersCountMismatch = errors.New("traits parameters number mismatch") 16 ) 17 18 // TRAIT: A Trait is a group of parameters that can be expressed as a group more than one time. Traits save a genetic 19 // algorithm from having to search vast parameter landscapes on every node. Instead, each node can simply point to a trait 20 // and those traits can evolve on their own. 21 type Trait struct { 22 // The trait ID 23 Id int 24 // The learned trait parameters 25 Params []float64 26 } 27 28 func NewTrait() *Trait { 29 trait := newTrait(Num_trait_params) 30 return trait 31 } 32 33 // The copy constructor 34 func NewTraitCopy(t *Trait) *Trait { 35 nt := newTrait(len(t.Params)) 36 nt.Id = t.Id 37 for i, p := range t.Params { 38 nt.Params[i] = p 39 } 40 return nt 41 } 42 43 // Special Constructor creates a new Trait which is the average of two existing traits passed in 44 func NewTraitAvrg(t1, t2 *Trait) (*Trait, error) { 45 if len(t1.Params) != len(t2.Params) { 46 return nil, ErrTraitsParametersCountMismatch 47 } 48 nt := newTrait(len(t1.Params)) 49 nt.Id = t1.Id 50 for i := 0; i < len(t1.Params); i++ { 51 nt.Params[i] = (t1.Params[i] + t2.Params[i]) / 2.0 52 } 53 return nt, nil 54 } 55 56 // The default private constructor 57 func newTrait(lenght int) *Trait { 58 return &Trait{ 59 Params:make([]float64, lenght), 60 } 61 } 62 63 // Perturb the trait parameters slightly 64 func (t *Trait) Mutate(trait_mutation_power, trait_param_mut_prob float64) { 65 for i := 0; i < len(t.Params); i++ { 66 if rand.Float64() > trait_param_mut_prob { 67 t.Params[i] += float64(utils.RandSign()) * rand.Float64() * trait_mutation_power 68 if t.Params[i] < 0 { 69 t.Params[i] = 0 70 } 71 } 72 } 73 } 74 75 func (t *Trait) String() string { 76 s := fmt.Sprintf("Trait #%d (", t.Id) 77 for _, p := range t.Params { 78 s = fmt.Sprintf("%s %f", s, p) 79 } 80 s = fmt.Sprintf("%s )", s) 81 return s 82 }