/*
* (C) 2003-2009 Spolecne s.r.o.
* Author: Tomas Straka
* www.spoledge.com
*
* Written permission must be obtained in advance from Spolecne s.r.o for any form of
* reproduction, use or distribution.
*/
package ants.models.thrakia;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import ants.Simulatible;
import ants.EventQueue;
import ants.models.thrakia.ZygothicGraph.Mediator;
/**
* The representation of antenas - the DBC where sensed Mediators are transfered
* into inpulses in neural network
*/
public class Tentacle extends TimeAware {
/**
* The container for synapses to the connected neurons
*/
private ArrayList<Synapse> synapses;
/**
* The minimal intensity in the world which can be recognized.
*/
private static final double minIntensity = 0.05;
/**
* The maximal intensity in the world which can be recognized. Corresponds
* to the brightest color in the viewer.
*/
private static final double maxIntensity = 1.0;
/**
* The maximal interval in between fires the neural network can process
*/
private static final double maxInterval = ThrakiaAnt.getInterval();
/**
* The minimal frequency of fires the neural network can process
*/
private static final double minFrequency = 1.0 / maxInterval;
/**
* The maximal frequency of fires the neural network can process
*/
private static final double maxFrequency = 1.0 / FireLaw.getMinInterval();
/**
* Create a <i>tentacle</i> with no </i>synapse</i> to other target neurons. Tentacles
* are made to transfer the signal, therefore this constructor should not be called.
* directly. The class is not Simulatible, but it can schedule neurons, so it needs
* access to their time queue.
*/
private Tentacle(EventQueue eq) {
super(eq);
synapses = new ArrayList<Synapse>();
}
/**
* Create a <i>tentacle</i> with one synapse. The synapse is to target neurons.
*/
public Tentacle(EventQueue eq, Synapse synapse) {
this(eq);
this.synapses.add(synapse);
}
/**
* Create a <i>tentacle</i> with an array of synapses. The synapse is to target neurons.
*/
public Tentacle(EventQueue eq, Synapse [] synapses) {
this(eq);
for(int i = 0; i < synapses.length; i++)
this.synapses.add( synapses[i] );
}
/**
* Change the intensity into frequecy of firing. More precisely,
* it returns time, when a connected neuron will receive mediators.
* If the time is shorter or longer than the neural network can manage,
* we do not have to make any special rules. It will work out itself.
*/
protected double getTimeIntervalForFire( Double intensity ) {
double frequency = minFrequency +
( ( intensity.doubleValue() - minIntensity )
* ( (maxFrequency-minFrequency) / (maxIntensity-minIntensity) )
);
if( frequency == 0.0d ) return maxInterval + 1.0; // Infinity
else return 1.0 / frequency;
}
/**
* Accept sensed Odours and schedule the Neurons
*/
public void accept( HashMap<Odour, Double> transmited ) {
// change the intensity of Odour into frequecy of firing
for( Odour o : transmited.keySet() ) {
double dTime = getTimeIntervalForFire( transmited.get( o ) );
for( double nextTime = dTime; nextTime < maxInterval; nextTime += dTime ) {
TimeCapsule tc = new TimeCapsule( o.getCorrespondentMediator() );
schedule( nextTime, tc );
}
}
}
/**
* Time events, which will feed all synapses at the right time with the right mediator.
*/
private class TimeCapsule implements Simulatible {
/**
* The mediator to fire
*/
private Mediator mediator;
/**
* Set the mediator. Multiple TimeCapsules (Odours) can have the same mediator. That is fine
*/
public TimeCapsule(Mediator mediator) {
this.mediator = mediator;
}
/**
* Time for invocation. Then go to the garbage collector
*/
public void simulate(EventQueue.Item item) {
HashSet<Mediator> mSet = new HashSet<Mediator>();
mSet.add(mediator);
for ( Synapse s : synapses ) s.transmit( mSet );
}
}
/**
* Return max recognizable intensity
*/
public static double getMaxIntensity() {
return maxIntensity;
}
}
|