【Title】[原]遺傳算法Java實現源代碼
【Date】2013-04-07
【Abstract】以前學習遺傳算法時,用Java實現的遺傳算法程序,現整理分享出來。
【Keywords】wintys、遺傳、算法、algorithm、種群、基因、個體、進化、染色體、適應度、Rosenbrock
【Environment】Windows 7、PowerDesigner16
【Author】wintys (wintys@gmail.com) http://wintys.cnblogs.com
【URL】http://www.cnblogs.com/wintys/archive/2013/04/07/genetic_algorithms.html
【Date】2013-04-07
【Abstract】以前學習遺傳算法時,用Java實現的遺傳算法程序,現整理分享出來。
【Keywords】wintys、遺傳、算法、algorithm、種群、基因、個體、進化、染色體、適應度、Rosenbrock
【Environment】Windows 7、PowerDesigner16
【Author】wintys (wintys@gmail.com) http://wintys.cnblogs.com
【URL】http://www.cnblogs.com/wintys/archive/2013/04/07/genetic_algorithms.html
【Content】:
1、簡介
此程序是對照《遺傳算法原理及應用》(周明、孫樹棟編著),附錄所列C程序改編而來,用Java實現的遺傳算法程序。相關理論請參考《遺傳算法原理及應用》。2、類圖
類圖由源代碼經PowerDesigner反向生成。

