#include <Simplex.h>
Diagram dziedziczenia dla Simplex
Metoda programowania liniowego służąca do rozwiązywania problemów w postaci standardowej:
gdzie:
- macierz współczynników funkcji ograniczeń,
- wektor ograniczeń,
- wektor kosztów.
Metoda simplex oparta jest na spostrzeżeniu, że punkt, w którym znajduje się minimum, jest jednym z punktów wierzchołkowych obszaru dopuszczalnego i że da się go osiągnąć w skończonej liczbie kroków, przechodząc między punktami wierzchołkowymi w taki sposób, aby przy każdym przejściu wartość funkcji celu zmniejszała się.
Aby znajdować punkty wierzchołkowe, algorytm w kolejnych iteracjach wyróżnia w macierzy część bazową i niebazową oraz rozwiązuje układy równań względem bazowych współczynników punktu (niebazowe współczynniki traktuje się jako zerowe).
W ten sposób w każdym etapie wyznaczany jest jeden punkt znajdujący się na przecięciu ograniczeń związanych z aktualną bazą. Na końcu każdego etapu w bazie wymienia się jedną zmienną: wprowadza się tą ze zmiennych niebazowych, której wzrost prowadzi do najszybszego spadku funkcji celu, a wyprowadza tą ze zmiennych bazowych, która po wprowadzeniu nowej zmiennej najszybciej osiąga wartość 0 (pamiętajmy, że standardowe sformułowanie problemu narzuca ograniczenie ).
Algorytm kończy się, gdy wprowadzenie żadnej ze zmiennych niebazowych do bazy nie będzie mogło prowadzić do spadku wartości funkcji celu.
Zaimplementowano dwufazową wersję algorytmu - jeśli wyznaczenie pierwszej bazy nie jest trywialne (macierz nie jest w postaci kanonicznej), metoda w celu znalezienia bazy tworzy problem rozszerzony (macierze ) i rozwiązuje go przy pomocy algorytmu simplex.
Informacje wejściowe:
- macierz współczynników funkcji ograniczeń [],
- wektor ograniczeń [],
- wektor kosztów (współczynników funkcji celu) [].
Oznaczenia:
- liczba ograniczeń (liczba wierszy macierzy ),
- liczba zmiennych (uwzględnia zmienne dopełniające, nie uwzględnia zmiennych rozszerzających, liczba kolumn macierzy ),
- macierz wsp. f. ograniczeń problemu rozszerzonego [],
- wektor ograniczeń problemu rozszerzonego [],
- wektor kosztów problemu rozszerzonego [],
- macierze aktualnie rozwiązywanego problemu,
- wektor bazowych współrzędnych aktualnego punktu [],
- wektor indeksów bazowych (indeksów kolumn macierzy , które tworzą aktualną bazę),
- wektor indeksów niebazowych,
- aktualna baza (macierz zbudowana z kolumn macierzy o indeksach z ) [],
- macierz zbudowana z pozostałych, niebazowych kolumn [],
- wektor kosztów zredukowanych (zawiera informację o wpływie ewentualnego wprowadzenia danej zmiennej niebazowej na wartość funkcji celu) [],
- wektor przesunięcia (zawiera informację o tym, jak proporcjonalnie zmienią się poszczególne zmienne bazowe po wprowadzeniu nowej zmiennej do bazy) [],
- indeks zmiennej wprowadzanej do bazy,
- indeks zmiennej wyprowadzanej z bazy,
- długość kroku przy przejściu do nowego punktu wierzchołkowego,
- informacja o aktualnie przeprowadzanej fazie algorytmu ( - faza wstępna: rozwiązywanie problemu rozszerzonego w celu znalezienia pierwszej bazy; - rozwiązywanie problemu właściwego) .
Procedura.
Krok 1:
Sprawdzamy, czy ostatnich kolumn macierzy tworzy macierz identycznościową. Jeśli tak, przechodzimy do kroku 2. Jeśli nie, przechodzimy do kroku 3.
Krok 2:
Macierz bazowa będzie utworzona z ostatnich kolumn macierzy .
Podstawiamy:
Przechodzimy do kroku 5.
Krok 3:
W celu znalezienia pierwszej bazy rozwiązujemy problem rozszerzony.
Tworzymy macierze problemu rozszerzonego:
gdzie:
- macierz jednostkowa ,
- wektor zerowy o wersach,
- wektor jednostkowy o wersach.
Podstawiamy:
Na podstawie i oraz tworzymy macierze i .
Podstawiamy i przechodzimy do kroku 6.
Krok 4:
Sprawdzamy, czy otrzymane po rozwiązaniu problemu rozszerzonego indeksy bazowe są poprawne (nie dotyczą kolumn rozszerzających):
Jeśli , to STOP - zmiennych rozszerzających nie udało się wyeliminować, problemu nie da się rozwiązać.
W przeciwnym wypadku usuwamy niebazowe indeksy zmiennych rozszerzających :
dla jeśli , element ten jest usuwany z wektora.
Przechodzimy do kroku 5.
Krok 5:
Podstawiamy:
Na podstawie i oraz tworzymy macierze i .
Przechodzimy do kroku 6.
Krok 6:
Obliczamy macierz odwrotną do bazowej .
Wyznaczamy pierwszy punkt wierzchołkowy:
Przechodzimy do kroku 7.
Krok 7:
Obliczamy wektor kosztów zredukowanych:
Sprawdzamy warunek stopu:
Jeśli , to: jeśli to STOP - wynikiem jest uzupełniony o pozostałe, niebazowe zmienne; jeśli , to przechodzimy do kroku 4.
Jeśli , to zapamiętujemy indeks najmniejszej składowej tego wektora - będzie to indeks zmiennej wprowadzanej do bazy:
Przechodzimy do kroku 8.
Krok 8:
Obliczamy wektor przesunięcia:
gdzie:
- s-ta kolumna macierzy .
Sprawdzamy, czy . Jeśli tak, to STOP - problem jest nieograniczony.
W przeciwnym wypadku szukamy zmiennej, którą należy wyprowadzić z bazy:
Przechodzimy do kroku 9.
Krok 9:
Zamieniamy indeksy zmiennej wychodzącej i wchodzącej do bazy:
Na podstawie nowych indeksów tworzymy macierze i .
Obliczamy nową macierz .
Wyznaczamy nowy punkt wierzchołkowy:
Przechodzimy do kroku 7.
Uwagi.
Zaimplementowano metodę niezmodyfikowaną, bez algorytmu zapobiegającego zapętleniu przy występowaniu punktów zdegenerowanych.
Metoda zaimplementowana na podstawie opisu zamieszczonego w:
Bruun H. N.: Algorithms for Linear Optimization - an Introduction. Lyngby, Technical University of Denmark 1999.
(http://www2.imm.dtu.dk/courses/02611/ALO.pdf).