C++程序-流水作业调度
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、问题描述
给定n个作业,每个作业有两道工序,分别在两台机器上处理。
一台机器一次只能处理一道工序,并且一道工序一旦开始就必须进行下去直到完成。
一个作业只有在机器1上的处理完成以后才能由机器2处理。
假设已知作业i在机器j上需要的处理时间为t[i,j]。
流水作业调度问题就是要求确定一个作业的处理顺序使得尽快完成这n个作业。
二、算法分析
n个作业{1,2,…,n}要在由2台机器
M和2M组成的流水线上完成加工。
每
1
个作业加工的顺序都是先在
M上加工,然后在2M上加工。
1M和2M加工作业i所
1
需要的时间分别为t[i,1]和t[i,2], n
1.流水作业调度问题要求确定这n
i≤
≤
个作业的最优加工顺序,使得从第一个作业在机器
M上开始加工,到最后一个
1
作业在机器
M上加工完成所需的时间最少。
2
从直观上我们可以看到,一个最优调度应使机器
M没有空闲时间,且机器2M
1
的空闲时间是最少。
在一般情况下,机器
M上会有机器空闲和作业积压两种情
2
况。
设全部作业的集合为}
N=。
N
2,1{n
,....,
S⊆是N的作业子集。
在一般情况下,
机器
M开始加工S中作业时,机器2M还在加工其他作业,要等时间t后才能利1
用。
将这种情况下完成S中作业所需的最短时间计为),
S
T。
流水作业调度问题
(t
的最优解为)0,
T。
(N
1.证明流水作业调度问题具有最优子结构
设a是所给n个流水作业的一个最优调度,它所需要的加工时间为
']1),1([T a t +。
其中,'T 是在机器2M 的等待时间为]2),1([a t 时,安排作业)(),......,3(),2(n a a a 所需的时间。
记)}1({a N S -=,则我们可以得到])2),1([,('a t S T T =。
事实上,有T 的定义可知])2),1([,('a t S T T ≥.若])2),1([,('a t S T T >,设'a 是作业集S 在机器2M 的等待时间为]2),1([a t 情况下的一个最优调度。
则
)('),.....,2('),1(n a a a 是N 的一个调度且该调度所需的时间']1),1([])2),1([,(]1),1([T a t a t S T a t +<+。
这与a 是N 的一个最优调度矛盾,所以])2),1([,('a t S T T ≤。
从而])2),1([,('a t S T T =。
这就是证明了流水作业调度问题具有
最优子结构的性质。
2. 建立递归式计算最优解
由流水作业调度问题的最优子结构的性质我们可以得到,
])}2,[},{(]1,[{)0,(min 1i t i N T i t N T n
i -+=≤≤。
推广到更一般的情形,我们便有:
})}0],1,[max{]2,[},{(]1,[{min ),(i t t i t i S T i t t S T S
i -+-+=∈。
其中,}0],1,[max{i t t -这一项是
由于机器2M 上,作业i 需在]}1,[,max{i t t 时间之后才能开工。
因此,在机器1M 上完成作业i 之后,在机器上还需}0],1,[max{]2,[]1,[]}1,[,max{]2,[i t t i t i t i t t i t -+=-+时间才能完成对作业i 的加工。
按照上面所叙述的递归式,可以设计出解决流水作业调度问题的动态规划算法。
通过对递归式的分析,算法可以得到进一步的改进。
3. 流水调度问题的Johnson 法则
设a 是作业集S 在机器2M 的等待时间为t 时的任意一个最优调度。
如果在调度中,安排在最前面的两个作业分别为i 和j ,即j a i a ==)2(,)1(。
则由动态规划的递归式可以得到:
)},,{(]1,[]1,[})0],1,[max {},{(]1,[),(ij i t j i S T j t i t i t t b i S T i t t S T -++=-+-+=
其中,}0],1,[}0],1,[max {]2,[max {]2,[j t i t t i t j t t ij --++=
]}2,[]1,[,0},0],1,[max{max{
]1,[]2,[]2,[i t j t i t t j t i t j t --+-+= }0],2,[]1,[],1,[max{]1,[]2,[]2,[i t j t i t t j t i t j t --+-+= ]}1,[],2,[]1,[]1,[,max{]1,[]1,[]2,[]2,[i t i t j t i t t i t j t i t j t -++--+=
如果作业i 和j 满足]}1,[],2,[min{]}1,[],2,[min{i t j t j t i t ≥,则称作业i 和j 满足Johnson 不等式。
如果作业i 和j 不满足Johnson 不等式,则交换作业i 和j 的加工次序后,作业i 和j 满足Johnson 不等式。
在作业集S 当机器2M 的等待时间为t 时的调度a 中,交换作业i 和作业
j 的加工次序,得到的作业集S 的另一个调度a ’,它所需要的加工时间为
)},,{(]1,[]1,[),('ji t j i S T j t i t t S T -++=。
其中,]}1,[],2,[]1,[]1,[,max {]1,[]1,[]2,[]2,[j t j t j t i t t i t j t i t j t t ji -++--+=
当作业i 和j 满足Johnson 不等式]}1,[],2,[min{]}1,[],2,[min{i t j t j t i t ≥时,我们有]}1,[],2,[max{]}1,[],2,[max{i t j t j t i t --≤--
从而,]}1,[],2,[max{]1,[]1,[]}1,[],2,[max{]1,[]1,[i t j t j t i t i t i t j t i t --++≤--++ 由此可得,]}1,[],2,[]1,[]1,[max{]}1,[],2,[]1,[]1,[max{i t j t j t i t i t i t j t i t -+≤-+ 因此任意t 有
]}1,[],2,[]1,[]1,[,max{]}1,[],2,[]1,[]1,[,max{i t j t j t i t t i t i t j t i t t -+≤-+
从而,ji ij t t ≤。
由此可见),('),(t S T t S T ≤。
换句话说,当作业i 和作业j 不满足Johnson 不等式时,交换它们的加工顺序后,作业i 和作业j 就满足Johnson 不等式了,且不增加加工时间。
由此可得,对于流水作业调度问题,必存在一个最优的调度a ,使得作业)(i a 和)1(+i a 满足Johnson 不等式:
11]},1),([],2),1([min{]}1),1([],2),([min{-≤≤+≥+n i i a t i a t i a t i a t ,称这样的调度a 为满
足Johnson 法则的调度。
进一步可以证明,调度a 满足Johnson 法则当且仅当对任意的i 和j 都有i<j 时有]}1),([],2),([min{]}1),([],2),([min{i a t j a t j a t i a t ≥。
由此可知,任意两个满足Johnson 法则的调度均为最优调度。
至此,我们将流水调度问题转化为求满足Johnson 法则的调度问题。
4. 算法的描述
从上面的分析可知,流水作业调度问题一定存在满足Johnson 法则的最优调度,且容易由下面的算法确定。
流水作业调度问题的Johnson 算法: (1) 令]}2,[]1,[|{]},2,[]1,[|{21i t i t i N i t i t i N ≥=<=;
(2) 将1N 中作业依]1,[i t 的非减序排列;将2N 中作业依]2,[i t 的非增序排
列;
(3)
1N 作业接2N 种作业构成满足Johnson 法则的最优调度。
具体的代码在文件夹《流水作业调度——动态规划法》文件夹中。
三、 时空效率分析
算法FlowJob 的主要计算时间花在对作业集的排序上。
在这里,我们
使用冒泡排序法(BubbleSort),因此,在最坏情况下算法FlowJob 所需要的计算时间为)log (n n O 。
所需要的空闲显然是)(n O 。
// FlowOperation.h
#ifndef FLOWOPERATION_H
#define FLOWOPERATION_H
class FlowOperation
{
public:
FlowOperation();
~FlowOperation();
void run(); // 运行接口
private:
int number; // 流水作业个数
int numberB; // 记录N1的个数
int numberC; // 记录N1的个数
int **a; // 存储流水作业时间
int **b; // N1(Ai<Bi)
int **c; // N2(Ai>=Bi)
bool input(); // 输入接口
bool sort(); // X=0 or X=1 快速排序目的是满足Johnson 不等式min(Bi,Aj)≥min(Bj,Ai) 任意 j≥i
bool sortB(int **b,int i,int j,int X); // X=0;
bool sortC(int **c,int i,int j,int X); // X=1;
void output(); // 输出计算的最优调度所用的时间
#endif
// FlowOperation.cpp
#include <iostream>
using std::endl;
using std::ios;
using std::cout;
#include <fstream>
using std::fstream;
using std::ifstream;
using std::ofstream;
#include <cstdlib>
//using std::exit;
#include "FlowOperation.h"
#define N 50 // 预定义有50个作业根据实际情况可作调整
ifstream inputFile("input.txt",ios::in); ofstream outputFile("output.txt",ios::out);
FlowOperation::FlowOperation() // 构造函数{
number=0;
numberB=0;
numberC=0;
a=new int *[N];
b=new int *[N];
c=new int *[N];
for (int i=0;i<N;i++)
{
a[i]=new int [2];
b[i]=new int [2];
c[i]=new int [2];
}
}
FlowOperation::~FlowOperation() // 析构函数
for (int i=0;i<2;i++)
{
delete []a[i];
delete []b[i];
delete []c[i];
}
delete []a;
delete []b;
delete []c;
}
bool FlowOperation::input() // 输入
{
inputFile>>number;
outputFile<<number<<endl;
cout<<number<<endl;
for (int j=0;j<2;j++) // 读取数据并导入到output.txt文件中{
for (int i=0;i<number;i++)
{
inputFile>>a[i][j];
outputFile<<a[i][j]<<" ";
cout<<a[i][j]<<" ";
}
outputFile<<endl;
cout<<endl;
}
outputFile<<endl;
cout<<endl;
for (int i=0;i<number;i++) // 分类判断 ai 与 bi 的关系即a[i][0] 与 a[i][1]的大小关系
{
if (a[i][0]<a[i][1])
{ // 提取满足ai<bi的时间事件在机器M1上的工作时间小于M2上的工作时间存储在数组b[]中
b[numberB][0]=a[i][0];
b[numberB][1]=a[i][1];
numberB++;
}
else
{ // 提取满足ai>=bi的时间事件在机器M1上的工作时间小于M2上的工作时间存储在数组c[]中
c[numberC][0]=a[i][0];
c[numberC][1]=a[i][1];
numberC++;
}
}
cout<<"numberB="<<numberB<<endl;
for (int k=0;k<2;k++)
{
for (int i=0;i<numberB;i++)
{
cout<<b[i][k]<<" ";
}
cout<<endl;
}
cout<<endl;
cout<<"numberC="<<numberC<<endl;
for ( k=0;k<2;k++)
{
for (int i=0;i<numberC;i++)
{
cout<<c[i][k]<<" ";
}
cout<<endl;
}
cout<<endl;
if (a!=NULL)
{
if ((b!=NULL) || (c!=NULL))
{
return true;
}
return false;
}
return false;
}
bool FlowOperation::sort()
{
if (sortB(b,0,numberB-1,0)) // 判断是否一对数组b[][] 排好序{
if (sortC(c,0,numberC-1,1)) // 判断是否一对数组c[][] 排好序{
return true;
}
return false;
}
return true;
}
bool FlowOperation::sortB(int **b,int i,int j,int X) // 升序排序{
if (i<j)
{
int left=i;
int right=j;
j++;// 目的是使用 --j
int pivot=b[i][X];
while (i<j)
{
while(i<j) // 从左边寻找第一个大于 pivot 的数不适用等号
{
if (b[++i][X]<pivot)
{
continue;
}
break;
}
while(j>i) // 从右边寻找第一个小于 pivot 的数不适用等号{
if (b[--j][X]>pivot)
{
continue;
}
break;
}
if (i<j)
{
int t;
t=b[i][X];
b[i][X]=b[j][X];
b[j][X]=t;
int Y=(X+1)%2;
t=b[i][Y];
b[i][Y]=b[j][Y];
b[j][Y]=t;
}
}
{
int t;
t=b[left][X];
b[left][X]=b[j][X];
b[j][X]=t;
int Y=(X+1)%2;
t=b[left][Y];
b[left][Y]=b[j][Y];
b[j][Y]=t;
}
sortB(b,left,j-1,X);
sortB(b,j+1,right,X);
}
return true;
}
bool FlowOperation::sortC(int **c,int i,int j,int X) // 降序排序{
if (i<j)
{
int left=i;
int right=j;
j++;// 目的是使用 --j
int pivot=c[i][X];
while (i<j)
{
while(i<j) // 从左边寻找第一个小于 pivot 的数不适用等号{
if (c[++i][X]>pivot)
{
continue;
}
break;
}
while(j>i) // 从右边寻找第一个大于 pivot 的数不适用等号{
if (c[--j][X]<pivot)
{
continue;
}
break;
}
if (i<j)
{
int t;
t=c[i][X];
c[i][X]=c[j][X];
c[j][X]=t;
int Y=(X+1)%2;
t=c[i][Y];
c[i][Y]=c[j][Y];
c[j][Y]=t;
}
}
{
int t;
t=c[left][X];
c[left][X]=c[j][X];
c[j][X]=t;
int Y=(X+1)%2;
t=c[left][Y];
c[left][Y]=c[j][Y];
c[j][Y]=t;
}
sortC(c,left,j-1,X);
sortC(c,j+1,right,X);
}
return true;
}
void FlowOperation::run() // 运行接口
{
if (input()) // 调用并判断是否完成输入、和划分{
if (sort()) // 判断是否已排好序
{
output(); // 调用outpu()函数实现导入、输出}
}
}
void FlowOperation::output() // 结果输出
{
for (int k=0;k<2;k++) // 把排序好的数据导入到output.txt文件中以备查看
{
for (int i=0;i<numberB;i++)
{
cout<<b[i][k]<<" ";
outputFile<<b[i][k]<<" ";
}
cout<<endl;
outputFile<<endl;
}
cout<<endl;
outputFile<<endl;
for ( k=0;k<2;k++) // 把排序好的数据导入到output.txt文件中以备查看
{
for (int i=0;i<numberC;i++)
{
cout<<c[i][k]<<" ";
outputFile<<c[i][k]<<" ";
}
cout<<endl;
outputFile<<endl;
}
cout<<endl;
outputFile<<endl;
// 以下代码是实现计算总时间sum
int sum=b[0][0];
int t=b[0][1];
for (int i=1;i<numberB;i++) // 完成a[i]之和还需要时间t才可以结束
{
sum+=b[i][0];
t=(t>b[i][0] ? (t-b[i][0]) : 0 );
t+=a[i][1];
}
cout<<endl;
cout<<sum<<" "<<t<<endl;
cout<<"gsjfsjfgj"<<endl;
for (i=0;i<numberC;i++)
{
sum+=c[i][0];
t=(t>c[i][0] ? (t-c[i][0]) : 0 );
t+=c[i][1];
}
sum+=t;
cout<<sum<<endl;
outputFile<<sum<<endl; // 把计算结果导入到output.txt文件中}
// main.cpp
#include "FlowOperation.h"
int main()
{
FlowOperation f;
f.run();
return 0;
}
欢迎您的下载,
资料仅供参考!
致力为企业和个人提供合同协议,策划案计划书,学习资料等等
打造全网一站式需求。