---
# System prepended metadata

title: Zadanie 7 - Lista 2

---

# Zadanie 7 - Lista 2
## Treść:
<img style="width: 100%" src="https://i.imgur.com/c6JxTR6.png" alt="Zadanie 7 Lista 2 2021">

## Rozwiązanie

### Algorytm:
1. Zainicjalizuj dwie zmienne $l=0,r=n-1$ 
2. Utwórz dwa zbiory: 
    2. Zbiór $O=\emptyset$ który będzie przechowywał optymalną kolejność wykoywania zadań
    3. Zbiór $Z=\{a_i,b_i\},|Z|=n$ który będzie przechowywał pary z czasem wykonywania $i$-tego zadania na maszynach $A$ i $B$.
3. Dopóki zbiór $Z\ne \emptyset$:
    3. Znajdź najkrótszy czas wykonywania pewnego zadania na dowolnej z maszyn, i zapisz go jako $p$ (W przypadku gdy takich zadań jest więcej niż jedno, weź pierwsze takie zadanie w zbiorze $Z$).
    4. Dla każdego $i$ w zbiorze $Z$ wstaw za parę $\{a_i,b_i\}$, $\{a_i-p,b_i-p\}$
    5. Dla każdego $i$ w zbiorze $Z$ jeżeli para jest postaci:   
       5.1 $\{0,b_i\}$ Dodaj tą parę do zbioru $O$ na indeksie $l$, usuń parę ze zbioru $Z$, $l+=1$.
       5.2 $\{a_i,0\}$ Dodaj tą parę do zbioru $O$ na indeksie $r$, usuń parę ze zbioru $Z$, $r-=1$.

### Przykładowy przebieg algorytmu:
<div style="width: 100%; display: table;">
    <div style="display: table-row">
<div style="display: table-cell">

1. 
| $Z_i$    | $a_i$    | $b_i$    |
| -------- | -------- | -------- |
| a        | **1**    | 5        |
| b        | 6        | 9        |
| c        | 7        | 2        |
| d        | 2        | 3        |
| e        | 4        | 5        |

$O=\{\_,\_,\_,\_,\_\}$

</div>

<div style="display: table-cell">

2.
| $Z_i$    | $a_i$    | $b_i$    |
| -------- | -------- | -------- |
| _        | _        | _        |
| b        | 5        | 8        |
| c        | 6        | **1**    |
| d        | 1        | 2        |
| e        | 3        | 4        |

$O=\{a,\_,\_,\_,\_\}$

</div>

<div style="display: table-cell">

3.
| $Z_i$    | $a_i$    | $b_i$    |
| -------- | -------- | -------- |
| _        | _        | _        |
| b        | 4        | 7        |
| _        | _        | _        |
| d        | **0**    | 1        |
| e        | 2        | 3        |

$O=\{a,\_,\_,\_,c\}$

</div>

<div style="display: table-cell">

4.
| $Z_i$    | $a_i$    | $b_i$    |
| -------- | -------- | -------- |
| _        | _        | _        |
| b        | 4        | 7        |
| _        | _        | _        |
| _        | _        | _        |
| e        | **2**    | 3        |

$O=\{a,d,\_,\_,c\}$

</div>

<div style="display: table-cell">

5.
| $Z_i$    | $a_i$    | $b_i$    |
| -------- | -------- | -------- |
| _        | _        | _        |
| b        | 2        | 5        |
| _        | _        | _        |
| _        | _        | _        |
| _        | _        | _        |

$O=\{a,d,e,b,c\}$

</div>
</div>
</div>

### Poprawność:
Algorytm ten korzysta z czterech lematów:
1. Mając pewne ustawienie zadań, zmiana ich kolejności w taki sposób aby kolejność wykonywania zadań na maszynie $A$ i na maszynie $B$, daje nam kolejność nie mniej optymalną niż oryginalna. 
    1.1 $\implies$ Kolejność wykonywania zadań na maszynie $A$ i $B$ będzie taka sama.

2. Mając pewne optymalne rozwiązanie dla zbioru $Z=\{a_i-p,b_i-p\}$ będzie ono również optymalne dla zbioru $Z=\{a_i,b_i\}$. 
    2.1$\implies$ Możemy uzyskać rozwiązanie optymalne poprzez odejmowanie w każdym kroku minimalnej wartości w zbiorze $Z$ od każdego z jego elementów.
