原创:工作指派问题解决方案---模拟退火算法C实现
- /*****************************************************************************
- ** Copyright: NEW NEU laboratory
- ** File name: SA_工作指派问题
- ** Description:模拟退火算法解决工作指派问题
- ** Author: 1702--GCJ
- ** Version: 1.0
- ** Date: 2017/10/4
- ** History: 无
- *****************************************************************************/
- #include"stdio.h"
- #include"stdlib.h"
- #include"string.h"
- #include "time.h"
- #include "math.h"
- /*----------------------------------------------------
- @brief 参数配置区
- */
- #define WORK_NUM 100 //工作数量
- #define WORKER_NUM 100 //工人数量
- #define INIT_TEM (60 + WORK_NUM * 10) //初始温度
- #define END_TEM 60 //终止温度
- #define De_TEM 2 //降温函数
- #define INTER_WHILE 500 //内循环次数 类似于邻居个数
- typedef int ElementType;
- ElementType **Time; //存储工人工作时间 指针
- ElementType CurrentTem; //当前温度
- //定义解的存储类型 向量形式
- typedef struct _Solve{
- ElementType *initSolution; //初始解 //每个元素对应的序号表示工人 总序号表示工人总数 内部元素表示工人对应的工作
- ElementType *currentSolution; //当前解
- ElementType * optimalSolution; //最优解
- ElementType *tempSolution; //临时解
- ElementType OptimalSolutionValue; //记录最优解 (总时间)
- ElementType CurrentSolutionValue; //记录上次的值
- ElementType NextSolutionValue ; //记录交换后的总时间
- }StrSolve;//存储解结构
- StrSolve * SolutionSpace ; //解空间(包含当前解和初始解)指针
- typedef struct _Tabu{
- int smallNum;
- int bigNum; //存储数量大的元素
- }Tabu; //禁忌表结构
- typedef struct _MotionTable{
- Tabu tabu; //存储改变的元素
- ElementType changedistance; //改变的距离
- }MotionTable;//记录2opt邻域移动信息
- /*************************************************
- **Function: MemBlockWork
- **Description: 申请存储工人工作时间的空间
- **Calls: 无
- **Called By: ReadDataTxt()
- **Input: 无
- **Output: 无
- **Return: 指向存储工人工作时间的指针
- **Others: 无
- *************************************************/
- ElementType ** MemBlockWork();
- /*************************************************
- **Function: ReadDataTxt
- **Description: 从txt文档中读取工人工作时间数据
- **Calls: MemBlockWork()
- **Called By: main()
- **Input: 无
- **Output: 无
- **Return: void
- **Others: 里面直接用的全局变量 指针Time
- *************************************************/
- void ReadDataTxt();
- /*************************************************
- **Function: CreateSolutionSpace
- **Description: 创建并初始化解空间
- **Calls: 无
- **Called By: Init2Opt()
- **Input: worker_num 工人数量
- **Output: 无
- **Return: StrSolve *指针变量
- **Others: 不用这块内存的时候要逐一释放掉 !
- *************************************************/
- StrSolve *CreateSolutionSpace(int worker_num);
- /*************************************************
- **Function: GetInitSolution
- **Description: 获得初始解
- **Calls: 无
- **Called By: Init2Opt()
- **Input: StrSolve * 指针变量
- **Output: 无
- **Return: StrSolve *指针变量
- **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 工人工作不能重复及数组空间的数字不能重复
- *************************************************/
- void GetInitSolution(StrSolve * strSolve);
- /*************************************************
- **Function: Get2optSolution
- **Description: 得到1个2邻域解 用tempSolution来存储
- **Calls:
- **Called By: SA()
- **Input: solutionSpace 解空间指针
- **Output: 无
- **Return: void
- **Others: 随机数要注意!
- *************************************************/
- void Get2optSolution( StrSolve * solutionSpace );
- /*************************************************
- **Function: Init2Opt
- **Description: 初始化SA需要用的值
- **Calls: CreateSolutionSpace() GetInitSolution()
- **Called By: main()
- **Input: 无
- **Output: 无
- **Return: void
- **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 不知道为什么只能在Main函数中调用否则 会出现段错误
- *************************************************/
- void Init2Opt();
- /*************************************************
- **Function: GetSumTime
- **Description: 获取当前解的总工作时间
- **Calls:
- **Called By: SA()
- **Input: distance 存储工人工作时间的矩阵指针 Solution 解指针
- **Output: 无
- **Return: 总工作时间
- **Others: 里面用到了WORKER_NUM 宏
- *************************************************/
- int GetSumTime( ElementType **distance,ElementType * Solution);
- /*************************************************
- **Function: SA
- **Description: 模拟退火算法
- **Calls: GetSumTime() Get2optSolution() memcpy() rand() exp()
- **Called By: main()
- **Input: solutionSpace 解空间指针
- **Output: 最优值信息 工人工作分配
- **Return: 无
- **Others:
- *************************************************/
- void SA( StrSolve *solutionSpace);
- /*************************************************
- **Function: MemFree
- **Description: 释放申请的动态内存
- **Calls: free()
- **Called By: main()
- **Input: distance 存储工人工作时间矩阵 strSolve 解空间的指针
- **Output: 无
- **Return: void
- **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行
- *************************************************/
- void MemFree(ElementType ** distance,StrSolve *strSolve);
- /*******************************************************************************MAIN函数*************************************/
- int main(int argc,char *argv[])
- {
- clock_t start, finish;
- double duration;
- //设置随机数种子 为以后使用rand()做准备
- srand((unsigned int)time());
- Init2Opt();
- //从读取数据开始的起始时间
- start = clock();
- //将工人工作时间的数据存储到Time指向的空间中
- ReadDataTxt(Time);
- //模拟退火算法开始
- SA(SolutionSpace);
- //第二次用模拟退火
- // memcpy( SolutionSpace->currentSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );
- // memcpy( SolutionSpace->initSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );
- // memcpy( SolutionSpace->tempSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*WORKER_NUM );
- // GetInitSolution(SolutionSpace);//初始化解
- // SA(SolutionSpace);
- //结束时间
- finish = clock();
- duration = (double)(finish - start) / CLOCKS_PER_SEC;
- printf("\n SA算法运行时间:%.4f秒 \n",duration);
- //释放申请的内存
- MemFree(Time,SolutionSpace);
- return ;
- }
- /*************************************************
- **Function: MemBlockWork
- **Description: 申请存储工人工作时间的空间
- **Calls: 无
- **Called By: ReadDataTxt()
- **Input: 无
- **Output: 无
- **Return: 指向存储工人工作时间的指针
- **Others: 无
- *************************************************/
- ElementType ** MemBlockWork()
- {
- ElementType ** Distance;
- int i=;
- //动态申请一块内存存储工人工作时间
- Distance = (ElementType **)malloc(sizeof(ElementType *)* WORKER_NUM);
- for(i = ;i< WORKER_NUM; i++){
- Distance[i] = (ElementType *)malloc(sizeof (ElementType )* WORK_NUM);
- }
- return Distance;
- }
- /*************************************************
- **Function: ReadDataTxt
- **Description: 从txt文档中读取工人工作时间数据
- **Calls: MemBlockWork()
- **Called By: main()
- **Input: 无
- **Output: 无
- **Return: void
- **Others: 里面直接用的全局变量 指针Time
- *************************************************/
- void ReadDataTxt()
- {
- // FILE *fpRead=fopen("F:\\GCJ\\Desktop\\智能优化方法作业\\data.txt","r");
- FILE *fpRead=fopen("data.txt","r"); //从data.txt中读取数据
- int i,j;
- if(fpRead==NULL){
- printf("open file data.txt failed!\n");
- exit();
- }
- Time = MemBlockWork(); //申请一块存储城市数量空间
- for( i = ;i < WORKER_NUM; i++ ){
- for(j= ;j < WORK_NUM ;j++ ){
- fscanf(fpRead,"%d",&Time[i][j]);//自动读取数据 只要自己能够控制好存储位置即可
- // printf("Time[%d][%d] = %d ",i,j,Time[i][j]);
- }
- }
- fclose(fpRead);
- }
- /*************************************************
- **Function: CreateSolutionSpace
- **Description: 创建并初始化解空间
- **Calls: 无
- **Called By: Init2Opt()
- **Input: worker_num 工人数量
- **Output: 无
- **Return: StrSolve *指针变量
- **Others: 不用这块内存的时候要逐一释放掉 !
- *************************************************/
- StrSolve *CreateSolutionSpace(int worker_num)
- {
- int i;
- StrSolve *strSolve = (StrSolve *)malloc( sizeof(StrSolve) ) ;
- strSolve->initSolution = ( ElementType *)malloc(sizeof(ElementType)* worker_num );
- strSolve->currentSolution = ( ElementType *)malloc(sizeof(ElementType)* worker_num );
- strSolve->optimalSolution = ( ElementType *)malloc(sizeof(ElementType)* worker_num );
- strSolve->tempSolution = ( ElementType *)malloc(sizeof(ElementType)* worker_num );
- //初始化解空间
- for(i = ;i< worker_num;i++){
- strSolve->initSolution[i] = (ElementType);
- strSolve->currentSolution[i] = (ElementType);
- strSolve->optimalSolution[i] = (ElementType);
- strSolve->tempSolution[i] = (ElementType);
- }
- strSolve->CurrentSolutionValue = ;
- strSolve->NextSolutionValue = ;
- strSolve->OptimalSolutionValue = ;
- return strSolve;
- }
- /*************************************************
- **Function: GetInitSolution
- **Description: 获得初始解
- **Calls: 无
- **Called By: Init2Opt()
- **Input: StrSolve * 指针变量
- **Output: 无
- **Return: StrSolve *指针变量
- **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 工人工作不能重复及数组空间的数字不能重复
- *************************************************/
- void GetInitSolution(StrSolve * strSolve)
- {
- int i;
- //产生0- WORK_NUM-1 (工作数量减1) 之间的随机数不能重复
- //默认从0号工作顺序开始
- for( i = ;i < WORKER_NUM;i++){
- strSolve->initSolution[i] = i;
- strSolve->currentSolution[i] = i;
- strSolve->optimalSolution[i] = i;
- strSolve->tempSolution[i] = i;
- }
- }
- /*************************************************
- **Function: Get2optSolution
- **Description: 得到1个2邻域解 用tempSolution来存储
- **Calls:
- **Called By: SA()
- **Input: solutionSpace 解空间指针
- **Output: 无
- **Return: void
- **Others: 随机数要注意!
- *************************************************/
- void Get2optSolution( StrSolve * solutionSpace )
- {
- //产生一个 0 - - WORKER-1之间的随机数 表示交换工人对应的工作数 [0,WORKER)
- MotionTable motiontable;
- ElementType temp;
- // ElementType changeDistance;
- int rand1,rand2;
- // rand1 = (CityNum-1) *rand()/(RAND_MAX + 1.0);
- rand1 = rand()%WORKER_NUM; //[0,WORKER_NUM)
- rand2 = rand()%WORKER_NUM;
- while( rand2 == rand1 ) //必须产生两个不同的随机数
- rand2 = rand()%WORKER_NUM;
- //记录交换的两个工人编号
- motiontable.tabu.smallNum = (rand2 >rand1)? rand1:rand2;
- motiontable.tabu.bigNum = (rand2 >rand1)? rand2:rand1;
- //更新当前解 //用临时解作为j解
- temp = solutionSpace->tempSolution[ motiontable.tabu.smallNum ];
- solutionSpace->tempSolution[ motiontable.tabu.smallNum] = solutionSpace->tempSolution[ motiontable.tabu.bigNum ];
- solutionSpace->tempSolution[ motiontable.tabu.bigNum ] = temp;
- // motiontable->changedistance = Get2OptChangeDistance( &motiontable->tabu ,strSolve->tempSolution );
- }
- /*************************************************
- **Function: Init2Opt
- **Description: 初始化SA需要用的值
- **Calls: CreateSolutionSpace() GetInitSolution()
- **Called By: main()
- **Input: 无
- **Output: 无
- **Return: void
- **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解 ! 不知道为什么只能在Main函数中调用否则 会出现段错误
- *************************************************/
- void Init2Opt()
- {
- SolutionSpace = CreateSolutionSpace(WORKER_NUM);//创建解空间
- GetInitSolution(SolutionSpace);//初始化解
- }
- /*************************************************
- **Function: GetSumTime
- **Description: 获取当前解的总工作时间
- **Calls:
- **Called By: SA()
- **Input: distance 存储工人工作时间的矩阵指针 Solution 解指针
- **Output: 无
- **Return: 总工作时间
- **Others: 里面用到了WORKER_NUM 宏
- *************************************************/
- int GetSumTime( ElementType **distance,ElementType * Solution)
- {
- //只要保证Solution 里面的值不一样即可算出
- int i;
- int SumLevel = ;
- for(i = ; i < WORKER_NUM ; i++){
- SumLevel += distance[ i ][ Solution[i] ];
- }
- return SumLevel;
- }
- /*************************************************
- **Function: SA
- **Description: 模拟退火算法
- **Calls: GetSumTime() Get2optSolution() memcpy() rand() exp()
- **Called By: main()
- **Input: solutionSpace 解空间指针
- **Output: 最优值信息 工人工作分配
- **Return: 无
- **Others:
- *************************************************/
- void SA( StrSolve *solutionSpace)
- {
- int i;//当前内循环次数
- ElementType ChangeValue = ;
- double rand1;
- //更新初始值和最优解/值
- solutionSpace->OptimalSolutionValue = GetSumTime( Time,solutionSpace->initSolution );
- solutionSpace->CurrentSolutionValue = solutionSpace->OptimalSolutionValue;
- // memcpy( solutionSpace->optimalSolution,solutionSpace->initSolution,sizeof(ElementType)* WORKER_NUM );//初始化的时候已经完成
- //设定当前温度为初始温度
- CurrentTem = INIT_TEM;
- while( CurrentTem >= END_TEM){
- for( i = ;i < INTER_WHILE ;i++){
- //获取 2邻域一个解 //里面修改了临时解的邻域 在下面的if else if else 处理应对好了
- Get2optSolution( solutionSpace );
- //计算目标值改变大小
- solutionSpace->NextSolutionValue = GetSumTime( Time,solutionSpace->tempSolution );
- ChangeValue = solutionSpace->NextSolutionValue - solutionSpace->CurrentSolutionValue ;
- //Metropolis准则
- if( ChangeValue < ){//接受该解
- //更新当前解 //不用更新临时解了 因为已经更新好了
- memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*WORKER_NUM );
- solutionSpace->CurrentSolutionValue = solutionSpace->NextSolutionValue;
- //判断是否更新最优解
- if( solutionSpace->CurrentSolutionValue < solutionSpace->OptimalSolutionValue ){
- //更新最优解
- memcpy( solutionSpace->optimalSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );
- solutionSpace->OptimalSolutionValue = solutionSpace->CurrentSolutionValue;
- }
- }/*Metropolis 准则 end*/
- else if( exp ( -(1.00*ChangeValue)/CurrentTem ) > (rand1 = rand()/(RAND_MAX+1.0) ) ){ //如果大于随机数 那么也接受该点
- //更新当前解 //不用更新临时解了 因为已经更新好了
- memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*WORKER_NUM );
- solutionSpace->CurrentSolutionValue = solutionSpace->NextSolutionValue;
- //判断是否更新最优解 //实际上在这里肯定不会更新的 但是先不改了
- if( solutionSpace->CurrentSolutionValue < solutionSpace->OptimalSolutionValue ){
- //更新最优解
- memcpy( solutionSpace->optimalSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );
- solutionSpace->OptimalSolutionValue = solutionSpace->CurrentSolutionValue;
- }
- }
- else{//没有满足准则的时候 就要更新临时解为原来的currentSolution 因为获得2邻域解的时候修改了tempSolution
- memcpy( solutionSpace->tempSolution,solutionSpace->currentSolution,sizeof(ElementType)*WORKER_NUM );
- }/*if ...else if ..else end*/
- }/*for end 内循环*/
- //更新降温函数 根据外层的循环次数而定
- CurrentTem -= De_TEM;
- } /*while end*/
- //输出历史最优值及工作分配
- printf("\n工人工作时间最优值为:%d\n",solutionSpace->OptimalSolutionValue);
- printf("工人分配的工作为:\n");
- for( i = ;i < WORKER_NUM; i++){
- printf("工人:%d 分配工作:%d\n",i+,+solutionSpace->optimalSolution[i]);
- }
- printf("\n工人工作时间最优值为:%d\n",solutionSpace->OptimalSolutionValue);
- }
- /*************************************************
- **Function: MemFree
- **Description: 释放申请的动态内存
- **Calls: free()
- **Called By: main()
- **Input: distance 存储工人工作时间矩阵 strSolve 解空间的指针
- **Output: 无
- **Return: void
- **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行
- *************************************************/
- void MemFree(ElementType ** distance,StrSolve *strSolve)
- {
- int i=;
- int j = ;
- //释放矩阵元素存储区
- for(i = ;i < WORKER_NUM; i++){
- free( distance[i] );
- }
- free(distance);
- //释放解空间
- free(strSolve->initSolution);
- free(strSolve->currentSolution);
- free(strSolve->optimalSolution);
- free(strSolve->tempSolution);
- free(strSolve);
- }
下面是试验的结果图:
相关资源(源码包+数据+报告)可在下面网址下载:
http://download.csdn.net/download/geself/10191272
运行环境:windows7
IDE : DEVC++
原创:工作指派问题解决方案---模拟退火算法C实现的更多相关文章
- 模拟退火算法Python编程(3)整数规划问题
1.整数规划问题 整数规划问题在工业.经济.国防.医疗等各行各业应用十分广泛,是指规划中的变量(全部或部分)限制为整数,属于离散优化问题(Discrete Optimization). 线性规划问题的 ...
- 【原创】机器学习之PageRank算法应用与C#实现(2)球队排名应用与C#代码
在上一篇文章:机器学习之PageRank算法应用与C#实现(1)算法介绍 中,对PageRank算法的原理和过程进行了详细的介绍,并通过一个很简单的例子对过程进行了讲解.从上一篇文章可以很快的了解Pa ...
- 推荐学习《算法之美:指导工作与生活的算法》中文PDF+英文PDF
我们所有人的生活都受到有限空间和有限时间的限制,因此常常面临一系列难以抉择的问题.在一天或者一生的时光里,哪些事是我们应该做的,哪些是应该放弃的?我们对杂乱无序的容忍底线是什么?新的活动与熟悉并喜爱的 ...
- 模拟退火算法(1)Python 实现
1.模拟退火算法 模拟退火算法借鉴了统计物理学的思想,是一种简单.通用的启发式优化算法,并在理论上具有概率性全局优化性能,因而在科研和工程中得到了广泛的应用. 退火是金属从熔融状态缓慢冷却.最终达到能 ...
- 模拟退火算法Python编程(2)约束条件的处理
1.最优化与线性规划 最优化问题的三要素是决策变量.目标函数和约束条件. 线性规划(Linear programming),是研究线性约束条件下线性目标函数的极值问题的优化方法,常用于解决利用现有的资 ...
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...
- 模拟退火算法-[HDU1109]
模拟退火算法的原理模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到 ...
- 【高级算法】模拟退火算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46453761 ---------------------------------- ...
- 模拟退火算法(SA)求解TSP 问题(C语言实现)
这篇文章是之前写的智能算法(遗传算法(GA).粒子群算法(PSO))的补充.其实代码我老早之前就写完了,今天恰好重新翻到了,就拿出来给大家分享一下,也当是回顾与总结了. 首先介绍一下模拟退火算法(SA ...
随机推荐
- 前端开发【第3篇:JavaScript序】
JavaScript历史 聊聊JavaScript的诞生 JavaScirpt鼻祖:Bremdan Eich(布兰登·艾奇),JavaScript的诞生于浏览器的鼻祖网景公司(Netscape),发布 ...
- JavaWeb程序连接SQLserver数据库
声明:一直以来都以为javaweb程序连接数据库是一个很高大上很难的问题,结果今天学习了一下,不到两个小时就解决了,所以总结一篇博客. JavaWeb程序连接SQLserver数据库分为一下步骤: 1 ...
- poj 1986LCA离线dfs+并查集
题意,给出边和权值,求出两个点间的最短距离. 用离线算法的时候有个地方不知道怎么处理了.在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理.套一个rmq的模板吧,用来处理 ...
- CCIE-交换路由复习笔记
交换 考点: 1.trunk link(基础) 2.vtp 3.vlan 4.stp rstp mstp 5.hsrp vrrp glbp 6.ec Trunk link: 修改封装模式 802.1q ...
- 转:【深入Java虚拟机】之五:多态性实现机制——静态分派与动态分派
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17965867 方法解析 Class文件的编译过程中不包含传统编译中的连接步骤,一切方法 ...
- 关于SVM数学细节逻辑的个人理解(一)
网上,书上有很多的关于SVM的资料,但是我觉得一些细节的地方并没有讲的太清楚,下面是我对SVM的整个数学原理的推导过程,其中我理解的地方力求每一步都是有理有据,希望和大家讨论分享. 首先说明,目前我的 ...
- 201521123084 《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...
- 团队作业8——第二次项目冲刺(Beta阶段)Day5--5.23
1.提供当天站立式会议照片一张 2.会议内容 讨论已完成的功能 对于界面,谈谈各自的看法 商定测试计划 用户需求进一步调研 3.工作安排 队员 今日任务 明日任务 贡献比 林燕 测试运行效果 根据测试 ...
- 201521123082《Java程序设计》第2周学习总结
201521123082<Java程序设计>第2周学习总结 标签(空格分隔): Java 1.本周学习总结 巩固了类型转换的相关细节 初步认识了类和对象,使用Java撰写程序几乎都在使用对 ...
- 201521123080《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 List中指定元素的删除(题目4-1) 1.1 实验总结 在covnertS ...