// This file is a part of the Framsticks GenoFX library. // Copyright (C) 2002-2011 Maciej Komosinski. See LICENSE.txt for details. // Refer to http://www.framsticks.com/ for further information. #include //isupper() #include "geno_fx.h" #include #include #include static double distrib_force[]= // for '!' { 3, // distribution 0 -__/ +1 0.001, 0.2, // "slow" neurons 0.001, 1, 1, 1, // "fast" neurons }; static double distrib_inertia[]= // for '=' { 2, // distribution 0 |..- +1 0, 0, // "fast" neurons 0.7, 0.98, }; static double distrib_sigmo[]= // for '/' { 5, // distribution -999 -..-^-..- +999 -999, -999, //"perceptron" 999, 999, -5, -1, // nonlinear 1, 5, -1, 1, // ~linear }; int Geno_fx::roulette(const double *probtab,const int count) { double sum=0; int i; for (i=0;itype(i)[0]=='f') { double _mn=0,_mx=1,_def=0.5; defined=p->getMinMax(i,_mn,_mx,_def); if (defined==1) _mx=_mn+1.0; if (_mx<_mn && defined==3) _mn=_mx=_def; //only default was defined, let's assume min=max=default if (defined<3) _def=(_mn+_mx)/2.0; mn=_mn; mx=_mx; def=_def; } if (p->type(i)[0]=='d') { long _mn=0,_mx=1,_def=0; defined=p->getMinMax(i,_mn,_mx,_def); if (defined==1) _mx=_mn+1; if (_mx<_mn && defined==3) _mn=_mx=_def; //only default was defined, let's assume min=max=default if (defined<3) _def=(_mn+_mx)/2; mn=_mn; mx=_mx; def=_def; } return defined==3; } int Geno_fx::selectRandomProperty(Neuro* n) { int neuext=n->extraProperties().getPropCount(), neucls=n->getClass()==NULL?0:n->getClass()->getProperties().getPropCount(); if (neuext+neucls==0) return -1; //no properties in this neuron int index=randomN(neuext+neucls); if (index>=neuext) index=index-neuext+100; return index; } double Geno_fx::mutateNeuProperty(double current,Neuro *n,int i) { if (i==-1) return mutateCreepNoLimit('f',current,-10,10); //i==-1: mutating weight of neural connection Param p; if (i>=100) {i-=100; p=n->getClass()->getProperties();} else p=n->extraProperties(); double newval=current; /*bool ok=*/getMutatedProperty(p,i,current,newval); return newval; } bool Geno_fx::mutatePropertyNaive(ParamInterface &p,int i) { double mn,mx,df; if (p.type(i)[0]!='f' && p.type(i)[0]!='d') return false; //don't know how to mutate getMinMaxDef(&p,i,mn,mx,df); ExtValue ev; p.get(i,ev); ev.setDouble(mutateCreep(p.type(i)[0],ev.getDouble(),mn,mx)); p.set(i,ev); return true; } bool Geno_fx::mutateProperty(ParamInterface &p,int i) { double newval; ExtValue ev; p.get(i,ev); bool ok=getMutatedProperty(p,i,ev.getDouble(),newval); if (ok) {ev.setDouble(newval); p.set(i,ev);} return ok; } bool Geno_fx::getMutatedProperty(ParamInterface &p,int i,double oldval,double &newval) { newval=0; if (p.type(i)[0]!='f' && p.type(i)[0]!='d') return false; //don't know how to mutate const char *n=p.id(i),*na=p.name(i); if (strcmp(n,"si")==0 && strcmp(na,"Sigmoid")==0) newval=CustomRnd(distrib_sigmo); else if (strcmp(n,"in")==0 && strcmp(na,"Inertia")==0) newval=CustomRnd(distrib_inertia); else if (strcmp(n,"fo")==0 && strcmp(na,"Force")==0) newval=CustomRnd(distrib_force); else { double mn,mx,df; getMinMaxDef(&p,i,mn,mx,df); newval=mutateCreep(p.type(i)[0],oldval,mn,mx); } return true; } double Geno_fx::mutateCreepNoLimit(char type,double current,double mn,double mx) { double result=RndGen.Gauss(current,(mx-mn)/2/5); // /halfinterval, 5 times narrower if (type=='d') {result=int(result+0.5); if (result==current) result+=randomN(2)*2-1;} else result=floor(result*1000+0.5)/1000.0; //round return result; } double Geno_fx::mutateCreep(char type,double current,double mn,double mx) { 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? //reflect: if (result>mx) result=mx-(result-mx); else if (resultmx) result=mx; else if (result active; for(int i=0;igenactive) active+=Neuro::getClass(i); if (!active==0) return NULL; else return active(randomN(!active)); } NeuroClass* Geno_fx::parseNeuroClass(char*& s) { int len=strlen(s); int Len=0; NeuroClass *I=NULL; for(int i=0;iname; int l=strlen(n); if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=Neuro::getClass(i); Len=l;} } s+=Len; return I; } Neuro* Geno_fx::findNeuro(const Model *m,const NeuroClass *nc) { if (!m) return NULL; for(int i=0;igetNeuroCount();i++) if (m->getNeuro(i)->getClass()==nc) return m->getNeuro(i); return NULL; //neuron of class 'nc' was not found } int Geno_fx::neuroClassProp(char*& s,NeuroClass *nc,bool also_v1_N_props) { int len=strlen(s); int Len=0,I=-1; if (nc) { Param p=nc->getProperties(); for(int i=0;i=l && l>Len && (strncmp(s,n,l)==0)) {I=100+i; Len=l;} if (also_v1_N_props) //recognize old properties symbols /=! { if (strcmp(n,"si")==0) n="/"; else if (strcmp(n,"in")==0) n="="; else if (strcmp(n,"fo")==0) n="!"; l=strlen(n); if (len>=l && l>Len && (strncmp(s,n,l)==0)) {I=100+i; Len=l;} } } } Neuro n; Param p=n.extraProperties(); for(int i=0;i=l && l>Len && (strncmp(s,n,l)==0)) {I=i; Len=l;} } s+=Len; return I; } bool Geno_fx::isWS(const char c) {return c==' ' || c=='\n' || c=='\t' || c=='\r';} void Geno_fx::skipWS(char *&s) { if (!s) FramMessage("Geno_fx","skipWS","NULL reference!",1); else while (isWS(*s)) s++; } bool Geno_fx::areAlike(char *g1,char *g2) { while (*g1 || *g2) { skipWS(g1); skipWS(g2); if (*g1 != *g2) return false; //when difference if (!*g1 && !*g2) break; //both end g1++; g2++; } return true; //equal } char* Geno_fx::strchrn0(const char *str,char ch) { return ch==0?NULL:strchr((char*)str,ch); } bool Geno_fx::isNeuroClassName(const char firstchar) { return isupper(firstchar) || firstchar=='|' || firstchar=='@' || firstchar=='*'; }