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

Материал из Викиконспекты
Перейти к: навигация, поиск
(лемма)
Строка 3: Строка 3:
 
|definition=
 
|definition=
 
Дано <tex>m</tex> станков с разной скоростью выполнения работ <tex>v_j</tex> и <tex>n</tex> работ с заданным временем выполнения <tex>p_i</tex>. Работы можно прерывать и продолжать их выполнение на другом станке. Необходимо построить такое расписание, чтобы суммарное время окончания всех работ было минимальным.
 
Дано <tex>m</tex> станков с разной скоростью выполнения работ <tex>v_j</tex> и <tex>n</tex> работ с заданным временем выполнения <tex>p_i</tex>. Работы можно прерывать и продолжать их выполнение на другом станке. Необходимо построить такое расписание, чтобы суммарное время окончания всех работ было минимальным.
 +
}}
 +
== Описание алгоритма ==
 +
[[Файл:QpmtnSumCi example.png|320px|thumb|right|Пример работы алгоритма]]
 +
=== Идея ===
 +
Для решения применим правило '''SRPT-FM''' (Shortest Remaining Processing Time on Fastest Machine), которое предлагает класть работу с наименьшим оставшемся временем обработки на самый быстрый доступный станок. Отсортируем работы по времени обработки в невозрастающем порядке так, что <tex>p_1 \ge p_2 \ge ... \ge p_n</tex>. Отсортируем станки по скорости обработки в невозрастающем порядке, так чтобы <tex>v_1 \ge v_2 \ge ... \ge v_m</tex>. Далее назначаем <tex>n</tex>-ю работу на станок <tex>M_1</tex> (1-й по скорости станок) на время <tex>t_1 = \cfrac{p_n}{v_1}</tex>, то есть пока она полностью не выполнится. Теперь назначим <tex>n-1</tex> работу сначала станок <tex>M_2</tex> на время <tex>t_1</tex>, а затем на время от <tex>t_1</tex> до <tex>t_2 \ge t_1</tex> на станок <tex>M_1</tex>, пока она не завершится. С <tex>n-2</tex> работой поступаем аналогично, сначала она <tex>t_1</tex> времени выполняется на станке <tex>M_3</tex>, затем <tex>t_2 - t_1</tex> времени на станке <tex>M_2</tex>, и, начиная с <tex>t_2</tex> до <tex>t_3 \ge t_2</tex>, на станке <tex>M_1</tex>. Также поступаем со всеми оставшимися работами.
 +
 +
=== Псевдокод ===
 +
a = 0
 +
p[] // массив времен обработки работ отсортированный в невозрастающем порядке
 +
v[] // массив скоростей обработки станков отсортированный в невозрастающем порядке
 +
'''while''' p[1] > 0
 +
    Находим наибольший i такой, что p[i] > 0
 +
    t = p[i] / v[1]
 +
    '''for''' j = i '''down to''' k = max(1, i - m + 1)
 +
        Назначаем работу j на станок <tex>M_{1+i-j}</tex> на время от a до a + t
 +
        p[j] = p[j] - t * v[1 + i - j]
 +
    a = a + t
 +
 +
Сложность алгоритма составляет <tex> \mathcal{O}(n\log{n} + mn)</tex>.
 +
 +
