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

Материал из Викиконспекты
Перейти к: навигация, поиск
м
м (rollbackEdits.php mass rollback)
 
(не показаны 4 промежуточные версии 2 участников)
Строка 14: Строка 14:
 
<li> Пока множество <tex> X </tex> не пусто, распределяем работы по спискам следующим образом:
 
<li> Пока множество <tex> X </tex> не пусто, распределяем работы по спискам следующим образом:
 
<ul>
 
<ul>
<li> находим такие индексы <tex> i </tex> и <tex> j </tex>, что  <tex>p_{ij} = \min \{ p_{ij}  \mid i \in X; j = 1, 2\}</tex>, </li>
+
<li> находим такие индексы <tex> i </tex> и <tex> j </tex>, что  <tex>p_{ij} = \min \{ p_{ij}  \mid i \in X \land j = 1, 2\}</tex>, </li>
 
<li>если минимум достигается на первом станке (иными словами <tex> j = 1 </tex>), то поставим работу <tex> i </tex> в конец  списка <tex> L </tex>, иначе ставим в начало списка <tex> R </tex>,  </li>
 
<li>если минимум достигается на первом станке (иными словами <tex> j = 1 </tex>), то поставим работу <tex> i </tex> в конец  списка <tex> L </tex>, иначе ставим в начало списка <tex> R </tex>,  </li>
 
<li>удаляем работу <tex> i </tex> из множества <tex> X </tex>. </li>
 
<li>удаляем работу <tex> i </tex> из множества <tex> X </tex>. </li>
 
</ul>
 
</ul>
 
</li>
 
</li>
<li> Рассмотрим список <tex> T = L + R</tex> - конкатенацию <tex> L</tex> и <tex>R</tex>. Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы. </li>
+
<li> Рассмотрим список <tex> T = L ~\texttt{++}~ R</tex> {{---}} конкатенацию <tex> L</tex> и <tex>R</tex>. Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы. </li>
  
 
</ol>
 
</ol>
Строка 31: Строка 31:
 
[[Файл:f2cmax_first_fixed.png|400px|thumb|right|Рис. 1]]
 
[[Файл:f2cmax_first_fixed.png|400px|thumb|right|Рис. 1]]
 
Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках.  
 
Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках.  
Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна <tex> k </tex>, где <tex> k < n </tex>. Пусть на <tex> k </tex> позиции на первом и втором станках стоит работа <tex> i </tex>, а на втором станке на позиции <tex> k + 1 </tex> стоит работа <tex> j </tex>. Тогда заметим, что если мы поставим работу <tex> j </tex> на первом станке сразу после работы <tex> i </tex>, то последовательные работы с <tex> h </tex> по <tex> m </tex> (см. Рис. 1) по-прежнему будут успевать выполниться, так как на втором станке они выполняются в текущем расписании после <tex> j </tex>. Таким образом нам удалось увеличить длину наибольшего общего префикса, а так как по нашему предположению она была максимальна, то наше предположение неверно, то искомое расписание с одинаковым порядком выполнения работ на обоих станках существует.
+
Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна <tex> k </tex>, где <tex> k < n </tex>. Пусть на <tex> k </tex> позиции на первом и втором станках стоит работа <tex> i </tex>, а на втором станке на позиции <tex> k + 1 </tex> стоит работа <tex> j </tex>. Тогда заметим, что если мы поставим работу <tex> j </tex> на первом станке сразу после работы <tex> i </tex>, то последовательные работы с <tex> h </tex> по <tex> m </tex> (см. рис. 1) по-прежнему будут успевать выполниться, так как на втором станке они выполняются в текущем расписании после <tex> j </tex>. Таким образом нам удалось увеличить длину наибольшего общего префикса, а так как по нашему предположению она была максимальна, то предположение неверно и искомое расписание с одинаковым порядком выполнения работ на обоих станках существует.
 
}}
 
}}
  
