source: cpp/frams/genetics/oper_fx.cpp @ 120

Last change on this file since 120 was 119, checked in by Maciej Komosinski, 11 years ago

reorganization of genetic sources (makefiles not updated yet)

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1// This file is a part of the Framsticks GenoFX library.
2// Copyright (C) 2002-2011  Maciej Komosinski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include <ctype.h>  //isupper()
6#include "geno_fx.h"
7#include <common/framsg.h>
8#include <common/nonstd_math.h>
9#include <frams/util/rndutil.h>
10
11static double distrib_force[]=   // for '!'
12{
133,                 // distribution 0 -__/ +1
140.001, 0.2,        // "slow" neurons
150.001, 1,
16    1, 1,          // "fast" neurons
17};
18static double distrib_inertia[]=  // for '='
19{
202,                 // distribution 0 |..- +1
21  0, 0,            // "fast" neurons
220.7, 0.98,
23};
24static double distrib_sigmo[]=  // for '/'
25{
265,                 // distribution -999 -..-^-..- +999
27-999, -999,        //"perceptron"
28 999, 999,
29  -5, -1,          // nonlinear
30   1, 5,
31  -1, 1,           // ~linear
32};
33
34
35int Geno_fx::roulette(const double *probtab,const int count)
36{
37   double sum=0;
38   int i;
39   for (i=0;i<count;i++) sum+=probtab[i];
40   double sel=rnd01*sum;
41   for (sum=0,i=0;i<count;i++) {sum+=probtab[i]; if (sel<sum) return i;}
42   return -1;
43}
44
45bool Geno_fx::getMinMaxDef(ParamInterface *p,int i,double &mn,double &mx,double &def)
46{
47   mn=mx=def=0;
48   int defined=0;
49   if (p->type(i)[0]=='f')
50   {
51      double _mn=0,_mx=1,_def=0.5;
52      defined=p->getMinMax(i,_mn,_mx,_def);
53      if (defined==1) _mx=_mn+1.0;
54      if (_mx<_mn && defined==3) _mn=_mx=_def; //only default was defined, let's assume min=max=default
55      if (defined<3) _def=(_mn+_mx)/2.0;
56      mn=_mn; mx=_mx; def=_def;
57   }
58   if (p->type(i)[0]=='d')
59   {
60      long _mn=0,_mx=1,_def=0;
61      defined=p->getMinMax(i,_mn,_mx,_def);
62      if (defined==1) _mx=_mn+1;
63      if (_mx<_mn && defined==3) _mn=_mx=_def; //only default was defined, let's assume min=max=default
64      if (defined<3) _def=(_mn+_mx)/2;
65      mn=_mn; mx=_mx; def=_def;
66   }
67   return defined==3;
68}
69
70int Geno_fx::selectRandomProperty(Neuro* n)
71{
72   int neuext=n->extraProperties().getPropCount(),
73       neucls=n->getClass()==NULL?0:n->getClass()->getProperties().getPropCount();
74   if (neuext+neucls==0) return -1; //no properties in this neuron
75   int index=randomN(neuext+neucls);
76   if (index>=neuext) index=index-neuext+100;
77   return index;
78}
79
80double Geno_fx::mutateNeuProperty(double current,Neuro *n,int i)
81{
82   if (i==-1) return mutateCreepNoLimit('f',current,-10,10); //i==-1: mutating weight of neural connection
83   Param p;
84   if (i>=100) {i-=100; p=n->getClass()->getProperties();}
85      else p=n->extraProperties();
86   double newval=current;
87   /*bool ok=*/getMutatedProperty(p,i,current,newval);
88   return newval;
89}
90
91bool Geno_fx::mutatePropertyNaive(ParamInterface &p,int i)
92{
93   double mn,mx,df;
94   if (p.type(i)[0]!='f' && p.type(i)[0]!='d') return false; //don't know how to mutate
95   getMinMaxDef(&p,i,mn,mx,df);
96
97   ExtValue ev;
98   p.get(i,ev);
99   ev.setDouble(mutateCreep(p.type(i)[0],ev.getDouble(),mn,mx));
100   p.set(i,ev);
101   return true;
102}
103
104bool Geno_fx::mutateProperty(ParamInterface &p,int i)
105{
106   double newval;
107   ExtValue ev;
108   p.get(i,ev);
109   bool ok=getMutatedProperty(p,i,ev.getDouble(),newval);
110   if (ok) {ev.setDouble(newval); p.set(i,ev);}
111   return ok;
112}
113
114bool Geno_fx::getMutatedProperty(ParamInterface &p,int i,double oldval,double &newval)
115{
116   newval=0;
117   if (p.type(i)[0]!='f' && p.type(i)[0]!='d') return false; //don't know how to mutate
118   const char *n=p.id(i),*na=p.name(i);
119     if (strcmp(n,"si")==0 && strcmp(na,"Sigmoid")==0) newval=CustomRnd(distrib_sigmo); else
120     if (strcmp(n,"in")==0 && strcmp(na,"Inertia")==0) newval=CustomRnd(distrib_inertia); else
121     if (strcmp(n,"fo")==0 && strcmp(na,"Force")==0) newval=CustomRnd(distrib_force); else
122     {
123       double mn,mx,df;
124       getMinMaxDef(&p,i,mn,mx,df);
125       newval=mutateCreep(p.type(i)[0],oldval,mn,mx);
126     }
127   return true;
128}
129
130double Geno_fx::mutateCreepNoLimit(char type,double current,double mn,double mx)
131{
132   double result=RndGen.Gauss(current,(mx-mn)/2/5); // /halfinterval, 5 times narrower
133   if (type=='d') {result=int(result+0.5); if (result==current) result+=randomN(2)*2-1;}
134    else result=floor(result*1000+0.5)/1000.0; //round
135   return result;
136}
137
138double Geno_fx::mutateCreep(char type,double current,double mn,double mx)
139{
140   double result=mutateCreepNoLimit(type,current,mn,mx); //TODO consider that when boundary is touched (reflect/absorb below), the default precision (3 digits) may change. Is it good or bad?
141   //reflect:
142   if (result>mx) result=mx-(result-mx); else
143    if (result<mn) result=mn+(mn-result);
144   //absorb (just in case 'result' exceeded the allowed range so much):
145   if (result>mx) result=mx; else
146    if (result<mn) result=mn;
147   return result;
148}
149
150NeuroClass* Geno_fx::getRandomNeuroClass()
151{
152        SListTempl<NeuroClass*> active;
153   for(int i=0;i<Neuro::getClassCount();i++)
154      if (Neuro::getClass(i)->genactive) active+=Neuro::getClass(i);
155   if (!active==0) return NULL; else return active(randomN(!active));
156}
157
158NeuroClass* Geno_fx::parseNeuroClass(char*& s)
159{
160   int len=strlen(s);
161   int Len=0;
162   NeuroClass *I=NULL;
163   for(int i=0;i<Neuro::getClassCount();i++)
164   {
165      const char *n=Neuro::getClass(i)->name;
166      int l=strlen(n);
167      if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=Neuro::getClass(i); Len=l;}
168   }
169   s+=Len;
170   return I;
171}
172
173Neuro* Geno_fx::findNeuro(const Model *m,const NeuroClass *nc)
174{
175  if (!m) return NULL;
176  for(int i=0;i<m->getNeuroCount();i++)
177     if (m->getNeuro(i)->getClass()==nc) return m->getNeuro(i);
178  return NULL; //neuron of class 'nc' was not found
179}
180
181int Geno_fx::neuroClassProp(char*& s,NeuroClass *nc,bool also_v1_N_props)
182{
183   int len=strlen(s);
184   int Len=0,I=-1;
185   if (nc)
186   {
187      Param p=nc->getProperties();
188      for(int i=0;i<p.getPropCount();i++)
189      {
190         const char *n=p.id(i);
191         int l=strlen(n);
192         if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=100+i; Len=l;}
193         if (also_v1_N_props) //recognize old properties symbols /=!
194         {
195            if (strcmp(n,"si")==0) n="/"; else
196            if (strcmp(n,"in")==0) n="="; else
197            if (strcmp(n,"fo")==0) n="!";
198            l=strlen(n);
199            if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=100+i; Len=l;}
200         }
201      }
202   }
203   Neuro n;
204   Param p=n.extraProperties();
205   for(int i=0;i<p.getPropCount();i++)
206   {
207      const char *n=p.id(i);
208      int l=strlen(n);
209      if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=i; Len=l;}
210   }
211   s+=Len;
212   return I;
213}
214
215bool Geno_fx::isWS(const char c)
216{return c==' ' || c=='\n' || c=='\t' || c=='\r';}
217
218void Geno_fx::skipWS(char *&s)
219{ if (!s) FramMessage("Geno_fx","skipWS","NULL reference!",1); else
220     while (isWS(*s)) s++;
221}
222
223bool Geno_fx::areAlike(char *g1,char *g2)
224{
225        while (*g1 || *g2)
226        {
227                skipWS(g1);
228                skipWS(g2);
229                if (*g1 != *g2) return false; //when difference
230      if (!*g1 && !*g2) break; //both end
231      g1++;
232      g2++;
233        }
234        return true; //equal
235}
236
237char* Geno_fx::strchrn0(const char *str,char ch)
238{ return ch==0?NULL:strchr((char*)str,ch); }
239
240bool Geno_fx::isNeuroClassName(const char firstchar)
241{
242   return isupper(firstchar) || firstchar=='|' || firstchar=='@' || firstchar=='*';
243}
244
Note: See TracBrowser for help on using the repository browser.