/*
* File name: NeuroEnvironment.java (package eas.simulation.brain.neural.neuroSimulation)
* Author(s): lko
* Java version: 7.0
* Generation date: 20.04.2013 (09:47:46)
*
* (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.simulation.brain.neural.neuroSimulation;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.LinkedList;
import eas.math.geometry.Polygon2D;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.simulation.brain.neural.GeneralNeuralNetwork;
import eas.simulation.brain.neural.NeuralLink;
import eas.simulation.brain.neural.Neuron;
import eas.simulation.spatial.sim2D.standardEnvironments.AbstractEnvironment2D;
import eas.startSetup.ParCollection;
import eas.startSetup.marbBuilder.zeichenModi.ArrowMaster;
/**
* @author lko
*/
public class NeuroEnvironment extends AbstractEnvironment2D<NeuroAgent> {
/**
*
*/
private static final long serialVersionUID = -715321668811763637L;
private GeneralNeuralNetwork network;
private Vector2D distanceBetweenNeurons = new Vector2D(3, 3);
public NeuroEnvironment(int id, ParCollection params, GeneralNeuralNetwork net) {
super(id, params);
this.setNetwork(net);
}
@Override
public BufferedImage getOutsideView() {
return this.getOutsideView(null);
}
@Override
public BufferedImage getOutsideView(Graphics2D g2) {
Graphics2D g;
BufferedImage img = super.getOutsideView(g2);
if (g2 == null) {
g = img.createGraphics();
g.drawImage(img, 0, 0, null);
} else {
g = g2;
}
Polygon2D pfeilSpitze = new Polygon2D(ArrowMaster.EINFACHE_SPITZE_1);
pfeilSpitze.scale(pfeilSpitze.getBoundingBox().middle(), new Vector2D(0.139 / 1.5, 0.139 / 1.5));
ArrowMaster pfeilMaster = new ArrowMaster(getParCollection());
double leftBorder = -2;
double rightBorder = (this.network.getNeuronCount() - 1) * this.distanceBetweenNeurons.x + 2;
for (int i = 0; i < this.network.getNeuronCount(); i++) {
Polygon2D polTarget = this.getAgentShapeInEnvironment(i);
Neuron currentNeuron = this.network.getNeuron(i);
double dicke = polTarget.getBoundingBox().getWidth() / 30;
double inputOutputArrowLength = dicke * 6;
// Draw input / output.
if (currentNeuron.isInput()) {
Color color = Color.orange;
Polygon2D points = new Polygon2D();
ArrayList<Double> thicks = new ArrayList<Double>(2);
thicks.add(dicke);
thicks.add(dicke);
Vector2D startPoint = new Vector2D(leftBorder, polTarget.getBoundingBox().middle().y);
points.add(startPoint);
points.add(new Vector2D(leftBorder + inputOutputArrowLength, polTarget.getBoundingBox().middle().y));
Polygon2D arrow = pfeilMaster.segmentPfeilPol2D(points,
thicks, ArrowMaster.KUGEL_ENDE,
ArrowMaster.EINFACHE_SPITZE_1, new Vector2D(1, 1),
new Vector2D(1, 1));
arrow = this.getPolygonInVisualization(arrow);
g.setColor(color);
g.fillPolygon(arrow.toPol());
g.setColor(Color.black);
g.drawPolygon(arrow.toPol());
g.drawString(StaticMethods.round(currentNeuron.getInput(), 2)
+ "", (float) startPoint.x, (float) startPoint.y - 5);
Vector2D textPos = new Vector2D(startPoint.x, startPoint.y - 0.2);
textPos = this.getPointInVisualization(textPos);
g.setColor(Color.blue);
g.setFont(new Font("", Font.PLAIN, 10));
g.drawString(
"[" + Math.round(currentNeuron.getInput() * 10000.0) / 10000.0 + "]",
(int) textPos.x,
(int) textPos.y);
}
if (currentNeuron.isOutput()) {
Color color = Color.orange;
Polygon2D points = new Polygon2D();
ArrayList<Double> thicks = new ArrayList<Double>(2);
thicks.add(dicke);
thicks.add(dicke);
Vector2D startPoint = new Vector2D(rightBorder - inputOutputArrowLength, polTarget.getBoundingBox().middle().y);
points.add(startPoint);
points.add(new Vector2D(rightBorder, polTarget.getBoundingBox().middle().y));
Polygon2D arrow = pfeilMaster.segmentPfeilPol2D(points,
thicks, ArrowMaster.KUGEL_ENDE,
ArrowMaster.EINFACHE_SPITZE_1, new Vector2D(1, 1),
new Vector2D(1, 1));
arrow = this.getPolygonInVisualization(arrow);
g.setColor(color);
g.fillPolygon(arrow.toPol());
g.setColor(Color.black);
g.drawPolygon(arrow.toPol());
g.drawString(StaticMethods.round(currentNeuron.getOutput(), 2)
+ "", (float) startPoint.x, (float) startPoint.y - 8);
color = Color.orange;
Vector2D textPos = new Vector2D(startPoint.x, startPoint.y - 0.2);
textPos = this.getPointInVisualization(textPos);
g.setColor(Color.blue);
g.setFont(new Font("", Font.PLAIN, 10));
g.drawString(
"[" + Math.round(currentNeuron.getOutput() * 10000.0) / 10000.0 + "]",
(int) textPos.x,
(int) textPos.y);
}
double maxWeight = Double.NEGATIVE_INFINITY;
double minWeight = Double.POSITIVE_INFINITY;
for (NeuralLink link : currentNeuron.getIncomingLinks()) {
if (link.getWeight() > maxWeight) {
maxWeight = link.getWeight();
}
if (link.getWeight() < minWeight) {
minWeight = link.getWeight();
}
}
// Paint links.
for (NeuralLink link : this.network.getNeuron(i).getIncomingLinks()) {
Polygon2D polSource = this.getAgentShapeInEnvironment(link.getSourceNeuronID());
double xSource = polSource.getBoundingBox().middle().x;
double ySource = 0;
double xTarget = 0;
double yTarget = polTarget.getBoundingBox().middle().y;
Vector2D weightPosSelf = null;
if (i > link.getSourceNeuronID()) {
ySource = polSource.getBoundingBox().lowerRightCorner().y;
xTarget = polTarget.getBoundingBox().upperLeftCorner().x - pfeilSpitze.getBoundingBox().getWidth();
} else if (i < link.getSourceNeuronID()) {
ySource = polSource.getBoundingBox().upperLeftCorner().y;
xTarget = polTarget.getBoundingBox().lowerRightCorner().x + pfeilSpitze.getBoundingBox().getWidth();
} else { // ==
weightPosSelf = new Vector2D(polSource.centerPoint().x - 1, polSource.centerPoint().y - 1.075);
}
Polygon2D punkte = new Polygon2D();
punkte.add(new Vector2D(xSource, ySource));
punkte.add(new Vector2D(xSource, yTarget));
punkte.add(new Vector2D(xTarget, yTarget));
LinkedList<Double> dicken = new LinkedList<Double>();
double weightFactor;
if (Math.abs(maxWeight) > Math.abs(minWeight)) {
minWeight = -maxWeight;
} else {
maxWeight = -minWeight;
}
if (link.getWeight() >= 0) {
weightFactor = link.getWeight() / maxWeight;
} else {
weightFactor = link.getWeight() / minWeight;
}
if (weightFactor > 0 && weightFactor < 0.26) {
weightFactor = 0.26;
}
if (weightFactor <= 0 && weightFactor > -0.26) {
weightFactor = -0.26;
}
if (Double.isNaN(weightFactor)) {
weightFactor = 0.1;
}
double actualDicke = dicke * weightFactor;
dicken.add(actualDicke);
dicken.add(actualDicke);
dicken.add(actualDicke);
// Arrow.
Polygon2D pol = pfeilMaster.segmentPfeilPol2D(
punkte,
dicken,
ArrowMaster.EINFACHER_ABSCHLUSS,
ArrowMaster.EINFACHE_SPITZE_1,
new Vector2D(1, 1),
new Vector2D(dicke / actualDicke, dicke / actualDicke));
pol = this.getPolygonInVisualization(pol);
if (link.getWeight() > 0) {
g.setColor(Color.black);
} else {
g.setColor(Color.red);
}
if (weightPosSelf == null) {
g.fillPolygon(pol.toPol());
g.drawPolygon(pol.toPol());
}
// Weight text.
Font font;
if (Math.abs(weightFactor) > 0.5) {
font = new Font("", Font.BOLD, 12);
} else {
font = new Font("", Font.PLAIN, 10);
}
Vector2D weightPos = new Vector2D(
polSource.getBoundingBox().middle().x + 0.15,
polTarget.getBoundingBox().middle().y - 0.15);
if (weightPosSelf != null) {
weightPos = weightPosSelf;
}
weightPos = this.getPointInVisualization(weightPos);
g.setFont(font);
g.drawString("" + StaticMethods.round(link.getWeight(), 2),
(int) weightPos.x, (int) weightPos.y);
}
Vector2D textPos = new Vector2D(i * this.distanceBetweenNeurons.x - 1, i * this.distanceBetweenNeurons.y + 1.25);
textPos = this.getPointInVisualization(textPos);
g.setColor(Color.blue);
g.setFont(new Font("", Font.PLAIN, 10));
g.drawString(
"[" + Math.round(currentNeuron.getNetOutput() * 10000.0) / 10000.0 + "]",
(int) textPos.x,
(int) textPos.y);
}
return img;
}
public void setNetwork(GeneralNeuralNetwork net) {
if (net != null) {
this.network = net;
} else {
this.network = new GeneralNeuralNetwork(this.getParCollection());
}
this.removeAllAgents();
for (int i = 0; i < this.network.getNeuronCount(); i++) {
this.addAgent(
new NeuroAgent(
i,
this,
this.getParCollection(),
this.network.getNeuron(i)),
new Vector2D(this.distanceBetweenNeurons.x * i, this.distanceBetweenNeurons.y * i),
0);
}
}
}