基因表达式编程[Java]:如何查看人口成员

时间:2017-06-09 18:15:09

标签: java evolutionary-algorithm genetic-programming watchmaker

我使用基因表达式编程library演示来获取替代数学表达式。我下载了uncommons.watchmaker框架的所有类文件,并创建了一个没有jar文件运行的新项目。 Java Project (full source code) is attached here

我稍微修改了demo以产生给定数字的替代数学表达式。例如,让我说我希望得到2到11之间的所有数字组合,它们会乘以12。我会得到6 * 2,3 * 4,3 * 2 * 2,2 * 6,4 * 3,2 * 2 * 3.主程序是TestMainProg.java

我有兴趣了解如何打印最后一代人口

调查结果:

在制表师API中,它表示evolvePopulation() in EvolutionEngine interface可用于获取最终的人口数据。但是,我不知道如何调用该方法并打印数据。查看EvolutionEngine.java,EvaluatedCandidate.java和AbstractEvolutionEngine.java将非常有用。

以下是我使用的代码:

import java.util.ArrayList;
import java.util.List;
import org.gep4j.GeneFactory;
import org.gep4j.INode;
import org.gep4j.INodeFactory;
import org.gep4j.IntegerConstantFactory;
import org.gep4j.KarvaEvaluator;
import org.gep4j.MutationOperator;
import org.gep4j.RecombinationOperator;
import org.gep4j.SimpleNodeFactory;
import org.gep4j.math.Multiply;
import org.uncommons.maths.random.MersenneTwisterRNG;
import org.uncommons.maths.random.Probability;
import org.uncommons.watchmaker.framework.EvolutionEngine;
import org.uncommons.watchmaker.framework.EvolutionObserver;
import org.uncommons.watchmaker.framework.EvolutionaryOperator;
import org.uncommons.watchmaker.framework.FitnessEvaluator;
import org.uncommons.watchmaker.framework.GenerationalEvolutionEngine;
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.operators.EvolutionPipeline;
import org.uncommons.watchmaker.framework.selection.RouletteWheelSelection;
import org.uncommons.watchmaker.framework.termination.TargetFitness;

public class TestMainProg {
    final KarvaEvaluator karvaEvaluator = new KarvaEvaluator();
    public INode[] bestIndividual=null;

    public void go() {
        List<INodeFactory> factories = new ArrayList<INodeFactory>();

        // init the GeneFactory that will create the individuals

        //factories.add(new SimpleNodeFactory(new Add()));
        factories.add(new SimpleNodeFactory(new Multiply()));
        factories.add(new IntegerConstantFactory(2, 35)); //12,60,1 and the target number
        double num = 36.0;

        GeneFactory factory = new GeneFactory(factories, 20); //20 is the gene size

        List<EvolutionaryOperator<INode[]>> operators = new ArrayList<EvolutionaryOperator<INode[]>>();
        operators.add(new MutationOperator<INode[]>(factory, new Probability(0.01d)));
        operators.add(new RecombinationOperator<INode[]>(factory, new Probability(0.5d)));
        EvolutionaryOperator<INode[]> pipeline = new EvolutionPipeline<INode[]>(operators);

        FitnessEvaluator<INode[]> evaluator = new FitnessEvaluator<INode[]>() {
            @Override
            public double getFitness(INode[] candidate, List<? extends INode[]> population) {
                double result = (Double) karvaEvaluator.evaluate(candidate);
                double error = Math.abs(num - result);
                return error;
            }

            @Override
            public boolean isNatural() {
                return false;
            }
        };

        EvolutionEngine<INode[]> engine = new GenerationalEvolutionEngine<INode[]>(factory, pipeline, evaluator,
                new RouletteWheelSelection(), new MersenneTwisterRNG());


        // add an EvolutionObserver so we can print out the status.         
        EvolutionObserver<INode[]> observer = new EvolutionObserver<INode[]>() {
            @Override
            public void populationUpdate(PopulationData<? extends INode[]> data) {
                bestIndividual = data.getBestCandidate();
                System.out.printf("Generation %d, PopulationSize = %d, error = %.1f, value = %.1f, %s\n", 
                                  data.getGenerationNumber(), data.getPopulationSize(),
                                  Math.abs(/*Math.PI*/ num - (Double)karvaEvaluator.evaluate(bestIndividual)), 
                                  (Double)karvaEvaluator.evaluate(bestIndividual), 
                                  karvaEvaluator.print(bestIndividual));    

            }
        };
        engine.addEvolutionObserver(observer);

        //to get the total population
        engine.evolvePopulation(100,10,new TargetFitness(0.0001, false));

    }