== Доказательство корректности алгоритма ==
 +
{{Лемма
 +
|statement=
 +
Существует оптимальное расписание, в котором <tex>C_j \le C_k</tex>, когда <tex>p_j \le p_k</tex>, для всех <tex>j</tex> и <tex>k</tex>
 +
|proof=
 +
Рассмотрим расписание <tex>S</tex>, где для некоторых <tex>j</tex> и <tex>k</tex> верно, что <tex>C_j > C_k</tex>, но <tex>p_j \le p_k</tex>. С помощью обмена частей обработки, полученной работами <tex>j</tex> и <tex>k</tex>, мы можем изменить расписание <tex>S</tex>, получив новое оптимальное расписание <tex>S'</tex>, где обработка работ <tex>j</tex> и <tex>k</tex> завершается во времена <tex>C'_j \le C_k</tex> и <tex>C'_k = C_j</tex> соответственно, при этом время завершения обработки остальных работ остается прежним. Тот факт, что в расписании <tex>S'</tex> работа <tex>j</tex> заканчивается раньше <tex>k</tex>, при этом не нарушая оптимальности расписания, свидетельствует о существовании расписания, описанного в условии леммы.
 +
 +
Для построения расписания <tex>S'</tex> из расписания <tex>S</tex> введем следующие обозначения:
 +
* <tex>p^1_j</tex>, <tex>p^1_k</tex> {{---}} количество обработки, полученной одновременно <tex>j</tex> и <tex>k</tex>, когда работа <tex>j</tex> была на более быстром станке или обе работы были на одинаковых станках.
 +
* <tex>p^2_j</tex>, <tex>p^2_k</tex> {{---}} количество обработки, полученной одновременно <tex>j</tex> и <tex>k</tex>, когда работа <tex>k</tex> была на более быстром станке.
 +
* <tex>p^3_j</tex>, <tex>p^3_k</tex> {{---}} количество обработки, полученной <tex>j</tex> и <tex>k</tex> до момента <tex>C_k</tex> на непересекающихся участках времени.
 +
* <tex>p^+_j</tex> {{---}} количество обработки, полученной <tex>j</tex> после момента <tex>C_k</tex>.
 +
 +
Далее существуют два случая:
 +
* Если <tex>p^+_j \le p^3_k</tex>, то расписание <tex>S'</tex> получается обменом обработки, полученной <tex>j</tex> после момента <tex>C_k</tex> с частью обработки, полученной <tex>k</tex> не одновременно с <tex>j</tex>.
 +
* Если <tex>p^+_j > p^3_k</tex>, то для начала обмениваем всю обработку <tex>p^3_k</tex> с частью <tex>p^+_j</tex>, чтобы получить новое расписании, где <tex>C'_k = C_j</tex> и <tex>\tilde{p}^+_j = p^+_j - p^3_k</tex> обработки <tex>j</tex> после момента <tex>C_k</tex>. Пусть <tex>p^2_j</tex> и <tex>p^2_k</tex> представлены числом <tex>T</tex> непересекающихся временных интервалов длинной <tex>t_i</tex> с <tex>v^i_j</tex>, <tex>v^i_k</tex> {{---}} скоростями станков, обрабатывающих <tex>j</tex> и <tex>k</tex> в интервал <tex>i</tex> и <tex>p^{2,i}_j = v^i_j \cdot t_i</tex>, <tex>p^{2,i}_k = v^i_k \cdot t_i</tex> {{---}} количество обработки, полученной соответвующей задачей за этот интервал. Так как <tex>p^1_j \ge p^1_k</tex> и <tex>p_j \le p_k</tex>, то <tex>p^2_j + \tilde{p}^+_j \le p^2_k</tex>. Следовательно существует такой <tex>\tilde{p}^{+,i}_j</tex>, что верно:<br><tex>\sum\limits_{i=1}^{T}{\tilde{p}^{+,i}_j} = \tilde{p}^+_j</tex>,  <tex>p^{2,i}_j + \tilde{p}^{+,i}_j \le p^{2,i}_k</tex>,  <tex>i = 1...T</tex><br>Для каждого <tex>i = 1...T</tex> пусть <tex>t^i_j = \cfrac{\tilde{p}^{+,i}_j}{v^i_k - v^i_j}</tex>,  <tex>t^i_k = t^i_j \cdot \cfrac{v^i_j}{v^i_k}</tex>. Чтобы получить расписание <tex>S'</tex> для каждого из <tex>T</tex> интервалов нужно обменять:<br> 1) обработку, полученную в начале интервала работой <tex>k</tex> на более быстром станке, с обработкой <tex>j</tex>, полученной на медленном станке, на интервалы <tex>t^i_k</tex> и <tex>t^i_j</tex> соответственно<br>2) обработку <tex>\tilde{p}^{+,i}_j</tex>, полученной <tex>j</tex> после момента <tex>C_k</tex>, с таким же количеством обработки, полученной работой <tex>k</tex> на более быстром станке в этот интервал сразу после момента <tex>t^i_k</tex>.
 +
}}
 +
 +
{{Теорема
 +
|statement=
 +
Расписание, построенное по принципу '''SRPT-FM''', оптимальное для задачи <tex> Q \mid pmtn \mid \sum C_i </tex>
 +
|proof=
 +
В разработке
 
}}
 
}}

