利用遗传算法求:De jong 函数f2(x) = ∑_(i=0)^10▒x_i^2 ,|xi|100,求解f2 (x)的最小值

Main类

package com.tylg.EAofDejong;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;

public class Main {

	public static void main(String[] args) {
		Fitness f = new Fitness();
		Code c = new Code();
	
		String[] s = c.initAll(100, 40); // s中存放的就是初始生成的40组染色体,每组染色体有100个基因
		System.out.println("初始种群为:40个");
		for (int i = 0; i < 40; i++) {
			System.out.print(s[i]);
			System.out.print("***********");
			System.out.println(f.fitness(s[i]));
		}
		
		System.out.println("经过遗传迭代后的种群为:");
		
		String[] end = Main.runEA(s);
		for (int i = 0; i < 40; i++) {
			System.out.println(end[i]);
			System.out.println(f.fitness(end[i]));
		}

	}

	public static String[] runEA(String[] init) {

		String[] sChoose = new String[40];
		String[] sCross = new String[20];
		String[] sMutation = new String[20];

		for (int i = 0; i < 40; i++) {
			sChoose[i] = init[i];
		}

		for (int d = 0; d < 1000; d++) {
			sCross = choose(sChoose); // sCross大小为20
			sMutation = cross(sCross); // sMutation大小为20
			sChoose = mutation(sMutation, sCross); // sChoose大小为40
		}

		return sChoose;
	}

	/*
	 * 变异算子
	 */
	private static String[] mutation(String[] sMutation, String[] parents) {

		for (int i = 0; i < 20; i++) {
			if (Math.random() < 0.2) { // 变异概率为0.2
				int bit1 = (int)(Math.random() * 20); // bit1为某一位
				int bit2 = (int)(Math.random() * 20 + 20); // bit2为某一位
				int bit3 = (int)(Math.random() * 20 + 40); // bit3为某一位
				int bit4 = (int)(Math.random() * 20 + 60); // bit4为某一位
				int bit5 = (int)(Math.random() * 20 + 80); // bit5为某一位
				StringBuilder sb = new StringBuilder(sMutation[i]);
				if (sMutation[i].substring(bit1, bit1 + 1).equals("0")) {
					sb.replace(bit1, bit1 + 1, "1");
				} else {
					sb.replace(bit1, bit1 + 1, "0");
				}

				if (sMutation[i].substring(bit2, bit2 + 1).equals("0")) {
					sb.replace(bit2, bit2 + 1, "1");
				} else {
					sb.replace(bit2, bit2 + 1, "0");
				}

				if (sMutation[i].substring(bit3, bit3 + 1).equals("0")) {
					sb.replace(bit3, bit3 + 1, "1");
				} else {
					sb.replace(bit3, bit3 + 1, "0");
				}

				if (sMutation[i].substring(bit4, bit4 + 1).equals("0")) {
					sb.replace(bit4, bit4 + 1, "1");
				} else {
					sb.replace(bit4, bit4 + 1, "0");
				}

				if (sMutation[i].substring(bit5, bit5 + 1).equals("0")) {
					sb.replace(bit5, bit5 + 1, "1");
				} else {
					sb.replace(bit5, bit5 + 1, "0");
				}
			}
		}

		return Main.linkArray(parents, sMutation);
	}

	/*
	 * 交叉算子
	 */
	private static String[] cross(String[] sCross) {

//		String[] sMid = new String[20];
//		System.arraycopy(sCross, 0, sMid, 0, 20); // 先将原数组·中的元素进行保存

		for (int i = 0; i < 10; i++) { // 该循环让整个sCross数组都发生交换,采用中点交叉
			String s1 = sCross[i].substring(0, 50);
			String s2 = sCross[i].substring(50, 100);
			String s3 = sCross[19 - i].substring(0, 50);
			String s4 = sCross[19 - i].substring(50, 100);
			sCross[i] = s1.concat(s4);
			sCross[19 - i] = s4.concat(s2);
		}

		return sCross; // 将字符串数组连接在一块
	}

