/******************************************************************************* * TurtleKit 3 - Agent Based and Artificial Life Simulation Platform * Copyright (C) 2011-2016 Fabien Michel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package turtlekit.pheromone; /** * @author Fabien Michel * */ public class DefaultCPUPheromoneGrid extends AbstractPheromoneGrid<Float> implements Pheromone<Float>{ /** * @param name * @param width * @param height * @param evaporationCoeff * @param diffusionCoeff */ final private float[] values; final private float[] tmp; final private int[] neighborsIndexes; public DefaultCPUPheromoneGrid(String name, int width, int height, float evaporationCoeff, float diffusionCoeff, int[] neighborsIndexes2) { super(name, width, height, evaporationCoeff, diffusionCoeff); values = new float[width * height]; tmp = new float[width * height]; neighborsIndexes = neighborsIndexes2; setMaximum(0f); } @Override public Float get(int index) { return values[index]; } /* (non-Javadoc) * @see turtlekit.pheromone.DataGrid#set(int, java.lang.Object) */ @Override public void set(int index, Float value) { values[index] = value; } public int getMaxDirection(int xcor, int ycor) { float max = get(normeValue(xcor + 1, getWidth()), ycor); int maxDir = 0; float current = get(normeValue(xcor + 1, getWidth()), normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 45; } current = get(xcor, normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 90; } current = get(normeValue(xcor - 1, getWidth()), normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 135; } current = get(normeValue(xcor - 1, getWidth()), ycor); if (current > max) { max = current; maxDir = 180; } current = get(normeValue(xcor - 1, getWidth()), normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 225; } current = get(xcor, normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 270; } current = get(normeValue(xcor + 1, getWidth()), normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 315; } return maxDir; } public int getMinDirection(int i, int j) { float min = get(normeValue(i + 1, getWidth()), j); int minDir = 0; float current = get(normeValue(i + 1, getWidth()), normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 45; } current = get(i, normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 90; } current = get(normeValue(i - 1, getWidth()), normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 135; } current = get(normeValue(i - 1, getWidth()), j); if (current < min) { min = current; minDir = 180; } current = get(normeValue(i - 1, getWidth()), normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 225; } current = get(i, normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 270; } current = get(normeValue(i + 1, getWidth()), normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 315; } return minDir; } @Override protected void diffusionUpdateKernel(){ for (int i=getWidth()-1; i >=0 ; i--) for (int j=getHeight()-1; j >=0 ; j--){ values[get1DIndex(i,j)] += getTotalUpdateFromNeighbors(i, j); } } public void diffusionAndEvaporationUpdateKernel(){ float evapCoef = getEvaporationCoefficient(); for (int i=getWidth()-1; i >=0 ; i--) for (int j=getHeight()-1; j >=0 ; j--){ int k = get1DIndex(i,j); values[k] += getTotalUpdateFromNeighbors(i, j); values[k] -= values[k] * evapCoef; } } float getTotalUpdateFromNeighbors(int i, int j){ int index = get1DIndex(i, j)*8; return tmp[neighborsIndexes[index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]]; } @Override public void diffuseValuesToTmpGridKernel() { float diffCoef = getDiffusionCoefficient(); for (int i = values.length - 1; i >= 0 ; i--) { float give = values[i] * diffCoef; float giveToNeighbor = give / 8; values[i] -= give;//TODO a[k] = value - give tmp[i] = giveToNeighbor; } } @Override public void evaporationKernel() { float evapCoef = (float) getEvaporationCoefficient(); if (evapCoef != 0) { for (int i = values.length - 1; i >= 0; i--) { values[i] -= values[i] * evapCoef; } } } @Override public void incValue(int x, int y, float quantity) { incValue(get1DIndex(x, y), quantity); } /** * Adds <code>inc</code> to the current value of the cell * with the corresponding index * * @param index cell's index * @param inc how much to add */ public void incValue(int index, float inc) { // inc += get(index); // if (inc > maximum) // setMaximum(inc); // set(index, inc); set(index, inc + get(index)); } }