source: cpp/frams/_demos/genomanipulation.cpp @ 534

Last change on this file since 534 was 534, checked in by Maciej Komosinski, 3 years ago

Renamed: get/setGene -> get/setGenes, setGeneOnly -> setGenesAssumingSameFormat

  • Property svn:eol-style set to native
File size: 12.4 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <time.h>
8#include <common/virtfile/stdiofile.h>
9
10#include <frams/model/model.h>
11#include <frams/genetics/preconfigured.h>
12#include <common/loggers/loggertostdout.h>
13
14/**
15 @file
16 Sample code: Accessing model elements
17*/
18
19PreconfiguredGenetics genetics;
20
21void printNiceBanner(const char* title)
22{
23printf("    #############################################\n"
24       "   ##                                           ##\n"
25       "  ##    %-37s    ##\n"
26       "   ##                                           ##\n"
27       "    #############################################\n",title);
28}
29void printProperties(Param &pi)
30{
31printf(" #        id                      type  name        group (%d properties)\n",pi.getPropCount());
32for (int i=0;i<pi.getPropCount();i++)
33        {
34        const char* type=pi.type(i);
35        if (*type=='p') continue;
36        printf("%2d. %8s = %-20s %-3s %-10s  %-10s\n",i,pi.id(i),pi.get(i).c_str(),pi.type(i),pi.name(i),pi.grname(pi.group(i)));
37        }
38}
39
40#define PRINT_PROPERTIES(p) {Param tmp_param(p); printProperties(tmp_param);}
41
42void changeOneProperty(Param &pi)
43{
44if (pi.getPropCount()<=0) return;
45int i=rand() % pi.getPropCount();
46double maxprop=1,minprop=0,def;
47pi.getMinMax(i,minprop,maxprop,def);
48printf("      Change property #%d to random value from range [%g..%g]\n",i,minprop,maxprop);
49printf("      Current value of '%s' (%s) is '%s'\n",pi.id(i),pi.name(i),pi.get(i).c_str());
50char t[100];
51sprintf(t,"%g",minprop+(rnd01)*(maxprop-minprop));
52printf("      Setting new value... [ using ParamInterface::set() ]\n");
53pi.set(i,t);
54printf("      The value is now '%s'\n",pi.get(i).c_str());
55}
56
57#define CHANGE_ONE_PROPERTY(p) {Param tmp_param(p); changeOneProperty(tmp_param);}
58
59void moreAboutPart(Part* p)
60{
61printf("Here is the full listing of properties as they are printed in f0\n"
62       " (please compare with f0 genotype).\n"
63       "Some properties have special meaning (eg. geometry and connections groups)\n"
64       "and should be handled with care, because they influence other elements of the model.\n\n"
65       " [this data is provided by Part::properties() ]\n");
66PRINT_PROPERTIES(p->properties());
67printf("\nHowever, there is a subset of properties which may be modified more freely.\n"
68       "Properties on this list are related only to this part and can be changed\n"
69       "without much consideration. They are guaranteed to be always valid; any inconsistencies\n"
70       "will be silently repaired.\n"
71       "\n [this data is provided by Part::extraProperties() ]\n");
72PRINT_PROPERTIES(p->extraProperties());
73printf("\nThis set of properties can vary from release to release,\n"
74       "but can be safely accessed by using extraProperties() call.\n"
75           "This method accesses the full set of properies (even those\n"
76           "which appear in future releases).\n"
77       "Now we will try to change some of properties:\n\n");
78p->getModel().open();
79CHANGE_ONE_PROPERTY(p->extraProperties());
80p->getModel().close();
81printf("\nLet's see f0... (check out part #%d !)\n\n%s\n", p->refno, p->getModel().getF0Geno().getGenes().c_str());
82}
83
84void playWithAbsolute(Joint *j)
85{
86printf("\nAbsolute Joints adapt to its Parts' positions.\n"
87       "We can move a Part, and it does not influence the second part, nor the Joint.\n"
88       "Let's move the first Part along y axis by -0.1...\n");
89j->getModel().open();
90j->part1->p.y-=0.1;
91j->getModel().close();
92printf("The Part's position is changed, but everything else stays intact:\n\n%s\n",
93       j->getModel().getF0Geno().getGenes().c_str());
94}
95
96void playWithDelta(Joint *j)
97{
98printf("\nDelta fields (dx,dy,dz) describe relative location of the second part.\n"
99       "This joint will change the second Part's positions to preserve delta distance.\n"
100       "Let's move the first Part (#%d) along y axis (+0.1) and change delta.z (dz) by 0.1.\n",j->part1->refno);
101j->getModel().open();
102j->part1->p.y+=0.1;
103j->d.z+=0.1;
104j->getModel().close();
105printf("Position of the second Part referenced by this joint (part #%d) is now changed:\n\n%s\n",
106       j->part2->refno, j->getModel().getF0Geno().getGenes().c_str());
107printf("If no delta fields are defined, they will be computed automatically.\n"
108       "You can always delete existing delta values by using Joint::resetDelta().\n"
109       "Now we will change the second Part's z position by -0.2 and call resetDelta()...\n");
110j->getModel().open();
111j->part2->p.z-=0.2;
112j->resetDelta();
113j->getModel().close();
114printf("As you can see, Joint's delta fields have altered:\n\n%s\n", j->getModel().getF0Geno().getGenes().c_str());
115}
116
117void switchDelta(Joint *j)
118{
119int option=! j->isDelta();
120printf("How would this joint look like with delta option %s?\n[ by calling Joint::useDelta(%d) ]\n",option?"enabled":"disabled",option);
121j->getModel().open();
122j->useDelta( ! j->isDelta() );
123j->getModel().close();
124printf("f0 is now:\n\n%s\n...so this is %s joint.\n",
125       j->getModel().getF0Geno().getGenes().c_str(), option?"a delta":"an absolute");
126
127}
128
129void moreAboutJoint(Joint* j)
130{
131printf("Similarly as with Part, the full list of properties comes first:\n\n");
132PRINT_PROPERTIES(j->properties());
133printf("\nActually, there are two kinds of Joints: delta and absolute.\n"
134       "For this object, Joint::isDelta() returns %d, so this is the %s Joint.\n",
135       j->isDelta(),j->isDelta()?"delta":"absolute");
136if (j->isDelta())
137        {
138        playWithDelta(j);
139        switchDelta(j);
140        playWithAbsolute(j);
141        }
142else
143        {
144        playWithAbsolute(j);
145        switchDelta(j);
146        playWithDelta(j);
147        }
148
149printf("Part references and delta fields are the 'core' properties of the Joint.\n"
150       "The other properties are available from Joint::extraProperties()\n"
151       "and at the moment are defined as follows:\n\n");
152PRINT_PROPERTIES(j->extraProperties());
153printf("\nThey can be changed just like Part's extra properties:\n");
154j->getModel().open();
155CHANGE_ONE_PROPERTY(j->extraProperties());
156j->getModel().close();
157printf("And after that we have this genotype:\n\n%s\n", j->getModel().getF0Geno().getGenes().c_str());
158}
159
160
161
162void moreAboutNeuro(Neuro* n)
163{
164printf("Basic features of Neuro object are similar to those of Part and Joint.\n"
165       "We can request a property list:\n\n");
166PRINT_PROPERTIES(n->properties());
167printf("\n...and extra properties (which are designed to be always valid and easy to change):\n\n");
168PRINT_PROPERTIES(n->extraProperties());
169printf("\nAs usual, we will change something:\n");
170n->getModel().open();
171CHANGE_ONE_PROPERTY(n->extraProperties());
172n->getModel().close();
173printf("Each neuron can have any number of inputs = weighted connections\n with other neurons.\n"
174       "According to Neuro::getInputCount(), this one has %d inputs.\n",n->getInputCount());
175printf("Standard API is provided for accessing those inputs (getInput(int)),\n"
176       "adding inputs (addInput(Neuro*)) and removing them (removeInput(int)).\n\n");
177
178printf("\nThe most unusual thing is 'details' field (d).\n"
179       "It is something like separate object with its own set of properties.\n"
180       "Currently the value of 'd' is '%s'.\n",n->getDetails().c_str());
181
182{
183NeuroClass* cl=n->getClass();
184if (!cl)
185        printf("It should contain the class name but the meaning of '%s' is unknown\n",n->getDetails().c_str());
186else
187{
188
189printf("'%s' is the class name (Neuro::getClassName() == '%s') and means '%s'.\n",
190       cl->getName().c_str(),cl->getName().c_str(),cl->getLongName().c_str());
191printf("Neuro::getClass() gives you information about basic characteristic\n"
192       "of the class, that can be analyzed automatically.\n");
193printf("For the current object we can learn that it supports ");
194if (cl->getPreferredInputs()<0) printf("any number of inputs");
195  else if (cl->getPreferredInputs()==0) printf("no inputs");
196  else printf("%d inputs",cl->getPreferredInputs());
197printf(" (getPreferredInputs()) ");
198printf(cl->getPreferredOutput()?"and provides meaningful output signal (getPreferredOutput()==1).\n":"and doesn't provide useful output signal (getPreferredOutput()==0).\n");
199
200SyntParam p=n->classProperties();
201if (p.getPropCount()>0)
202        {
203        printf("The class defines its own properties:\n\n [ data provided by Neuro::classProperties() ]\n");
204        printProperties(p);
205        printf("and they can be changed:\n");
206        n->getModel().open();
207        changeOneProperty(p);
208        p.update();
209        n->getModel().close();
210        printf("After that, 'details' contains the new object: '%s'.\n",n->getDetails().c_str());
211        }
212else
213        printf("(This class does not have its own properties\n"
214               " - Neuro::classProperties().getPropCount()==0)\n");
215}
216}
217
218printf("The class of this object can be changed using Neuro::setClassName()\n"
219       "The following classes are available:\n"
220       " [ data provided by Neuro::getClassInfo()->getProperties() ]\n\n");
221printf(" #  class  description       properties\n");
222for (int i=0;i<n->getClassCount();i++)
223        {
224        NeuroClass* cl=n->getClass(i);
225        Param p=cl->getProperties();
226        printf("%2d.%6s  %-20s  %2d\n",i,cl->getName().c_str(),cl->getLongName().c_str(),p.getPropCount());
227        }
228int cl=rand() % n->getClassCount();
229printf("\nLet's change the Neuro's class to '%s'...\n",n->getClassName(cl).c_str());
230n->getModel().open();
231n->setClass(n->getClass(cl));
232{
233SyntParam p=n->classProperties();
234if (p.getPropCount()>0)
235        {
236        printProperties(p);
237        changeOneProperty(p);
238        p.update();
239        }
240}
241
242if (n->getInputCount()>0)
243{
244        printf("Info for input #0 = \"%s\"\n",n->getInputInfo(0).c_str());
245        printf("Info for input #0, field \"%s\" = \"%s\"\n", "abc", n->getInputInfo(0,"abc").c_str());
246        n->setInputInfo(0,"test",44);
247        n->setInputInfo(0,"abc","yeah");
248}
249
250n->getModel().close();
251printf("The final object description will be then: '%s'\nAnd the full f0 genotype:\n\n%s\n",
252       n->getDetails().c_str(), n->getModel().getF0Geno().getGenes().c_str());
253
254
255}
256
257void findingConverters()
258{
259GenoConverter *gc=Geno::getConverters()->findConverters(0,'1');
260if (gc) printf("found converter accepting f1: \"%s\"\n",gc->name);
261SListTempl<GenoConverter*> found;
262Geno::getConverters()->findConverters(&found,-1,'0');
263printf("found %d converter(s) producing f0\n",found.size());
264}
265
266int main(int argc,char*argv[])
267{
268LoggerToStdout messages_to_stdout(LoggerBase::Enable); //redirect model-related errors to stdout
269
270srand(time(0));
271printNiceBanner("Welcome to Genotype Manipulation App!");
272
273findingConverters();
274
275SString gen(argc>1?argv[1]:"X[|G:1.23]");
276if (!strcmp(gen.c_str(),"-"))
277        {
278        gen=0;
279        StdioFILEDontClose in(stdin);
280        loadSString(&in,gen);
281        }
282Geno g(gen);
283printf("\nSource genotype: '%s'\n",g.getGenes().c_str());
284printf("                  ( format %c %s)\n",
285       g.getFormat(), g.getComment().c_str());
286
287Model m(g);//.getConverted('0'));
288
289if (!m.isValid())
290        {
291        printf("Cannot build Model from this genotype!\n");
292        return 2;       
293        }
294printf("Converted to f0:\n%s\n",m.getF0Geno().getGenes().c_str());
295
296printf("Model contains: %d part(s)\n"
297       "                %d joint(s)\n"
298       "                %d neuron(s)\n",m.getPartCount(),m.getJointCount(),m.getNeuroCount());
299
300printf("\nInvestigating details...\n");
301
302if (m.getPartCount()>0)
303        {
304        int p=rand()%m.getPartCount();
305        printNiceBanner("P A R T    O B J E C T");
306        printf("            (part # %d)\n",p);
307        moreAboutPart(m.getPart(p));
308        }
309
310if (m.getJointCount()>0)
311        {
312        int j=rand()%m.getJointCount();
313        printNiceBanner("J O I N T    O B J E C T");
314        printf("            (joint # %d)\n",j);
315        moreAboutJoint(m.getJoint(j));
316        }
317
318if (m.getNeuroCount()>0)
319        {
320        int n=rand()%m.getNeuroCount();
321        printNiceBanner("N E U R O    O B J E C T");
322        printf("            (neuro # %d)\n",n);
323        moreAboutNeuro(m.getNeuro(n));
324        }
325
326#ifdef MODEL_V1_COMPATIBLE
327printNiceBanner("Old Neuro/NeuroItem view");
328int nc=m.old_getNeuroCount();
329printf("Model::old_getNeuroCount() = %d\n",nc);
330for (int i=0;i<nc;i++)
331        {
332        Neuro *n=m.old_getNeuro(i);
333        printf("neuron #%d: p=%d, j=%d, force=%g, inertia=%g, sigmoid=%g\n",
334               i,n->part_refno,n->joint_refno,
335               n->force,n->inertia,n->sigmo);
336        int nicount=n->getItemCount();
337        printf("    %d items\n",nicount);
338        for (int j=0;j<nicount;j++)
339                {
340                NeuroItem *ni=n->getNeuroItem(j);
341                printf("        item #%d - '%s', conn=%d, weight=%g\n",
342                       j,ni->getDetails().c_str(),ni->conn_refno,ni->weight);
343                }
344        }
345printf("end.\n");
346#endif
347
348printf("\n######### THE END ###########\n\n"
349       "Hints:\n"
350       "  1. You can redirect output: genomanipulation >filename.txt\n"
351       "  2. Each run can yield different results, because some\n"
352       "     values are randomly generated.\n"
353       "  3. This application will use custom genotype passed as\n"
354       "     a commandline parameter: genomanipulation XX\n"
355       "\n");
356return 0;
357}
Note: See TracBrowser for help on using the repository browser.