forum.alglib.net
http://forum.alglib.net/

Scale Free Evolution Strategy
http://forum.alglib.net/viewtopic.php?f=2&t=1374
Page 1 of 1

Author:  seanvn [ Sun Jan 26, 2014 12:55 am ]
Post subject:  Scale Free Evolution Strategy

You might be interested in this scale free evolution strategy algorithm I devised:
Code:

#include <stdio.h>
#include <stdint.h>
#include <math.h>
// Sean O'Connor 23 January 2014.  Hoang Hoa Tham, Ba Dinh, Hanoi.
// Return the position of the highest set bit.
uint32_t topBit(uint32_t x){         
        return ilogbf(x);
}

// Fill back all bits from the highest set bit.
uint32_t fillBack(uint32_t x){         
        x |= x>>1;
        x |= x>>2;
        x |= x>>4;
        x |= x>>8;
        x |= x>>16;
        return x;
}

// Xorshift128 RNG + inject randomization to allow seeding.
uint32_t rnd32(uint32_t inject){   
  static uint32_t x = 123456789;
  static uint32_t y = 362436069;
  static uint32_t z = 521288629;
  static uint32_t w = 88675123;
  x+=inject;
  uint32_t t = x ^ (x << 11);
  x = y; y = z; z = w;
  w ^= (w >> 19) ^ t ^ (t >> 8);
  return w;
}

// A random number from the inclusive interval.
uint32_t rndInterval(uint32_t start,uint32_t end){
        uint32_t r=end-start;
        uint32_t m=fillBack(r);
        uint32_t x;
        while((x=rnd32(0)&m)>r);
        return x+start;
}

// Mutates the parent value with random number whose value
// is ranged on one of a number of equally likely scales.
// the parent value should be between -1 and 1 inclusive.
float midas(float pv,uint32_t baseExp,uint32_t topExp){
        float m=0,cv;
        uint32_t x=rnd32(0)&0x807fffff;                        // rnd mutation and mask out the exponent of the future 32 bit floating point number
        uint32_t y=rndInterval(baseExp,topExp); // decide on a characteristic scale for the mutation
        if(y>127) y=127;                                                // limit the mutation exponent to 127 (fp values -2 to 2)
        *(uint32_t*)&m=x+(y<<23);                                // construct the fp number from its sign,mantissa and exponent
        cv=m+pv;
        if(cv<-1 || cv>1) cv=pv;                                // if the mutated value is out of bounds then there is no mutation
        return cv;
}

// Canterlot (Scale Free) Evolution Strategy.
// Provides scale free mutations for doing numerical optimizations etc.  The values in the parent
// vector should be between -1 and 1 inclusive.
// The precision value is between 0 and 127. 127 being maximum precison (slower but more perfect).
// The over the top (ott) parameter provides the ability to produce really high magnitude mutations if needed.
void canterlot(float *parent,float *child,uint32_t n,uint32_t precision,uint32_t ott){
        uint32_t maxshift,shift,idx,rExp,baseExp,topExp;
        baseExp=127-precision;                                        // the lowest exponent value to be used in the mutation f.p. number.
        topExp=rndInterval(baseExp,127+ott);        // virtual highest exponent value to be used in f.p. mutation vector (will be clipped to 127)
        maxshift=topBit(n);                                                // number of divisions of population size (1,2,3 to 4,5 to 8,9 to 16,...,25% to 50%,50% to 100%) possible.
        shift=rndInterval(0,maxshift);                        // select a division uniformly at random (a single mutation is as likely to occur as say 9 to 16 mutations).
        rExp=rnd32(0) | 0x80000000;                                // msb set+31 random bits
        if(shift<2){
                rExp >>=shift;                                                                                // shift rExp right 0 or 1 places.
                for(uint32_t i=0;i<n;i++){         
                        if(rnd32(0)<=rExp){                                                                // 25 To 50 or 50 to 100% of the time.
                                child[i]=midas(parent[i],baseExp,topExp);        // child gets mutated value.
                        }else{
                                child[i]=parent[i];                                                        // child gets unmutated value.
                        }
                }
                idx=rndInterval(0,n-1);                                                                // shoe in at least 1 topExp scale mutation.
                child[idx]=midas(parent[idx],topExp,topExp);         
        }else{
                for(uint32_t i=0;i<n;i++){
                        child[i]=parent[i];                                                                // first copy across parent vector to child vector.
                }         
                idx=rndInterval(0,n-1);         
                child[idx]=midas(parent[idx],topExp,topExp);                // do at least 1 topExp scale mutation.
                if(shift!=2){                                                                         
                        rExp >>=34-shift;                                                                  // do a shift of rExp to see how many further mutations to make, (1,2 to 3, 4 to 7).
                        for(uint32_t i=0;i<rExp;i++){
                                do{
                                        idx=rndInterval(0,n-1);                                        // select one index at random.
                                }while(parent[idx]!=child[idx]);                        // if definitely already mutated then try a different index.
                                child[idx]=midas(parent[idx],baseExp,topExp);  // do the mutation.
                        }         
                }
        }
}

// replace with a good test function
float cost(float *vec,uint32_t n){
        float r=0;
        for(uint32_t i=0;i<n;i++){
                r+=vec[i]*vec[i];
    }
        return r;
}

int main(int argc, char **argv){
        float parentCost,childCost=0,parent[20],child[20];
        for(uint32_t j=0;j<20;j++) parent[j]=1;
        rnd32(442523);        // seed random number generator
        parentCost=cost(parent,20);
        for(uint32_t i=0;i<20000;i++){
                canterlot(parent,child,20,32,0);
                childCost=cost(child,20);
                if(childCost<parentCost){
                        parentCost=childCost;
                        for(uint32_t j=0;j<20;j++) parent[j]=child[j];
            }
        }
        for(uint32_t i=0;i<20;i++) printf("%f\n",parent[i]);
        return 0;
}


Page 1 of 1 All times are UTC
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/