指派问题java实现_原创:工作指派问题解决方案---模拟退火算法C实现

1 /*****************************************************************************2 ** Copyright: NEW NEU laboratory3 ** File name: SA_工作指派问题4 ** Description:模拟退火算法解决工作指派问题5 ** Author: 1702--GCJ6 ** Version: 1.07 ** Date: 2017/10/48 ** History: 无9 *****************************************************************************/

10

11 #include"stdio.h"

12 #include"stdlib.h"

13 #include"string.h"

14 #include "time.h"

15 #include "math.h"

16

17 /*----------------------------------------------------18 @brief 参数配置区19 */

20 #define WORK_NUM 100 //工作数量

21 #define WORKER_NUM 100 //工人数量

22 #define INIT_TEM (60 + WORK_NUM * 10) //初始温度

23 #define END_TEM 60 //终止温度

24 #define De_TEM 2 //降温函数

25 #define INTER_WHILE 500 //内循环次数 类似于邻居个数

26

27 typedef intElementType;28 ElementType **Time; //存储工人工作时间 指针

29 ElementType CurrentTem; //当前温度30

31 //定义解的存储类型 向量形式

32 typedef struct_Solve{33 ElementType *initSolution; //初始解//每个元素对应的序号表示工人 总序号表示工人总数 内部元素表示工人对应的工作

34 ElementType *currentSolution; //当前解

35 ElementType * optimalSolution; //最优解

36 ElementType *tempSolution; //临时解

37 ElementType OptimalSolutionValue; //记录最优解 (总时间)

38 ElementType CurrentSolutionValue; //记录上次的值

39 ElementType NextSolutionValue ; //记录交换后的总时间

40

41 }StrSolve;//存储解结构

42

43 StrSolve * SolutionSpace ; //解空间(包含当前解和初始解)指针

44

45 typedef struct_Tabu{46 intsmallNum;47 int bigNum; //存储数量大的元素

48 }Tabu; //禁忌表结构

49

50 typedef struct_MotionTable{51 Tabu tabu; //存储改变的元素

52 ElementType changedistance; //改变的距离

53 }MotionTable;//记录2opt邻域移动信息

54

55 /*************************************************56 **Function: MemBlockWork57 **Description: 申请存储工人工作时间的空间58 **Calls: 无59 **Called By: ReadDataTxt()60 **Input: 无61 **Output: 无62 **Return: 指向存储工人工作时间的指针63 **Others: 无64 *************************************************/

65 ElementType **MemBlockWork();66

67 /*************************************************68 **Function: ReadDataTxt69 **Description: 从txt文档中读取工人工作时间数据70 **Calls: MemBlockWork()71 **Called By: main()72 **Input: 无73 **Output: 无74 **Return: void75 **Others: 里面直接用的全局变量 指针Time76 *************************************************/

77 voidReadDataTxt();78

79 /*************************************************80 **Function: CreateSolutionSpace81 **Description: 创建并初始化解空间82 **Calls: 无83 **Called By: Init2Opt()84 **Input: worker_num 工人数量85 **Output: 无86 **Return: StrSolve *指针变量87 **Others: 不用这块内存的时候要逐一释放掉 !88 *************************************************/

89 StrSolve *CreateSolutionSpace(intworker_num);90

91 /*************************************************92 **Function: GetInitSolution93 **Description: 获得初始解94 **Calls: 无95 **Called By: Init2Opt()96 **Input: StrSolve * 指针变量97 **Output: 无98 **Return: StrSolve *指针变量99 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 工人工作不能重复及数组空间的数字不能重复100 *************************************************/

101 void GetInitSolution(StrSolve *strSolve);102

103 /*************************************************104 **Function: Get2optSolution105 **Description: 得到1个2邻域解 用tempSolution来存储106 **Calls:107 **Called By: SA()108 **Input: solutionSpace 解空间指针109 **Output: 无110 **Return: void111 **Others: 随机数要注意!112 *************************************************/

113 void Get2optSolution( StrSolve *solutionSpace );114

115 /*************************************************116 **Function: Init2Opt117 **Description: 初始化SA需要用的值118 **Calls: CreateSolutionSpace() GetInitSolution()119 **Called By: main()120 **Input: 无121 **Output: 无122 **Return: void123 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 不知道为什么只能在Main函数中调用否则 会出现段错误124 *************************************************/

125 voidInit2Opt();126

127 /*************************************************128 **Function: GetSumTime129 **Description: 获取当前解的总工作时间130 **Calls:131 **Called By: SA()132 **Input: distance 存储工人工作时间的矩阵指针 Solution 解指针133 **Output: 无134 **Return: 总工作时间135 **Others: 里面用到了WORKER_NUM 宏136 *************************************************/

