source: cpp/frams/_demos/gdk_test.cpp @ 180

Last change on this file since 180 was 145, checked in by sz, 11 years ago

Genetics reorganization (affects ALL applications!):

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