3. Mając w $k$-tej pętli algorytmu dla pewnego zadania $i$, czasy $\{0,b_i\}$ możemy dodać to zadanie na pierwszą wolną pozycję w optymalnej kolejności wykonywania zadań, nie pogarszając optymalności naszego rozwiązania.
4. Mając w $k$-tej pętli algorytmu dla pewnego zadania $i$, czasy $\{a_i,0\}$ możemy dodać to zadanie na ostatnią wolną pozycję w optymalnej kolejności wykonywania zadań, nie pogarszając optymalności naszego rozwiązania.

    3.1 $\land$ 4.1 $\implies$ Możemy rozwiązanie optymalne uzyskać poprzez budowanie go "od końców", wstawiajać odpowiednio zadania typu $3$ na pierwszej wolnej pozycji w zbiorze $O$, oraz zadania typu $4$ na ostatniej wolnej pozycji w zbiorze $O$.
### Dowody lematów:
#### Lemat 1:
Załóżmy, że mamy pewne rozwiązanie w którym na maszynie $A$ i na maszynie $B$, zadania nie są wykonywane w takiej samej kolejności, tj. istnieją pewne zadania $i$ oraz $j$ takie, że zadanie $j$ zostanie wykonane na maszynie $A$ wcześniej niż zadanie $j$, a na maszynie $B$ zadanie $j$ zostanie wykonane przed zadaniem $i$.

W takim wypadku możemy łatwo zauważyć, że zamieniając kolejność na maszynie $B$, tak aby zadanie $j$ wykonało się po zadaniu $i$, w żaden sposób nie wpłynie negatywnie na optymalność naszego rozwiązania. W najgorszym wypadku czas wykonywania zadań na maszynie $B$ nie ulegnie zmianie ($a_j$=0), w innych wypadkach zmniejszymy czas oczekiwania na maszynie $B$ w rezultacie uzyskując rozwiązanie bardziej optymalne.


```mermaid
gantt
    title Przykład:
    section Maszyna A
    a_i           :a1, 2023-04-30, 3d
    a_k           : 2d
    a_j           : 5d
    section Maszyna B
    b_k           :2023-05-5, 4d
    b_j           :2023-05-10,4d
    b_i           : 8d
    section A
    a_i           :a1, 2023-04-30, 3d
    a_k           : 2d
    a_j           : 5d
    section B po zamianie
    b_i           : 2023-05-03, 8d
    b_k           : 2023-05-11, 4d
    b_j           :4d
```
#### Lemat 2:
Załóżmy, że mamy pewne optymalne rozwiązanie dla zadań o czasach $\{a_i,b_i\}$. Głównym czynnikiem wpływającym na optymalność naszego rozwiązania jest czas oczekiwania na maszynie $B$. 

Korzystając z **Lematu 1** wiemy, że kolejność wykonywania zadań na maszynach $A$ i $B$ będzie taka sama. 

Aby pokazać, że zwiększenie czasu wykonywania wszystkich zadań o pewne $p$, w żaden sposób nie wpłynie na czasy oczekiwania na maszynie $B$, rozważmy przypadek w którym wykonujemy kolejno zadania $i,j,k$ oraz $a_j>b_i$. Oznaczmy kolejno:
1. $\textrm{DUR}_{a_j}$ jako czas wykonywania zadania $a_j$, który będzie również czasem rozpoczęcia zadania $b_j$
2. $\textrm{DUR}_{b_i}$ jako czas wykonywania zadania $b_i$
3. $m$ jako czas oczekiwania na maszynie $B$ między zadaniami $b_i$ oraz $b_j$, gdzie wiemy, że $m=\textrm{DUR}_{a_j}-\textrm{DUR}_{b_i}$ 