Таким образом задача сводится к поиску этой искомой перестановки.  Докажем, что полученный приведенным выше алгоритмом список является оптимальной перестановкой работ.  
+
Таким образом задача сводится к поиску этой перестановки.  Докажем, что полученный приведенным выше алгоритмом список является оптимальной перестановкой работ.  
  
 
{{лемма
 
{{лемма
 
|id=lemma1
 
|id=lemma1
 
|about=1
 
|about=1
|statement= Если для каких-то работ <tex> i </tex> и <tex> j </tex> из списка <tex> T </tex> верно неравенство <tex> \min(p_{i1}, p_{j2}) <   \min(p_{j1}, p_{i2}) </tex>, то работа <tex> i </tex> встречается в списке <tex> T </tex> раньше, чем <tex> j </tex>.
+
|statement= Если для каких-то работ <tex> i </tex> и <tex> j </tex> из списка <tex> T </tex> верно неравенство <tex> \min(p_{i1}, p_{j2}) < \min(p_{j1}, p_{i2}) </tex>, то работа <tex> i </tex> встречается в списке <tex> T </tex> раньше, чем <tex> j </tex>.
 
|proof=
 
|proof=
 
Пусть <tex> p_{i1} < p_{j2} </tex>. Случай <tex> p_{i1} > p_{j2} </tex> рассматривается аналогично.  
 
Пусть <tex> p_{i1} < p_{j2} </tex>. Случай <tex> p_{i1} > p_{j2} </tex> рассматривается аналогично.  
Строка 52: Строка 52:
 
|statement= Пусть имеем произвольное расписание, в котором работа <tex> j </tex> идет сразу же после работы <tex> i </tex>. Тогда если <tex> \min(p_{j1}, p_{i2}) \leqslant  \min(p_{i1}, p_{j2}) </tex>, то можем поменять местами эти работы без ухудшения целевой функции.  
 
|statement= Пусть имеем произвольное расписание, в котором работа <tex> j </tex> идет сразу же после работы <tex> i </tex>. Тогда если <tex> \min(p_{j1}, p_{i2}) \leqslant  \min(p_{i1}, p_{j2}) </tex>, то можем поменять местами эти работы без ухудшения целевой функции.  
 
|proof=
 
|proof=
[[Файл:f2cmax_fixed.png|200px|thumb|right|Рис. 2 - Расположение последовательных работ]]
+
[[Файл:f2cmax_fixed.png|200px|thumb|right|Рис. 2 {{---}} Расположение последовательных работ]]
 
Пусть <tex> w_{ij} </tex> {{---}} время, прошедшее с начала выполнения работы <tex> i </tex> на первом станке до окончания работы <tex> j </tex> на втором станке.  
 
Пусть <tex> w_{ij} </tex> {{---}} время, прошедшее с начала выполнения работы <tex> i </tex> на первом станке до окончания работы <tex> j </tex> на втором станке.  
  
Строка 101: Строка 101:
 
==Псевдокод==
 
==Псевдокод==
  
   '''function''' F2Cmax(n: '''int''', p: '''int'''[n][2]): '''list'''
+
   '''function''' F2Cmax(p: '''int'''[n][2]): '''list<int>'''
       '''list''' L = <tex>\varnothing </tex>
+
       '''list<int>''' L = <tex>\varnothing </tex>
       '''list''' R = <tex>\varnothing </tex>
+
       '''list<int>''' R = <tex>\varnothing </tex>
       '''set''' X = <tex>\{1, \dots, n\}</tex>
+
       '''set<int>''' X = <tex>\{1, \ldots, n\}</tex>
       '''while''' X <tex> \neq \varnothing</tex>
+
       '''while''' X <tex>\neq \varnothing</tex>
         Найти i и j , такие что <tex>p_{ij} = \min \{ p_{ij} \mid i \in X; j = 1, 2\}</tex>
+
         Найти i и j, такие что <tex>p_{ij} = \min \{ p_{ij} \mid i \in X \land j = 1, 2\}</tex>
 
         '''if''' j == 1
 
         '''if''' j == 1
 
             L.addLast(i)
 
             L.addLast(i)
Строка 112: Строка 112:
 
             R.addFirst(i)
 
             R.addFirst(i)
 
         X.remove(i)
 
         X.remove(i)
       '''list''' T = L + R
+
       '''list<int>''' T = L ++ R
 
       '''return''' T
 
       '''return''' T
  
 
==Сложность алгоритма==
 
==Сложность алгоритма==
Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за <tex>O(\log n)</tex> (либо предварительной [[Сортировка|сортировкой]], либо  с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за <tex>O(\log n)</tex>, например [[Двоичная_куча|кучи]]). А так как мы делаем  это <tex> n </tex> раз, алгоритм работает за <tex>O(n\log n)</tex>.
+
Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за <tex>O(\log n)</tex> (либо предварительной [[Сортировка|сортировкой]], либо  с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за <tex>O(\log n)</tex>, например, [[Двоичная_куча|кучи]]). А так как мы делаем  это <tex> n </tex> раз, алгоритм работает за <tex>O(n\log n)</tex>.
  
 
==См. также==
 
==См. также==

Текущая версия на 19:27, 4 сентября 2022

F2∣∣Cmax

Задача:
Рассмотрим задачу:
  • дано n работ и 2 станка,
  • для каждой работы известно её время выполнения на каждом станке pij,
  • каждую работу необходимо выполнить сначала на первом станке, а потом на втором.
Требуется минимизировать время окончания выполнения всех работ.


Описание алгоритма

Пусть pi1 — время выполнения i-ой работы на первом станке, а pi2 — на втором.

  1. Алгоритм строит два списка L и R. Изначально они пусты. Также поддерживается множество еще не распределенных по спискам L и R работ X={ii=1,,n}
  2. Пока множество X не пусто, распределяем работы по спискам следующим образом:
    • находим такие индексы i и j, что pij=min{pijiXj=1,2},
    • если минимум достигается на первом станке (иными словами j=1), то поставим работу i в конец списка L, иначе ставим в начало списка R,
    • удаляем работу i из множества X.
  3. Рассмотрим список T=L ++ R — конкатенацию L и R. Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы.

Доказательство корректности алгоритма

Теорема:
Существует оптимальное расписание, в котором станки выполняют работы в одном и том же порядке.
Доказательство:
Рис. 1

Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках.

Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна k, где k<n. Пусть на k позиции на первом и втором станках стоит работа i, а на втором станке на позиции k+1 стоит работа j. Тогда заметим, что если мы поставим работу j на первом станке сразу после работы i, то последовательные работы с h по m (см. рис. 1) по-прежнему будут успевать выполниться, так как на втором станке они выполняются в текущем расписании после j. Таким образом нам удалось увеличить длину наибольшего общего префикса, а так как по нашему предположению она была максимальна, то предположение неверно и искомое расписание с одинаковым порядком выполнения работ на обоих станках существует.

Таким образом задача сводится к поиску этой перестановки. Докажем, что полученный приведенным выше алгоритмом список является оптимальной перестановкой работ.

Лемма (1):
Если для каких-то работ i и j из списка T верно неравенство min(pi1,pj2)<min(pj1,pi2), то работа i встречается в списке T раньше, чем j.
Доказательство:

Пусть pi1<pj2. Случай pi1>pj2 рассматривается аналогично.

Так как pi1<min(pj1,pi2), то работа i \in L . Работа j либо стоит в R , либо она стоит в L и при этом p_{i1} \lt p_{j1} . Заметим, что в обоих случаях она расположена позже (в силу нашего построения), чем работа i .
\triangleleft
Лемма (2):
Пусть имеем произвольное расписание, в котором работа j идет сразу же после работы i . Тогда если \min(p_{j1}, p_{i2}) \leqslant \min(p_{i1}, p_{j2}) , то можем поменять местами эти работы без ухудшения целевой функции.
Доказательство:
\triangleright
Рис. 2 — Расположение последовательных работ

Пусть w_{ij} — время, прошедшее с начала выполнения работы i на первом станке до окончания работы j на втором станке.

Рассмотрим возможные случаи расположения работ i и j (см. Рис. 2)

  1. Работа i начинается на втором станке сразу же после завершения ее на первом
      • Выполнение работы i на втором станке заканчивается позже, чем работы j на первом.
        Тогда w_{ij} = p_{i1} + p_{i2} + p_{j2} .
      • Выполнение работы i на втором станке заканчивается раньше, чем работы j на первом.
        В этом случае w_{ij} = p_{i1} + p_{j1} + p_{j2} .
  2. Работа i не может начаться на втором станке сразу же после завершения ее на первом
    • Выполнение работы i на втором станке заканчивается раньше, чем работы j на первом.
      Здесь снова имеем w_{ij} = p_{i1} + p_{j1} + p_{j2} .
    • Выполнение работы i на втором станке заканчивается позже, чем работы j на первом.
      Пусть \Delta — время прошедшее с начала выполнения работы i на первом станке и до начала ее выполнения на втором станке. Получили, что w_{ij} = \Delta + p_{i2} + p_{j2} .

Таким образом, w_{ij} = \max (p_{i1} + p_{j1} + p_{j2}, p_{i1} + p_{i2} + p_{j2}, \Delta + p_{i2} + p_{j2}) .

Иначе говоря, w_{ij} = \max (p_{i1} + \max(p_{j1}, p_{i2}) + p_{j2}, \Delta + p_{i2} + p_{j2}) .

Аналогично, w_{ji} = \max (p_{j1} + \max(p_{i1}, p_{j2}) + p_{i2}, \Delta + p_{i2} + p_{j2})

Так как \min(a, b) = - \max(-a, -b), то из условия леммы имеем \max(-p_{i1}, -p_{j2}) \leqslant \max(-p_{j1}, -p_{i2}) . Добавив p_{i1} + p_{i2} + p_{j1} + p_{j2} к обеим частям, получим, что p_{j1} + \max(p_{i1}, p_{j2}) + p_{i2} \leqslant p_{i1} + \max(p_{j1}, p_{i2}) + p_{j2} , то есть w_{ji} \leqslant w_{ij} и при смене местами работ i и j ответ не ухудшается.
\triangleleft


Теорема:
Построенная перестановка T является оптимальной.
Доказательство:
\triangleright

Рассмотрим произвольную перестановку S . Пусть перестановки T и S имеют общий префикс длины l-1 . Пусть i = T_{l} и j = S_{l} . Рассмотрим множество работ M = \{T_{r} \mid r = l, \dots, n\}. Заметим, что для любой работы k \in M верно, что \min(p_{k1}, p_{i2}) \geqslant \min(p_{i1}, p_{k2}) , так как если было бы верно обратное, то есть \min(p_{k1}, p_{i2}) \lt \min(p_{i1}, p_{k2}) , то по лемме 1 было бы верно, что k идет раньше i , что неверно.

Очевидно, что в перестановке S работа i будет стоять после j (иначе общий префикс был бы длиннее), то заметим, что в этой перестановке для работы i и для предыдущей работы w верно \min(p_{w1}, p_{i2}) \geqslant \min(p_{i1}, p_{w2}) (так как w \in M ), то по лемме 2 можем поменять местами работы i и w без ухудшения ответа. То такими операциями сможем дойти до пары работ i и j , которые при смене увеличат общий префикс перестановок S и T .

Таким образом любая перестановка сводится к нашей без ухудшения ответа такими операциями, что подтверждает оптимальность перестановки T
\triangleleft

Псевдокод

  function F2Cmax(p: int[n][2]): list<int>
     list<int> L = \varnothing 
     list<int> R = \varnothing 
     set<int> X = \{1, \ldots, n\}
     while X \neq \varnothing
        Найти i и j, такие что p_{ij} = \min \{ p_{ij} \mid i \in X \land j = 1, 2\}
        if j == 1
           L.addLast(i)
        else 
           R.addFirst(i)
        X.remove(i)
     list<int> T = L ++ R
     return T

Сложность алгоритма

Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за O(\log n) (либо предварительной сортировкой, либо с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за O(\log n), например, кучи). А так как мы делаем это n раз, алгоритм работает за O(n\log n).

См. также

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

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