Changeset 1258 for cpp/frams/genetics/f1


Ignore:
Timestamp:
06/22/23 03:50:59 (11 months ago)
Author:
Maciej Komosinski
Message:

f1->f0 conversion settings: modifier compatibility, 'C' and 'Q' modifier influence, bending muscle default range

Location:
cpp/frams/genetics/f1
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/f1/f1_conv.cpp

    r1247 r1258  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2023  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1414//#define v1f1COMPATIBLE //as in ancient Framsticks 1.x
    1515
     16#define FIELDSTRUCT GenoConv_f1
     17static ParamEntry f1_conv_paramtab[] =
     18{
     19        { "Genetics: Converters: f1 to f0", 1, 3, },
     20        { "conv_f1_f0_modcompat", 1, 0, "Modifier compatibility", "d 0 1 1 ~Before June 2023~Modern", FIELD(settings.modifier_compatibility), "The modern implementation makes the influence of modifiers more consistent and uniform, and the extreme property values are easier to reach with a lower number of characters, which improves the topology for evolutionary search.\nPrevious implementation can be enabled for compatibility, for example when you want to test old genotypes." },
     21        { "conv_f1_f0_cq_influence", 1, 0, "'C' and 'Q' modifier influence", "d 0 1 1 ~Before June 2023~Modern", FIELD(settings.cq_mod_influence), "'C' and 'Q' modifier semantics was changed in June 2023. Previously they did not affect the stick immediately following the current sequence of modifiers. In the modern implementation, all modifiers consistently start their influence at the very next stick that is being created in the current branch.\nExample:\nIn the old interpretation of 'XcXX', only the last stick is rotated, because 'c' starts its influence at the stick that occurs after the current stick. In the modern implementation, the same effect is achieved with 'XXcX', where 'c' immediately bends the first 'X' that appears after it.\nPrevious implementation can be enabled for compatibility, for example when you want to test old genotypes." },
     22        { "conv_f1_f0_branch_muscle_range", 1, 0, "Bending muscle default range", "d 0 2 0 ~Full/NumberOfBranches~Full/(NumberOfBranches+1)~Full", FIELD(settings.branch_muscle_range), "Determines how the bending muscle default turning range is limited when the muscle is controlling a stick growing from a branching point that has 'NumberOfBranches' sticks separated by commas. The motivation of the limited range is to keep the neighboring sticks from intersecting when they are bent by muscles. This constraint may degrade the performance (e.g. velocity) of creatures, but this default value can be overridden by providing a specific range property value for the '|' muscle neuron in the genotype.\n"
     23          "- Full/NumberOfBranches - a compromise between the two other settings.\n"
     24          "- Full/(NumberOfBranches+1) - because the originating stick also counts as a branch. This setting guarantees that in the worst case, when at least two neighboring branches have sticks controlled by bending muscles and their controlling signals are at extreme values, the sticks can touch and overlap, but will not intersect. This setting is in most cases too strict because (1) all branches are very rarely controlled by muscles, (2) there are often 'empty' branches - multiple commas with no sticks in-between, and (3) the share of the originating stick is effectively wasted because this stick itself has no muscle at the branching point so it will not bend; the muscle bending range is symmetrical and the default range is equal for all muscles in a branching, but the sticks equipped with muscles in a branching are rarely evenly spaced.\n"
     25          "- Full: Always 1 (the complete angle) - because we do not have to care about the physical plausibility and avoid intersecting sticks, and other genetic representations do not impose such constraints, so this full angle setting can be useful as the default bending range when comparing the performance of various genetic encodings."},
     26
     27        { 0, },
     28};
     29#undef FIELDSTRUCT
     30
    1631class Builder
    1732{
    1833public:
    19         Builder(const char*g, int mapping = 0) :invalid(0), genbegin(g), usemapping(mapping), first_part_mapping(NULL), own_first_part_mapping(true), model_energy(0), model_energy_count(0) {}
     34        Builder(GenoConv_f1_Settings& _settings, const char*g, int mapping = 0) :settings(_settings), invalid(0), genbegin(g), usemapping(mapping), first_part_mapping(NULL), own_first_part_mapping(true), model_energy(0), model_energy_count(0)
     35        {
     36                switch (settings.modifier_compatibility)
     37                {
     38                case GenoConv_f1_Settings::MODIF_COMPAT_LEGACY: gp_ops = GeneProps::getLegacyOps(); break;
     39                case GenoConv_f1_Settings::MODIF_COMPAT_ALL_CHANGE_05: gp_ops = GeneProps::getAllChange05Ops(); break;
     40                }
     41        }
    2042        ~Builder() { if (own_first_part_mapping) SAFEDELETE(first_part_mapping); }
     43
     44        GenoConv_f1_Settings& settings;
     45        GenePropsOps* gp_ops;
    2146        char tmp[222];
    2247        bool invalid;
     
    4368        void grow(int part1, const char*g, Pt3D k, GeneProps c, int branching_part);
    4469        void setPartMapping(int p, const char* g);
    45         int growJoint(int part1, int part2, Pt3D &angle, GeneProps &c, const char *g);
     70        int growJoint(int part1, int part2, const Pt3D &angle, const GeneProps &c, const char *g);
    4671        int growPart(GeneProps &c, const char *g);
    4772        const char *skipNeuro(const char *z);
     
    94119}
    95120
     121GenoConv_f1::GenoConv_f1()
     122{
     123        name = "Recursive encoding";
     124        in_format = '1';
     125        mapsupport = 1;
     126
     127        param.setParamTab(f1_conv_paramtab);
     128        param.select(this);
     129        param.setDefault();
     130}
     131
    96132/** main conversion function - with conversion map support */
    97133SString GenoConv_f1::convert(SString &i, MultiMap *map, bool using_checkpoints)
    98134{
    99135        const char* g = i.c_str();
    100         Builder builder(g, map ? 1 : 0);
     136        Builder builder(settings, g, map ? 1 : 0);
    101137        builder.model.open(using_checkpoints);
    102138        builder.grow(-1, g, Pt3D_0, GeneProps::standard_values, -1); // uses Model::addFromString() to create model elements
     
    125161{
    126162        int hasmuscles = 0;
    127         k += Pt3D(c.twist, 0, c.curvedness);
     163        if (settings.cq_mod_influence == settings.CQ_INFLUENCE_OLD)
     164                k += Pt3D(c.twist, 0, c.curvedness);
    128165        while (1)
    129166        {
    130                 if (c.executeModifier(*g) == 0)
     167                if (c.executeModifier(*g, gp_ops) == 0)
    131168                {
    132169                        setPartMapping(part1, g);
     
    177214                                {
    178215                                        Part *part = model.getPart(part1);
    179                                         part->density = ((part->mass*part->density) + 1.0 / c.weight) / (part->mass + 1.0); // v=m*d
     216                                        part->density = ((part->mass * part->density) + 1.0 / c.weight) / (part->mass + 1.0); // v=m*d
    180217                                        //                      part->volume+=1.0/c.weight;
    181218                                        part->mass += 1.0;
    182219                                }
    183                                 model_energy += c.energy;
     220
     221                                if (settings.modifier_compatibility == settings.MODIF_COMPAT_LEGACY)
     222                                        model_energy += 0.9 * c.energy + 0.1;
     223                                else
     224                                        model_energy += c.energy;
    184225                                model_energy_count++;
    185226
    186227                                int part2 = growPart(c, g);
    187                                 growJoint(part1, part2, k, c, g);
     228                                Pt3D new_k;
     229                                switch (settings.cq_mod_influence)
     230                                {
     231                                case GenoConv_f1_Settings::CQ_INFLUENCE_OLD: new_k = k; break;
     232                                case GenoConv_f1_Settings::CQ_INFLUENCE_NEW: new_k = k + Pt3D(c.twist, 0, c.curvedness); break;
     233                                }
     234                                growJoint(part1, part2, new_k, c, g);
    188235                                //              est* e = new est(*s,*s2,k,c,zz,this);
    189236
     
    201248                                int count = countBranches(g + 1, ga);
    202249                                c.muscle_reset_range = false;
    203                                 c.muscle_bend_range = 1.0 / count;
     250                                switch (settings.branch_muscle_range)
     251                                {
     252                                case GenoConv_f1_Settings::MUSCLE_RANGE_ORIGINAL:
     253                                        c.muscle_bend_range = 1.0 / count;
     254                                        break;
     255                                case GenoConv_f1_Settings::MUSCLE_RANGE_STRICT:
     256                                        c.muscle_bend_range = 1.0 / (count + 1);
     257                                        break;
     258                                case GenoConv_f1_Settings::MUSCLE_RANGE_UNLIMITED:
     259                                        c.muscle_bend_range = 1.0;
     260                                        break;
     261                                }
    204262                                for (int i = 0; i < count; i++)
    205                                         grow(part1, (char*)ga(i), k + Pt3D(0, 0, -M_PI + (i + 1)*(2 * M_PI / (count + 1))), c, part1);
     263                                        grow(part1, (char*)ga(i), k + Pt3D(0, 0, -M_PI + (i + 1) * (2 * M_PI / (count + 1))), c, part1);
    206264                                return;
    207265                        }
     
    270328}
    271329
    272 int Builder::growJoint(int part1, int part2, Pt3D &angle, GeneProps &c, const char *g)
     330int Builder::growJoint(int part1, int part2, const Pt3D &angle, const GeneProps &c, const char *g)
    273331{
    274332        double len = std::min(2.0, c.length);
     
    309367        if (*t && *next != ',' && *next != ']') // old style muscles [|rest] or [@rest]
    310368                switch (*t)
    311         {
     369                {
    312370                case '@': if (t[1] == ':') break;
    313371                        haveclass = 1;
     
    338396                        t++;
    339397                        break;
    340         }
     398                }
    341399        while (*t && *t <= ' ') t++;
    342400        bool finished = 0;
  • cpp/frams/genetics/f1/f1_conv.h

    r779 r1258  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2023  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    5151
    5252 */
     53
     54struct GenoConv_f1_Settings
     55{
     56        paInt modifier_compatibility, cq_mod_influence, branch_muscle_range;
     57
     58        static constexpr int MODIF_COMPAT_LEGACY = 0;
     59        static constexpr int MODIF_COMPAT_ALL_CHANGE_05 = 1;
     60
     61        static constexpr int CQ_INFLUENCE_OLD = 0;
     62        static constexpr int CQ_INFLUENCE_NEW = 1;
     63
     64        static constexpr int MUSCLE_RANGE_ORIGINAL = 0;
     65        static constexpr int MUSCLE_RANGE_STRICT = 1;
     66        static constexpr int MUSCLE_RANGE_UNLIMITED = 2;
     67};
     68
    5369class GenoConv_f1 : public GenoConverter
    5470{
    5571public:
    56         GenoConv_f1()
    57         {
    58                 name = "Recursive encoding";
    59                 in_format = '1';
    60                 mapsupport = 1;
    61         }
     72        GenoConv_f1();
    6273        SString convert(SString &i, MultiMap *map, bool using_checkpoints);
    6374        ~GenoConv_f1() {}
     75
     76        GenoConv_f1_Settings settings;
     77
     78        Param param;
     79        ParamInterface* getParam() { return &param; }
    6480};
    6581
Note: See TracChangeset for help on using the changeset viewer.