本文共 5377 字,大约阅读时间需要 17 分钟。
针对第三种具体情况,我们首先确定故障判断和维修时间的实现。
对于故障判断,我们选择为每一个CNC工作的时刻生成一个从0到100的随机数a,如果生成的随机数a<1,即该时刻会发生故障。
而对于维修时间,我们同样采用了随机数的方法,生成了一个从600到1200的随机数b,b代表该次维修所花的秒数。
在这个模型中,我们对RGV与CNC赋予了更多的智能,使得它们能够识别故障行为。具体过程为:当利用贪心算法确定最优解时,我们会进行最优解是否故障的判断,如果判断为真,则跳过该解,重新进行利用贪心算法确定优解的步骤。如果判断为假,则按照4.1,4.2的模型继续进行调度。当调度过程进行至上下料完成时刻,我们会对CNC进行一次故障判断,如果判断为真,则进入维修操作,如果判断为假,则重新进行利用贪心算法确定优解的步骤。算法流程图如下图所示:
图7
对于这种模型,我们进行了C++的代码实现,得到了RGV的调度策略和系统的作业效率。针对结果,我们发现故障的发生基本服从泊松过程,且故障发生之后调度策略会发生极大的变化,而产量也会下降,与我们的预期相同。
/*------------------------CNC.h-----------------------*/#pragma onceclass CNC{private: int number; //CNC编号 int position; //CNC位置 int count; //CNC剩余工作时间 int n; //加工物序列号 int flag; //CNC当前状态,1故障,0正常public: CNC(int num, int pos); void countdown(int tem); friend class RGV;};/*------------------------CNC.cpp-----------------------*/#include "stdafx.h"#include "CNC.h"using namespace std;CNC::CNC( int num, int pos){ number = (num > 0) ? num : ERROR; position = (pos >= 0) ? pos : ERROR; count = 0; n = 0; flag = 0;}void CNC::countdown(int temp){ if (count > temp) { count -= temp; } else { count = 0; if (flag) { flag = 0; //恢复正常 cout << "CNC#" << number << "恢复正常" << endl; } }}/*------------------------RGV.h-----------------------*/#pragma once#include "CNC.h"class RGV{private: int position; //rgv当前位置 int now_cnc; //当前目标 int rgv_flag; //rgv_flag,1有熟料,0无public: int t_time; //总用时 int scr_times; //报废次数 int sum; //加工熟料总数 RGV(); void Init(CNC *p); //第一轮初始化 int posCalculate(int pos1, int pos2); //计算RGV移动时间 void move(CNC *p); //RGV移动 void load(CNC *p); //RGV上下料 void clean(CNC *p);//RGV清洗 void wait(CNC *p);//RGV等待 void repair(CNC *p);//RGV故障修复};/*------------------------RGV.cpp-----------------------*/#include "stdafx.h"#include "RGV.h"#define STEP1 23#define STEP2 41#define STEP3 59#define CNC_WORKTIME 580#define CNC1 30#define CNC0 35#define CLEAN 30#define CNCNUMBER 8using namespace std;int n = 0; //加工物序列号RGV::RGV() { position = 0; now_cnc = 1; rgv_flag = 0; t_time = 0; scr_times = 0; sum = 0;}void RGV::Init(CNC *p){ CNC* ptr = p; for (int i = 0; i < CNCNUMBER; i++, now_cnc++) //所有CNC剩余时间 - rgv移动时间 { int temp = posCalculate(position, (p + now_cnc - 1)->position); if (temp) { t_time += temp; CNC*ptr1 = p; for (int i = 0; i < CNCNUMBER; i++, ptr1++) //所有CNC剩余时间 - rgv移动时间 { ptr1->countdown(temp); } } load(p); position = (p + now_cnc - 1)->position; }}int RGV::posCalculate(int pos1, int pos2)//RGV移动时间计算{ switch (abs(pos1 - pos2)) { case 3: return STEP3; case 2: return STEP2; case 1: return STEP1; case 0: return 0; default: return ERROR; }}void RGV::move(CNC *p)//RGV移动{ CNC* ptr = p; int time1 = 10000;//最少时间 int time2 = 0; //当前时间 int next_cnc = 1; for (int i = 0; i < CNCNUMBER; i++, ptr++) { if (!(ptr->flag)) { int postime = posCalculate(position, ptr->position); time2 = ptr->count + postime;//CNC工作剩余时间 + RGV移动到当前位置时间 if (time1 > time2) { time1 = time2; next_cnc = ptr->number; } } else continue; } if (now_cnc != next_cnc) {//当前对象不是最优对象,移动 int temp = posCalculate(position, (p + next_cnc - 1)->position); if (temp) { t_time += temp; CNC*ptr1 = p; for (int i = 0; i < CNCNUMBER; i++, ptr1++) //所有CNC剩余时间 - rgv移动时间 { ptr1->countdown(temp); } } position = (p + next_cnc - 1)->position; now_cnc = next_cnc; } //cout << "position" << position << '\t' << "now_cnc" << now_cnc << endl; //test wait(p);}void RGV::load(CNC *p)//RGV上下料{ CNC* ptr = p + now_cnc - 1; //此处数组下标和CNC编号要注意! int temp = 0; cout << t_time << '\t' << '\t' << ptr->n << '\t' << '\t' << ++n << '\t' << now_cnc << endl; if ((ptr->number % 2) == 1) { temp = CNC1; } else { temp = CNC0; } t_time += temp; CNC*ptr1 = p; for (int i = 0; i < CNCNUMBER; i++, ptr1++) //所有CNC剩余时间 - rgv移动时间 { ptr1->countdown(temp); } ptr->n = n; ptr->count = CNC_WORKTIME; rgv_flag = 1;}void RGV::clean(CNC* p)//RGV清洗{ sum++; int temp = CLEAN; t_time += temp; CNC*ptr1 = p; for (int i = 0; i < CNCNUMBER; i++, ptr1++) //所有CNC剩余时间 - rgv移动时间 { ptr1->countdown(temp); }}void RGV::wait(CNC* p){ CNC* ptr = p + now_cnc - 1; if (ptr->count) { int temp = ptr->count; t_time += temp; CNC*ptr1 = p; for (int i = 0; i < CNCNUMBER; i++, ptr1++) //所有CNC剩余时间 - rgv移动时间 { ptr1->countdown(temp); } ptr->count = 0; } else return;}void RGV::repair(CNC *p){ CNC*ptr = p + now_cnc - 1; double rand_num = rand() % 100; //生成随机数 if (rand_num < 1.0) { //故障概率0.01 scr_times++; cout << t_time << '\t' << n << "号物料报废" << '\t' << "CNC#" << ptr->number << "发生故障" << endl; ptr->flag = 1; //故障 int repair_time = rand() % 600 + 600; ptr->count = repair_time; } else return;}/*------------------------main.cpp--------------------------*/// main.cpp: 定义控制台应用程序的入口点。//#include "stdafx.h"#include "RGV.h"#include "CNC.h"#define CNCNUMBER 8#define TIME 28800using namespace std;int main(){ RGV rgv; CNC cnc[CNCNUMBER] = { CNC(1,0), CNC(2,0), CNC(3,1), CNC(4,1), CNC(5,2), CNC(6,2), CNC(7,3), CNC(8,3) }; CNC *pCNC = cnc; cout <<"时间" << '\t' << "下料开始" << '\t' << "上料开始" << '\t' << "CNC#" << endl; /*第一轮 仅需考虑RGV“移动”和“上下料”动作*/ rgv.Init(pCNC); /*第(n+1)轮 RGV循环“移动”,“上下料”和“清洗”动作*/ while (rgv.t_time <= TIME) { rgv.move(pCNC); rgv.load(pCNC); rgv.repair(pCNC); rgv.clean(pCNC); } cout << "生成熟料总数:" << rgv.sum-rgv.scr_times << endl; cout << "发生故障次数" << rgv.scr_times << endl; system("pause"); return 0;}
转载地址:http://hqdxi.baihongyu.com/