原创:工作指派问题解决方案---模拟退火算法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 ...
随机推荐
- 网络协议TFTP
TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议.和使用TCP的文件传输协议(FTP ...
- 多路复用(select、epoll)实现tcp服务
-------------------------------多路复用的服务器(select)------------------------------- 网络通信被Unix系统抽象为文件的读写,通 ...
- fetch的使用说明
1.RN官方文档中,可使用XMLHttpRequest var request = new XMLHttpRequest(); request.onreadystatechange = (e) =&g ...
- 【小白成长撸】--Fibonacci
/*程序的版权和版本声明部分: *Copyright(c) 2016,电子科技大学本科生 *All rights reserved. *文件名:Fibonacci *程序作用:计算菲薄拉稀数列 *作者 ...
- 团队作业2——需求分析&原型设计
Deadline: 2017-4-14 22:00PM,以博客发表日期为准 评分基准: 按时交 - 有分,检查的项目包括后文的三个方面 需求分析 原型设计 编码规范 晚交 - 0分 迟交两周以上 - ...
- Java学习2——HelloWorld(编写第一个java程序)
编写 在自己的工作文件目录下(如上一篇中配置的classpath路径)创建HelloWorld.java文件,编写如下代码,并保存 public class HelloWorld { public s ...
- 201521123059 《Java程序设计》第四周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 参考资料: 百度脑图 XMind 1.2 使用常规方法总结其他上课内容. 1.多态性就是相同的形态,不同的行为(不同的定义).多态就 ...
- 201521123060 《Java程序设计》第13周学习总结
1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2.书面作业 1.网络基础 1.1比较ping www.baidu.com与ping cec.jmu.edu ...
- 201521123003《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...
- 201521123078 《Java程序设计》第14周学习总结
1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) 2 ...