```java
package evolutionary;
import java.util.*;
import static java.lang.Math.*;
public class Evolutionary {
//精度
static double precision= 0.0001f;
//种群个数
static int number=100;
//位数
static int bit_number;
//上界
static double[] uppers;
//下界
static double[] lowers;
//交叉概率
static float cross_probability=0.6f;
//变异概率
static float variation_probability=0.01f;
//迭代次数
static int epoch=1000;
//随机数
static Random random = new Random();
//测试数据
static boolean[] test = new boolean[]{false, false, false, false, false, true, false, true, false, true, false, false, true, false, true, false, false,
true, true, false, true, true, true, true, false, true, true, true, true, true, true, true, false};
public static void main(String[] args) {
uppers = new double[]{12.1, 5.8};
lowers = new double[]{-3.0, 4.1};
// uppers = new double[]{2.048, 2.048};
// lowers = new double[]{-2.048, -2.048};
evolutionary_algorithms(precision,number,uppers,lowers,cross_probability,variation_probability,epoch);
}
//f(x1,x2),适应度函数
static double func(double[] x) {
return 21.5 + x[0] * sin(4 * PI * x[0]) + x[1] * sin(20 * PI * x[1]);
}
// static double func(double[] x){
// return 100*pow(x[1]-pow(x[0],2),2)+pow(1-x[1],2);
// }
/**
@Param presion:精度
@Param number:种群数量
@Param uppers:对应自变量的上界数组
@Param lowers:对应自变量的下界数组
@Param func:适应度函数 暂未灵活设计
@Param cross_probability:交叉概率
@Param variation_probability:变异概率
@Param epoch:迭代轮数
**/
static void evolutionary_algorithms(double precision,int number,double[] uppers,double[] lowers,float cross_probability,float variation_probability,int epoch){
//总编码长度
bit_number=0;
//每个自变量的编码长度
int[] bit_numbers = new int[uppers.length];
for(int i=0;i<bit_numbers.length;i++){
bit_numbers[i] = encode(uppers[i], lowers[i]);
bit_number+=bit_numbers[i];
}
System.out.println("编码位数:" + bit_number);
//种群
boolean[][] population;
//适应度
double[] adaptability=new double[number];
//对应个体
boolean[][] next_population;
//子代适应度值
double[] next_adaptability;
//每一代最优值
double pre_child=0;
//初始化种群
population = init_population();
for (int i = 0; i < epoch; i++) {
System.out.println("第" + i + "epoch:");
//计算个体适应度
adaptability = adaptabilityFunc(population, bit_numbers);
pre_child=Arrays.stream(adaptability).max().getAsDouble();
System.out.println(pre_child);
//轮盘赌
next_population = roulette(population, adaptability);
//交叉
next_population = cross_operators(next_population, cross_probability);
//变异
next_population = variation(next_population, variation_probability);
//子代适应度值
next_adaptability = adaptabilityFunc(next_population, bit_numbers);
//生成子代
population = generate_children(population, adaptability, next_population, next_adaptability);
//每一代最优值
}
//解码
{
boolean[] x_string;
//自变量
double[] xs=new double[bit_numbers.length];
//断点位置
int breakpoint;
for (int i=0;i<adaptability.length;i++){
if(adaptability[i]==pre_child){
breakpoint=0;
for(int j=0;j<bit_numbers.length;j++){
breakpoint+=bit_numbers[j];
if(j==0)
x_string=Arrays.copyOfRange(population[i], 0, breakpoint);
else
x_string=Arrays.copyOfRange(population[i], breakpoint-bit_numbers[j] ,breakpoint- 1);
xs[j]=decode(x_string, uppers[j], lowers[j]);
}
}
}
System.out.println(Arrays.toString(xs));
}
}
//初始化种群
static boolean[][] init_population() {
boolean[][] population_ = new boolean[number][bit_number];
for (int i = 0; i < number; i++) {
System.out.print("第" + i + "个:");
for (int j = 0; j < bit_number; j++) {
population_[i][j] = random.nextBoolean();
if (population_[i][j])
System.out.print("1");
else
System.out.print("0");
}
System.out.println();
}
return population_;
}
//计算个体适应度
static double[] adaptabilityFunc(boolean population[][], int[] bit_numbers) {
boolean[] x_string;
//自变量
double[] xs=new double[bit_numbers.length];
//断点位置
int breakpoint;
double[] adaptability_ = new double[population.length];
for (int i = 0; i < population.length; i++) {
breakpoint=0;
for(int j=0;j<bit_numbers.length;j++){
breakpoint+=bit_numbers[j];
if(j==0)
x_string=Arrays.copyOfRange(population[i], 0, breakpoint);
else
x_string=Arrays.copyOfRange(population[i], breakpoint-bit_numbers[j] ,breakpoint- 1);
xs[j]=decode(x_string, uppers[j], lowers[j]);
}
adaptability_[i] = func(xs);
}
return adaptability_;
}
//轮盘赌
static boolean[][] roulette(boolean[][] population, double[] adaptability) {
//适应度比值
double[] probability;
//累计适应度
double[] cumulation_probability;
//对应个体
boolean[][] next_population;
//计算比值
probability = adaptability_probability(adaptability);
//计算累积适应度
cumulation_probability = cumulation_probability(probability);
//选择对应个体
next_population = choose_parents(cumulation_probability, population);
return next_population;
}
//计算比值
static double[] adaptability_probability(double[] adaptability) {
double[] probability_ = new double[adaptability.length];
double adaptability_all = 0;
for (int i = 0; i < adaptability.length; i++) {
adaptability_all += adaptability[i];
}
for (int i = 0; i < adaptability.length; i++) {
probability_[i] = adaptability[i] / adaptability_all;
}
return probability_;
}
//计算累积适应度
static double[] cumulation_probability(double[] probability) {
double[] cumulation_probability_ = new double[probability.length];
cumulation_probability_[0] = probability[0];
for (int i = 1; i < cumulation_probability_.length; i++) {
cumulation_probability_[i] = cumulation_probability_[i - 1] + probability[i];
}
return cumulation_probability_;
}
//选择父代
static boolean[][] choose_parents(double[] cumulation_probability, boolean[][] population) {
double random1;
boolean[][] next_population = new boolean[number][bit_number];
for (int i = 0; i < number; i++) {
random1 = random.nextDouble();
for (int j = 0; j < population.length; j++) {
if (j == 0) {
if (0 <= random1 && random1 < cumulation_probability[j]) {
System.arraycopy(population[j],0,next_population[i],0,population[j].length);
break;
}
} else {
if (cumulation_probability[j - 1] <= random1 && random1 < cumulation_probability[j]){
System.arraycopy(population[j - 1],0,next_population[i],0,population[j-1].length);
}
}
}
}
return next_population;
}
static int boolean_to_int(boolean[] x_string) {
int number = 0;
for (int i = 0; i < x_string.length; i++) {
if (x_string[i])
number += pow(2, (x_string.length - i));
}
return number;
}
//编码
static int encode(double upper, double lower) {
//位数
return (int) ceil(log((upper - lower) / precision + 1) / log(2));
}
//解码
static double decode(boolean[] x_string, double upper, double lower) {
return lower + (upper - lower) * boolean_to_int(x_string) / (pow(2, (x_string.length + 1)) - 1);
}
//交叉算子
static boolean[][] cross_operators(boolean[][] next_population, float cross_probability) {
for (int i = 0; i < number; i = i + 2) {
if (random.nextDouble() < cross_probability)
next_population = two_points_cross(next_population, i, i + 1);
}
return next_population;
}
//两条染色体交叉
static boolean[][] two_points_cross(boolean[][] next_population, int i, int j) {
int random1 = random.nextInt(bit_number);
int random2 = random.nextInt(bit_number);
int max_bound = Math.max(random1, random2);
int min_bound = Math.min(random1, random2);
boolean swap;
for (int m = min_bound; m < max_bound; m++) {
swap = next_population[i][m];
next_population[i][m] = next_population[j][m];
next_population[j][m] = swap;
}
return next_population;
}
//变异算子
static boolean[][] variation(boolean[][] next_population, float variation_probability) {
Random random = new Random();
for (int i = 0; i < number * bit_number; i++) {
if (random.nextDouble() <= variation_probability) {
next_population[(int) (i / bit_number)][i % bit_number] = !next_population[(int) (i / bit_number)][i % bit_number];
}
}
return next_population;
}
//生成子代
static boolean[][] generate_children(boolean[][] population, double[] adaptability, boolean[][] next_population, double[] next_adaptability) {
boolean[][] end_populaition = new boolean[population.length][population[0].length];
int length = population.length;
population = Arrays.copyOf(population, population.length + next_population.length);
System.arraycopy(next_population, 0, population, length, next_population.length);
adaptability = Arrays.copyOf(adaptability, adaptability.length + next_adaptability.length);
System.arraycopy(next_adaptability, 0, adaptability, length, next_adaptability.length);
double max1_number;
double max2_number;
int m1, m2;
if (adaptability[0] > adaptability[1]) {
max1_number = adaptability[0];
max2_number = adaptability[1];
m1 = 0;
m2 = 1;
} else {
max1_number = adaptability[1];
max2_number = adaptability[0];
m1 = 1;
m2 = 0;
}
for (int i = 2; i < adaptability.length; i++) {
if (adaptability[i] > max1_number) {
max2_number = max1_number;
max1_number = adaptability[i];
m2 = m1;
m1 = i;
} else if (adaptability[i] > max2_number) {
max2_number = adaptability[i];
m2 = i;
}
}
end_populaition = roulette(population, adaptability);
System.arraycopy(population[m1],0, end_populaition[0] ,0, end_populaition[0] .length);
System.arraycopy(population[m2],0, end_populaition[1] ,0, end_populaition[1] .length);
return end_populaition;
}
}