今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

基于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----------------------------
分享到:

专栏

类型标签

网站访问总量