通用遗传算法

通用遗传算法

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 @   gdxstart  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示