/*
* Datei: RekArt1NurErstAut.java
* Autor(en): Lukas K�nig
* Java-Version: 6.0
* Erstellt (vor): 15.09.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/
package fmg.fmg8.endlAutomat.rekombination;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import fmg.fmg8.endlAutomat.EndlicherAutomat;
import fmg.fmg8.endlAutomat.RobCode;
import fmg.fmg8.endlAutomat.ZInfo;
import fmg.fmg8.endlAutomat.conditions.Condition;
import fmg.fmg8.graphVis.graph.Knoten;
import fmg.fmg8.sonstiges.MathMeth;
import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.statistik.Parametersatz;
import fmg.fmg8.umgebung2D.Roboter;
/**
* Klasse zur Definition einer Rekombination von n:m Robotern. Die Topologie
* wird nicht rekombiniert, sondern nur von einem Elternroboter �bernommen.
* (Siehe Methode rekombEinzeln).
*
* @author Lukas K�nig
*/
public class RekArt1NurErstAut implements RekVerfahren {
/**
* Der Zufallsgenerator.
*/
private Random rand;
/**
* Die Parameter.
*/
private Parametersatz pars;
/**
* Erzeugt ein Objekt der Klasse RekombinationsArt1, wobei eine
* Rekombination mit der angegebenen Anzahl von Eltern und Kinder
* eingestellt wird. Die Auswirkung auf die Anzahl der Individuen in der
* Kindpopulation muss jedoch erst daraus abgeleitet werden. Bitte die
* �brigen Kommentare beachten!
*
* @param random Der Zufallsgenerator.
* @param params Der Parametersatz.
*/
public RekArt1NurErstAut(final Random random,
final Parametersatz params) {
this.pars = params;
this.rand = random;
throw new RuntimeException("Diese Rekombination ist nicht ausgew�hlt.");
}
/**
* Erzeugt einen Kind-Roboter aus einer beliebigen Liste von
* Elternrobotern.
*
* Dabei wird fitnessproportional ein Eltern-Roboter ausgew�hlt, dessen
* Knoten und Kanten vollst�ndig �bernommen werden. Bei Knoten und Kanten,
* die bei ALLEN anderen Elternteilen vorhanden sind, wird die jeweilige
* Beschriftung fitnessproportional zuf�llig von einem der Eltern gew�hlt.
*
* Wenn weniger Roboter als die vorgegebene Kinderanzahl vorhanden sind,
* werden die Kinder dupliziert. Es muss mindestens ein Kind vorhanden
* sein!
*
* @param rob Liste zu rekombinierender Roboter.
*
* @return Die neue Roboterliste, die nur den Eintrag 0 enth�lt.
*/
public RobCode[] rekombEinz(final Roboter[] rob) {
RobCode[] robC = new RobCode[1];
EndlicherAutomat kind = new EndlicherAutomat();
int id = rob[0].getId();
long fitness;
ArrayList<Long> vert = new ArrayList<Long>(rob.length);
ArrayList<Integer> zustaende;
boolean vorhandenAll;
Iterator<Integer> it, it1, it2;
Integer aktName;
Knoten[] knotenListe = new Knoten[rob.length];
Knoten zwischKnoten;
Integer kn1, kn2;
Knoten zKnoten;
Condition zCond;
int aktion;
int param;
int alt;
boolean istStart;
Roboter aktRob;
Condition[] condListe = new Condition[rob.length];
int j = -1;
/*
* Ersetzt alle Vorkommnisse von <code>null</code> im Array rob durch
* g�ltige im Array weiter vorne stehende Roboter. Dabei wird die
* Liste der Roboter VOR dem ersten Vorkommnis von <code>null</code>
* immer wieder �ber das Array gelegt und die null-Werte werden
* �berschrieben:
*
* [1 3 null null null null] => [1 3 1 3 1 3].
*
* Wenn nach dem ersten Vorkommnis von <code>null</code> ein g�ltiger
* Roboter vorkommt (dies ist kein erw�nschter Fall), dann wird er
* im Array belassen.
*/
for (int i = 0; i < rob.length; i++) {
if (rob[i] == null) {
if (j < 0) {
j = i;
}
rob[i] = rob[i % j];
}
}
for (int i = 0; i < rob.length; i++) {
if (rob[i].getFitness()[0] > 0) {
vert.add(new Long(rob[i].getFitness()[0]));
} else {
vert.add(new Long(0));
}
}
aktRob = (Roboter) MathMeth.randVerteilung(rob, vert, this.rand);
zustaende = aktRob.vAuts()[0].getKnList();
fitness = aktRob.getFitness()[0];
vorhandenAll = true;
it = zustaende.iterator();
while (it.hasNext()) {
aktName = (Integer) it.next();
for (int i = 0; i < rob.length; i++) {
zwischKnoten = rob[i].vAuts()[0].holeKnoten(aktName);
if (zwischKnoten != null) {
knotenListe[i] = zwischKnoten;
} else {
vorhandenAll = false;
break;
}
}
if (vorhandenAll) {
zKnoten = (Knoten) MathMeth.randVerteilung(knotenListe,
vert,
this.rand);
} else {
zKnoten = aktRob.vAuts()[0].holeKnoten(aktName);
}
aktion = ((ZInfo) zKnoten.getInfo()).getAktion();
param = ((ZInfo) zKnoten.getInfo()).getParam();
alt = ((ZInfo) zKnoten.getInfo()).getAlter();
istStart = ((ZInfo) zKnoten.getInfo()).istStartZ();
kind.einfuegenKnoten(aktName, aktion, param, alt);
if (istStart) {
kind.setStart(kind.holeKnoten(aktName));
}
}
it1 = zustaende.iterator();
while (it1.hasNext()) {
kn1 = (Integer) it1.next();
it2 = zustaende.iterator();
while (it2.hasNext()) {
kn2 = (Integer) it2.next();
vorhandenAll = true;
if (aktRob.vAuts()[0].kanteExistiert(kn1, kn2)) {
for (int i = 0; i < rob.length; i++) {
if (rob[i].vAuts()[0].kanteExistiert(kn1, kn2)) {
condListe[i] = rob[i].vAuts()[0].getCondZuTrans(kn1,
kn2);
} else {
vorhandenAll = false;
break;
}
}
if (vorhandenAll) {
zCond = (Condition) MathMeth.randVerteilung(condListe,
vert,
this.rand);
} else {
zCond = aktRob.vAuts()[0].getCondZuTrans(kn1, kn2);
}
kind.einfuegKante(kn1, kn2, zCond, 1);
}
}
}
/*
* TODO: Alter der Knoten UND Kanten.
*/
int[] fits = new int[1];
String[] codes = new String[1];
fits[0] = (int) fitness;
codes[0] = kind.erzeugeStringSeq();
robC[0] = new RobCode(
id,
fits,
codes,
aktRob.getConds(),
aktRob.getTransStdCodes(),
SonstMeth.stringAusListSeqs(aktRob.getTransCodes()),
SonstMeth.stringAusListSeqs(aktRob.getVerhCodes()));
return robC;
}
/**
* F�hrt eine Rekombination der gesamten Population durch. Die
* Rekombination geschieht auf Basis der Methode <code>rekombEinz</code>.
*
* @param pop Die zu rekombinierende Population von Robotern.
*
* @return Die rekombinierte Population.
*/
public ArrayList<RobCode> rekombiniere(final ArrayList<Roboter> pop) {
ArrayList<RobCode> kindPop = new ArrayList<RobCode>();
Roboter[] eltern;
Roboter aktRob;
Iterator<Roboter> it = pop.iterator();
while (it.hasNext()) {
aktRob = it.next();
eltern = aktRob.getEltern().holeNahe(aktRob.getPosition().x,
aktRob.getPosition().y,
this.pars.getRekAnzEltern());
for (int i = 0; i < this.pars.getRekAnzKinder().intValue(); i++) {
kindPop.add(this.rekombEinz(eltern)[0]);
}
}
if (this.pars.getRekNormiert().booleanValue()) {
while (kindPop.size() > pop.size()) {
kindPop.remove(this.rand.nextInt(kindPop.size()));
}
}
while (kindPop.size() > this.pars.getRekMaxPopSize().intValue()) {
kindPop.remove(this.rand.nextInt(kindPop.size()));
}
return kindPop;
}
/**
* Die toString-Methode.
*
* @return Ausgabe.
*/
public String toString() {
String s = "";
s = s
+ "Rekombinationsart1 (nur erster Automat), Kinder: "
+ this.pars.getRekAnzKinder()
+ ", Eltern: "
+ this.pars.getRekAnzEltern()
+ ", Maximalgr��e: "
+ this.pars.getRekMaxPopSize()
+ ", Normieren: "
+ this.pars.getRekNormiert();
return s;
}
}