54 lines
2.4 KiB
Python
54 lines
2.4 KiB
Python
|
|
#!/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.")
|