edu.snu.leader.hierarchy.simple.Individual.java Source code

Java tutorial

Introduction

Here is the source code for edu.snu.leader.hierarchy.simple.Individual.java

Source

/*
 *  The Bio-inspired Leadership Toolkit is a set of tools used to
 *  simulate the emergence of leaders in multi-agent systems.
 *  Copyright (C) 2014 Southern Nazarene University
 *
 *  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 edu.snu.leader.hierarchy.simple;

// Imports
import edu.snu.leader.util.MiscUtils;
import ec.util.MersenneTwisterFast;
import org.apache.commons.lang.Validate;
import org.apache.log4j.Logger;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;

/**
 * Individual
 *
 * TODO Class description
 *
 * @author Brent Eskridge
 * @version $Revision$ ($Author$)
 */
public class Individual {
    /** Our logger */
    private static final Logger _LOG = Logger.getLogger(Individual.class.getName());

    /** The individual's ID */
    private Object _id = null;

    /** The individual's group ID */
    private Object _groupID = null;

    /** The individual's location */
    private Point2D _location = null;

    /** Flag indicating whether or not the individual is active */
    private boolean _active = false;

    /** The number of neighbors that are considered "nearest" */
    private int _nearestNeighborCount = 0;

    /** The individual's nearest neighbors */
    private List<Neighbor> _nearestNeighbors = new LinkedList<Neighbor>();

    /** The neighbor this individual is following (if any) */
    private Neighbor _leader = null;

    /** The individuals following this individual */
    private List<Neighbor> _followers = new LinkedList<Neighbor>();

    /** The timestep we went active */
    private long _activeTimestep = Long.MAX_VALUE;

    /** The individual's internal motivation */
    private float _motivation = 0.0f;

    /** The individual's threshold for activity */
    private float _threshold = 0.0f;

    /** The individual's skill level */
    private float _skill = 0.0f;

    /** The individual's confidence */
    private float _confidence = 0.0f;

    /** The individual's reputation */
    private float _reputation = 0.0f;

    /** The individual's boldness */
    private float _boldness = 0.0f;

    /**
     * Builds this Individual object
     *
     * @param simState
     */
    public Individual(SimulationState simState) {
        // Generate our id
        _id = simState.generateUniqueIndividualID();

        // Get the random number generator
        MersenneTwisterFast random = simState.getRandom();

        // Generate our location
        _location = new Point2D.Float(random.nextFloat(), random.nextFloat());

        // Generate our motivation
        //        _motivation = (random.nextFloat() / 2.0f );
        _motivation = 0.0f;

        // Generate our threshold
        float motivationRemainder = 1.0f - _motivation;
        _threshold = _motivation + (random.nextFloat() * motivationRemainder);

        // Generate our skill level
        _skill = (float) MiscUtils.getUnitConstrainedGaussian(random);

        // Generate our confidence
        _confidence = (float) MiscUtils.getUnitConstrainedGaussian(random);

        // Generate our reputation
        _reputation = (float) MiscUtils.getUnitConstrainedGaussian(random);

        // Generate our boldness
        _boldness = (float) MiscUtils.getUnitConstrainedGaussian(random);

        // Log it all
        _LOG.debug("Individual: id=[" + _id + "] location=[" + _location + "] motivation=["
                + String.format("%06.4f", _motivation) + "] threshold=[" + String.format("%06.4f", _threshold)
                + "] skill=[" + String.format("%06.4f", _skill) + "] confidence=["
                + String.format("%06.4f", _confidence) + "] reputation=[" + String.format("%06.4f", _reputation)
                + "] boldness=[" + String.format("%06.4f", _boldness) + "]");
    }

    /**
     * Initializes this individual
     *
     * @param simState
     */
    public void initialize(SimulationState simState) {
        // NOTE: There used to be more here
        //       Finding nearest neighbors is left abstracted to its own
        //       method in case we do more here in the future

        // Find our nearest neighbors
        findNearestNeighbors(simState);
    }

    /**
     * Updates this individual
     */
    public void update() {
        // Has our activation timestep been changed?
        if (Long.MAX_VALUE > _activeTimestep) {
            // Yup, we are active
            _active = true;
        }
    }

    /**
     * Returns a flag indicating that the motivation is larger than the
     * threshold
     *
     * @return <code>true</code> if the motivation is larger than the
     * threshold, otherwise, <code>false</code>
     */
    public boolean isMotivationOverThreshold() {
        return _motivation > _threshold;
    }

    /**
     * Signals this individual to follow the specified individual
     *
     * @param ind
     * @param simState
     */
    public void follow(Individual ind, SimulationState simState) {
        Validate.notNull(ind, "Unable to follow a NULL leader");

        // Get the distance to the individual
        float distance = (float) _location.distance(ind._location);

        // Follow it
        follow(new Neighbor(distance, ind), simState);
    }

    /**
     * Signals this individual to follow the specified individual
     *
     * @param neighbor
     * @param simState
     */
    public void follow(Neighbor neighbor, SimulationState simState) {
        Validate.notNull(neighbor, "Unable to follow a NULL leader");

        // Store it as our leader
        _leader = neighbor;

        // Get their group ID
        _groupID = neighbor.getIndividual().getGroupID();

        // Tell the leader it is being followed
        neighbor.getIndividual().addFollower(this);

        // Log the next time step as the time we are active
        _activeTimestep = simState.getCurrentTime() + 1;
    }

