您的位置:首页 > 其它

动态规划 - 装配线调度问题

2012-03-17 11:39 337 查看

1 动态规划介绍

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。

动态规划通常应用于最优化问题。此类问题可能有很多种可行解。每个解有一个解,而我们希望找出一个最优解(最大值或最小值)。

动态规划算法的设计可分为如下4个步骤:

(1)描述最优解的结构;

(2)递归定义最优解的值;

(3)按自底向上的方式计算最优解的值;

(4)由计算出的结果构造一个最优解。

第1~3步构成问题的动态规划解得基础,第4步在只要求计算最优解的值时可以略去。如果的确做了第4步,则有时要在第3步的计算中记录一些附加信息,要构造一个最优解变得容易。

2 装配线调度问题描述

一个找出通过工厂装配线的最快方式的制造问题。共有两条装配线,每一条装配线上有n个装配站,编号为j = 0, 1, … , n - 1。装配线i(i = 0或1),在装配站S[i][j]上所需的装配时间记为a[i][j]。一个汽车底盘进入工厂,然后进入装配线i的进入时间为e[i],在通过一条线的第j个装配站后,这个底盘来到任一条线的第(j + 1)个装配站。如果留在相同的装配线上,则没有移动的开销;如果在装配站S[i][j]后,它移动到了另一条线上,则花费时间t[i][j]。在离开一条线的第n个装配站后,完成的汽车离开装配线i的离开时间为x[i]


f[i][j]:表示底盘从起点到装配站S[i][j]的最快可能时间。

t[i][j]:表示底盘从装配站S[i][j]移到另一条装配线花费的时间。

a[i][j]:表示底盘在装配站S[i][j]停留的时间。

e[i]:表示底盘进入装配线i的时间。

x[i]:表示底盘完成安装离开装配线花费的时间。

3 问题分析

步骤1:通过工厂最快线路的结构

通过装配站S[1][j]的最快线路只能是以下二者之一:

(1) 通过装配站S[1][j-1]的最快线路,然后直接通过装配站S[1][j]。

(2) 通过装配站S[2][j-1]的最快线路,从装配线2移动到装配线1,然后通过装配站S[1][j]。

当然,通过装配站S[2][j]的最快线路也只能是以下二者之一:

(1) 通过装配站S[2][j-1]的最快线路,然后直接通过装配站S[2][j]。

(2) 通过装配站S[1][j-1]的最快线路,从装配线1移动到装配线2,然后通过装配站S[1][j]。

为了解决装配线调度问题,即寻找通过任意一条装配线上的第j个装配站的最快路线,就可以解决装配线调度问题。

步骤2:一个递归的解

假设已经完成了汽车的装配,那么这些路线的较快者即是:

fast =min{f[1]
+ x[1], f[2]
+ x[2]};

初值为:

f[1][1] =e[1] + a[1][1];

f[2][1] =e[2] + a[2][1];

考虑f[i][j](j>1)的计算,很明显:

f[1][j] =min{f[1][j-2] + a[1][j], f[2][j-1] + t[2][j-1] + a[2][j]};

f[2][j] =min{f[2][j-2] + a[2][j], f[1][j-1] + t[1][j-1] + a[1][j]};

步骤3:计算最快时间

整个过程花费时间为O(n);

步骤4:构造通过工厂的最快路线

为了构造通过工厂的最快路线,需要构造一个新的数组l[i][j],其值为(1或者2),表示装配线编号,装配站j-1被通过S[i][j]的最快路线所使用。

4 实例与编码

1. 实例

e[1]=2, e[2]=4;

x[1]=3; x[2]=2;

a[i][j]的值如下表:

j

1

2

3

4

5

6

a[1][j]

7

9

3

4

8

4

a[2][j]

8

5

6

4

5

7

t[i][j]的值如下表:

j

1

2

3

4

5

t[1][j]

2

3

1

3

4

t[2][j]

2

1

2

2

1

2. 编码实现

针对具体问题的实现代码

/**
* fastway - 求解装配线最快线路的时间
* Param.:
*      @a[][]: 在装配线i上第j个装配站停留的时间(i=0,1;j=0...(n-1))
*      @t[][]: 从装配线i上第j-1个装配站移动到另一个装配线的时间
*      @e[]:   进入装配线i的时间
*      @x[]:   在装配线i上最后一个装配站离开的时间
*      @n:     装配站的个数
*      @f[][]: 经过装配线i上第j个装配站时的最快时间(被赋值)
*      @flag[][]: 通过装配站j的最快线路的装配站j-1所在的装配线(被赋值)
*      @fast: 最快线路的时间(被赋值)
*      @falg: 最快线路的最后一个装配站所在的装配线(被赋值)
* return:
*      无
*/
void fastway(int a[][6], int t[][5], int e[], int x[], int n,
int f[][6], int flag[][6], int *fastp, int *lastflagp)
{
int j, fast, lastflag;

f[0][0] = e[0] + a[0][0];
f[1][0] = e[1] + a[1][0];
for (j = 1; j < n; j++)
{
/* 计算f[0][j]和flag[0][j] */
if ((f[0][j - 1] + a[0][j]) <= (f[1][j - 1] + t[1][j - 1] + a[0][j]))
{
f[0][j] = f[0][j - 1] + a[0][j];
flag[0][j] = 0;
}
else
{
f[0][j] = f[1][j - 1] + t[1][j - 1] + a[0][j];
flag[0][j] = 1;
}
/* 计算f[1][j]和flag[1][j] */
if ((f[1][j - 1] + a[1][j]) <= (f[0][j - 1] + t[0][j - 1] + a[1][j]))
{
f[1][j] = f[1][j - 1] + a[1][j];
flag[1][j] = 1;
}
else
{
f[1][j] = f[0][j - 1] + t[0][j - 1] + a[1][j];
flag[1][j] = 0;
}
}

/* 计算最优解fast和flag(表示从哪个装配线上的n装配站完成) */
if ((f[0][n - 1] + x[0]) <= (f[1][n - 1] + x[1]))
{
fast = f[0][n - 1] + x[0];
lastflag = 0;
}
else
{
fast = f[1][n - 1] + x[1];
lastflag = 1;
}

*fastp = fast;
*lastflagp = lastflag;
}
/**
* printway - 求解装配线最快线路的时间
* Param.:
*      @flag[][]: 通过装配站j的最快线路的装配站j-1所在的装配线(被赋值)
*      @falg: 最快线路的最后一个装配站所在的装配线(被赋值)
*      @n:     装配站的个数
* return:
*      无
*/
void printway(int flag[][6], int *lastflagp, int n)
{
int i, j;
i = *lastflagp;
printf("line:%d, station:%d\n", i, n);
for (j = n; j >= 1; j--)
{
i = flag[i][j];
printf("line:%d, stations:%d\n", i, (j - 1));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: