/*
* Datei: MutationsArt1Trans.java
* Autor(en): Lukas K�nig
* Java-Version: 1.4
* Erstellt (vor): 08.01.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/
package fmg.fmg8.endlAutomat.mutation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import fmg.fmg8.endlAutomat.EndlicherAutomat;
import fmg.fmg8.endlAutomat.Transition;
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.umgebung2D.Roboter;
/**
* Die erste Mutationsart mit angepasstem Modus f�r die Mutation von
* Translatoren.
*
* @author Lukas K�nig
*/
public class MutArt1VT implements CondMutVerfahren {
/**
* Der Zufallsgenerator.
*/
private Random rand;
/**
* Der konstante Parameter zur Einschr�nkung direkter Zahlmutationen.
* Es muss gelten: 0 < k <= 255.
*/
private int k;
/**
* Der Modus (�bersetzer oder Verhaltensautomat).
*/
private int modus;
/**
* Verhaltensautomaten-Modus.
*/
public static final int MODUS_VERHALTEN
= SonstMeth.MODUS_VERHALTEN;
/**
* �bersetzermodus.
*/
public static final int MODUS_TRANSLATOR
= SonstMeth.MODUS_TRANSLATOR;
/**
* Konstruktor.
*
* @param random Der Zufallsgenerator.
* @param kKonst Die Konstante k aus der Definition der Mutation: Gibt an
* wie gro� die �nderung bei bspw. Sensorwerten maximal
* sein darf.
* @param mod Der Modus (Verhalten oder �bersetzer).
*/
public MutArt1VT(
final Random random,
final int kKonst,
final int mod) {
this.rand = random;
this.k = kKonst;
this.modus = mod;
throw new RuntimeException("Mutation nicht ausgewaehlt.");
}
/**
* Falls (mind.) eine "false"-Kante im Automaten existiert, wird eine
* zuf�llige "false"-Kante gel�scht. Sonst bleibt der Automat unver�ndert.
* Die Zuf�lligkeit bezieht sich nur auf die Wahl des Ausgangsknotens.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Kante entfernt wurde.
*/
public final boolean mutationFalseKanteRem(final EndlicherAutomat ea) {
HashMap<Integer, LinkedList<Transition>> alleBeds
= ea.getAlleBedingungen();
ArrayList<Integer> alleKnoten
= new ArrayList<Integer>(alleBeds.keySet());
LinkedList<Transition> aktBeds;
Integer aktKnoten;
Iterator<Transition> it;
String aktBed;
Transition vollstBed;
Integer fZustand;
int pruefIndex;
while (alleKnoten.size() > 0) {
pruefIndex = this.rand.nextInt(alleKnoten.size());
aktKnoten = alleKnoten.get(pruefIndex);
aktBeds = alleBeds.get(aktKnoten);
it = aktBeds.iterator();
while (it.hasNext()) {
vollstBed = (Transition) it.next();
aktBed = vollstBed.getCond().formatted();
if (aktBed.charAt(1) == fmg.fmg8.endlAutomat.Konstanten.FALSE) {
fZustand = new Integer(vollstBed.getFolgezustand());
ea.entferneKante(aktKnoten, fZustand, vollstBed);
return true;
}
}
alleKnoten.remove(pruefIndex);
}
return false;
}
/**
* F�gt eine "false"-Kante in den Automaten ein, falls mindestens ein
* Zustand existiert. Die eingef�gte Kante zeigt
* von rand(Z) nach rand(Z)
* mit Z = Zust�nde des Automaten.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Kante eingef�gt wurde.
*/
public final boolean mutationFalseKanteEin(final EndlicherAutomat ea) {
ArrayList<Integer> knListe = ea.getKnList();
Integer zufallsKnoten1;
Integer zufallsKnoten2;
if (knListe.size() > 0) {
zufallsKnoten1 = knListe.get(this.rand.nextInt(knListe.size()));
zufallsKnoten2 = knListe.get(this.rand.nextInt(knListe.size()));
if (!ea.kanteExistiert(zufallsKnoten1, zufallsKnoten2)) {
ea.einfuegKante(
zufallsKnoten1,
zufallsKnoten2,
" " + fmg.fmg8.endlAutomat.Konstanten.FALSE + " ",
1);
return true;
}
}
return false;
}
/**
* L�scht einen Zustand ohne eingehende Kanten aus dem Automaten,
* falls mindestens ein solcher Zustand existiert.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob ein Zustand gel�scht wurde.
*/
public final boolean mutationZustandRem1(final EndlicherAutomat ea) {
ArrayList<Integer> knListe = ea.getKnList();
Knoten zufallsKnoten1;
int zufallsIndex;
while (knListe.size() > 0) {
zufallsIndex = this.rand.nextInt(knListe.size());
zufallsKnoten1 = (Knoten) ea.holeKnoten(knListe.get(zufallsIndex));
if (!ea.istStartZ(zufallsKnoten1)
&& zufallsKnoten1.holeVorgaenger().size() == 0) {
ea.entferneKnoten(knListe.get(zufallsIndex));
return true;
}
knListe.remove(zufallsIndex);
}
return false;
}
/**
* L�scht einen Zustand ohne ausgehende Kanten und IDLE als Befehl aus dem
* Automaten, falls mindestens ein solcher Zustand existiert.
*
* SEMI-SEMANTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob ein Zustand gel�scht wurde.
*/
public final boolean mutationZustandRem2(final EndlicherAutomat ea) {
ArrayList<Integer> knListe = ea.getKnList();
Knoten zufallsKnoten1;
int zufallsIndex;
while (knListe.size() > 0) {
zufallsIndex = this.rand.nextInt(knListe.size());
zufallsKnoten1 = (Knoten) ea.holeKnoten(knListe.get(zufallsIndex));
if (((ZInfo) zufallsKnoten1.getInfo()).getAktion()
== Konstanten.IDLE_BEFEHL
&& zufallsKnoten1.holeNachfolger().size() == 0
&& !ea.istStartZ(zufallsKnoten1)) {
ea.entferneKnoten(knListe.get(zufallsIndex));
return true;
}
knListe.remove(zufallsIndex);
}
return false;
}
/**
* F�gt einen Zustand ohne eingehende Kanten in den Automaten ein.
* Falls der Namensraum f�r Zust�nde �berl�uft, bleibt der Automat
* unver�ndert. Falls vorher kein Startzustand
* existierte, wird der neue Zustand zum Startzustand.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob ein Zustand eingef�gt wurde.
*/
public final boolean mutationZustandEin(final EndlicherAutomat ea) {
int parameter;
int befehl;
ArrayList<Integer> knListe = ea.getKnList();
final int byteMax = 255;
Integer name;
parameter = this.rand.nextInt(this.k) + 1;
befehl = SonstMeth.glVertZwischen(
SonstMeth.minBef(this.modus),
SonstMeth.maxBef(this.modus),
this.rand);
for (int i = 1; i <= byteMax; i++) {
name = new Integer(i);
if (!knListe.contains(name)) {
ea.einfuegenKnoten(name, befehl, parameter, 1);
if (ea.holeStartzustand() == null) {
ea.setStart(ea.holeKnoten(name));
}
return true;
}
}
return false;
}
/**
* Mutiert eine zuf�llige Bedingung nach dem folgenden Muster:
* false <> a = b <> a ~ b <> a <= b <> a < b <> a # b <> a != b <> true
* Falls keine Bedingung existiert, bleibt der Automat unver�ndert.
*
* SEMANTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Bedingung mutiert wurde.
*/
public final boolean mutationBedA(final EndlicherAutomat ea) {
ArrayList<Transition> bedingungen = ea.getBedListe();
Transition aktBed;
String aktString;
String neuString = "";
int pos;
int zufallsindex;
ArrayList<Character> zeichen = new ArrayList<Character>(2);
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.FALSE));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.GL));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.UNGF));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.KLGL));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.GRGL));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.KL));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.GR));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.NUNGF));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.UGL));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.TRUE));
boolean links = this.rand.nextBoolean();
boolean oben = this.rand.nextBoolean();
boolean var1 = this.rand.nextBoolean();
boolean var2 = !var1 || this.rand.nextBoolean();
String string1;
String string2;
if (bedingungen.size() > 0) {
zufallsindex = this.rand.nextInt(bedingungen.size());
aktBed = (Transition) bedingungen.get(zufallsindex);
aktString = aktBed.getCond().formatted();
pos = this.indexZeichen(aktString,
zeichen);
if (aktString.charAt(pos)
== fmg.fmg8.endlAutomat.Konstanten.FALSE) {
if (var1) {
int variable1 = SonstMeth.glVertZwischen(
SonstMeth.minVar(this.modus),
SonstMeth.maxVar(this.modus),
this.rand);
string1 = " "
+ fmg.fmg8.endlAutomat.Konstanten.EING + " "
+ fmg.fmg8.sonstiges.SonstMeth.normZahl(variable1);
} else {
int nummer1 = this.rand.nextInt(255) + 1;
string1 = fmg.fmg8.sonstiges.SonstMeth.normZahl(nummer1);
}
if (var2) {
int variable2 = SonstMeth.glVertZwischen(
SonstMeth.minVar(this.modus),
SonstMeth.maxVar(this.modus),
this.rand);
string2 = " "
+ fmg.fmg8.endlAutomat.Konstanten.EING + " "
+ fmg.fmg8.sonstiges.SonstMeth.normZahl(variable2);
} else {
int nummer2 = this.rand.nextInt(255) + 1;
string2 = fmg.fmg8.sonstiges.SonstMeth.normZahl(nummer2);
}
neuString = aktString.substring(0, pos - 1)
+ string1
+ " " + fmg.fmg8.endlAutomat.Konstanten.GL + " "
+ string2
+ aktString.substring(pos + 2);
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.GL) {
if (links) {
int lGrenze;
int rGrenze;
if (pos >= 6 && aktString.charAt(pos - 6)
== fmg.fmg8.endlAutomat.Konstanten.EING) {
lGrenze = pos - 7;
} else {
lGrenze = pos - 4;
}
if (aktString.charAt(pos + 3)
== fmg.fmg8.endlAutomat.Konstanten.EING) {
rGrenze = pos + 8;
} else {
rGrenze = pos + 5;
}
neuString = aktString.substring(0, lGrenze)
+ " " + fmg.fmg8.endlAutomat.Konstanten.FALSE + " "
+ aktString.substring(rGrenze);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.UNGF
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.UNGF) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.GL
+ aktString.substring(pos + 1);
} else {
if (oben) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.KLGL
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.GRGL
+ aktString.substring(pos + 1);
}
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.KLGL) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.UNGF
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.KL
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.GRGL) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.UNGF
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.GR
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.KL) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.KLGL
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.NUNGF
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.GR) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.GRGL
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.NUNGF
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos)
== fmg.fmg8.endlAutomat.Konstanten.NUNGF) {
if (links) {
if (oben) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.KL
+ aktString.substring(pos + 1);
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.GR
+ aktString.substring(pos + 1);
}
} else {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.UGL
+ aktString.substring(pos + 1);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.UGL) {
if (links) {
neuString = aktString.substring(0, pos)
+ fmg.fmg8.endlAutomat.Konstanten.NUNGF
+ aktString.substring(pos + 1);
} else {
int lGrenze;
int rGrenze;
if (pos >= 6 && aktString.charAt(pos - 6)
== fmg.fmg8.endlAutomat.Konstanten.EING) {
lGrenze = pos - 7;
} else {
lGrenze = pos - 4;
}
if (aktString.charAt(pos + 3)
== fmg.fmg8.endlAutomat.Konstanten.EING) {
rGrenze = pos + 8;
} else {
rGrenze = pos + 5;
}
neuString = aktString.substring(0, lGrenze)
+ " "
+ fmg.fmg8.endlAutomat.Konstanten.TRUE
+ " "
+ aktString.substring(rGrenze);
}
}
if (aktString.charAt(pos) == fmg.fmg8.endlAutomat.Konstanten.TRUE) {
if (var1) {
int variable1 = SonstMeth.glVertZwischen(
SonstMeth.minVar(this.modus),
SonstMeth.maxVar(this.modus),
this.rand);
string1 = " "
+ fmg.fmg8.endlAutomat.Konstanten.EING
+ " "
+ fmg.fmg8.sonstiges.SonstMeth.normZahl(variable1);
} else {
int nummer1 = this.rand.nextInt(255) + 1;
string1 = fmg.fmg8.sonstiges.SonstMeth.normZahl(nummer1);
}
if (var2) {
int variable2 = SonstMeth.glVertZwischen(
SonstMeth.minVar(this.modus),
SonstMeth.maxVar(this.modus),
this.rand);
string2 = " "
+ fmg.fmg8.endlAutomat.Konstanten.EING
+ " "
+ fmg.fmg8.sonstiges.SonstMeth.normZahl(variable2);
} else {
int nummer2 = this.rand.nextInt(255) + 1;
string2 = fmg.fmg8.sonstiges.SonstMeth.normZahl(nummer2);
}
neuString = aktString.substring(0, pos - 1)
+ string1
+ " " + fmg.fmg8.endlAutomat.Konstanten.UGL + " "
+ string2
+ aktString.substring(pos + 2);
}
aktBed.setBedingung(neuString);
return true;
}
return false;
}
/**
* Gibt die Position einer zuf�lligen Folge von (zeichen1, zeichen2)
* in einem String zur�ck. Falls keine solche Folge existiert,
* wird -1 zur�ckgegeben. Der Index bezieht sich immer auf die MITTE
* des ZWEITEN Zeichens (jedes Zeichen wird als 3 character kodiert).
*
* @param bedingung Der zu durchsuchende String.
* @param zeichen1 Das erste Zeichen der Folge.
* @param zeichen2 Das zweite Zeichen der Folge.
*
* @return Die Position einer zuf�lligen Zeichenfolge wie beschrieben
* im String.
*/
private int indexZeichenfolge(final String bedingung,
final char zeichen1,
final char zeichen2) {
int start = this.rand.nextInt(bedingung.length());
int i;
char lastTok;
while (start % 3 != 1) {
start = (start + 1) % bedingung.length();
}
i = (start + 3) % bedingung.length();
lastTok = bedingung.charAt(start);
while (i != start) {
if (bedingung.charAt(i) == zeichen2
&& lastTok == zeichen1) {
return i;
}
lastTok = bedingung.charAt(i);
i = (i + 3) % bedingung.length();
}
return -1;
}
/**
* Gibt die Position der zu pos geh�renden �ffnenden Klammer zur�ck.
*
* @param bed Die zu durchsuchende Bedingung.
* @param pos Die Startposition.
*
* @return Die Position der zu pos geh�renden �ffnenden Klammer. 0, falls
* keine existiert.
*/
private int findeKlLinks(final String bed,
final int pos) {
int klammer = 0;
if (pos < 0 || pos >= bed.length()) {
return -1;
}
if (bed.charAt(pos) != fmg.fmg8.endlAutomat.Konstanten.KZ) {
klammer = 1;
}
for (int i = pos; i >= 0; i--) {
if (bed.charAt(i) == fmg.fmg8.endlAutomat.Konstanten.KZ) {
klammer += 1;
} else if (bed.charAt(i) == fmg.fmg8.endlAutomat.Konstanten.KA) {
klammer -= 1;
}
if (klammer == 0) {
return i;
}
}
return 0;
}
/**
* Gibt die Position der zu pos geh�renden schlie�enden Klammer zur�ck.
*
* @param bed Die zu durchsuchende Bedingung.
* @param pos Die Startposition.
*
* @return Die Position der zu pos geh�renden schlie�enden Klammer.
* "lastIndex", falls keine existiert.
*/
private int findeKlRechts(final String bed,
final int pos) {
int klammer = 0;
if (pos < 0 || pos >= bed.length()) {
return -1;
}
if (bed.charAt(pos) != fmg.fmg8.endlAutomat.Konstanten.KA) {
klammer = 1;
}
for (int i = pos; i < bed.length(); i++) {
if (bed.charAt(i) == fmg.fmg8.endlAutomat.Konstanten.KA) {
klammer += 1;
} else if (bed.charAt(i) == fmg.fmg8.endlAutomat.Konstanten.KZ) {
klammer -= 1;
}
if (klammer == 0) {
return i;
}
}
return bed.length() - 1;
}
/**
* Mutiert eine zuf�llige Bedingung nach dem folgenden Muster:
* (A AND true) > A < (true AND A)
* (A OR true) > true < (true OR A)
* (A AND false) > false < (false AND A)
* (A OR false) > A < (false OR A)
* Falls keine mutierbare Bedingung existiert, bleibt der Automat
* unver�ndert.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Bedingung mutiert wurde.
*/
public final boolean mutationBedBeinfacher(final EndlicherAutomat ea) {
ArrayList<Transition> bedingungen = ea.getBedListe();
Transition aktBed;
String aktString;
String neuString;
int posLKlammer;
int posRKlammer;
int pos;
int zufallsindex;
while (bedingungen.size() > 0) {
zufallsindex = rand.nextInt(bedingungen.size());
aktBed = (Transition) bedingungen.get(zufallsindex);
aktString = aktBed.getCond().formatted();
pos = this.indexZeichenfolge(aktString,
fmg.fmg8.endlAutomat.Konstanten.UND,
fmg.fmg8.endlAutomat.Konstanten.TRUE);
if (pos < 0) {
pos = this.indexZeichenfolge(
aktString,
fmg.fmg8.endlAutomat.Konstanten.ODER,
fmg.fmg8.endlAutomat.Konstanten.FALSE);
}
if (pos >= 0) {
posLKlammer = this.findeKlLinks(aktString, pos);
posRKlammer = pos + 3;
neuString = aktString.substring(0, posLKlammer - 1)
+ aktString.substring(posLKlammer + 2,
pos - 4)
+ aktString.substring(posRKlammer + 2);
aktBed.setBedingung(neuString);
return true;
}
pos = this.indexZeichenfolge(
aktString,
fmg.fmg8.endlAutomat.Konstanten.TRUE,
fmg.fmg8.endlAutomat.Konstanten.UND);
if (pos < 0) {
pos = this.indexZeichenfolge(
aktString,
fmg.fmg8.endlAutomat.Konstanten.FALSE,
fmg.fmg8.endlAutomat.Konstanten.ODER);
}
if (pos >= 0) {
posLKlammer = pos - 3;
posRKlammer = this.findeKlRechts(aktString, pos);
neuString = aktString.substring(0, pos - 7)
+ aktString.substring(pos + 2,
posRKlammer - 1)
+ aktString.substring(posRKlammer + 2);
aktBed.setBedingung(neuString);
return true;
}
pos = this.indexZeichenfolge(aktString,
fmg.fmg8.endlAutomat.Konstanten.ODER,
fmg.fmg8.endlAutomat.Konstanten.TRUE);
if (pos < 0) {
pos = this.indexZeichenfolge(aktString,
fmg.fmg8.endlAutomat.Konstanten.UND,
fmg.fmg8.endlAutomat.Konstanten.FALSE);
}
if (pos >= 0) {
posLKlammer = this.findeKlLinks(aktString, pos);
posRKlammer = pos + 3;
neuString = aktString.substring(0, posLKlammer - 1)
+ aktString.substring(pos - 1, pos + 2)
+ aktString.substring(posRKlammer + 2);
aktBed.setBedingung(neuString);
return true;
}
pos = this.indexZeichenfolge(aktString,
fmg.fmg8.endlAutomat.Konstanten.TRUE,
fmg.fmg8.endlAutomat.Konstanten.ODER);
if (pos < 0) {
pos = this.indexZeichenfolge(aktString,
fmg.fmg8.endlAutomat.Konstanten.FALSE,
fmg.fmg8.endlAutomat.Konstanten.UND);
}
if (pos >= 0) {
posLKlammer = pos - 6;
posRKlammer = this.findeKlRechts(aktString, pos);
neuString = aktString.substring(0, posLKlammer - 1)
+ aktString.substring(pos - 4, pos - 1)
+ aktString.substring(posRKlammer + 2);
aktBed.setBedingung(neuString);
return true;
}
bedingungen.remove(zufallsindex);
}
return false;
}
/**
* Gibt zuf�llig eine Position zur�ck, an der eines der �bergebenen Zeichen
* ist. Falls keine solche Position existiert, wird -1 zur�cgegeben.
*
* @param bedingung Der zu durchsuchende String.
* @param zeichen Liste der Zeichen, deren Position gesucht werden soll.
*
* @return Die Position eines zuf�lligen Zeichens wie beschrieben
* im String oder -1.
*/
private int indexZeichen(final String bedingung,
final List<Character> zeichen) {
int start = this.rand.nextInt(bedingung.length());
int i;
while (start % 3 != 1) {
start = (start + 1) % bedingung.length();
}
i = (start + 3) % bedingung.length();
while (i != start) {
if (zeichen.contains(new Character(bedingung.charAt(i)))) {
return i;
}
i = (i + 3) % bedingung.length();
}
if (zeichen.contains(new Character(bedingung.charAt(i)))) {
return i;
}
return -1;
}
/**
* Mutiert eine zuf�llige Bedingung nach dem folgenden Muster:
* (A AND true) < A > (true AND A)
* (A OR false) < A > (false OR A)
* Falls keine Bedingung existiert, bleibt der Automat unver�ndert.
*
* SYNTAKTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Bedingung mutiert wurde.
*/
public final boolean mutationBedkomplexer(final EndlicherAutomat ea) {
// Sei & e {UND, ODER}
// Fall 1: Bed = A => Bed2 = (t & A)
// Fall 2: Bed = (... (A & B) ...) => Bed2 = (... ((t & A) & B) ...)
// Fall 3: Bed = (... (A & B) ...) => Bed2 = (... (A & (t & B)) ...)
// 1. Suche pos mit BED[pos] = UND oder BED[pos] = ODER.
// 2. Falls so ein pos ex.: zuf�llig Fall 2 oder Fall 3.
// Sonst: Fall 1.
ArrayList<Transition> bedingungen = ea.getBedListe();
Transition aktBed;
String aktString;
String neuString = "";
int posLKlammer;
int posRKlammer;
int pos;
int zufallsindex;
ArrayList<Character> zeichen = new ArrayList<Character>(2);
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.UND));
zeichen.add(new Character(fmg.fmg8.endlAutomat.Konstanten.ODER));
boolean und = this.rand.nextBoolean();
boolean fallZwei = this.rand.nextBoolean();
boolean erzwingeFall1 = this.rand.nextInt(5) == 0;
if (bedingungen.size() > 0) {
zufallsindex = this.rand.nextInt(bedingungen.size());
aktBed = (Transition) bedingungen.get(zufallsindex);
aktString = aktBed.getCond().formatted();
pos = this.indexZeichen(aktString,
zeichen);
if (pos < 0 || erzwingeFall1) {
// Fall 1
if (und) {
neuString = " " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.TRUE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.UND + " "
+ aktString
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " ";
} else {
neuString =
" " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.FALSE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.ODER + " "
+ aktString
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " ";
}
} else {
// Fall 2 oder 3
posLKlammer = this.findeKlLinks(aktString, pos);
posRKlammer = this.findeKlRechts(aktString, pos);
if (fallZwei && und) {
neuString = aktString.substring(0, posLKlammer + 2)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.TRUE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.UND + " "
+ aktString.substring(
posLKlammer + 2,
pos - 1)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " "
+ aktString.substring(pos - 1);
}
if (fallZwei && !und) {
neuString = aktString.substring(0, posLKlammer + 2)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.FALSE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.ODER + " "
+ aktString.substring(
posLKlammer + 2,
pos - 1)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " "
+ aktString.substring(pos - 1);
}
if (!fallZwei && und) {
neuString =
aktString.substring(0, pos + 2)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ aktString.substring(
pos + 2,
posRKlammer - 1)
+ " " + fmg.fmg8.endlAutomat.Konstanten.UND + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.TRUE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " "
+ aktString.substring(posRKlammer - 1);
}
if (!fallZwei && !und) {
neuString = aktString.substring(0, pos + 2)
+ " " + fmg.fmg8.endlAutomat.Konstanten.KA + " "
+ aktString.substring(
pos + 2,
posRKlammer - 1)
+ " " + fmg.fmg8.endlAutomat.Konstanten.ODER + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.FALSE + " "
+ " " + fmg.fmg8.endlAutomat.Konstanten.KZ + " "
+ aktString.substring(posRKlammer - 1);
}
}
aktBed.setBedingung(neuString);
return true;
}
return false;
}
/**
* Gibt die Position einer zuf�lligen Zahl in der Bedingung zur�ck.
* (Gemeint sind konstante Byte-Werte). Falls keine Zahl existiert,
* wird -1 zur�ckgegeben. Der Index bezieht sich immer auf die MITTE
* einer 3-stelligen Zahl. (Jedes Zeichen wird als 3 character kodiert.)
*
* @param bedingung Die zu durchsuchende Bedingung.
*
* @return Die Position einer zuf�lligen Byte-Konstante im String.
*/
private int indexZahl(final String bedingung) {
int start = this.rand.nextInt(bedingung.length());
int i;
char lastTok;
while (start % 3 != 1) {
start = (start + 1) % bedingung.length();
}
i = (start + 3) % bedingung.length();
lastTok = bedingung.charAt(start);
while (i != start) {
if (SonstMeth.istZiff(bedingung.charAt(i))
&& lastTok != fmg.fmg8.endlAutomat.Konstanten.EING) {
return i;
}
lastTok = bedingung.charAt(i);
i = (i + 3) % bedingung.length();
}
if (SonstMeth.istZiff(bedingung.charAt(i))
&& lastTok != fmg.fmg8.endlAutomat.Konstanten.EING) {
return i;
}
return -1;
}
/**
* Gibt die Position einer zuf�lligen SensorVar in der Bedingung zur�ck.
* Falls keine SensorVar existiert,
* wird -1 zur�ckgegeben. Der Index bezieht sich immer auf die MITTE
* der 3-stelligen Sensor-Nummer. (Jedes Zeichen wird als 3 character
* kodiert.)
*
* @param bedingung Die zu durchsuchende Bedingung.
*
* @return Die Position einer zuf�lligen SensorVar im String.
*/
private int indexSensVar(final String bedingung) {
int start = this.rand.nextInt(bedingung.length());
int i;
char lastTok;
while (start % 3 != 1) {
start = (start + 1) % bedingung.length();
}
i = (start + 3) % bedingung.length();
lastTok = bedingung.charAt(start);
while (i != start) {
if (SonstMeth.istZiff(bedingung.charAt(i))
&& lastTok == fmg.fmg8.endlAutomat.Konstanten.EING) {
return i;
}
lastTok = bedingung.charAt(i);
i = (i + 3) % bedingung.length();
}
if (SonstMeth.istZiff(bedingung.charAt(i))
&& lastTok == fmg.fmg8.endlAutomat.Konstanten.EING) {
return i;
}
return -1;
}
/**
* Mutiert eine zuf�llige Zahl in einer zuf�lligen Bedingung.
* Falls keine solche Zahl existiert, bleibt der Automat unver�ndert.
*
* SEMANTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Bedingung mutiert wurde.
*/
public final boolean mutationBedZahl(final EndlicherAutomat ea) {
ArrayList<Transition> bedingungen = ea.getBedListe();
int zufallsIndex;
Transition zufallsBed;
String bedString;
int alt;
int neu;
String neuS;
int pos;
while (bedingungen.size() > 0) {
zufallsIndex = this.rand.nextInt(bedingungen.size());
zufallsBed = (Transition) bedingungen.get(zufallsIndex);
bedString = zufallsBed.getCond().formatted();
pos = this.indexZahl(bedString);
if (pos >= 0) {
alt = Integer.parseInt(bedString.substring(pos - 1, pos + 2));
neu = alt + (this.rand.nextInt(2 * this.k)) - this.k;
if (neu < 1) {
neu = 1;
}
if (neu > 255) {
neu = 255;
}
neuS = bedString.substring(0, pos - 1)
+ SonstMeth.normZahl(neu)
+ bedString.substring(pos + 2);
zufallsBed.setBedingung(neuS);
return true;
}
bedingungen.remove(zufallsIndex);
}
return false;
}
/**
* Mutiert eine zuf�llige Sensorvariable in einer zuf�lligen Bedingung.
* Falls keine solche Sensorvariable existiert, bleibt der Automat
* unver�ndert.
*
* SEMANTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob eine Bedingung mutiert wurde.
*/
public final boolean mutationBedSensVar(final EndlicherAutomat ea) {
ArrayList<Transition> bedingungen = ea.getBedListe();
int zufallsIndex;
Transition zufallsBed;
String bedString;
int neu;
String neuS;
int pos;
while (bedingungen.size() > 0) {
zufallsIndex = this.rand.nextInt(bedingungen.size());
zufallsBed = (Transition) bedingungen.get(zufallsIndex);
bedString = zufallsBed.getCond().formatted();
pos = this.indexSensVar(bedString);
if (pos >= 0) {
neu = SonstMeth.glVertZwischen(
SonstMeth.minVar(this.modus),
SonstMeth.maxVar(this.modus),
this.rand);
neuS = bedString.substring(0, pos - 1)
+ SonstMeth.normZahl(neu)
+ bedString.substring(pos + 2);
zufallsBed.setBedingung(neuS);
return true;
}
bedingungen.remove(zufallsIndex);
}
return false;
}
/**
* Mutiert Parameter und evtl. Befehl eines zuf�lligen Zustands, falls
* mindestens ein Zustand im Automaten existiert.
*
* SEMANTISCH
*
* @param ea Der zu mutierende Automat.
* @return Ob ein Zustand mutiert wurde.
*/
public final boolean mutationZustand(final EndlicherAutomat ea) {
ArrayList<Integer> knListe = ea.getKnList();
Knoten zufallsKnoten1;
int veraenderung;
int neuParam;
int altParam;
int neuBefehl;
int zufallsIndex;
if (knListe.size() == 0) {
return false;
} else {
zufallsIndex = this.rand.nextInt(knListe.size());
zufallsKnoten1 = (Knoten) ea.holeKnoten(knListe.get(zufallsIndex));
veraenderung = this.rand.nextInt(2 * this.k) - this.k;
altParam = ((ZInfo)
zufallsKnoten1.getInfo()).getParam();
if (veraenderung + altParam > 0) {
neuParam = altParam + veraenderung;
neuBefehl = ((ZInfo)
zufallsKnoten1.getInfo()).getAktion();
} else if (veraenderung + altParam < 0) {
neuParam = (veraenderung + altParam) * -1;
neuBefehl = SonstMeth.glVertZwischen(
SonstMeth.minBef(this.modus),
SonstMeth.maxBef(this.modus),
this.rand);
} else { // veraenderung + altparam == 0
neuParam = 1;
neuBefehl = ((ZInfo)
zufallsKnoten1.getInfo()).getAktion();
}
((ZInfo) zufallsKnoten1.getInfo()).setAkt(neuBefehl);
((ZInfo) zufallsKnoten1.getInfo()).setPar(neuParam);
return true;
}
}
/**
* Die toString-Methode.
*
* @return String.
*/
@Override
public String toString() {
return "Mutationsart1";
}
/**
* @return Der Zufallsgenerator.
*/
public Random getRand() {
return this.rand;
}
/**
* Mutiert die �bergebene Bedingung.
*
* @param cond Die zu mutierende Bedingung.
*
* @return Die mutierte Bedingung.
*/
@Override
public Condition mutiere(final Condition cond) {
EndlicherAutomat aut = new EndlicherAutomat();
Long[] intObj = new Long[5];
ArrayList<Long> vert = new ArrayList<Long>(5);
aut.einfuegenKnoten(1, 1, 1, 1);
aut.einfuegKante(1, 1, cond, 1);
for (int i = 0; i < intObj.length; i++) {
intObj[i] = new Long(i);
}
vert.add(new Long(10)); // 0 : mutationBedA
vert.add(new Long(9)); // 1 : mutationBedBeinfacher
vert.add(new Long(3)); // 2 : mutationBedZahl
vert.add(new Long(6)); // 3 : mutationBedkomplexer
vert.add(new Long(1)); // 4 : mutationBedSensVar
Long rnd = (Long) MathMeth.randVerteilung(
intObj,
vert,
this.getRand());
switch(rnd.intValue()) {
case 0:
this.mutationBedA(aut);
break;
case 1:
this.mutationBedBeinfacher(aut);
break;
case 2:
this.mutationBedZahl(aut);
break;
case 3:
this.mutationBedkomplexer(aut);
break;
case 4:
this.mutationBedSensVar(aut);
break;
default:
break;
}
return aut.holeKnoten(1).getInfo().getBedingungen().get(0).getCond();
}
/**
* Mutiert den aktiven Verhaltensautomaten des �bergebenen Roboters.
* ACHTUNG: BISHER NUR VERHALTENSAUTOMAT!
*
* @param rob Der zu mutierende Roboter.
*
* @return Ob der Automat mutiert wurde.
*/
public final boolean mutiere(final Roboter rob) {
Long[] intObj = new Long[11];
ArrayList<Long> vert = new ArrayList<Long>(11);
boolean b;
for (int i = 0; i < intObj.length; i++) {
intObj[i] = new Long(i);
}
vert.add(new Long(10)); // 0 : mutationBedA
vert.add(new Long(4)); // 1 : mutationBedBeinfacher
vert.add(new Long(7)); // 2 : mutationFalseKanteRem
vert.add(new Long(3)); // 3 : mutationZustandRem1
vert.add(new Long(3)); // 4 : mutationZustandRem2
vert.add(new Long(1)); // 5 : mutationZustand
vert.add(new Long(3)); // 6 : mutationBedZahl
vert.add(new Long(7)); // 7 : mutationFalseKanteEin
vert.add(new Long(4)); // 8 : mutationZustandEin
vert.add(new Long(6)); // 9 : mutationBedkomplexer
vert.add(new Long(1)); // 10: mutationBedSensVar
Long rnd = (Long) MathMeth.randVerteilung(intObj,
vert,
this.rand);
int zufall = rnd.intValue();
// Mutiere Verhaltensautomaten.
switch(zufall) {
case 0:
b = this.mutationBedA(rob.getAktVAut());
break;
case 1:
b = this.mutationBedBeinfacher(rob.getAktVAut());
break;
case 2:
b = this.mutationFalseKanteRem(rob.getAktVAut());
break;
case 3:
b = this.mutationZustandRem1(rob.getAktVAut());
break;
case 4:
b = this.mutationZustandRem2(rob.getAktVAut());
break;
case 5:
b = this.mutationZustand(rob.getAktVAut());
break;
case 6:
b = this.mutationBedZahl(rob.getAktVAut());
break;
case 7:
b = this.mutationFalseKanteEin(rob.getAktVAut());
break;
case 8:
b = this.mutationZustandEin(rob.getAktVAut());
break;
case 9:
b = this.mutationBedkomplexer(rob.getAktVAut());
break;
case 10:
b = this.mutationBedSensVar(rob.getAktVAut());
break;
default:
b = false;
}
// Setze Code des Verhaltensautomaten.
if (b) {
rob.setAktVCode(rob.getAktVAut().erzeugeSequenz());
}
return b;
}
}