    /**
     * Signals this individual to initiate action
     *
     * @param simState
     */
    public void initiateAction(SimulationState simState) {
        // If we are already following an individual, something is fubar
        Validate.isTrue(null == _leader, "Unable to both follow and initiate action");

        // Log the next time step as the time we are active
        _activeTimestep = simState.getCurrentTime() + 1;

        // Get our own group ID
        _groupID = simState.generateUniqueGroupID();
    }

    /**
     * Signals this individual that the specified individual is following it
     *
     * @param ind
     */
    public void addFollower(Individual ind) {
        // Get the distance to the individual
        float distance = (float) _location.distance(ind._location);

        // Add it to the list of followers
        _followers.add(new Neighbor(distance, ind));
    }

    /**
     * Returns a list of individuals that are following this individual
     *
     * @return The followers
     */
    public List<Neighbor> getFollowers() {
        return new ArrayList<Neighbor>(_followers);
    }

    /**
     * Returns the number of immediate followers
     *
     * @return The number of immediate followers
     */
    public int getImmediateFollowerCount() {
        return _followers.size();
    }

    /**
     * Returns the total number of followers of this individual
     *
     * @return The total number of followers
     */
    public int getTotalFollowerCount() {
        int total = 0;

        Iterator<Neighbor> followerIter = _followers.iterator();
        while (followerIter.hasNext()) {
            // Increment the total to include the follower itself
            ++total;

            // Add the total number of followers of this follower
            total += followerIter.next().getIndividual().getTotalFollowerCount();
        }

        return total;
    }

    /**
     * Returns the distance of the individual from the initiator
     *
     * @return The distance
     */
    public int getDistanceToInitiator() {
        int distance = 0;

        // Make sure we aren't the initiator
        if (null != _leader) {
            // Ask our leader how far away they are
            distance = 1 + _leader.getIndividual().getDistanceToInitiator();
        }

        return distance;
    }

    /**
     * Returns the motivation for this object
     *
     * @return The motivation
     */
    public float getMotivation() {
        return _motivation;
    }

    /**
     * Sets the motivation for this object.
     *
     * @param motivation The specified motivation
     */
    public void setMotivation(float motivation) {
        _motivation = motivation;
    }

    /**
     * Returns the threshold for this object
     *
     * @return The threshold
     */
    public float getThreshold() {
        return _threshold;
    }

    /**
     * Sets the threshold for this object.
     *
     * @param threshold The specified threshold
     */
    public void setThreshold(float threshold) {
        _threshold = threshold;
    }

    /**
     * Returns the id for this object
     *
     * @return The id
     */
    public Object getID() {
        return _id;
    }

    /**
     * Returns the groupID for this object
     *
     * @return The groupID
     */
    public Object getGroupID() {
        return _groupID;
    }

    /**
     * Returns the location for this object
     *
     * @return The location
     */
    public Point2D getLocation() {
        return _location;
    }

    /**
     * Returns the active flag for this object
     *
     * @return The active flag
     */
    public boolean isActive() {
        return _active;
    }

    /**
     * Returns the nearestNeighbors for this object
     *
     * @return The nearestNeighbors
     */
    public List<Neighbor> getNearestNeighbors() {
        return _nearestNeighbors;
    }

    /**
     * Returns the leader for this object
     *
     * @return The leader
     */
    public Neighbor getLeader() {
        return _leader;
    }

    /**
     * Returns the activeTimestep for this object
     *
     * @return The activeTimestep
     */
    public long getActiveTimestep() {
        return _activeTimestep;
    }

    /**
     * Returns the skill for this object
     *
     * @return The skill
     */
    public float getSkill() {
        return _skill;
    }

    /**
     * Returns the confidence for this object
     *
     * @return The confidence
     */
    public float getConfidence() {
        return _confidence;
    }

    /**
     * Returns the reputation for this object
     *
     * @return The reputation
     */
    public float getReputation() {
        return _reputation;
    }

    /**
     * Returns the boldness for this object
     *
     * @return The boldness
     */
    public float getBoldness() {
        return _boldness;
    }

    /**
     * Finds the nearest neighbors for this individual
     *
     * @param simState
     */
    private void findNearestNeighbors(SimulationState simState) {
        _LOG.trace("Entering findNearestNeighbors( simState )");

        // Get the number of nearest neighbors
        _nearestNeighborCount = simState.getNearestNeighborCount();

        // Build a priority queue to sort things for us
        PriorityQueue<Neighbor> sortedNeighbors = new PriorityQueue<Neighbor>();

        // Iterate through all the individuals
        Iterator<Individual> indIter = simState.getAllIndividuals().iterator();
        while (indIter.hasNext()) {
            // Get the individual
            Individual ind = indIter.next();

            // If it is us, continue on
            if (_id.equals(ind._id)) {
                continue;
            }

            // Build a neighbor out of it and put it in the queue
            Neighbor neighbor = new Neighbor((float) _location.distance(ind._location), ind);
            sortedNeighbors.add(neighbor);
        }

        // Get the "nearest" neighbors
        int count = Math.min(sortedNeighbors.size(), _nearestNeighborCount);
        for (int i = 0; i < count; i++) {
            _nearestNeighbors.add(sortedNeighbors.poll());
        }

        _LOG.trace("Leaving findNearestNeighbors( simState )");
    }

}