/*
* Datei: RekArt1.java
* Autor(en): Lukas K�nig
* Java-Version: 6.0
* Erstellt (vor): 24.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;
/**
* @author Lukas K�nig
*/
public class RekArt1 implements RekVerfahren {
/**
* Der Zufallsgenerator.
*/
private Random rand;
/**
* Die Parameter.
*/
private Parametersatz pars;
/**
* Erzeugt ein Objekt der Klasse RekArt1, 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 RekArt1(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 f�r jeden Automaten des Roboters separat fitnessproportional
* ein Eltern-Roboter ausgew�hlt, dessen Knoten und Kanten des
* entsprechenden Automaten 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.
*/
@Override
public RobCode[] rekombEinz(final Roboter[] rob) {
int id;
int alt;
int param;
int aktion;
int anzRobs;
int aktName;
int[] fitness;
Condition zCond;
Integer kn1, kn2;
Knoten zwischKnoten;
boolean vorhandenAll;
Iterator<Integer> it;
Iterator<Integer> it1;
Iterator<Integer> it2;
Roboter aktRob = null;
EndlicherAutomat[] kind;
ArrayList<Integer> zustaende;
RobCode[] robC = new RobCode[1];
Knoten[] knotList = new Knoten[rob.length];
Condition[] condListe = new Condition[rob.length];
ArrayList<Long> vert = new ArrayList<Long>(rob.length);
if (rob.length <= 0 || rob[0] == null) {
SonstMeth.log(SonstMeth.LOG_ERROR,
"Kein Roboter zum Rekombinieren �bergeben ("
+ this + ")",
this.pars);
}
id = rob[0].getId();
kind = new EndlicherAutomat[rob[0].vAuts().length];
/*
* 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 allerdings kein erw�nschter Fall), dann
* wird er im Array belassen.
*/
anzRobs = -1;
for (int i = 0; i < rob.length; i++) {
if (rob[i] == null) {
if (anzRobs < 0) {
anzRobs = i;
}
rob[i] = rob[i % anzRobs];
}
}
fitness = new int[rob[0].vAuts().length];
for (int i = 0; i < rob[0].vAuts().length; i++) {
vert.clear();
// Erzeuge Wahrscheinlichkeitsverteilung fitnessproportional.
for (int j = 0; j < rob.length; j++) {
if (rob[j].getFitness()[i] > 0) {
vert.add(new Long(rob[j].getFitness()[i]));
} else {
vert.add(new Long(0));
}
}
aktRob = (Roboter) MathMeth.randVerteilung(rob, vert, this.rand);
zustaende = aktRob.vAuts()[i].getKnList();
fitness[i] = aktRob.getFitness()[i];
kind[i] = new EndlicherAutomat();
vorhandenAll = true;
// Zust�nde einf�gen.
it = zustaende.iterator();
while (it.hasNext()) {
aktName = it.next();
for (int j = 0; j < rob.length; j++) {
zwischKnoten = rob[j].vAuts()[i].holeKnoten(aktName);
if (zwischKnoten != null) {
knotList[j] = zwischKnoten;
} else {
vorhandenAll = false;
break;
}
}
if (vorhandenAll) {
zwischKnoten = (Knoten) MathMeth.randVerteilung(knotList,
vert,
this.rand);
} else {
zwischKnoten = aktRob.vAuts()[i].holeKnoten(aktName);
}
aktion = ((ZInfo) zwischKnoten.getInfo()).getAktion();
param = ((ZInfo) zwischKnoten.getInfo()).getParam();
alt = ((ZInfo) zwischKnoten.getInfo()).getAlter();
kind[i].einfuegenKnoten(aktName, aktion, param, alt);
}
kind[i].setStartBeliebig(); // Setze auf ersten vorh. Knoten.
if (aktRob.vAuts()[i].holeStartzustand() != null) {
// Setze auf Startkn, falls vorhanden.
kind[i].setStart(aktRob.vAuts()[i].holeStartzustand());
}
// Kanten einf�gen.
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()[i].kanteExistiert(kn1, kn2)) {
for (int j = 0; j < rob.length; j++) {
if (rob[j].vAuts()[i].kanteExistiert(kn1, kn2)) {
condListe[j] = rob[j].vAuts()[i].getCondZuTrans(
kn1,
kn2);
} else {
vorhandenAll = false;
break;
}
}
if (vorhandenAll) {
zCond = (Condition) MathMeth.randVerteilung(
condListe,
vert,
this.rand);
} else {
zCond = aktRob.vAuts()[i].getCondZuTrans(kn1, kn2);
}
kind[i].einfuegKante(kn1, kn2, zCond, 1);
}
}
}
}
String[] codes = new String[rob[0].vAuts().length];
for (int i = 0; i < rob[0].vAuts().length; i++) {
codes[i] = kind[i].erzeugeStringSeq();
}
// Erzeuge W'keits-Vert. fitprop. f�r Bedingungen.
vert.clear();
for (int j = 0; j < rob.length; j++) {
if (rob[j].getFitSum() > 0) {
vert.add(new Long(rob[j].getFitSum()));
} else {
vert.add(new Long(0));
}
}
aktRob = (Roboter) MathMeth.randVerteilung(rob, vert, this.rand);
robC[0] = new RobCode(
id,
fitness,
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.
*/
@Override
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.getUmg().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, Kinder: "
+ this.pars.getRekAnzKinder()
+ ", Eltern: "
+ this.pars.getRekAnzEltern()
+ ", Maximalgr��e: "
+ this.pars.getRekMaxPopSize()
+ ", Normieren: "
+ this.pars.getRekNormiert();
return s;
}
}