refactoring: constraints
This commit is contained in:
parent
b65dd3ef95
commit
d520dcafc5
39
STRUKTUR.md
39
STRUKTUR.md
@ -26,9 +26,19 @@
|
|||||||
- `Dienst`: Datenmodell für Diensttypen
|
- `Dienst`: Datenmodell für Diensttypen
|
||||||
- `Elterndienstplaner`: Hauptklasse mit Optimierungslogik
|
- `Elterndienstplaner`: Hauptklasse mit Optimierungslogik
|
||||||
- Fairness-Berechnungen (global/lokal)
|
- Fairness-Berechnungen (global/lokal)
|
||||||
- Optimierungsmodell-Erstellung
|
- Optimierungsmodell-Erstellung (modular aufgeteilt)
|
||||||
- Statistiken
|
- Statistiken
|
||||||
|
|
||||||
|
**Constraint-Funktionen** (modular aufgeteilt):
|
||||||
|
- `_erstelle_entscheidungsvariablen()`: Erstellt binäre Variablen
|
||||||
|
- `_add_constraint_ein_dienst_pro_woche()`: C1 - Max 1 Dienst pro Woche
|
||||||
|
- `_add_constraint_ein_dienst_pro_tag()`: C2 - Max 1 Dienst pro Tag
|
||||||
|
- `_add_constraint_verfuegbarkeit()`: C3 - Nur verfügbare Eltern
|
||||||
|
- `_add_constraint_dienst_bedarf()`: C4 - Alle Dienste müssen besetzt werden
|
||||||
|
- `_add_fairness_constraints()`: F1 & F2 - Erstellt Variablen und Constraints für Fairness
|
||||||
|
- `_berechne_fairness_gewichte()`: Zeitabhängige Gewichtung (Sep-Jul)
|
||||||
|
- `_erstelle_zielfunktion()`: Zielfunktion mit Fairness & Präferenzen
|
||||||
|
|
||||||
**Abhängigkeiten**:
|
**Abhängigkeiten**:
|
||||||
- Importiert `csv_io` für Datei-Operationen
|
- Importiert `csv_io` für Datei-Operationen
|
||||||
- Verwendet `pulp` für lineare Optimierung
|
- Verwendet `pulp` für lineare Optimierung
|
||||||
@ -41,7 +51,7 @@ elterndienstplaner.py (700+ Zeilen)
|
|||||||
├── Dienst Klasse
|
├── Dienst Klasse
|
||||||
├── CSV Parsing (150+ Zeilen)
|
├── CSV Parsing (150+ Zeilen)
|
||||||
├── Fairness-Berechnung
|
├── Fairness-Berechnung
|
||||||
├── Optimierung
|
├── Optimierung (200+ Zeilen inline)
|
||||||
└── CSV Schreiben
|
└── CSV Schreiben
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -54,30 +64,29 @@ csv_io.py (220 Zeilen)
|
|||||||
elterndienstplaner.py (500 Zeilen)
|
elterndienstplaner.py (500 Zeilen)
|
||||||
├── Dienst Klasse
|
├── Dienst Klasse
|
||||||
├── Fairness-Berechnung
|
├── Fairness-Berechnung
|
||||||
├── Optimierung
|
│ ├── berechne_faire_zielverteilung_global()
|
||||||
|
│ └── berechne_faire_zielverteilung_lokal()
|
||||||
|
├── Optimierung (modular)
|
||||||
|
│ ├── erstelle_optimierungsmodell() (30 Zeilen - übersichtlich!)
|
||||||
|
│ ├── _erstelle_entscheidungsvariablen()
|
||||||
|
│ ├── _add_constraint_ein_dienst_pro_woche()
|
||||||
|
│ ├── _add_constraint_ein_dienst_pro_tag()
|
||||||
|
│ ├── _add_constraint_verfuegbarkeit()
|
||||||
|
│ ├── _add_constraint_dienst_bedarf()
|
||||||
|
│ ├── _add_fairness_constraints()
|
||||||
|
│ └── _erstelle_zielfunktion()
|
||||||
└── Statistiken
|
└── Statistiken
|
||||||
```
|
```
|
||||||
|
|
||||||
## Nächste Schritte (Optional)
|
## Nächste Schritte (Optional)
|
||||||
|
|
||||||
### Phase 2: Constraint-Funktionen auslagern
|
|
||||||
```python
|
|
||||||
def _add_constraint_ein_dienst_pro_woche(prob, x, ...):
|
|
||||||
"""C1: Je Eltern und Dienst nur einmal die Woche"""
|
|
||||||
|
|
||||||
def _add_constraint_ein_dienst_pro_tag(prob, x, ...):
|
|
||||||
"""C2: Je Eltern nur einen Dienst am Tag"""
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 3: Fairness-Modul (optional)
|
### Phase 3: Fairness-Modul (optional)
|
||||||
```
|
```
|
||||||
fairness.py
|
fairness.py
|
||||||
├── FairnessBerechner
|
├── FairnessBerechner
|
||||||
│ ├── berechne_global()
|
│ ├── berechne_global()
|
||||||
│ └── berechne_lokal()
|
│ └── berechne_lokal()
|
||||||
```
|
```## Verwendung
|
||||||
|
|
||||||
## Verwendung
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from csv_io import EingabeParser, AusgabeWriter
|
from csv_io import EingabeParser, AusgabeWriter
|
||||||
|
|||||||
@ -254,21 +254,8 @@ class Elterndienstplaner:
|
|||||||
|
|
||||||
return ziel_dienste_lokal
|
return ziel_dienste_lokal
|
||||||
|
|
||||||
def erstelle_optimierungsmodell(self) -> Tuple[pulp.LpProblem, Dict[Tuple[str, date, Dienst], pulp.LpVariable]]:
|
def _erstelle_entscheidungsvariablen(self) -> Dict[Tuple[str, date, Dienst], pulp.LpVariable]:
|
||||||
"""Erstellt das PuLP Optimierungsmodell"""
|
"""Erstellt die binären Entscheidungsvariablen x[eltern, tag, dienst]"""
|
||||||
print("Erstelle Optimierungsmodell...")
|
|
||||||
|
|
||||||
# Debugging: Verfügbarkeit prüfen
|
|
||||||
print("\nDebug: Verfügbarkeit analysieren...")
|
|
||||||
for tag in self.tage[:5]: # Erste 5 Tage
|
|
||||||
verfügbare = [e for e in self.eltern if self.verfügbarkeit.get((e, tag), True)]
|
|
||||||
benötigte = self.benoetigte_dienste.get(tag, [])
|
|
||||||
print(f" {tag}: Benötigt {len(benötigte)} Dienste {benötigte}, verfügbar: {verfügbare}")
|
|
||||||
|
|
||||||
# LP Problem erstellen
|
|
||||||
prob = pulp.LpProblem("Elterndienstplaner", pulp.LpMinimize)
|
|
||||||
|
|
||||||
# Entscheidungsvariablen: x[eltern, tag, dienst] ∈ {0,1}
|
|
||||||
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable] = {}
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable] = {}
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
for tag in self.tage:
|
for tag in self.tage:
|
||||||
@ -278,10 +265,14 @@ class Elterndienstplaner:
|
|||||||
f"x_{eltern.replace(' ', '_')}_{tag}_{dienst.kuerzel}",
|
f"x_{eltern.replace(' ', '_')}_{tag}_{dienst.kuerzel}",
|
||||||
cat='Binary'
|
cat='Binary'
|
||||||
)
|
)
|
||||||
|
return x
|
||||||
|
|
||||||
# Vereinfachtes Modell: Grundlegende Constraints
|
def _add_constraint_ein_dienst_pro_woche(
|
||||||
|
self,
|
||||||
# C1: Je Eltern und Dienst nur einmal die Woche
|
prob: pulp.LpProblem,
|
||||||
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable]
|
||||||
|
) -> None:
|
||||||
|
"""C1: Je Eltern und Dienst nur einmal die Woche"""
|
||||||
woche_start = self.tage[0]
|
woche_start = self.tage[0]
|
||||||
woche_nr = 0
|
woche_nr = 0
|
||||||
while woche_start <= self.tage[-1]:
|
while woche_start <= self.tage[-1]:
|
||||||
@ -296,12 +287,18 @@ class Elterndienstplaner:
|
|||||||
woche_vars.append(x[eltern, tag, dienst])
|
woche_vars.append(x[eltern, tag, dienst])
|
||||||
|
|
||||||
if woche_vars:
|
if woche_vars:
|
||||||
prob += pulp.lpSum(woche_vars) <= 1, f"C1_{eltern.replace(' ', '_')}_{dienst.kuerzel}_w{woche_nr}"
|
prob += pulp.lpSum(woche_vars) <= 1, \
|
||||||
|
f"C1_{eltern.replace(' ', '_')}_{dienst.kuerzel}_w{woche_nr}"
|
||||||
|
|
||||||
woche_start += timedelta(days=7)
|
woche_start += timedelta(days=7)
|
||||||
woche_nr += 1
|
woche_nr += 1
|
||||||
|
|
||||||
# C2: Je Eltern nur einen Dienst am Tag
|
def _add_constraint_ein_dienst_pro_tag(
|
||||||
|
self,
|
||||||
|
prob: pulp.LpProblem,
|
||||||
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable]
|
||||||
|
) -> None:
|
||||||
|
"""C2: Je Eltern nur einen Dienst am Tag"""
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
for tag in self.tage:
|
for tag in self.tage:
|
||||||
tag_vars = []
|
tag_vars = []
|
||||||
@ -312,39 +309,50 @@ class Elterndienstplaner:
|
|||||||
if tag_vars:
|
if tag_vars:
|
||||||
prob += pulp.lpSum(tag_vars) <= 1, f"C2_{eltern.replace(' ', '_')}_{tag}"
|
prob += pulp.lpSum(tag_vars) <= 1, f"C2_{eltern.replace(' ', '_')}_{tag}"
|
||||||
|
|
||||||
# C3: Dienste nur verfügbaren Eltern zuteilen
|
def _add_constraint_verfuegbarkeit(
|
||||||
|
self,
|
||||||
|
prob: pulp.LpProblem,
|
||||||
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable]
|
||||||
|
) -> None:
|
||||||
|
"""C3: Dienste nur verfügbaren Eltern zuteilen"""
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
for tag in self.tage:
|
for tag in self.tage:
|
||||||
if not self.verfügbarkeit.get((eltern, tag), True):
|
if not self.verfügbarkeit.get((eltern, tag), True):
|
||||||
for dienst in self.dienste:
|
for dienst in self.dienste:
|
||||||
if (eltern, tag, dienst) in x:
|
if (eltern, tag, dienst) in x:
|
||||||
prob += x[eltern, tag, dienst] == 0, f"C3_{eltern.replace(' ', '_')}_{tag}_{dienst.kuerzel}"
|
prob += x[eltern, tag, dienst] == 0, \
|
||||||
|
f"C3_{eltern.replace(' ', '_')}_{tag}_{dienst.kuerzel}"
|
||||||
|
|
||||||
# Alle benötigten Dienste müssen zugeteilt werden (flexibel)
|
def _add_constraint_dienst_bedarf(
|
||||||
|
self,
|
||||||
|
prob: pulp.LpProblem,
|
||||||
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable]
|
||||||
|
) -> None:
|
||||||
|
"""C4: Alle benötigten Dienste müssen zugeteilt werden"""
|
||||||
for tag in self.tage:
|
for tag in self.tage:
|
||||||
for dienst in self.benoetigte_dienste.get(tag, []):
|
for dienst in self.benoetigte_dienste.get(tag, []):
|
||||||
dienst_vars = []
|
dienst_vars = []
|
||||||
verfuegbare_eltern = 0
|
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
if (eltern, tag, dienst) in x:
|
if (eltern, tag, dienst) in x:
|
||||||
# Prüfe ob Eltern verfügbar
|
# Prüfe ob Eltern verfügbar
|
||||||
if self.verfügbarkeit.get((eltern, tag), True):
|
if self.verfügbarkeit.get((eltern, tag), True):
|
||||||
dienst_vars.append(x[eltern, tag, dienst])
|
dienst_vars.append(x[eltern, tag, dienst])
|
||||||
verfuegbare_eltern += 1
|
|
||||||
|
|
||||||
if dienst_vars:
|
if dienst_vars:
|
||||||
# Anzahl benötigter Personen pro Dienst (aus Dienst-Objekt)
|
# Anzahl benötigter Personen pro Dienst (aus Dienst-Objekt)
|
||||||
benoetigte_personen = dienst.personen_anzahl
|
benoetigte_personen = dienst.personen_anzahl
|
||||||
prob += pulp.lpSum(dienst_vars) == benoetigte_personen, f"Bedarf_{tag}_{dienst.kuerzel}"
|
prob += pulp.lpSum(dienst_vars) == benoetigte_personen, \
|
||||||
|
f"Bedarf_{tag}_{dienst.kuerzel}"
|
||||||
|
|
||||||
# FAIRNESS-CONSTRAINTS UND ZIELFUNKTION
|
def _add_fairness_constraints(
|
||||||
objective_terms = []
|
self,
|
||||||
|
prob: pulp.LpProblem,
|
||||||
# Berechne faire Zielverteilungen (global und lokal)
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable],
|
||||||
ziel_dienste_global = self.berechne_faire_zielverteilung_global()
|
ziel_dienste_global: DefaultDict[str, DefaultDict[Dienst, float]],
|
||||||
ziel_dienste_lokal = self.berechne_faire_zielverteilung_lokal()
|
ziel_dienste_lokal: DefaultDict[str, DefaultDict[Dienst, float]]
|
||||||
|
) -> Tuple[Dict, Dict]:
|
||||||
# Hilfsvariablen für Fairness-Abweichungen
|
"""F1 & F2: Erstellt Fairness-Variablen und fügt Fairness-Constraints hinzu (global und lokal)"""
|
||||||
|
# Hilfsvariablen für Fairness-Abweichungen erstellen
|
||||||
fairness_abweichung_lokal = {} # F2
|
fairness_abweichung_lokal = {} # F2
|
||||||
fairness_abweichung_global = {} # F1
|
fairness_abweichung_global = {} # F1
|
||||||
|
|
||||||
@ -355,7 +363,7 @@ class Elterndienstplaner:
|
|||||||
fairness_abweichung_global[eltern, dienst] = pulp.LpVariable(
|
fairness_abweichung_global[eltern, dienst] = pulp.LpVariable(
|
||||||
f"fair_global_{eltern.replace(' ', '_')}_{dienst.kuerzel}", lowBound=0)
|
f"fair_global_{eltern.replace(' ', '_')}_{dienst.kuerzel}", lowBound=0)
|
||||||
|
|
||||||
# F1: Globale Fairness & F2: Lokale Fairness
|
# Fairness-Constraints hinzufügen
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
for dienst in self.dienste:
|
for dienst in self.dienste:
|
||||||
# Tatsächliche Dienste im aktuellen Monat
|
# Tatsächliche Dienste im aktuellen Monat
|
||||||
@ -368,7 +376,6 @@ class Elterndienstplaner:
|
|||||||
# F2: Lokale Fairness - nur aktueller Monat
|
# F2: Lokale Fairness - nur aktueller Monat
|
||||||
ziel_lokal = ziel_dienste_lokal[eltern][dienst]
|
ziel_lokal = ziel_dienste_lokal[eltern][dienst]
|
||||||
if ziel_lokal > 0:
|
if ziel_lokal > 0:
|
||||||
# Lokale Fairness-Constraints
|
|
||||||
prob += (tatsaechliche_dienste_monat - ziel_lokal <=
|
prob += (tatsaechliche_dienste_monat - ziel_lokal <=
|
||||||
fairness_abweichung_lokal[eltern, dienst])
|
fairness_abweichung_lokal[eltern, dienst])
|
||||||
prob += (ziel_lokal - tatsaechliche_dienste_monat <=
|
prob += (ziel_lokal - tatsaechliche_dienste_monat <=
|
||||||
@ -382,15 +389,17 @@ class Elterndienstplaner:
|
|||||||
# Tatsächliche Dienste global (Vergangenheit + geplant)
|
# Tatsächliche Dienste global (Vergangenheit + geplant)
|
||||||
total_dienste_inkl_vergangenheit = tatsaechliche_dienste_monat + vorherige_dienste
|
total_dienste_inkl_vergangenheit = tatsaechliche_dienste_monat + vorherige_dienste
|
||||||
|
|
||||||
# Globale Fairness-Constraints
|
|
||||||
prob += (total_dienste_inkl_vergangenheit - ziel_global <=
|
prob += (total_dienste_inkl_vergangenheit - ziel_global <=
|
||||||
fairness_abweichung_global[eltern, dienst])
|
fairness_abweichung_global[eltern, dienst])
|
||||||
prob += (ziel_global - total_dienste_inkl_vergangenheit <=
|
prob += (ziel_global - total_dienste_inkl_vergangenheit <=
|
||||||
fairness_abweichung_global[eltern, dienst])
|
fairness_abweichung_global[eltern, dienst])
|
||||||
|
|
||||||
# Gewichtung: Jahresanfang F1 stärker, Jahresende F2 stärker
|
return fairness_abweichung_lokal, fairness_abweichung_global
|
||||||
# Annahme: September = Jahresanfang, Juli = Jahresende
|
|
||||||
|
def _berechne_fairness_gewichte(self) -> Tuple[int, int]:
|
||||||
|
"""Berechnet Gewichtung basierend auf Jahreszeit (Sep-Jul Schuljahr)"""
|
||||||
aktueller_monat = self.tage[0].month if self.tage else 1
|
aktueller_monat = self.tage[0].month if self.tage else 1
|
||||||
|
|
||||||
if 9 <= aktueller_monat <= 12: # Sep-Dez: Jahresanfang
|
if 9 <= aktueller_monat <= 12: # Sep-Dez: Jahresanfang
|
||||||
gewicht_f1 = 100 # Global wichtiger
|
gewicht_f1 = 100 # Global wichtiger
|
||||||
gewicht_f2 = 50 # Lokal weniger wichtig
|
gewicht_f2 = 50 # Lokal weniger wichtig
|
||||||
@ -401,6 +410,21 @@ class Elterndienstplaner:
|
|||||||
gewicht_f1 = 50 # Global weniger wichtig
|
gewicht_f1 = 50 # Global weniger wichtig
|
||||||
gewicht_f2 = 100 # Lokal wichtiger
|
gewicht_f2 = 100 # Lokal wichtiger
|
||||||
|
|
||||||
|
return gewicht_f1, gewicht_f2
|
||||||
|
|
||||||
|
def _erstelle_zielfunktion(
|
||||||
|
self,
|
||||||
|
prob: pulp.LpProblem,
|
||||||
|
x: Dict[Tuple[str, date, Dienst], pulp.LpVariable],
|
||||||
|
fairness_abweichung_lokal: Dict,
|
||||||
|
fairness_abweichung_global: Dict
|
||||||
|
) -> None:
|
||||||
|
"""Erstellt die Zielfunktion mit Fairness und Präferenzen"""
|
||||||
|
objective_terms = []
|
||||||
|
|
||||||
|
# Fairness-Gewichtung
|
||||||
|
gewicht_f1, gewicht_f2 = self._berechne_fairness_gewichte()
|
||||||
|
|
||||||
# Fairness-Terme zur Zielfunktion hinzufügen
|
# Fairness-Terme zur Zielfunktion hinzufügen
|
||||||
for eltern in self.eltern:
|
for eltern in self.eltern:
|
||||||
for dienst in self.dienste:
|
for dienst in self.dienste:
|
||||||
@ -410,12 +434,12 @@ class Elterndienstplaner:
|
|||||||
# P1: Bevorzugte Dienste (positiv belohnen)
|
# P1: Bevorzugte Dienste (positiv belohnen)
|
||||||
for (eltern, tag, dienst), präf in self.präferenzen.items():
|
for (eltern, tag, dienst), präf in self.präferenzen.items():
|
||||||
if (eltern, tag, dienst) in x and präf == 1: # bevorzugt
|
if (eltern, tag, dienst) in x and präf == 1: # bevorzugt
|
||||||
objective_terms.append(-5 * x[eltern, tag, dienst]) # Schwächer als Fairness
|
objective_terms.append(-5 * x[eltern, tag, dienst])
|
||||||
|
|
||||||
# P2: Abgelehnte Dienste (bestrafen)
|
# P2: Abgelehnte Dienste (bestrafen)
|
||||||
for (eltern, tag, dienst), präf in self.präferenzen.items():
|
for (eltern, tag, dienst), präf in self.präferenzen.items():
|
||||||
if (eltern, tag, dienst) in x and präf == -1: # abgelehnt
|
if (eltern, tag, dienst) in x and präf == -1: # abgelehnt
|
||||||
objective_terms.append(25 * x[eltern, tag, dienst]) # Schwächer als Fairness
|
objective_terms.append(25 * x[eltern, tag, dienst])
|
||||||
|
|
||||||
# Zielfunktion setzen
|
# Zielfunktion setzen
|
||||||
if objective_terms:
|
if objective_terms:
|
||||||
@ -425,6 +449,41 @@ class Elterndienstplaner:
|
|||||||
prob += pulp.lpSum([var for var in x.values()])
|
prob += pulp.lpSum([var for var in x.values()])
|
||||||
|
|
||||||
print(f"Verwende Gewichtung: F1 (global) = {gewicht_f1}, F2 (lokal) = {gewicht_f2}")
|
print(f"Verwende Gewichtung: F1 (global) = {gewicht_f1}, F2 (lokal) = {gewicht_f2}")
|
||||||
|
|
||||||
|
def erstelle_optimierungsmodell(self) -> Tuple[pulp.LpProblem, Dict[Tuple[str, date, Dienst], pulp.LpVariable]]:
|
||||||
|
"""Erstellt das PuLP Optimierungsmodell"""
|
||||||
|
print("Erstelle Optimierungsmodell...")
|
||||||
|
|
||||||
|
# Debugging: Verfügbarkeit prüfen
|
||||||
|
print("\nDebug: Verfügbarkeit analysieren...")
|
||||||
|
for tag in self.tage[:5]: # Erste 5 Tage
|
||||||
|
verfügbare = [e for e in self.eltern if self.verfügbarkeit.get((e, tag), True)]
|
||||||
|
benötigte = self.benoetigte_dienste.get(tag, [])
|
||||||
|
print(f" {tag}: Benötigt {len(benötigte)} Dienste {benötigte}, verfügbar: {verfügbare}")
|
||||||
|
|
||||||
|
# LP Problem erstellen
|
||||||
|
prob = pulp.LpProblem("Elterndienstplaner", pulp.LpMinimize)
|
||||||
|
|
||||||
|
# Entscheidungsvariablen erstellen
|
||||||
|
x = self._erstelle_entscheidungsvariablen()
|
||||||
|
|
||||||
|
# Grundlegende Constraints hinzufügen
|
||||||
|
self._add_constraint_ein_dienst_pro_woche(prob, x)
|
||||||
|
self._add_constraint_ein_dienst_pro_tag(prob, x)
|
||||||
|
self._add_constraint_verfuegbarkeit(prob, x)
|
||||||
|
self._add_constraint_dienst_bedarf(prob, x)
|
||||||
|
|
||||||
|
# Fairness-Constraints
|
||||||
|
ziel_dienste_global = self.berechne_faire_zielverteilung_global()
|
||||||
|
ziel_dienste_lokal = self.berechne_faire_zielverteilung_lokal()
|
||||||
|
|
||||||
|
fairness_abweichung_lokal, fairness_abweichung_global = self._add_fairness_constraints(
|
||||||
|
prob, x, ziel_dienste_global, ziel_dienste_lokal
|
||||||
|
)
|
||||||
|
|
||||||
|
# Zielfunktion erstellen
|
||||||
|
self._erstelle_zielfunktion(prob, x, fairness_abweichung_lokal, fairness_abweichung_global)
|
||||||
|
|
||||||
print(f"Modell erstellt mit {len(x)} Variablen und {len(prob.constraints)} Constraints")
|
print(f"Modell erstellt mit {len(x)} Variablen und {len(prob.constraints)} Constraints")
|
||||||
return prob, x
|
return prob, x
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user