kleine Änderungen
This commit is contained in:
parent
0f9c815b86
commit
dc088fa214
47 changed files with 183868 additions and 573 deletions
|
|
@ -91,9 +91,43 @@ def loese() -> tuple[list[tuple[int, int, int, int]], int]:
|
|||
return plan, loeser.Value(makespan)
|
||||
|
||||
|
||||
def untere_schranke() -> int:
|
||||
"""Wie in JobShop_Intervalle.py: laengster Auftrag bzw. hoechste Maschinenlast.
|
||||
|
||||
Kein Plan kann kuerzer sein als der laengste Auftrag (seine Schritte laufen
|
||||
nacheinander) und auch nicht kuerzer als die am staerksten belegte Maschine
|
||||
(ihre Schritte koennen sich nicht ueberlappen)."""
|
||||
je_auftrag = max(sum(dauer for _, dauer in auftrag)
|
||||
for auftrag in AUFTRAEGE)
|
||||
last = [0] * len(MASCHINENNAMEN)
|
||||
for auftrag in AUFTRAEGE:
|
||||
for maschine, dauer in auftrag:
|
||||
last[maschine] += dauer
|
||||
return max(je_auftrag, max(last))
|
||||
|
||||
|
||||
def stillstaende(plan):
|
||||
"""Luecken ZWISCHEN zwei Arbeitsgaengen derselben Maschine.
|
||||
|
||||
Nur die inneren: Was eine Maschine vor ihrem ersten oder nach ihrem letzten
|
||||
Arbeitsgang tut, ist keine Luecke im Plan, sondern sein Rand."""
|
||||
luecken = []
|
||||
for maschine in range(len(MASCHINENNAMEN)):
|
||||
zeiten = sorted((beginn, beginn + dauer)
|
||||
for _, m, beginn, dauer in plan if m == maschine)
|
||||
for (_, ende), (naechster_beginn, _) in zip(zeiten, zeiten[1:]):
|
||||
if naechster_beginn > ende:
|
||||
luecken.append((maschine, ende, naechster_beginn))
|
||||
return luecken
|
||||
|
||||
|
||||
def zeichne_statisch(plan, makespan: int) -> None:
|
||||
"""Matplotlib-Fassung fuer das PDF."""
|
||||
figur, achse = plt.subplots(figsize=(9.0, 3.2))
|
||||
figur, achse = plt.subplots(figsize=(9.0, 3.4))
|
||||
for maschine, von, bis in stillstaende(plan):
|
||||
achse.barh(y=maschine, width=bis - von, left=von, height=0.55,
|
||||
facecolor="none", edgecolor="#be123c", linewidth=1.2,
|
||||
hatch="///", zorder=2)
|
||||
for auftrag, maschine, beginn, dauer in plan:
|
||||
achse.barh(y=maschine, width=dauer, left=beginn, height=0.55,
|
||||
color=FARBEN[auftrag % len(FARBEN)],
|
||||
|
|
@ -108,7 +142,21 @@ def zeichne_statisch(plan, makespan: int) -> None:
|
|||
achse.set_xlabel("Zeiteinheiten")
|
||||
achse.set_xlim(0, makespan)
|
||||
achse.set_xticks(range(makespan + 1))
|
||||
achse.set_title(f"Job-Shop-Plan, Makespan = {makespan}", fontsize=11)
|
||||
|
||||
schranke = untere_schranke()
|
||||
achse.axvline(schranke, color="#059669", linestyle="--", linewidth=1.5,
|
||||
zorder=5)
|
||||
# x in Datenkoordinaten, y als Anteil der Achsenhoehe: Die y-Achse ist
|
||||
# umgekehrt, ein fester y-Wert laege sonst ausserhalb des Bildes.
|
||||
unten = achse.get_xaxis_transform()
|
||||
# Der Makespan steht schon im Titel - hier nur die Schranke, sonst
|
||||
# stossen beide Beschriftungen aneinander.
|
||||
achse.text(schranke - 0.12, 0.03, f"untere Schranke {schranke}",
|
||||
transform=unten, fontsize=8.5, color="#059669", ha="right",
|
||||
va="bottom", zorder=6)
|
||||
achse.set_title(f"Job-Shop-Plan: Makespan {makespan}, untere Schranke "
|
||||
f"{schranke} — schraffiert steht die Maschine still",
|
||||
fontsize=11)
|
||||
achse.grid(axis="x", linestyle=":", alpha=0.5)
|
||||
for rand in ("top", "right", "left"):
|
||||
achse.spines[rand].set_visible(False)
|
||||
|
|
@ -170,6 +218,40 @@ def zeichne_interaktiv(plan, makespan: int) -> None:
|
|||
|
||||
if __name__ == "__main__":
|
||||
plan, makespan = loese()
|
||||
print(f"Makespan: {makespan}")
|
||||
schranke = untere_schranke()
|
||||
print(f"Makespan: {makespan}, untere Schranke: {schranke}")
|
||||
for maschine, von, bis in stillstaende(plan):
|
||||
print(f" Stillstand: {MASCHINENNAMEN[maschine]} von {von} bis {bis}")
|
||||
|
||||
# Gegenprobe zu den Zahlen, die das Kapitel abdruckt.
|
||||
if schranke > makespan:
|
||||
raise SystemExit(f"Gantt: Die untere Schranke {schranke} liegt ueber "
|
||||
f"dem Makespan {makespan} - eine der beiden Zahlen "
|
||||
f"ist falsch.")
|
||||
if (schranke, makespan) != (10, 11):
|
||||
raise SystemExit(f"Gantt: Schranke {schranke} / Makespan {makespan}; "
|
||||
f"das Kapitel druckt 10 / 11 ab.")
|
||||
if not any(m == 1 and von == 4 for m, von, _ in stillstaende(plan)):
|
||||
raise SystemExit("Gantt: Die Luecke in der Dreherei bei Zeitpunkt 4 "
|
||||
"fehlt - der Text daneben bespricht genau sie.")
|
||||
|
||||
# Der Text daneben rechnet vor: Die Engpassmaschine ist von 0 bis zum
|
||||
# Makespan belegt, ihre Arbeit ist die Schranke, der Rest Stillstand.
|
||||
last = [0] * len(MASCHINENNAMEN)
|
||||
for auftrag in AUFTRAEGE:
|
||||
for maschine, dauer in auftrag:
|
||||
last[maschine] += dauer
|
||||
engpass = last.index(max(last))
|
||||
leerlauf = sum(bis - von for m, von, bis in stillstaende(plan)
|
||||
if m == engpass)
|
||||
if last[engpass] + leerlauf != makespan:
|
||||
raise SystemExit(
|
||||
f"Gantt: {MASCHINENNAMEN[engpass]} arbeitet {last[engpass]} und "
|
||||
f"steht {leerlauf} still, zusammen "
|
||||
f"{last[engpass] + leerlauf} statt {makespan}. Der Text daneben "
|
||||
f"rechnet genau diese Summe vor.")
|
||||
print(f" Engpass {MASCHINENNAMEN[engpass]}: {last[engpass]} Arbeit + "
|
||||
f"{leerlauf} Stillstand = {makespan}")
|
||||
|
||||
zeichne_statisch(plan, makespan)
|
||||
zeichne_interaktiv(plan, makespan)
|
||||
|
|
|
|||
Loading…
Reference in a new issue