差分进化算法(DE)的C++面向对象方法实现
代码来源于网络,写得非常棒
1 /*DE_test 2 *对相应的Matlab程序进行测试 3 */ 4 5 #include <iostream> 6 #include <cmath> 7 #include <ctime> 8 using namespace std; 9 10 //产生随机数,随机数为(0.0,1.0) 11 double Rand_Double(void) 12 { 13 return static_cast<double>(rand()) / static_cast<double>(RAND_MAX); 14 } 15 16 //测试函数Hansen 17 //参数个数为2 18 double Hansen(double *p_pars) 19 { 20 return (cos(1.0) + 2.0*cos(p_pars[0] + 2.0) + 3.0*cos(2.0*p_pars[0] + 3.0) 21 + 4.0*cos(3.0*p_pars[0] + 4.0) + 5.0*cos(4.0*p_pars[0] + 5.0)) 22 * (cos(2.0*p_pars[1] + 1.0) + 2.0*cos(3.0*p_pars[1] + 2.0) + 23 3.0*cos(4.0*p_pars[1] + 3.0) + 4.0*cos(5.0*p_pars[1] + 4.0) + 5.0*cos(6.0*p_pars[1] + 5.0)); 24 } 25 26 class CFunction 27 { 28 public: 29 void *m_p_fun;//指向测试函数的指针 30 int m_pars_num;//参数个数 31 double m_min;//下限 32 double m_max;//上限 33 bool m_pos;//求解最小值还是最大值,如果是最小值则m_pos为false,如果是最大值则m_pos为true 34 public: 35 CFunction(void *p_fun, int pars_num, double min, double max, bool pos) 36 :m_p_fun(p_fun), m_pars_num(pars_num), m_min(min), m_max(max), m_pos(pos) 37 { 38 } 39 40 virtual double Compute(double *p_pars) = 0; 41 }; 42 43 class CHansen :public CFunction 44 { 45 public: 46 //注册函数 47 CHansen(void) 48 :CFunction(Hansen, 2, -10.0, 10.0, false) 49 { 50 } 51 52 double Compute(double *p_pars) 53 { 54 return Hansen(p_pars); 55 } 56 }; 57 58 //个体 59 class CIndividual 60 { 61 public: 62 double *m_p_DNA;//参数 63 double m_f;//适应值 64 int m_DNA_length;//DNA的长度 65 66 public: 67 CIndividual(void) 68 :m_f(0.0), m_DNA_length(0), m_p_DNA(NULL) 69 { 70 } 71 72 ~CIndividual(void) 73 { 74 if (m_p_DNA != NULL) 75 delete[] m_p_DNA; 76 } 77 78 //初始化,分配内存空间 79 void Ini(int pars_num) 80 { 81 m_DNA_length = pars_num; 82 m_p_DNA = new double[m_DNA_length]; 83 } 84 85 //假定两者分配的内存空间的大小一样 86 CIndividual& operator=(CIndividual& ind) 87 { 88 m_f = ind.m_f; 89 //m_DNA_length = ind.m_DNA_length; 90 for (int i = 0; i < m_DNA_length; ++i) 91 { 92 m_p_DNA[i] = ind.m_p_DNA[i]; 93 } 94 return *this; 95 } 96 97 friend ostream& operator<<(ostream& o, CIndividual& ind)//运算符重载 98 { 99 return o << ind.m_f; 100 } 101 }; 102 103 104 int main() 105 { 106 //---------------------------设置随机数------------------------------------ 107 srand((unsigned int)(time(NULL))); 108 109 //获得参数 110 int Num, T; 111 double zoom, cr; 112 113 cout << "种群大小:"; 114 cin >> Num; 115 116 cout << "进化代数:"; 117 cin >> T; 118 119 cout << "缩放因子:"; 120 cin >> zoom; 121 122 cout << "交叉因子:"; 123 cin >> cr; 124 125 //----------------------对函数进行操作,注册函数------------------------------ 126 CHansen fun_Hansen; 127 128 CFunction *p_fun = &fun_Hansen;//为了实现多态 129 int pars_num = p_fun->m_pars_num;//参数个数 130 double min = p_fun->m_min;//下限 131 double max = p_fun->m_max;//上限 132 bool pos = p_fun->m_pos;//求最大值还是最小值 133 134 //----------------------注册种群,并分配内存空间----------------------------- 135 CIndividual *p_old = new CIndividual[Num]; 136 CIndividual *p_new = new CIndividual[Num]; 137 for (int i = 0; i < Num; ++i) 138 { 139 p_old[i].Ini(pars_num); 140 p_new[i].Ini(pars_num); 141 } 142 143 //-------------------------产生初始的随机种群-------------------------------- 144 int i; 145 for (i = 0; i < Num; ++i)//对种群进行遍历 146 { 147 for (int j = 0; j < pars_num; ++j)//对参数列表进行遍历 148 p_old[i].m_p_DNA[j] = Rand_Double()*(max - min) + min; 149 p_old[i].m_f = p_fun->Compute(p_old[i].m_p_DNA); 150 } 151 152 CIndividual ind_best; 153 ind_best.Ini(pars_num); 154 155 for (int t = 0; t < T; ++t)//开始一代一代地进化 156 { 157 //显示结果 158 ind_best = p_old[0]; 159 for (int i = 1; i < Num; ++i) 160 { 161 if (pos == true && ind_best.m_f < p_old[i].m_f)//求最大值 162 ind_best = p_old[i]; 163 else if (pos == false && ind_best.m_f > p_old[i].m_f)//求最小值 164 ind_best = p_old[i]; 165 } 166 cout << ind_best << "\n"; 167 168 //差分变异 169 for (i = 0; i < Num; ++i)//对种群进行遍历 170 { 171 //产生三个随机数 172 int x1, x2, x3; 173 x1 = rand() % Num; 174 do 175 { 176 x2 = rand() % Num; 177 } while (x1 == x2); 178 do 179 { 180 x3 = rand() % Num; 181 } while (x1 == x3 || x2 == x3); 182 183 for (int j = 0; j < pars_num; ++j)//对参数列表进行遍历 184 { 185 p_new[i].m_p_DNA[j] = p_old[x1].m_p_DNA[j] + zoom * (p_old[x2].m_p_DNA[j] - p_old[x3].m_p_DNA[j]); 186 if (p_new[i].m_p_DNA[j]<min || p_new[i].m_p_DNA[j]>max)//越界 187 p_new[i].m_p_DNA[j] = p_old[i].m_p_DNA[j]; 188 } 189 } 190 191 //交叉操作,注意,交叉要对每个实数位进行交叉 192 for (i = 0; i < Num; ++i)//对种群进行遍历 193 { 194 for (int j = 0; j < pars_num; ++j) 195 { 196 if (Rand_Double() > cr)//不交叉 197 p_new[i].m_p_DNA[j] = p_old[i].m_p_DNA[j]; 198 } 199 p_new[i].m_f = p_fun->Compute(p_new[i].m_p_DNA); 200 } 201 202 //选择操作 203 for (i = 0; i < Num; ++i)//对种群进行遍历 204 { 205 if (pos == true && p_new[i].m_f < p_old[i].m_f)//求最大值 206 p_new[i] = p_old[i]; 207 else if (pos == false && p_new[i].m_f > p_old[i].m_f)//求最小值 208 p_new[i] = p_old[i]; 209 } 210 211 //交换 212 CIndividual *p_tmp; 213 p_tmp = p_old; 214 p_old = p_new; 215 p_new = p_tmp; 216 //此时,新种群的值被保存到p_old中 217 } 218 219 return 0; 220 }