Commit 03866544 authored by Ant01n3's avatar Ant01n3

Added the classes to handle demographics.

They are not yet connected to the main simulation code.
parent 12fdc83b
......@@ -45,13 +45,12 @@ import org.miv.pherd.geom.Point3;
* </p>
*
* <p>
* The boid is in fact split in two parts, the {@link Boid} class itself and the
* {@link BoidParticle} inner class that represents the boid in the forces
* system. The boid particle in turn contains a {@link BoidForces} object that
* represents all the forces exercising on the boid. Globally, the {@link Boid}
* class acts on the graph and updates its position, creating links toward other
* boids/nodes that it sees, whereas the {@link BoidParticle} and the
* {@link BoidForces} are used to compute the boid position.
* The boid is in fact split in two parts, the {@link Boid} class itself that
* represents the boid in the forces system. The boid particle in turn contains
* a {@link BoidForces} object that represents all the forces exercising on the
* boid. Globally, the {@link Boid} class acts on the graph and updates its
* position, creating links toward other boids/nodes that it sees, whereas
* the {@link BoidForces} are used to compute the boid position.
* </p>
*
* @author Guilhelm Savin
......@@ -59,9 +58,8 @@ import org.miv.pherd.geom.Point3;
*/
public class Boid extends AdjacencyListNode {
protected final BoidSpecies species;
/** Parameters of this group of boids. */
protected final BoidSpecies species;
/** The set of forces acting on this particle. */
protected BoidForces forces;
......
......@@ -105,11 +105,6 @@ public abstract class BoidForces {
* Compute the forces applied to a boid under the form of a barycenter that
* the boids tries to reach (attraction), an overall direction for all the
* surrounding boids, an overall direction of all the surrounding boids.
*
* @param source
* The boid the forces are computed on.
* @param startCell
* The start cell (usually the root cell of the n-tree).
*/
public void compute() {
Collection<Boid> neigh;
......@@ -203,13 +198,11 @@ public abstract class BoidForces {
public void moveBarycenter(Point3 p) {
barycenter.move(p);
}
/**
* A boid particle p2 that is visible by p1 as been found, integrate it in
* the forces that apply to the boid p1.
*
* @param p1
* The source boid.
* @param b
* the boid visible by p1.
* @param rep
......@@ -291,7 +284,7 @@ public abstract class BoidForces {
* angle for example.
* </p>
*
* @param source
* @param boid
* The source boid.
* @param point
* The point to consider.
......
......@@ -33,6 +33,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import org.graphstream.boids.forces.ntree.NTreeForcesFactory;
......@@ -48,7 +49,7 @@ import org.miv.pherd.geom.Point3;
import java.util.Random;
/**
* Shared data for boids.
* Represents a boid simulation and their underlying interaction graph.
*
* @author Damien Olivier
* @author Guilhelm Savin
......@@ -57,7 +58,7 @@ import java.util.Random;
public class BoidGraph extends AdjacencyListGraph {
public static enum Parameter {
MAX_STEPS, AREA, SLEEP_TIME, STORE_FORCES_ATTRIBUTES, REMOVE_CAUGHT_BOIDS, NORMALIZE_MODE, RANDOM_SEED
MAX_STEPS, AREA, SLEEP_TIME, STORE_FORCES_ATTRIBUTES, NORMALIZE_MODE, RANDOM_SEED
}
/**
......@@ -83,12 +84,7 @@ public class BoidGraph extends AdjacencyListGraph {
protected boolean storeForcesAttributes;
/**
* Remove the boids caught by a predator ?.
*/
protected boolean removeCaughtBoids;
/**
* Normalise boids attraction/repulsion vectors (make the boids move
* Normalize boids attraction/repulsion vectors (make the boids move
* constantly, since very small vectors can be extended).
*/
protected boolean normalizeMode;
......@@ -118,10 +114,25 @@ public class BoidGraph extends AdjacencyListGraph {
*/
protected Random random;
/**
* Factory for the forces model used in boids.
*/
protected BoidForcesFactory forcesFactory;
/**
* Lower point in space.
*/
protected Point3 lowAnchor;
/**
* Higher point in space.
*/
protected Point3 highAnchor;
/**
* Listeners for boid-graph specific events.
*/
protected ArrayList<BoidGraphListener> listeners = new ArrayList<BoidGraphListener>();
/**
* New context.
......@@ -137,7 +148,6 @@ public class BoidGraph extends AdjacencyListGraph {
highAnchor = new Point3(1, 1, 1);
loop = false;
normalizeMode = true;
removeCaughtBoids = false;
storeForcesAttributes = false;
sleepTime = 20;
area = 1;
......@@ -239,14 +249,6 @@ public class BoidGraph extends AdjacencyListGraph {
this.sleepTime = sleepTime;
}
public boolean isCaughtBoidsRemoved() {
return removeCaughtBoids;
}
public void setRemoveCaughtBoids(boolean removeCaughtBoids) {
this.removeCaughtBoids = removeCaughtBoids;
}
public boolean isNormalizeMode() {
return normalizeMode;
}
......@@ -366,9 +368,6 @@ public class BoidGraph extends AdjacencyListGraph {
case STORE_FORCES_ATTRIBUTES:
setStoreForcesAttributes(Boolean.parseBoolean(value));
break;
case REMOVE_CAUGHT_BOIDS:
setRemoveCaughtBoids(Boolean.parseBoolean(value));
break;
case NORMALIZE_MODE:
setNormalizeMode(Boolean.parseBoolean(value));
break;
......@@ -408,6 +407,10 @@ public class BoidGraph extends AdjacencyListGraph {
public void step() {
stepBegins(step + 1);
for(BoidGraphListener listener: listeners) {
listener.step(step + 1);
}
}
@Override
......@@ -435,6 +438,14 @@ public class BoidGraph extends AdjacencyListGraph {
} catch (InterruptedException e) {
}
}
/**
* Register a listener for boid specific events.
* @param listener The listener to register.
*/
public void addBoidGraphListener(BoidGraphListener listener) {
listeners.add(listener);
}
@Override
protected void addNodeCallback(AbstractNode node) {
......@@ -442,6 +453,10 @@ public class BoidGraph extends AdjacencyListGraph {
b.getSpecies().register(b);
super.addNodeCallback(node);
for(BoidGraphListener listener: listeners) {
listener.boidAdded(b);
}
}
@Override
......@@ -450,6 +465,10 @@ public class BoidGraph extends AdjacencyListGraph {
b.getSpecies().unregister(b);
super.removeNodeCallback(node);
for(BoidGraphListener listener: listeners) {
listener.boidDeleted(b);
}
}
@Override
......
package org.graphstream.boids;
/**
* Listener for boids specific events on the boid graph.
*
* <p>
* These are not GraphStream events.
* </p>
*
* @author Guilhelm Savin
* @author Antoine Dutot
*/
public interface BoidGraphListener {
/**
* One iteration passed. During an iteration, all boids are moved according to their
* forces model.
* @param time The current iteration time.
*/
void step(int time);
/**
* One boid was added.
* @param boid The added boid.
*/
void boidAdded(Boid boid);
/**
* One boid was removed.
* @param boid The removed boid.
*/
void boidDeleted(Boid boid);
}
\ No newline at end of file
......@@ -135,9 +135,19 @@ public class BoidSpecies implements Iterable<Boid> {
*/
protected HashMap<String, Boid> boids;
/**
* Specify a CSS class for the species name for the GraphStream viewer.
*/
protected boolean addSpeciesNameInUIClass;
/**
* Allow to create unique identifiers for boids.
*/
private int currentIndex = 0;
/**
* Allow to create unique identifiers for boids.
*/
private long timestamp = System.nanoTime();
/**
......
package org.graphstream.boids;
import java.util.HashMap;
import java.util.LinkedList;
/**
* Handles the appearance and disappearance of boids.
*
* @author Guilhelm Savin
* @author Antoine Dutot
*/
public class DemographicManager implements BoidGraphListener {
/**
* The boid graph.
*/
protected BoidGraph ctx;
/**
* Allow to count time.
*/
protected int currentDate = 0;
/**
* List of boids marked for removal at each step.
* @see #check()
* @see #killAll()
*/
protected LinkedList<Boid> toRemove = new LinkedList<Boid>();
/**
* List of boids marked for reproduction at each step.
* @see #check()
* @see #makeLove()
*/
protected LinkedList<Boid> futureParents = new LinkedList<Boid>();
/**
* Date of birth of each active boid, according to {@link #currentDate}.
* @see #currentDate
*/
protected HashMap<Boid, Integer> birthdays = new HashMap<Boid, Integer>();
/**
* Probability function for boid reproduction.
*/
protected Probability reproduceProbability;
/**
* Probability function for boid death.
*/
protected Probability deathProbability;
public DemographicManager(BoidGraph ctx) {
this(ctx, new Probability.ConstantProbability(1), new Probability.DeathProbability());
}
public DemographicManager(BoidGraph ctx, Probability reproduceProbability, Probability deathProbability) {
this.ctx = ctx;
this.reproduceProbability = reproduceProbability;
this.deathProbability = deathProbability;
ctx.addBoidGraphListener(this);
}
/**
* Set the probability function for boid reproduction.
* @param rc The new probability.
*/
public void setReproduceCondition(Probability rc) {
this.reproduceProbability = rc;
}
/**
* Set the probability function for boid death.
* @param dp The new probability.
*/
public void setDeathProbability(Probability dp) {
this.deathProbability = dp;
}
/**
* Called by the boid graph each time a boid is added.
* @param b The boid to add.
*/
protected void register(Boid b) {
birthdays.put(b, currentDate);
}
/**
* Called by the boid graph each time a boid is removed.
* @param b The boid to remove.
*/
protected void unregister(Boid b) {
birthdays.remove(b);
}
/**
* Kill one boid.
* @param b The boid to remove.
*/
protected void kill(Boid b) {
unregister(b);
ctx.removeNode(b.getId());
}
/**
* Genocide all the boids marked for removed by {@link #check()}.
*/
protected void killAll() {
/*
* if( toRemove.size() > 0 ) System.err.printf( "[DM] kill %d boids\n",
* toRemove.size() );
*/
while (toRemove.size() > 0)
kill(toRemove.poll());
}
/**
* Create boids according to the list of future parents created by {@link #check()}.
*/
protected void makeLove() {
Boid b;
// int i = 0;
while (futureParents.size() > 0) {
b = futureParents.poll();
String id = b.getSpecies().createNewId();
ctx.addNode(id);
// ctx.addBoid(b.getSpecies(), b.getPosition().x, b.getPosition().y, b
// .getPosition().z);
// i++;
}
/*
* if( i > 0 ) System.err.printf("[DM] born %d boids\n", i );
*/
}
/**
* identifies boids succeptible to disapear or reproduce and remove/add them.
*/
protected void check() {
int age;
for (Boid b : birthdays.keySet()) {
age = currentDate - birthdays.get(b);
if (ctx.random.nextFloat() < deathProbability.getProbability(ctx, b, age)) {
toRemove.add(b);
} else if (ctx.random.nextFloat() < reproduceProbability .getProbability(ctx, b, age)) {
futureParents.add(b);
}
}
makeLove();
killAll();
currentDate++;
}
public void boidAdded(Boid boid) {
register(boid);
}
public void boidDeleted(Boid boid) {
unregister(boid);
}
/**
* Call this method after each step of boid computation, to add or remove boids according to
* reproduction rules.
*/
public void step(int time) {
check();
}
/**
* A demographic manager that handles boids species.
*
* @author Guilhelm Savin
* @author Antoine Dutot
*/
public static class SpeciesDemographicManager extends DemographicManager {
BoidSpecies species;
public SpeciesDemographicManager(BoidSpecies species, BoidGraph ctx) {
super(ctx);
this.species = species;
}
public SpeciesDemographicManager(BoidSpecies species, BoidGraph ctx,
Probability r, Probability d) {
super(ctx, r, d);
this.species = species;
}
@Override
protected void register(Boid b) {
if (b.getSpecies() == species)
super.register(b);
}
@Override
protected void unregister(Boid b) {
if (b.getSpecies() == species)
super.unregister(b);
}
}
}
\ No newline at end of file
package org.graphstream.boids;
/**
* Various probability distributions.
*
* @author Guilhelm Savin
*/
public interface Probability {
public static class ConstantProbability implements Probability {
double p;
public ConstantProbability(double p) {
this.p = p;
}
public double getProbability(BoidGraph ctx, Boid b, int age) {
return p;
}
}
public static abstract class SigmoidProbability implements Probability {
double lambda = 1;
double seuil = 0;
public SigmoidProbability(double lambda, double seuil) {
this.lambda = lambda;
this.seuil = seuil;
}
protected double getSigmoidValue(double x) {
return 1.0 / (1.0 + Math.exp(-lambda * (x - seuil)));
}
protected double getSigmoidValue(double x, double lambda, double seuil) {
return 1.0 / (1.0 + Math.exp(-lambda * (x - seuil)));
}
}
public static class DeathProbability extends SigmoidProbability {
public DeathProbability() {
super(0.3, 80);
}
public DeathProbability(int averageLifeHopeness) {
super(0.3, averageLifeHopeness);
}
public double getProbability(BoidGraph ctx, Boid b, int age) {
return getSigmoidValue(age);
}
}
// public static class EnergyDependentReproduceProbability extends
// Probability.SigmoidProbability {
// float reproduce;
//
// public EnergyDependentReproduceProbability(float reproduce) {
// super(0.1, 0);
// this.reproduce = reproduce;
// }
//
// public double getProbability(BoidGraph ctx, Boid b, int age) {
// return reproduce * getSigmoidValue(b.getForces().getEnergy());
// }
// }
//
// public static class EnergyDependentDeathProbability extends
// DeathProbability {
// double lunchAlpha = 0.4;
//
// public EnergyDependentDeathProbability(int averageLifeHopeness) {
// seuil = averageLifeHopeness;
// }
//
// @Override
// public double getProbability(BoidGraph ctx, Boid b, int age) {
// if (b.getForces().getEnergy() <= 0)
// return 1;
// else
// return super.getProbability(ctx, b, age);// Math.max(1-getSigmoidValue(b.getEnergy(),0.1,0),super.getProbability(ctx,b,age));
// }
// }
double getProbability(BoidGraph ctx, Boid b, int age);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment