From 97382c8e9d638bf29a460380a5530be264996a43 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Wed, 3 May 2006 22:21:24 +0200 Subject: [PATCH] Initial import from SVN (svn://129.187.65.205/platz/trunk, r1) Converted from SVN working copy. Original SVN server no longer available. Original commit date: 2006-05-03, author: sm --- .gitignore | 4 + bin/run | 17 + bin/run.bat | 21 + cfg/platz.cfg | 10 + cfg/strafen.cfg | 19 + cfg/zyklus.cfg | 8 + libs/Strukturdaten.py | 1092 +++++++++++++++++++++++++++++++++ libs/ga.py | 194 ++++++ libs/platz.py | 73 +++ work/test1/PersonenTische.csv | 19 + work/test1/TischePersonen.txt | 27 + work/test1/bestellung.xml | 32 + work/test1/tische.ini | 28 + work/test2/bestellung.xml | 90 +++ work/test2/tische.ini | 35 ++ 15 files changed, 1669 insertions(+) create mode 100644 .gitignore create mode 100755 bin/run create mode 100644 bin/run.bat create mode 100644 cfg/platz.cfg create mode 100644 cfg/strafen.cfg create mode 100644 cfg/zyklus.cfg create mode 100755 libs/Strukturdaten.py create mode 100755 libs/ga.py create mode 100755 libs/platz.py create mode 100644 work/test1/PersonenTische.csv create mode 100644 work/test1/TischePersonen.txt create mode 100755 work/test1/bestellung.xml create mode 100755 work/test1/tische.ini create mode 100755 work/test2/bestellung.xml create mode 100755 work/test2/tische.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..419c3b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.pyc +__pycache__/ +*.pyo +work/ausgabe.txt diff --git a/bin/run b/bin/run new file mode 100755 index 0000000..4f3799e --- /dev/null +++ b/bin/run @@ -0,0 +1,17 @@ +#!/bin/bash +# ------------------------------------- +# Wo ist das Programm hinkopiert +export PLATZ=/Users/sm/develop/python/platz +echo $PLATZ +# ------------------------------------- + +# Umgebung setzen +export PLATZ_CFG=$PLATZ/cfg +export PLATZ_LIBS=$PLATZ/libs +export PLATZ_WORK=$PLATZ/work + +# Wo sind die Pythonskripte ? +export PYTHONPATH=$PYTHONPATH:$PLATZ_LIBS + +# Startet das Sitzplatzprogramm +python $PLATZ_LIBS/platz.py diff --git a/bin/run.bat b/bin/run.bat new file mode 100644 index 0000000..02c953e --- /dev/null +++ b/bin/run.bat @@ -0,0 +1,21 @@ +echo off +REM Hier die Umgebung anpassen +REM ------------------------------------- +REM Wo ist das Programm hinkopiert +set PLATZ=h:\develop\python\platz +REM Wo liegt der Interpreter +set PYTHONSHELL=l:\tools\i486_nt\python24 +REM ------------------------------------- + +REM Umgebung setzen +set PLATZ_CFG=%PLATZ%\cfg +set PLATZ_LIBS=%PLATZ%\libs +set PLATZ_WORK=%PLATZ%\work + +set PATH=%PYTHONSHELL%;%PATH% + +REM Wo sind die Pythonskripte ? +set PYTHONPATH=%PLATZ_LIBS% + +REM Startet das Sitzplatzprogramm +python %PLATZ_LIBS%\platz.py diff --git a/cfg/platz.cfg b/cfg/platz.cfg new file mode 100644 index 0000000..c3fca62 --- /dev/null +++ b/cfg/platz.cfg @@ -0,0 +1,10 @@ +[Config] +Zyklusdatei=$PLATZ_CFG/zyklus.cfg +Zyklusart=Easy +Strafendatei=$PLATZ_CFG/strafen.cfg +Tischedatei=$PLATZ_WORK/test1/tische.ini +XMLdatei_Bestellung=$PLATZ_WORK/test1/bestellung.xml +AusgabeTischePersonen=$PLATZ_WORK/test1/TischePersonen.txt +AusgabePersonTisch=$PLATZ_WORK/test1/PersonenTische.csv + + diff --git a/cfg/strafen.cfg b/cfg/strafen.cfg new file mode 100644 index 0000000..8a0b177 --- /dev/null +++ b/cfg/strafen.cfg @@ -0,0 +1,19 @@ +# Strafpunkte fuer die Trennung einer Gruppe: +# Aufbau: Anzahl der Trennungen = { Gruppengroesse:Strafpunkte, .. } +[Trennung] +1={ 2:-10, 3:-8, 4:-6, 6:-4, 10:-2 } +2={ 3:-20, 4:-8, 6:-6, 10:-4 } +3={ 4:-30, 6:-10, 10:-6 } + +# Wieviele Strafpunkte bekommt man +# wenn zwei Gruppen nicht am Nachbartisch sitzen +# wenn einer aus einer Gruppe allein sitzen muss +[Globals] +NichtNachbar=-3 +Allein=-30 +TischWertigkeiten={ 1:-3, 2:-2, 3:-1 } + +# TischWertigkeiten sind Strafpunkte fuer schlechte Ausnutzung der +# freien Sitze an einem Tisch. +# An einem Tisch, der bis auf einen Platz voll besetzt ist, +# kann niemand mehr gut dazu. wenn zwei Plaetze frei sind, ist das etwas besser. diff --git a/cfg/zyklus.cfg b/cfg/zyklus.cfg new file mode 100644 index 0000000..81f952f --- /dev/null +++ b/cfg/zyklus.cfg @@ -0,0 +1,8 @@ +[Easy] +Abfolge='e,'+'s,z,m,j,z,'*3+'s' +Anzahl='10,'+'5,x,2,x,x,'*3+'1' + +[Simple] +Abfolge='e,s' +Anzahl='20,1' + diff --git a/libs/Strukturdaten.py b/libs/Strukturdaten.py new file mode 100755 index 0000000..73b4cbf --- /dev/null +++ b/libs/Strukturdaten.py @@ -0,0 +1,1092 @@ +""" +Enthaelt alle Datenstrukturen um die noetigen Hierarchien zur Beschreibung einer Sitzplatzverteilung aufzubauen + +""" + +__author__ = "Michael Stangl" +__version__ = "$Revision: $" +__date__ = "$Date: $" +__copyright__ = "Copyright (c) 2005 Michael Stangl" +__license__ = "Python" + +from sets import Set +from itertools import chain +from UserList import UserList +from random import * +import ConfigParser, os +import copy +from xml.dom import minidom + + +# Strukturklassen: Person, Gruppe, Tisch +class Person: + """enthaelt alle Daten zu einer Person die noetig sind""" + def __init__(self, Id, Vorname, Name, Titel=''): + self.Id = Id + self._Vorname = Vorname + self._Name = Name + self._Titel = Titel + def __repr__(self): + return ' Person %s: "%s %s %s"' % ( self.Id, self._Titel, + self._Vorname, self._Name) + print self.__repr__ + +class Gruppe: + """enthalt alle Daten zu einer Gruppe""" + Art = 'Gruppe' + def __init__(self, Id, Personen=[]): + self.Id = Id + self._Personen = Set() + self._Anzahl = 0 + self.PvonId = {} + for P in Personen: + self.Person_dazu( P ) + def __repr__(self): + result = '+ %s %s: Ids: ' % (self.Art, self.Id) + for P in self._Personen: + result = result + repr(P.Id) + ',' + result = result + ' %s Person(en)' % (self._Anzahl) + return result + print self + for P in self._Personen: + print P + def Person_dazu(self, P): + self._Personen.add(P) + self._Anzahl = self._Anzahl + 1 + self.PvonId[ P.Id ] = P + def Person_weg(self, P): + if P in self._Personen : + self._Personen.remove(P) + self._Anzahl = self._Anzahl - 1 + else: + raise KeyError, "Person ist nicht enthalten" + def teilen(self, NeueGroesse=0): + if self._Anzahl == 1: + raise IndexError, "Gruppe ist nur noch einer" + if NeueGroesse == 0: + NeueGroesse = int(self._Anzahl/2) + one = Gruppe( self.Id, self._Personen ) + two = Gruppe( self.Id, self._Personen ) + two._Personen.clear() + for i in xrange(NeueGroesse): + two._Personen.add(one._Personen.pop()) + one._Anzahl = len(one._Personen) + two._Anzahl = len(two._Personen) + return [one,two] + def PersonVonPid(self, SearchedId): + return self.PvonId[SearchedId] + def Anzahl(self): + return self._Anzahl + def __contains__(self, P): + return P in self._Personen + def __iter__(self): + for P in self._Personen: + yield(P) + def __cmp__(self,other): + if self._Anzahl < other._Anzahl: return -1 + elif self._Anzahl == other._Anzahl: return 0 + else: return 1 + def __getattr__(self, attrname): + if attrname == 'Anzahl': + return self._Anzahl + elif attrname == 'Id': + return self.Id + else: + raise AttributeError, attrname + +class Tisch(Gruppe): + """enthalt alle Daten zu einem Tisch""" + Art = 'Tisch' + def __init__(self, Id, Plaetze=1, Koordinaten=(0,0), pids=[], Nachbarliste=[], Hof=0, Nummer=0 ): + self._Plaetze = Plaetze + self.Hof = Hof + self.Nummer = Nummer + self.X_Koordinate = Koordinaten[0] + self.Y_Koordinate = Koordinaten[1] + self.Nachbarn = Set(Nachbarliste) + Gruppe.__init__( self, Id, pids ) + def istvoll(self, n=0): + if ((self._Anzahl + n) == self._Plaetze ): + return True + else: + return False + def istleer(self): + if (self._Anzahl == 0 ): + return True + else: + return False + def istNachbar(self,Tid): + if Tid in self.Nachbarn: + return True + else: + return False + def freiePlaetze(self): + return int( self._Plaetze - self._Anzahl ) + def besetztePlaetze(self): + return self._Anzahl + def Person_dazu(self, P): + if (self._Anzahl == self._Plaetze ): + raise IndexError, "Tisch voll" + else: + Gruppe.Person_dazu( self, P ) + def Person_weg(self, P): + if (self._Anzahl == 0 ): + raise IndexError, "Tisch schon leer" + else: + Gruppe.Person_weg( self, P ) + def teilen(self): + pass + def __repr__(self): + result = ( Gruppe.__repr__( self ) + + ' fuer [%s], %s noch frei,' % + (self._Plaetze, + self._Plaetze - self._Anzahl) + ) + result = result + " Nachbarn:" + for N in chain(self.Nachbarn): + result = result + repr(N) + return result + def __getattr__(self, attrname): + if attrname == 'Anzahl': + return self._Anzahl + if attrname == 'Plaetze': + return self._Plaetze + elif attrname == 'Id': + return self.Id + else: + raise AttributeError, attrname + + +# Containerklassen Personen, Gruppen, Tische, Plaetze +class Personen: + """ein Pool mit mehreren Personen""" + def __init__( self, Personen=[] ): + self._Personen = Set(Personen) + self.PvonId = {} + for P in Personen: + self.PvonId[ P.Id ] = P + def __repr__( self): + result = '+ PersonenListe:\n' + for P in self._Personen: + result = result + repr(P) + '\n' + return result + def PersonVonPid( self, SearchedId ): + return self.PvonId[SearchedId] + def PersonAdd( self, Person ): + self._Personen.add( Person ) + Pid = Person.Id + self.PvonId[ Pid ] = Person + def ListeVonIds( self, PersonenIds ): + PersonenListe = [] + for Id in PersonenIds: + PersonenListe.append( self.PersonVonPid( Id ) ) + return PersonenListe + +class Gruppen: + """Containerklasse fuer Gruppenzusammenstellung """ + Art = 'Gruppen' + def __init__( self, GruppenListe=[]): + self.GruppenListe = [] + self.PvonPid = {} + self.GvonPid = {} + self.NLeute = 0 + for G in chain( GruppenListe ): + self.Gruppe_dazu( G ) + print "gruppen hinzugefuegt" + def __iter__( self): + sortiert = self.GruppenListe[:] + sortiert.sort() + for G in sortiert: + yield(G) + def __repr__( self): + result = "-- "+self.Art+"aufstellung:\n" + for G in chain( self.GruppenListe): + result = result + repr(G)+ '\n' + result = result + "Gesamtanzahl der Leute: " + repr(self.NLeute) + "\n" + return result + def vonId(self, SearchedId): + for G in chain(self.GruppenListe): + if ( int(G.Id) == SearchedId ): + return G + def PersonVonPid(self, SearchedId): + return self.PvonPid[SearchedId] + def GruppeVonPid(self, SearchedId): + return self.GvonPid[SearchedId] + def Gruppe_dazu(self, G): + self.GruppenListe.append( G ) + self.NLeute = self.NLeute + G._Anzahl + for P in G: + self.PvonPid[ P.Id ] = P + self.GvonPid[ P.Id ] = G + +class Tische: + """Containerklasse fuer Tischaufstellung """ + Art = 'Tisch' + def __init__( self, TischListe =[] ): + self.TischListe = TischListe + self.Groesster = 0 + self.NStuehle = 0 + self.IdGroesster = 0 + # stelle den groessten Tisch fest + # und zaehle die Plaetze + for T in chain( TischListe ): + self.NStuehle = self.NStuehle + T.Plaetze + if (T.Plaetze > self.Groesster ): + self.Groesster = T.Plaetze + self.IdGroesster = T.Id + def __repr__( self ): + result = "-- "+self.Art+"aufstellung:\n" + for T in chain(self.TischListe): + result = result + repr(T)+ '\n' + result = ( result + " Groesster Tisch: " + + repr(self.IdGroesster) + + "( " + repr(self.Groesster) + " )\n" ) + return result + def Tisch_dazu(self, T): + self.NStuehle = self.NStuehle + T.Plaetze + self.TischListe.append( T ) + if (T.Plaetze > self.Groesster ): + self.Groesster = T.Plaetze + self.IdGroesster = T.Id + def __iter__( self): + sortiert = self.TischListe[:] + sortiert.sort() + for T in sortiert: + yield(T) + def laden( self, FileName ): + ## print "-- Tische laden" + config = ConfigParser.ConfigParser() + config.read( os.path.expanduser(FileName) ) + for section in config.sections(): + Tid = int(section) + Nummer = eval(config.get( section, 'Nummer' )) + nPl = eval(config.get( section, 'Plaetze' )) + Koords = eval(config.get( section, 'Koordinaten' )) + Nachbarn = eval(config.get( section, 'Nachbarliste' )) + Hofid = eval(config.get( section, 'Hof' )) + T = Tisch( Tid, Plaetze=nPl, Koordinaten=Koords, Nachbarliste=Nachbarn, Hof=Hofid, Nummer=Nummer ) + self.Tisch_dazu( T ) + def vonId(self, SearchedId): + for T in chain(self.TischListe): + if ( int(T.Id) == SearchedId ): + return T + def deepcopy(self): + NeueTischliste = [] + for T in chain( self.TischListe ): + TNeu = copy.deepcopy( T ) + NeueTischliste.append( TNeu ) + NeueTische = Tische( NeueTischliste ) + return NeueTische + + + +# Klasse fuer Information der Verteilung der Sitze +class Plaetze: + """Informationen ueber freie oder benachbarte Plaetze""" + def __init__(self, Tische): + # mache Listen mit den Tischen mit n Freien Plaetzen + self.__TIDsNFreie = [] + self.__Groesster = Tische.Groesster + self.__Tische = Tische + for i in range( self.__Groesster + 1 ): + self.__TIDsNFreie.append( Set() ) + for T in Tische.TischListe: + n_freie = T.freiePlaetze() + self.__TIDsNFreie[n_freie].add(T.Id) + def __repr__(self): + result = "\n-- Tische mit n Freien Plaetzen:\n" + for i in xrange(self.__Groesster+1): + result = result + " " +repr(i) + " :" + repr(self.__TIDsNFreie[i]) + "\n" + return result + def IdsnFreie(self, n_freie): + """gibt ein Set mit allen Tischids zurueck, wo noch X freie Plaetze sind""" + return self.__TIDsNFreie[n_freie] + def nFreie(self, n_freie): + """gibt einen Tisch zurueck, wo noch X freie Plaetze sind""" + try: + TischId = int(self.__TIDsNFreie[n_freie].pop()) + # aber veraendere deswegen die Liste nicht + self.__TIDsNFreie[n_freie].add(TischId) + return self.__Tische.vonId(TischId) + except KeyError: + return None + def mindestensNFreie(self, n_freie): + """gibt einen Tisch zurueck, wo noch X oder mehr freie Plaetze sind""" + ## print "-- Plaetze.mindestensNFreie", n_freie + ## print "-- Plaetze.mindestensNFreie.Groesster", self.__Groesster + N = n_freie + if n_freie > self.__Groesster: + return None + while N < self.__Groesster+1: + T = self.nFreie(N) + if T is None: + N = N + 1 + else: + return T + return None + def NachbarTische(self, n1, n2): + """gibt zwei Nachbartische zurueck, wo zwei Gruppen hinpassen + + falls durch eine Gruppe ein Tisch voll werden wuerde, ist voll=1 + falls beide Tisch gefuellt werden wuerden, ist voll=2 + """ + # zuerst versuchen einen Tisch fuer die groessere der beiden Gruppen zu finden + # falls es nicht klappt, wirds auch keine Nachbarn geben... + n = max([n1,n2]) + T = self.mindestensNFreie( n ) + if T is None: + return [None,None] + + T1 = self.mindestensNFreie(n1) + + # davon nun die Nachbarn abklappern, ob ein Tisch dabei ist, + # wo noch genuegend Plaetze frei sind + n_Nachbar = n2 + IdNachbarTisch = 0 + while n_Nachbar < self.__Groesster+1: + # ein Set bauen, das aus Tischids besteht, die sowohl Nachbarn sind, + # als auch mindestens die gewuenschte Anzahl von Plaetzen frei hat + NeueNachbarn = self.__TIDsNFreie[n_Nachbar] & T1.Nachbarn + try: + IdNachbarTisch = NeueNachbarn.pop() + T2 = self.__Tische.vonId( IdNachbarTisch ) + return [T1,T2] + except KeyError: + n_Nachbar = n_Nachbar + 1 + return [None,None] + def update(self, Tisch, n_freivorher): + """aktualisiere die aktuelle Platzverteilung""" + ## print "----------------" + ## print "Plaetze.update" + self.__TIDsNFreie[n_freivorher].remove(Tisch.Id) + freiPlaetze = Tisch.freiePlaetze() + self.__TIDsNFreie[freiPlaetze].add(Tisch.Id) + ## print "freie Plaetze: ", freiPlaetze, "Tischid", Tisch.Id, "\n" + +# Strafliste. Was ist wie schlecht? +class Strafliste: + """enthaelt die Informationen zur Vergabe der Wertigkeit einer Sitzplatzverteilung""" + def __init__(self, GruppenTrennen={}, NichtNachbar=-5, Allein=-20, TischWert={}): + self.GruppenTrennen = GruppenTrennen + self.NichtNachbar = NichtNachbar + self.Allein = Allein + self.TischWert = TischWert + def __repr__(self): + """Drucke alle Bestrafungen auf der Konsole aus""" + return ("+ Strafliste:\n" + "Trennen von Gruppen (Groesse:Strafe): %s\n" + "Strafe kein Gruppenmitglied am Nachbartisch : %s\n" + "Strafe fuer eine Person allein: %s" + % ( self.GruppenTrennen, + self.NichtNachbar, + self.Allein) ) + def gibPunkte(self, Typ, Gruppengroesse=0, N_Teilungen=0, freiePlaetze=0): + if cmp(Typ,'allein') == 0: + return self.Allein + elif cmp(Typ,'nichtNachbar')== 0: + return self.NichtNachbar + elif cmp(Typ,'Tischbesetzung')== 0: + try: + return self.TischWert[freiePlaetze] + except KeyError: + return 0 + elif cmp(Typ,'Trennung')== 0: + if (N_Teilungen == 0): + return 0 + elif (N_Teilungen == 1) & (Gruppengroesse < 2): + raise IndexError, "Gruppe sind mindestens zwei Leute" + elif (N_Teilungen == 2) & (Gruppengroesse < 3): + raise IndexError, "mindestens drei Leute noetig" + elif (N_Teilungen > 2): + return -50 + if self.GruppenTrennen[N_Teilungen].has_key(Gruppengroesse): + return self.GruppenTrennen[N_Teilungen][Gruppengroesse] + else: + return self.gibPunkte('Trennung',Gruppengroesse-1, N_Teilungen) + else: + raise IndexError, "Bezeichner gibts nicht" + def laden( self, FileName ): + print "-- Strafliste laden" + config = ConfigParser.ConfigParser() + config.read( os.path.expanduser(FileName) ) + self.NichtNachbar = eval(config.get( 'Globals', 'NichtNachbar' )) + self.Allein = eval(config.get( 'Globals', 'Allein' )) + self.TischWert = eval( config.get( 'Globals', 'TischWertigkeiten' ) ) + for (k,v) in config.items( 'Trennung' ): + self.GruppenTrennen[int(k)] = eval(v) + + +# Sitzplatzverteilung, bestehend aus den Einzelelementen +class Sitzplatzverteilung: + """Loesungsvorschlag fuer eine Sitzplatzordung""" + + # Aenderung der Sitzplatzverteilung (Aktion) + def __init__(self, Tische=[], Gruppen=[], Strafen='', VIPListe={}, VIPs=[] ): + """erzeugt eine Sitzplatzverteilung nach dem Zufallsprinzip + + Zufallgenerator, um zu entscheiden, nach welcher + Verteilungsart verfahren wird: + - zuerst die groessten Gruppen auf die passenden Tische + verteilen, solange sie noch an einen Tisch passen + oder + - zuerst alle kleinsten Gruppen, da man die nicht mehr teilen + sollte + """ + #print "+ Sitzplatzverteilung\n" + if Gruppen.NLeute > Tische.NStuehle: + print "Anzahl der Leute:", Gruppen.NLeute + print "Anzahl der Plaetze:", Tische.NStuehle + raise IndexError, "zu wenig Stuehle" + + self.MutationsGroesse = 2 + self.VIP = VIPs + self.VIPListe = VIPListe + self.Gruppen = Gruppen + self.Strafen = Strafen + + self.Tische = Tische.deepcopy() + ## self.Tische = Tische + + self.Groesster = Tische.Groesster + self.value = 0 + self.Tid_Value = {} + self.Gid_Value = {} + self.Gid_Tid = {} + + # zuerst die VIPs an die richtigen Tische setzen + self.VIPsSetzen( VIPListe, VIPs, self.Tische ) + + # fuehre Buch ueber die ab jetzt freien Plaetze + self.info = Plaetze( self.Tische ) + + # alle Gruppen auf die Tische verteilen + self.GruppenSetzen( Gruppen ) + + # die Sitzplatzverteilung bepunkten + self.bewerten() + print "erzeugt: ", self.value + def __repr__(self): + """Ausgabe der Sitzplatzverteilung an der Konsole""" + r = "-- Sitzplatzverteilung:\n" + Tids = [] + for T in self.Tische: + Tids.append(T.Id) + Tids.sort() + for Tid in Tids: + T = self.Tische.vonId(Tid) + r = r + repr(T) + "\n" + r = r + " Gruppenwertigkeiten:\n" + Gids = [] + for G in self.Gruppen: + Gids.append(G.Id) + Gids.sort() + for Gid in Gids: + G = self.Gruppen.vonId(Gid) + r = r + " Gruppe " + repr(G.Id) + " (" + repr(self.GruppenWertGet(G)) + ")" + r = r + ", Teilungen: " + repr(self.GruppenTeilungGet(G)) + "\n" + r = r + " Tischwertigkeiten:\n" + for Tid in Tids: + T = self.Tische.vonId(Tid) + r = r + " Tisch " + repr(T.Id) + " (" + repr(self.TischWertGet(T)) + ")\n" + r = r + "Wertigkeit:" + repr(self.value) + "\n" + return r + def speichern(self, OutputTP, OutputPT ): + """Ausgabe der Sitzplatzverteilung in ein File""" + Tids = [] + for T in self.Tische: + Tids.append(T.Id) + Tids.sort() + Liste = [] + + # rausschreiben Tisch -> Personen + fout = open( OutputTP, 'w+') + for Tid in Tids: + T = self.Tische.vonId(Tid) + fout.write( "["+ repr(T.Id)+ "]\n" ) + PlatzNummer = 1 + for P in T: + str = "" + str = str + P._Titel + " " + str = str + P._Vorname + " " + str = str + P._Name + " = " + str = str + "Hof " + repr(T.Hof) + ", " + str = str + "Tisch "+ repr( T.Nummer ) + ", " + str = str + "Nummer "+ repr( PlatzNummer ) + str = str + "\n" + PlatzNummer = PlatzNummer + 1 + fout.write( str ) + + str = "" + str = str + P._Name + ", " + str = str + P._Vorname + ", " + str = str + P._Titel + " = " + str = str + "Hof " + repr(T.Hof) + ", " + str = str + "Tisch "+ repr( T.Nummer ) + ", " + str = str + "Nummer "+ repr( PlatzNummer ) + str = str + "\n" + Liste.append( str ) + + fout.write( "\n" ) + fout.close() + + # rausschreiben Personen -> Tisch + Liste.sort() + fout = open( OutputPT, 'w+') + fout.writelines( Liste ) + fout.close() + + def mutieren(self): + """Aendert die vorhandene Sitzplatzverteilung hoffentlich zum Besseren""" + [IdsSchlechteGruppen, Wertigkeiten] = self.SchlechteGruppenTopX(Anzahl=self.MutationsGroesse) + SchlechteGruppen = [] + for Gid in IdsSchlechteGruppen: + G = self.Gruppen.vonId(Gid) + self.GruppeEntfernen(G) + SchlechteGruppen.append(G) + self.GruppenSetzen( SchlechteGruppen ) + self.bewerten() + + print "mutiert: ", self.value + return self + def __cmp__(self,other): + if self.value < other.value: return -1 + elif self.value == other.value: return 0 + else: return 1 + def bewerten(self): + """Errechnet die momentane Wertigkeit der Sitzplaetze""" + self.GesamtWertSet( 0 ) + # Tische bewerten + for T in self.Tische: + #print T + n_freie = T.freiePlaetze() + Strafpunkte = self.Strafen.gibPunkte( 'Tischbesetzung', freiePlaetze=n_freie ) + self.TischWertSet( T, Strafpunkte ) + self.GesamtWertAdd( Strafpunkte ) + + #self.GruppenWertAdd( Gruppe, self.Strafen.gibPunkte( 'nichtNachbar') ) + + # schauen wie oft eine Gruppe getrennt wurde + for G in self.Gruppen: + NTeilungen = self.GruppenTeilungGet(G) + Strafpunkte = self.Strafen.gibPunkte( 'Trennung', G.Anzahl(), NTeilungen ) + self.GruppenWertSet( G, Strafpunkte ) + self.GesamtWertAdd( Strafpunkte ) + + # schauen ob Leute an einem Tisch allein sind + Strafpunkte = self.Strafen.gibPunkte( 'allein' ) + for T in self.Tische: + Gids = self.LeuteAllein( T ) + for Gid in Gids: + G = self.Gruppen.vonId( Gid ) + self.GruppenWertAdd( G, Strafpunkte ) + self.GesamtWertAdd( Strafpunkte ) + def Wertigkeit(self): + """Ausgabe der Guete der Sitzplatzverteilung an der Konsole""" + return ' L '+ repr(self.value) + + # Personenspezifische Funktionen + def PersonSetzen(self, Person, Tisch): + """setzt eine Person an den Tisch""" + Tisch.Person_dazu( Person ) + def PersonEntfernen(self, Person, Tisch): + """entfernt eine Person von dem Tisch""" + Tisch.Person_weg( Person ) + FreiVorher = Tisch.freiePlaetze() + # der Tisch hat jetzt weniger freie Plaetze + self.info.update( Tisch, FreiVorher ) + def PlatzTauschen(self, neuePerson, altePerson, Tisch): + """Tauscht zwischen zwei Personen den Sitzplatz""" + self.PersonEntfernen( altePerson, Tisch ) + self.PersonSetzen( neuePerson, Tisch ) + + # Gruppenspezifische Funktionen + def GruppenSetzen(self, Gruppen ): + """setzt mal die grossen mal die kleinen Gruppen auf beliebige Plaetze""" + # Mache Liste der Gruppen, der Groesse nach sortiert + Gruppenliste = [] + for G in Gruppen: + Gruppenliste.append(G) + + # uns setzte sie auf freie Plaetze + while len(Gruppenliste) > 0: + wahl = choice(['grosse', 'kleine']) + if cmp(wahl,'grosse')== 0: + G = Gruppenliste.pop(0) + else: + G = Gruppenliste.pop(-1) + self.GruppeSetzen(G) + def GruppeSetzen(self, Gruppe, Tisch=None ): + """setzt eine Gruppe irgendwohin wo Platz ist + oder an einen gewuenschten Tisch + """ + ## print "---------------------" + ## print "GruppeSetzen: Gruppe:", Gruppe + if Tisch is None: + Tisch = self.info.mindestensNFreie(Gruppe.Anzahl()) + + # kein Tisch mehr in der gewuenschten groesse frei. + # also Gruppe trennen + if Tisch is None: + # neue Gruppengroesse zufaellig bestimmen + Teil1 = choice( range(Gruppe.Anzahl()) ) + [G1, G2] = Gruppe.teilen( Teil1 ) + + # Benachbarte Tische suchen die gross genug sind + n1 = G1.Anzahl() + n2 = G2.Anzahl() + [TA,TNA] = self.info.NachbarTische(n1, n2) + [TB,TNB] = self.info.NachbarTische(n2, n1) + if TA is None and TB is None: + # keine Nachbarn gefunden, also irgendwo hinsetzen + self.GruppeSetzen(G1) + self.GruppeSetzen(G2) + elif TA is None: + self.GruppeSetzen(G2,TB) + self.GruppeSetzen(G1,TNB) + elif TB is None: + self.GruppeSetzen(G1,TA) + self.GruppeSetzen(G2,TNA) + else: + # nimm die Kombination, die die Tische am besten fuellt + vollA = 0 + vollB = 0 + if TA.istvoll(n1): vollA = vollA + 1 + if TNA.istvoll(n2): vollA = vollA + 1 + if TB.istvoll(n2): vollB = vollB + 1 + if TNB.istvoll(n1): vollB = vollB + 1 + if vollA > vollB: + self.GruppeSetzen(G1,TA) + self.GruppeSetzen(G2,TNA) + else: + self.GruppeSetzen(G2,TB) + self.GruppeSetzen(G1,TNB) + else: + FreiVorher = Tisch.freiePlaetze() + for P in Gruppe: + self.PersonSetzen(P, Tisch) + # der Tisch hat jetzt weniger freie Plaetze + self.info.update( Tisch, FreiVorher ) + # zur Gruppe merken, an welchen Tischen sie jetzt sitzt + try: + Ids = self.Gid_Tid[Gruppe.Id] + Ids.add(Tisch.Id) + except KeyError: + s = Set() + s.add(Tisch.Id) + self.Gid_Tid[Gruppe.Id] = s + def GruppeEntfernen(self, Gruppe): + """entfernt eine Gruppe von Ihren Tischen""" + TischIds = self.Gid_Tid[Gruppe.Id] + + for Tid in TischIds: + T = self.Tische.vonId(Tid) + FreiVorher = T.freiePlaetze() + for P in Gruppe: + #print "P:", P + try: + self.PersonEntfernen( P, T ) + except IndexError: + pass + except KeyError: + pass + self.info.update( T, FreiVorher ) + del self.Gid_Tid[Gruppe.Id] + # der Tisch hat jetzt weniger freie Plaetze + # print self.Tische + + # Bewertungsfunktionen (Evaluation) + # entscheiden bei der Mutation der Sitzplatzverteilung welche Tische als + # erstes wieder aufgeloest werden und welche nicht so schnell + def GesamtWertSet(self, Wert): + """setzt die Gesamtwertung auf einen bestimmten Wert""" + self.value = Wert + def GesamtWertGet(self): + """gibt den Wert der Gesamtwertung zurueck""" + return self.value + def GesamtWertAdd(self, Wert): + """fuegt den Wert zur Gesamtwertung hinzu""" + self.value = self.value + Wert + def GruppenWertSet(self, Gruppe, Wert): + self.Gid_Value[Gruppe.Id] = Wert + def GruppenWertGet(self, Gruppe): + """gibt die Zufriedenheit einer Gruppe zurueck + + je nachdem, wie oft die Gruppe oft geteilt wurde + (je nach deren Groesse, bei grossen laesst es sich nicht vermeiden) + """ + try: + return self.Gid_Value[Gruppe.Id] + except KeyError: + return 0 + def GruppenWertAdd(self, Gruppe, Wert): + """fuegt den Wert der Gruppenwertigkeit hinzu """ + try: + self.Gid_Value[Gruppe.Id] = self.Gid_Value[Gruppe.Id] + Wert + except KeyError: + self.Gid_Value[Gruppe.Id] = Wert + def TischWertSet(self, Tisch, Wert): + """setzt die Wertigkeit dieses Tisches auf einen bestimmten Wert""" + self.Tid_Value[Tisch.Id] = Wert + def TischWertGet(self, Tisch): + """Gib die Wertigkeit eines Tisches zurueck + + - wenn viele unzufriedene Leute an dem Tisch sitzen, + ist die Wertigkeit schlecht + - wenn nur noch ein Platz frei ist, + ist die Wertigkeit des Tisches ebenfalls schlecht + weil man niemanden mehr dort hinsetzen kann + - wenn die Leute der eigenen Gruppe nicht an den Nachbartischen sitzen, + ist die Wertigkeit auch nicht gut + """ + try: + return self.Tid_Value[Tisch.Id] + except KeyError: + return 0 + + def LeuteAllein(self, Tisch): + """Stellt fest wieviele Leute an diesem Tisch alleine sind, + weil sie zu einer Gruppe gehoeren, + die an diesem Tisch nicht vertreten ist + """ + Anzahl_von_Gid = {} + Gids = [] + for P in Tisch: + G = self.Gruppen.GruppeVonPid(P.Id) + try: + Anzahl_von_Gid[G.Id] = Anzahl_von_Gid[G.Id] + 1 + except KeyError: + Anzahl_von_Gid[G.Id] = 1 + for Gid, Anzahl in Anzahl_von_Gid.iteritems(): + if Anzahl == 1: + Gids.append(Gid) + return Gids + + + # Funktionen fuer mehrere Einheiten (Information) + def SchlechteTischeTopX(self, Anzahl=-1): + """gibt eine List mit X Tischids zurueck, die schlechte Wertungen haben""" + return self.TopX( self.Tid_Value, Anzahl ) + def SchlechteGruppenTopX(self, Anzahl=-1): + """gibt eine List mit X Gruppenids zurueck, die schlechte Wertungen haben""" + return self.TopX( self.Gid_Value, Anzahl ) + + # Hilfsfunktionen + def GruppenTeilungGet(self, Gruppe): + try: + return len( self.Gid_Tid[Gruppe.Id] ) - 1 + except KeyError: + return 0 + def VIPsSetzen(self, VIPListe, VIPs, Tische ): + """setze die VIPs auf Ihre Plaetze""" + #print " VIPsSetzen:" + for PersonId, TischId in VIPListe.iteritems(): + #print " VIPsSetzen: PersonId", PersonId + #print " VIPsSetzen: TischId", TischId + Person = VIPs.PersonVonPid(PersonId) + Tisch = Tische.vonId(TischId) + self.PersonSetzen( Person, Tisch ) + def TopX(self, Liste, Anzahl=-1 ): + """gibt eine Liste mit X Ids zurueck, die die schlechtesten Wertungen haben""" + Min = 0 + RListe=[] + Wertigkeit=[] + # TODO filter verwenden + for Id, Wert in Liste.iteritems(): + if Wert <= Min: + RListe.append(Id) + Wertigkeit.append(Wert) + Min = Wert + return [RListe[-Anzahl:], Wertigkeit[-Anzahl:] ] + + +# Sitzplatzverteilung, bestehend aus den Einzelelementen +class XMLConfig: + """aus Xml file alles einlesen""" + def getText(self, nodelist): + rc = "" + for node in nodelist: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + def handlePersonNode( self, person ): + """Personendaten erfassen""" + info = {} + try: + Titel = person.getElementsByTagName("Titel")[0] + info["Titel"] = self.getText(Titel.childNodes) + except IndexError: + info["Titel"] = "" + Vorname = person.getElementsByTagName("Vorname")[0] + Nachname = person.getElementsByTagName("Nachname")[0] + info["Vorname"] = self.getText(Vorname.childNodes) + info["Nachname"] = self.getText(Nachname.childNodes) + return info + def HandleBestellung(self, Bestellung): + """alle Bloecke in der XML Bestellung parsen""" + PidListe = [] + VipHash = {} + + PN = Personen() + GN = Gruppen() + VIPGruppe = Gruppe( 0 ) + + print '-HandleBestellung' + AlleGruppenXML = Bestellung.getElementsByTagName("Gruppe") + PID = 0 + GID = 0 + for GruppeXML in AlleGruppenXML: + GID = GID + 1 + print '-- GID ' + repr(GID) + G = Gruppe( GID ) + + IsVip = False + AnzahlReservierungen = 1 + for Node in GruppeXML.childNodes: + if Node.nodeName == 'Tisch': + TischNr = self.getText(Node.childNodes) + print 'TischNr:', TischNr + IsVip = True + if Node.nodeName == 'Anzahl': + AnzahlReservierungen = int(self.getText(Node.childNodes)) + print 'Anzahl der Reservierungen:', AnzahlReservierungen + IsContingent = True + + for Node in GruppeXML.childNodes: + if Node.nodeName == 'Person': + NRes = 0 + for i in range(int(AnzahlReservierungen)): + NRes = NRes + 1 + PID = PID + 1 + print "PID =" + repr(PID) + info = self.handlePersonNode( Node ) + + Vorname = info["Vorname"] + Nachname = info["Nachname"] + Titel = info["Titel"] + P = Person( PID, Vorname, Nachname, Titel) + if IsVip == True: + PidListe.append( int(PID) ) + VipHash[ int(PID) ] = int(TischNr) + VIPGruppe.Person_dazu( P ) + else: + PN.PersonAdd( P ) + G.Person_dazu( P ) + if (G.Anzahl > 0) & (IsVip != True): + GN.Gruppe_dazu( G ) + if IsVip == True: + GID = GID - 1 + print PN + print GN + print VIPGruppe + print VipHash + print '==========' + return [ PN, GN, VIPGruppe, VipHash ] + def laden(self, Bestellung): + """lese alle Eingangsdaten aus einem XML File ein""" + fsock = open( Bestellung, 'r') + xmlini = minidom.parse(fsock) + return self.HandleBestellung(xmlini) + + + +if __name__ == '__main__': + + print "\n-- Erzeuge Personen:" + P1 = Person( 1, 'Michael', 'Stangl') + P2 = Person( 2, 'Magnus', 'Mueller') + P3 = Person( 3, 'Bernd Robert', 'Hoehn') + P4 = Person( 4, 'Heinz', 'Ruehmann') + P5 = Person( 5, 'Franz', 'Bruegge') + P6 = Person( 6, 'Hubert', 'K') + print P1 + print P2 + print P3 + print P4 + print P5 + print P6 + + print "\n-- Mehrzahl von Personen:" + PN = Personen([P1, P2, P3, P4, P5, P6]) + print PN + + print "\n-- Erzeuge Gruppen mit den Personen:" + G1 = Gruppe( 1, [P1, P2] ) + G1.Person_dazu( P3 ) + G2 = Gruppe( 2 ) + G2.Person_dazu( P4 ) + G3 = Gruppe( 3, [P5,P6] ) + + print "\n-- Stelle Gruppen dar:" + print G1 + print G2 + print G3 + + print "\n-- Durchlaufe Gruppe 3:" + for P in G3: + print P + + print "\n-- Mache Liste der Gruppen:" + GN = Gruppen([G1,G2,G3]) + print GN + + print "\n-- Durchlaufe Gruppen sortiert:" + for G in GN: + print G + + print "\n-- Teile Gruppe:" + [GX, GY] = G1.teilen() + print GX + print GY + [GX, GY] = G1.teilen(3) + print GX + print GY + + print "\n-- Erzeuge Tische mit Personen:" + T1 = Tisch( 1, Plaetze=5, Koordinaten=(1,2), pids=[P1, P2], Nachbarliste=[2] ) + print T1 + + T2 = Tisch( 2, Plaetze=4, Koordinaten=(3,2), Nachbarliste=[1,3] ) + T2.Person_dazu( P3 ) + print T2 + T2.Person_dazu( P4 ) + print T2 + T2.Person_weg( P4 ) + print T2 + T3 = Tisch( 3, Plaetze=2, Koordinaten=(5,2), Nachbarliste=[2] ) + print "\n-- Ist Tisch 2 voll oder leer?:" + print "ist voll = ", T2.istvoll() + print "ist leer = ", T2.istleer() + + print "\n-- Wieviele Plaetze sind an Tisch 1 noch frei ?:" + print "Freie Plaetze = ", T1.freiePlaetze() + print "Besetzte Plaetze = ", T1.besetztePlaetze() + + print "\n-- Stelle Tische dar:" + print T1 + print T2 + print T3 + print "\n-- Ist Person Nummer 3 an Tisch 1 ?:" + print P1 in T1 + print "-- Ist Person Nummer 4 an Tisch 1 ?:" + print P4 in T1 + + TE = Tische([T1,T2,T3]) + print TE + + print "\n-- Hole Tisch 2 aufgrund seiner Id :" + TX = TE.vonId( 2 ) + print TX + + print "\n-- Hole Gruppe 2 aufgrund ihrer Id :" + GX = GN.vonId( 2 ) + print GX + + print "\n-- Hole Person 2 aufgrund ihrer Id aus den Gruppen:" + PX = GN.PersonVonPid( 2 ) + print PX + + print "\n-- schau wo noch mindestens 3 Plaetze frei sind:" + info = Plaetze(TE) + print info.mindestensNFreie( 3 ) + + print "\n-- schau wo zwei Gruppen bestimmter Groesse nebeneinander sitzen koennen:" + print " zwei neben drei:" + [TX,TY] = info.NachbarTische(2, 3) + print TX + print TY + print " drei neben zwei:" + [TX,TY] = info.NachbarTische(3, 2) + print TX + print TY + + P1 = Person( 1, 'Michael', 'Stangl') + P2 = Person( 2, 'Magnus', 'Mueller') + P3 = Person( 3, 'Bernd Robert', 'Hoehn') + P4 = Person( 4, 'Heinz', 'Ruehmann') + P5 = Person( 5, 'Marlene', 'Dietrich') + P6 = Person( 6, 'Sergio', 'Leone') + P7 = Person( 7, 'Walter', 'Emmerlich') + P8 = Person( 8, 'Harald', 'Junke') + P9 = Person( 9, 'Willi', 'Brandt') + P10 = Person( 10, 'Michael', 'Schumacher') + P11 = Person( 11, 'Ralf', 'Schumacher') + P12 = Person( 12, 'Bla', 'Button') + P13 = Person( 13, 'Heinz Harald', 'Frenzen') + +# +# T1 T2 T3 T4 +# <3> <5> <3> <4> +# +# G1 G2 G3 G4 +# <3> <2> <2> <6> +# + print "\n-- Mache Gruppen:" + VIPGruppe = ( Gruppe( 1, [P1, P2, P3] ) ) + G2 = ( Gruppe( 2, [P4, P5] ) ) + G3 = ( Gruppe( 3, [P6, P7] ) ) + G4 = ( Gruppe( 4, [P8, P9, P10, P11, P12, P13] ) ) + GN = Gruppen([G2,G3,G4]) + print GN + + print "\n-- Mache Tische:" + T1 = ( Tisch( 1, Plaetze=3, Koordinaten=(1,1), Nachbarliste=[2] ) ) + T2 = ( Tisch( 2, Plaetze=5, Koordinaten=(2,1), Nachbarliste=[1,3] ) ) + T3 = ( Tisch( 3, Plaetze=3, Koordinaten=(3,1), Nachbarliste=[2,4] ) ) + T4 = ( Tisch( 4, Plaetze=4, Koordinaten=(4,1), Nachbarliste=[3] ) ) + + TE = Tische([T1,T2,T3,T4]) + print TE + + print "\n-- Mache Listen:" + # Personenid - Tischid + VIPListePT = { 3:1, 2:1, 1:1 } + print "VIP Liste:", VIPListePT + + # Strafliste + # die Teilung einer grossen Gruppe ist nicht so schlimm + # wie die einer kleinen + Teilung = list() + Teilung.append({'x':'x'}) + Teilung.append({2:-10, 3:-8, 4:-6, 6:-4, 10:-2}) + Teilung.append({3:-20, 4:-8, 6:-6, 10:-4}) + Teilung.append({4:-30, 6:-10, 10:-6}) + # Ein Platz an einem Tisch frei ist schlechter als zwei Plaetze frei + TischWertigkeiten={ 1:-3, 2:-2, 3:-1 } + SL = Strafliste(GruppenTrennen=Teilung, NichtNachbar=-3, Allein=-30, TischWert=TischWertigkeiten) + print SL + + print "\n-- Teste Strafliste:" + print "SL.gibPunkte('Trennung', 7,1):", SL.gibPunkte('Trennung', 7,1) + print "SL.gibPunkte('Trennung', 5,1):", SL.gibPunkte('Trennung', 5,1) + print "SL.gibPunkte('Trennung', 3,1):", SL.gibPunkte('Trennung', 3,1) + try: + print "SL.gibPunkte('Trennung',(1,1):",SL.gibPunkte('Trennung',1,1) + except IndexError: + print "Gruppe sind mindestens zwei" + + print "\n-- Baue Sitzplatzverteilung:" + SV = Sitzplatzverteilung(Tische=TE, Gruppen=GN, Strafen=SL, + VIPListe=VIPListePT, VIPs=VIPGruppe) + print SV + + print "\n-- Mutiere Sitzplatzverteilung:" + SV.mutieren() + print SV + + print "\n-- Gibt die 3 Tische mit der schlechtesten Wertung:" + [TischIds, Wertigkeit]=SV.SchlechteTischeTopX(3) + print "TischIds:", TischIds + print "Wertigkeit:", Wertigkeit + + print "\n-- Gibt die Gruppen mit der schlechtesten Wertung:" + [GruppenIds, Wertigkeit]=SV.SchlechteGruppenTopX(3) + print "GruppenIds:", GruppenIds + print "Wertigkeit:", Wertigkeit + + +else: + pass + + + + diff --git a/libs/ga.py b/libs/ga.py new file mode 100755 index 0000000..b4e0c00 --- /dev/null +++ b/libs/ga.py @@ -0,0 +1,194 @@ +""" +Enthaelt alle Datenstrukturen um die einen genetischen Algorithmus darzustellen + +""" +from random import * +from itertools import chain +from string import split +from copy import deepcopy +import ConfigParser, os + + +__author__ = "Michael Stangl" +__version__ = "$Revision: $" +__date__ = "$Date: $" +__copyright__ = "Copyright (c) 2005 Michael Stangl" +__license__ = "Python" + +class Loesung: + """ein einfaches Loesungsobjekt. Taugt um es als Superklasse zu ueberladen""" + def __init__(self, *Argumente, **keywords): + self.Id = -1 * randint(1,100) + self.value = self.Id + print " initialisiere Loesung " + repr(self.Id) + def mutieren(self): + print " mutiere Loesung " + repr(self.Id) + self.Id = -1 * randint(1,100) + self.value = self.Id + return self + def kreuzen(self,obj): + print " kreuze Loesung " + repr(self.Id) + def laden(self): + print " lade Loesung " + repr(self.Id) + def speichern(self): + print " speichere Loesung " + repr(self.Id) + def __repr__(self): + return ' L '+ repr(self.Id) + def __cmp__(self,other): + if self.value < other.value: return -1 + elif self.value == other.value: return 0 + else: return 1 + +class Zyklus: + """Definiert wie ein Zyklus ablaufen soll: + + wann sollen Objekte generiert, gekreuzt, mutiert und selektiert werden + wieviele sind davon jeweils betroffen + """ + def __init__(self, Name='default', + Abfolge='e,m,s', + Anzahl='10,10,10'): + self.Name = Name + self.Abfolge = split(Abfolge, ',') + self.Anzahl = split(Anzahl,',') + def __repr__(self): + return( "Zyklus: %s\n" + " Zyklusabfolge: %s\n" + " Anzahl : %s\n" + % ( self.Name, + self.Abfolge, + self.Anzahl ) ) + def laden(self, FileName, ZyklusName): + config = ConfigParser.ConfigParser() + ZyklusPath= os.path.split( FileName ) + ZyklusPath= os.path.join( FileName ) + config.read( ZyklusPath ) + self.Name = ZyklusName + Abfolge = eval( config.get( ZyklusName, 'Abfolge' )) + Anzahl = eval( config.get( ZyklusName, 'Anzahl' )) + self.Abfolge = Abfolge.split(',') + self.Anzahl = Anzahl.split(',') + pass + +class Farm: + """enthaelt und pflegt Loesungsobjekte, kreuzt, mutiert, selektiert sie""" + def __init__(self, Zyklus, Klasse, *Arguments, **keywords): + """initialisiere die Farm + + mit einem definerten Zyklus fuer die Zucht und dem gewunschten zu Zuchtobjekt + """ + self.Position = 0 + self.Pool = [] + self.PoolNeu = [] + self.Zyklus = Zyklus + self.Klasse = Klasse + for Aktion, Zahl in zip(Zyklus.Abfolge,Zyklus.Anzahl): + #print 'Aktion:',Aktion + #print 'Zahl:',Zahl + self.Position = self.Position + 1 + if Aktion == 'e': + self.LoesungenErzeugen(int(Zahl), Klasse, *Arguments, **keywords) + elif Aktion == 'm': + self.LoesungenMutieren(int(Zahl)) + elif Aktion == 's': + self.LoesungenAuswaehlen(int(Zahl)) + elif Aktion == 'S': + self.LoesungenZufaelligAuswaehlen(int(Zahl)) + elif Aktion == 'j': + self.LoesungenBehalten() + elif Aktion == 'z': + self.NeueGeneration() + else: + pass + def LoesungenErzeugen(self, N, Klasse, *Arguments, **keywords): + """ Erzeuge Loesungen""" + for i in xrange(N): + L = Klasse( *Arguments, **keywords ) + self.Pool.append(L) + #print repr(len(self.Pool)) + ' Loesungsobjekte erzeugt' + def LoesungenKreuzen(self,N): + """mache aus zwei Loesungen eine neue""" + #print "+ Loesungen kreuzen" + for i in xrange(N): + self.Pool.append(self.Pool[i].kreuzen()) + def LoesungenMutieren(self, N): + """veraendere die Loesung, so dass sie hoffentlich besser wird""" + print "+ Loesungen mutieren: ", N + for n in xrange(N): + #print " -"+repr(n+1)+" mal" + for L in chain(self.Pool): + O = deepcopy(L) + self.PoolNeu.append(O.mutieren()) + #print self + def LoesungenBehalten(self): + """Behalte alle Eltern aus dem alten Pool""" + print "+ alten Loesungspool behalten" + self.PoolNeu = self.PoolNeu + self.Pool + #print self + def NeueGeneration(self): + """Loesche alle bisherigen Eltern und mache einen neuen Zyklus""" + print "+ Neue Generation erzeugen" + self.Pool = self.PoolNeu + self.PoolNeu = [] + #print self + #print "---------------" + def LoesungenAuswaehlen(self, N): + """Selektiere die besten Loesungen""" + print "+ die besten -", repr(N) +" - Loesungen auswaehlen -" + for i in xrange(N): + L = max(self.Pool) + self.PoolNeu.append(L) + self.Pool.remove(L) + #print self + def LoesungenZufaelligAuswaehlen(self, N): + """Selektiere zufaellig Loesungen""" + print "+ zufaellig auswaehlen -"+ repr(N) + "-" + for i in xrange(N): + self.PoolNeu.append(choice(self.Pool)) + #print self + def __repr__(self): + """Drucke die Farm am Bildschirm aus""" + return( " gewaehlte Objekte (%d): %s\n" + " Elternobjekte (%d) : %s\n" + % ( len(self.PoolNeu), self.PoolNeu, + len(self.Pool), self.Pool)) + def laden(self): + print "+ laden" + def speichern(self): + print "+ speichern" + def Bester(self): + return max(self.Pool) + + +if __name__ == '__main__': + print "\n-- Erzeuge Zyklus:" + #Z = Zyklus( Name='Easy', + #Abfolge='e,s,+,m,j,S,+', + #Anzahl='10,5,x,2,x,5,x' + #) + Z = Zyklus( Name='Easy', + Abfolge='e,'+'s,z,m,j,z,'*3+'s', + Anzahl='10,'+'5,x,2,x,x,'*3+'1' + ) + print Z + + print "\n-- Erzeuge Loesungen:" + L1 = Loesung() + L2 = Loesung() + L3 = Loesung() + print L1, L2, L3 + print 'L1 > L2 =', L1 > L2 + print 'L2 > L3 =', L2 > L3 + print 'L1 > L3 =', L1 > L3 + + A=2 + B=3 + + print "\n-- Erzeuge Farm:" + F1 = Farm( Z, Loesung, Arg1=A, Arg2=B, Arg3=L1 ) + print F1 + +else: + pass + + diff --git a/libs/platz.py b/libs/platz.py new file mode 100755 index 0000000..8b84aa7 --- /dev/null +++ b/libs/platz.py @@ -0,0 +1,73 @@ +""" +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 ConfigParser + + +if __name__ == '__main__': + + # lade Vorgaben fuer Optimierungszyklus und + config = ConfigParser.ConfigParser() + ConfigPath= os.path.join( os.getenv('PLATZ_CFG'), 'platz.cfg') + config.read( os.path.expandvars( ConfigPath )) + + Zyklusconfig = os.path.normpath( config.get( 'Config', 'Zyklusdatei' )) + Zyklusconfig = os.path.expandvars( Zyklusconfig ) + Zyklusart = config.get( 'Config', 'Zyklusart' ) + + Strafenconfig = os.path.normpath(config.get( 'Config', 'Strafendatei' )) + Strafenconfig = os.path.expandvars( Strafenconfig ) + ## print Strafenconfig + + # lade Eingabedateien + Tischconfig = os.path.normpath(config.get( 'Config', 'Tischedatei' )) + Tischconfig = os.path.expandvars(Tischconfig) + Bestellung = os.path.normpath(config.get( 'Config', 'XMLdatei_Bestellung' )) + Bestellung = os.path.expandvars( Bestellung ) + + # lade Ausgabedateien + AusgabeTP= os.path.normpath(config.get( 'Config', 'AusgabeTischePersonen' )) + AusgabeTP = os.path.expandvars(AusgabeTP) + AusgabePT = os.path.normpath(config.get( 'Config', 'AusgabePersonTisch' )) + AusgabePT = os.path.expandvars(AusgabePT) + + Z = Zyklus() + Z.laden( Zyklusconfig, Zyklusart ) + print Z + SL = Strafliste() + SL.laden( Strafenconfig ) + print SL + TE = Tische() + TE.laden( Tischconfig ) + print TE + + InputFile = XMLConfig() + [ PN, GN, VIPGruppe, VIPListePT ] = 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 ) + +else: + pass + + + + diff --git a/work/test1/PersonenTische.csv b/work/test1/PersonenTische.csv new file mode 100644 index 0000000..29b5469 --- /dev/null +++ b/work/test1/PersonenTische.csv @@ -0,0 +1,19 @@ +AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 2 +AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 3 +AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 4 +AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 5 +AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 6 +AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 2 +AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 3 +AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 4 +AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 5 +AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 6 +BB, B, Prof. = Hof 1, Tisch 3, Nummer 2 +BB, B, Prof. = Hof 1, Tisch 3, Nummer 3 +BB, B, Prof. = Hof 1, Tisch 3, Nummer 4 +BB, B, Prof. = Hof 1, Tisch 3, Nummer 5 +CC, C, Dr. = Hof 1, Tisch 4, Nummer 2 +CC, C, Dr. = Hof 1, Tisch 4, Nummer 3 +CC, C, Dr. = Hof 1, Tisch 4, Nummer 4 +CC, C, Dr. = Hof 1, Tisch 4, Nummer 5 +CC, C, Dr. = Hof 1, Tisch 4, Nummer 6 diff --git a/work/test1/TischePersonen.txt b/work/test1/TischePersonen.txt new file mode 100644 index 0000000..2d21859 --- /dev/null +++ b/work/test1/TischePersonen.txt @@ -0,0 +1,27 @@ +[1] +Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 1 +Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 2 +Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 3 +Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 4 +Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 5 + +[2] +Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 1 +Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 2 +Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 3 +Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 4 +Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 5 + +[3] +Prof. B BB = Hof 1, Tisch 3, Nummer 1 +Prof. B BB = Hof 1, Tisch 3, Nummer 2 +Prof. B BB = Hof 1, Tisch 3, Nummer 3 +Prof. B BB = Hof 1, Tisch 3, Nummer 4 + +[4] +Dr. C CC = Hof 1, Tisch 4, Nummer 1 +Dr. C CC = Hof 1, Tisch 4, Nummer 2 +Dr. C CC = Hof 1, Tisch 4, Nummer 3 +Dr. C CC = Hof 1, Tisch 4, Nummer 4 +Dr. C CC = Hof 1, Tisch 4, Nummer 5 + diff --git a/work/test1/bestellung.xml b/work/test1/bestellung.xml new file mode 100755 index 0000000..e4cc7de --- /dev/null +++ b/work/test1/bestellung.xml @@ -0,0 +1,32 @@ + + + + + A + AA + Dipl. Ing. + + 10 + + + + + B + BB + Prof. + + 4 + + + + + C + CC + Dr. + + 5 + + + + + diff --git a/work/test1/tische.ini b/work/test1/tische.ini new file mode 100755 index 0000000..88b783e --- /dev/null +++ b/work/test1/tische.ini @@ -0,0 +1,28 @@ +[1] +Nummer=1 +Hof=1 +Plaetze=5 +Nachbarliste=[2] +Koordinaten=(1,1) + +[2] +Nummer=2 +Hof=1 +Plaetze=5 +Nachbarliste=[1,3] +Koordinaten=(2,1) + +[3] +Nummer=3 +Hof=1 +Plaetze=5 +Nachbarliste=[2,4] +Koordinaten=(3,1) + +[4] +Nummer=4 +Hof=1 +Plaetze=5 +Nachbarliste=[3] +Koordinaten=(4,1) + diff --git a/work/test2/bestellung.xml b/work/test2/bestellung.xml new file mode 100755 index 0000000..2ee9577 --- /dev/null +++ b/work/test2/bestellung.xml @@ -0,0 +1,90 @@ + + + + + + Michael + Stangl + Dipl. Ing. + + + Magnus + Mueller + Professor + + + Bernd Robert + Hoehn + Professor + + 1 + + + + + + Heinz + Bruegge + + + Hubert + K + + + + + + Heinz + Ruehmann + + + Marlene + Dietrich + + + + + + Sergio + Leone + + + Walter + Emmerlich + + + Harald + Junke + + + Willi + Brandt + Dr. + + + Michael + Schumacher + + + Ralf + Schumacher + + + Heinz Harald + Frenzen + + + + + + + Bestelli + Bloedkopf + + 3 + + + + + diff --git a/work/test2/tische.ini b/work/test2/tische.ini new file mode 100755 index 0000000..d66f52f --- /dev/null +++ b/work/test2/tische.ini @@ -0,0 +1,35 @@ +[1] +Nummer=1 +Hof=1 +Plaetze=3 +Nachbarliste=[2] +Koordinaten=(1,1) + +[2] +Nummer=2 +Hof=1 +Plaetze=5 +Nachbarliste=[1,3] +Koordinaten=(2,1) + +[3] +Nummer=3 +Hof=1 +Plaetze=3 +Nachbarliste=[2,4] +Koordinaten=(3,1) + +[4] +Nummer=4 +Hof=1 +Plaetze=4 +Nachbarliste=[3,5] +Koordinaten=(4,1) + +[5] +Nummer=5 +Hof=1 +Plaetze=4 +Nachbarliste=[4] +Koordinaten=(5,1) +