github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/genetics/organism.go (about) 1 package genetics 2 3 import ( 4 "github.com/yaricom/goNEAT/neat/network" 5 "fmt" 6 "bytes" 7 ) 8 9 // The object to associate implementation specific data with particular organism for various algorithm implementations 10 type OrganismData struct { 11 // The implementation specific data object to be associated with organism 12 Value interface{} 13 } 14 15 // Organisms are Genotypes (Genomes) and Phenotypes (Networks) with fitness information, 16 // i.e. the genotype and phenotype together. 17 type Organism struct { 18 // A measure of fitness for the Organism 19 Fitness float64 20 // The error value indicating how far organism's performance is from ideal task goal, e.g. MSE 21 Error float64 22 // Win marker (if needed for a particular task) 23 IsWinner bool 24 25 // The Organism's phenotype 26 Phenotype *network.Network 27 // The Organism's genotype 28 Genotype *Genome 29 // The Species of the Organism 30 Species *Species 31 32 // Number of children this Organism may have 33 ExpectedOffspring float64 34 // Tells which generation this Organism is from 35 Generation int 36 37 // The utility data transfer object to be used by different GA implementations to hold additional data. 38 // Implemented as ANY to allow implementation specific objects. 39 Data *OrganismData 40 41 // A fitness measure that won't change during fitness adjustments of population's epoch evaluation 42 originalFitness float64 43 44 // Marker for destruction of inferior Organisms 45 toEliminate bool 46 // Marks the species champion 47 isChampion bool 48 49 // Number of reserved offspring for a population leader 50 superChampOffspring int 51 // Marks the best in population 52 isPopulationChampion bool 53 // Marks the duplicate child of a champion (for tracking purposes) 54 isPopulationChampionChild bool 55 56 // DEBUG variable - highest fitness of champ 57 highestFitness float64 58 59 // Track its origin - for debugging or analysis - we can tell how the organism was born 60 mutationStructBaby bool 61 mateBaby bool 62 63 // The flag to be used as utility value 64 Flag int 65 } 66 67 // Creates new organism with specified genome, fitness and given generation number 68 func NewOrganism(fit float64, g *Genome, generation int) (org *Organism, err error) { 69 phenotype := g.Phenotype 70 if phenotype == nil { 71 phenotype, err = g.Genesis(g.Id) 72 if err != nil { 73 return nil, err 74 } 75 } 76 org = &Organism{ 77 Fitness:fit, 78 Genotype:g, 79 Phenotype:phenotype, 80 Generation:generation, 81 } 82 return org, nil 83 } 84 85 // Regenerate the network based on a change in the genotype 86 func (o *Organism) UpdatePhenotype() (err error) { 87 // First, delete the old phenotype (net) 88 o.Phenotype = nil 89 90 // Now, recreate the phenotype off the new genotype 91 o.Phenotype, err = o.Genotype.Genesis(o.Genotype.Id) 92 return err 93 } 94 95 // Method to check if this algorithm is champion child and if so than if it's damaged 96 func (o *Organism) CheckChampionChildDamaged() bool { 97 if o.isPopulationChampionChild && o.highestFitness > o.Fitness { 98 return true 99 } 100 return false 101 } 102 103 // Encodes this organism for wired transmission during parallel reproduction cycle 104 func (o *Organism) MarshalBinary() ([]byte, error) { 105 var buf bytes.Buffer 106 _, err := fmt.Fprintln(&buf, o.Fitness, o.Generation, o.highestFitness, o.isPopulationChampionChild, o.Genotype.Id) 107 o.Genotype.Write(&buf) 108 if err != nil { 109 return nil, err 110 } else { 111 return buf.Bytes(), nil 112 } 113 } 114 // Decodes organism received over the wire during parallel reproduction cycle 115 func (o *Organism) UnmarshalBinary(data []byte) error { 116 // A simple encoding: plain text. 117 b := bytes.NewBuffer(data) 118 var genotype_id int 119 _, err := fmt.Fscanln(b, &o.Fitness, &o.Generation, &o.highestFitness, &o.isPopulationChampionChild, &genotype_id) 120 o.Genotype, err = ReadGenome(b, genotype_id) 121 if err == nil { 122 o.Phenotype, err = o.Genotype.Genesis(genotype_id) 123 } 124 125 return err 126 } 127 128 func (o *Organism) String() string { 129 champStr := "" 130 if o.isChampion { 131 champStr = " - CHAMPION - " 132 } 133 eliminStr := "" 134 if o.toEliminate { 135 eliminStr = " - TO BE ELIMINATED - " 136 } 137 return fmt.Sprintf("[Organism generation: %d, fitness: %.3f, original fitness: %.3f%s%s]", 138 o.Generation, o.Fitness, o.originalFitness, champStr, eliminStr) 139 } 140 141 // Dumps all organism's fields into string 142 func (o *Organism) Dump() string { 143 b := bytes.NewBufferString("Organism:") 144 fmt.Fprintln(b, "Fitness: ", o.Fitness) 145 fmt.Fprintln(b, "Error: ", o.Error) 146 fmt.Fprintln(b, "IsWinner: ", o.IsWinner) 147 fmt.Fprintln(b, "Phenotype: ", o.Phenotype) 148 fmt.Fprintln(b, "Genotype: ", o.Genotype) 149 fmt.Fprintln(b, "Species: ", o.Species) 150 fmt.Fprintln(b, "ExpectedOffspring: ", o.ExpectedOffspring) 151 fmt.Fprintln(b, "Data: ", o.Data) 152 fmt.Fprintln(b, "Phenotype: ", o.Phenotype) 153 fmt.Fprintln(b, "originalFitness: ", o.originalFitness) 154 fmt.Fprintln(b, "toEliminate: ", o.toEliminate) 155 fmt.Fprintln(b, "isChampion: ", o.isChampion) 156 fmt.Fprintln(b, "superChampOffspring: ", o.superChampOffspring) 157 fmt.Fprintln(b, "isPopulationChampion: ", o.isPopulationChampion) 158 fmt.Fprintln(b, "isPopulationChampionChild: ", o.isPopulationChampionChild) 159 fmt.Fprintln(b, "highestFitness: ", o.highestFitness) 160 fmt.Fprintln(b, "mutationStructBaby: ", o.mutationStructBaby) 161 fmt.Fprintln(b, "mateBaby: ", o.mateBaby) 162 fmt.Fprintln(b, "Flag: ", o.Flag) 163 164 return b.String() 165 } 166 167 // Organisms is sortable list of organisms by fitness 168 type Organisms []*Organism 169 170 func (f Organisms) Len() int { 171 return len(f) 172 } 173 func (f Organisms) Swap(i, j int) { 174 f[i], f[j] = f[j], f[i] 175 } 176 func (f Organisms) Less(i, j int) bool { 177 if f[i].Fitness < f[j].Fitness { 178 // try to promote most fit organisms 179 return true // lower fitness is less 180 } else if f[i].Fitness == f[j].Fitness { 181 // try to promote less complex organisms 182 ci := f[i].Phenotype.Complexity() 183 cj := f[j].Phenotype.Complexity() 184 if ci > cj { 185 return true // higher complexity is less 186 } else if ci == cj { 187 return f[i].Genotype.Id < f[j].Genotype.Id // least recent (older) is less 188 } 189 } 190 return false 191 }