J2pij1Lmax — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм)
Строка 41: Строка 41:
 
Давайте детально рассмотрим алгоритм. <tex>T1</tex> и <tex>T2</tex> обозначают первый период времени <tex>t \ge 0</tex>, когда соответствующие машины <tex>A</tex> и <tex>B</tex> бездействуют. <tex>LAST(i)</tex> обозначает время окончания последней запланированной операции <tex>i</tex>-той работы. <tex>Z</tex> {{---}} множество работ, где <tex>d_i \ge r</tex>  
 
Давайте детально рассмотрим алгоритм. <tex>T1</tex> и <tex>T2</tex> обозначают первый период времени <tex>t \ge 0</tex>, когда соответствующие машины <tex>A</tex> и <tex>B</tex> бездействуют. <tex>LAST(i)</tex> обозначает время окончания последней запланированной операции <tex>i</tex>-той работы. <tex>Z</tex> {{---}} множество работ, где <tex>d_i \ge r</tex>  
  
  '''main()'''
+
  '''function''' main():
   '''for''' k: -r + 1 '''to''' r - 1
+
   '''for''' k = -r + 1 '''to''' r - 1
     <tex>L(k)</tex> = <tex>\emptyset</tex>;
+
     <tex>L(k)</tex> = <tex>\emptyset</tex>
     Z = <tex>\emptyset</tex>;
+
     Z = <tex>\emptyset</tex>
   '''for''' i: 1 '''to''' n
+
   '''for''' i = 1 '''to''' n
 
     '''if''' <tex>d_i</tex> < r
 
     '''if''' <tex>d_i</tex> < r
       '''for''' j: 1 '''to''' n_i
+
       '''for''' j = 1 '''to''' <tex>n_i</tex>
 
         добавить <tex>O_{ij}</tex> в <tex>L(d_i - n_i + j)</tex>
 
         добавить <tex>O_{ij}</tex> в <tex>L(d_i - n_i + j)</tex>
 
     '''else'''
 
     '''else'''
 
       добавить работу i в Z
 
       добавить работу i в Z
   '''for''' i: 1 '''to''' n
+
   '''for''' i = 1 '''to''' n
     LAST(i) = 0;
+
     LAST(i) = 0
   T1 = 0;
+
   T1 = 0
   T2 = 0;
+
   T2 = 0
   '''for''' k: -r + 1 '''to''' r - 1
+
   '''for''' k = -r + 1 '''to''' r - 1
 
     '''while''' <tex>L(k) \ne \emptyset</tex>
 
     '''while''' <tex>L(k) \ne \emptyset</tex>
 
       Выбрать задание <tex>O_{ij}</tex> из <tex>L(k)</tex>
 
       Выбрать задание <tex>O_{ij}</tex> из <tex>L(k)</tex>
       <tex>L(k)</tex> = <tex>L(k)\setminus\{O_{ij}\}</tex>;
+
       <tex>L(k)</tex> = <tex>L(k)\setminus\{O_{ij}\}</tex>
 
       schedule(<tex>O_{ij}</tex>)  
 
       schedule(<tex>O_{ij}</tex>)  
 
   '''while''' <tex>z \ne \emptyset</tex>
 
   '''while''' <tex>z \ne \emptyset</tex>
 
     Выбрать работу i из Z
 
     Выбрать работу i из Z
 
     Z = <tex>Z \setminus\{i\}</tex>;
 
     Z = <tex>Z \setminus\{i\}</tex>;
     '''for''' j: 1 '''to''' <tex>n_i</tex>
+
     '''for''' j = 1 '''to''' <tex>n_i</tex>
 
       schedule(<tex>O_{ij}</tex>)
 
       schedule(<tex>O_{ij}</tex>)
  
  '''schedule(<tex>O_{ij}</tex>)'''
+
  '''function''' schedule(<tex>O_{ij}</tex>):
 
   '''if''' <tex>\mu_{ij}</tex> == A
 
   '''if''' <tex>\mu_{ij}</tex> == A
 
     '''if''' T1 < LAST(i)  
 
     '''if''' T1 < LAST(i)  
Строка 72: Строка 72:
 
       A(t) = <tex>O_{ij}</tex> (*)
 
       A(t) = <tex>O_{ij}</tex> (*)
 
     '''else'''
 
     '''else'''
       t = T1;