3、代碼
3.1、染色體
//染色體:Chromesone.java
class Chromosome implements Cloneable{
private StringBuffer chromosome;
private int chromosomeLength;//染色體長度
private char defaultChar; //默認基因填充字符
public Chromosome(int chromosomeLength){
chromosome = new StringBuffer(chromosomeLength);
chromosome.setLength(chromosomeLength);
defaultChar = '0';
this.chromosomeLength = chromosomeLength;
}
//設置基因
public boolean setGene(int begin , int end , String gene){
int len = gene.length();
if(len > end - begin + 1)
return false;
//index => chromosome , idx => gene
for (int index = begin , idx = 0; index <= end; index++ , idx++) {
if(idx < len)
chromosome.setCharAt(index , gene.charAt(idx));
else
chromosome.setCharAt(index , defaultChar);
}
return true;
}
//獲取基因
public String getGene(int begin , int end){
char[] dest = new char[end - begin + 1];
chromosome.getChars(begin , end + 1 , dest , 0);
return new String(dest);
}
public int getLength(){
return chromosomeLength;
}
public String toString(){
return chromosome.toString();
}
@Override
public Object clone()throws CloneNotSupportedException{
Chromosome c = null;
try{
c = (Chromosome)super.clone();
c.chromosome = new StringBuffer(chromosome);
}catch(CloneNotSupportedException e ){
System.out.println(e.getMessage());
}
return c;
}
}
class Chromosome implements Cloneable{
private StringBuffer chromosome;
private int chromosomeLength;//染色體長度
private char defaultChar; //默認基因填充字符
public Chromosome(int chromosomeLength){
chromosome = new StringBuffer(chromosomeLength);
chromosome.setLength(chromosomeLength);
defaultChar = '0';
this.chromosomeLength = chromosomeLength;
}
//設置基因
public boolean setGene(int begin , int end , String gene){
int len = gene.length();
if(len > end - begin + 1)
return false;
//index => chromosome , idx => gene
for (int index = begin , idx = 0; index <= end; index++ , idx++) {
if(idx < len)
chromosome.setCharAt(index , gene.charAt(idx));
else
chromosome.setCharAt(index , defaultChar);
}
return true;
}
//獲取基因
public String getGene(int begin , int end){
char[] dest = new char[end - begin + 1];
chromosome.getChars(begin , end + 1 , dest , 0);
return new String(dest);
}
public int getLength(){
return chromosomeLength;
}
public String toString(){
return chromosome.toString();
}
@Override
public Object clone()throws CloneNotSupportedException{
Chromosome c = null;
try{
c = (Chromosome)super.clone();
c.chromosome = new StringBuffer(chromosome);
}catch(CloneNotSupportedException e ){
System.out.println(e.getMessage());
}
return c;
}
}
3.2、個體
3.2.1、抽象個體
//Individual.java
abstract class Individual implements Cloneable{
protected Chromosome chrom;//個體基因型:一個基因型染色體由多個基因組成
protected int genelen;//基因長度
protected double fitness;//適應度
protected double targetValue;//目標函數值
public abstract void coding();//編碼
public abstract void decode();//解碼
public abstract void calFitness();//計算個體適應度
public abstract void generateIndividual();//隨機產生個體
public abstract void calTargetValue();//獲取目標函數值
public double getFitness(){
return fitness;
}
public double getTargetValue(){
return targetValue;
}
public int getChromlen(){
return chrom.getLength();
}
public boolean setChrom(int begin , int end , String gene){
return chrom.setGene(begin,end,gene);
}
public String getChrom(int begin , int end){
return chrom.getGene(begin,end);
}
public void mutateSingleBit(int index){
String gene , gn;
gene = chrom.getGene(index , index);
gn = gene.equals("0") ? "1":"0";
chrom.setGene(index , index , gn);
}
@Override
public Object clone(){
Individual indv = null;
try{
indv = (Individual)super.clone();
indv.chrom = (Chromosome)chrom.clone();
}catch(CloneNotSupportedException e ){
System.out.println(e.getMessage());
}
return indv;
}
}
abstract class Individual implements Cloneable{
protected Chromosome chrom;//個體基因型:一個基因型染色體由多個基因組成
protected int genelen;//基因長度
protected double fitness;//適應度
protected double targetValue;//目標函數值
public abstract void coding();//編碼
public abstract void decode();//解碼
public abstract void calFitness();//計算個體適應度
public abstract void generateIndividual();//隨機產生個體
public abstract void calTargetValue();//獲取目標函數值
public double getFitness(){
return fitness;
}
public double getTargetValue(){
return targetValue;
}
public int getChromlen(){
return chrom.getLength();
}
public boolean setChrom(int begin , int end , String gene){
return chrom.setGene(begin,end,gene);
}
public String getChrom(int begin , int end){
return chrom.getGene(begin,end);
}
public void mutateSingleBit(int index){
String gene , gn;
gene = chrom.getGene(index , index);
gn = gene.equals("0") ? "1":"0";
chrom.setGene(index , index , gn);
}
@Override
public Object clone(){
Individual indv = null;
try{
indv = (Individual)super.clone();
indv.chrom = (Chromosome)chrom.clone();
}catch(CloneNotSupportedException e ){
System.out.println(e.getMessage());
}
return indv;
}
}
3.2.2、Rosenbrock個體實現
//RosenbrockIndividual.java
class RosenbrockIndividual extends Individual {
private double x1 , x2; // 個體表現型
//基因型chromosome由 (x1 , x2)編碼而成
RosenbrockIndividual(int chromlen){
genelen = 10;
chrom = new Chromosome(chromlen);
}
//編碼
public void coding(){
String code1,code2;
code1 = codingVariable(x1);
code2 = codingVariable(x2);
chrom.setGene(0 , 9 , code1);
chrom.setGene(10, 19 , code2);
}
//解碼
public void decode(){
String gene1,gene2;
gene1 = chrom.getGene(0 , 9);
gene2 = chrom.getGene(10 , 19);
x1 = decodeGene(gene1);
x2 = decodeGene(gene2);
}
//計算目標函數值
public void calTargetValue(){
decode();
targetValue = rosenbrock(x1 , x2);
}
//計算個體適應度
public void calFitness(){
fitness = getTargetValue();
}
private String codingVariable(double x){
double y = (((x + 2.048) * 1023) / 4.096);
String code = Integer.toBinaryString((int) y);
StringBuffer codeBuf = new StringBuffer(code);
for(int i = code.length(); i<genelen; i++)
codeBuf.insert(0,'0');
return codeBuf.toString();
}
private double decodeGene(String gene){
int value ;
double decode;
value = Integer.parseInt(gene, 2);
decode = value/1023.0*4.096 - 2.048;
return decode;
}
public String toString(){
String str = "";
///str = "基因型:" + chrom + " ";
///str+= "表現型:" + "[x1,x2]=" + "[" + x1 + "," + x2 + "]" + "\t";
str+="函數值:" + rosenbrock(x1 , x2) + "\n";
return str;
}
/**
*Rosenbrock函數:
*f(x1,x2) = 100*(x1**2 - x2)**2 + (1 - x1)**2
*在當x在[-2.048 , 2.048]內時,
*函數有兩個極大點:
*f(2.048 , -2.048) = 3897.7342
*f(-2.048,-2.048) = 3905.926227
*其中后者為全局最大點。
*/
public static double rosenbrock(double x1 , double x2){
double fun;
fun = 100*Math.pow((x1*x1 - x2) , 2) + Math.pow((1 - x1) , 2);
return fun;
}
//隨機產生個體
public void generateIndividual(){
x1 = Math.random() * 4.096 - 2.048;
x2 = Math.random() * 4.096 - 2.048;
//同步編碼和適應度
coding();
calTargetValue();
calFitness();
}
}
class RosenbrockIndividual extends Individual {
private double x1 , x2; // 個體表現型
//基因型chromosome由 (x1 , x2)編碼而成
RosenbrockIndividual(int chromlen){
genelen = 10;
chrom = new Chromosome(chromlen);
}
//編碼
public void coding(){
String code1,code2;
code1 = codingVariable(x1);
code2 = codingVariable(x2);
chrom.setGene(0 , 9 , code1);
chrom.setGene(10, 19 , code2);
}
//解碼
public void decode(){
String gene1,gene2;
gene1 = chrom.getGene(0 , 9);
gene2 = chrom.getGene(10 , 19);
x1 = decodeGene(gene1);
x2 = decodeGene(gene2);
}
//計算目標函數值
public void calTargetValue(){
decode();
targetValue = rosenbrock(x1 , x2);
}
//計算個體適應度
public void calFitness(){
fitness = getTargetValue();
}
private String codingVariable(double x){
double y = (((x + 2.048) * 1023) / 4.096);
String code = Integer.toBinaryString((int) y);
StringBuffer codeBuf = new StringBuffer(code);
for(int i = code.length(); i<genelen; i++)
codeBuf.insert(0,'0');
return codeBuf.toString();
}
private double decodeGene(String gene){
int value ;
double decode;
value = Integer.parseInt(gene, 2);
decode = value/1023.0*4.096 - 2.048;
return decode;
}
public String toString(){
String str = "";
///str = "基因型:" + chrom + " ";
///str+= "表現型:" + "[x1,x2]=" + "[" + x1 + "," + x2 + "]" + "\t";
str+="函數值:" + rosenbrock(x1 , x2) + "\n";
return str;
}
/**
*Rosenbrock函數:
*f(x1,x2) = 100*(x1**2 - x2)**2 + (1 - x1)**2
*在當x在[-2.048 , 2.048]內時,
*函數有兩個極大點:
*f(2.048 , -2.048) = 3897.7342
*f(-2.048,-2.048) = 3905.926227
*其中后者為全局最大點。
*/
public static double rosenbrock(double x1 , double x2){
double fun;
fun = 100*Math.pow((x1*x1 - x2) , 2) + Math.pow((1 - x1) , 2);
return fun;
}
//隨機產生個體
public void generateIndividual(){
x1 = Math.random() * 4.096 - 2.048;
x2 = Math.random() * 4.096 - 2.048;
//同步編碼和適應度
coding();
calTargetValue();
calFitness();
}
}
3.3、種群
//Population.java
class Population{
private int generation; //種群的代數
private int size; //群體大小
private Individual[] pop; //種群
private double averageFitness; //平均適應度
private double[] relativeFitness; //相對適應度
private int chromlen;//基因長度
Individual bestIndividual;//當前代適應度最好的個體
Individual worstIndividual;//當前代適應度最差的個體
Individual currentBest;//到目前代為止最好的個體
private int worstIndex;//bestIndividual對應的數組下標
public Population(int size){
this.generation = 0;
this.size = size;
this.pop = new Individual[size];
this.averageFitness = 0;
this.relativeFitness = new double[size];
this.chromlen = 20;
for(int i = 0; i < size; i++){
pop[i] = new RosenbrockIndividual(chromlen);
}
}
//初始化種群
public void initPopulation(){
for(int i = 0;i < size;i++){
pop[i].generateIndividual();
}
findBestAndWorstIndividual();
}
//----------------------------------------------------
//比例選擇
public void select(){
double[] rouletteWheel; //賭盤
Individual[] childPop = new Individual[size];
calRelativeFitness();
//產生賭盤
rouletteWheel = new double[size];
rouletteWheel[0] = relativeFitness[0];
for(int i=1;i<size -1;i++){
rouletteWheel[i] = relativeFitness[i] + rouletteWheel[i - 1];
}
rouletteWheel[size - 1] = 1;
//進行賭盤選擇,產生新種群
for(int i = 0;i < size ; i++){
double rnd = rand();
for(int j = 0; j < size; j++){
if(rnd < rouletteWheel[j]){
childPop[i] = pop[j];
break;
}
}
}
for(int i = 0;i < size; i++){
pop[i] = childPop[i];
}
//return childPop;
}
//求總適應度
private double calTotalFitness(){
double total = 0;
for(int i = 0 ; i < size ;i++)
total += pop[i].getFitness();
return total;
}
//計算相對適應度
public double[] calRelativeFitness(){
double totalFitness = calTotalFitness();
for(int i = 0 ;i < size ; i++){
relativeFitness[i] = pop[i].getFitness() / totalFitness;
}
return relativeFitness;
}
//================================
//------------------------------------------------------
//單點交叉
public void crossover(){
for(int i = 0 ; i < size/2*2; i+=2){
int rnd;
//隨機兩兩配對
rnd = rand(i , size);
if(rnd != i)
exchange(pop , i , rnd);
rnd = rand(i , size);
if(rnd != i+1)
exchange(pop , i + 1 , rnd);
//交叉
double random = rand();
if(random < GeneticAlgorithms.crossoverRate){
cross(i);
}
}
}
//執行交叉操作
private void cross(int i){
String chromFragment1,chromFragment2;//基因片段
int rnd = rand(0 , getChromlen() - 1);//交叉點為rnd之后,可能的位置有chromlen - 1個.
chromFragment1 = pop[i].getChrom(rnd + 1 , getChromlen() - 1);
chromFragment2 = pop[i+1].getChrom(rnd + 1 , getChromlen() - 1);
pop[i].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment2);
pop[i+1].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment1);
}
//產生隨機數
private int rand(int start , int end){//產生區間為[start , end)的隨機整數
return (int)(rand()*(end - start) + start);
}
//交換
private void exchange(Individual[] p ,int src , int dest){
Individual temp;
temp = p[src];
p[src] = p[dest];
p[dest] = temp;
}
//==============================
//-----------------------------------------------------
//變異
public void mutate(){
for(int i = 0 ; i < size;i++){
for(int j = 0 ;j < getChromlen(); j++){
if(rand() < GeneticAlgorithms.mutateRate){
pop[i].mutateSingleBit(j);
///System.out.print("變異"+ i +" - "+ j + " ");///
}
}
}
}
//==============================
//-----------------------------------------------------
//進化
public void evolve(){
select();
crossover();
mutate();
evaluate();
}
//==============================
//計算目標函數值、適應度、找出最優個體。
public void evaluate(){
//同步目標函數值和適應度
for(int i = 0; i < size; i++){
pop[i].calTargetValue();
pop[i].calFitness();
}
//使用最優保存策略(Elitist Model)保存最優個體
findBestAndWorstIndividual();
pop[worstIndex] = (Individual)currentBest.clone();
generation++;
}
//找出適應度最大的個體
public void findBestAndWorstIndividual(){
bestIndividual = worstIndividual = pop[0];
for(int i = 1; i <size;i++){
if(pop[i].fitness > bestIndividual.fitness){
bestIndividual = pop[i];
}
if(pop[i].fitness < worstIndividual.fitness){
worstIndividual = pop[i];
worstIndex = i;
}
}
if( generation == 0 ){//初始種群
currentBest = (Individual)bestIndividual.clone();
}else{
if(bestIndividual.fitness > currentBest.fitness)
currentBest = (Individual)bestIndividual.clone();
}
}
//判斷進化是否完成
public boolean isEvolutionDone(){
if(generation < GeneticAlgorithms.maxGeneration)
return false;
return true;
}
//計算平均適應度
public double calAverageFitness(){
for(int i = 0 ; i < size; i++){
averageFitness += pop[i].getFitness();
}
averageFitness/=size;
return averageFitness;
}
//產生隨機數
private double rand(){
return Math.random();
}
public int getChromlen(){
return chromlen;
}
public void setGeneration(int generation){
this.generation = generation;
}
public int getGeneration(){
return generation;
}
/*
public String printPop(Individual[] pop){
String str="";
for(int i = 0 ; i < size ; i++)
str += pop[i];
return str;
}*/
public String toString(){
String str="";
for(int i = 0 ; i < size ; i++)
str += pop[i];
return str;
}
}
class Population{
private int generation; //種群的代數
private int size; //群體大小
private Individual[] pop; //種群
private double averageFitness; //平均適應度
private double[] relativeFitness; //相對適應度
private int chromlen;//基因長度
Individual bestIndividual;//當前代適應度最好的個體
Individual worstIndividual;//當前代適應度最差的個體
Individual currentBest;//到目前代為止最好的個體
private int worstIndex;//bestIndividual對應的數組下標
public Population(int size){
this.generation = 0;
this.size = size;
this.pop = new Individual[size];
this.averageFitness = 0;
this.relativeFitness = new double[size];
this.chromlen = 20;
for(int i = 0; i < size; i++){
pop[i] = new RosenbrockIndividual(chromlen);
}
}
//初始化種群
public void initPopulation(){
for(int i = 0;i < size;i++){
pop[i].generateIndividual();
}
findBestAndWorstIndividual();
}
//----------------------------------------------------
//比例選擇
public void select(){
double[] rouletteWheel; //賭盤
Individual[] childPop = new Individual[size];
calRelativeFitness();
//產生賭盤
rouletteWheel = new double[size];
rouletteWheel[0] = relativeFitness[0];
for(int i=1;i<size -1;i++){
rouletteWheel[i] = relativeFitness[i] + rouletteWheel[i - 1];
}
rouletteWheel[size - 1] = 1;
//進行賭盤選擇,產生新種群
for(int i = 0;i < size ; i++){
double rnd = rand();
for(int j = 0; j < size; j++){
if(rnd < rouletteWheel[j]){
childPop[i] = pop[j];
break;
}
}
}
for(int i = 0;i < size; i++){
pop[i] = childPop[i];
}
//return childPop;
}
//求總適應度
private double calTotalFitness(){
double total = 0;
for(int i = 0 ; i < size ;i++)
total += pop[i].getFitness();
return total;
}
//計算相對適應度
public double[] calRelativeFitness(){
double totalFitness = calTotalFitness();
for(int i = 0 ;i < size ; i++){
relativeFitness[i] = pop[i].getFitness() / totalFitness;
}
return relativeFitness;
}
//================================
//------------------------------------------------------
//單點交叉
public void crossover(){
for(int i = 0 ; i < size/2*2; i+=2){
int rnd;
//隨機兩兩配對
rnd = rand(i , size);
if(rnd != i)
exchange(pop , i , rnd);
rnd = rand(i , size);
if(rnd != i+1)
exchange(pop , i + 1 , rnd);
//交叉
double random = rand();
if(random < GeneticAlgorithms.crossoverRate){
cross(i);
}
}
}
//執行交叉操作
private void cross(int i){
String chromFragment1,chromFragment2;//基因片段
int rnd = rand(0 , getChromlen() - 1);//交叉點為rnd之后,可能的位置有chromlen - 1個.
chromFragment1 = pop[i].getChrom(rnd + 1 , getChromlen() - 1);
chromFragment2 = pop[i+1].getChrom(rnd + 1 , getChromlen() - 1);
pop[i].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment2);
pop[i+1].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment1);
}
//產生隨機數
private int rand(int start , int end){//產生區間為[start , end)的隨機整數
return (int)(rand()*(end - start) + start);
}
//交換
private void exchange(Individual[] p ,int src , int dest){
Individual temp;
temp = p[src];
p[src] = p[dest];
p[dest] = temp;
}
//==============================
//-----------------------------------------------------
//變異
public void mutate(){
for(int i = 0 ; i < size;i++){
for(int j = 0 ;j < getChromlen(); j++){
if(rand() < GeneticAlgorithms.mutateRate){
pop[i].mutateSingleBit(j);
///System.out.print("變異"+ i +" - "+ j + " ");///
}
}
}
}
//==============================
//-----------------------------------------------------
//進化
public void evolve(){
select();
crossover();
mutate();
evaluate();
}
//==============================
//計算目標函數值、適應度、找出最優個體。
public void evaluate(){
//同步目標函數值和適應度
for(int i = 0; i < size; i++){
pop[i].calTargetValue();
pop[i].calFitness();
}
//使用最優保存策略(Elitist Model)保存最優個體
findBestAndWorstIndividual();
pop[worstIndex] = (Individual)currentBest.clone();
generation++;
}
//找出適應度最大的個體
public void findBestAndWorstIndividual(){
bestIndividual = worstIndividual = pop[0];
for(int i = 1; i <size;i++){
if(pop[i].fitness > bestIndividual.fitness){
bestIndividual = pop[i];
}
if(pop[i].fitness < worstIndividual.fitness){
worstIndividual = pop[i];
worstIndex = i;
}
}
if( generation == 0 ){//初始種群
currentBest = (Individual)bestIndividual.clone();
}else{
if(bestIndividual.fitness > currentBest.fitness)
currentBest = (Individual)bestIndividual.clone();
}
}
//判斷進化是否完成
public boolean isEvolutionDone(){
if(generation < GeneticAlgorithms.maxGeneration)
return false;
return true;
}
//計算平均適應度
public double calAverageFitness(){
for(int i = 0 ; i < size; i++){
averageFitness += pop[i].getFitness();
}
averageFitness/=size;
return averageFitness;
}
//產生隨機數
private double rand(){
return Math.random();
}
public int getChromlen(){
return chromlen;
}
public void setGeneration(int generation){
this.generation = generation;
}
public int getGeneration(){
return generation;
}
/*
public String printPop(Individual[] pop){
String str="";
for(int i = 0 ; i < size ; i++)
str += pop[i];
return str;
}*/
public String toString(){
String str="";
for(int i = 0 ; i < size ; i++)
str += pop[i];
return str;
}
}
3.4 測試
//GeneticAlgorithms.java 給定參數,測試遺傳算法
import java.io.*;
//2008-11-21
class GeneticAlgorithms{
public static double crossoverRate;//交叉概率
public static double mutateRate;//變異概率
public static int maxGeneration;//進化代數
public static int populationSize;//群體大小
static {
//crossoverRate = 0.6;
//mutateRate = 0.001;
//maxGeneration = 100;
//populationSize = 500;
maxGeneration = 100;
populationSize = 500;
crossoverRate = 0.6;
mutateRate = 0.001;
}
public static void main(String[] args)throws IOException{
FileWriter fw = new FileWriter("result.txt");
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
Population pop = new Population(populationSize);
pop.initPopulation();
pw.println("初始種群:\n" + pop);
while(!pop.isEvolutionDone()){
pop.evolve();
pw.print("第" + pop.getGeneration() + "代Best:" + pop.bestIndividual );
pw.print("第" + pop.getGeneration() + "代current:" + pop.currentBest );
pw.println("");
}
pw.println();
pw.println("第"+ pop.getGeneration() + "代群體:\n" + pop);
pw.close();
}
public void print(){
}
}
import java.io.*;
//2008-11-21
class GeneticAlgorithms{
public static double crossoverRate;//交叉概率
public static double mutateRate;//變異概率
public static int maxGeneration;//進化代數
public static int populationSize;//群體大小
static {
//crossoverRate = 0.6;
//mutateRate = 0.001;
//maxGeneration = 100;
//populationSize = 500;
maxGeneration = 100;
populationSize = 500;
crossoverRate = 0.6;
mutateRate = 0.001;
}
public static void main(String[] args)throws IOException{
FileWriter fw = new FileWriter("result.txt");
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
Population pop = new Population(populationSize);
pop.initPopulation();
pw.println("初始種群:\n" + pop);
while(!pop.isEvolutionDone()){
pop.evolve();
pw.print("第" + pop.getGeneration() + "代Best:" + pop.bestIndividual );
pw.print("第" + pop.getGeneration() + "代current:" + pop.currentBest );
pw.println("");
}
pw.println();
pw.println("第"+ pop.getGeneration() + "代群體:\n" + pop);
pw.close();
}
public void print(){
}
}
【Reference】
[1]《遺傳算法原理及應用》(周明、孫樹棟編著)
【Attachment】