edu.snu.leader.discrete.simulator.GautraisConflictDecisionCalculator.java Source code

Java tutorial

Introduction

Here is the source code for edu.snu.leader.discrete.simulator.GautraisConflictDecisionCalculator.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.discrete.simulator;

import java.util.List;

import org.apache.commons.lang.Validate;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;

import edu.snu.leader.discrete.behavior.Decision;
import edu.snu.leader.discrete.utils.Reporter;

/**
 * GautraisConflictDecisionCalculator Gautrais model with conflict for decision
 * calculation
 * 
 * @author Tim Solum
 * @version $Revision$ ($Author$)
 */
public class GautraisConflictDecisionCalculator implements DecisionProbabilityCalculator {
    /** The simulation state */
    private SimulationState _simState = null;

    private double _tauO = 0;

    private double _alphaC = 0;

    private double _gammaC = 0;

    private double _epsilonC = 0;

    private double _alphaF = 0;

    private double _betaF = 0;

    /** The conflict value for agents that have zero velocity */
    private double _defaultConflictValue = .1;

    private int _destinationSizeRadius = 0;

    private double[] _followProbabilities = null;

    private double[] _cancelProbabilities = null;

    @Override
    public void initialize(SimulationState simState) {
        _simState = simState;

        // set values from properties
        String tauO = _simState.getProperties().getProperty("tau-o");
        Validate.notEmpty(tauO, "tau-o may not be empty");
        _tauO = Double.parseDouble(tauO);

        String alphaF = _simState.getProperties().getProperty("alpha-f");
        Validate.notEmpty(alphaF, "alpha-f may not be empty");
        _alphaF = Double.parseDouble(alphaF);

        String gammaC = _simState.getProperties().getProperty("gamma-c");
        Validate.notEmpty(gammaC, "gamma-c may not be empty");
        _gammaC = Double.parseDouble(gammaC);

        String epsilonC = _simState.getProperties().getProperty("epsilon-c");
        Validate.notEmpty(epsilonC, "epsilon-c may not be empty");
        _epsilonC = Double.parseDouble(epsilonC);

        String alphaC = _simState.getProperties().getProperty("alpha-c");
        Validate.notEmpty(alphaC, "alpha-c may not be empty");
        _alphaC = Double.parseDouble(alphaC);

        String betaF = _simState.getProperties().getProperty("beta-f");
        Validate.notEmpty(betaF, "beta-f may not be empty");
        _betaF = Double.parseDouble(betaF);

        String defConflictValue = _simState.getProperties().getProperty("default-conflict-value");
        Validate.notEmpty(defConflictValue, "default-conflict-value may not be empty");
        _defaultConflictValue = Double.parseDouble(defConflictValue);

        _destinationSizeRadius = _simState.getDestinationRadius();

        // add gautrais info to root directory path
        _simState.setRootDirectory(Reporter.ROOT_DIRECTORY + "GautraisValues");
    }

    /**
     * Returns an array of all the possible follow probabilities. Will be null
     * if pre-generation was not specified in properties file.
     * 
     * @return
     */
    public double[] getPreCalculatedFollowProbabilities() {
        return _followProbabilities;
    }

    /**
     * Returns an array of all the possible cancel probabilities. Will be null
     * if pre-generation was not specified in properties file.
     * 
     * @return
     */
    public double[] getPreCalculatedCancelProbabilities() {
        return _cancelProbabilities;
    }

    @Override
    public void calcInitiateProb(Decision decision) {
        double tauI = _tauO;
        double conflict = _defaultConflictValue;
        // calculate conflict
        conflict = calculateConflict(decision);
        // calculate k value
        double k = kValue(conflict);
        // calculate tauI
        tauI /= k;
        // set probability
        decision.setProbability(1 / tauI);
    }

    @Override
    public void calcFollowProb(Decision decision) {
        double conflict = calculateConflict(decision);
        double tauR = 0;
        // total number neighbors
        int N = 0;
        // followers
        int r = 0;

        Agent agent = decision.getAgent();

        // calculate r followers and N total
        List<Agent> neighbors = agent.getNearestNeighbors();
        N = neighbors.size();
        for (int i = 0; i < neighbors.size(); i++) {
            // N++;
            if (agent.getObservedGroupHistory().get(neighbors.get(i).getId()).groupId == (decision.getLeader()
                    .getGroup().getId())) {
                r++;
            }
        }

        // calculate tauR
        tauR = _alphaF + ((_betaF * (N - r)) / r);
        // 1-conflict for follow
        tauR *= 1 / kValue(1 - conflict);
        decision.setProbability(1 / tauR);
    }

    @Override
    public void calcCancelProb(Decision decision) {
        double Cr = 0;
        // followers
        int r = 1;

        Agent agent = decision.getAgent();

        // calculate r followers
        List<Agent> neighbors = agent.getNearestNeighbors();
        for (int i = 0; i < neighbors.size(); i++) {
            if (agent.getObservedGroupHistory().get(neighbors.get(i).getId()).groupId
                    .equals(agent.getGroup().getId())) {
                r++;
            }
        }

        // calculate Cr
        Cr = _alphaC / (1 + (Math.pow(r / _gammaC, _epsilonC)));

        decision.setProbability(Cr);

    }

    /**
     * Calculate the k value for conflict
     * 
     * @param decision The decision that the k value is calculated for
     * @return The k value
     */
    private double kValue(double conflict) {
        // k = 2 * conflict
        double k = 2 * conflict;
        return k;
    }

    private double calculateConflict(Decision decision) {
        Agent agent = decision.getAgent();
        Agent leader = decision.getLeader();
        double Ci = 0.1;

        // calculate the leader's next location
        Vector2D leaderNextLocation = leader.getCurrentDestination().add(leader.getCurrentVelocity());
        // calculate the sides of a triangle
        // calculate side from agent's preferred destination to leader's next
        double A = Vector2D.distance(agent.getPreferredDestination().getVector(), leaderNextLocation);
        // calculate side from agent's preferred destination to leader's current
        double B = Vector2D.distance(agent.getPreferredDestination().getVector(), leader.getCurrentLocation());
        // calculate side from leader's current to leader's next
        double C = Vector2D.distance(leader.getCurrentLocation(), leaderNextLocation);

        // check if the leader is in the agent's preferred destination
        if (leader.getCurrentLocation()
                .distance1(agent.getPreferredDestination().getVector()) < _destinationSizeRadius) {
            Ci = 0.1;
        }
        // check if the leader is not moving
        else if (leader.getCurrentVelocity().equals(Vector2D.ZERO)) {
            Ci = .9;
        } else {
            double angle = 0.0;

            if (A <= 0 || B <= 0 || C <= 0) {
                // if a side is 0 then there is no triangle it is a line
                // if segment B is longer than C then the degree should be 180
                if (B > C) {
                    angle = 180;
                }
                // if the segment B is shorter than C then the degree should be
                // 0
                else {
                    angle = 0.0;
                }
            }
            // have three sides so use law of cosines
            else {
                // calculate angle between leader's current position and agent's
                // preferred destination by law of cosines
                double lawOfCosines = (Math.pow(A, 2) - Math.pow(B, 2) - Math.pow(C, 2)) / (-2 * B * C);
                // because of rounding error there can be lawOfCosines values
                // that are oh so slightly larger or smaller than 1 or -1
                // this augments them to their correct values
                if (lawOfCosines < -1) {
                    lawOfCosines = -1;
                } else if (lawOfCosines > 1) {
                    lawOfCosines = 1;
                }
                angle = Math.acos(lawOfCosines);
            }

            // if angle is greater than 180 than it becomes 360 - angle
            if (angle > 180) {
                angle = 360 - angle;
            }
            // make it into degrees
            angle = angle * 180 / Math.PI;
            // calculate conflict
            Ci = angle / 180;
        }

        // prevent K value from becoming 0
        if (Ci < .1) {
            Ci = .1;
        } else if (Ci > .9) {
            Ci = .9;
        }

        // set the conflict for the decision
        decision.setConflict(Ci);
        // return the conflict value for whatever needs to use it
        return Ci;
    }
}