/*
* File name: AntEnvironment.java (package eas.users.oclrws1112.AntTrail)
* Author(s): Julien
* Java version: 6.0
* Generation date: 04.01.2012 (15:33:18)
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.users.ocScenarios.oclrws1112.antTrail;
import java.io.File;
import java.util.List;
import eas.math.geometry.Vector2D;
import eas.plugins.standard.visualization.chartPlugin.ChartEvent;
import eas.plugins.standard.visualization.chartPlugin.ChartEventStoreAsPDF;
import eas.simulation.Wink;
import eas.simulation.spatial.sim2D.gridSimulation.standardEnvironments.AbstractGridEnvironment;
import eas.simulation.spatial.sim2D.gridSimulation.standardGridObjects.GridObject;
import eas.simulation.spatial.sim2D.standardAgents.AbstractAgent2D;
import eas.startSetup.ParCollection;
/**
* @author Nico
* @author Julien
*/
public class AntEnvironment extends AbstractGridEnvironment<AbstractAgent2D<?>> {
/**
*
*/
private static final long serialVersionUID = -5717159986404703093L;
private Vector2D nest; // speichert Koordinaten des Nestzentrums ab
private boolean isLandscape; // gibt an, ob Ameise sich auf einer Gebirgslandschaft oder Ebene bewegt
private int minOfActualWays; // Minimum der aktuellen Weglaengen der Ameisen
private int minOfMinWays; // Minimum der minimalen bisher gefundenen Weglaengen der Ameisen
private double meanOfActualWays; // Durchschnitt der aktuellen Weglaengen
private double stableMean = 0; // Durchschnitt der ueber einen Zeitraum stabil ist
@SuppressWarnings("unused")
private int stabileTicks = 0; // Zeitdauer, wie lange Durchschnitt stabil war
private int liegtAufStrasse; // Anzahl der Zellen die potenziell auf einer Strass liegen
private boolean strasseGefunden = true;
private double meanOfMinWays; // Durchschnitt der minimalen Weglaengen
private double actualVariance; // Varianz der aktuellen Weglaengen
private double standDev; // Standardabweichung der aktuellen Weglaengen
private int antsHasWay; // Anzahl Ameisen, die aktuelle einen Weg gefunden haben
private int antPheromoneValue; // so viel Pheromon legt eine Ameise
private int pheromoneEvaporationRate; // Evaporationsrate des Pheromons
private boolean strasseGefundenVar3 = false;
private int soLongUnderMean = 0; // wie viel Ticks lang, mindestens 6 Ameisenwege kleiner sind als der Durchschnitt
private double genormterWeg = 0.0; // fuer Variante 4!
private boolean strasse4gefunden = false; // fuer Variante 4!
private int zaehler = 0; // fuer Variante 4!
private double zeitGefunden = 0.0; // fuer Variante 4!
private double summeDurchschnitt = 0.0; // fuer Variante 4!
private double summeDurchschnittMitte = 0.0; // fuer Variante 4!
private double summeDurchschnittAnfang = 0.0; // fuer Variante 4!
public AntEnvironment(int ident, ParCollection params, int width,
int height, boolean isTorus, boolean landscape, int phValue, int phEvaporation, Integer MaxPhValue) {
super(ident, params, width, height, isTorus);
this.setLandscape(landscape);
this.setAntPheromoneValue(phValue);
this.pheromoneEvaporationRate = phEvaporation;
Pheromone.MaxValue = MaxPhValue;
}
@Override
public void step(Wink simTime) {
super.step(simTime);
computeStatistics(simTime);
ChartEvent chart = new ChartEvent("Weglängen zum Futter", "Durchschnitt der akt. Weglängen", getMeanOfActualWays());
chart.setyAxisLabel("Weglänge in Ticks");
ChartEvent chart2 = new ChartEvent("Genormte Weglängen zum Futter", "Genormte Weglänge", genormterWeg);
// ChartEvent chart3 = new ChartEvent("Weglängen zum Futter", "Minimale akt. Weglänge", minOfActualWays);
// ChartEvent chart4 = new ChartEvent("Weglängen zum Futter", "Durchschnitt aller min Weglängen", meanOfMinWays);
this.getSimTime().broadcastEvent(chart);
this.getSimTime().broadcastEvent(chart2);
// this.getSimTime().broadcastEvent(chart3);
// this.getSimTime().broadcastEvent(chart4);
if (simTime.getLastTick() == 5000){
this.getSimTime().broadcastEvent(new ChartEventStoreAsPDF("Weglängen zum Futter", new File("Grafik_Ameisenalgorithmus.pdf")));
}
//Pheromon evaporiert
for (int i = 0; i < this.getWidth(); i++) {
for (int j = 0; j < this.getHeight(); j++) {
changePheromone(i, j, pheromoneEvaporationRate); }
}
}
public Pheromone getPheromone(double x, double y) {
List<GridObject> liste = this.getFieldPosition(x, y);
for (GridObject go : liste) {
if (go.getClass().isInstance(new Pheromone())) {
return (Pheromone) go; }
}
return null;
}
//gibt Elevation-Objekt an einer bestimmten Stelle zurueck
public Elevation getElevation(double x, double y) {
List<GridObject> liste = this.getFieldPosition(x, y);
for (GridObject go : liste) {
if (go.getClass().isInstance(new Elevation(1,1))) {
return (Elevation) go; }
}
return null;
}
public Vector2D getNest() {
return nest;
}
private void computeStatistics(Wink simTime){
List<AbstractAgent2D<?>> ants = this.getAgents();
int antsWithWay = 0; // Anzahl der Ameisen, die einen Weg gefunden haben
int wholeActualWay = 0; // gesamte aktuelle Weglaenge von allen Ameisen
int wholeMinWay = 0; // kumulierte minimale Weglaenge von allen Ameisen
setMinOfActualWays(0);
for(AbstractAgent2D<?> emmet : ants){
// falls Ameise einen Weg gefunden hat
if(((Ant) emmet).actualDistance != 0){
// gesamte aktuelle Weglaenge wird berechnet
wholeActualWay = wholeActualWay + ((Ant)emmet).actualDistance;
// gesamte minimale Weglaenge wird berechnet
wholeMinWay = wholeMinWay + ((Ant)emmet).minDistance;
antsWithWay++;
// Minimum von alle aktuellen Wegen der Ameisen wird berechnet
if(getMinOfActualWays() == 0 | ((Ant) emmet).actualDistance < getMinOfActualWays()){
setMinOfActualWays(((Ant) emmet).actualDistance);
}
// Minimum von alle minimalen bisher gefundenen Wegen der Ameisen wird berechnet
if(getMinOfMinWays() == 0 | ((Ant) emmet).minDistance < getMinOfMinWays()){
setMinOfMinWays(((Ant) emmet).minDistance);
}
}
}
// durchschnittliche Weglaengen werden berechnet
if(antsWithWay != 0){
setMeanOfActualWays(wholeActualWay / antsWithWay);
setMeanOfMinWays(wholeMinWay / antsWithWay);
}
// Varianz und Standardabweichung werden berechnet
double var = 0;
for(AbstractAgent2D<?> emmet : ants){
if(((Ant) emmet).actualDistance != 0){
var = var + Math.pow(((Ant) emmet).actualDistance - getMeanOfActualWays(),2);
}
}
actualVariance = var / antsWithWay;
setStandDev(Math.pow(actualVariance,0.5));
setAntsHasWay(antsWithWay);
// Variante 1.: Es wird berechnet, wie lange ein Durchschnittswert stabil ist
// Falls lange stabil (mit erlaubter Abweichung) dann Straße?
if(getMeanOfActualWays() < stableMean * 0.9 | getMeanOfActualWays() > stableMean * 1.1){
// System.out.println("");
// System.out.println("So lange war der Durschnitt " + stableMean + " stabil: " + stabileTicks);
stabileTicks = 1;
stableMean = getMeanOfActualWays();
}
else{
stabileTicks++;
}
// Variante 2.: Sobald Pheromonspiegel auf mindestens 10 Zellen einen bestimmten Schwellwert erreicht hat und diesen ueber
// eine bestimmte Anzahl an Ticks haelt, dann Strasse.
double schwellWert = 2500;
int tickSchwelle = 100;
if(strasseGefunden){
for(int x=0; x < this.getWidth(); x++){
for(int y=0; y < this.getHeight(); y++){
List<GridObject> pheromones = this.getFieldPosition(x,y);
for(GridObject ph : pheromones){
if(ph.getClass().isInstance(new Pheromone())){
if(((Pheromone)ph).getPheromone() >= schwellWert){
((Pheromone)ph).pheromoneIndex++;
if(((Pheromone)ph).pheromoneIndex >= tickSchwelle){
liegtAufStrasse++;
}
}
else{
((Pheromone)ph).pheromoneIndex = 0;
}
}
}
if(liegtAufStrasse >= 10){
System.out.println("Ameisenstraße hat sich gebildet bei Tick: " + simTime.getCurrentTime());
strasseGefunden = false;
}
}
}
}
// Variante3.: Falls mindestens 6 von 10 Ameisen Wege kuerzer als der Durschnitt gefunden haben und dies ueber
// 50 Ticks der Fall ist, dann Ameisenstrasse.
int underMean = 0;
if(strasseGefundenVar3){
for(AbstractAgent2D<?> emmet : ants){
if(antsHasWay >= 10){
// if(((Ant) emmet).actualDistance <= meanOfActualWays){
if(((Ant) emmet).actualDistance <= 25){
underMean++;
}
}
}
if(underMean >= 6){
soLongUnderMean++;
}
else{
soLongUnderMean = 0;
}
if(soLongUnderMean >= 50){
System.out.println("Ameisenstraße Variante3 hat sich gebildet bei Tick: " + simTime.getCurrentTime());
strasseGefundenVar3 = false;
}
}
// Variante 4
if(meanOfActualWays >0 && !strasse4gefunden){
genormterWeg = 13/meanOfActualWays; // Wert zwischen 1 (perfekt) und 0 (schlecht)
if (genormterWeg > 0.5){
zaehler++;
}
if (zaehler > 100){
zeitGefunden = simTime.getCurrentTime();
System.out.println("Ameisenstrasse genormt ab: " + zeitGefunden);
strasse4gefunden = true;
}
}
if (strasse4gefunden){
if (simTime.getCurrentTime() < (zeitGefunden+10000)){
summeDurchschnitt+=meanOfActualWays;
}
if (simTime.getCurrentTime() == (zeitGefunden+10000)){
System.out.println("Wer 10k Ticks nach Strasse: " + summeDurchschnitt/10000);
}
}
// Durchschnittlaenge nach 20000 Ticks
if (simTime.getCurrentTime() < 20000){
summeDurchschnittAnfang+=meanOfActualWays;
}
if (simTime.getCurrentTime() == 20000){
System.out.println("Durchschnitt ab Anfang: " + summeDurchschnittAnfang/20000);
}
if (simTime.getCurrentTime() >= 10000 && simTime.getCurrentTime() < 20000){
summeDurchschnittMitte+=meanOfActualWays;
}
if (simTime.getCurrentTime() == 20000){
System.out.println("Durchschnitt ab Mitte: "+ summeDurchschnittMitte/10000);
}
}
public void changePheromone(double x, double y, double pheromonWert) {
Pheromone ph = getPheromone(x,y);
ph.setPheromone(Math.max(0, ph.getPheromone() + pheromonWert));
}
/**
* @return Returns the antPheromoneValue.
*/
public int getAntPheromoneValue() {
return antPheromoneValue;
}
/**
* @param antPheromoneValue The antPheromoneValue to set.
*/
public void setAntPheromoneValue(int antPheromoneValue) {
this.antPheromoneValue = antPheromoneValue;
}
/**
* @return Returns the isLandscape.
*/
public boolean isLandscape() {
return isLandscape;
}
/**
* @param isLandscape The isLandscape to set.
*/
public void setLandscape(boolean isLandscape) {
this.isLandscape = isLandscape;
}
/**
* @return Returns the minOfActualWays.
*/
public int getMinOfActualWays() {
return minOfActualWays;
}
/**
* @param minOfActualWays The minOfActualWays to set.
*/
public void setMinOfActualWays(int minOfActualWays) {
this.minOfActualWays = minOfActualWays;
}
/**
* @return Returns the meanOfActualWays.
*/
public double getMeanOfActualWays() {
return meanOfActualWays;
}
/**
* @param meanOfActualWays The meanOfActualWays to set.
*/
public void setMeanOfActualWays(double meanOfActualWays) {
this.meanOfActualWays = meanOfActualWays;
}
/**
* @return Returns the meanOfMinWays.
*/
public double getMeanOfMinWays() {
return meanOfMinWays;
}
/**
* @param meanOfMinWays The meanOfMinWays to set.
*/
public void setMeanOfMinWays(double meanOfMinWays) {
this.meanOfMinWays = meanOfMinWays;
}
/**
* @return Returns the antsHasWay.
*/
public int getAntsHasWay() {
return antsHasWay;
}
/**
* @param antsHasWay The antsHasWay to set.
*/
public void setAntsHasWay(int antsHasWay) {
this.antsHasWay = antsHasWay;
}
/**
* @return Returns the standDev.
*/
public double getStandDev() {
return standDev;
}
/**
* @param standDev The standDev to set.
*/
public void setStandDev(double standDev) {
this.standDev = standDev;
}
/**
* @return Returns the minOfMinWays.
*/
public int getMinOfMinWays() {
return minOfMinWays;
}
/**
* @param minOfMinWays The minOfMinWays to set.
*/
public void setMinOfMinWays(int minOfMinWays) {
this.minOfMinWays = minOfMinWays;
}
/**
* @param nest The nest to set.
*/
public void setNest(Vector2D nest) {
this.nest = nest;
}
}