- Timestamp:
- 05/04/23 00:57:57 (20 months ago)
- Location:
- cpp/frams/genetics
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/genooperators.cpp
r1226 r1233 8 8 #include <common/nonstd_math.h> 9 9 #include <frams/util/rndutil.h> 10 #include <algorithm> // std::min, std::max 10 11 11 12 // … … 355 356 } 356 357 357 int GenoOperators::getRandomChar(const char *choices, const char *excluded) 358 { 359 int allowed_count = 0; 360 for (size_t i = 0; i < strlen(choices); i++) if (!strchrn0(excluded, choices[i])) allowed_count++; 361 if (allowed_count == 0) return -1; //no char is allowed 362 int rnd_index = rndUint(allowed_count) + 1; 363 allowed_count = 0; 364 for (size_t i = 0; i < strlen(choices); i++) 365 { 366 if (!strchrn0(excluded, choices[i])) allowed_count++; 367 if (allowed_count == rnd_index) return int(i); 368 } 369 return -1; //never happens 370 } 371 372 NeuroClass *GenoOperators::parseNeuroClass(char *&s, ModelEnum::ShapeType supported_shapetype) 358 NeuroClass *GenoOperators::parseNeuroClass(char *&s, ModelEnum::ShapeType for_shape_type) 373 359 { 374 360 int maxlen = (int)strlen(s); … … 378 364 { 379 365 NeuroClass *nci = Neuro::getClass(i); 380 if (!nci->isShapeTypeSupported( supported_shapetype))366 if (!nci->isShapeTypeSupported(for_shape_type)) 381 367 continue; 382 368 const char *nciname = nci->name.c_str(); … … 434 420 } 435 421 422 bool GenoOperators::canStartNeuroClassName(const char firstchar) 423 { 424 return isupper(firstchar) || firstchar == '|' || firstchar == '@' || firstchar == '*'; 425 } 426 436 427 bool GenoOperators::isWS(const char c) 437 428 { … … 466 457 } 467 458 468 bool GenoOperators::canStartNeuroClassName(const char firstchar) 469 { 470 return isupper(firstchar) || firstchar == '|' || firstchar == '@' || firstchar == '*'; 471 } 459 int GenoOperators::getRandomChar(const char *choices, const char *excluded) 460 { 461 int allowed_count = 0; 462 for (size_t i = 0; i < strlen(choices); i++) if (!strchrn0(excluded, choices[i])) allowed_count++; 463 if (allowed_count == 0) return -1; //no char is allowed 464 int rnd_index = rndUint(allowed_count) + 1; 465 allowed_count = 0; 466 for (size_t i = 0; i < strlen(choices); i++) 467 { 468 if (!strchrn0(excluded, choices[i])) allowed_count++; 469 if (allowed_count == rnd_index) return int(i); 470 } 471 return -1; //never happens 472 } 473 474 //#include <cassert> 475 string GenoOperators::simplifiedModifiers(const char *str_of_char_pairs, vector<int> &char_counts) 476 { 477 // assert(strlen(str_of_char_pairs) == char_counts.size()); 478 // assert(char_counts.size() % 2 == 0); 479 const int MAX_NUMBER_SAME_TYPE = 8; // max. number of modifiers of each type = 8 (mainly for Rr) 480 string simplified; 481 //#define CLUMP_IDENTICAL_MODIFIERS //not good because properties are calculated incrementally, non-linearly, and their values are updated after each modifier character, so these values may for example saturate after a large number of identical modifier symbols. The order of modifiers is in general relevant and extreme values of properties increase this relevance, so better keep the modifiers dispersed. 482 #ifdef CLUMP_IDENTICAL_MODIFIERS 483 for (size_t i = 0; i < strlen(str_of_char_pairs); i++) 484 if ((i % 2) == 0) //only even index "i" in str_of_char_pairs 485 for (int j = 0; j < std::min(MAX_NUMBER_SAME_TYPE, abs(char_counts[i] - char_counts[i + 1])); j++) //assume that an even-index char and the following odd-index char have the opposite influence, so they cancel out. 486 simplified += str_of_char_pairs[i + (char_counts[i + 1] > char_counts[i])]; //inner loop adds a sequence of same chars such as rrrrr or QQQ 487 #else 488 for (size_t i = 0; i < strlen(str_of_char_pairs); i++) 489 if ((i % 2) == 0) //only even index "i" in str_of_char_pairs 490 { 491 char_counts[i] -= char_counts[i + 1]; //from now on, even items in the vector store the difference between antagonistic modifier symbols; odd items are not needed 492 char_counts[i] = std::min(std::max(char_counts[i], -MAX_NUMBER_SAME_TYPE), MAX_NUMBER_SAME_TYPE); 493 } 494 int remaining; 495 do { 496 remaining = 0; 497 for (size_t i = 0; i < strlen(str_of_char_pairs); i++) 498 if ((i % 2) == 0) //only even index "i" in str_of_char_pairs 499 if (char_counts[i] != 0) 500 { 501 simplified += str_of_char_pairs[i + (char_counts[i] < 0)]; 502 char_counts[i] += char_counts[i] > 0 ? -1 : +1; //decrease the difference towards zero 503 remaining += abs(char_counts[i]); 504 } 505 } while (remaining > 0); 506 #endif 507 return simplified; 508 } -
cpp/frams/genetics/genooperators.h
r1226 r1233 121 121 \retval GENOPER_OPFAIL 122 122 \sa 123 Mutation example to illustrate the exchange of pointers for \ egeno.124 The mutation adds random letter at the beginning or removes last letter from \ egeno.123 Mutation example to illustrate the exchange of pointers for \a geno. 124 The mutation adds random letter at the beginning or removes last letter from \a geno. 125 125 \code 126 126 { … … 144 144 virtual int mutate(char *&geno, float& chg, int &method) { method = -1; chg = -1; return GENOPER_NOOPER; } 145 145 146 /**Crosses over two genotypes. It is sufficient to return only one child (in \ e g1) and set \e chg1 only, then \eg2 must equal "".146 /**Crosses over two genotypes. It is sufficient to return only one child (in \a g1) and set \a chg1 only, then \a g2 must equal "". 147 147 148 148 Avoid unnecessary calls in your code. Every genotype argument passed to this … … 167 167 \param geno genotype 168 168 \param pos 0-based char offset 169 \retval number-encoded visual style (and validity) of the genotype char at \ egeno[pos].169 \retval number-encoded visual style (and validity) of the genotype char at \a geno[pos]. 170 170 Assume white background. 171 171 \sa GENSTYLE_* macros, like GENSTYLE_BOLD*/ … … 183 183 static const int NEUROCLASS_PROP_OFFSET = 100; //a NeuroClass property is identified by some functions below as a single-value integer index, yet a property is either "standard" or "extra" (two separate lists), hence this offset to tell one case from the other. 184 184 185 static int roulette(const double *probtab, const int count); ///<returns random index according to probabilities in the \ e probtab table or -1 if all probs are zero. \e count is the number of elements in \eprobtab.185 static int roulette(const double *probtab, const int count); ///<returns random index according to probabilities in the \a probtab table or -1 if all probs are zero. \a count is the number of elements in \a probtab. 186 186 static bool getMinMaxDef(ParamInterface *p, int propindex, double &mn, double &mx, double &def); ///<perhaps a more useful (higher-level) way to obtain min/max/def info for integer and double properties. Returns true if min/max/def was really available (otherwise it is just invented). 187 187 static bool mutateRandomNeuroClassProperty(Neuro* n); ///<high-level neuron mutation function, will select and mutate a random property of Neuron's NeuroClass. Returns true if successful and some property was actually mutated. Could return false when the NeuroClass of the Neuron have no properties, or when a randomly selected property was not suitable for mutation (for example a string or another non-number type). 188 188 static int selectRandomNeuroClassProperty(Neuro* n); ///<selects random property (either 0-based extraproperty of NeuroClass or NEUROCLASS_PROP_OFFSET-based standard property of NeuroClass). -1 if Neuroclass has no properties. 189 static double getMutatedNeuroClassProperty(double current, Neuro *n, int propindex); ///<returns value \ e current mutated for the property \e propindex of Neuron's NeuroClass or for extraproperty (\e propindex - NEUROCLASS_PROP_OFFSET) of Neuron's NeuroClass. Neuro \en is used as read-only.190 static double getMutatedNeuronConnectionWeight(double current); ///<returns mutated value of \ ecurrent.189 static double getMutatedNeuroClassProperty(double current, Neuro *n, int propindex); ///<returns value \a current mutated for the property \a propindex of Neuron's NeuroClass or for extraproperty (\a propindex - NEUROCLASS_PROP_OFFSET) of Neuron's NeuroClass. Neuro \a n is used as read-only. 190 static double getMutatedNeuronConnectionWeight(double current); ///<returns mutated value of \a current. 191 191 static bool mutatePropertyNaive(ParamInterface &p, int propindex); ///<creep-mutate selected property. Returns true when success. mutateProperty() should be used instead of this function. 192 192 static bool mutateProperty(ParamInterface &p, int propindex); ///<like mutatePropertyNaive(), but uses special probability distributions for some neuron properties. 193 static bool getMutatedProperty(ParamInterface &p, int i, double oldval, double &newval); ///<like mutateProperty(), but just returns \ e newval, does not get nor set it using \ep.194 static double mutateCreepNoLimit(char type, double current, double stddev, bool limit_precision_3digits); ///<returns \ e current value creep-mutated with Gaussian distribution and \e stddev standard deviation. Precision limited to 3 digits after comma when \e limit_precision_3digits is true. \etype must be either 'd' (integer) or 'f' (float/double).193 static bool getMutatedProperty(ParamInterface &p, int i, double oldval, double &newval); ///<like mutateProperty(), but just returns \a newval, does not get nor set it using \a p. 194 static double mutateCreepNoLimit(char type, double current, double stddev, bool limit_precision_3digits); ///<returns \a current value creep-mutated with Gaussian distribution and \a stddev standard deviation. Precision limited to 3 digits after comma when \a limit_precision_3digits is true. \a type must be either 'd' (integer) or 'f' (float/double). 195 195 static double mutateCreep(char type, double current, double mn, double mx, double stddev, bool limit_precision_3digits); ///<just as mutateCreepNoLimit(), but forces mutated value into the [mn,mx] range using the 'reflect' approach. 196 static double mutateCreep(char type, double current, double mn, double mx, bool limit_precision_3digits); ///<just as mutateCreepNoLimit(), but forces mutated value into the [\ e mn,\emx] range using the 'reflect' approach and assumes standard deviation to be a fraction of the mx-mn interval width.196 static double mutateCreep(char type, double current, double mn, double mx, bool limit_precision_3digits); ///<just as mutateCreepNoLimit(), but forces mutated value into the [\a mn,\a mx] range using the 'reflect' approach and assumes standard deviation to be a fraction of the mx-mn interval width. 197 197 static void setIntFromDoubleWithProbabilisticDithering(ParamInterface &p, int index, double value); ///<sets a double value in an integer field; when a value is non-integer, applies random "dithering" so that both lower and higher integer value have some chance to be set. 198 198 static void linearMix(vector<double> &p1, vector<double> &p2, double proportion); ///<mixes two real-valued vectors; inherited proportion should be within [0,1]; 1.0 does not change values (all inherited), 0.5 causes both vectors to become their average, 0.0 swaps values (none inherited). 199 199 static void linearMix(ParamInterface &p1, int i1, ParamInterface &p2, int i2, double proportion); ///<mixes i1'th and i2'th properties of p1 and p2; inherited proportion should be within [0,1]; 1.0 does not change values (all inherited), 0.5 causes both properties to become their average, 0.0 swaps values (none inherited). For integer properties applies random "dithering" when necessary. 200 200 201 static int getActiveNeuroClassCount(Model::ShapeType for_shape_type); ///<returns active class count 201 202 static NeuroClass* getRandomNeuroClass(Model::ShapeType for_shape_type); ///<returns random neuroclass or NULL when no active classes. … … 204 205 static NeuroClass* getRandomNeuroClassWithOutputAndWantingNoInputs(Model::ShapeType for_shape_type); ///<returns random sensor or NULL when no active classes. Note: only neuroclasses that prefer 0 inputs are considered, not those that prefer any number of inputs (thus including 0) - see getRandomNeuroClassWithOutputAndWantingNoOrAnyInputs(). 205 206 static NeuroClass* getRandomNeuroClassWithOutputAndWantingNoOrAnyInputs(Model::ShapeType for_shape_type); ///<returns random neuron or NULL when no active classes. Note: both neuroclasses that prefer 0 inputs and those that prefer any number of inputs (thus including 0) are considered. 206 static int getRandomNeuroClassWithOutput(const vector<NeuroClass*>& NClist); ///<returns index of random NeuroClass from the NClist or -1 when no neurons in the list provide output \e NClist list of available neuron classes 207 static int getRandomNeuroClassWithInput(const vector<NeuroClass*>& NClist); ///<returns index of random NeuroClass from the NClist or -1 when no neurons in the list want input(s) \e NClist list of available neuron classes 208 static int getRandomChar(const char *choices, const char *excluded); ///<returns index of a random character from \e choices excluding \e excluded, or -1 when everything is excluded or \e choices is empty. 209 static NeuroClass* parseNeuroClass(char *&s, ModelEnum::ShapeType supported_shapetype); ///<returns the longest matching neuroclass that satisfies supported_shapetype (ModelEnum::SHAPETYPE_BALL_AND_STICK or ModelEnum::SHAPETYPE_SOLIDS) or NULL if the string does not begin with an appropriate neuroclass name. Advances the \e s pointer if the neuroclass is found. 210 static Neuro* findNeuro(const Model *m, const NeuroClass *nc); ///<returns pointer to first Neuro of class \e nc, or NULL if there is no such Neuro. 211 static int neuroClassProp(char *&s, NeuroClass *nc, bool also_v1_N_props = false); ///<returns 0-based extraproperty of NeuroClass or NEUROCLASS_PROP_OFFSET-based standard property of NeuroClass, or -1 if the string does not begin with a valid property name. Advance the \e s pointer if success. 212 static bool isWS(const char c); ///<is \e c a whitespace char? 213 static void skipWS(char *&s); ///<advances pointer \e s skipping whitespaces. 207 static int getRandomNeuroClassWithOutput(const vector<NeuroClass*>& NClist); ///<returns index of random NeuroClass from the NClist or -1 when no neurons in the list provide output \a NClist list of available neuron classes 208 static int getRandomNeuroClassWithInput(const vector<NeuroClass*>& NClist); ///<returns index of random NeuroClass from the NClist or -1 when no neurons in the list want input(s) \a NClist list of available neuron classes 209 static NeuroClass* parseNeuroClass(char *&s, ModelEnum::ShapeType for_shape_type); ///<returns the longest matching neuroclass that supports for_shape_type (ModelEnum::SHAPETYPE_BALL_AND_STICK or ModelEnum::SHAPETYPE_SOLIDS) or NULL if the string does not begin with an appropriate neuroclass name. Advances the \a s pointer if the neuroclass is found. 210 static Neuro* findNeuro(const Model *m, const NeuroClass *nc); ///<returns pointer to first Neuro of class \a nc, or NULL if there is no such Neuro. 211 static int neuroClassProp(char *&s, NeuroClass *nc, bool also_v1_N_props = false); ///<returns 0-based extraproperty of NeuroClass or NEUROCLASS_PROP_OFFSET-based standard property of NeuroClass, or -1 if the string does not begin with a valid property name. Advance the \a s pointer if success. 212 static bool canStartNeuroClassName(const char firstchar); ///<determines if \a firstchar may start NeuroClass name. If not, it might start NeuroClass' (or Neuro's) property name. 213 214 static bool isWS(const char c); ///<is \a c a whitespace char? 215 static void skipWS(char *&s); ///<advances pointer \a s skipping whitespaces. 214 216 static bool areAlike(char*, char*); ///<compares two text strings skipping whitespaces. Returns 1 when equal, 0 when different. 215 static char* strchrn0(const char *str, char ch); ///<like strchr, but does not find zero char in \ estr.216 static bool canStartNeuroClassName(const char firstchar); ///<determines if \e firstchar may start NeuroClass name. If not, it might start NeuroClass' (or Neuro's) property name. 217 218 217 static char* strchrn0(const char *str, char ch); ///<like strchr, but does not find zero char in \a str. 218 219 static int getRandomChar(const char *choices, const char *excluded); ///<returns index of a random character from \a choices excluding \a excluded, or -1 when everything is excluded or \a choices is empty. 220 static string simplifiedModifiers(const char *str_of_char_pairs, vector<int> &char_counts); ///<returns a sequence of chars from \a str_of_char_pairs based on how many times each char occurred in \a char_counts. Assume that an even-index char and the following odd-index char have the opposite influence, so they cancel out. 219 221 //@} 220 222 };
Note: See TracChangeset
for help on using the changeset viewer.