只是基本实现了遗传算法的思想及运算功能,算法得到的结果收敛性过强,推测可能是处理样本数太小。
1研究目的
通过遗传算法计算出加工部件选择加工机器的最佳方案。
2.研究背景介绍
假设每个加工部件可以在所以的加工机器上加工,选择不同的加工机器则加工时间不同,各个部件的加工时间相互独立没有关系。
一个项目包含部件的集合J, J = { J1,J2,J3 …Jn},n为部件的编号;本次研究预设为20个部件。
车间的机器为集合M,M={ M 1,M 2,M 3 …M k},k为设备的编号;本次研究预设为4台机器。
已知每个部件对应加工机器的工作时间表;本次研究随机生成一张加工时间表,加工时间分布在[2,10]之间。
假设每个部件只有一道工序,算法为每个部件分配加工的机器,并且尽量使加工时间最短。
最优结果约束条件1:为了满足实际生产情况,保证生产过程的资源利用率,每台机器分配加工任务的时间差小于range;本次研究设定为5。
最优结果约束条件2:在满足约束条件1的基础上,选择方案集中最长加工时间最短的方案。即选择方案中单台机器的最长加工时间都小于其他方案中的单台机器的最长加工时间。
3.研究方法
3.1遗传算法基本理论
遗传算法是由美国的 J. Holland 教授于 1975 年在他的专著《自然界和人工系统的适应性》中首先提出的,它是一类借鉴生物界自然选择和自然遗传机制的随机化搜索算法。遗传算法模拟自然选择和自然遗传过程中发生的繁殖、交叉和基因突变现象,在每次迭代中都保留一组候选解,并按某种指标从解群中选取较优的个体,利用遗传算子(选择、交叉和变异)对这些个体进行组合,产生新一代的候选解群,重复此过程,直到满足某种收敛指标为止。
3.2遗传算法的实现原理
基本遗传算法(Simple Genetic Algorithms,简称 SGA,又称简单遗传算法或标准遗传算法),是由 Goldberg 总结出的一种最基本的遗传算法,其遗传进化操作过程简单,容易理解,是其它一些遗传算法的雏形和基础。标准遗传算法(Canonical Genetic Algorithms)的步骤
如下:
(1)构造满足约束条件的染色体。由于遗传算法不能直接处理解空间中的解,所以必须通过编码将解表示成适当的染色体。实际问题的染色体有多种编码方式,染色体编码方式的选取应尽可能符合问题约束,否则将影响计算效率。
(2)随机产生初始群体。初始群体是搜索开始时的一组染色体,其数量应适当选择。
(3)计算每个染色体的适应度。适应度是反映染色体优劣的唯一指标,遗传算法就是要寻得适应度最大的染色体。
(4)使用复制、交叉和变异算子产生子群体。这三个算子是遗传算法的基本算子,其中复制体现了优胜劣汰的自然规律,交叉体现了有性繁殖的思想,变异体现了进化过程中的基因突变。
(5)重复步骤(3),(4)直到满足终止条件为止。
4.算法处理步骤
1.编码
规定奇数位为部件的编号,偶数位为前一位代表的部件选择的机器编号。
例如序列[1,1, 2,1, 3,2, 4,1, 5,2]表示:部件1选择机器1,部件2选择机器1,部件3选择机器2,部件4选择机器1,部件5选择机器2。
运算开始时对每个部件随机选择一个机器编号,产生8000个选择方案(基因片段)。
2.适应度
分为两个等级:
适应度1: 本次方案中单台机器的最长加工时间与最短加工时间的差值;
适应度2: 本次方案中单台机器的最长的加工时间;
3.选择算子
阶段1:选取适应度1中距离小于range的基因组;
阶段2:从选取的基因组中以适应度2大小的倒数为选择概率轮盘选择;
本次研究设定一次进化过程中在本方案中选择两个符合条件的基因组,并对他们进行交叉操作。
4.交叉算子
在满足交叉概率的条件下,随机生成一个部件序号,对相应部件的加工机器的基因片段进行交叉操作,即对上一步选择的两个基因片段进行操作,随机选择一个部件,交换这个部件的加工机器编号。
交叉操作完成后还要进行适应度1函数判断,满足则交叉成功,复制进种群中,否则不进行复制。
5.变异算子
在满足变异概率的条件下,对偶数位的基因片段生成[1,4]的随机数,即对部件重新随机选择一个加工机器。
变异操作完成后还要进行适应度1函数判断,满足则变异成功,复制进种群中,否则不进行复制。
4.流程图
4.实验及结果分析
参数设定:
部件的数量:20
机器的数量:4
初始生成种群:8000
优化选择种群(从初始生成种群中选择满足适应度1的种群):20
迭代次数:5
交叉率:0.9
变异率:0.1
随机生成的加工时间记录表: (行表示部件序号; 列表示机器编号)
机器1 机器2 机器3 机器4
部件1 3—-5—-2—-5—-
部件2 3—-2—-6—-6—-
部件3 5—-4—-3—-6—-
部件4 9—-4—-3—-5—-
部件5 8—-2—-5—-3—-
部件6 3—-2—-7—-7—-
部件7 2—-2—-6—-4—-
部件8 5—-4—-6—-3—-
部件9 3—-9—-5—-9—-
部件10 3—-8—-2—-5—-
部件11 3—-3—-8—-4—-
部件12 5—-8—-5—-2—-
部件13 3—-3—-9—-3—-
部件14 9—-7—-9—-5—-
部件15 2—-6—-5—-5—-
部件16 6—-5—-4—-7—-
部件17 6—-8—-2—-4—-
部件18 5—-7—-5—-5—-
部件19 4—-7—-9—-3—-
部件20 7—-3—-4—-8—-
/************************************************/
最终输出结果:
20个部件最终选择的机器号为:
***部件1选择的机器编号为:1
***部件2选择的机器编号为:2
***部件3选择的机器编号为:2
***部件4选择的机器编号为:3
***部件5选择的机器编号为:1
***部件6选择的机器编号为:2
***部件7选择的机器编号为:4
***部件8选择的机器编号为:3
***部件9选择的机器编号为:3
***部件10选择的机器编号为:3
***部件11选择的机器编号为:4
***部件12选择的机器编号为:4
***部件13选择的机器编号为:4
***部件14选择的机器编号为:1
***部件15选择的机器编号为:1
***部件16选择的机器编号为:2
***部件17选择的机器编号为:2
***部件18选择的机器编号为:4
***部件19选择的机器编号为:4
***部件20选择的机器编号为:3
每个机器的运行时间为:
***机器1的累计加工时间:22
***机器2的累计加工时间:21
***机器3的累计加工时间:20
***机器4的累计加工时间:21
4个机器运行时间的最大差值为:
2
4个机器的最长运行时间为:
22
附java源代码:
本程序含有两个类:Chromosome Genetic
类Chromosome对基因的数据结构进行定义,并且定义了计算适应度1、适应度2的方法;
类Genetic包含对基因的操作:选择、交叉、变异、迭代
类Chromosome
importjava.util.Random;
public classChromosome implements Cloneable{
public int [] _Component; //编码数组
private int_ComponentNumber; //部件的数量
private int_MachineNumber; //机器的数量
private int []_fitness1; //单个机器总计运行时间适应度函数
private int _fitness2; //二阶段适应度函数
private int _fitMaxMin; //一阶段适应度函数,最长运行时间与最短运行时间之差
/************************************private变量封装 ********************************/
public int get_fitMaxMin(){
return _fitMaxMin;
}
public void set_fitMaxMin(int_fitMaxMin) {
this._fitMaxMin =_fitMaxMin;
}
public int[] get_fitness1(){
return _fitness1;
}
public void set_fitness1(int[]_fitness1) {
this._fitness1 =_fitness1;
}
public int get_fitness2(){
return _fitness2;
}
public void set_fitness2(int_fitness2) {
this._fitness2 =_fitness2;
}
public int[] get_Component(){
return _Component;
}
public void set_Component(int[]_Component) {
this._Component =_Component;
}
public int get_MachineNumber(){
return _MachineNumber;
}
public void set_MachineNumber(int_MachineNumber) {
this._MachineNumber =_MachineNumber;
}
public int get_ConponentNumber(){
return_ComponentNumber;
}
public void set_ConponentNumber(int_ConponentNumber) {
this._ComponentNumber= _ConponentNumber;
}
/************************************************private变量封装 end*****************************/
public Chromosome(){
//设定部件的数量:20
this._ComponentNumber=20;
//设定机器的数量:4
this._MachineNumber=4;
this._Component=newint[_ComponentNumber*2];
}
public void randomGeneration(){ //初始化编码数组
Random rm=newRandom();
int sequenceNum=1;
for(inti=0;i<_ComponentNumber*2;i++){
_Component[i]=sequenceNum; //输入部件编号
i++;
sequenceNum++;
_Component[i]=rm.nextInt(_MachineNumber)+1; //随机选择机器编号
}
}
public void caculateFitness1(int[][] _GenerateLoad){
this._fitness1=newint[_MachineNumber];
for(inti=0;i<_ComponentNumber;i++){
intn1=_Component[i*2+1]-1;
_fitness1[n1]+=_GenerateLoad[i][n1];
//为每个机器计算选择部件的总计加工时间,从时间表里选择
}
}
public int caculateFitness2(){
int Max=0;
int min=500;
for(inti=0;i<_MachineNumber;i++){
if(Max<_fitness1[i]){
Max=_fitness1[i];
}
if(min>_fitness1[i]){
min=_fitness1[i];
}
}
this._fitness2=Max;
this._fitMaxMin=Max-min;
return _fitness2;
}
public Object clone() throwsCloneNotSupportedException{
Chromosomechromosome1=(Chromosome)super.clone();
chromosome1._Component=this._Component.clone();
chromosome1._ComponentNumber=this._ComponentNumber;
chromosome1._fitness1=this._fitness1.clone();
chromosome1._fitness2=this._fitness2;
chromosome1._MachineNumber=this._MachineNumber;
chromosome1._fitMaxMin=this._fitMaxMin;
return chromosome1;
}
public void printMachineInfo(){ //输出机器的加工时间
int NO=0;
for (int i = 0;i < _MachineNumber; i++) {
NO=i+1;
System.out.println(“***机器”+NO+”的累计加工时间:”+_fitness1[i]);
}
}
public void printComponentInfo(){
for (int i = 0;i < _ComponentNumber; i++) {
System.out.println(“***部件”+_Component[i*2]+”选择的机器编号为:”+_Component[i*2+1]);
}
}
}
类Genetic
importjava.util.Random;
public classGenetic{
private int iteration; //运行代数
private double p_c; //交叉率
private double p_m; //变异率
private double range; //评判适应度1的参数
private Chromosome[] project=newChromosome[8000]; //染色体组,初始生成8000组
public int[] bestChromosome=new int[40]; //[偶数]:存储基因序号;[奇数]:存储//机器运行最长小时数; 20个选择//的基因信息
private int selectNum; //选择算子的选择个数参数
private int[][]tempGenetics=new int[20][40]; //优化选择的种群 :20个部件*2 (单个基因组/************************* 所占的位置)* 20(选择20个基因)==所有候选基因所占位置*/
private int[][]_GenerateLoad; //部件对应机器运行事件表
private Chromosome[]selectedChromosomes=new Chromosome[2]; //存储两个交叉的基因片段
private int []selectedNO=new int [2];
public int[] getBestChromosome(){
return bestChromosome;
}
public void setBestChromosome(int[]bestChromosome) {
this.bestChromosome =bestChromosome;
}
public int getSelectNum(){
return selectNum;
}
public void setSelectNum(intselectNum) {
this.selectNum =selectNum;
}
public double getRange(){
return range;
}
public void setRange(doublerange) {
this.range = range;
}
public int getG(){
return iteration;
}
public void setG(intiteration) {
this.iteration =iteration;
}
public double getP_c(){
return p_c;
}
public void setP_c(doublep_c) {
this.p_c = p_c;
}
public double getP_m(){
return p_m;
}
public void setP_m(doublep_m) {
this.p_m = p_m;
}
/*************************************************************************************/
public Genetic(){ //初始化遗传过程参数
this.iteration=5; //运行5代
this.p_c=0.9; //交叉率0.9
this.p_m=0.1; //变异率0.1
this.range=5; //设定各台机器之间总的运行时间评判参数
this.selectNum=20; //设定每次选择20个基因
int flag=0;
project[0]=newChromosome();
this._GenerateLoad=newint[project[0].get_ConponentNumber()][project[0].get_MachineNumber()]; //生成部件相应机器上加工的时间记录表
GenerateLoadFunc(project[0].get_ConponentNumber(),project[0].get_MachineNumber());
project[0].randomGeneration();
project[0].caculateFitness1(_GenerateLoad);
bestChromosome[0]=0;
bestChromosome[1]=500;
for(inti=1;i<8000;i++){ //8000个初始基因片段
project[i]=newChromosome();
project[i].randomGeneration();
project[i].caculateFitness1(_GenerateLoad);
inttempMaxDistence=project[i].caculateFitness2();
if((project[i].get_fitMaxMin()<range)&&flag<20){
copyComponent(flag,i,tempGenetics,project);
bestChromosome[flag*2]=i; //记录这20个基因片段里的信息
bestChromosome[flag*2+1]=tempMaxDistence;
flag++;
}
}
// for(int m=0;m<20;m++){
//测试输出选择的20个基因片段
// System.out.println(bestChromosome[m*2]+”************”);
// System.out.println(project[bestChromosome[m*2]].get_fitMaxMin());
// }
// arrangeSelected(bestChromosome);
if(flag<20){
System.out.println(“生成的初始基因片段有缺陷,各机器之间的负荷差别过大,请重新生成”);
System.out.println(“符合条件的基因片段数:”);
System.out.println(flag);
System.exit(0);
}
System.out.println(“随机生成的加工时间记录表:”);
printLoadTimeTable(_GenerateLoad); //打印时间记录表
for(inti=0;i<20;i++){
printSelectComponent(i);
}
}
/*************************************************************************************/
public void solve(){
for(inti=0;i<iteration;i++){ //选择、交叉、变异运行 iteration 代
selectFunc(bestChromosome);
crossFunc();
mutationFunc();
}
OutputFinal(); //输出最终选择
}
public void selectFunc(int[]bestChromosome){ //选择算子
boolean flag=true;
int tempSelNumber=0;
int i=0;
Random rm=new Random();
int []tempbestChromosome=new int[40];
//暂存选择的20个基因信息,防止更改bestChromosome数组里面的信息,采用位复制
for(intm=0;m<40;m++){
tempbestChromosome[m]=bestChromosome[m];
}
while(flag){ //随机选择两个交叉的基因
if(1/(double)tempbestChromosome[i*2+1]>rm.nextDouble()){
try{ selectedChromosomes[tempSelNumber]=(Chromosome)(project[this.bestChromosome[i*2]].clone()); //复制随机选择的基因片段
selectedNO[tempSelNumber]=this.bestChromosome[i*2];
} catch(CloneNotSupportedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
tempbestChromosome[i*2+1]=-1; //屏蔽已经选择的基因
tempSelNumber++;
if(tempSelNumber==2){
flag=false;
}
}
i++;
if(i==20){
i=0;
}
}
}
public void crossFunc(){ //交叉算子
Random rm=newRandom();
int tempNO=0;
int temp=0;
if(rm.nextDouble()<p_c){
tempNO=rm.nextInt(20);
temp=selectedChromosomes[0]._Component[tempNO*2+1];
selectedChromosomes[0]._Component[tempNO*2+1]=selectedChromosomes[1]._Component[tempNO*2+1];
selectedChromosomes[1]._Component[tempNO*2+1]=temp;
selectedChromosomes[0].caculateFitness1(_GenerateLoad);
selectedChromosomes[1].caculateFitness1(_GenerateLoad);
selectedChromosomes[0].caculateFitness2();
selectedChromosomes[1].caculateFitness2();
if(selectedChromosomes[0].get_fitMaxMin()<range){
try{
project[selectedNO[0]]=(Chromosome)selectedChromosomes[0].clone();
System.out.println(“交换了~~~”);
} catch(CloneNotSupportedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
if(selectedChromosomes[1].get_fitMaxMin()<range){
try{
project[selectedNO[1]]=(Chromosome)selectedChromosomes[1].clone();
// System.out.println(“交换了~~~”);
} catch(CloneNotSupportedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void mutationFunc(){ //变异算子
Random rm=newRandom();
for(inti=0;i<20;i++){
if(rm.nextDouble()<p_m){ //随机选择先前的20条基因中的一条进行变异操作
try{
ChromosometempChromesome=(Chromosome)project[bestChromosome[i*2]].clone();
tempChromesome._Component[rm.nextInt(20)*2+1]=rm.nextInt(4)+1; //随机选择20个部件中的一个,重新为这个部件随机生成机器号
tempChromesome.caculateFitness1(_GenerateLoad);
inttempfitness2=tempChromesome.caculateFitness2();
inttempfitness2Old=project[bestChromosome[i*2]].caculateFitness2();
if(tempChromesome.get_fitMaxMin()<range&&tempfitness2<=tempfitness2Old){
System.out.println(“变异进化成功了~~~”);
System.out.println(tempChromesome.get_fitMaxMin());
try{
project[bestChromosome[i*2]]=(Chromosome)tempChromesome.clone();
bestChromosome[i*2+1]=tempfitness2;
}catch (CloneNotSupportedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch(CloneNotSupportedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void OutputFinal(){
intbestNO=bestChromosome[0];
intbestTime=bestChromosome[1];
for(inti=1;i<20;i++){
//从20个基因片段中选择最长运行时间最短的基因组
if(bestTime>bestChromosome[i*2+1]){
bestNO=bestChromosome[i*2];
bestTime=bestChromosome[i*2+1];
}
}
System.out.println(“在暂存序列中的序号是:”+bestNO);
project[bestNO].caculateFitness2();
System.out.println(“20个部件最终选择的机器号为:”);
project[bestNO].printComponentInfo();
System.out.println(“每个机器的运行时间为:”);
project[bestNO].printMachineInfo();
System.out.println(“4个机器运行时间的最大差值为:”);
System.out.println(project[bestNO].get_fitMaxMin());
System.out.println(“4个机器的最长运行时间为:”);
System.out.println(project[bestNO].caculateFitness2());
}
/************************************************************************************/
public static voidmain(String args[]){
Genetic ga=newGenetic();
ga.solve();
}
/*********************************************************************************/
public void copyComponent(intn1,int i,int [][] tempGenetics,Chromosome [] projeChromosomes){
int [] tempComponent=newint[40];
tempComponent=projeChromosomes[i].get_Component();
for(intj=0;j<40;j++){ //可以把40设置为变量,每一个基因片段所占的位置
tempGenetics[n1][j]=tempComponent[j];
}
}
public void copyChromosome(inttempSelNumber,int SeledNumber,Chromosome []selectedChromosomes,Chromosome [] project){
}
public void printSelectComponent(intj){
int tempNo=j+1;
System.out.println(“选择的基因片段”+tempNo);
System.out.println(“[部件编号]:[机器编号]—“);
for(inti=0;i<40;i++){
System.out.print(tempGenetics[j][i]+”:”);
i++;
System.out.print(tempGenetics[j][i]+”—“);
}
System.out.print(“\n”);
}
public void GenerateLoadFunc(int_ComponentNumber,int _MachineNumber){
Random rm=newRandom();
for(inti=0;i<_ComponentNumber;i++){
for(intj=0;j<_MachineNumber;j++){
_GenerateLoad[i][j]=rm.nextInt(8)+2;
}
}
}
public void printLoadTimeTable(int[][]_GenerateLoad){ //输出时间记录表
for(inti=0;i<20;i++){
for(intj=0;j<4;j++){
System.out.print(_GenerateLoad[i][j]+”—-“);
}
System.out.print(“\n”);
}
}
public void printSelectTable(int[]bestChromosome){
for(inti=0;i<20;i++){
System.out.print(bestChromosome[i]+”—-“);
if((i+1)%4==0){
System.out.print(“\n”);
}
}
}
}