+
       t = T1
       A(t) = <tex>O_{ij}</tex>;
+
       A(t) = <tex>O_{ij}</tex>
 
       '''while''' <tex>A(T_1)</tex> <tex>\ne \emptyset</tex>
 
       '''while''' <tex>A(T_1)</tex> <tex>\ne \emptyset</tex>
         T1 = T1 + 1;
+
         T1 = T1 + 1
 
   '''else'''
 
   '''else'''
 
     '''if''' T2 < LAST(i)
 
     '''if''' T2 < LAST(i)
Строка 81: Строка 81:
 
       B(t) = <tex>O_{ij}</tex> (**)
 
       B(t) = <tex>O_{ij}</tex> (**)
 
     '''else'''
 
     '''else'''
       t = T2;
+
       t = T2
       A(t) = <tex>O_{ij}</tex>;
+
       A(t) = <tex>O_{ij}</tex>
 
       '''while''' <tex>B(T_2) \ne \emptyset</tex>
 
       '''while''' <tex>B(T_2) \ne \emptyset</tex>
         T2 = T2 + 1;
+
         T2 = T2 + 1
 
   LAST(i) = t + 1
 
   LAST(i) = t + 1
  

Версия 22:48, 11 мая 2016

Условие задачи

В нотации Грэхема задача носит название [math]J2\mid p_{ij} = 1\mid L_{max}[/math]

Дано [math]n[/math] работ [math]i = 1,\ldots,n[/math] и две машины, обозначенные как [math]A[/math] и [math]B[/math].

[math]i[/math]-тая работа состоит из [math]n_i[/math] операций [math]O_{ij}[/math] [math](j = 1,\ldots n_i)[/math], которые должны быть выполнены последовательно и, при этом, если [math]O_{ij} [/math] операция была совершена на машине [math]A (B)[/math], то операция [math]O_{i,j-1}[/math] должна быть совершена на машине [math]B (A)[/math].

Задача заключается в том, что для данного каждой [math]i[/math]-той работе дедлайна [math]d_i \ge 0[/math] необходимо найти достижимое расписание с наименьшими максимальным временем опоздания:

[math]\max\{C_i - d_i | i = 1, \ldots, n\}[/math]

Описание решения

Судя по условию, [math]i[/math]-тая работа может характеризоваться двумя значениями: количество операций [math]n_i[/math] и машиной, на которой была совершена первая операция. Пусть [math]r = \sum_{i=1}^n N_i[/math] — общее количество операций.

Допустим, самым ранним моментом, когда операция может начать выполняться, будет момент времени 0, а верхнюю границу момента начала выполнения последней операции обозначим за [math]t_{max}[/math]. К примеру, мы можем выбрать [math]t_{max} = r[/math]. Тогда расписание можно представить как два списка [math]A(t)[/math] и [math]B(t) (t = 0,\ldots,t_{max})[/math], где [math]A(t) = O_{ij}[/math], если операция [math]O_{ij}[/math] должна выполниться на машине [math]A[/math] в момент времени [math]t[/math] и [math]A(t) =[/math] [math] \varnothing[/math], если машина [math]A[/math] простаивает в этот момент. И для каждой операции [math]O_{ij}[/math], выполняющейся на машине [math]A[/math] существует [math]t[/math], для которого [math]A(t) = O_{ij}[/math]. Аналогично для [math]B_i[/math]. Расписание достижимо тогда и только тогда, когда из [math]A(t) (B(t)) = O_{ij} , 1 \lt j \leqslant n_i[/math] следует [math]O_{i,j-1} = B(s) (A(s))[/math] для некоторого [math]s \lt t[/math], и первая операция для каждой работы запланирована на нужной машине. Перестановку всех операций будем называть списком. Для данного списка [math]L[/math] осуществимое расписание может быть создано следующим способом: планируем выполнять операции в порядке, соответствующим [math]L[/math], причем каждую операцию стараемся выполнить как можно раньше. Подобное расписание будем называть соответствующим [math]L[/math] расписанием. [math]C_i[/math] — время окончания работы [math]i[/math] в достижимом расписании [math]y = (A(t), B(t))[/math] можно рассчитать как:

[math]C_i = \max\{t + 1 | A(t)\}[/math] или [math]B(t)[/math] — операция [math]i[/math]-той работы}

