Zadanie 4: Programowanie liniowe

Transkrypt

Zadanie 4: Programowanie liniowe
Informatyka, studia dzienne, mgr II st.
semestr II
Metody obliczeniowe optymalizacji
2013/2014
Prowadzący: mgr inż. Łukasz Chomątek
Data oddania:
poniedziałek, 12:15
Ocena:
Mateusz Grotek 186816
Paweł Tarasiuk 186875
Zadanie 4: Programowanie liniowe∗
1. Cel
Celem niniejszego zadania jest analiza dwufazowej metody sympleks, w
ramach której przygotowana została jej implementacja. Program powinien
wykrywać sytuacje patologiczne (brak rozwiązań, rozwiązania niejednoznaczne). Sugerowanym dodatkowym elementem funkcjonalności jest wypisywanie
postaci kolejnych tablic sympleksowych w czytelny sposób.
2. Rozwiązanie zadania i opis programu
Klasyczna metoda sympleks pozwala na znajdywanie ekstremów funkcji
liniowej na wielościanie wypukłym, tj. na podzbiorze przestrzeni będącym
iloczynem skończonej liczby takich zbiorów, których brzeg stanowi w zadanej przestrzeni hiperpłaszczyznę. Tak zdefiniowany iloczyn zbiorów nazywany jest zbiorem rozwiązań dopuszczalnych, zaś punkty realizujące szukane
optimum – rozwiązaniami optymalnymi.
Wspomniane powyżej zbiory mogą zostać opisane jako nierówności nieostre. Aby zastosować najpopularniejszą wersję klasycznej metody sympleks
należy sprowadzić problem do postaci układu nierówności, w którym wszystkie zmienne decyzyjne (współrzędne kartezjańskiego układu współrzędnych
opisującego zadaną przestrzeń) były nieujemne, oraz spełniony był pewien
układ nierówności. Każdy taki układ może zostać tak przekształcony, aby
∗
SVN:
http://serce.ics.p.lodz.pl/svn/labs/moo/lc_pn_1215/
wladcywszechswiata@125
1
zbiór rozwiązań dopuszczalnych był zbiorem ograniczonym, a wszystkie nierówności były typu „≤” – jest to osiągane np. poprzez podstawianie zmiennych pomocniczych zależnych liniowo od zmiennych decyzyjnych z ujemnym
współczynnikiem kierunkowym. Niech n – liczba zmiennych decyzyjnych, m –
liczba nierówności. Weźmy dowolną i-tą nierówność (i ∈ {1, . . . , m}) postaci
ai1 x1 + . . . + ain xn ≤ bi
gdzie aij to pewne współczynniki rzeczywiste, j ∈ {1, . . . , n}. Dla każdego
rozwiązania dopuszczalnego (x1 , . . . , xn ) da się wskazać pewną taką liczbę
nieujemną si , że:
ai1 x1 + . . . + ain xn + 1si = bi .
Po wprowadzeniu zmiennych bilansujących dostajemy układ równań, w
którym chcemy znaleźć takie rozwiązania, dla których wszystkie wartości
zmiennych decyzyjnych oraz zmiennych bilansujących są nieujemne, oraz
funkcja optymalności przyjmuje najbardziej pożądaną wartość (minimalną
bądź maksymalną). Zauważmy, że skoro funkcja optymalności ma być funkcją liniową, a zbiór rozwiązań dopuszczalnych jest wielościanem, to przynajmniej jeden z wierzchołków wielościanu stanowi rozwiązanie optymalne.
Wierzchołki wielościanu będą w tym wypadku reprezentowane przez rozwiązania bazowe układu równań, tj. takie, dla których co najwyżej m zmiennych
ma wartość inną niż 0.
Konkretne kroki klasycznej metoda sympleks wyznaczającej maksimum
funkcji liniowej mogą zostać zapisane w języku Octave następująco:
# zred_A -- wartości zmiennych dla rozważanego wierzchołka
# zred_b -- wartość funkcji celu dla rozważanego wierzchołka
# A -- współczynniki tabeli sympleksowej
# b -- wyrazy wolne tabeli sympleksowej
# bazowe -- numery zmiennych bazowych (w metodzie klasycznej zaczynamy od samych
# zmiennych bilansujących)
function wyjscie=metoda_sympleks(zred_A, zred_b, A, b, bazowe, nazwy, \
kod_warunku, komunikat, faza1)
[kr, z] = size(A);
zd = z - kr;
sprawdzone = [];
iteracje = 0;
# zazwyczaj: dopóki któryś współczynnik jest ujemny
while eval(kod_warunku) # w klasycznym podejściu kod_warunku to po prostu "min(zred_A) < 0"
# sprawdzam, czy dany zestaw zmiennych bazowych nie był analizowany wcześniej
for k = [1:size(sprawdzone)(1)]
if sprawdzone(k, :) == bazowe
display(’Brak rozwiazania zadania programowania linowego (nie da się spełnić warunku; zapętlenie)’);
exit();
endif
endfor
# zapamiętuję bieżący zestaw zmiennych bazowych
sprawdzone = [sprawdzone; bazowe];
# wyznaczam zmienną wychodzącą z bazy
# delty -- współczynniki optymalności (z bazy wyjdzie zmienna z największym
# współczynnikiem)
delty = -zred_A;
for i = [1:kr]
delty(bazowe(i)) = -Inf;
endfor
2
[najwieksza_delta, wchodzaca] = max(delty);
# w klazycznym podejściu, delta powinna być dodatnia
# jednak w fazie I chcemy usunąć zmienne sztuczne z bazy za wszelką cenę (choćby ujemnych delt!)
if najwieksza_delta <= 0 && ! faza1
display(’Brak rozwiazania zadania programowania linowego (nie da się spełnić warunku)’);
exit();
endif
# wyznaczam zmienną wchodzącą do bazy
# ilorazy -- ilorazy wyjścia (z bazy wyjdzie zmienna z najmniejszym dodatnim
# ilorazem wyjścia)
ilorazy = b ./ A(:, wchodzaca);
wychodzaca_bazowa = -1;
for wiersz = [1:kr]
if A(wiersz, wchodzaca) != 0 && ilorazy(wiersz) > 0 \
&& (wychodzaca_bazowa == -1 || ilorazy(wiersz) < ilorazy(wychodzaca_bazowa))
wychodzaca_bazowa = wiersz;
endif
endfor
if wychodzaca_bazowa == -1
display(’Brak rozwiazania zadania programowania linowego (kolumna zerowa?)’);
exit();
endif
wychodzaca = bazowe(wychodzaca_bazowa);
# element centralny
centralny = [wychodzaca_bazowa, wchodzaca];
# normalizacja wiersza wskazanego przez element centralny
mnoznik = 1 / A(centralny(1), centralny(2));
A(centralny(1), :) *= mnoznik;
b(centralny(1)) *= mnoznik;
# krok metody Gaussa (kolumna z nową zmienną bazową musi zawierać jedną jedynkę
# i same zera)
for wiersz = [1:kr]
if wiersz != centralny(1)
mnoznik = -A(wiersz, centralny(2));
A(wiersz, :) += mnoznik .* A(centralny(1), :);
b(wiersz) += mnoznik * b(centralny(1));
endif
endfor
mnoznik = -zred_A(centralny(2));
zred_A += mnoznik .* A(centralny(1), :);
zred_b += mnoznik * b(centralny(1));
# aktualizacja informacji o zmiennych bilansujących
for i = [1:kr]
if bazowe(i) == wychodzaca
bazowe(i) = wchodzaca;
endif
endfor
# wypisanie komunikatów
bazowe_napis = ’’;
for i = [1:kr]
bazowe_napis = cstrcat(bazowe_napis, cell2mat(nazwy(bazowe(i))), ’ ’);
endfor
disp(cstrcat(komunikat, bazowe_napis));
rysuj_tabelke(nazwy, zred_A, zred_b, A, b);
iteracje += 1;
endwhile
# obliczenie współczynników optymalności po skończonej pracy
delty = -zred_A;
for kolumna = [1:z]
for wiersz = [1:kr]
delty(kolumna) += zred_A(bazowe(wiersz)) .* A(wiersz, kolumna);
endfor
endfor
3
# jeżeli współczynnik optymalności dla jakiejś zmiennej niebazowej wynosi 0
# (czyli zer jest więcej niż zmiennych bazowych), to rozwiązanie jest niejednoznaczne
jednoznaczne = sum(delty == 0) <= zd;
wyjscie = {zred_A, zred_b, A, b, bazowe, iteracje, jednoznaczne};
endfunction
Klasyczna metoda sympleks pozwala rozwiązywać zadania programowania
liniowego, lecz samo przekształcanie problemu tak, aby zbiór rozwiązań optymalnych był ograniczony i aby punkt (0, 0, 0) był właściwym wierzchołkiem
startowym jest łatwe do wykonania ręcznie, lecz kłopotliwe do zapisania w
postaci ogólnego algorytmu. Ten problem rozwiązywany jest poprzez zastosowanie dwufazowej metody sympleks, która polega na tym, że przed samym
szukaniem rozwiązania optymalnego wykonywana jest dodatkowo „pierwsza faza rozwiązania”, czyli szukanie odpowiedniego wierzchołka startowego.
Druga faza jest już dokładnie tym samym, co klasyczna metoda sympleks,
tyle że zaczynamy od tabeli sympleks która od razu wskazuje na dobry wierzchołek startowy (powstaje ona w wyniku przekształceń z pierwszej fazy).
Dodatkowo, pierwsza faza pozwala wykryć przypadki układów sprzecznych (może to być interpretowane jako porażka przy szukaniu wierzchołka
startowego).
Pierwsza faza polega na tym, że do każdego równania dodajemy dodatkowe zmienne sztuczne (poza ewentualnymi zmiennymi bilansującymi) i zamiast maksymalizacji funkcji celu minimalizujemy sumę zmiennych sztucznych (czyli maksymalizujemy liczbę przeciwną do tej sumy). Zaczynamy jednak od wierzchołka, gdzie wszystkie zmienne sztuczne są zerami, więc w
tymczasowej funkcji celu podstawiamy je za pomocą kombinacji zmiennych
decyzyjnych, bilansujących i wyrazów wolnych wynikających z poszczególnych równości. Jest to realizowane poprzez następujące sumy po kolumnach:
zred_A = -[sum(A(:, 1:zd), 1), zeros(1, kr)];
zred_b = -sum(b, 1);
gdzie kr – liczba równości, zd – liczba zmiennych przed dodaniem zmiennych sztucznych.
Jeżeli po przeprowadzeniu metody sympleks z pierwszej fazy okaże się,
że maksymalna wartość liczby przeciwnej do sumy zmiennych sztucznych
(zred b) jest ujemna, to pierwotne zadanie programowania liniowego jest
sprzeczne.
Ostatecznie, rozwiązanie dwufazowej metody sympleks jest jednoznaczne, gdy otrzymano rozwiązania jednoznaczne w obu fazach oraz zred b po
pierwszej fazie nie jest zerem.
3. Wyniki
3.1. Typowe zadanie programowania liniowego
Zaczniemy od typowego zadania ze zbioru zadań do ekonometrii matematycznej.
12x1 + 12x2 + 9x3 → „Max”
4