137 int GetSumTime( ElementType **distance,ElementType *Solution);138

139 /*************************************************140 **Function: SA141 **Description: 模拟退火算法142 **Calls: GetSumTime() Get2optSolution() memcpy() rand() exp()143 **Called By: main()144 **Input: solutionSpace 解空间指针145 **Output: 最优值信息 工人工作分配146 **Return: 无147 **Others:148 *************************************************/

149 void SA( StrSolve *solutionSpace);150

151 /*************************************************152 **Function: MemFree153 **Description: 释放申请的动态内存154 **Calls: free()155 **Called By: main()156 **Input: distance 存储工人工作时间矩阵 strSolve 解空间的指针157 **Output: 无158 **Return: void159 **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行160 *************************************************/

161 void MemFree(ElementType ** distance,StrSolve *strSolve);162

163 /*******************************************************************************MAIN函数*************************************/

164 int main(int argc,char *argv[])165 {166 clock_t start, finish;167 doubleduration;168

169 //设置随机数种子 为以后使用rand()做准备

170 srand((unsigned int)time(0));171 Init2Opt();172

173 //从读取数据开始的起始时间

174 start =clock();175

176 //将工人工作时间的数据存储到Time指向的空间中

177 ReadDataTxt(Time);178

179 //模拟退火算法开始

180 SA(SolutionSpace);181

182 //第二次用模拟退火183 //memcpy( SolutionSpace->currentSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );184 //memcpy( SolutionSpace->initSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );185 //memcpy( SolutionSpace->tempSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );186 //GetInitSolution(SolutionSpace);//初始化解187 //SA(SolutionSpace);188

189 //结束时间

190 finish =clock();191 duration = (double)(finish - start) /CLOCKS_PER_SEC;192 printf("\n SA算法运行时间:%.4f秒 \n",duration);193

194 //释放申请的内存

195 MemFree(Time,SolutionSpace);196

197 return 0;198 }199

200 /*************************************************201 **Function: MemBlockWork202 **Description: 申请存储工人工作时间的空间203 **Calls: 无204 **Called By: ReadDataTxt()205 **Input: 无206 **Output: 无207 **Return: 指向存储工人工作时间的指针208 **Others: 无209 *************************************************/

210 ElementType **MemBlockWork()211 {212 ElementType **Distance;213 int i=0;214

215 //动态申请一块内存存储工人工作时间

216 Distance = (ElementType **)malloc(sizeof(ElementType *)*WORKER_NUM);217 for(i = 0;i< WORKER_NUM; i++){218 Distance[i] = (ElementType *)malloc(sizeof (ElementType )*WORK_NUM);219 }220 returnDistance;221 }222

223 /*************************************************224 **Function: ReadDataTxt225 **Description: 从txt文档中读取工人工作时间数据226 **Calls: MemBlockWork()227 **Called By: main()228 **Input: 无229 **Output: 无230 **Return: void231 **Others: 里面直接用的全局变量 指针Time232 *************************************************/

233 voidReadDataTxt()234 {235 //FILE *fpRead=fopen("F:\\GCJ\\Desktop\\智能优化方法作业\\data.txt","r");

236 FILE *fpRead=fopen("data.txt","r"); //从data.txt中读取数据

237 inti,j;238 if(fpRead==NULL){239 printf("open file data.txt failed!\n");240 exit(1);241 }242 Time = MemBlockWork(); //申请一块存储城市数量空间

243 for( i = 0;i < WORKER_NUM; i++){244 for(j=0 ;j < WORK_NUM ;j++){245 fscanf(fpRead,"%d",&Time[i][j]);//自动读取数据 只要自己能够控制好存储位置即可246 //printf("Time[%d][%d] = %d ",i,j,Time[i][j]);

247 }248 }249 fclose(fpRead);250 }251

252 /*************************************************253 **Function: CreateSolutionSpace254 **Description: 创建并初始化解空间255 **Calls: 无256 **Called By: Init2Opt()257 **Input: worker_num 工人数量258 **Output: 无259 **Return: StrSolve *指针变量260 **Others: 不用这块内存的时候要逐一释放掉 !261 *************************************************/

