程序是对工序进行排列,使工人总的工资成本最低。
C编的,VS08报错说某些位置读取发生冲突。
麻烦大家帮忙改改吧~很急,谢谢~~
源程序如下:
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<conio.h>
#defineN 5
#defineM 2 //5个工序,2个工人
#definePOPSIZE 500
intc[M]={2,5}; //工人每小时工作成本
intT[M]={3,2}; //每个工人参与工序的总次数
intJ[M][N]; //记录工人在某个工序参加与否
inta[M][N]={{1,2,3},{3,4,5}}; //每个工人参加的工序集
int popsize ; //种群大小
int maxgeneration; //最大世代数
double pcross = 0.0; //交叉率
double pmutation = 0.0; //变异率
double sumfitness; //种群个体适应值累计
struct individual //定义染色体个体结构体
{
int chrom[N]; //定义染色体二进制表达形式
doublefitness; //染色体的适应值
};
intgeneration; //当前执行的世代数
intbest_index; //本世代最好的染色体索引序号
structindividual bestindividual; //最佳染色体个体
structindividual currentbest; //当前最好的染色体个体currentbest
intbestgeneration; //当前最好染色体个体产生的代数
structindividual oldpop[POPSIZE];//种群数组
structindividual newpop[POPSIZE];//新种群数组
/* 随机数发生器使用的静态变量*/
static double oldrand[55];
static int jrand;
static double rndx2;
static int rndcalcflag;
//函数声明
voidprintline(FILE *);
voidinitialoldpop(FILE *ffp); //初始化当代种群
voidgeneratenextpop(FILE *ffp); //产生下一代种群
voidevaluateoldpop(); //评价种群
voidcalculateobjectfitness(); //计算种群适应度
voidfindbestindividual(); //寻找最好的染色体个体
intselect(); //选择操作
//将p中移除掉q中位置在j1,j2之间的元素,其余元素前移,返回剩下元素的数量
intsearchanddelete(int *p,int*q,int j1,intj2);
voidcrossover(int *,int*,int *,int*,FILE *ffp); //交叉操作
voidmutation(int *); //变异操作
voidinput(); //输入接口
voidoutputtextreport(FILE *ffp); //每代输出文字报告
voidreport(FILE *ffp); //输出最终结果报告
//以下为一些随机数相关函数
voidadvance_random();
intflip(double);intrnd(int, int);
voidrandomize();
doublerandomnormaldeviate();
floatrandomperc();float rndreal(float,float);
voidwarmup_random(float);
voidmain() //主函数 (函数主体开始)
{
int i;
FILE*fp; //指针文件
//打开文本文件
if((fp= fopen(“Result.txt”,“w+”))==NULL)
{
printf(“Can not open file!\n”);
}
fprintf(fp,“本程序为使用基本SGA求解Talent Scheduling问题\n”);
generation=0; //初始化generation当前执行的代
input(); //初始化种群大小、交叉率、变异率
randomize(); // 初始化随机数发生器
initialoldpop(fp); //产生初始化种群
evaluateoldpop();
while(generation<maxgeneration) //小于最大世代数,执行循环体
{
generation++;
generatenextpop(fp); //生成子代种群(A.选择; B.交叉;C.变异)
for(i = 0 ; i < popsize ; i++)
{
oldpop[i]=newpop[i];
}
evaluateoldpop(); //评价新生子代种群
outputtextreport(fp); //输出当前子代种群统计报告
}
report(fp); //输出最终报告
fclose(fp); //关闭fp指向的文件句柄,防止句柄泄露
printf(“计算结果已输出到Result.txt文件中。”);
system(“pause”);
}
voidprintline(FILE *ffp)
{
fprintf(ffp,“\n*************************************************************\n”);
}
voidinitialoldpop(FILE *ffp) //种群初始化,对种群中每条染色体,生成-5的不重复序列
{
int i,p,q,r;
srand( (unsigned)time( NULL ) );
for (i=0;i<popsize; i++)
{
int a[N]={0,1,2,3,4};
p=N;
q=0;
while(p> 0) //对oldpop[i]染色体生成随机序列
{
r=rand();
r%=p;
oldpop[i].chrom[q]=a[r];
a[r]=a[p-1]; // 把后一个移到刚生成的位置
q++;
p–;
}
}
}
voidgeneratenextpop(FILE *ffp) //生成下一代
{
int mate1,mate2,j=0;
do{
//挑选交叉配对
mate1=select();
mate2=select();
crossover(oldpop[mate1].chrom,oldpop[mate2].chrom,newpop[j].chrom,newpop[j+1].chrom,ffp);
mutation(newpop[j].chrom);
mutation(newpop[j+1].chrom);
j=j+2;
}
while(j<(popsize-1));
}
voidevaluateoldpop() //评价种群
{
calculateobjectfitness(); //计算种群个体的适应度
findbestindividual(); //找到最好和最差的染色体个体
}
voidcalculateobjectfitness() //计算染色体个体适应值
{
int i,j,k,l,s,r,x;
int p=0;
int temp;
int u[N]={1,2,1,2,1};
int X[M]={0,0};
for(i=0;i<popsize;i++)
{
oldpop[i].fitness=0.0;
for(s=0;s<N;s++)
{
r=oldpop[i].chrom[s];
temp=u[r];
u[r]=u[s];
u[s]=temp;
}
for(j=0;j<M;j++)
{
for(k=0;k<N;k++)
for(l=0;l<N;l++)
{
if(a[j][k]==oldpop[i].chrom[l])
J[j][l]=1;
else
J[j][l]=0; //记录各个工人在随机工序序列中的参与位置
}
while(J[j][p]!=1)
{
p++;
}
x=1;
X[j]=u[p];
while(x<T[j])
{
p++;
X[j]=X[j]+u[p];
if(J[j][p]==1)
x++;
}
}
for(j=0;j<M;j++)
oldpop[i].fitness=oldpop[i].fitness+X[j]*c[j];
}
}
voidfindbestindividual( ) //求最佳个体
{
int i;
sumfitness=0.0;
bestindividual=oldpop[0];
best_index=0;
sumfitness+=oldpop[0].fitness;
currentbest.fitness=oldpop[0].fitness;
for(generation=0;generation<maxgeneration;generation++)
for(i=1;i<popsize; i++)
{
if (oldpop[i].fitness<bestindividual.fitness) //依次比较,找出最佳个体
{ bestindividual=oldpop[i]; //(选适应值最小的)
best_index=i;
}
sumfitness+=oldpop[i].fitness; // 存放种群总体适应值
}
if(bestindividual.fitness<currentbest.fitness)//第n代最好的,通过比较小于以往最好个体的话,暂时存放在currentbest
{
currentbest=bestindividual;
bestgeneration=generation;
}
}
//将p[]中移除掉q[]中位置在j1,j2之间的元素,其余元素前移,返回剩下元素的数量
intsearchanddelete(int *p,int*q,int j1,intj2)
{
int num=N;
int i,j;
for(j=j1;j<j2;j++)
for(i=0;i<num;i++)
{ if(q[j]==p[i])
{ while((i+1)<num)
{
p[i]=p[i+1];
i++;
}
num–;//删除一个元素,计数器减一
}
}
num=N-(j2-j1);//计算剩下元素的数目
return num;
}
intselect() //轮盘赌选择
{
float randomperc();
double sum,pick;
int i;
pick=randomperc();//产生[0,]上随机数
sum=0.0;
if(sumfitness!=0)
{
for(i=0;(sum<pick)&&(i<popsize);i++)
sum+=sumfitness-oldpop[i].fitness/sumfitness;
}
else
i=rnd(1,popsize);
return(i-1);
}
voidcrossover(int *parent1,int*parent2,int *child1,int*child2,FILE *ffp) //ox交叉算法
{
int i,j;
int jcross1,jcross2;//交叉位置
int temp;
int num1,num2;
int temp1[N],temp2[N];//分别作为暂存parent1,parent2的数组
for(i=0;i<N;i++)
{
temp1[i]=parent1[i];
temp2[i]=parent2[i];
}
if(flip(pcross))
{
//在和N-1之间随机产生两个交叉位置值
jcross1=-1;
jcross2=-1;
while(jcross1==jcross2)
{
jcross1=rand()%(N-1)+1;
jcross2=rand()%(N-1)+1;
}
if(jcross1>jcross2)
{
temp=jcross1;
jcross1=jcross2;
jcross2=temp;
}
//将切割点之间的元素复制到后代的切割点之间
j=jcross1;
while(j<jcross2)
{
child1[j]=temp1[j];
child2[j]=temp2[j];
j++;
}
//将parent2中,除掉child1中位置在jcross1,jcross2之间的元素,其余元素前移,返回剩下元素的数量
num1=searchanddelete(temp2,child1,jcross1,jcross2);
//将parent1中,除掉child2中位置在jcross1,jcross2之间的元素,其余元素前移,返回剩下元素的数量
num2=searchanddelete(temp1,child2,jcross1,jcross2);
//将去掉多余元素的parent2中值复制到child1中,避开jcross1,jcross2之间的元素
j=0;i=0;
while(j<jcross1)
{
child1[j]=temp2[i];
i++;
j++;
}
j=jcross2;//数组下标避开jcross1,jcross2之间的元素
while(i<num1)
{
child1[j]=temp2[i];
i++;
j++;
}
//将去掉多余元素的parent1中值复制到child2中,避开jcross1,jcross2之间的元素
j=0;i=0;
while(j<jcross1)
{
child2[j]=temp1[i];
i++;
j++;
}
j=jcross2;//数组下标避开jcross1,jcross2之间的元素
while(i<num2)
{
child2[j]=temp1[i];
i++;
j++;
}
}//if
else
{
for(i=0;i<N;i++)
{
child1[i]=temp1[i];
child2[i]=temp2[i];
}
}
}
voidmutation(int *child) //变异是在染色体上随机地选择两点,交换其编码
{
int i;
int j1,j2,temp;
for(i=0;i<N;i++)
{
if (flip(pmutation))
{
j1=rand()%(N-1)+1;
j2=rand()%(N-1)+1;
temp=child[j1];
child[j1]=child[j2];
child[j2]=temp;
}
}
}
void input() //数据输入
{
printf(“初始化全局变量:\n”);
printf(” 种群大小(50-500偶数):”);
scanf(“%d”,&popsize); //输入种群大小,必须为偶数
if((popsize%2)!= 0)
{
printf( ” 种群大小设置为偶数\n”);
popsize++;
}
printf(” 最大世代数(100-300):”); //输入最大世代数
scanf(“%d”,&maxgeneration);
printf(” 交叉率(0.2-0.99):”); //输入交叉率
scanf(“%lf”,&pcross);
printf(” 变异率(0.001-0.1):”); //输入变异率
scanf(“%lf”,&pmutation);
}
void outputtextreport(FILE *ffp)//数据输出
{
int i;
printline(ffp);
fprintf(ffp,“\n\t当前世代=%d\n”,generation);
fprintf(ffp,“本世代最好的染色体为:\n”);
for(i=0;i<N;i++)
fprintf(ffp,” %d”,bestindividual.chrom[i]);
fprintf(ffp,“\n总长度(相对长度)为%6.1f”,currentbest.fitness);
}
void report(FILE *ffp)
{
int i;
fprintf(ffp,“\n”);
fprintf(ffp,” 统计结果: “);
fprintf(ffp,“\n”);
fprintf(ffp,“\n种群数:%d”,popsize);
fprintf(ffp,“\n最大世代数:%d”,maxgeneration);
fprintf(ffp,“\n交叉率:%5.1f”,pcross);
fprintf(ffp,“\n变异率:%5.1f”,pmutation);
fprintf(ffp,“\n最终求得tsp问题的最短路径解”);
fprintf(ffp,“产生于%d代”,bestgeneration);
fprintf(ffp,“\n其染色体编码为:“);
for( i = 0 ; i < N ; i++ )
fprintf(ffp,” %d-“,currentbest.chrom[i]);
fprintf(ffp,“\n总长度(相对长度)为%6.1f”,currentbest.fitness);
fprintf(ffp,“\n”);
}
voidadvance_random() // 产生个随机数
{
int j1;
double new_random;
for(j1 = 0; j1 < 24; j1++)
{
new_random = oldrand[j1] – oldrand[j1+31];
if(new_random < 0.0) new_random =new_random + 1.0;
oldrand[j1] = new_random;
}
for(j1 = 24; j1 < 55; j1++)
{
new_random = oldrand [j1] – oldrand [j1-24];
if(new_random < 0.0) new_random =new_random + 1.0;
oldrand[j1] = new_random;
}
}
intflip(double prob) //以一定概率产生或
{
if(randomperc() <= prob)
return(1);
else
return(0);
}
voidrandomize() /* 设定随机数种子并初始化随机数发生器*/
{
float randomseed;
int j1;
for(j1=0; j1<=54; j1++)
oldrand[j1] = 0.0;
jrand=0;
do
{
printf(“请输入随机数种子[0-1]:\n”);
scanf(“%f”,&randomseed);
}
while((randomseed < 0.0) ||(randomseed > 1.0));
warmup_random(randomseed);
}
doublerandomnormaldeviate() // 产生随机标准差
{
double t, rndx1;
if(rndcalcflag)
{ rndx1 = sqrt(- 2.0*log((double) randomperc()));
t = 6.2831853072 * (double)randomperc();
rndx2 = rndx1 * sin(t);
rndcalcflag = 0;
return(rndx1 * cos(t));
}
else
{
rndcalcflag = 1;
return(rndx2);
}
}
floatrandomperc() //与库函数random()作用相同,产生[0,1]之间一个随机数
{
jrand++;
if(jrand >= 55)
{
jrand = 1;
advance_random();
}
return((float)oldrand[jrand]);
}
intrnd(int low,inthigh) //在整数low和high之间产生一个随机整数
{
int i;
if(low >= high)
i = low;
else
{
i = ((int)randomperc() * (high – low +1)) + low;
if(i > high) i = high;
}
return(i);
}
voidwarmup_random(float random_seed) //初始化随机数发生器
{
int j1, ii;
double new_random, prev_random;
oldrand[54] = random_seed;
new_random = 0.000000001;
prev_random = random_seed;
for(j1 = 1 ; j1 <= 54; j1++)
{
ii = (21*j1)%54;
oldrand[ii] = new_random;
new_random = prev_random-new_random;
if(new_random<0.0) new_random =new_random + 1.0;
prev_random = oldrand[ii];
}
advance_random();
advance_random();
advance_random();
jrand = 0;
}