3x1 + 5x2 + 4x3 + s1 = 2400
3x1 + 5x2 + 1x3 + s2 = 2000


10x1 + 5x2 + 6x3 + s3 = 2400
x1 , x2 , x3 , s1 , s2 , s3 ≥ 0
Wywołanie naszego programu wygląda następująco:
c = [ 12, 12, 9, 0, 0, 0 ];
A = [ 3, 5, 4, 1, 0, 0; 3, 2, 1, 0, 1, 0; 10, 5, 6, 0, 0, 1 ];
b = [ 2400; 2000; 2400 ];
dwufazowy_sympleks(c, A, b);
Na standardowe wyjście wypisane zostały tabele sympleksowe oraz wynik:
I FAZA (szukanie wierzchołka startowego)
Początkowa tabela (ze zmiennymi bilansującymi)
x1
x2
x3
x4
x5
x6
y1
y2
y3
-16
-12
-11
-1
-1
-1
0
0
0 | -6.8e+03
-------------------------------------------------------------------------------------------+----------3
5
4
1
0
0
1
0
0 |
2.4e+03
3
2
1
0
1
0
0
1
0 |
2e+03
10
5
6
0
0
1
0
0
1 |
2.4e+03
Faza I, zmienne bazowe: y1 y2 x1
x1
x2
x3
x4
x5
x6
y1
y2
y3
0
-4
-1.4
-1
-1
0.6
0
0
1.6 | -2.96e+03
----------------------------------------------------------------------------------------------------+-----------0
3.5
2.2
1
0
-0.3
1
0
-0.3 |
1.68e+03
0
0.5
-0.8
0
1
-0.3
0
1
-0.3 |
1.28e+03
1
0.5
0.6
0
0
0.1
0
0
0.1 |
240
Faza I, zmienne bazowe: x2 y2 x1
x1
x2
x3
x4
x5
x6
y1
y2
y3
0
0
1.11
0.143
-1
0.257
1.14
0
1.26 | -1.04e+03
----------------------------------------------------------------------------------------------------+-----------0
1
0.629
0.286
0
-0.0857
0.286
0
-0.0857 |
480
0
0
-1.11
-0.143
1
-0.257
-0.143
1
-0.257 |
1.04e+03
1
0
0.286
-0.143
0
0.143
-0.143
0
0.143 |
0
Faza I, zmienne bazowe: x2 x5 x1
x1
x2
x3
x4
x5
x6
y1
y2
y3
0
0
6.66e-16 -5.55e-17
0
0
1
1
1 |
0
----------------------------------------------------------------------------------------------------+-----------0
1
0.629
0.286
0
-0.0857
0.286
0
-0.0857 |
480
0
0
-1.11
-0.143
1
-0.257
-0.143
1
-0.257 |
1.04e+03
1
0
0.286
-0.143
0
0.143
-0.143
0
0.143 |
0
Faza I, zmienne bazowe: x4 x5 x1
x1
x2
x3
x4
x5
x6
y1
y2
y3
0
1.94e-16
7.88e-16
0
0 -1.67e-17
1
1
1 |
9.33e-14
----------------------------------------------------------------------------------------------------+-----------0
3.5
2.2
1
0
-0.3
1
0
-0.3 |
1.68e+03
0
0.5
-0.8
0
1
-0.3
0
1
-0.3 |
1.28e+03
1
0.5
0.6
0
0
0.1
0
0
0.1 |
240
Faza I, zmienne bazowe: x4 x5 x6
x1
x2
x3
x4
x5
x6
y1
y2
y3
1.67e-16 2.78e-16 8.88e-16
0
0
0
1
1
1 | 1.33e-13
-------------------------------------------------------------------------------------------+----------3
5
4
1
0
0
1
0
0 |
2.4e+03
3
2
1
0
1
0
0
1
0 |
2e+03
10
5
6
0
0
1
0
0
1 |
2.4e+03
II FAZA (powrót do zagadnienia pierwotnego)
Wierzchołek startowy: [0 0 0 2.4e+03 2e+03 2.4e+03]
x1
x2
x3
x4
x5
x6
5
-12
-12
-9
0
0
0 |
0
-------------------------------------------------------+---------3
5
4
1
0
0 | 2.4e+03
3
2
1
0
1
0 |
2e+03
10
5
6
0
0
1 | 2.4e+03
Faza II, zmienne bazowe: x4 x5 x1
x1
x2
x3
x4
x5
x6
0
-6
-1.8
0
0
1.2 | 2.88e+03
-------------------------------------------------------------+----------0
3.5
2.2
1
0
-0.3 | 1.68e+03
0
0.5
-0.8
0
1
-0.3 | 1.28e+03
1
0.5
0.6
0
0
0.1 |
240
Faza II, zmienne bazowe: x2 x5 x1
x1
x2
x3
x4
x5
x6
0
0
1.97
1.71
0
0.686 | 5.76e+03
-------------------------------------------------------------+----------0
1
0.629
0.286
0
-0.0857 |
480
0
0
-1.11
-0.143
1
-0.257 | 1.04e+03
1
0
0.286
-0.143
0
0.143 |
0
Wierzchołek optymalny: [0 480 0 0 1.04e+03 0]
Maksimum: 5.76e+03
Jest to rozwiązanie jednoznaczne
Liczba kroków fazy I: 5
Liczba kroków fazy II: 2
Nazwy zmiennych innych niż zmienne sztuczne zostały nadane automatycznie, więc zamiast s1 , s2 , s3 program posługuje się nazwami x4 , x5 , x6 .
3.2. Przypadek do testowania metody dwufazowej
Dla testowania dwufazowej metody sympleks nie musimy zastanawiać się
nad pierwotnym podziałem na zmienne decyzyjne i bilansujące – po prostu
szukamy najlepszego rozwiązania bazowego z dodatnimi wartościami zmiennych.
Weźmy zadanie programowania linowego:
7x1 + 2x2 + −3x3 − x4 → „Max”
(
8x1 + 3x2 − 5x3 + x4 = 4
3x1 + 1x2 − 2x3 − x4 = 1
x1 , x2 , x3 , x4 ≥ 0
Zauważmy, że nie sposób wskazać tu trywialny wierzchołek startowy (nie
da się np. podstawić samych zer pod zmienne decyzyjne i odpowiednich liczb
pod zmienne bilansujące, bo nie ma tu nawet takiego podziału). Dla dwufazowej metody sympleks nie jest to problem:
I FAZA (szukanie wierzchołka startowego)
Początkowa tabela (ze zmiennymi bilansującymi)
x1
x2
x3
x4
y1
y2
-11
-4
7
0
0
0 |
-5
-------------------------------+-----8
3
-5
1
1
0 |
4
3
1
-2
-1
0
1 |
1
Faza I, zmienne bazowe: y1 x1
x1
x2
x3
x4
y1
y2
0 -0.333 -0.333
-3.67
0
3.67 |
-1.33
-------------------------------------------------+---------
6
0
1
0.333
0.333
0.333
-0.667
3.67
-0.333
1
0
-2.67
0.333
|
|
1.33
0.333
Faza I, zmienne bazowe: x4 x1
x1
x2
x3
x4
y1
y2
0 5.55e-17 5.55e-17
0
1
1 |
0
-------------------------------------------------------------+----------0
0.0909
0.0909
1
0.273
-0.727 |
0.364
1
0.364
-0.636
0
0.0909
0.0909 |
0.455
II FAZA (powrót do zagadnienia pierwotnego)
Wierzchołek startowy: [0.455 0 0 0.364]
x1
x2
x3
x4
0
0.455
-1.55
0 |
2.82
---------------------------------+--------0 0.0909 0.0909
1 |
0.364
1
0.364 -0.636
0 |
0.455
Faza II, zmienne bazowe: x3 x1
x1 x2 x3 x4
0
2
0 17 |
9
-----------------+----0
1
1 11 |
4
1
1
0
7 |
3
Wierzchołek optymalny: [3 0 4 0]
Maksimum: 9
Jest to rozwiązanie jednoznaczne
Liczba kroków fazy I: 2
Liczba kroków fazy II: 1
3.3. Przypadek niejednoznaczny
Weźmy zadanie programowania liniowego:
x1 + x2 + x3 → „Max”
(
x1 = 0
x1 + x2 + x3 = 1
x1 , x2 , x3 ≥ 0
Rozwiązanie widać jak na dłoni i jest nim cały odcinek łączący dwa wierzchołki. Program wypisuje stosowny komunikat
I FAZA (szukanie wierzchołka startowego)
Początkowa tabela (ze zmiennymi bilansującymi)
x1 x2 x3 y1 y2
-2 -1 -1
0
0 | -1
---------------------+----1
0
0
1
0 |
0
1
1
1
0
1 |
1
Faza I, zmienne bazowe: y1 x1
x1 x2 x3 y1 y2
0
1
1
0
2 |
1
---------------------+----0 -1 -1
1 -1 | -1
1
1
1
0
1 |
1
Faza I, zmienne bazowe: x2 x1
x1 x2 x3 y1 y2
0
0
0
1
1 |
0
---------------------+----0
1
1 -1
1 |
1
1
0
0
1
0 |
0
7
II FAZA (powrót do zagadnienia pierwotnego)
Wierzchołek startowy: [0 1 0]
x1 x2 x3
0
0
0 |
1
-------------+----0
1
1 |
1
1
0
0 |
0
Wierzchołek optymalny: [0 1 0]
Maksimum: 1
Jest to potencjalnie jedno z wielu rozwiązań
Liczba kroków fazy I: 2
Liczba kroków fazy II: 0
3.4. Przypadek sprzeczny
Weźmy fałszywe zadanie programowania liniowego:
x1 + x2 + x3 → „Max”
(
x1 + x 2 + x3 = 0
x1 + x 2 + x3 = 1
x1 , x2 , x3 ≥ 0
Program wypisuje następujące wyjście:
I FAZA (szukanie wierzchołka startowego)
Początkowa tabela (ze zmiennymi bilansującymi)
x1 x2 x3 y1 y2
-2 -2 -2
0
0 | -1
---------------------+----1
1
1
1
0 |
0
1
1
1
0
1 |
1
Faza I, zmienne bazowe: y1 x1
x1 x2 x3 y1 y2
0
0
0
0
2 |
1
---------------------+----0
0
0
1 -1 | -1
1
1
1
0
1 |
1
Faza I, zmienne bazowe: y1 x2
x1 x2 x3 y1 y2
0
0
0
0
2 |
1
---------------------+----0
0
0
1 -1 | -1
1
1
1
0
1 |
1
Faza I, zmienne bazowe: y1 x1
x1 x2 x3 y1 y2
0
0
0
0
2 |
1
---------------------+----0
0
0
1 -1 | -1
1
1
1
0
1 |
1
Brak rozwiazania zadania programowania linowego (nie da się spełnić warunku; zapętlenie)
4. Wnioski
Dwufazowa metoda sympleks jest bardzo wygodnym podejściem do numerycznego rozwiązywania zadań programowania liniowego. Asymptotyczna
8
złożoność obliczeniowa pozostaje taka sama jak w przypadku problemów gotowych do zastosowania klasycznej metody sympleks. Kolejną zaletą metody
sympleks, która pozostaje zachowana w metodzie dwufazowej jest to, że błędy
obliczeniowe są niewielkie (podobnie jak w przypadku rozwiązywania układów równań metodą Gaussa, które generuje znacznie mniejsze błędy niż np.
metoda wyznaczników). Jednakże, w przeciwieństwie do klasycznej metody
sympleks, tutaj można podstawić dowolne zadanie programowania liniowego.
Dwufazowa metoda sympleks dostarcza nam bowiem automatyczne mechanizmy wykrywania zadań sprzecznych oraz znajdywania wierzchołków startowych, tak aby zawsze poruszać się po wierzchołkach wielościanu ograniczonego. Fakt, że kod programu realizujący klasyczną metodę sympleks może być
wspólny dla obu faz (tak jak zostało to zrealizowane w niniejszym projekcie)
przypuszczalnie czyni dwufazową metodę sympleks najbardziej wygodnym
sposobem wykrywania przypadków sprzecznych i dostosowywania do metody
sympleks zadań programowania linowego, w których rozwiązanie składające
się z samych zer nie musi należeć do zbioru rozwiązań dopuszczalnych.
Literatura
[1] dr inż. Jacek Rogowski, Materiały do kursu z „Badań operacyjnych i ekonometrii matematycznej” dla drugiego roku studiów zamawianych 2013/2014.
[2] dr inż. Arkadiusz Tomczyk, Materiały do wykładów z „Metod obliczeniowych
optymalizacji”.
[3] John W. Eaton, GNU Octave - Documentation.
9