Zwiększmy zatem czas wykonywania wszystkich zadań o $p$. Możemy zauważyć, zatem, że:
$\textrm{DUR}_{a_j+p}=\textrm{DUR}_{a_j}+p$ 
$\textrm{DUR}_{b_i+p}=\textrm{DUR}_{b_i}+p$
$m'=\textrm{DUR}_{a_j+p}-\textrm{DUR}_{b_i+p}=\textrm{DUR}_{a_j}+p-\textrm{DUR}_{b_i}-p=\textrm{DUR}_{a_j}-\textrm{DUR}_{b_i}=m$

Zatem możemy zauważyć, że zwieksząjąc czasy wykonywania wszystkich zadań o $p$, czas oczekiwania na maszynie $B$ nie ulegnie zmianie, $\implies$ rozwiązanie optymalne dla zadań postaci $\{a_i,b_i\}$ będzie nadal optymalne dla zadań postaci $\{a_i+p,b_i+p\}$. 

> Czas wykonywania takich zadań wzrośnie dokładnie o $(n+1)\cdot p$, ponieważ czas wykonywania każdego zadania zwiększamy o $p$ $(+n\cdot p)$, oraz na rozpoczęcie wykonywania zadań na maszynie $B$ będziemy musieli dodatkowo poczekać $p$ $(+p)$.

```mermaid
gantt
    title Przykład:
    section Maszyna A
    a_i           :a1, 2020-04-30, 3d
    a_j           : 2020-05-03, 5d
    a_k           : 8d
    section Maszyna B
    b_i           :2020-05-3,4d
    m : 1s
    b_j           :2020-05-8,9d
    b_k           :2d
    section Maszyna A + p
    a_i+p         :a1, 2020-04-30, 5d
    a_j+p         : 7d
    a_k+p         : 10d
    section Maszyna B + p
    b_i+p         :2020-05-5,6d
    m : 1s
    b_j+p         :2020-05-12,11d
    b_k+p         :4d
```
#### Lemat 3:
Załóżmy, że mamy zadanie $i$ postaci $\{0,b_i\}$. Niech $a_j$ będzie pierwszym zadaniem wykonywanym na maszynie $A$.
Rozpatrzmy 2 przypadki:
1. $b_i\leq a_j$ : W takim wypadku, ustawiając $i$-te zadanie jako pierwsze, w żaden sposób nie opóźnimy czasu rozpoczęcia wykonywania kolejnych zadań na maszynie $B$. (A zatem i czasu skończenia wykonywania zadań na maszynie $B$).
2. $b_i>a_j$ : W takim wypadku, ustawiając $i$-te zadanie jako pierwsze, mimo, że wydłużymy czas wykonywania wszystkich zadań na maszynie $B$, nadal jak najbardziej zwiększamy swoje szanse na "załatanie dziur" na maszynie $B$. Zatem istnieje szansa, że zmniejszymy sume czasów oczekiwania na maszynie $B$ i tym samym w możliwie najmniejszym stopniu wydłużymy czas działania maszyny $B$.

##### Dlaczego w k-tej pętli takie zadanie powinno trafić na pierwszą wolną pozycję w zbiorze przechowującą optymalną kolejność? (Budowanie $O$ "od końców")

Należy pamiętać o tym, że w $k$-tej pętli naszego algorytmu, zadanie postaci $\{a_i=0,b_i\}$ uzyskamy na skutek odejmowania kolejnych minimów ze zbioru $Z$.
Oznacza to, że $\{0,b_i\}=\{a_{\textrm{og }i}-p_1-p_2- \dots -p_k,b_{\textrm{ og }i}-p_1-p_2\dots -p_k\}$ gdzie oryginalnymi czasami wykonywania $i$-tego zadania było $\{a_{\textrm{og }i},b_{\textrm{og }i}\}\in Z$. 
Zatem w $k$-tej pętli algorytmu będzie zachodzić $\forall \{a_j,b_j\} \in Z\setminus O: a_i<a_j$. Zatem $i$-te zadanie powinno zostać wykonane przed wszystkimi innymi zadaniami które pozostały w zbiorze $Z$, ponieważ zależy nam na jak najmniejszym opóźnieniu czasu rozpoczęcia wykonywania zadań na maszynie $B$.

