今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
基于Apache math3 的遗传算法计算复杂函数在定义域内的最值(二)
上一节中主要写了遗传算法的定义,Apache math 提供的遗传算法接口实现求函数最大值的理论。这一节直接上代码。
EquationChromosome 该类主要为计算函数的适应度(函数值) 主要代码如下
@Override public double fitness() { return val;//返回在当前基因(解)的函数值,这里函数函数值计算我通过luaj框架来计算,具体百度 }
//在经过选择,交叉,突变后新的基因 @Override public AbstractListChromosome<Integer> newFixedLengthChromosome(List<Integer> newReprs) { EquationChromosome ecNew = new EquationChromosome(newReprs); ecNew.setFunctionExpression(functionExpression); ecNew.setFactorValues(binaryToDecimal(newReprs)); return ecNew; } private Map<String, Double> binaryToDecimal(List<Integer> newReprs) { String [] name =new String[]{"x1","x2"};//测试用定死了两个变量 Map<String,Double> solution =new HashMap<>(); for(int i=0;i<newReprs.size()/64;i++){ List<Integer> one =newReprs.subList(i*64,(i+1)*64); String binaryStr = one.stream().map(v->v+"").collect(Collectors.joining()); long longBit =Long.parseUnsignedLong(binaryStr,2); //转换到定义域范围内,假定定义域为[0,4] Double bd=Double.longBitsToDouble(longBit); double max=4; double min=0; double value =((bd-Double.MIN_VALUE)/(Double.MAX_VALUE-Double.MIN_VALUE))*(max-min)+min; solution.put(name[i],value); } return solution; }
选择使用默认的选择类
TournamentSelection
EquationCrossover 该类继承了 NPointCrossover 重写主要是为了防止交叉后基因表现(二进制)超出Double范围 ,因为double 占8字节,二进制总共有64位,最高位位符号位,51-62 总共11位指数为,剩余的52位小数位
指数位的最大值为1204,如果指数位11位都为1,则此时将超出double范围,表示为NaN,故如下处理
for(int i=0;i<child1Rep.size()/64;i++){ List<Integer> sub =child1Rep.subList(i*64,(i+1)*64); List<Integer> sub11 =sub.subList(1,12); long sum = sub11.stream().filter(n->n==1).count(); if(sum==11) child1Rep.set(i*64+11,0); } for(int i=0;i<child2Rep.size()/64;i++){ List<Integer> sub =child2Rep.subList(i*64,(i+1)*64); List<Integer> sub11 =sub.subList(1,12); long sum = sub11.stream().filter(n->n==1).count(); if(sum==11) child2Rep.set(i*64+11,0); }
EquationMutaion implements MutationPolicy 此类和上述EquationCrossover情况类似,不在叙述。
EquationStoppingCondition implements StoppingCondition 遗传算法的停止条件,这里给出集中方式。
- 在一段时间后停止
- 再执行N代后停止
- 基因在N次无变化后停止
- 函数值变化范围很小或不变化后停止
接下来执行GA运算
public class GATest { public static final int POPULATION_SIZE = 60; public static final double CROSSOVER_RATE = 0.9; public static final double MUTATION_RATE = 0.03; public static final double ELITISM_RATE = 0.1; public static final int TOURNAMENT_ARITY = 2; public static final int DIMENSION = TARGET_STRING.length(); public static final String exp="x1*x1+x2*x2"; // public static final String exp="21.5+x1*(math.sin(4*math.pi*x1)+x2*math.sin(20*math.pi*x2))"; public void getResult(){ long startTime = System.currentTimeMillis(); // initialize a new genetic algorithm GeneticAlgorithm ga = new GeneticAlgorithm(new EquationCrossover<>(2), CROSSOVER_RATE, new EquationMutaion(), MUTATION_RATE, new TournamentSelection(TOURNAMENT_ARITY)); List<Map<String,Double>> init = new ArrayList<>(); Map<String,Double> initVal =new HashMap<>(); initVal.put("x1",1.2); initVal.put("x2",1.5); Map<String,Double> initVal2 =new HashMap<>(); initVal2.put("x1",3.1); initVal2.put("x2",3.22); init.add(initVal); init.add(initVal2); // initial population Population initial = getInitialPopulation(init); // stopping condition StoppingCondition stoppingCondition = new EquationStoppingCondition(10000,200); System.out.println("Starting evolution ..."); // run the algorithm Population finalPopulation = ga.evolve(initial, stoppingCondition); // Get the end time for the simulation. long endTime = System.currentTimeMillis(); // best chromosome from the final population EquationChromosome best = (EquationChromosome) finalPopulation.getFittestChromosome(); System.out.println("Generation " + ga.getGenerationsEvolved() + ": " + best.toString()); Map<String,Double> map= best.getFactorValues(); for(String key:map.keySet()){ double max= map.get(key); System.out.println("Solution " + key+ " : "+map.get(key)); } System.out.println("----------------------------Total execution time: " + (endTime - startTime) + "ms----------------------------"); } private Population getInitialPopulation(List<Map<String,Double>> initValues) { List<Chromosome> popList = new LinkedList<Chromosome>(); for(Map<String,Double> factors:initValues){ List<Double> geneList = factors.values().stream().collect(Collectors.toList()); for (int i = 0; i < POPULATION_SIZE; i++) { EquationChromosome ec = new EquationChromosome(getGene(geneList)); ec.setFactorValues(factors); ec.setFunctionExpression(exp); popList.add(ec); } } return new ElitisticListPopulation(popList, 2 * popList.size(), ELITISM_RATE); } public List<Integer> getGene(List<Double> values){ List<Integer> geneList =new ArrayList<>(); for(Double val:values){ String binStr = Long.toBinaryString(Double.doubleToLongBits(val)); //不足64位补0 if(binStr.length()==62){ StringBuilder sb = new StringBuilder(binStr); sb.insert(0,"0"); sb.insert(1,"0"); binStr=sb.toString(); } if(binStr.length()==63){ StringBuilder sb = new StringBuilder(binStr); sb.insert(0,"0"); binStr=sb.toString(); } for(int i=0;i<binStr.length();i++){ geneList.add(Integer.valueOf(binStr.charAt(i)-48)); } } return geneList; } public static String toBinary(long num,int digits){ String cover =Long.toBinaryString(1<<digits).substring(1); String str =Long.toBinaryString(num); return str.length()<digits?cover.substring(str.length())+str:str; } }
测试
@Test public void test(){ for(int i=0;i<10;i++) { GATest gat = new GATest(); gat.getResult(); } }
执行10次之后的结果为:
Starting evolution ... Generation 530: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 6021ms---------------------------- Starting evolution ... Generation 627: (f=32.0 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : -4.0 Solution x2 : 4.0 ----------------------------Total execution time: 2075ms---------------------------- Starting evolution ... Generation 544: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1383ms---------------------------- Starting evolution ... Generation 587: (f=32.0 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : -4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1487ms---------------------------- Starting evolution ... Generation 586: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1454ms---------------------------- Starting evolution ... Generation 579: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1490ms---------------------------- Starting evolution ... Generation 527: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1272ms---------------------------- Starting evolution ... Generation 574: (f=32.0 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : -4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1393ms---------------------------- Starting evolution ... Generation 595: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1486ms---------------------------- Starting evolution ... Generation 697: (f=32.0 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Solution x1 : 4.0 Solution x2 : 4.0 ----------------------------Total execution time: 1785ms----------------------------分享到: