1632
правки
Изменения
м
Следующий ==Описание алгоритма==Для решения задачи применим следующий алгоритм решает эту задачу:
Мы предполагаемПредположим, что <tex>d_i \geqslant 0</tex> для <tex>i = 1,\ldots,n</tex> и хотя бы для одной работы <tex>i</tex> : <tex>d_i = 0</tex>. Иначе, вычтем из всех <tex>d_i</tex> минимальное значение по <tex>d_i</tex>.
Так как Заметим, что <tex>\forall</tex> <tex>i = 1,\ldots,n</tex>: <tex>C_i \geqslant 1</tex> для всех и <tex>\exists</tex> <tex>i = 1,\ldots,n</tex> и : <tex>d_i = 0</tex> справедливо . Поэтому <tex>L_i = C_i - d_i \geqslant 1</tex> как минимум для одной работы <tex>i</tex>. К тому же, можно предположить, что <tex>C_i \leqslant r</tex>. Таким образом, работы с <tex>d_i > r - 1</tex>, то есть c <tex>L_i = C_i - d_i < 1</tex>, можно смело игнорировать. Они не влияют на значение улучшаемой функции <tex>\max(L_i)</tex>, так как для некого <tex>i</tex> : <tex>L_i \geqslant 1</tex> можно выполнять эти работы в любом порядке после всех остальных. Для оставшихся операций <tex>O_{ij}</tex> мы имеем:
Каждую Для того, чтобы найти расписание, соответствующее списку всех операций <tex>L</tex>, выполним следующие шаги:*на первом шаге каждую операцию мы кладём в соответствующий [[список]] (на самом деле это должна быть [[Двоичная куча|куча]] (англ. ''heap'') для хорошей асимптотики) <tex>L(k)</tex>, где <tex>k = l(O_{ij}) = d_i - n_i + j</tex> <tex>(-r + 1 \leqslant k \leqslant r - 1)</tex>. На ; *на втором шаге мы планируем операции соответственно возрастающему по номеру списка <tex>k</tex> порядку, где операции из одного списка могут выполнятся в произвольном порядке.
Z = <tex>\emptyset</tex>
Очевидно==Асимптотика==Суммарное количество операций равно <tex>r</tex>. Первый шаг алгоритма занимает <tex>O(r)</tex>, так как каждая операция добавляется либо в <tex>L</tex>, либо в <tex>Z</tex>. На втором шаге каждая операция назначается единожды, то есть на втором шаге также выполняется <tex>O(r)</tex> действий. И, наконец, суммарное время всех вызовов функции <tex>\mathrm{schedule}</tex> также равно <tex>O(r)</tex>, что так как суммарное количество шагов итераций циклов внутри этой функции не превышает <tex>O(r)</tex>. Итого, время работы алгоритма ограничено <tex>O(r)</tex>.
rollbackEdits.php mass rollback
<tex dpi = "200">J2\mid p_{ij} = 1\mid L_{max}-</tex>
{{Задача
|definition=
Дано <tex>n</tex> работ <tex>i = 1,\ldots,n</tex> и две машины, обозначенные как <tex>A</tex> и <tex>B</tex>. <tex>i</tex>-тая работа состоит из <tex>n_i</tex> операций <tex>O_{ij}</tex> <tex>(j = 1,\ldots n_i)</tex>, которые должны быть выполнены последовательно и, при этом, если <tex>O_{ij} </tex> операция была совершена на машине<br><tex>A (B)</tex>, то операция <tex>O_{i,j-1}</tex> должна быть совершена на машине <tex>B (A)</tex>. Задача заключается в том, что для данного каждой <tex>i</tex>-той работе дедлайна <tex>d_i \geqslant 0</tex> необходимо найти достижимое расписание с наименьшими максимальным временем опоздания: <tex>\max\{C_i - d_i \mid i = 1, \ldots, n\}</tex>.
}}
Необходимо отметить, что рассматриваемая задача более узкая, чем следует из ее названия по нотации Грэхема: машины в последовательности операций должны чередоваться.==Описание решениязадачи==Судя по условиюИз условия следует, что <tex>i</tex>-тая работа может характеризоваться двумя значениями: количество числом операций <tex>n_i</tex> и машиной, на которой была совершена первая операция. Пусть <tex>r = \overset{n}{\underset{i=1}{\sum}}N_in_i</tex> {{---}} общее количество операций.
Допустим, самым ранним моментом, когда операция может начать выполняться, будет момент времени <tex>0</tex>, а верхнюю границу момента начала выполнения последней операции обозначим за <tex>t_{max}</tex>. К примеру, мы можем выбрать <tex>t_{max} = r</tex>. Тогда расписание можно представить как два списка <tex>A(t)</tex> и <tex>B(t)</tex> <tex>(t = 0,\ldots,t_{max})</tex>, где <tex>A(t) = O_{ij}</tex>, если операция <tex>O_{ij}</tex> должна выполниться на машине <tex>A</tex> в момент времени <tex>t</tex> и <tex>A(t) =</tex> <tex> \varnothing</tex>, если машина <tex>A</tex> простаивает в этот момент. И для каждой операции <tex>O_{ij}</tex>, выполняющейся на машине <tex>A</tex> существует <tex>t</tex>, для которого <tex>A(t) = O_{ij}</tex>. Аналогично для <tex>B_i</tex>. Расписание достижимо тогда и только тогда, когда из <tex>A(t) (B(t)) = O_{ij} , 1 < j \leqslant n_i</tex> следует <tex>O_{i,j-1} = B(s) (A(s))</tex> для некоторого <tex>s < t</tex>, и первая операция для каждой работы запланирована на нужной машине. Перестановку всех Обозначим некоторую перестановку операций будем называть спискомза <tex>L</tex>. Для данного списка <tex>L</tex> осуществимое расписание может быть создано следующим способом: планируем выполнять операции в порядке, соответствующем <tex>L</tex>, причем каждую операцию стараемся выполнить как можно раньше. Подобное расписание будем называть соответствующим <tex>L</tex> расписанием.
<tex>C_i</tex> {{---}} время окончания работы <tex>i</tex> в достижимом расписании <tex>y = (A(t), B(t))</tex> можно рассчитать как:
Задача заключается в том, что для данного каждой работе <tex>i</tex> дедлайна <tex>d_i \geqslant 0</tex> нужно найти достижимое расписание с наименьшим максимальным временем опоздания:
<tex>L_{\max} = \max\limits_{C_i - d_i \mid i = 1, ..n}\ldots, n{C_i - d_i\}</tex>
* введём для каждой операции <tex>O_{ij}</tex> величину <tex>l(O_{ij}) = d_i - n_i + j</tex>{{---}} максимальное время завершения <tex>O_{ij}</tex>, при котором работа будет завершена не позднее дедлайна, при условии, что остальные операции выполняются без задержек вслед за ней,
* создадим список всех операций <tex>L</tex>, упорядоченный в порядке неубывания значений <tex>l(O_{ij})</tex>,
* найдем соответствующее списку <tex>L</tex> расписание.
Этот алгоритм может быть реализован с асимптотикой <tex>O(r \log r)</tex>.
<tex>-r + 1 \leqslant l(O_{ij}) = d_i - n_i + j \leqslant r - 1</tex>
==Алгоритм==
Рассмотрим алгоритм. Пусть:
*<tex>\mathtt{T1}</tex> и <tex>\mathtt{T2}</tex> {{---}} первый период времени <tex>t \geqslant 0</tex>, когда соответствующие машины <tex>A</tex> и <tex>B</tex> бездействуют;
*<tex>\mathtt{LAST([i)]}</tex> {{---}} время окончания последней запланированной операции <tex>i</tex>-той работы;
*<tex>\mathtt{Z}</tex> {{---}} множество работ, где <tex>d_i \geqslant r</tex>.
'''function''' mainsolve(): <font color=darkgreen>// Шаг 1</font> <font color=darkgreen>// Инициализируем L и Z</font>
'''for''' k = -r + 1 '''to''' r - 1
<tex>L(k)</tex> = <tex>\emptyset</tex>
'''for''' i = 1 '''to''' n
'''if''' <tex>d_i</tex> < r
добавить работу i в Z
'''for''' i = 1 '''to''' n
LAST([i) ] = 0
T1 = 0
T2 = 0
<font color=darkgreen>// Шаг 2</font>
<font color=darkgreen>// Планируем операции соответственно возрастающему по номеру списка порядку</font>
'''for''' k = -r + 1 '''to''' r - 1
'''while''' <tex>L(k) \ne \emptyset</tex>
<tex>L(k)</tex> = <tex>L(k)\setminus\{O_{ij}\}</tex>
schedule(<tex>O_{ij}</tex>)
<font color=darkgreen>// Планируем операции, соответствующие работам с <tex color>d_i \geqslant r</tex></font>
'''while''' <tex>z \ne \emptyset</tex>
Выбрать работу i из Z
'''function''' schedule(<tex>O_{ij}</tex>):
t = 0
'''if''' <tex>\mu_{ij}</tex> == A
'''if''' T1 < LAST([i) ] t = LAST([i)] A(t) = <tex>O_{ij}</tex> <font color=darkgreen>// </font><tex> (*)</tex>
'''else'''
t = T1
T1 = T1 + 1
'''else'''
'''if''' T2 < LAST([i)] t = LAST([i)] B(t) = <tex>O_{ij}</tex> <font color=darkgreen>//</font> <tex> (**)</tex>
'''else'''
t = T2
'''while''' <tex>B(T_2) \ne \emptyset</tex>
T2 = T2 + 1
LAST([i) ] = t + 1
==Доказательство==
Для доказательства того, что алгоритм решения задачи корректен, необходимо показать то, что он строит достижимое расписание. Это справедливо тогда и только тогда, когда до исполнения строчек <tex>(*) </tex> и <tex>(**) </tex> пусты <tex>A(t) </tex> и <tex>B(t) </tex> соответственно. Иначе две разные операции будут выполняться в один момент времени на одной машине. Для того, чтобы показать достижимость докажем лемму.
{{Лемма
<tex> l(A(v)) \leqslant l(A(t)) </tex> <tex> for</tex> <tex> v = 1, . . . , t - 1</tex> и
<tex> l(A(0)) \leqslant l(A(t)) </tex> <tex> if </tex> <tex> A(0) \neq \emptyset</tex>.
<tex>(***)</tex>
Таким образом, в каждом расписании должно существовать, по крайней мере, одно опоздание, т.к. если <tex> A(0)\neq \emptyset</tex> то <tex> l(A(v)) < t + 1</tex> при <tex> v = 0, . . . , t</tex> и мы должны запланировать <tex> t + 1 </tex> операций во временном интервале <tex> [0, t] </tex>, что невозможно. Если же <tex> A(0) = \emptyset </tex>, то все задачи начинаются на машине <tex> B </tex> и <tex> t</tex> операций должны обрабатываться в интервале времени <tex> [1, t] </tex>, что тоже не возможно.
Для доказательства <tex>(***) </tex> заметим, что (***) верно, если <tex> A(t) </tex> является первой операцией для работы, так как если <tex> l(A(t)) < l(A(v)) </tex> при некоторых <tex>v = 0. . . , t - 1</tex>,
то алгоритм должен запланировать <tex> A(t) </tex> перед <tex> A(v) </tex>.
Теперь положим <tex> A(t) = O_{ij}</tex> для какого-нибудь <tex> i</tex> и <tex> j > 1</tex>.
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 180 {{---}} 186 стр. {{---}} ISBN 978-3-540-69515-8
[[Категория: Дискретная математика Алгоритмы и алгоритмыструктуры данных]]
[[Категория: Теория расписаний]]