#!/usr/bin/env python3 # Matrixform.py """ Kapitel Fundament: Von der ausgeschriebenen Form zur Matrixform - und zurück. Zeigt, dass beide Schreibweisen dasselbe Modell beschreiben. """ import numpy as np from scipy.optimize import linprog # --- Modell in Matrixform ------------------------------------------------- # max 3*x1 + 5*x2 u.d.N. x1 <= 4, 2*x2 <= 12, 3*x1 + 2*x2 <= 18, x >= 0 c = np.array([3.0, 5.0]) # Ertragsvektor (Maximierung) A = np.array([[1.0, 0.0], # Zeile 1: nur x1 kommt vor [0.0, 2.0], # Zeile 2: nur x2 kommt vor [3.0, 2.0]]) # Zeile 3: beide b = np.array([4.0, 12.0, 18.0]) namen = ["Rohstoff A", "Rohstoff B", "Maschinenzeit"] # --- Ausgeschriebene Form maschinell erzeugen ------------------------------ def zeige_ausgeschrieben(c, A, b, namen): """Druckt die Matrixform als lesbares Ungleichungssystem.""" terme = " + ".join(f"{c[j]:g}*x{j+1}" for j in range(len(c))) print(f"max {terme}") print("u.d.N.") for i in range(A.shape[0]): summanden = " + ".join(f"{A[i, j]:g}*x{j+1}" for j in range(A.shape[1]) if A[i, j] != 0) print(f" {summanden:<24} <= {b[i]:>5g} ({namen[i]})") print(f" x1, ..., x{len(c)} >= 0") zeige_ausgeschrieben(c, A, b, namen) # --- Zulässigkeit eines Punktes prüfen ------------------------------------ def ist_zulaessig(x, A, b, toleranz=1e-9): """Prüft A x <= b und x >= 0 komponentenweise.""" verbrauch = A @ x # Matrix-Vektor-Produkt: alle Zeilen auf einmal return bool(np.all(verbrauch <= b + toleranz) and np.all(x >= -toleranz)) for kandidat in [np.array([2.0, 6.0]), np.array([4.0, 3.0]), np.array([4.0, 6.0])]: zulaessig = ist_zulaessig(kandidat, A, b) zielwert = c @ kandidat verbrauch = A @ kandidat print(f"\nx = {kandidat} -> A x = {verbrauch} " f"{'zulaessig' if zulaessig else 'UNZULAESSIG'}, Z = {zielwert:g}") # --- Lösen: linprog minimiert, also c negieren ----------------------------- ergebnis = linprog(c=-c, A_ub=A, b_ub=b, bounds=[(0, None)] * len(c), method="highs") print("\n" + "-" * 60) print(f"Optimale Loesung: x* = {np.round(ergebnis.x, 4)}") print(f"Optimaler Wert: Z* = {-ergebnis.fun:g}") print("Hinweis: linprog minimiert, deshalb wurde c negiert und das") print(" Ergebnis am Ende wieder mit -1 multipliziert.")