Версия 01:07, 30 мая 2016

[math] Q \mid pmtn \mid \sum C_i [/math]

Задача:
Дано [math]m[/math] станков с разной скоростью выполнения работ [math]v_j[/math] и [math]n[/math] работ с заданным временем выполнения [math]p_i[/math]. Работы можно прерывать и продолжать их выполнение на другом станке. Необходимо построить такое расписание, чтобы суммарное время окончания всех работ было минимальным.

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

Пример работы алгоритма

Идея

Для решения применим правило SRPT-FM (Shortest Remaining Processing Time on Fastest Machine), которое предлагает класть работу с наименьшим оставшемся временем обработки на самый быстрый доступный станок. Отсортируем работы по времени обработки в невозрастающем порядке так, что [math]p_1 \ge p_2 \ge ... \ge p_n[/math]. Отсортируем станки по скорости обработки в невозрастающем порядке, так чтобы [math]v_1 \ge v_2 \ge ... \ge v_m[/math]. Далее назначаем [math]n[/math]-ю работу на станок [math]M_1[/math] (1-й по скорости станок) на время [math]t_1 = \cfrac{p_n}{v_1}[/math], то есть пока она полностью не выполнится. Теперь назначим [math]n-1[/math] работу сначала станок [math]M_2[/math] на время [math]t_1[/math], а затем на время от [math]t_1[/math] до [math]t_2 \ge t_1[/math] на станок [math]M_1[/math], пока она не завершится. С [math]n-2[/math] работой поступаем аналогично, сначала она [math]t_1[/math] времени выполняется на станке [math]M_3[/math], затем [math]t_2 - t_1[/math] времени на станке [math]M_2[/math], и, начиная с [math]t_2[/math] до [math]t_3 \ge t_2[/math], на станке [math]M_1[/math]. Также поступаем со всеми оставшимися работами.

Псевдокод

a = 0
p[] // массив времен обработки работ отсортированный в невозрастающем порядке
v[] // массив скоростей обработки станков отсортированный в невозрастающем порядке
while p[1] > 0
   Находим наибольший i такой, что p[i] > 0
   t = p[i] / v[1]
   for j = i down to k = max(1, i - m + 1)
       Назначаем работу j на станок [math]M_{1+i-j}[/math] на время от a до a + t
       p[j] = p[j] - t * v[1 + i - j]
   a = a + t

Сложность алгоритма составляет [math] \mathcal{O}(n\log{n} + mn)[/math].

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

Лемма:
Существует оптимальное расписание, в котором [math]C_j \le C_k[/math], когда [math]p_j \le p_k[/math], для всех [math]j[/math] и [math]k[/math]
Доказательство:
[math]\triangleright[/math]

Рассмотрим расписание [math]S[/math], где для некоторых [math]j[/math] и [math]k[/math] верно, что [math]C_j \gt C_k[/math], но [math]p_j \le p_k[/math]. С помощью обмена частей обработки, полученной работами [math]j[/math] и [math]k[/math], мы можем изменить расписание [math]S[/math], получив новое оптимальное расписание [math]S'[/math], где обработка работ [math]j[/math] и [math]k[/math] завершается во времена [math]C'_j \le C_k[/math] и [math]C'_k = C_j[/math] соответственно, при этом время завершения обработки остальных работ остается прежним. Тот факт, что в расписании [math]S'[/math] работа [math]j[/math] заканчивается раньше [math]k[/math], при этом не нарушая оптимальности расписания, свидетельствует о существовании расписания, описанного в условии леммы.