    public static final void main(String args[]) {
        new TestMainProg().go();        
    }
}

1 个答案:

答案 0 :(得分:0)

在最终人群中打印所有正确的候选人很简单:

engine.evolvePopulation(100,10,new TargetFitness(0, false)).stream()
   .filter( e -> e.getFitness() == 0 ) // Find all survivors
   .map( e -> karvaEvaluator.print( e.getCandidate() ) ) // Convert to String
   .forEach( System.out::println ); // Print

然而,获得多个两个数字组合更为棘手:

  1. GeneFactory基因长度为5或者可以生成A x B x C,例如2 x 2 x 9 = 36
  2. 每次演变都只能保证一个正确的结果。
  3. 第一点应该很容易修复。 第二,我们可以进行几次演化并巩固结果。 无法保证你会获得所有组合,但你运行得越多,它就越有可能。

      

    优化提示:
      1.数字范围应尽可能小,即2到(目标/ 2)   2.由于只有乘法,所以不需要重组。
      3.只留下(数字)突变,这可能有更高的发生机会。

    我的解决方案:

    import java.util.*;
    import java.util.stream.Collectors;
    import org.gep4j.*;
    import org.gep4j.math.Multiply;
    import org.uncommons.maths.random.MersenneTwisterRNG;
    import org.uncommons.maths.random.Probability;
    import org.uncommons.watchmaker.framework.*;
    import org.uncommons.watchmaker.framework.operators.EvolutionPipeline;
    import org.uncommons.watchmaker.framework.selection.RouletteWheelSelection;
    import org.uncommons.watchmaker.framework.termination.TargetFitness;
    
    public class TestMainProg {
       private static final double NUM = 36.0;
       private static final int RUN = 50;
    
       public void go() {
          KarvaEvaluator karvaEvaluator = new KarvaEvaluator();
    
          GeneFactory factory = new GeneFactory( Arrays.asList(
             new SimpleNodeFactory(new Multiply()),
             new IntegerConstantFactory( 2, (int)(NUM/2) )
          ), 3 );
    
          EvolutionaryOperator<INode[]> pipeline = new EvolutionPipeline<>( Arrays.asList(
             new MutationOperator<>(factory, new Probability(0.5d))
          ) );
    
          FitnessEvaluator<INode[]> evaluator = new FitnessEvaluator<INode[]>() {
             @Override public double getFitness(INode[] candidate, List<? extends INode[]> population) {
                return Math.abs( NUM - (Double) karvaEvaluator.evaluate(candidate) );
             }
             @Override public boolean isNatural() {
                return false;
             }
          };
    
          EvolutionEngine<INode[]> engine = new GenerationalEvolutionEngine<>(factory, pipeline, evaluator,
                new RouletteWheelSelection(), new MersenneTwisterRNG());
    
          Set<String> results = new HashSet<>();
          for ( int i = 0 ; i < RUN ; i ++ ) {
             List<EvaluatedCandidate<INode[]>> finalPopulation =
                engine.evolvePopulation(100,10, new TargetFitness(0, false));
             // Add all survivors to result
             finalPopulation.stream().filter( e -> e.getFitness() == 0 )
                .map( e -> karvaEvaluator.print( e.getCandidate() ) )
                .forEach( results::add );
          }
          new TreeSet( results ).stream().forEach( System.out::println );
       }
    
       public static final void main(String args[]) {
          new TestMainProg().go();
       }
    }