Zatem ustawiając takie zadanie na pierwszej wolnej pozycji zbioru $O$, na mocy **lematu 2** uzyskamy również optymalne rozwiązanie dla oryginalnego zbioru $Z$.
```mermaid
gantt
    title Przykład:
    section Maszyna A
    a_j         :a1, 2020-04-30, 5d
    a_k         : 7d
    a_l         : 10d
    section Maszyna B
    b_j         :2020-05-5,6d
    b_k         :2020-05-12,10d
    b_l         :4d
    section A + ai=0
    a_i         :2020-04-30,1h
    a_j         :a1, 2020-04-30, 5d
    a_k         : 7d
    a_l         : 10d
    section B + bi<aj
    b_i         :2020-04-30,3d
    b_j         :2020-05-5,6d
    b_k         :2020-05-12,10d
    b_l         :4d
    section B + bi>aj
    b_i         :2020-04-30,7d
    b_j         :2020-05-7,6d
    b_k         :2020-05-13,10d
    b_l         :4d
```
#### Lemat 4:
Załóżmy, że mamy zadanie $i$ postaci $\{a_i,0\}$. Niech $b_l$ będzie ostatnim zadaniem wykonywanym na maszynie $B$. 
Rozpatrzmy 2 przypadki:
1. $a_i\leq b_l$ : W takim wypadku, ustawiając $i$-te zadanie jako ostatnie, w żaden sposób nie opóźnimy czasu rozpoczęcia wykonywania kolejnych zadań na maszynie $B$. (A także ponieważ $b_i=0$ : czasu skończenia wykonywania zadań na maszynie $B$).
2. $a_i>b_l$ : W takim wypadku, ustawiając $i$-te zadanie jako ostatnie, mimo, że wydłużymy czas wykonywania wszystkich zadań na maszynie $B$, w żaden sposób nie opóźnimy czasu rozpoczęcia wykonywania wcześniejszych zadań na maszynie $B$, zatem w możliwie najmniejszym stopniu wydłużymy czas wykonywania zadań na maszynie $B$.
##### Dlaczego w k-tej pętli takie zadanie powinno trafić na ostatnią wolną pozycję w zbiorze przechowującą optymalną kolejność? (Budowanie $O$ "od końców")

Należy pamiętać o tym, że w $k$-tej pętli naszego algorytmu, zadanie postaci $\{a_i,b_i=0\}$ uzyskamy na skutek odejmowania kolejnych minimów ze zbioru $Z$.
Oznacza to, że $\{a_i,0\}=\{a_{\textrm{og }i}-p_1-p_2- \dots -p_k,b_{\textrm{ og }i}-p_1-p_2\dots -p_k\}$ gdzie oryginalnymi czasami wykonywania $i$-tego zadania było $\{a_{\textrm{og }i},b_{\textrm{og }i}\}\in Z$. 
Zatem w $k$-tej pętli algorytmu będzie zachodzić $\forall \{a_j,b_j\} \in Z\setminus O: b_i<b_j$. Zatem $i$-te zadanie powinno zostać wykonane po wszystkich innych zadaniach które pozostały w zbiorze $Z$, ponieważ zależy nam na jak najmniejszym wydłużeniu czasu wykonywania zadań na maszynie $B$.

Zatem ustawiając takie zadanie na ostatniej wolnej pozycji zbioru $O$, na mocy **lematu 2** uzyskamy również optymalne rozwiązanie dla oryginalnego zbioru $Z$.
```mermaid
gantt
    title Przykład:
    section Maszyna A
    a_j         :a1, 2020-04-30, 5d
    a_k         : 7d
    a_l         : 10d
    section Maszyna B
    b_j         :2020-05-5,6d
    b_k         :2020-05-12,10d
    b_l         :4d
    section A + a[i]<b[l]
    a_j         :a1, 2020-04-30, 5d
    a_k         : 7d
    a_l         : 10d
    a_i         : 2d
    section B + b[i]
    b_j         :2020-05-5,6d
    b_k         :2020-05-12,10d
    b_l         :4d
    b_i=0       :1h
    section A + a[i]>b[l]
    a_j         :a1, 2020-04-30, 5d
    a_k         : 7d
    a_l         : 10d
    a_i         : 5d
    section B + b[i].
    b_j         :2020-05-5,6d
    b_k         :2020-05-12,10d
    b_l         :4d
    b_i=0       :2020-05-27,2h