262 StrSolve *CreateSolutionSpace(intworker_num)263 {264 inti;265 StrSolve *strSolve = (StrSolve *)malloc( sizeof(StrSolve) ) ;266 strSolve->initSolution = ( ElementType *)malloc(sizeof(ElementType)*worker_num );267 strSolve->currentSolution = ( ElementType *)malloc(sizeof(ElementType)*worker_num );268 strSolve->optimalSolution = ( ElementType *)malloc(sizeof(ElementType)*worker_num );269 strSolve->tempSolution = ( ElementType *)malloc(sizeof(ElementType)*worker_num );270

271 //初始化解空间

272 for(i = 0;i< worker_num;i++){273 strSolve->initSolution[i] = (ElementType)0;274 strSolve->currentSolution[i] = (ElementType)0;275 strSolve->optimalSolution[i] = (ElementType)0;276 strSolve->tempSolution[i] = (ElementType)0;277 }278 strSolve->CurrentSolutionValue = 0;279 strSolve->NextSolutionValue = 0;280 strSolve->OptimalSolutionValue = 0;281

282 returnstrSolve;283 }284

285 /*************************************************286 **Function: GetInitSolution287 **Description: 获得初始解288 **Calls: 无289 **Called By: Init2Opt()290 **Input: StrSolve * 指针变量291 **Output: 无292 **Return: StrSolve *指针变量293 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 工人工作不能重复及数组空间的数字不能重复294 *************************************************/

295 void GetInitSolution(StrSolve *strSolve)296 {297 inti;298 //产生0- WORK_NUM-1 (工作数量减1) 之间的随机数不能重复299 //默认从0号工作顺序开始

300 for( i = 0;i < WORKER_NUM;i++){301 strSolve->initSolution[i] =i;302 strSolve->currentSolution[i] =i;303 strSolve->optimalSolution[i] =i;304 strSolve->tempSolution[i] =i;305 }306

307 }308

309 /*************************************************310 **Function: Get2optSolution311 **Description: 得到1个2邻域解 用tempSolution来存储312 **Calls:313 **Called By: SA()314 **Input: solutionSpace 解空间指针315 **Output: 无316 **Return: void317 **Others: 随机数要注意!318 *************************************************/

319 void Get2optSolution( StrSolve *solutionSpace )320 {321 //产生一个 0 - - WORKER-1之间的随机数 表示交换工人对应的工作数 [0,WORKER)

322 MotionTable motiontable;323 ElementType temp;324 //ElementType changeDistance;

325 intrand1,rand2;326 //rand1 = (CityNum-1) *rand()/(RAND_MAX + 1.0);

327 rand1 = rand()%WORKER_NUM; //[0,WORKER_NUM)

328 rand2 = rand()%WORKER_NUM;329 while( rand2 == rand1 ) //必须产生两个不同的随机数

330 rand2 = rand()%WORKER_NUM;331

332 //记录交换的两个工人编号

333 motiontable.tabu.smallNum = (rand2 >rand1)?rand1:rand2;334 motiontable.tabu.bigNum = (rand2 >rand1)?rand2:rand1;335

336 //更新当前解//用临时解作为j解

337 temp = solutionSpace->tempSolution[ motiontable.tabu.smallNum ];338 solutionSpace->tempSolution[ motiontable.tabu.smallNum] = solutionSpace->tempSolution[ motiontable.tabu.bigNum ];339 solutionSpace->tempSolution[ motiontable.tabu.bigNum ] =temp;340

341 //motiontable->changedistance = Get2OptChangeDistance( &motiontable->tabu ,strSolve->tempSolution );

342

343 }344

345 /*************************************************346 **Function: Init2Opt347 **Description: 初始化SA需要用的值348 **Calls: CreateSolutionSpace() GetInitSolution()349 **Called By: main()350 **Input: 无351 **Output: 无352 **Return: void353 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 不知道为什么只能在Main函数中调用否则 会出现段错误354 *************************************************/

355 voidInit2Opt()356 {357 SolutionSpace = CreateSolutionSpace(WORKER_NUM);//创建解空间

358 GetInitSolution(SolutionSpace);//初始化解

359 }360

361 /*************************************************362 **Function: GetSumTime363 **Description: 获取当前解的总工作时间364 **Calls:365 **Called By: SA()366 **Input: distance 存储工人工作时间的矩阵指针 Solution 解指针367 **Output: 无368 **Return: 总工作时间369 **Others: 里面用到了WORKER_NUM 宏370 *************************************************/

371 int GetSumTime( ElementType **distance,ElementType *Solution)372 {373 //只要保证Solution 里面的值不一样即可算出

374 inti;375 int SumLevel = 0;376 for(i = 0; i < WORKER_NUM ; i++){377 SumLevel +=distance[ i ][ Solution[i] ];378 }379

380 returnSumLevel;381 }382

