资源

工作轮班安排:寻找最佳分配(clp3)

/*********************************************************************//*                                                                   *//*S A S S A M P L E L I B R A R Y*//**//*名称:clp3*//*标题:工作轮班安排:寻找最佳分配(clp3)*//*产品:或*//*系统:全部*//*关键字:或*//*程序:CLP,GANTT*//*数据:*//*                                                                   *//*支持:更新:*//*参考:*//*MISC:CLP程序章节中的示例3*//*约束编程书*//*                                                                   *//*********************************************************************/proc-clp-out=clpout;/*六名工人(艾伦、鲍勃、约翰、迈克、斯科特和特德)分配给3个工作班次*/var(W1-W6)=[1,3];/*第一班至少需要1人,最多需要4人;第二班至少需要2人,最多需要3人;第三班正好需要两个人*/gcc(W1-W6)=((1,1,4)(2,2,3)(3,2,2));/*艾伦第一班不工作*/林肯W1<>1;/*鲍勃只上三班*/林肯W2=3;运行;/*打印解决方案*/程序打印;标题“轮班调度问题的解决方案”;运行;/*生成甘特图*/proc转置数据=clpout out=tmp1;运行;数据tmp2(drop=_NAME_);格式名称$8。;设置tmp1;reName col1=e_start;e_finish=col1+1;持续时间=1;如果名称='W1',则名称='Alan';否则,如果_Name_='W2',则Name='Bob';否则,如果名称='W3',则名称='John';否则,如果名称='W4',则名称='Mike';否则,如果名称='W5',则名称='Scott';否则,如果_Name_='W6',则Name='Ted';否则删除;运行;proc格式;价值转移1=“换档1”2=“换档2”3=“移位3”4 = ' ';运行;goptions htext=1.5;模式1 c=ltgray;title j=c h=6pct“示例3:可行的工作轮班分配”;过程甘特数据=tmp2;格式e_start shift。;图表/pcompress(压缩)跳过=2dur=持续时间刻度=16图表宽度=84ref=2 3 lref=20使用格式诺列根;id名称;运行;%宏调用clp(obj);%put目标值为:&obj。。;proc-clp-out=clpout;/*六名工人(艾伦、鲍勃、约翰、迈克、斯科特和特德)将被分配到3个工作班次*/var(W1-W6)=[1,3];var(C1-C6)=[1100];/*第一班至少需要1人,最多需要4人;第二班至少需要2人,最多需要3人;第三班正好需要两个人*/gcc(W1-W6)=((1,1,4)(2,2,3)(3,2,2));/*艾伦第一班不工作*/林肯W1<>1;/*鲍勃只上第三班*/林肯W2=3;/*指定指派工人轮班的成本。使用100(一个大数字)表示分配这是不可能的*/元件(W1,(100,12,10),C1);元件(W2,(100,100,6),C2);元件(W3,(16,8,12),C3);元素(W4,(10,6,8),C4);元件(W5,(6,6,8),C5);元件(W6,(12,4,4),C6);/*总成本不得超过给定的目标值*/林肯C1+C2+C3+C4+C5+C6<=&obj;运行;/*找到解决方案后*//*&_ORCLP_包含字符串SOLUTIONS_FOUND=1*/%如果%index(&_ORCLP_,SOLUTIONS_FOUND=1)%,则%let clpreturn=SUCCESSFUL;%修补;/*确定最优目标值的二分搜索法*/%宏观最低成本(lb,ub);%do%while(&lb<&ub-1);%put当前lb=&lb,ub=&ub。。;%设newobj=%eval((&lb+&ub)/2);%让clpreturn=NOTFOUND;%callclp(&newobj);%如果&clpreturn=SUCCESSFUL%,则%let ub=&newobj;%else%let lb=&newobj;%结束;%callclp(&ub);%put给定范围内的最小可能目标值为&ub。;%put任何小于&ub的值都会使问题变得不可行;程序打印;运行;%修补;/*找出1到100之间的最小目标值*/%最小成本(lb=1,ub=100);proc转置数据=clpout out=tmp1;运行;数据tmp2(drop=_NAME_);格式名称$8。;设置tmp1;reName col1=e_start;e_finish=col1+1;持续时间=1;如果名称='W1',则名称='Alan';否则,如果名称='W2',则名称='Bob';否则,如果_Name_='W3',则Name='John';否则,如果名称='W4',则名称='Mike';否则,如果名称='W5',则名称='Scott';否则,如果名称='W6',则名称='Ted';否则删除;运行;数据tmp4;设置tmp1;如果n≤6,则删除;运行;proc格式;价值转移1=“换档1”2=“换档2”3=“移位3”4 = ' '5 = ' ';运行;数据tmp5(drop=_Name_);格式e_start shift。;格式成本1$8。;设置tmp2;设置tmp4;重命名col1=成本;cost1=“$”||strip(col1);运行;数据标签;_y=-1_xvar=“e_start”_xoffset=0.25_yoffset=-.15;_clabel=“蓝色”_hlabel=1.0_lvar=“成本1”;运行;进程排序数据=tmp5输出=tmp6;通过e_start;运行;数据tmp6;保留总数0;设置tmp6;总计=总计+成本;运行;数据tmp7(keep=x y drop=max y cscale);设置tmp6 end=last;y=滞后(总计);如果(dif(e_start)),则执行;x=e_start;产出;结束;如果(最后)那么做;y=总数;x=e_start+1;产出;最大y=y+5;c刻度=6/最大值y;stry=y;调用symput('max_x',put(x+0.15,best.));调用symput('mincost',strip(put,stry,best.));调用symput('max_y',strip(put(max_y,best.));调用症状('scale',put(cscale,best.));结束;运行;%放置&max_y;%放置&cscale;%放置&mincost;%annomac;数据anno;/*定义成本曲线*/%dclanno;%系统(2,2,4);*长度实验室16美元;设置tmp7;当='a'时;如果n_=1,则执行;do i=0到&max_y乘以5;lab=投入(i,美元7.);%标签(&maxx+0.8,(&maxy-i)*/cscale,实验室,黑色,0,0,1.0,4);产出;%标签(&maxx+0.9,(&maxy-i)*/cscale,'-',黑色,0,0,1.0,4);结束;%移动(1,&max_y*&cscale);/*开始成本曲线的初始点*/结束;否则;%绘制(x,(&max_y-y)*/cscale,蓝色,2,2);结束;运行;goptions htext=1.5;pattern1c=ltgray;title1 j=c h=6pct“示例3:最佳工作轮班分配”;title2 j=c h=5pct“最低成本表:$&mincost”;proc-gantt data=tmp5-labdata=labels-annotate=anno;图表/pcompress(压缩)跳过=2图表宽度=84labsplit=“/”刻度=16mindate=1最大日期=5参考=2 3 4使用格式nolegend;id名称;运行;