Задача заключается в том, что для данного каждой работе [math]i[/math] дедлайна [math]d_i \geqslant 0[/math] мы хотим найти достижимое расписание с наименьшими максимальным временем опоздания:

[math]\max\{C_i - d_i | i = 1, \ldots, n\}[/math]

Следующий алгоритм решает эту задачу:

  • Введём для каждой операции [math]O_{ij}[/math] величину [math]l(O_{ij}) = d_i - n_i + j[/math]
  • Создадим список всех операций [math]L[/math], упорядоченный в порядке неубывания значений [math]l(O_{ij})[/math]
  • Найдем соответствующее списку [math]L[/math] расписание.

Этот алгоритм может быть реализованным с асимптотикой [math]O(r \log r)[/math].

Мы предполагаем, что [math]d_i \geqslant 0[/math] для [math]i = 1,\ldots,n[/math] и хотя бы для одной работы [math]i[/math] [math]d_i = 0[/math]. Иначе, вычтем из всех [math]d_i[/math] минимальное значение по [math]d_i[/math].

Так как [math]C_i \geqslant 1[/math] для всех [math]i = 1,\ldots,n[/math] и [math]d_i = 0[/math] справедливо [math]L_i = C_i - d_i \geqslant 1[/math] как минимум для одной работы [math]i[/math]. К тому же, можно предположить, что [math]C_i \leqslant r[/math]. Таким образом, работы с [math]d_i \gt r - 1[/math], то есть c [math]L_i = C_i - d_i \lt 1[/math], можно смело игнорировать. Они не влияют на значение улучшаемой функции [math]\max(L_i)[/math], так как для некого [math]i[/math] [math]L_i \geqslant 1[/math] можно выполнять эти работы в любом порядке после всех остальных. Для оставшихся операций [math]O_{ij}[/math] мы имеем:

[math]-r + 1 \leqslant l(O_{ij}) = d_i - n_i + j \leqslant r - 1[/math]

Каждую операцию мы кладём в соответствующий список (на самом деле это должен быть heap для хорошей асимптотики) [math]L(k)[/math], где [math]k = l(O_{ij}) = d_i - n_i + j[/math] [math](-r + 1 \leqslant k \leqslant r - 1)[/math]. На втором шаге мы планируем операции соответственно возрастающему по номеру списка [math]k[/math] порядку, где операции из одного списка могут выполнятся в произвольном порядке.

Алгоритм

Давайте детально рассмотрим алгоритм. [math]T1[/math] и [math]T2[/math] обозначают первый период времени [math]t \ge 0[/math], когда соответствующие машины [math]A[/math] и [math]B[/math] бездействуют. [math]LAST(i)[/math] обозначает время окончания последней запланированной операции [math]i[/math]-той работы. [math]Z[/math] — множество работ, где [math]d_i \ge r[/math]

function main():
  for k = -r + 1 to r - 1
    [math]L(k)[/math] = [math]\emptyset[/math]
    Z = [math]\emptyset[/math]
  for i = 1 to n
    if [math]d_i[/math] < r
      for j = 1 to [math]n_i[/math]
        добавить [math]O_{ij}[/math] в [math]L(d_i - n_i + j)[/math]
    else
      добавить работу i в Z
  for i = 1 to n
    LAST(i) = 0
  T1 = 0
  T2 = 0
  for k = -r + 1 to r - 1
    while [math]L(k) \ne \emptyset[/math]
      Выбрать задание [math]O_{ij}[/math] из [math]L(k)[/math]
      [math]L(k)[/math] = [math]L(k)\setminus\{O_{ij}\}[/math]
      schedule([math]O_{ij}[/math]) 
  while [math]z \ne \emptyset[/math]
    Выбрать работу i из Z
    Z = [math]Z \setminus\{i\}[/math];
    for j = 1 to [math]n_i[/math]
      schedule([math]O_{ij}[/math]) 	
function schedule([math]O_{ij}[/math]):
  if [math]\mu_{ij}[/math] == A
    if T1 < LAST(i) 
      t = LAST(i)
      A(t) = [math]O_{ij}[/math] (*)
    else
      t = T1
      A(t) = [math]O_{ij}[/math]
      while [math]A(T_1)[/math] [math]\ne \emptyset[/math]
        T1 = T1 + 1
  else
    if T2 < LAST(i)
      t = LAST(i)
      B(t) = [math]O_{ij}[/math] (**)
    else
      t = T2
      A(t) = [math]O_{ij}[/math]
      while [math]B(T_2) \ne \emptyset[/math]
        T2 = T2 + 1
  LAST(i) = t + 1