383 /*************************************************384 **Function: SA385 **Description: 模拟退火算法386 **Calls: GetSumTime() Get2optSolution() memcpy() rand() exp()387 **Called By: main()388 **Input: solutionSpace 解空间指针389 **Output: 最优值信息 工人工作分配390 **Return: 无391 **Others:392 *************************************************/

393 void SA( StrSolve *solutionSpace)394 {395 int i;//当前内循环次数

396 ElementType ChangeValue = 0;397 doublerand1;398

399 //更新初始值和最优解/值

400 solutionSpace->OptimalSolutionValue = GetSumTime( Time,solutionSpace->initSolution );401 solutionSpace->CurrentSolutionValue = solutionSpace->OptimalSolutionValue;402 //memcpy( solutionSpace->optimalSolution,solutionSpace->initSolution,sizeof(ElementType)* WORKER_NUM );//初始化的时候已经完成403

404 //设定当前温度为初始温度

405 CurrentTem =INIT_TEM;406 while( CurrentTem >=END_TEM){407

408 for( i = 0;i < INTER_WHILE ;i++){409

410 //获取 2邻域一个解//里面修改了临时解的邻域 在下面的if else if else 处理应对好了

411 Get2optSolution( solutionSpace );412

413 //计算目标值改变大小

414 solutionSpace->NextSolutionValue = GetSumTime( Time,solutionSpace->tempSolution );415 ChangeValue = solutionSpace->NextSolutionValue - solutionSpace->CurrentSolutionValue ;416

417 //Metropolis准则

418 if( ChangeValue < 0 ){//接受该解419

420 //更新当前解//不用更新临时解了 因为已经更新好了

421 memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*WORKER_NUM );422 solutionSpace->CurrentSolutionValue = solutionSpace->NextSolutionValue;423

424 //判断是否更新最优解

425 if( solutionSpace->CurrentSolutionValue < solutionSpace->OptimalSolutionValue ){426

427 //更新最优解

428 memcpy( solutionSpace->optimalSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );429 solutionSpace->OptimalSolutionValue = solutionSpace->CurrentSolutionValue;430 }431 }/*Metropolis 准则 end*/

432 else if( exp ( -(1.00*ChangeValue)/CurrentTem ) > (rand1 = rand()/(RAND_MAX+1.0) ) ){ //如果大于随机数 那么也接受该点433

434 //更新当前解//不用更新临时解了 因为已经更新好了

435 memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*WORKER_NUM );436 solutionSpace->CurrentSolutionValue = solutionSpace->NextSolutionValue;437

438 //判断是否更新最优解//实际上在这里肯定不会更新的 但是先不改了

439 if( solutionSpace->CurrentSolutionValue < solutionSpace->OptimalSolutionValue ){440 //更新最优解

441 memcpy( solutionSpace->optimalSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );442 solutionSpace->OptimalSolutionValue = solutionSpace->CurrentSolutionValue;443 }444 }445 else{//没有满足准则的时候 就要更新临时解为原来的currentSolution 因为获得2邻域解的时候修改了tempSolution

446

447 memcpy( solutionSpace->tempSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );448

449 }/*if ...else if ..else end*/

450

451 }/*for end 内循环*/

452

453 //更新降温函数 根据外层的循环次数而定

454 CurrentTem -=De_TEM;455

456 } /*while end*/

457

458 //输出历史最优值及工作分配

459 printf("\n工人工作时间最优值为:%d\n",solutionSpace->OptimalSolutionValue);460 printf("工人分配的工作为:\n");461 for( i = 0;i < WORKER_NUM; i++){462 printf("工人:%d 分配工作:%d\n",i+1,1+solutionSpace->optimalSolution[i]);463 }464 printf("\n工人工作时间最优值为:%d\n",solutionSpace->OptimalSolutionValue);465 }466

467 /*************************************************468 **Function: MemFree469 **Description: 释放申请的动态内存470 **Calls: free()471 **Called By: main()472 **Input: distance 存储工人工作时间矩阵 strSolve 解空间的指针473 **Output: 无474 **Return: void475 **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行476 *************************************************/

477 void MemFree(ElementType ** distance,StrSolve *strSolve)478 {479 int i=0;480 int j = 0;481

482 //释放矩阵元素存储区

483 for(i = 0;i < WORKER_NUM; i++){484 free( distance[i] );485 }486 free(distance);487

488 //释放解空间

489 free(strSolve->initSolution);490 free(strSolve->currentSolution);491 free(strSolve->optimalSolution);492 free(strSolve->tempSolution);493 free(strSolve);494

495 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值