	/*
	 * 选择算子
	 */
	private static String[] choose(String[] s) {
		Fitness f = new Fitness();
		Code c = new Code();

		// 未经选择的种群(二进制形式)
		double fAll = 0;
		for (int i = 0; i < s.length; i++) {
			double v = f.fitness(s[i]); // 产生的这个二进制数转化为0~100000的十进制数
			fAll += v;
		}

		// 把种群从二进制变为十进制后,再计算出各自的适应度值
		double[] fArr = new double[40];
		for (int i = 0; i < 40; i++) {
			fArr[i] = f.fitness(s[i]); // 适应度数组
		}

		// 通过下列的for循环,可以得到一个适应度大小从高到低排序的genes染色体数组
		for (int i = 0; i < 40 - 1; i++) {
			for (int j = i + 1; j < 40; j++) {
				if (fArr[i] < fArr[j]) {
					double c1 = fArr[i];
					fArr[i] = fArr[j];
					fArr[j] = c1;
					// 让适应度数组的变化同步至二进制字符串染色体的变化,该做法可让染色体中的基因也是按照一定大小排序
					String c2 = s[i];
					s[i] = s[j];
					s[j] = c2;
				}
			}
		}

		/*
		 * 计算出每个染色体的相对适应度,即( fc[i] = fArr[i] / fAll ),且fc数组中存放的相对适应度从高到低排序的值
		 */
		double[] fc = new double[40];
		for (int i = 0; i < 40; i++) {
			fc[i] = fArr[i] / fAll;
		}

		/*
		 * 轮盘赌---- 可得到一组新的newgenes[]染色体数组
		 */
		String[] newgenes = new String[20];
		for (int i = 0; i < 20; i++) { // 扔骰子次数为GROUPSIZE次
			double dice = Math.random();
			double chip1 = 0.0, chip2 = fc[0];
			for (int j = 0; j < 20 * 2; j++) { // 骰子的值dice与从高到底进行排序的适应度值相比较,
				if ((chip1 < dice || chip1 == dice) && (dice < chip2)) {
					newgenes[i] = s[j];
					break;
				} else {
					chip1 = chip2;
					chip2 += fc[j + 1];
				}
			}
		}

		return newgenes;
	}

	public static String[] linkArray(String[] array1, String[] array2) {

		String[] sMerge = new String[array1.length + array2.length];
		for (int i = 0; i < array1.length; i++) {
			sMerge[i] = array1[i];
		}
		for (int i = 0; i < array2.length; i++) {
			sMerge[array1.length + i] = array1[i];
		}
		return sMerge;
	}

}

Code类

package com.tylg.EAofDejong;

public class Code {
	public String initSingle(int lengthOfGene) {
		String res = "";
		StringBuilder sb = new StringBuilder(res);
		for (int i = 0; i < lengthOfGene; i++) {
			if (Math.random() < 0.5) {
				sb.append("0");
			}	else {
				sb.append("1");
			}
		}
		return "" + sb;
	}
	
	/*
	 * 初始化一组染色体-----(调用初始化一条染色体函数)lengthOfGene表示染色体的长度,即二进制码的位数,groupsize即为种群个数
	 */
	public String[] initAll(int lengthOfGene, int groupSize) {
		
		String[] initall = new String[groupSize];
		for (int i = 0; i < groupSize; i++) {
			initall[i] = initSingle(lengthOfGene);
		}
		return initall; // 该数组当中包含多个字符串,即包含多条(groupSize)染色体
	}
}

Fitness类

package com.tylg.EAofDejong;

public class Fitness {
	public double fitness(String s) { // 输入的s位10个数,也就是10个x各自的二进制字符串连接起来的,若每十个字符代表一个X,则s有100个字符
		double f = 0;
		for (int i = 0; i < 10; i++) {
			int forw = i * 10;
			int end = (i + 1) * 10;
			f += Math.pow(stringToNum(s.substring(forw, end)),2);
		}
		
		return f;
	}

	public double stringToNum(String ss) {
		int x = Integer.parseUnsignedInt(ss, 2);
		double y = ((200.0 / 1023) * x) - 100.0;
		return y;
	}

}

你可能感兴趣的:(算法)