6710d4f06a
Weniger vermeidbare Gruppentrennungen:
- strafen.cfg: Tischbesetzung bestraft jetzt gestaffelt nach freien
Plaetzen (teilbelegte Tische am teuersten, mit Fallback auf den
naechstkleineren Eintrag), Trennungsstrafen deutlich erhoeht - so
werden Gruppen nicht mehr getrennt, obwohl leere Tische danebenstehen
- gibPunkte('Tischbesetzung') mit Naechst-kleiner-Fallback
- mutieren() setzt geraeumte Gruppen groesste-zuerst neu
(GruppenSetzen(GrosseZuerst=True)), damit grosse Gruppen die frei
gewordenen ganzen Tische bekommen und wieder zusammenkommen
(uebrig bleiben nur physisch unvermeidbare Trennungen, Gruppe > Tisch)
Abstammungsbaum (neuer Schalter --show-lineage -> Abstammung.svg):
- neue Klasse ga.Abstammung zeichnet den vollen Mutationsbaum aller
Loesungen; der Ast der finalen besten Loesung ist hervorgehoben und
mit ihrer Id beschriftet
- hierarchische Loesungs-Ids (Farm._WurzelId/_KindId): Wurzel '7',
Mutationskind '7.2', dessen Kind '7.2.1' - die ganze Abstammung ist
direkt aus der Id ablesbar
Tests (15 gruen), README und CLAUDE.md aktualisiert; Beispiele mit den
neuen Strafen und beiden Grafiken neu berechnet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
121 lines
4.4 KiB
Python
Executable File
121 lines
4.4 KiB
Python
Executable File
"""
|
|
Enthaelt alle Datenstrukturen um die Sitzplatzverteilung als GA zu variieren
|
|
|
|
"""
|
|
|
|
__author__ = "Michael Stangl"
|
|
__version__ = "$Revision: $"
|
|
__date__ = "$Date: $"
|
|
__copyright__ = "Copyright (c) 2005 Michael Stangl"
|
|
__license__ = "Python"
|
|
|
|
from ga import *
|
|
from Strukturdaten import *
|
|
import optparse
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
# Kommandozeilenoption --indir: Verzeichnis mit den Eingabedateien
|
|
# (tische.ini, bestellung.json) und Ziel fuer die Ausgabedateien
|
|
# (TischePersonen.txt, PersonenTische.csv)
|
|
parser = optparse.OptionParser()
|
|
parser.add_option( "--indir", dest="indir", default=None,
|
|
help="Verzeichnis mit tische.ini und bestellung.json; "
|
|
"dort werden auch TischePersonen.txt und PersonenTische.csv abgelegt" )
|
|
parser.add_option( "--tosvg", dest="tosvg", action="store_true", default=False,
|
|
help="zusaetzlich eine Sitzplatzverteilung.svg im --indir Verzeichnis "
|
|
"erzeugen (Tische als weisse Kreise, Personen als farbige "
|
|
"Kreise je Gruppe)" )
|
|
parser.add_option( "--show-connections", dest="showconn", action="store_true",
|
|
default=True,
|
|
help="in der Sitzplatzverteilung.svg jede ueber mehrere Tische "
|
|
"getrennte Gruppe mit einer Linie in ihrer Gruppenfarbe "
|
|
"verbinden (Vorgabe: an; nur mit --tosvg wirksam)" )
|
|
parser.add_option( "--hide-connections", dest="showconn",
|
|
action="store_false",
|
|
help="die Verbindungslinien getrennter Gruppen in der "
|
|
"Sitzplatzverteilung.svg nicht zeichnen" )
|
|
parser.add_option( "--show-development", dest="showdev", action="store_true",
|
|
default=False,
|
|
help="zusaetzlich eine Entwicklung.svg im --indir Verzeichnis "
|
|
"erzeugen: Verlauf der Loesungsfindung (Zeitachse nach rechts, "
|
|
"beste/durchschnittliche/schlechteste Wertigkeit auf der Y-Achse)" )
|
|
parser.add_option( "--show-lineage", dest="showlineage", action="store_true",
|
|
default=False,
|
|
help="zusaetzlich eine Abstammung.svg im --indir Verzeichnis "
|
|
"erzeugen: Stammbaum aller Loesungen (Mutationsbaum); der Ast der "
|
|
"finalen besten Loesung ist hervorgehoben und mit ihrer "
|
|
"Abstammungs-Id beschriftet" )
|
|
parser.add_option( "--zyklus-art", dest="zyklusart", default="Adaptiv",
|
|
help="Name des GA-Profils in zyklus.cfg (Vorgabe: Adaptiv). "
|
|
"Weitere mitgelieferte Profile: Easy, Simple" )
|
|
(options, args) = parser.parse_args()
|
|
|
|
if options.indir is None:
|
|
parser.error( "--indir ist erforderlich" )
|
|
InDir = os.path.expandvars( os.path.expanduser( options.indir ) )
|
|
if not os.path.isdir( InDir ):
|
|
parser.error( "--indir '%s' ist kein Verzeichnis" % InDir )
|
|
|
|
# zyklus.cfg (GA-Profile) und strafen.cfg (Strafpunkte) direkt aus dem
|
|
# per $PLATZ_CFG bestimmten cfg-Verzeichnis laden. Das GA-Profil waehlt
|
|
# der Schalter --zyklus-art (Vorgabe: Adaptiv).
|
|
CfgDir = os.getenv('PLATZ_CFG')
|
|
if not CfgDir:
|
|
parser.error( "Umgebungsvariable PLATZ_CFG ist nicht gesetzt "
|
|
"(bin/setenv aufrufen)" )
|
|
Zyklusconfig = os.path.join( CfgDir, 'zyklus.cfg' )
|
|
Zyklusart = options.zyklusart
|
|
Strafenconfig = os.path.join( CfgDir, 'strafen.cfg' )
|
|
|
|
# lade Eingabedateien
|
|
Tischconfig = os.path.join( InDir, 'tische.ini' )
|
|
Bestellung = os.path.join( InDir, 'bestellung.json' )
|
|
|
|
# lade Ausgabedateien
|
|
AusgabeTP= os.path.join( InDir, 'TischePersonen.txt' )
|
|
AusgabePT = os.path.join( InDir, 'PersonenTische.csv' )
|
|
AusgabeSVG = os.path.join( InDir, 'Sitzplatzverteilung.svg' )
|
|
AusgabeEntwicklung = os.path.join( InDir, 'Entwicklung.svg' )
|
|
AusgabeAbstammung = os.path.join( InDir, 'Abstammung.svg' )
|
|
|
|
Z = Zyklus()
|
|
Z.laden( Zyklusconfig, Zyklusart )
|
|
print(Z)
|
|
SL = Strafliste()
|
|
SL.laden( Strafenconfig )
|
|
print(SL)
|
|
TE = Tische()
|
|
TE.laden( Tischconfig )
|
|
print(TE)
|
|
|
|
InputFile = JSONConfig()
|
|
[ PN, GN, VIPGruppe, VIPListePT, GruppenNamen ] = InputFile.laden( Bestellung )
|
|
print(PN)
|
|
print(GN)
|
|
print(VIPGruppe)
|
|
print(VIPListePT)
|
|
|
|
print("\n-- Erzeuge Farm:")
|
|
F1 = Farm( Z, Sitzplatzverteilung, Tische=TE, Gruppen=GN, Strafen=SL, VIPListe=VIPListePT, VIPs=VIPGruppe )
|
|
#print(F1)
|
|
S = F1.Bester()
|
|
print(S)
|
|
S.speichern( AusgabeTP, AusgabePT )
|
|
if options.tosvg:
|
|
S.alsSVG( AusgabeSVG, Verbindungen=options.showconn )
|
|
if options.showdev:
|
|
F1.Entwicklung.alsSVG( AusgabeEntwicklung )
|
|
print( "Entwicklungsverlauf geschrieben:", AusgabeEntwicklung )
|
|
if options.showlineage:
|
|
F1.Abstammung.alsSVG( AusgabeAbstammung,
|
|
HervorId=getattr(S, '_absid', None) )
|
|
print( "Abstammungsbaum geschrieben:", AusgabeAbstammung )
|
|
|
|
else:
|
|
pass
|
|
|
|
|
|
|