Для построения расписания [math]S'[/math] из расписания [math]S[/math] введем следующие обозначения:

  • [math]p^1_j[/math], [math]p^1_k[/math] — количество обработки, полученной одновременно [math]j[/math] и [math]k[/math], когда работа [math]j[/math] была на более быстром станке или обе работы были на одинаковых станках.
  • [math]p^2_j[/math], [math]p^2_k[/math] — количество обработки, полученной одновременно [math]j[/math] и [math]k[/math], когда работа [math]k[/math] была на более быстром станке.
  • [math]p^3_j[/math], [math]p^3_k[/math] — количество обработки, полученной [math]j[/math] и [math]k[/math] до момента [math]C_k[/math] на непересекающихся участках времени.
  • [math]p^+_j[/math] — количество обработки, полученной [math]j[/math] после момента [math]C_k[/math].

Далее существуют два случая:

  • Если [math]p^+_j \le p^3_k[/math], то расписание [math]S'[/math] получается обменом обработки, полученной [math]j[/math] после момента [math]C_k[/math] с частью обработки, полученной [math]k[/math] не одновременно с [math]j[/math].
  • Если [math]p^+_j \gt p^3_k[/math], то для начала обмениваем всю обработку [math]p^3_k[/math] с частью [math]p^+_j[/math], чтобы получить новое расписании, где [math]C'_k = C_j[/math] и [math]\tilde{p}^+_j = p^+_j - p^3_k[/math] обработки [math]j[/math] после момента [math]C_k[/math]. Пусть [math]p^2_j[/math] и [math]p^2_k[/math] представлены числом [math]T[/math] непересекающихся временных интервалов длинной [math]t_i[/math] с [math]v^i_j[/math], [math]v^i_k[/math] — скоростями станков, обрабатывающих [math]j[/math] и [math]k[/math] в интервал [math]i[/math] и [math]p^{2,i}_j = v^i_j \cdot t_i[/math], [math]p^{2,i}_k = v^i_k \cdot t_i[/math] — количество обработки, полученной соответвующей задачей за этот интервал. Так как [math]p^1_j \ge p^1_k[/math] и [math]p_j \le p_k[/math], то [math]p^2_j + \tilde{p}^+_j \le p^2_k[/math]. Следовательно существует такой [math]\tilde{p}^{+,i}_j[/math], что верно:
    [math]\sum\limits_{i=1}^{T}{\tilde{p}^{+,i}_j} = \tilde{p}^+_j[/math], [math]p^{2,i}_j + \tilde{p}^{+,i}_j \le p^{2,i}_k[/math], [math]i = 1...T[/math]
    Для каждого [math]i = 1...T[/math] пусть [math]t^i_j = \cfrac{\tilde{p}^{+,i}_j}{v^i_k - v^i_j}[/math], [math]t^i_k = t^i_j \cdot \cfrac{v^i_j}{v^i_k}[/math]. Чтобы получить расписание [math]S'[/math] для каждого из [math]T[/math] интервалов нужно обменять:
    1) обработку, полученную в начале интервала работой [math]k[/math] на более быстром станке, с обработкой [math]j[/math], полученной на медленном станке, на интервалы [math]t^i_k[/math] и [math]t^i_j[/math] соответственно
    2) обработку [math]\tilde{p}^{+,i}_j[/math], полученной [math]j[/math] после момента [math]C_k[/math], с таким же количеством обработки, полученной работой [math]k[/math] на более быстром станке в этот интервал сразу после момента [math]t^i_k[/math].
[math]\triangleleft[/math]
Теорема:
Расписание, построенное по принципу SRPT-FM, оптимальное для задачи [math] Q \mid pmtn \mid \sum C_i [/math]
Доказательство:
[math]\triangleright[/math]
В разработке
[math]\triangleleft[/math]