劳勒算法实施协助
UPDATE2:
我想我现在明白了:
<?php
/*
* @name Lawler's algorithm PHP implementation
* @desc This algorithm calculates an optimal schedule of jobs to be
* processed on a single machine (in reversed order) while taking
* into consideration any precedence constraints.
* @author Richard Knop
*
*/
$jobs = array(1 => array('processingTime' => 2,
'dueDate' => 3),
2 => array('processingTime' => 3,
'dueDate' => 15),
3 => array('processingTime' => 4,
'dueDate' => 9),
4 => array('processingTime' => 3,
'dueDate' => 16),
5 => array('processingTime' => 5,
'dueDate' => 12),
6 => array('processingTime' => 7,
'dueDate' => 20),
7 => array('processingTime' => 5,
'dueDate' => 27),
8 => array('processingTime' => 6,
'dueDate' => 40),
9 => array('processingTime' => 3,
'dueDate' => 10));
// precedence constrainst, i.e job 2 must be completed before job 5 etc
$successors = array(2=>5,
7=>9);
$n = count($jobs);
$optimalSchedule = array();
for ($i = $n; $i >= 1; $i--) {
// jobs not required to precede any other job
$arr = array();
foreach ($jobs as $k => $v) {
if (false === array_key_exists($k, $successors)) {
$arr[] = $k;
}
}
// calculate total processing time
$totalProcessingTime = 0;
foreach ($jobs as $k => $v) {
if (true === array_key_exists($k, $arr)) {
$totalProcessingTime += $v['processingTime'];
}
}
// find the job that will go to the end of the optimal schedule array
$min = null;
$x = 0;
$lastKey = null;
foreach($arr as $k) {
$x = $totalProcessingTime - $jobs[$k]['dueDate'];
if (null === $min || $x < $min) {
$min = $x;
$lastKey = $k;
}
}
// add the job to the optimal schedule array
$optimalSchedule[$lastKey] = $jobs[$lastKey];
// remove job from the jobs array
unset($jobs[$lastKey]);
// remove precedence constraint from the successors array if needed
if (true === in_array($lastKey, $successors)) {
foreach ($successors as $k => $v) {
if ($lastKey === $v) {
unset($successors[$k]);
}
}
}
}
// reverse the optimal schedule array and preserve keys
$optimalSchedule = array_reverse($optimalSchedule, true);
// add tardiness to the array
$i = 0;
foreach ($optimalSchedule as $k => $v) {
$optimalSchedule[$k]['tardiness'] = 0;
$j = 0;
foreach ($optimalSchedule as $k2 => $v2) {
if ($j <= $i) {
$optimalSchedule[$k]['tardiness'] += $v2['processingTime'];
}
$j++;
}
$i++;
}
echo '<pre>';
print_r($optimalSchedule);
echo '</pre>';
更新:
所以这里有一些更多的资料来源,其中包含我发现的劳勒算法的解释:
这是我在 PHP 中实现的 Lawler 算法(我知道...但我已经习惯了):
<?php
$jobs = array(1, 2, 3, 4, 5, 6);
$jobsSubset = array(2, 5, 6);
$n = count($jobs);
$processingTimes = array(2, 3, 4, 3, 2, 1);
$dueDates = array(3, 15, 9, 7, 11, 20);
$optimalSchedule = array();
foreach ($jobs as $j) {
$optimalSchedule[] = 0;
}
$dicreasedCardinality = array();
for ($i = $n; $i >= 1; $i--) {
$x = 0;
$max = 0;
// loop through all jobs
for ($j = 0; $j < $i; $j++) {
// ignore if $j already is in the $dicreasedCardinality array
if (false === in_array($j, $dicreasedCardinality)) {
// if the job has no succesor in $jobsSubset
if (false === isset($jobs[$j+1])
|| false === in_array($jobs[$j+1], $jobsSubset)) {
// here I find an array index of a job with the maximum due date
// amongst jobs with no sucessor in $jobsSubset
if ($x < $dueDates[$j]) {
$x = $dueDates[$j];
$max = $j;
}
}
}
}
// move the job at the end of $optimalSchedule
$optimalSchedule[$i-1] = $jobs[$max];
// decrease the cardinality of $jobs
$dicreasedCardinality[] = $max;
}
print_r($optimalSchedule);
现在上面返回了一个像这样的最佳时间表:
Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 3
[4] => 2
[5] => 6
)
这对我来说似乎不正确。问题可能出在我对算法的实现上,因为我不确定我是否正确理解它。我使用了 这个 源来实现它。
那里的描述有点混乱。例如,我不太明白子集 D 是如何定义的(我猜它是任意的)。
有人能帮我解决这个问题吗?我一直在尝试寻找一些对算法有更简单解释的来源,但我发现的所有来源都更加复杂(带有数学证明等),所以我被上面的链接困住了。
是的,这是一项作业,如果它不明显的话。
我还有几周的时间来解决这个问题,但我已经花了几天的时间试图了解这个算法到底是如何工作的,但没有成功,所以我认为在那段时间我不会变得更聪明。
UPDATE2:
I think I got it now:
<?php
/*
* @name Lawler's algorithm PHP implementation
* @desc This algorithm calculates an optimal schedule of jobs to be
* processed on a single machine (in reversed order) while taking
* into consideration any precedence constraints.
* @author Richard Knop
*
*/
$jobs = array(1 => array('processingTime' => 2,
'dueDate' => 3),
2 => array('processingTime' => 3,
'dueDate' => 15),
3 => array('processingTime' => 4,
'dueDate' => 9),
4 => array('processingTime' => 3,
'dueDate' => 16),
5 => array('processingTime' => 5,
'dueDate' => 12),
6 => array('processingTime' => 7,
'dueDate' => 20),
7 => array('processingTime' => 5,
'dueDate' => 27),
8 => array('processingTime' => 6,
'dueDate' => 40),
9 => array('processingTime' => 3,
'dueDate' => 10));
// precedence constrainst, i.e job 2 must be completed before job 5 etc
$successors = array(2=>5,
7=>9);
$n = count($jobs);
$optimalSchedule = array();
for ($i = $n; $i >= 1; $i--) {
// jobs not required to precede any other job
$arr = array();
foreach ($jobs as $k => $v) {
if (false === array_key_exists($k, $successors)) {
$arr[] = $k;
}
}
// calculate total processing time
$totalProcessingTime = 0;
foreach ($jobs as $k => $v) {
if (true === array_key_exists($k, $arr)) {
$totalProcessingTime += $v['processingTime'];
}
}
// find the job that will go to the end of the optimal schedule array
$min = null;
$x = 0;
$lastKey = null;
foreach($arr as $k) {
$x = $totalProcessingTime - $jobs[$k]['dueDate'];
if (null === $min || $x < $min) {
$min = $x;
$lastKey = $k;
}
}
// add the job to the optimal schedule array
$optimalSchedule[$lastKey] = $jobs[$lastKey];
// remove job from the jobs array
unset($jobs[$lastKey]);
// remove precedence constraint from the successors array if needed
if (true === in_array($lastKey, $successors)) {
foreach ($successors as $k => $v) {
if ($lastKey === $v) {
unset($successors[$k]);
}
}
}
}
// reverse the optimal schedule array and preserve keys
$optimalSchedule = array_reverse($optimalSchedule, true);
// add tardiness to the array
$i = 0;
foreach ($optimalSchedule as $k => $v) {
$optimalSchedule[$k]['tardiness'] = 0;
$j = 0;
foreach ($optimalSchedule as $k2 => $v2) {
if ($j <= $i) {
$optimalSchedule[$k]['tardiness'] += $v2['processingTime'];
}
$j++;
}
$i++;
}
echo '<pre>';
print_r($optimalSchedule);
echo '</pre>';
UPDATE:
So here are some more sources with the explanation of Lawler's algorithm I found:
- Source 1
- Source 2
- Source 3 (this is a really good source but one crucial page is missing in the preview + this book is not available at amazon or anywhere else bacause it is limited to China - if it were I would have bought it already)
Here is my implemenation of Lawler's algorithm in PHP (I know... but I'm used to it):
<?php
$jobs = array(1, 2, 3, 4, 5, 6);
$jobsSubset = array(2, 5, 6);
$n = count($jobs);
$processingTimes = array(2, 3, 4, 3, 2, 1);
$dueDates = array(3, 15, 9, 7, 11, 20);
$optimalSchedule = array();
foreach ($jobs as $j) {
$optimalSchedule[] = 0;
}
$dicreasedCardinality = array();
for ($i = $n; $i >= 1; $i--) {
$x = 0;
$max = 0;
// loop through all jobs
for ($j = 0; $j < $i; $j++) {
// ignore if $j already is in the $dicreasedCardinality array
if (false === in_array($j, $dicreasedCardinality)) {
// if the job has no succesor in $jobsSubset
if (false === isset($jobs[$j+1])
|| false === in_array($jobs[$j+1], $jobsSubset)) {
// here I find an array index of a job with the maximum due date
// amongst jobs with no sucessor in $jobsSubset
if ($x < $dueDates[$j]) {
$x = $dueDates[$j];
$max = $j;
}
}
}
}
// move the job at the end of $optimalSchedule
$optimalSchedule[$i-1] = $jobs[$max];
// decrease the cardinality of $jobs
$dicreasedCardinality[] = $max;
}
print_r($optimalSchedule);
Now the above returns an optimal schedule like this:
Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 3
[4] => 2
[5] => 6
)
Which doesn't seem right to me. The problem might be with my implementation of the algorithm because I am not sure I understand it correctly. I used this source to implement it.
The description there is a little confusing. For example, I didn't quite get how is the subset D defined (I guess it is arbitrary).
Could anyone help me out with this? I have been trying to find some sources with simpler explanation of the algorithm but all sources I found were even more complicated (with math proofs and such) so I am stuck with the link above.
Yes, this is a homework, if it wasn't obvious.
I still have few weeks to crack this but I have spent few days already trying to get how exactly this algorithm works with no success so I don't think I will get any brighter during that time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据您的链接源,Lawler 的算法将一组形式为“作业
i
必须在作业j
之前安排”的约束作为输入(指定为关系prec
),这似乎没有出现在您的代码中。如果您可以按任何顺序安排作业,那么劳勒算法专门用于更简单的最早截止日期优先算法(一行描述:按照截止日期递增的顺序对作业进行排序)。编辑:让我更具体一些。最初集合
D
是所有作业。 Lawler 反复在D
中查找截止日期最晚的作业i
,但受限于D
中没有其他作业j
code> 必须安排在i
之后(即i
在D
中没有后继者),并从其中删除i
D
。作业按照与移除相反的顺序进行安排。如果没有优先级约束,那么这就是 EDF。According to your linked source, Lawler's algorithm takes as input a set of constraints of the form "job
i
must be scheduled before jobj
" (specified as a relationprec
), which seems not to be featured in your code. If you can schedule the jobs in any order, then Lawler's algorithm specializes to the simpler Earliest Deadline First algorithm (one line description: sort the jobs in order of increasing deadline).EDIT: let me be more specific. Initially the set
D
is all jobs. Lawler repeatedly finds the jobi
inD
with the latest deadline, subject to the constraint that no other jobj
inD
must be scheduled afteri
(i.e.,i
has no successors inD
), and removesi
fromD
. The jobs are scheduled in reverse order of removal. If there are no precedence constraints, then this is just EDF.