package eva2.problems.simple;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import eva2.util.annotation.Description;
import eva2.util.annotation.Parameter;
/**
* @author Maximus Mutschler & Jan-Peter Hohloch
*
*/
@Description("Getting an Ass in Hypervolleyball.")
public class HyperVolleyballProblem extends SimpleProblemDouble {
private static final long serialVersionUID = 2796213693976730881L;
/**
* Problem dimension
*/
private int dimension = 4;
private int spaceDimension = dimension - 1;
private Random r = new Random();
/**
* Regular court's side's size.
*/
private final double courtSize = 9;
/**
* 2^(n)+1 players on the court. Where n is the number of space dimensions.
* This means, in a two dimensional court, there are 5 players arranged like
* a cross.
*/
private int numberOfPlayers = getNumberOfPlayers();
public List<Player> players = new ArrayList<HyperVolleyballProblem.Player>();
/**
* same range for all players
*/
private double sigma = 1;
public HyperVolleyballProblem() {
calcPlayers();
}
private void calcPlayers() {
players.clear();
double[] position = new double[spaceDimension];
Arrays.fill(position, courtSize / 2);
players.add(new Player(position, sigma));
double[][] positions = new double[numberOfPlayers - 1][spaceDimension];
playerPositions(0, numberOfPlayers - 1, positions, 0);
for (double[] p : positions) {
players.add(new Player(p, sigma));
}
}
/**
*
* @param begin
* index
* @param end
* index
* @param positions
* will get filled with the positions of the players
* @param index
* current dimension.
*/
private void playerPositions(int begin, int end, double[][] positions,
int index) {
if (index == positions[0].length) {
return;
}
int center = (((end - begin) / 2) + begin);
for (int i = begin; i < center; i++) {
positions[i][index] = courtSize / 4;
}
for (int i = center; i < end; i++) {
positions[i][index] = (courtSize * 3) / 4;
}
playerPositions(begin, center, positions, index + 1);
playerPositions(center, end, positions, index + 1);
}
private double density(double[] position) {
double dens = 0;
for (Player p : players) {
dens += normDistribution(distance(position, p.getPosition()), 0,
p.getSigma());
}
return dens;
}
private double distance(double[] a, double[] b) {
double dist = 0;
for (int i = 0; i < b.length; i++) {
dist += (a[i] - b[i]) * (a[i] - b[i]);
}
return Math.sqrt(dist);
}
private double normDistribution(double x, double mu, double sigma) {
return (1 / (Math.sqrt(2 * Math.PI) * sigma))
* Math.exp((-0.5 * (x - mu) * (x - mu)) / (sigma * sigma));
}
@Override
public double[] evaluate(double[] individual) {
double force = individual[0];
int penalty = 1;
if (force <= 0) {
return new double[] { penalty - force };
}
double[] position = Arrays
.copyOfRange(individual, 1, individual.length);
for (int i = 0; i < position.length; i++) {
position[i] += r.nextGaussian() * force;
}
for (double p : position) {
if ((p > courtSize) || (p < 0)) {
return new double[] { p < 0 ? penalty - p
: (penalty - courtSize) + p };// abweichung
// vom
// feld
// nehmen
}
}
return new double[] { density(position) // individual[0] = velocity.
/ force };
}
@Override
public int getProblemDimension() {
return dimension;
}
public int getDimension() {
return this.dimension;
}
/**
* Set the problem dimension.
*
* @param d
* The dimension.
*/
@Parameter(description = "Set 2 <= Dimension <= 100.")
public void setDimension(int d) {
if (d < 2) {
d = 2;
}
if (d > 100) {
d = 100;
}
dimension = d;
spaceDimension = dimension - 1;
numberOfPlayers = getNumberOfPlayers();
calcPlayers();
}
private int getNumberOfPlayers() {
return (int) Math.pow(2, (spaceDimension)) + 1;
}
@Parameter(description = "Set 0 < Sigma (Players \"range\")")
public void setPlayerSigma(double sigma) {
if (sigma != 0) {
this.sigma = Math.abs(sigma);
}
}
public double getPlayerSigma() {
return sigma;
}
public class Player {
private static final long serialVersionUID = 2796413693976730841L;
private double[] position;
private double sigma;
public Player() {
setPosition(new double[] { 0, 0, 0 });
setSigma(1);
}
public Player(double[] position, double sigma) {
this.setPosition(position);
this.setSigma(sigma);
}
@Override
public String toString() {
return Arrays.toString(getPosition()) + " sigma:" + getSigma();
}
/**
* @return the position
*/
public double[] getPosition() {
return position;
}
/**
* @param position
* the position to set
*/
public void setPosition(double[] position) {
this.position = position;
}
/**
* @return the sigma
*/
public double getSigma() {
return sigma;
}
/**
* @param sigma
* the sigma to set
*/
public void setSigma(double sigma) {
this.sigma = sigma;
}
}
// public static void main(String[] args) {
// HyperVolleyballProblem p = new HyperVolleyballProblem();
// for (Player pl : p.players) {
// System.out.println(pl);
// }
// }
}