Różnice między wybraną wersją a wersją aktualną.
Poprzednia rewizja po obu stronachPoprzednia wersjaNowa wersja | Poprzednia wersja | ||
notatki:programowanie_liniowe [2025/05/16 13:21] – administrator | notatki:programowanie_liniowe [2025/05/16 19:26] (aktualna) – administrator | ||
---|---|---|---|
Linia 1: | Linia 1: | ||
- | ====== Programowanie Liniowe: ćwiczenia====== | + | ====== |
- | Programowanie liniowe (PL) to jedna z najważniejszych dziedzin optymalizacji matematycznej, | + | Programowanie liniowe (eng. LP) to jedna z najważniejszych dziedzin optymalizacji matematycznej, |
==== Krótka historia ==== | ==== Krótka historia ==== | ||
Linia 123: | Linia 123: | ||
* Ustaw " | * Ustaw " | ||
* Zmieniane komórki: `B5:C5` | * Zmieniane komórki: `B5:C5` | ||
- | | + | Ograniczenia: |
* czas pracy ≤ 40 | * czas pracy ≤ 40 | ||
Linia 145: | Linia 145: | ||
model = LpProblem(name=" | model = LpProblem(name=" | ||
- | # Zmienne decyzyjne | + | # Zmienne decyzyjne |
- | x = LpVariable(name=" | + | x = LpVariable(name=" |
- | y = LpVariable(name=" | + | y = LpVariable(name=" |
# Funkcja celu | # Funkcja celu | ||
Linia 167: | Linia 167: | ||
=== Wynik === | === Wynik === | ||
< | < | ||
- | Lampy stojące: | + | Lampy stojące: |
- | Lampy biurkowe: | + | Lampy biurkowe: |
- | Maksymalny zysk: 1360.0 zł | + | Maksymalny zysk: 1400.0 zł |
</ | </ | ||
+ | ====== Przykład problemu produkcyjnego – Rajstopy ====== | ||
+ | Rozważmy problem optymalizacji produkcji w zakładzie wytwarzającym dwa rodzaje rajstop: cienkie i grube. Celem jest **maksymalizacja utargu**, przy ograniczonych zasobach surowców. | ||
+ | |||
+ | ==== Treść zadania ==== | ||
+ | |||
+ | Zakład produkuje: | ||
+ | |||
+ | * **Rajstopy cienkie** – wymagają: 10 g przędzy elastycznej i 10 g bawełnianej, | ||
+ | * **Rajstopy grube** – wymagają: 20 g przędzy elastycznej i 25 g bawełnianej. | ||
+ | |||
+ | Stan magazynowy: | ||
+ | |||
+ | * **200 kg przędzy elastycznej** = 200 000 g, | ||
+ | * **500 kg przędzy bawełnianej** = 500 000 g. | ||
+ | |||
+ | Ceny sprzedaży: | ||
+ | |||
+ | * Rajstopy cienkie: **1,50 zł / para**, | ||
+ | * Rajstopy grube: **4,00 zł / para**. | ||
+ | |||
+ | ==== Zmienna decyzyjna ==== | ||
+ | |||
+ | Niech: | ||
+ | |||
+ | * $x$ – liczba par rajstop cienkich, | ||
+ | * $y$ – liczba par rajstop grubych. | ||
+ | |||
+ | ==== Funkcja celu ==== | ||
+ | |||
+ | Zakład chce **zmaksymalizować utarg** (czyli całkowity przychód): | ||
+ | |||
+ | $$ | ||
+ | Z = 1.5x + 4y | ||
+ | $$ | ||
+ | |||
+ | ==== Ograniczenia ==== | ||
+ | |||
+ | 1. **Zużycie przędzy elastycznej**: | ||
+ | |||
+ | $$ | ||
+ | 10x + 20y \leq 200\,000 | ||
+ | $$ | ||
+ | |||
+ | 2. **Zużycie przędzy bawełnianej**: | ||
+ | |||
+ | $$ | ||
+ | 10x + 25y \leq 500\,000 | ||
+ | $$ | ||
+ | |||
+ | 3. **Nieujemność zmiennych**: | ||
+ | |||
+ | $$ | ||
+ | x \geq 0,\quad y \geq 0 | ||
+ | $$ | ||
+ | |||
+ | ==== Model matematyczny ==== | ||
+ | |||
+ | $$ | ||
+ | \begin{cases} | ||
+ | \text{Maksymalizuj } Z = 1.5x + 4y \\ | ||
+ | \text{przy warunkach:} \\ | ||
+ | 10x + 20y \leq 200\,000 \\ | ||
+ | 10x + 25y \leq 500\,000 \\ | ||
+ | x \geq 0,\ y \geq 0 | ||
+ | \end{cases} | ||
+ | $$ | ||
+ | |||
+ | ==== Komentarz ==== | ||
+ | |||
+ | Model ten można rozwiązać w Excelu (przy pomocy dodatku Solver) lub w Pythonie, np. za pomocą biblioteki `PuLP`. Wynikiem będzie liczba par rajstop cienkich i grubych, które zakład powinien wyprodukować, | ||
+ | |||
+ | W kolejnych sekcjach można przedstawić konkretne rozwiązanie (metodą graficzną, w Excelu lub Pythonie) i analizę wyniku. | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | from pulp import LpMaximize, LpProblem, LpVariable | ||
+ | |||
+ | # Tworzymy problem maksymalizacji | ||
+ | model = LpProblem(name=" | ||
+ | |||
+ | # Zmienne decyzyjne (liczba par rajstop) | ||
+ | x = LpVariable(name=" | ||
+ | y = LpVariable(name=" | ||
+ | |||
+ | # Funkcja celu – maksymalizacja utargu | ||
+ | model += 1.5 * x + 4 * y, " | ||
+ | |||
+ | # Ograniczenia zużycia przędzy (gramy) | ||
+ | model += (10 * x + 20 * y <= 200_000, " | ||
+ | model += (10 * x + 25 * y <= 500_000, " | ||
+ | |||
+ | # Rozwiązanie | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | </ | ||
+ | |||
+ | === Nagłówek === | ||
+ | |||
+ | < | ||
+ | Plan produkcji maksymalizujący utarg: | ||
+ | Rajstopy cienkie: 0.0 par | ||
+ | Rajstopy grube: 10000.0 par | ||
+ | Maksymalny utarg: 40000.0 zł | ||
+ | </ | ||
+ | |||
+ | ====== Przykład problemu produkcyjnego – " | ||
+ | |||
+ | Zakład produkcyjny wytwarza trzy rodzaje tkanin: | ||
+ | |||
+ | * **Pościelowe** | ||
+ | * **Sukienkowe** | ||
+ | * **Dekoracyjne** | ||
+ | |||
+ | Proces produkcji każdej tkaniny przebiega w trzech wydziałach: | ||
+ | |||
+ | * **Przędzalnia** | ||
+ | * **Tkalnia** | ||
+ | * **Wykończalnia** | ||
+ | |||
+ | Dla każdego rodzaju tkaniny określono: | ||
+ | |||
+ | * **Jednostkowe zużycie czasu pracy maszyn** (w minutach na 1 mb – metr bieżący), | ||
+ | * **Jednostkowy zysk** (w złotówkach na 1 mb). | ||
+ | |||
+ | Maksymalny **czas pracy maszyn** w każdym z wydziałów jest ograniczony – wartości te podano w godzinach, co należy przeliczyć na minuty (1 godzina = 60 minut). | ||
+ | |||
+ | ==== Dane wejściowe ==== | ||
+ | |||
+ | ^ Tkaniny | ||
+ | | Pościelowe | ||
+ | | Sukienkowe | ||
+ | | Dekoracyjne | ||
+ | ^ Maksymalny czas pracy maszyn (w godz.) ^ 2400 ^ 3000 ^ 2600 | ||
+ | ^ Po przeliczeniu na minuty | ||
+ | |||
+ | |||
+ | ==== Zmienna decyzyjna ==== | ||
+ | |||
+ | Niech: | ||
+ | |||
+ | * $x$ – liczba metrów bieżących tkanin **pościelowych**, | ||
+ | * $y$ – liczba metrów bieżących tkanin **sukienkowych**, | ||
+ | * $z$ – liczba metrów bieżących tkanin **dekoracyjnych**. | ||
+ | |||
+ | ==== Funkcja celu ==== | ||
+ | |||
+ | Celem jest **maksymalizacja zysku**: | ||
+ | |||
+ | $$ | ||
+ | Z = 5x + 4.5y + 6z | ||
+ | $$ | ||
+ | |||
+ | ==== Ograniczenia czasowe (przeliczone na minuty) ==== | ||
+ | |||
+ | 1. **Przędzalnia**: | ||
+ | |||
+ | $$ | ||
+ | 2x + 1y + 2z \leq 144000 | ||
+ | $$ | ||
+ | |||
+ | 2. **Tkalnia**: | ||
+ | |||
+ | $$ | ||
+ | 1x + 2y + 2z \leq 180000 | ||
+ | $$ | ||
+ | |||
+ | 3. **Wykończalnia**: | ||
+ | |||
+ | $$ | ||
+ | 2x + 2y + 1z \leq 156000 | ||
+ | $$ | ||
+ | |||
+ | 4. **Nieujemność zmiennych**: | ||
+ | |||
+ | $$ | ||
+ | x \geq 0,\quad y \geq 0,\quad z \geq 0 | ||
+ | $$ | ||
+ | |||
+ | ==== Model matematyczny ==== | ||
+ | |||
+ | $$ | ||
+ | \begin{cases} | ||
+ | \text{Maksymalizuj } Z = 5x + 4.5y + 6z \\ | ||
+ | \text{przy warunkach:} \\ | ||
+ | 2x + 1y + 2z \leq 144000 \\ | ||
+ | 1x + 2y + 2z \leq 180000 \\ | ||
+ | 2x + 2y + 1z \leq 156000 \\ | ||
+ | x, y, z \geq 0 | ||
+ | \end{cases} | ||
+ | $$ | ||
+ | |||
+ | ==== Cel zadania ==== | ||
+ | |||
+ | Wyznaczyć optymalny plan produkcji tkanin, czyli wartości $x$, $y$, $z$, które maksymalizują zysk zakładu, nie przekraczając dostępnych limitów czasu pracy maszyn w każdym dziale produkcyjnym. | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | from pulp import LpMaximize, LpProblem, LpVariable | ||
+ | |||
+ | # Tworzymy model | ||
+ | model = LpProblem(name=" | ||
+ | |||
+ | # Zmienne decyzyjne: ilość mb tkanin | ||
+ | x = LpVariable(name=" | ||
+ | y = LpVariable(name=" | ||
+ | z = LpVariable(name=" | ||
+ | |||
+ | # Funkcja celu: maksymalizacja zysku | ||
+ | model += 5 * x + 4.5 * y + 6 * z, " | ||
+ | |||
+ | # Ograniczenia czasowe – przeliczone na minuty | ||
+ | model += 2 * x + 1 * y + 2 * z <= 144_000, " | ||
+ | model += 1 * x + 2 * y + 2 * z <= 180_000, " | ||
+ | model += 2 * x + 2 * y + 1 * z <= 156_000, " | ||
+ | |||
+ | # Rozwiązanie | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | </ | ||
+ | |||
+ | === Wynik === | ||
+ | |||
+ | < | ||
+ | Optymalny plan produkcji: | ||
+ | Tkanina pościelowa: | ||
+ | Tkanina sukienkowa: | ||
+ | Tkanina dekoracyjna: | ||
+ | Maksymalny zysk: | ||
+ | </ | ||
+ | |||
+ | ====== Przykład problemu produkcyjnego – kapelusze ====== | ||
+ | |||
+ | Pracownia specjalizująca się w produkcji męskich kapeluszy i beretów dysponuje ograniczonymi zasobami surowca oraz stoi wobec ograniczonego popytu rynkowego. Celem jest opracowanie takiego planu produkcji, który **zmaksymalizuje całkowity zysk** w miesiącach jesienno-zimowych (I i IV kwartał). | ||
+ | |||
+ | ==== Treść zadania ==== | ||
+ | |||
+ | * **Surowiec**: | ||
+ | * Na jeden **kapelusz** potrzeba: **0,6 m²** filcu. | ||
+ | * Na jeden **beret** potrzeba: **0,4 m²** filcu. | ||
+ | * Łączny miesięczny **limit zakupu filcu**: **960 m²**. | ||
+ | * **Popyt rynkowy**: nie więcej niż **1000 sztuk każdego produktu miesięcznie**. | ||
+ | **Zysk jednostkowy**: | ||
+ | |||
+ | * Kapelusz: **3 zł/szt.** | ||
+ | * Beret: **2 zł/szt.** | ||
+ | |||
+ | ==== Zmienna decyzyjna ==== | ||
+ | |||
+ | Niech: | ||
+ | |||
+ | * $x$ – liczba produkowanych kapeluszy miesięcznie, | ||
+ | * $y$ – liczba produkowanych beretów miesięcznie. | ||
+ | |||
+ | ==== Funkcja celu ==== | ||
+ | |||
+ | Celem jest **maksymalizacja zysku**: | ||
+ | |||
+ | $$ | ||
+ | Z = 3x + 2y | ||
+ | $$ | ||
+ | |||
+ | ==== Ograniczenia ==== | ||
+ | |||
+ | 1. **Zużycie filcu**: | ||
+ | |||
+ | $$ | ||
+ | 0.6x + 0.4y \leq 960 | ||
+ | $$ | ||
+ | |||
+ | 2. **Ograniczenia popytowe (sprzedażowe)**: | ||
+ | |||
+ | $$ | ||
+ | x \leq 1000 \\ | ||
+ | y \leq 1000 | ||
+ | $$ | ||
+ | |||
+ | 3. **Nieujemność zmiennych**: | ||
+ | |||
+ | $$ | ||
+ | x \geq 0,\quad y \geq 0 | ||
+ | $$ | ||
+ | |||
+ | ==== Model matematyczny ==== | ||
+ | |||
+ | $$ | ||
+ | \begin{cases} | ||
+ | \text{Maksymalizuj } Z = 3x + 2y \\ | ||
+ | \text{przy warunkach:} \\ | ||
+ | 0.6x + 0.4y \leq 960 \\ | ||
+ | x \leq 1000 \\ | ||
+ | y \leq 1000 \\ | ||
+ | x, y \geq 0 | ||
+ | \end{cases} | ||
+ | $$ | ||
+ | |||
+ | ==== Cel zadania ==== | ||
+ | |||
+ | Wyznaczyć liczbę kapeluszy i beretów, jaką pracownia powinna produkować w miesiącach jesienno-zimowych, | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | from pulp import LpMaximize, LpProblem, LpVariable | ||
+ | |||
+ | # Tworzymy model maksymalizacji zysku | ||
+ | model = LpProblem(name=" | ||
+ | |||
+ | # Zmienne decyzyjne: liczba kapeluszy i beretów | ||
+ | x = LpVariable(name=" | ||
+ | y = LpVariable(name=" | ||
+ | |||
+ | # Funkcja celu: maksymalizacja zysku | ||
+ | model += 3 * x + 2 * y, " | ||
+ | |||
+ | # Ograniczenie zużycia filcu | ||
+ | model += 0.6 * x + 0.4 * y <= 960, " | ||
+ | |||
+ | # Ograniczenia popytowe | ||
+ | model += x <= 1000, " | ||
+ | model += y <= 1000, " | ||
+ | |||
+ | # Rozwiązanie | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | |||
+ | </ | ||
+ | |||
+ | === Wynik: === | ||
+ | |||
+ | < | ||
+ | Optymalny plan produkcji: | ||
+ | Kapelusze: 1000 szt. | ||
+ | Berety: | ||
+ | Maksymalny zysk: 4800.00 zł | ||
+ | </ | ||
+ | |||
+ | ====== Przykład problemu produkcyjnego – Pani Zuzia ====== | ||
+ | |||
+ | Pani Zuzia prowadzi małą firmę gastronomiczną, | ||
+ | |||
+ | ==== Treść zadania ==== | ||
+ | |||
+ | Dania oferowane: | ||
+ | |||
+ | * **Maxi** – cena: 19 zł | ||
+ | * **Mini** – cena: 11 zł | ||
+ | Składniki potrzebne do przygotowania: | ||
+ | |||
+ | | ||
+ | |||
+ | * Maxi: 7 dag (0,07 kg) | ||
+ | * Mini: 4 dag (0,04 kg) | ||
+ | |||
+ | **Kapusta**: | ||
+ | |||
+ | * Maxi: 10 dag (0,10 kg) | ||
+ | * Mini: 7 dag (0,07 kg) | ||
+ | Dzienne zapasy: | ||
+ | |||
+ | * **Mięso**: 1,3 kg | ||
+ | * **Kapusta**: | ||
+ | |||
+ | ==== Zmienna decyzyjna ==== | ||
+ | |||
+ | Niech: | ||
+ | |||
+ | * $x$ – liczba dań typu **Maxi**, | ||
+ | * $y$ – liczba dań typu **Mini**. | ||
+ | |||
+ | ==== Funkcja celu ==== | ||
+ | |||
+ | Celem jest **maksymalizacja przychodu**: | ||
+ | |||
+ | $$ | ||
+ | Z = 19x + 11y | ||
+ | $$ | ||
+ | |||
+ | ==== Ograniczenia zasobów ==== | ||
+ | |||
+ | 1. **Mięso**: | ||
+ | |||
+ | $$ | ||
+ | 0.07x + 0.04y \leq 1.3 | ||
+ | $$ | ||
+ | |||
+ | 2. **Kapusta**: | ||
+ | |||
+ | $$ | ||
+ | 0.10x + 0.07y \leq 2.0 | ||
+ | $$ | ||
+ | |||
+ | 3. **Nieujemność zmiennych**: | ||
+ | |||
+ | $$ | ||
+ | x \geq 0,\quad y \geq 0 | ||
+ | $$ | ||
+ | |||
+ | ==== Model matematyczny ==== | ||
+ | |||
+ | $$ | ||
+ | \begin{cases} | ||
+ | \text{Maksymalizuj } Z = 19x + 11y \\ | ||
+ | \text{przy warunkach:} \\ | ||
+ | 0.07x + 0.04y \leq 1.3 \\ | ||
+ | 0.10x + 0.07y \leq 2.0 \\ | ||
+ | x, y \geq 0 | ||
+ | \end{cases} | ||
+ | $$ | ||
+ | |||
+ | ==== Cel zadania ==== | ||
+ | |||
+ | Wyznaczyć ile dań typu **Maxi** oraz **Mini** powinna przygotowywać Pani Zuzia dziennie, aby osiągnąć **maksymalny możliwy przychód**, | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | from pulp import LpMaximize, LpProblem, LpVariable, LpInteger | ||
+ | |||
+ | # Tworzymy model optymalizacji | ||
+ | model = LpProblem(name=" | ||
+ | |||
+ | # Zmienne decyzyjne jako liczby całkowite | ||
+ | x = LpVariable(name=" | ||
+ | y = LpVariable(name=" | ||
+ | |||
+ | # Funkcja celu: maksymalizacja przychodu | ||
+ | model += 19 * x + 11 * y, " | ||
+ | |||
+ | # Ograniczenia surowców | ||
+ | model += 0.07 * x + 0.04 * y <= 1.3, " | ||
+ | model += 0.10 * x + 0.07 * y <= 2.0, " | ||
+ | |||
+ | # Rozwiązanie problemu | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | print(f" | ||
+ | </ | ||
+ | |||
+ | === Wynik: === | ||
+ | |||
+ | < | ||
+ | Optymalny plan produkcji (liczby całkowite): | ||
+ | Dania Maxi: 14 szt. | ||
+ | Dania Mini: 8 szt. | ||
+ | Maksymalny przychód: 354.00 zł | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== Przykład Minimalizacyjny Ogrzewanie pomieszczeń ====== | ||
+ | |||
+ | Do ogrzania dwóch pomieszczeń o początkowej temperaturze 0°C można używać dwóch źródeł ciepła: węgla i koksu. Każde z tych paliw wpływa inaczej na temperaturę w pomieszczeniach, | ||
+ | |||
+ | ===== Dane wejściowe ===== | ||
+ | Początkowa temperatura w obu pomieszczeniach: | ||
+ | Minimalne wymagane temperatury: | ||
+ | * Pomieszczenie 1: co najmniej 180°C | ||
+ | * Pomieszczenie 2: co najmniej 200°C | ||
+ | fekt spalania: | ||
+ | **1 kg węgla**: | ||
+ | * Pomieszczenie 1: +30°C | ||
+ | * Pomieszczenie 2: +20°C | ||
+ | **1 kg koksu**: | ||
+ | * Pomieszczenie 1: +10°C | ||
+ | * Pomieszczenie 2: +20°C | ||
+ | Koszty: | ||
+ | * 1 tona węgla: 500 zł → 1 kg = 0,50 zł | ||
+ | * 1 tona koksu: 300 zł → 1 kg = 0,30 zł | ||
+ | |||
+ | ===== Zmienne decyzyjne ===== | ||
+ | * $ x $ – liczba **kg węgla** do spalenia | ||
+ | * $ y $ – liczba **kg koksu** do spalenia | ||
+ | |||
+ | ===== Funkcja celu ===== | ||
+ | Minimalizacja łącznego kosztu ogrzewania: | ||
+ | $$ | ||
+ | \min Z = 0.50x + 0.30y | ||
+ | $$ | ||
+ | |||
+ | ===== Ograniczenia ===== | ||
+ | Temperatury muszą być osiągnięte lub przekroczone: | ||
+ | |||
+ | * Dla pierwszego pomieszczenia: | ||
+ | $$ | ||
+ | 30x + 10y \geq 180 | ||
+ | $$ | ||
+ | |||
+ | * Dla drugiego pomieszczenia: | ||
+ | $$ | ||
+ | 20x + 20y \geq 200 | ||
+ | $$ | ||
+ | |||
+ | * Dodatkowo, nie możemy spalać ujemnych ilości paliwa: | ||
+ | $$ | ||
+ | x \geq 0,\quad y \geq 0 | ||
+ | $$ | ||
+ | |||
+ | ===== Cel ===== | ||
+ | Wyznaczyć minimalne ilości węgla $ x $ i koksu $ y $, które pozwolą uzyskać wymaganą temperaturę w obu pomieszczeniach przy **najniższym koszcie ogrzewania**. | ||
+ | |||
+ | ===== Rozwiązanie ===== | ||
+ | Rozwiązanie można uzyskać za pomocą: | ||
+ | * arkusza kalkulacyjnego (Excel: dodając Solver), | ||
+ | * programowania liniowego w Pythonie (np. z użyciem biblioteki PuLP), | ||
+ | * metody graficznej (jeśli szukamy wizualnego zrozumienia dla 2 zmiennych). | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | from pulp import LpProblem, LpVariable, LpMinimize, LpStatus, value | ||
+ | |||
+ | # Tworzenie modelu | ||
+ | model = LpProblem(" | ||
+ | |||
+ | # Zmienne decyzyjne: kg węgla (x), kg koksu (y) | ||
+ | x = LpVariable(" | ||
+ | y = LpVariable(" | ||
+ | |||
+ | # Funkcja celu: minimalizacja kosztów | ||
+ | model += 0.50 * x + 0.30 * y, " | ||
+ | |||
+ | # Ograniczenia temperatury | ||
+ | model += 30 * x + 10 * y >= 180, " | ||
+ | model += 20 * x + 20 * y >= 200, " | ||
+ | |||
+ | # Rozwiązanie | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | === Wynik: === | ||
+ | < | ||
+ | Status: Optimal | ||
+ | Węgiel (kg): 4.0 | ||
+ | Koks (kg): 6.0 | ||
+ | Minimalny koszt (zł): 3.8 | ||
+ | </ | ||
+ | |||
+ | ====== Problem transportowy - Transport mieszanki soli i piasku ====== | ||
+ | |||
+ | Miasto musi w okresie zimowym dostarczyć mieszankę soli i piasku z dwóch składnic do czterech dzielnic. Celem jest ustalenie takiego planu transportu, który **zaspokoi zapotrzebowanie wszystkich dzielnic** przy **najniższym możliwym koszcie transportu**. | ||
+ | |||
+ | ===== Dane wejściowe ===== | ||
+ | * Miasto dysponuje **dwiema składnicami** materiału. | ||
+ | * Materiał musi być rozwieziony do **czterech dzielnic**. | ||
+ | * Każda dzielnica ma określone **zapotrzebowanie na mieszankę (w tonach)**. | ||
+ | * Każda składnica ma ograniczoną **maksymalną ilość materiału, jaką może dostarczyć**. | ||
+ | * Koszty transportu (w zł/t) różnią się w zależności od trasy (składnica–dzielnica). | ||
+ | |||
+ | ==== Tabela kosztów transportu i zapotrzebowań ==== | ||
+ | |||
+ | ^ Dzielnica ^ Składnica 1 (zł/t) ^ Składnica 2 (zł/t) ^ Zapotrzebowanie (t) ^ | ||
+ | | 1 | 2.00 | 4.00 | 300 | | ||
+ | | 2 | 3.00 | 3.50 | 450 | | ||
+ | | 3 | 1.50 | 2.50 | 500 | | ||
+ | | 4 | 2.50 | 3.00 | 350 | | ||
+ | |||
+ | ==== Pojemności składnic ==== | ||
+ | |||
+ | * Składnica 1: **900 ton** | ||
+ | * Składnica 2: **750 ton** | ||
+ | |||
+ | ===== Zmienne decyzyjne ===== | ||
+ | Niech: | ||
+ | $x_{ij}$ – ilość ton mieszanki przetransportowanej ze składnicy $i$ do dzielnicy $j$, | ||
+ | gdzie $i \in \{1, 2\}$ i $j \in \{1, 2, 3, 4\}$. | ||
+ | |||
+ | ===== Funkcja celu ===== | ||
+ | Minimalizacja całkowitego kosztu transportu: | ||
+ | |||
+ | $$ | ||
+ | Z = \min \sum_{i=1}^{2} \sum_{j=1}^{4} c_{ij} \cdot x_{ij} | ||
+ | $$ | ||
+ | |||
+ | Gdzie $c_{ij}$ to koszt transportu 1 tony ze składnicy $i$ do dzielnicy $j$. | ||
+ | |||
+ | ===== Ograniczenia ===== | ||
+ | **Pojemności składnic: | ||
+ | |||
+ | $$ | ||
+ | x_{11} + x_{12} + x_{13} + x_{14} \leq 900 \\ | ||
+ | x_{21} + x_{22} + x_{23} + x_{24} \leq 750 | ||
+ | $$ | ||
+ | |||
+ | **Zapotrzebowanie dzielnic:** | ||
+ | |||
+ | $$ | ||
+ | x_{11} + x_{21} = 300 \\ | ||
+ | x_{12} + x_{22} = 450 \\ | ||
+ | x_{13} + x_{23} = 500 \\ | ||
+ | x_{14} + x_{24} = 350 | ||
+ | $$ | ||
+ | |||
+ | **Nieujemność zmiennych: | ||
+ | |||
+ | $$ | ||
+ | x_{ij} \geq 0 \quad \text{dla każdego } i, j | ||
+ | $$ | ||
+ | |||
+ | ===== Cel ===== | ||
+ | Wyznaczyć optymalne wartości $x_{ij}$, aby **całkowity koszt transportu był jak najmniejszy**, | ||
+ | |||
+ | ===== Uwagi ===== | ||
+ | To klasyczny przykład tzw. **problemu transportowego** w programowaniu liniowym. Rozwiązanie można znaleźć m.in. za pomocą: | ||
+ | * metody potencjałów (ręcznie lub w arkuszu kalkulacyjnym), | ||
+ | * programowania liniowego w Pythonie (np. `PuLP`, `scipy.optimize`), | ||
+ | * narzędzi takich jak Excel Solver. | ||
+ | |||
+ | ==== Rozwiązanie w Pythonie (biblioteka `PuLP`) ==== | ||
+ | |||
+ | Python oferuje bibliotekę `PuLP`, która umożliwia tworzenie i rozwiązywanie problemów programowania liniowego. | ||
+ | |||
+ | === Przykładowy kod: === | ||
+ | |||
+ | <code python> | ||
+ | import pulp | ||
+ | |||
+ | # Tworzymy problem minimalizacji kosztów | ||
+ | problem = pulp.LpProblem(" | ||
+ | |||
+ | # Składnice i dzielnice | ||
+ | skladnice = [1, 2] | ||
+ | dzielnice = [1, 2, 3, 4] | ||
+ | |||
+ | # Koszty transportu c_ij (słownik) | ||
+ | koszty = { | ||
+ | (1, 1): 2.00, (1, 2): 3.00, (1, 3): 1.50, (1, 4): 2.50, | ||
+ | (2, 1): 4.00, (2, 2): 3.50, (2, 3): 2.50, (2, 4): 3.00 | ||
+ | } | ||
+ | |||
+ | # Zapotrzebowania dzielnic | ||
+ | zapotrzebowanie = {1: 300, 2: 450, 3: 500, 4: 350} | ||
+ | |||
+ | # Pojemności składnic | ||
+ | pojemnosc = {1: 900, 2: 750} | ||
+ | |||
+ | # Zmienne decyzyjne x_ij: ilość materiału z i-tej składnicy do j-tej dzielnicy | ||
+ | x = pulp.LpVariable.dicts(" | ||
+ | lowBound=0, cat=' | ||
+ | |||
+ | # Funkcja celu: minimalizacja kosztu transportu | ||
+ | problem += pulp.lpSum(koszty[i, | ||
+ | |||
+ | # Ograniczenia pojemności składnic | ||
+ | for i in skladnice: | ||
+ | problem += pulp.lpSum(x[i, | ||
+ | |||
+ | # Ograniczenia zapotrzebowania dzielnic | ||
+ | for j in dzielnice: | ||
+ | problem += pulp.lpSum(x[i, | ||
+ | |||
+ | # Rozwiązanie problemu | ||
+ | problem.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(" | ||
+ | |||
+ | for i in skladnice: | ||
+ | for j in dzielnice: | ||
+ | print(f" | ||
+ | |||
+ | </ | ||
+ | === Wynik === | ||
+ | |||
+ | < | ||
+ | Status: Optimal | ||
+ | Minimalny koszt transportu: 3925.0 zł | ||
+ | x(1,1) = 300.0 t | ||
+ | x(1,2) = 0.0 t | ||
+ | x(1,3) = 500.0 t | ||
+ | x(1,4) = 100.0 t | ||
+ | x(2,1) = 0.0 t | ||
+ | x(2,2) = 450.0 t | ||
+ | x(2,3) = 0.0 t | ||
+ | x(2,4) = 250.0 t | ||
+ | </ | ||
+ | ====== Transport truskawek ====== | ||
+ | |||
+ | W sezonie letnim truskawki zbierane przez plantatorów muszą być dostarczone do punktów skupu. Każdy z plantatorów dysponuje określoną ilością truskawek (w tonach), a każdy punkt skupu ma sprecyzowane zapotrzebowanie. Celem jest tak zaplanować transport, aby **pokryć zapotrzebowanie punktów skupu przy minimalnych kosztach transportu**. | ||
+ | |||
+ | ===== Dane wejściowe ===== | ||
+ | |||
+ | **Dostępność truskawek u plantatorów: | ||
+ | * Plantator I: 12 tony | ||
+ | * Plantator II: 30 ton | ||
+ | * Plantator III: 6 ton | ||
+ | |||
+ | **Zapotrzebowanie punktów skupu:** | ||
+ | * Punkt A: 18 ton | ||
+ | * Punkt B: 12 ton | ||
+ | * Punkt C: 18 ton | ||
+ | |||
+ | ==== Tabela kosztów transportu (w zł za 1 tonę) ==== | ||
+ | |||
+ | ^ Plantator ↓ / Punkt → ^ A ^ B ^ C ^ | ||
+ | | I | 80 | 160 | 160 | | ||
+ | | II |240 | 320 | 80 | | ||
+ | | III | 32 | 160 | 32 | | ||
+ | |||
+ | ===== Zmienne decyzyjne ===== | ||
+ | Niech: | ||
+ | * $x_{ij}$ – ilość ton truskawek transportowana od plantatora $i$ do punktu skupu $j$ | ||
+ | gdzie $i \in \{1,2,3\}$ (plantatorzy) i $j \in \{A,B,C\}$ (punkty skupu) | ||
+ | |||
+ | ===== Funkcja celu ===== | ||
+ | Minimalizacja całkowitego kosztu transportu: | ||
+ | |||
+ | $$ | ||
+ | Z = \min \sum_{i=1}^{3} \sum_{j \in \{A,B,C\}} c_{ij} \cdot x_{ij} | ||
+ | $$ | ||
+ | |||
+ | Gdzie $c_{ij}$ to koszt transportu 1 tony z plantatora $i$ do punktu skupu $j$. | ||
+ | |||
+ | ===== Ograniczenia ===== | ||
+ | |||
+ | **Dostępność u plantatorów: | ||
+ | $$ | ||
+ | x_{1A} + x_{1B} + x_{1C} \leq 24 \\ | ||
+ | x_{2A} + x_{2B} + x_{2C} \leq 30 \\ | ||
+ | x_{3A} + x_{3B} + x_{3C} \leq 6 | ||
+ | $$ | ||
+ | |||
+ | **Zapotrzebowanie punktów skupu:** | ||
+ | $$ | ||
+ | x_{1A} + x_{2A} + x_{3A} = 18 \\ | ||
+ | x_{1B} + x_{2B} + x_{3B} = 12 \\ | ||
+ | x_{1C} + x_{2C} + x_{3C} = 18 | ||
+ | $$ | ||
+ | |||
+ | **Nieujemność zmiennych: | ||
+ | $$ | ||
+ | x_{ij} \geq 0 \quad \text{dla każdego } i,j | ||
+ | $$ | ||
+ | |||
+ | ===== Cel ===== | ||
+ | Wyznaczyć optymalne wartości zmiennych $x_{ij}$, aby: | ||
+ | * Całkowity koszt transportu był **najniższy** | ||
+ | * Spełnione zostały ograniczenia dostępności i zapotrzebowania | ||
+ | |||
+ | ===== Uwagi ===== | ||
+ | To klasyczny **problem transportowy** możliwy do rozwiązania z użyciem: | ||
+ | * **Python + PuLP** | ||
+ | * **Excel Solver** | ||
+ | * **Metody północno-zachodniego narożnika + metoda potencjałów** (dla zadań ręcznych) | ||
+ | === Kod === | ||
+ | <code python> | ||
+ | from pulp import LpProblem, LpVariable, LpMinimize, LpStatus, lpSum, value | ||
+ | |||
+ | # Model | ||
+ | model = LpProblem(" | ||
+ | |||
+ | # Plantatorzy i punkty skupu | ||
+ | plantatorzy = [' | ||
+ | punkty_skupu = [' | ||
+ | |||
+ | # Koszty transportu (zł/t) | ||
+ | koszty = { | ||
+ | (' | ||
+ | (' | ||
+ | (' | ||
+ | } | ||
+ | |||
+ | # Ilość dostępnych truskawek (t) | ||
+ | dostawy = {' | ||
+ | |||
+ | # Zapotrzebowanie punktów skupu (t) | ||
+ | zapotrzebowanie = {' | ||
+ | |||
+ | # Zmienne decyzyjne | ||
+ | x = { | ||
+ | (p, s): LpVariable(f" | ||
+ | for p in plantatorzy for s in punkty_skupu | ||
+ | } | ||
+ | |||
+ | # Funkcja celu: minimalizacja kosztów transportu | ||
+ | model += lpSum(koszty[p, | ||
+ | |||
+ | # Ograniczenia dostępności plantatorów | ||
+ | for p in plantatorzy: | ||
+ | model += lpSum(x[p, s] for s in punkty_skupu) <= dostawy[p], f" | ||
+ | |||
+ | # Ograniczenia zapotrzebowania punktów skupu | ||
+ | for s in punkty_skupu: | ||
+ | model += lpSum(x[p, s] for p in plantatorzy) == zapotrzebowanie[s], | ||
+ | |||
+ | # Rozwiązanie | ||
+ | model.solve() | ||
+ | |||
+ | # Wyniki | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | for p in plantatorzy: | ||
+ | for s in punkty_skupu: | ||
+ | print(f" | ||
+ | </ | ||
+ | === Wynik: === | ||
+ | < | ||
+ | Status: Optimal | ||
+ | Minimalny koszt transportu (zł): 6432.0 | ||
+ | |||
+ | Wielkości dostaw (t): | ||
+ | P1 -> A: 0.0 t | ||
+ | P1 -> B: 12.0 t | ||
+ | P1 -> C: 0.0 t | ||
+ | P2 -> A: 12.0 t | ||
+ | P2 -> B: 0.0 t | ||
+ | P2 -> C: 18.0 t | ||
+ | P3 -> A: 6.0 t | ||
+ | P3 -> B: 0.0 t | ||
+ | P3 -> C: 0.0 t | ||
+ | </ |