Ignore:
Timestamp:
05/04/23 00:57:57 (12 months ago)
Author:
Maciej Komosinski
Message:

Added a function that simplifies a sequence of modifier genes (useful in f1 and f4 encodings) by removing antagonistic modifier genes and limiting the number of genes of the same kind

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/genooperators.cpp

    r1226 r1233  
    88#include <common/nonstd_math.h>
    99#include <frams/util/rndutil.h>
     10#include <algorithm> // std::min, std::max
    1011
    1112//
     
    355356}
    356357
    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)
     358NeuroClass *GenoOperators::parseNeuroClass(char *&s, ModelEnum::ShapeType for_shape_type)
    373359{
    374360        int maxlen = (int)strlen(s);
     
    378364        {
    379365                NeuroClass *nci = Neuro::getClass(i);
    380                 if (!nci->isShapeTypeSupported(supported_shapetype))
     366                if (!nci->isShapeTypeSupported(for_shape_type))
    381367                        continue;
    382368                const char *nciname = nci->name.c_str();
     
    434420}
    435421
     422bool GenoOperators::canStartNeuroClassName(const char firstchar)
     423{
     424        return isupper(firstchar) || firstchar == '|' || firstchar == '@' || firstchar == '*';
     425}
     426
    436427bool GenoOperators::isWS(const char c)
    437428{
     
    466457}
    467458
    468 bool GenoOperators::canStartNeuroClassName(const char firstchar)
    469 {
    470         return isupper(firstchar) || firstchar == '|' || firstchar == '@' || firstchar == '*';
    471 }
     459int 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>
     475string 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}
Note: See TracChangeset for help on using the changeset viewer.