Очевидно, что количество шагов алгоритма ограничено [math]O(r)[/math]

Доказательство

Для доказательства того, что алгоритм решения задачи корректен, необходимо показать то, что он строит достижимое расписание. Это справедливо тогда и только тогда, когда до исполнения строчек (*) и (**) пусты A(t) и B(t) соответственно. Иначе две разные операции будут выполняться в один момент времени на одной машине. Для того, чтобы показать достижимость докажем лемму.

Лемма:
Пусть [math]Y = (A(t), B(t))[/math] — расписание, где [math]B(t) = \emptyset[/math] [math](A(t) = \emptyset)[/math]. Тогда для каждого [math]s \gt t[/math], где [math]B(s) = O_{ij}[/math] [math](A(s) = O_{ij})[/math] выполняется [math]A(s -1) = O_{i, j - 1}[/math] [math](B(s - 1) = O_{i, j -1}))[/math]
Доказательство:
[math]\triangleright[/math]

Докажем по индукции по [math]s[/math], что если [math]B(s) = O_{ij}[/math] и [math]s \gt t[/math], то [math]A(s -1) = O_{i, j - 1}[/math]. Это, очевидно, верно при [math]s = t+1[/math] так как если [math]B(t+1) = O_{ij}[/math] и [math]A(t)[/math] не соответствует работе [math]i[/math], то [math]B(t) = \emptyset[/math] означает что операция [math]O_{ij}[/math] должна быть запланирована в расписании ранее.

Предположим теперь что лемма верна для всех [math]v[/math] при [math]t \lt v \lt s[/math] и [math]B(s) = O_{ij}[/math] . Выберем максимальное [math]l[/math], такое что [math]t \lt l \lt s[/math] и [math]B(l) = \emptyset[/math]. По предположению индукции, [math]A(v- −1)[/math] и [math]B(v)[/math] соответствуют одной и той же работе для [math]v = l + 1,...,s —- 1[/math]. Пусть [math]A(s - 1[/math]) не соответствует работе [math]i[/math]. Тогда для каждого [math] v \in\{l, l + 1, . . . , s - 1\}[/math] операция [math]A(v)[/math] не соответствует работе [math]i[/math]. Таким образом, [math]O_{ij}[/math] может быть обработан в момент [math]l[/math], что противоречит тому, что [math]Y[/math] является расписанием.
[math]\triangleleft[/math]
Теорема:
Пусть [math]O_{ij}[/math] — операция, которую планируют строчкой (*) или (**) и [math]t = LAST(i) \gt T1(T2)[/math]. Тогда [math]A(t) = \emptyset[/math] [math](B(t) = \emptyset)[/math]
Доказательство:
[math]\triangleright[/math]
Предположим что [math] A(t) \neq \emptyset[/math] [math] (B(t) \neq \emptyset)[/math]. Поскольку [math] A(T1) = \emptyset[/math] [math] (B(T2) = \emptyset )[/math], из предыдущей леммы следует, что [math] A(t) [/math] и [math] B(t-1) [/math] [math] (B(t) [/math] и [math] A(t-1)) [/math] являются операциями одной и той же задачи [math] k[/math]. Так как [math] LAST (i)= t[/math], у нас должно быть значение [math] k \neq i[/math]. Это невозможно, т.к. при [math] LAST (i) = t[/math] и [math] \mu_{ij} = A(\mu_{ij} = B) [/math] , [math] B(t - 1) = O_{i,j-1}[/math] [math](A(t - 1) = O_{i,j-1})[/math].
[math]\triangleleft[/math]
Лемма:
Если существует расписание без опозданий, то данный алгоритм построит расписание без опозданий.
Доказательство:
[math]\triangleright[/math]
Эта статья находится в разработке!
[math]\triangleleft[/math]
Теорема:
Расписание, построенное данным алгоритмом, оптимально.
Доказательство:
[math]\triangleright[/math]
Эта статья находится в разработке!
[math]\triangleleft[/math]

См. также.

Источники информации

  • Peter Brucker. «Scheduling Algorithms» — «Springer», 2006 г. — 180 стр. — ISBN 978-3-540-69515-8