📄 citizen.h
字号:
#include <iostream.h>#include <math.h>#include "Array.h"#define abs(x) (((x) < 0) ? -(x) : (x))typedef float Real;///////////////////////////////////////////////////////////////////////////////// Citizen.h /////////////////////////////////////////////////////////////////////////////////class Citizen { public: Citizen(); ~Citizen();//// Main member functions.// void setSize(int,int); void initC(Ranges,int*,int,int); void showC(); void encodeParams(Ranges); Real decodeParam(Ranges,int); void mutateParam(Real,Real,int*,int);//// Support member functions.// int numParams(); int numBits(); void bitAdd(int,int); int bitVal(int); void paramAdd(int,Real); Real paramVal(int); Citizen& operator=(Citizen *); Real fit(); Real f1(); Real f2(); Real f3(); Real f4(); Real f5(); int checkRange(int,Real,Ranges);//// Friend functions.// friend Real Ranges::lowRange(int); friend Real Ranges::highRange(int); friend Real Ranges::expRange(int); private: SimpleFArray paramsF; // Array of Realing point numbers SimpleIArray paramsB; // Array of Genes};///////////////////////////////////////////////////////////////////////////////// Citizen.cc /////////////////////////////////////////////////////////////////////////////////Citizen::Citizen() {}Citizen::~Citizen() {//// Standard destructor// paramsF.~SimpleFArray(); paramsB.~SimpleIArray();}void Citizen::setSize(int np,int nb) {//// This routine is for setting the size of the parameter arrays. Normally, // the number of parameters and the number of bits do not need to be passed // in, but here, the arrays have been initially set. This is where they are // set, so 'np' and 'nb' have to be passed in here. // paramsF.setSize(np); paramsB.setSize(np*nb);}void Citizen::initC(Ranges r,int* iseed,int np, int nb) {//// This routine initializes a citizen. A citizen is an array of floating // point numbers, which are the parameters to be fit, and an array of 'bits' // which are integers that can only have the values 0 or 1. These two arrays// are paramsF and paramsB, respectivly This routine can be made more space// efficient by making the array of integers a single integer, or a couple // integers, depending on how many bits are desired. This routine just // generates random numbers, evenly distributed between the ranges which were// inputed at the beginning of the program. After the floating point // parameter is chosen, it is 'encoded' which means transformed into an array// of bits.// Real xx; Real pd; paramsF.setSize(np); paramsB.setSize(np*nb); for(int i = 0;i < np;i++) { xx = ran1(iseed); pd = r.highRange(i) - r.lowRange(i); paramsF[i] = r.lowRange(i) + xx*pd; encodeParams(r); }}void Citizen::showC() {//// This routine prints out the information for a single citizen. It is really// for display (and debugging) purposes only, and is not crucial to the main // program. The flag=1 option prints out the information in a more detailed // format, bit by bit, and the flag=0 option prints out only the string of bits.// int flag = 0; int start_bit; int np = numParams(); int nb = numBits(); for(int inp = 0;inp < np;inp++) { start_bit = inp*nb; cout << "Parameter " << inp << " is " << paramsF[inp] << " --> "; if (flag) cout << endl; for(int inb = 0;inb < nb;inb++) { if (flag) cout << "bit number " << start_bit+inb << " is "; cout << paramsB[start_bit+inb]; if (flag) cout << endl; } cout << endl; }}void Citizen::encodeParams(Ranges r) {//// This routine encodes the entire parameter set. It turns the array of // floating point numbers into an array of binary digits. flag = 1 turns // on debugging info.// int flag = 0; int np = numParams(); int nb = numBits(); int bit,start_bit,neg_bit; Real param,check2; for(int inp = 0;inp < np;inp++) { start_bit = inp*nb; neg_bit = start_bit; param = paramsF[inp];//// Assign the negative bit, which is the first bit in the sequence.// if (param < 0.0) paramsB[neg_bit] = 1; else paramsB[neg_bit] = 0; param = abs(param);//// Determine the rest of the gene sequence by comparing the remainder// of the parameter to successively smaller powers of 2.// check2 = r.expRange(inp); if (flag) cout << "At the start, start_bit is " << start_bit << endl; if (flag) cout << "At the start, check2 is " << check2 << endl; if (flag) cout << "At the start, param is " << param << endl; for(int inb = 1;inb < nb;inb++) { bit = start_bit + inb; if (flag) cout << "* bit is " << bit << endl; if (flag) cout << "* check2 is " << check2 << endl; if (flag) cout << "* param is " << param << endl; if (param >= check2) { if (flag) cout << "* Higher" << endl; paramsB[bit] = 1; param -= check2; check2 /= 2.0; } else { if (flag) cout << "* Lower" << endl; paramsB[bit] = 0; check2 /= 2.0; } if (flag) cout << "============================" << endl; } }}Real Citizen::decodeParam(Ranges r,int paramnum) {//// This routine takes one section of the binary array, corresponding to a // specific parameter, and converts it into a floating point number, and // then returns it. It does this by reversing the encoding algorithm, i.e., // adding successivly higher powers of 2, and then at the end, determining // the overall sign of the parameter. flag = 1 turns on debugging info.//// There are two different ways to add up the bits. From smallest to largest, // and from largest to smallest. Algorithm 1 adds the parameters up for // smallest bit to largest bit. Algorithm 2 adds the parameter up from largest// bit to smallest bit. Algorithm 1 is more accurate, Algorithm 2 is quicker, // because Algorithm 1 has to evaluate a pow() function for each bit.// int flag = 0; int ibit; int np = numParams(); int nb = numBits(); int neg_bit = paramnum*nb; Real param,check2,check2add; int start_bit = paramnum*nb; param = 0.0; check2 = r.expRange(paramnum);//// Algorithm 2// -----------// for(int inb = 1;inb < nb;inb++) { ibit = start_bit + inb; if (paramsB[ibit] == 1) param += check2; check2 /= 2.0; } if (paramsB[neg_bit] == 1) param *= -1.0;//// Algorithm 1// -----------//// for(int inb = (nb-1);inb >= 1;inb--) {// check2add = check2/pow(2.0,(inb-2));// ibit = start_bit + inb;// if (paramsB[ibit] == 1) param += check2add;// }////// Algorithm 2// -----------//// for(int inb = 1;inb < nb;inb++) {// ibit = start_bit + inb;// if (paramsB[ibit] == 1) param += check2;// check2 /= 2.0;// }// return param;}void Citizen::mutateParam(Real JmutRate,Real CmutRate,int *iseed,int inp) {//// This routine mutates a specific parameter by randomly changing bits.// There are two different types of mutation, each with its own rate.// flag = 1 turns on debugging info.//// Jump mutation - This randomly swiches a bit from 1 to 0, or from// 0 to 1, as the case may be. It goes through every bit in the // string and exposes to the posibility of mutation. The value // of the Jump mutation rate is typacally set to 1/(Population size).//// Creep mutation - This randomly switches the values of two adjacent bits // in the binary string that makes up a single parameter. Often, this // does nothing because adjacent bits have about a 50% probability of // being the same. This is typically set to // (Number of bits per parameter)/(Population size).// int flag = 0; int start_bit,temp_bit,switch_bit,bit; int nb = numBits(); int np = numParams();//// Jump mutation// if (flag) cout << "Starting jump mutation" << endl; start_bit = inp*nb; for (int inb = 0;inb < nb;inb++) { if (ran1(iseed) < JmutRate) { bit = start_bit + inb; if (flag) cout << "Mutating parameter " << inp; if (flag) cout << ", bit number is " << bit << endl; paramsB[bit] = 1-paramsB[bit]; } }//// Creep mutation//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -