edu.snu.leader.hidden.SpatialIndividual.java Source code

Java tutorial

Introduction

Here is the source code for edu.snu.leader.hidden.SpatialIndividual.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.hidden;

// Imports
import org.apache.commons.lang.Validate;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.log4j.Logger;
import edu.snu.leader.hidden.personality.PersonalityCalculator;
import edu.snu.leader.hidden.personality.PersonalityUpdateType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;

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

    /** Newline string.  NOTE: The old way is temporarily used
      * because a student can't use Java 1.7.  Once that is fixed, the new way will be used. */
    //protected static final String _NEWLINE = System.lineSeparator();
    protected static final String _NEWLINE = System.getProperty("line.separator");

    public static class InitiationEvent {
        public long simIndex;
        public float oldPersonality;
        public boolean successful;
        public int followers;
        public float newPersonality;

        /**
         * Builds this InitiationEvent object
         *
         * @param simIndex
         * @param personality
         */
        public InitiationEvent(long simIndex, float personality) {
            this.simIndex = simIndex;
            this.oldPersonality = personality;
        }
    }

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

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

    /** The individual's location */
    protected Vector2D _location = null;

    /** The individual's personality (ranking on bold/shy).  A value of 1.0
     * denotes maximum boldness, while 0.0 denotes maximum shyness. */
    protected float _personality = 0.0f;

    /** The individual's initial personality */
    protected float _initialPersonality = 0.0f;

    /** The individual's personality after the last initiation attempt */
    protected float _personalityAfterLastInitiation = 0.0f;

    /** The simulation index of this individual's last initiation attempt */
    protected long _lastInitiationAttempt = 0;

    /** The individual's assertiveness */
    protected float _assertiveness = 0.0f;

    /** The individual's preferred direction */
    protected float _preferredDirection = 0.0f;

    /** The individual's abstract conflict */
    protected float _conflict = 0.0f;

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

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

    /** Individuals for whom this individual is a nearest neighbor */
    protected Map<Object, SpatialIndividual> _mimicingNeighbors = new HashMap<Object, SpatialIndividual>();

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

    /** The neighbor that this individual first saw moving (if any) */
    protected Neighbor _firstMover = null;

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

    /** The number of times the individual attempted initiation */
    protected int _initiationAttempts = 0;

    /** The number of times the individual successfully initiated */
    protected int _initiationSuccesses = 0;

    /** The number of followers this individual had when an initiation was
     * successful */
    protected List<Integer> _successfulFollowers = new LinkedList<Integer>();

    /** The number of followers this individual had when an initiation failed */
    protected List<Integer> _failedFollowers = new LinkedList<Integer>();

    /** Statistics for the number of followers in a successful initiation */
    protected DescriptiveStatistics _successfulFollowersStats = new DescriptiveStatistics();

    /** Statistics for the number of followers in a failed initiation */
    protected DescriptiveStatistics _failedFollowersStats = new DescriptiveStatistics();

    /** A record of all the individual's initiations */
    protected List<InitiationEvent> _initiationHistory = new LinkedList<InitiationEvent>();

    /** The current initiation event */
    protected InitiationEvent _currentInitiationEvent = null;

    /** Flag indicating that the initiation history should be described */
    protected boolean _describeInitiationHistory = false;

    /** All the failed initiators in the current simulation */
    protected List<Neighbor> _failedLeaders = new LinkedList<Neighbor>();

    /**
     * Builds this SpatialIndividual object
     *
     * @param id
     * @param location
     * @param personality
     * @param assertiveness
     * @param preferredDirection
     * @param conflict
     * @param describeInitiationHistory
     */
    public SpatialIndividual(Object id, Vector2D location, float personality, float assertiveness,
            float preferredDirection, float conflict, boolean describeInitiationHistory) {
        _id = id;
        _location = location;
        _personality = personality;
        _initialPersonality = personality;
        _personalityAfterLastInitiation = personality;
        _assertiveness = assertiveness;
        _preferredDirection = preferredDirection;
        _conflict = conflict;
        _describeInitiationHistory = describeInitiationHistory;
    }

    /**
     * Finds the nearest neighbors for this individual
     *
     * @param simState
     */
    public 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<SpatialIndividual> indIter = simState.getAllIndividuals().iterator();
        while (indIter.hasNext()) {
            // Get the individual
            SpatialIndividual 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++) {
            Neighbor neighbor = sortedNeighbors.poll();
            _nearestNeighbors.add(neighbor);
            neighbor.getIndividual().signalNearestNeighborStatus(this);
            //            _LOG.debug( "Nearest neighbor: id=["
            //                    + getID()
            //                    + "] neighbor=["
            //                    + neighbor.getIndividual().getID()
            //                    + "]" );
        }

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

    /**
     * Resets all the nearest neighbor information for this individual
     */
    public void resetNearestNeighbors() {
        _nearestNeighbors.clear();
        _mimicingNeighbors.clear();
    }

    /**
     * TODO Method description
     *
     * @param ind
     */
    public void signalNearestNeighborStatus(SpatialIndividual ind) {
        _mimicingNeighbors.put(ind.getID(), ind);
        _LOG.debug("Mimic: watched=[" + getID() + "] watcher=[" + ind.getID() + "]");
    }

    /**
     * Returns true if this individual is given individual is a mimicing
     * neighbor of this individual
     *
     * @param ind The individual to test
     * @return
     */
    public boolean isMimicingNeighbor(SpatialIndividual ind) {
        return _mimicingNeighbors.containsKey(ind.getID());
    }

    /**
     * Returns the number of mimicing neighbors for this individual
     *
     * @return
     */
    public int getMimickingNeighborCount() {
        return _mimicingNeighbors.size();
    }

    /**
     * Signals this individual that a neighbor has moved
     *
     * @param ind
     */
    public void observeFirstMover(SpatialIndividual ind) {
        if (null == _firstMover) {
            // Get the distance to the individual
            float distance = (float) _location.distance(ind._location);

            _firstMover = new Neighbor(distance, ind);
            _LOG.debug("Ind [" + getID() + "] observed [" + ind.getID() + "]");
        }
    }

    public void resetFirstMover() {
        _firstMover = null;
    }

    /**
     * Signals this individual to follow the specified individual
     *
     * @param ind
     */
    public void follow(SpatialIndividual ind) {
        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));
    }

    /**
     * Signals this individual to follow the specified individual
     *
     * @param neighbor
     */
    public void follow(Neighbor neighbor) {
        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);
    }

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

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

        // Signal that we initiated a movement
        signalInitiationAttempt(simState);
    }

    /**
     * Signals this individual that the specified individual is following it
     *
     * @param ind
     */
    public void addFollower(SpatialIndividual 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));
    }

    /**
     * Cancel this individual's movement
     */
    public void cancel() {
        _LOG.debug("Ind=[" + getID() + "] is cancelling");

        // If we have a leader, stop following
        if (null != _leader) {
            _failedLeaders.add(_leader);
        }
        _leader = null;

        // Reset our group ID
        _groupID = null;

        // Tell all our followers to cancel
        Iterator<Neighbor> followerIter = _followers.iterator();
        while (followerIter.hasNext()) {
            followerIter.next().getIndividual().cancel();
        }

        // Clear all our followers
        _followers.clear();

        // Reset our first mover
        _firstMover = null;
    }

    /**
     * Resets this individual's simulation state
     */
    public void reset() {
        // Reset all the values changed during initiation or following
        _leader = null;
        _groupID = null;
        _followers.clear();
        _firstMover = null;
        _failedLeaders.clear();
    }

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

    /**
     * Returns a list of all the followers (including those following this
     * individual's followers)
     *
     * @return All the followers
     */
    public List<Neighbor> getAllFollowers() {
        List<Neighbor> allFollowers = new LinkedList<Neighbor>(_followers);
        Iterator<Neighbor> followerIter = _followers.iterator();
        while (followerIter.hasNext()) {
            allFollowers.addAll(followerIter.next().getIndividual().getAllFollowers());
        }

        return allFollowers;
    }

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

    public int getNearestNeighborsFollowingCount() {
        int count = 0;

        Iterator<Neighbor> nearestIter = _nearestNeighbors.iterator();
        while (nearestIter.hasNext()) {
            // Is it following us?
            Neighbor neighbor = nearestIter.next();

            // Get their leader
            Neighbor leader = neighbor.getIndividual().getLeader();
            boolean done = false;
            while ((null != leader) && !done) {
                // Is it us?
                if (leader.getIndividual().getID().equals(getID())) {
                    // Yup
                    ++count;
                    done = true;
                }
                leader = leader.getIndividual().getLeader();
            }

        }

        return count;
    }

    /**
     * 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 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 nearestNeighbors for this object
     *
     * @return The nearestNeighbors
     */
    public List<Neighbor> getNearestNeighbors() {
        return _nearestNeighbors;
    }

    /**
     * Returns the mimicking neighbors for this individual
     *
     * @return The mimicking neighbors
     */
    public List<SpatialIndividual> getMimickingNeighbors() {
        return new LinkedList<SpatialIndividual>(_mimicingNeighbors.values());
    }

    /**
     * TODO Method description
     *
     * @param ind
     * @return
     */
    public boolean isNearestNeighbor(SpatialIndividual ind) {
        boolean found = false;

        // Iterate through the nearest neighbors and check the ID
        Iterator<Neighbor> nearestIter = _nearestNeighbors.iterator();
        while (nearestIter.hasNext()) {
            if (nearestIter.next().getIndividual().getID().equals(ind.getID())) {
                found = true;
                break;
            }
        }

        return found;
    }

    /**
     * Returns the number of nearest neighbors for this individual
     *
     * @return The number of nearest neighbors for this individual
     */
    public int getNearestNeighborCount() {
        return _nearestNeighbors.size();
    }

    /**
     * Returns the number of nearest neighbors that have departed
     *
     * @param simState The current simulation state
     * @return The number of nearest neighbors that have departed
     */
    public int getNearestNeighborDepartedCount(SimulationState simState) {
        int count = 0;
        Iterator<Neighbor> iter = _nearestNeighbors.iterator();
        while (iter.hasNext()) {
            // Has this individual departed?
            if (simState.hasDeparted(iter.next().getIndividual().getID())) {
                // Yup
                ++count;
            }
        }

        return count;
    }

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

    /**
     *  Notes that the individual attempted an initiation
     *
     * @param simState The simulation's state
     */
    public void signalInitiationAttempt(SimulationState simState) {
        _initiationAttempts++;

        if (_describeInitiationHistory) {
            _currentInitiationEvent = new InitiationEvent(simState.getSimIndex(), _personality);
            _initiationHistory.add(_currentInitiationEvent);
        }
    }

    /**
     * Notes that the individual was successful in initiating movement
     *
     * @param simState The simulation's state
     */
    public void signalInitiationSuccess(SimulationState simState) {
        _initiationSuccesses++;

        // Log our total number of followers
        _successfulFollowers.add(getTotalFollowerCount());
        _successfulFollowersStats.addValue(getTotalFollowerCount());

        // Update the personality
        PersonalityCalculator personalityCalc = simState.getPersonalityCalc();
        if (null != personalityCalc) {
            _personality = personalityCalc.calculatePersonality(this, PersonalityUpdateType.TRUE_WINNER,
                    getTotalFollowerCount());

            // Allow for bystander effects
            for (Neighbor neighbor : _nearestNeighbors) {
                SpatialIndividual ind = neighbor.getIndividual();
                ind._personality = personalityCalc.calculatePersonality(ind, PersonalityUpdateType.BYSTANDER_WINNER,
                        getTotalFollowerCount());
            }
        }

        // Save the individual's personality and the simulation index
        _personalityAfterLastInitiation = _personality;
        _lastInitiationAttempt = simState.getSimIndex();

        // Are we keeping track of these things?
        if (_describeInitiationHistory) {
            _currentInitiationEvent.successful = true;
            _currentInitiationEvent.followers = getTotalFollowerCount();
            _currentInitiationEvent.newPersonality = _personality;
        }
    }

    /**
     * Notes that the individual failed in initiating movement
     *
     * @param simState The simulation's state
     */
    public void signalInitiationFailure(SimulationState simState) {

        // Log our total number of followers
        //        _failedFollowers.add( getTotalFollowerCount() );
        //        _failedFollowersStats.addValue( getTotalFollowerCount() );

        // Update the personality
        PersonalityCalculator personalityCalc = simState.getPersonalityCalc();
        if (null != personalityCalc) {
            _personality = personalityCalc.calculatePersonality(this, PersonalityUpdateType.TRUE_LOSER,
                    getTotalFollowerCount());

            // Allow for bystander effects
            for (Neighbor neighbor : _nearestNeighbors) {
                SpatialIndividual ind = neighbor.getIndividual();
                ind._personality = personalityCalc.calculatePersonality(ind, PersonalityUpdateType.BYSTANDER_LOSER,
                        getTotalFollowerCount());
            }
        }

        // Save the individual's personality and the simulation index
        _personalityAfterLastInitiation = _personality;
        _lastInitiationAttempt = simState.getSimIndex();

        // Are we keeping track of these things?
        if (_describeInitiationHistory) {
            _currentInitiationEvent.successful = false;
            _currentInitiationEvent.followers = getTotalFollowerCount();
            _currentInitiationEvent.newPersonality = _personality;
        }
    }

    /**
     * Describes this individual
     *
     * @return A string describing this individual
     */
    public String describe() {
        StringBuilder builder = new StringBuilder();

        String prefix = "individual." + getID() + ".";

        // Add the location
        builder.append(prefix);
        builder.append("location = ");
        builder.append(String.format("%06.4f", _location.getX()) + " " + String.format("%06.4f", _location.getY()));
        builder.append(_NEWLINE);

        // Add the personality
        builder.append(prefix);
        builder.append("personality = ");
        builder.append(_personality);
        builder.append(_NEWLINE);

        // Add the assertiveness
        builder.append(prefix);
        builder.append("assertiveness = ");
        builder.append(_assertiveness);
        builder.append(_NEWLINE);

        // Add the preferred direction
        builder.append(prefix);
        builder.append("preferred-direction = ");
        builder.append(_preferredDirection);
        builder.append(_NEWLINE);

        // Add the conflict
        builder.append(prefix);
        builder.append("conflict = ");
        builder.append(_conflict);
        builder.append(_NEWLINE);

        //        // Add the information for the number of successful followers
        //        double successfulFollowersMean = 0;
        //        double successfulFollowersStdDev = 0;
        //        if( 0 < getInitiationSuccesses() )
        //        {
        //            successfulFollowersMean = getSuccessfulFollowersMean();
        //            successfulFollowersStdDev = getSuccessfulFollowersStdDev();
        //        }
        //        builder.append( prefix );
        //        builder.append( "successful-followers-mean = " );
        //        builder.append( successfulFollowersMean );
        //        builder.append( _NEWLINE );
        //
        //        builder.append( prefix );
        //        builder.append( "successful-followers-std-dev = " );
        //        builder.append( successfulFollowersStdDev );
        //        builder.append( _NEWLINE );
        //
        //        // Add the information for the number of failed followers
        //        builder.append( prefix );
        //        builder.append( "failed-followers-mean = " );
        //        builder.append( getFailedFollowersMean() );
        //        builder.append( _NEWLINE );
        //
        //        builder.append( prefix );
        //        builder.append( "failed-followers-std-dev = " );
        //        builder.append( getFailedFollowersStdDev() );
        //        builder.append( _NEWLINE );

        // Add a the nearest neighbors information
        builder.append(prefix);
        builder.append("nearest-neighbors = ");
        Iterator<Neighbor> neighborIter = getNearestNeighbors().iterator();
        while (neighborIter.hasNext()) {
            Neighbor currentNeighbor = neighborIter.next();
            builder.append(currentNeighbor.getIndividual().getID());
            builder.append(" ");
        }
        builder.append(_NEWLINE);

        // Add the number of individuals with this individual as a neighbor
        builder.append(prefix);
        builder.append("mimicing-neighbor-count = ");
        builder.append(getMimickingNeighborCount());
        builder.append(_NEWLINE);

        // Add placeholders for the social network analysis data
        builder.append(prefix);
        builder.append("eigenvector-centrality = %%%");
        builder.append(getID());
        builder.append("-EIGENVECTOR-CENTRALITY%%%");
        builder.append(_NEWLINE);

        builder.append(prefix);
        builder.append("betweenness = %%%");
        builder.append(getID());
        builder.append("-BETWEENNESS%%%");
        builder.append(_NEWLINE);

        builder.append(prefix);
        builder.append("sna-todo = %%%");
        builder.append(getID());
        builder.append("-sna-todo%%%");
        builder.append(_NEWLINE);

        if (_describeInitiationHistory) {
            // Add the initiation history
            builder.append(prefix);
            builder.append("initiation-history =");
            Iterator<InitiationEvent> initiationIter = _initiationHistory.iterator();
            InitiationEvent currentEvent = null;
            while (initiationIter.hasNext()) {
                currentEvent = initiationIter.next();

                builder.append(" [");
                builder.append(currentEvent.simIndex);
                builder.append("  ");
                builder.append(currentEvent.oldPersonality);
                builder.append("  ");
                builder.append(currentEvent.successful);
                builder.append("  ");
                builder.append(currentEvent.newPersonality);
                builder.append("  ");
                builder.append(currentEvent.followers);
                builder.append("]");
            }
            builder.append(_NEWLINE);
        }

        return builder.toString();
    }

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

    /**
     * Sets the location for this individual
     *
     * @param location The new location
     */
    public void setLocation(Vector2D location) {
        _location = location;
    }

    /**
     * Returns the mean number of followers in failed initiations
     *
     * @return The mean
     */
    public double getFailedFollowersMean() {
        return _failedFollowersStats.getMean();
    }

    /**
     * Returns the mean number of followers in failed initiations
     *
     * @return The mean
     */
    public double getFailedFollowersStdDev() {
        return _failedFollowersStats.getStandardDeviation();
    }

    /**
     * Returns the mean number of followers in successful initiations
     *
     * @return The mean
     */
    public double getSuccessfulFollowersMean() {
        return _successfulFollowersStats.getMean();
    }

    /**
     * Returns the mean number of followers in successful initiations
     *
     * @return The mean
     */
    public double getSuccessfulFollowersStdDev() {
        return _successfulFollowersStats.getStandardDeviation();
    }

    /**
     * Returns the initiationAttempts for this object
     *
     * @return The initiationAttempts
     */
    public int getInitiationAttempts() {
        return _initiationAttempts;
    }

    /**
     * Returns the initiationSuccesses for this object
     *
     * @return The initiationSuccesses
     */
    public int getInitiationSuccesses() {
        return _initiationSuccesses;
    }

    /**
     * Sets the personality for this object.
     *
     * @param personality The specified personality
     */
    public void setPersonality(float personality) {
        _personality = personality;
    }

    /**
     * Returns the personality for this object
     *
     * @return The personality
     */
    public float getPersonality() {
        return _personality;
    }

    /**
     * Returns the initial personality for this individual
     *
     * @return The initial personality
     */
    public float getInitialPersonality() {
        return _initialPersonality;
    }

    /**
     * Returns the personality after the individual's last initiation attempt
     *
     * @return The personality after the individual's last initiation attempt
     */
    public float getPersonalityAfterLastInitiation() {
        return _personalityAfterLastInitiation;
    }

    /**
     * Returns the simulation index of the individual's last initiation attempt
     *
     * @return The simulation index of the individual's last initiation attempt
     */
    public long getLastInitiationAttempt() {
        return _lastInitiationAttempt;
    }

    /**
     * Returns the assertiveness for this object
     *
     * @return The assertiveness
     */
    public float getAssertiveness() {
        return _assertiveness;
    }

    /**
     * Returns the preferredDirection for this object
     *
     * @return The preferredDirection
     */
    public float getPreferredDirection() {
        return _preferredDirection;
    }

    /**
     * Sets the preferredDirection for this object
     *
     * @param preferredDirection The preferred direction of movement
     */
    public void setPreferredDirection(float preferredDirection) {
        _preferredDirection = preferredDirection;
    }

    /**
     * Returns the conflict for this object
     *
     * @return The conflict
     */
    public float getConflict() {
        return _conflict;
    }

    /**
     * Returns the firstMover for this object
     *
     * @return The firstMover
     */
    public Neighbor getFirstMover() {
        return _firstMover;
    }

}