Changeset 1258
- Timestamp:
- 06/22/23 03:50:59 (18 months ago)
- Location:
- cpp/frams/genetics/f1
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/f1/f1_conv.cpp
r1247 r1258 1 1 // This file is a part of Framsticks SDK. http://www.framsticks.com/ 2 // Copyright (C) 1999-202 1Maciej Komosinski and Szymon Ulatowski.2 // Copyright (C) 1999-2023 Maciej Komosinski and Szymon Ulatowski. 3 3 // See LICENSE.txt for details. 4 4 … … 14 14 //#define v1f1COMPATIBLE //as in ancient Framsticks 1.x 15 15 16 #define FIELDSTRUCT GenoConv_f1 17 static 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 16 31 class Builder 17 32 { 18 33 public: 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 } 20 42 ~Builder() { if (own_first_part_mapping) SAFEDELETE(first_part_mapping); } 43 44 GenoConv_f1_Settings& settings; 45 GenePropsOps* gp_ops; 21 46 char tmp[222]; 22 47 bool invalid; … … 43 68 void grow(int part1, const char*g, Pt3D k, GeneProps c, int branching_part); 44 69 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); 46 71 int growPart(GeneProps &c, const char *g); 47 72 const char *skipNeuro(const char *z); … … 94 119 } 95 120 121 GenoConv_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 96 132 /** main conversion function - with conversion map support */ 97 133 SString GenoConv_f1::convert(SString &i, MultiMap *map, bool using_checkpoints) 98 134 { 99 135 const char* g = i.c_str(); 100 Builder builder( g, map ? 1 : 0);136 Builder builder(settings, g, map ? 1 : 0); 101 137 builder.model.open(using_checkpoints); 102 138 builder.grow(-1, g, Pt3D_0, GeneProps::standard_values, -1); // uses Model::addFromString() to create model elements … … 125 161 { 126 162 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); 128 165 while (1) 129 166 { 130 if (c.executeModifier(*g ) == 0)167 if (c.executeModifier(*g, gp_ops) == 0) 131 168 { 132 169 setPartMapping(part1, g); … … 177 214 { 178 215 Part *part = model.getPart(part1); 179 part->density = ((part->mass *part->density) + 1.0 / c.weight) / (part->mass + 1.0); // v=m*d216 part->density = ((part->mass * part->density) + 1.0 / c.weight) / (part->mass + 1.0); // v=m*d 180 217 // part->volume+=1.0/c.weight; 181 218 part->mass += 1.0; 182 219 } 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; 184 225 model_energy_count++; 185 226 186 227 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); 188 235 // est* e = new est(*s,*s2,k,c,zz,this); 189 236 … … 201 248 int count = countBranches(g + 1, ga); 202 249 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 } 204 262 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); 206 264 return; 207 265 } … … 270 328 } 271 329 272 int Builder::growJoint(int part1, int part2, Pt3D &angle,GeneProps &c, const char *g)330 int Builder::growJoint(int part1, int part2, const Pt3D &angle, const GeneProps &c, const char *g) 273 331 { 274 332 double len = std::min(2.0, c.length); … … 309 367 if (*t && *next != ',' && *next != ']') // old style muscles [|rest] or [@rest] 310 368 switch (*t) 311 {369 { 312 370 case '@': if (t[1] == ':') break; 313 371 haveclass = 1; … … 338 396 t++; 339 397 break; 340 }398 } 341 399 while (*t && *t <= ' ') t++; 342 400 bool finished = 0; -
cpp/frams/genetics/f1/f1_conv.h
r779 r1258 1 1 // This file is a part of Framsticks SDK. http://www.framsticks.com/ 2 // Copyright (C) 1999-20 18Maciej Komosinski and Szymon Ulatowski.2 // Copyright (C) 1999-2023 Maciej Komosinski and Szymon Ulatowski. 3 3 // See LICENSE.txt for details. 4 4 … … 51 51 52 52 */ 53 54 struct 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 53 69 class GenoConv_f1 : public GenoConverter 54 70 { 55 71 public: 56 GenoConv_f1() 57 { 58 name = "Recursive encoding"; 59 in_format = '1'; 60 mapsupport = 1; 61 } 72 GenoConv_f1(); 62 73 SString convert(SString &i, MultiMap *map, bool using_checkpoints); 63 74 ~GenoConv_f1() {} 75 76 GenoConv_f1_Settings settings; 77 78 Param param; 79 ParamInterface* getParam() { return ¶m; } 64 80 }; 65 81
Note: See TracChangeset
for help on using the changeset viewer.