/* ======================================================================EXPKNAP.c,David Pisinger 1992年3月,1994年4月修改====================================================================== *//*这是与论文相对应的C代码:**D.皮辛格*精确0-1背包问题的扩展核算法*《欧洲运筹学杂志》,87(1995),175-187**有关该项目的更多详细信息,请参阅**D.皮辛格*背包问题的算法*哥本哈根大学DIKU 95/1号报告*帕肯大学1*DK-2100哥本哈根**当前代码用于对*随机生成的实例。然而,它应该很容易推导*通过剥离多个*测试例程。**该代码已在hp9000/735上测试,符合*ANSI-C标准,除了一些定时例程(可能*)。要编译代码,请使用:**cc-Aa-O-O扩展扩展.c-lm**通过发出命令运行代码**expknap n r类型**其中n:项目数量,*r:系数范围,*类型:1=未校正。,2=弱相关,3=强相关,4=子集和*输出将附加到文件“trace.exp”中。**请不要再分发。可以通过联系获得新副本*作者地址如下。错误和问题是指:**David Pisinger,副教授*哥本哈根大学DIKU,*Parken 1大学,*DK-2100哥本哈根。*电子邮件:pisinger@diku.dk*传真:+45 35 32 14 01*//* ======================================================================定义====================================================================== */#定义TESTS 50/*要生成的测试实例数*/#包括#包括#包括#包括#包括#包括#包括#包括/* ============================================================================================================================================ */#定义srand(x)srand48(x)#定义随机(x)(lrand48()%(x))#定义DET(a1,a2,b1,b2)((a1)*(长)(b2)-(a2)*(短)(b1))#定义SWAP(a,b){注册项t;t=*a;*a=*b;*b=t;}#定义NO(f,i)((int)((i+1)-f))#定义TRUE 1#定义FALSE 0#定义SORTSTACK 200/* ======================================================================类型声明====================================================================== */typedef int布尔值;/*布尔变量*/typedef短itype;/*项目利润和权重*/typedef长型;/*重量总和*//*外观上的项目*/typedef结构{t类型p;/*利润*/itype w;/*重量*/布尔值x;/*解决方案变量*/}退出;/*内部看到的项目*/typedef结构{t类型p;/*利润*/类型w;/*重量*/布尔值*x;/*指向原始解决方案变量的指针*/}项目;/*区间叠加*/typedef结构istk{项目*f;项目*1;类型ws;}伊斯托克;/* ======================================================================全局变量====================================================================== */项目*br;/*中断项目*/类型wsb;/*损益合计至分项*/类型psb;类型c;/*总容量*/类型z;/*下限*/项目*fsort;项目*lsort;伊斯托克;/*partsort返回的排序间隔*/伊斯塔克*ihead1,*stack1,*iend1;/*间隔堆栈,i<br*/istack*i头2,*stack2,*iend2;/*区间堆栈,i>br*/布尔值**ehead,**estack;/*异常堆栈*//* ======================================================================测试变量====================================================================== */文件*跟踪;长迭代;长河;长丹齐格;长时间接触;长redu;长类;/* ======================================================================hp9000/735的定时例程====================================================================== */#定义_INCLUDE_POSIX_SOURCE#包括#包括struct tms timestart,timeend;无效开始时间(void){次数(×开始);}无效结束时间(长*时间){双t1,t2;时间(&timeend);t1=(双精度)(timeend.tms_utime-timestart.tms_utime)/sysconf(_SC_CLK_TCK);t2=(双精度)(timeend.tms_stime-timestart.tms_stime)/sysconf(_SC_CLK_TCK);*时间=t1*1000;}/* ======================================================================汇总数据====================================================================== */void sumdata(int n1,int r1,int type1,long迭代,long heur,long z,长c,长dantzig,长touch,长redu,长sorts,长时间){静态long n;静态长r;静态长t;静态长迭代=0;静态长时间接触=0;静态长simpred=0;静态长岩心尺寸=0;静态长希腊间隙=0;静态长间隙=0;静态长时间总计=0;静态长zsum=0;静态长csum=0;静态双平方时间=0.0;双均值、方差、标准偏差;如果(n1==0){平均值=总时间/(1000*(两次)试验);方差=sqtime/TESTS-平均值*平均值;标准偏差=sqrt(方差);fprintf(跟踪,“n=%ld\n”,n);fprintf(跟踪,“r=%ld\n”,r);fprintf(跟踪,“t=%ld\n”,t);fprintf(trace,“iterations=%.0lf\n”,iterates/(double)TESTS);fprintf(trace,“touch=%.1lf\n”,touch/(double)TESTS);fprintf(trace,“touchedpct=%.1lf\n”,100*touch/((double)n*TESTS));fprintf(trace,“simpreduced=%.1lf\n”,simpred/(double)TESTS);fprintf(trace,“coresize=%.0lf\n”,coresize/(double)TESTS);fprintf(trace,“corepct=%.2lf\n”,100*coresize/((double)n*TESTS));fprintf(trace,“greedygap=%.1lf\n”,greedygap/(double)TESTS);fprintf(trace,“gap=%.1lf\n”,gap/(double)TESTS);fprintf(跟踪,“zsum=%.0lf\n”,zsum/(双精度)1);fprintf(trace,“csum=%.0lf\n”,csum/(double)1);fprintf(trace,“time=%.2lf\n”,mean/(double)1);fprintf(trace,“variance=%.2lf\n”,variance/(double)1);fprintf(trace,“stddev=%.2lf\n”,stddev/(double)1);}其他{n=n1;r=r1;t=类型1;iterates+=迭代;/*分支定界迭代*/触摸+=触摸;/*减少所涉及的变量*/simpred+=redu;/*变量缩减*/coresize+=排序;/*分选岩心尺寸*/希腊间隙+=z-heur;/*贪婪界限的差距*/间隙+=dantziz-z;/*LP和IP优化之间的差距*/tottime+=时间;/*总计算时间*/zsum=((zsum+z)%1000);/*控制所有解的和*/csum=((csum+c)%1000);/*控制所有容量的总和*/sqtime+=(时间/(双倍)1000)*(时间/;}}/* ======================================================================错误====================================================================== */void错误(char*str,…){va_list参数;va_start(参数,字符串);vprintf(字符串,参数);printf(“\n”);vfprintf(跟踪、字符串、参数);fprintf(跟踪,“\n”);va_end(参数);printf(“停止!!!\n\n”);fprintf(trace,“停止!!!\n\n”);fclose(跟踪);出口(-1);}/* ======================================================================帕洛克语====================================================================== */void pfree(无效*p){如果(p==NULL)错误(“释放NULL”);自由(p);}void*palloc(size_tno,size_teach){长尺寸;长*p;尺寸=无*(长)每个;如果(大小==0)大小=1;if(size!=(size_t)size)错误(“alloc too big%ld”,size);p=malloc(大小);if(p==NULL)错误(“无内存大小%ld”,大小);返回p;}/*======================================================================展品=================================================================*/作废展品(项目*f,项目*1){项目*i;光笔ps,ws;printf(“showitems”);ps=0;ws=0;对于(i=f;i<=l;i++){打印f(“%d:(%2hd,%2hd)%8lf%1hd\n”,(整数)((i+1)-f),i->p,i->w,i->p/(双)i->w、*(i->x));如果(i->x){ps+=i->p;ws+=i->w;}}printf(“showitems(%ld,%ld)”,ps,ws);}/* ======================================================================制造测试====================================================================== */stype maketest(exitem*f,exitem*1,int类型,int r,int v){寄存器exitem*j;寄存器类型和;类型c;r1型;总和=0;r1=r/10;对于(j=f;j<=l;j++){j->w=随机(r)+1;开关(类型){情况1:j->p=随机(r)+1;断裂;情况2:j->p=随机(2*r1+1)+j->w-r1;如果(j->p≤0)j->p=1;断裂;情况3:j->p=j->w+10;断裂;情况4:j->p=j->w;断裂;}总和+=j->w;}c=总和/2;返回c;}/* ======================================================================试验=================================================================*/无效测试(出口**f,出口**l,进口n,int r,int类型,int v){出口*a;/*为测试示例分配空间*/a=(exitem*)palloc(n,sizeof(exitem));*f=a*l=&a[n-1];/*生成测试实例*/c=制造测试(*f,*l,type,r,v);}/* ======================================================================自由实例====================================================================== */void freeinstance(退出*f){pfree(f);}/* ======================================================================定义解决方案====================================================================== */无效定义解决方案{寄存器布尔值**j;对于(j=ehead;j<estack;j++)**j=1-**j;}/* ======================================================================checksol公司====================================================================== */长checksol(exitem*f,exitem*1,long c,long z){寄存器exitem*i;寄存器类型集水坑,sumw;集水坑=0;总和=0;对于(i=f;i<=l;i++){如果(i->x){集水坑+=i->p;集水坑+=i->w;}}/*printf(“槽%ld,z%ld,sumw%ld,c%ld\n”,槽,z,sumw,c)*/if((sumw>c)|(sump!=z))错误(“错误的解决方案”);回油池;}/* ======================================================================推动====================================================================== */无效清除(){estack=ehead;}无效推送(项目*i){*estack=i->x;estack++;}/* ======================================================================普西语====================================================================== */void pushi(伊斯托克**stack,item*f,item*1,stype ws){寄存器istack*pos;pos=*堆栈;位置->f=f;位置->l=l;pos->ws=ws;(*堆栈)++;if((pos==iend1)|(pos==iend2))错误(“istack full”);}/* =========================================================================减少========================================================================= */减少空隙(项目**f,项目**l){注册项目*i、*j、*k;注册类型pb,wb;寄存器类型q;pb=br->p;wb=br->w;q=DET(z+1,c-wsb,pb,wb);i=*f;j=*l;如果(i<=br){k=fsort-1;而(i<=j){触摸++;如果(DET(-j->p,-j->w,pb,wb)<q){红色++;SWAP(i,j);i++;/*不可行*/}其他{SWAP(j,k);j——;k--;/*可行的*/}}如果(k==fsort-1){SWAP(*f,k);k-;}/*返回至少一个*/*l=fsort-1*f=k+1;}其他{k=lsort+1;而(i<=j){触摸++;如果(DET(i->p,i->w,pb,wb)<q){红色++;SWAP(i,j);j--;/*不可行*/}其他{SWAP(i,k);i++;k++;/*可行的*/}}if(k==lsort+1){SWAP(*1,k);k++;}/*至少返回一个*/*f=lsort+1*l=k-1;}}/* ======================================================================部分排序====================================================================== */无效部件排序(项目*f、项目*1、类型ws){注册类型mp,mw;注册项目*i、*j、*m;注册类型wi;整数d;d=l-f+1;如果(d>1){m=f+d/2;如果(DET(f->p,f->w,m->p,m->w)<0)SWAP(f,m);如果(d>2){如果(DET(m->p,m->w,l->p,l->w)<0){SWAP(m,l);如果(DET(f->p,f->w,m->p,m->w)<0)SWAP(f,m);}}}如果(d<=3){s.f=f;s.l=升;s.ws=ws;}其他{mp=m->p;mw=m->w;i=f;j=l;wi=ws;用于(;;){执行{wi+=i->w;i++;},同时(DET(i->p,i->w,mp,mw)>0);在(DET(j->p,j->w,mp,mw)<0)时执行{j--;};如果(i>j)断裂;SWAP(i,j);}如果(wi>c){pushi(&stack2,i,l,wi);部件排序(f,i-1,ws);}其他{pushi(&stack1,f,i-1,ws);部分排序(i,l,wi);}}}/* ======================================================================排序====================================================================== */布尔排序(istack**堆栈)/*如果扩展成功,则返回TRUE;如果没有更多间隔,则返回FALSE*/{寄存器istack*pos;if((*stack==ihead1)||(*stack==ihed2))返回FALSE;(*堆栈)--;pos=*堆栈;减少(&(pos->f),&(pos->l));部件排序(位置->f、位置->l、位置->ws);如果(s.f<fsort)fsort=s.f;如果(s.l>lsort)lsort=s.l;返回TRUE;}/* ======================================================================电子分支====================================================================== */短电子分支(itype ps,itype ws,item*s,item*t){短期改善;迭代++;改进=错误;如果(ws<=0){如果(ps>z){改进=真;z=ps;cleare();}用于(;;){if(t>lsort){if(!sorti(&stack2))break;}如果(DET(ps-(z+1),ws,t->p,t->w)<0)中断;if(电子分支(ps+t->p,ws+t->w,s,t+1)){改进=真;推力(t);}t++;}}其他{用于(;;){if(s<fsort){if(!sorti(&stack1))break;}如果(DET(ps-(z+1),ws,s->p,s->w)<0)中断;if(电子分支(ps-s->p,ws-s->w,s-1,t)){改进=真;推动;}s--;}}收益提高;}/* ======================================================================启发式的====================================================================== */类型启发式(项目*f,项目*1){登记项目*i;寄存器类型ps,ws;注册类型r、z、pb、dz;ps=0;ws=c;对于(i=f;i->w<=ws;i++){ws-=i->w;ps+=i->p;*(i->x)=1;}br=i;wsb=c-ws;psb=磅;/*确定dantzig界,并将其用作z的上界*/dz=(c-wsb)*br->p/br->w;dantzig=psb+dz;/*定义初始解决方案*/cleare();z=0;如果(z==dz)返回z;/*正向贪婪解*/r=c-wsb;对于(i=br;i<=l;i++){如果((i->w<=r)&&(i->p>z)){清除();推动(i);z=i->p;如果(z==dz),则返回z;}}/*反向贪婪解*/r=(wsb+br->w)-c;pb=br->p;对于(i=br-1;i>=f;i--){如果((i->w>=r)&&(pb-i->p>z)){清除();推(br);推动(i);z=pb-i->p;如果(z==dz),则返回z;}}返回z;}/* ======================================================================解释====================================================================== */stype expknap(exitem*f,exitem*1,stype cap){登记项目*j;寄存器exitem*i;项目*fitem,*litem;整数n;n=l-f+1;c=盖子;ihead1=(istack*)palloc(SORTSTACK,sizeof(istack));ihead2=(istack*)palloc(SORTSTACK,sizeof(istack));ehead=(boolean**)palloc(n,sizeof(boolean*));fitem=(item*)palloc(n,sizeof(item));litem=fitem+n-1;堆栈1=ihead1;iend1=ihead1+SORTSTACK;堆叠2=头部2;iend2=ihead2+SORTSTACK;/*将项复制到自己的数组*/对于(i=f,j=fitem;i=l;i++,j++){j->p=i->p;j->w=i->w;j->x=&(i->x);i->x=0;}/*查找中断项*/部分排序(fitem,litem,0);fsort=s.f;lsort=s.l;/*解决问题*/z=启发式(fitem,litem);heur=z+psb;电子分支(0,wsb-c,br-1,br);/*定义解决方案*/定义解决方案();pfree(i开头1);pfree(头2);pfree(ehead);pfree(fitem);排序=lsort-fsort+1;返回z+psb;}/* ======================================================================主要的====================================================================== */void main(int argc,char*argv[]){退出项*f,*l;类型z;长时间;int n,r,类型,v;如果(argc==4){n=原子序数(argv[1]);r=原子序数(argv[2]);类型=atoi(argv[3]);printf(“Expknap%d,%d,%d\n”,n,r,type);}其他{printf(“Expknap”);打印f(“n=”);scanf(“%d”,-n);printf(“r=”);扫描(“%d”,&r);printf(“t=”);扫描(“%d”,&type);}trace=fopen(“trace.exp”,“a”);fprintf(trace,“\nEXPKNAP:n:%d,r:%d,type:%d\n”,n,r,type);对于(v=1;v<=测试;v++){srand(v);迭代次数=0;redu=0;触摸=0;测试(&f,&l,n,r,type,v);starttime();z=解释(f,l,c);结束时间(&time);/*检查解决方案*/checksol(f,l,c,z);自由实例(f);sumdata(n,r,type,iterations,heur,z,c、 dantzig、touch、redu、sorts、time);}sumdata(0,0,0,1,0,0,0,0/0,0);fclose(跟踪);}