通用遗传算法

通用遗传算法

package chapter5;

import java.util.List;

/**
 * @author dance-start
 * @version 1.0
 * @description: 染色体类
 * @date 2023/5/9 13:13
 */
public abstract class Chromosome<T extends Chromosome<T>> implements Comparable<T> {
    //以下都是染色体类的基本特征
    public abstract double fitness();
    public abstract List<T> crossover(T other);
    public abstract void mutate();
    public  abstract T copy();
    @Override
    public int compareTo(T o) {
        Double mine = this.fitness();
        Double other = o.fitness();
        return mine.compareTo(other);
    }

}
package chapter5;

import java.util.*;
import java.util.List;

/**
 * @author dance-start
 * @version 1.0
 * @description: 普遍算法
 * @date 2023/5/9 13:25
 */
public class GeneticAlgorithm<C extends Chromosome<C>> {



    //1.选择方法,轮盘赌or锦标赛
    public enum SelectType {
        ROULETTE, TOURNAMENT;//roulette,touranment
    }

    private List<C> population;//种群
    private double mutationChance;//变异值
    private double crossChance;//交叉值
    private SelectType selectType;//选中值
    private Random random;//随机值

    /*
     * @Description
     * @Param 初代种群 变异值 交叉值 选择方法 随机值
     **/
    public GeneticAlgorithm(List<C> initialPopu, double mutationChance,
                            double crossChance, SelectType selectType) {
        this.population = initialPopu;
        this.mutationChance = mutationChance;
        this.crossChance = crossChance;
        this.selectType = selectType;
        this.random = new Random();
    }

    /*
     * @Description 轮盘式,选择旧种群里的染色体
     * @Param wheel:数组,表示适应度比例值;numPicks为被选中的染色体数量
     * @return 返回选中的染色体
     **/
    private List<C> pickRoulette(double[] wheel, int numPicks) {
        List<C> picks = new ArrayList<>();
        for (int i = 0; i < numPicks; i++) {//i代表每一个染色体
            //每选中一条染色体,就重新再产生随机数pick
            double pick = random.nextDouble();
            //循环遍历每一个染色体的适应度值,如果pick小与0,则结束
            for (int j = 0; j < wheel.length; j++) {
                pick -= wheel[j];
                if (pick <= 0) {
                    //如果pick<0,则将该染色体被选中
                    picks.add(population.get(j));
                }
            }
        }
        return picks;
    }
    /*
     * @Description 锦标赛
     * @Param partchromoNum表示从种群选中的染色体数量;
     *        picksNum表示从选中的染色体竞赛胜出的染色体数量。
     * @return 返回选中的染色体
     **/
    private List<C> pickTournament(int partchromoNum, int picksNum) {
        //打散种群
        Collections.shuffle(population);
        //选中部分染色体
        List<C> tournamet = population.subList(0, partchromoNum);
        //染色体从大到小排序
        Collections.sort(tournamet,Collections.reverseOrder());
        return tournamet.subList(0,picksNum);
    }
    /*
     * @Description 进行繁殖
     * @return 无
     **/
    private void reproduceAndReplace(){
        //用一个List容器存新的种群
        List<C> newPopulation = new ArrayList<>();
        while (newPopulation.size()<population.size()){//一直产生新的染色体,直到父种群==新种群
            //挑选出两条染色体,作为父母
            List<C> parents;
            //选择法
            if (selectType == SelectType.ROULETTE){
                //所有的适应度值之和
                double totalFitness = population.stream().mapToDouble(C::fitness).sum();
                //计算wheel
                double[] wheel = population.stream().mapToDouble(C -> C.fitness() / totalFitness).toArray();
                parents = pickRoulette(wheel, 2);

            }else {
                parents = pickTournament(population.size() / 2, 2);
            }
            //自我复制或交叉
            if (random.nextDouble()<crossChance){//交叉
                C father = parents.get(0);
                C mother = parents.get(1);
                List<C> crossover = father.crossover(mother);
                newPopulation.addAll(crossover);
            }else {//自我复制
                newPopulation.addAll(parents);
            }
            //控制新种群染色体个数
            if (newPopulation.size()>population.size()){
                newPopulation.remove(0);
            }
            //更新种群
            population = newPopulation;
        }
    }
    //变异方法,实现逻辑层面,具体交个run()方法实现
    private void mutate(){
        for (C indiv:population){
            if (random.nextDouble()<mutationChance){
                indiv.mutate();
            }
        }
    }
    /*
     * @Description 这里开始一代一代的进行繁殖突变
     * @Param maxGenerations表示主程序循环的次数;
     *        threshold表示适应度的满意值,如果有染色体的适应度大于等于该值,则直接终止程序。
     * @return 返回一个最好的(适应度最接近threshold)染色体
     **/
    public C run(int maxGenerations,double threshold){
        C best = Collections.max(population).copy();
        for (int generation =0;generation<maxGenerations;generation++){
            if (best.fitness()>=threshold){
                return best;
            }
            System.out.println("Generation:"+generation+"  Best"+best.fitness()+
                    "  Avg"+population.stream().mapToDouble(C::fitness).average().orElse(0.0));
            reproduceAndReplace();
            mutate();
            C hightest = Collections.max(population);
            if (hightest.fitness()>best.fitness()){
                best = hightest.copy();
            }
        }
        return best;
    }

}
package chapter5;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author dance-start
 * @version 1.0
 * @description: 实现计算函数 6x - x^2 + 4y -y^2 最大值化
 * @date 2023/5/10 12:24
 */
public class SimpleEquation extends Chromosome<SimpleEquation>{

    private int x,y;
    @Override
    public double fitness() {
        return 6*x-x*x+4*y-y*y;
    }
    public SimpleEquation(){};
    public SimpleEquation(int x,int y){
        this.x = x;
        this.y = y;
    }
    @Override
    public List<SimpleEquation> crossover(SimpleEquation other) {
        SimpleEquation child1 = new SimpleEquation(x,other.y);
        SimpleEquation child2 = new SimpleEquation(other.x, y);
        List<SimpleEquation> list = new ArrayList<>();
        list.add(child1);
        list.add(child2);
        return list;
    }

    @Override
    public void mutate() {
        Random random = new Random();
        if (random.nextDouble()>0.5){//变异x
            if (random.nextDouble()>0.5){
                x +=1;
            }else {
                x -=1;
            }
        }else {//变异y
            if (random.nextDouble()>0.5){
                y +=1;
            }else
                y -=1;
        }
    }

    @Override
    public SimpleEquation copy() {
        return new SimpleEquation(x,y);
    }

    @Override
    public String toString() {
        return "X: " + x + ", y:" + y + "Fitness" + fitness();
    }
    private static final int MAX_START = 100;
    public static SimpleEquation randomInstance(){
        Random random = new Random();
        return new SimpleEquation(random.nextInt(MAX_START),random.nextInt(MAX_START));
    }

    public static void main(String[] args) {
        ArrayList<SimpleEquation> initPopulation = new ArrayList<>();
        final int populationSize = 20;
        final int generations =100;
        final double threshold = 13.0;
        for (int i =0; i<populationSize;i++){
            initPopulation.add(SimpleEquation.randomInstance());
        }
        GeneticAlgorithm<SimpleEquation> ga = new GeneticAlgorithm<>(
                initPopulation,0.1,0.7, GeneticAlgorithm.SelectType.ROULETTE);
        SimpleEquation result = ga.run(100, 13.0);
        System.out.println(generations+threshold);
    }
}
posted @ 2023-05-12 23:19  郭培鑫同学  阅读(24)  评论(0编辑  收藏  举报