Loesungs-Ids wieder als fortlaufende Nummern 1..N (Vorgaenger separat)
- Farm._WurzelId/_KindId ersetzt durch _NeueId: jede Loesung bekommt eine einfache fortlaufende Nummer (Wurzeln wie Mutationskinder gleich) - die Abstammung steckt nicht mehr in der Id, sondern im schon vorher gemerkten Vorgaenger (Abstammung-Knoten 'eltern'); der Baum und die Hervorhebung des Sieger-Astes funktionieren unveraendert - Tests auf das neue Id-Schema umgestellt (Nummern 1..N, Abstammung ueber Vorgaenger), README/CLAUDE.md aktualisiert - Beispiele neu berechnet Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+22
-29
@@ -330,11 +330,14 @@ class Abstammung:
|
||||
"""Beobachtungsobjekt: zeichnet den Stammbaum aller Loesungen auf.
|
||||
|
||||
Jede Loesung bekommt von der Farm eine fortlaufende Abstammungs-Id.
|
||||
Beim Erzeugen entsteht ein Wurzelknoten (keine Eltern), beim Mutieren
|
||||
ein Kindknoten mit Verweis auf die Eltern-Id. alsSVG() zeichnet daraus
|
||||
einen Baum: Generationen als Zeilen (oben Start, nach unten spaeter),
|
||||
Knoten als Punkte (Farbe = Wertigkeit), Mutationskanten Eltern->Kind.
|
||||
Domaenen-agnostisch; funktioniert mit jeder Loesung, die .value hat.
|
||||
Jede Loesung hat eine fortlaufende Nummer (Id 1..N); die Abstammung
|
||||
ergibt sich aus dem gemerkten Vorgaenger (Eltern-Id), nicht aus der Id
|
||||
selbst. Beim Erzeugen entsteht ein Wurzelknoten (keine Eltern), beim
|
||||
Mutieren ein Kindknoten mit Verweis auf die Eltern-Id. alsSVG() zeichnet
|
||||
daraus einen Baum: Generationen als Zeilen (oben Start, nach unten
|
||||
spaeter), Knoten als Punkte (Farbe = Wertigkeit), Mutationskanten
|
||||
Eltern->Kind. Domaenen-agnostisch; funktioniert mit jeder Loesung, die
|
||||
.value hat.
|
||||
"""
|
||||
def __init__(self):
|
||||
# je Knoten: Id -> dict(eltern, generation, value, aktion)
|
||||
@@ -352,9 +355,9 @@ class Abstammung:
|
||||
"""zeichnet den aufgezeichneten Stammbaum als SVG.
|
||||
|
||||
HervorId (optional): Id der hervorzuhebenden Loesung (z.B. der
|
||||
finalen besten). Ihr Ast wird kraeftig gezeichnet und mit der
|
||||
sprechenden Id (z.B. 7.2.1) beschriftet, so dass man ihre ganze
|
||||
Abstammung ablesen kann."""
|
||||
finalen besten). Ihr Ast (die Kette ihrer Vorgaenger) wird kraeftig
|
||||
gezeichnet und der Knoten mit seiner Nummer beschriftet, so dass man
|
||||
die ganze Abstammung im Baum verfolgen kann."""
|
||||
if not self.Knoten:
|
||||
raise ValueError("keine Abstammung aufgezeichnet")
|
||||
|
||||
@@ -488,9 +491,8 @@ class Farm:
|
||||
# Abstammung: jede Loesung bekommt eine fortlaufende _absid; die
|
||||
# aktuelle Generationsnummer waechst mit jedem Erzeugen/Mutieren.
|
||||
self.Abstammung = Abstammung()
|
||||
self._AbsZaehler = 0
|
||||
self._AbsZaehler = 0 # vergibt fortlaufende Loesungs-Ids 1..N
|
||||
self._Generation = 0
|
||||
self._KindZaehler = {} # Eltern-Id -> Anzahl bisher vergebener Kinder
|
||||
if getattr(Zyklus, 'Modus', 'statisch') == 'adaptiv':
|
||||
self._LaufAdaptiv(Klasse, *Arguments, **keywords)
|
||||
else:
|
||||
@@ -570,28 +572,19 @@ class Farm:
|
||||
print("+ Abbruch: %d Generationen ohne nennenswerte "
|
||||
"Verbesserung" % OhneVerbesserung)
|
||||
break
|
||||
def _WurzelId(self):
|
||||
"""neue Id fuer eine erzeugte (elternlose) Loesung: schlicht eine
|
||||
fortlaufende Zahl als String ('1', '2', ...)."""
|
||||
def _NeueId(self):
|
||||
"""neue Id fuer eine Loesung: eine fortlaufende Nummer 1..N ueber
|
||||
alle je erzeugten Loesungen (Wurzeln wie Mutationskinder gleich).
|
||||
Die Abstammung ergibt sich nicht aus der Id, sondern aus dem
|
||||
separat gemerkten Vorgaenger (siehe erfassen(..., Eltern))."""
|
||||
self._AbsZaehler = self._AbsZaehler + 1
|
||||
return str(self._AbsZaehler)
|
||||
|
||||
def _KindId(self, ElternId):
|
||||
"""neue Id fuer ein Mutationskind: Eltern-Id + '.' + laufender Index,
|
||||
z.B. '7' -> '7.1', '7.2'; '7.2' -> '7.2.1'. So laesst sich die
|
||||
ganze Abstammung direkt aus der Id ablesen. Fehlt eine Eltern-Id
|
||||
(z.B. bei einer Loesung ohne Aufzeichnung), wird eine Wurzel-Id
|
||||
vergeben."""
|
||||
if not ElternId:
|
||||
return self._WurzelId()
|
||||
self._KindZaehler[ElternId] = self._KindZaehler.get(ElternId, 0) + 1
|
||||
return "%s.%d" % (ElternId, self._KindZaehler[ElternId])
|
||||
return self._AbsZaehler
|
||||
|
||||
def LoesungenErzeugen(self, N, Klasse, *Arguments, **keywords):
|
||||
""" Erzeuge Loesungen"""
|
||||
for i in range(N):
|
||||
L = Klasse( *Arguments, **keywords )
|
||||
L._absid = self._WurzelId()
|
||||
L._absid = self._NeueId() # Wurzel: kein Vorgaenger
|
||||
self.Abstammung.erfassen(
|
||||
L._absid, None, self._Generation, getattr(L, 'value', 0), 'e' )
|
||||
self.Pool.append(L)
|
||||
@@ -610,10 +603,10 @@ class Farm:
|
||||
for L in chain(self.Pool):
|
||||
O = deepcopy(L)
|
||||
Kind = O.mutieren()
|
||||
# Kind-Id = Eltern-Id + '.' + laufender Kindindex, damit man
|
||||
# an der Id die ganze Abstammung ablesen kann (z.B. 7.2.1).
|
||||
# Kind bekommt eine neue fortlaufende Nummer; der Vorgaenger
|
||||
# (Eltern-Id) wird separat in der Abstammung gemerkt.
|
||||
ElternId = getattr(L, '_absid', None)
|
||||
Kind._absid = self._KindId(ElternId)
|
||||
Kind._absid = self._NeueId()
|
||||
self.Abstammung.erfassen(
|
||||
Kind._absid, ElternId, self._Generation,
|
||||
getattr(Kind, 'value', 0), 'm' )
|
||||
|
||||
Reference in New Issue
Block a user