WikiPeerCode
/*
* CustomNode.java
*
* Created on January 22, 2005, 2:41 PM
* Modified on June 18, 2006, 13:55 by Jack
* Modified June 22, 2006 00:16 by Andrew
* Modified June 22, 2006 16:40 by Jack
* Modified June 26, 2006 22:14 by Andrew
*
* This class contains the parameters and methods
* for an agent acting on the network
*/
package RepMod;
import uchicago.src.sim.gui.NetworkDrawable;
import uchicago.src.sim.network.DefaultDrawableNode;
import uchicago.src.sim.gui.DrawableNonGridNode;
import uchicago.src.sim.util.Random;
import uchicago.src.sim.gui.OvalNetworkItem;
import java.awt.Color;
import uchicago.src.sim.gui.ColorMap;
import uchicago.src.sim.engine.CustomProbeable;
import java.util.ArrayList;
/**
*
* @author Jack Waddell
*
*/
// DefaultDrawableNode lets us draw it in the GUI
// CustomProbeable lets us define which attributes appear when
// probed in the GUI
public class CustomNode extends DefaultDrawableNode implements CustomProbeable {
//***********************************
// Static Parameters
// tracks next unique id
public static int nextID = 0;
public static GUIModel guiModel = null;
public static RepMod model;
// voteType, whether to use democratic or meritocratic votes
// 0 = democratic
// 1 = meritocratic
// public static int voteType;
// intVoteValue, the intrinsic value of an agent's vote
// vote weight = intVoteValue + (1-intVoteValue)*reputation
// now have continuous scale between democratic and meritocratic,
// and also avoid divide by zero for zero rep agents voting.
// 1 = democratic
// 0 = complete meritocratic
public static double intVoteValue;
// the degree by which the historical opinion is weighted
public static double histWeight;
// weight of current reputation of focus when assigning new opinion
public static double repWeight;
// the (negative of) slope of skill vs variance of noise
public static double noiseSlope;
//********************************8**
// Instance parameters
// Two colormaps are generated for color-coding the nodes in GUI
public static ColorMap centerColorMap;
public static ColorMap edgeColorMap;
public static final int colorMapSize = 16;
public static final int colorMapMax = colorMapSize - 1;
private int id; // uniquely ids node
public Color myColor; // used to draw color in GUI
public String myPajekColor = "Red"; // color to appear in Pajek output
public double reputation; // current wealth or stored reputation
public double skill; // skill parameter
//public int numVotes; // the number of vote rounds
//public double success; // most recent success
///////////////////////////////////////////////////////////////
// constructor
// Inputs: NetworkDrawable drawable, to draw in GUI
// double skill, the skill parameter
public CustomNode (NetworkDrawable drawable, double skill) {
super(drawable);
id = nextID++; // set id and iterate to next
this.skill = skill;
reputation = 0.5; // Generalize. Currently hard-coded
if (guiModel != null)
setNodeEdgeColorFromSkill();
//numVotes = 0;
//success = 0;
}
///////////////////////////////////////////////////////////
// getProbedProperties
// Required to implement CustomProbeable
// Inputs: none
// Outputs: array of strings holding parameter names
public String[] getProbedProperties(){
return new String[] {"id", "reputation", "skill"};
}
//////////////////////////////////////////////////////////
// step
// Input: none
// Output: none
// (Can be) Called by main model to have nodes execute a single step
public void step(){
}
//////////////////////////////////////////////////////////
// setNodeColorFromReputation
// Input: maxReputation, the highest reputation from all agents
// Output: none
// Sets the node color to the colormap leval depending on reputation
public void setNodeColorFromReputation(double maxReputation){
int i = (int) Math.round(colorMapMax*(reputation)/ (maxReputation));
this.setColor(centerColorMap.getColor(i));
}
//////////////////////////////////////////////////////////
// setNodeEdgeColorFromSkill
// Input: none
// Output: none
// Sets the node edge color to the colormap level depending on skill
public void setNodeEdgeColorFromSkill(){
int i = (int) Math.round(colorMapMax*skill);
this.setBorderColor(edgeColorMap.getColor(i));
this.setBorderWidth(3);
}
///////////////////////////////////////////////////////
// getDegree
// Input: none
// Output: int degree
// Calculates the degree of the node (assuming symmetric)
public int getDegree(){
return (this.getOutNodes()).size();
}
///////////////////////////////////////////////////////
// formOpinion
// Input: double success, the focus' real skill
// Output: double vote, the voter's estimate of focus' skill
/*
public double formOpinion(double fSkill, double prevOp, double fRep){
double op = fSkill + model.getNormalDouble(0, getNoiseFromSkill(this.skill));
op = histWeight*prevOp + repWeight*fRep + (1 - histWeight- repWeight)*op;
return op;
}
*/
// it should /really/ be (arguably, of course):
// opinion = (1 - weight) * (focus' real skill + noise)
// + weight * [opinion-weighted average of common nbrs opinions of focus]
public double formOpinion(CustomEdge fEdge){
CustomNode focus = (CustomNode) fEdge.getTo();
double signal = focus.getSkill() +
model.getNormalDouble(0, getNoiseFromSkill(this.skill));
double myOpinion = histWeight*fEdge.getOpinion() + (1-histWeight)*signal;
double localWeightedOpFeedback = 0;
ArrayList nbrEdges = this.getOutEdges();
// form opinion-weighted average of common nbrs opinions of focus
for(int ni = 0; ni < nbrEdges.size(); ni++){
CustomEdge nbrEdge = (CustomEdge) nbrEdges.get(ni);
CustomNode nbr = (CustomNode) nbrEdge.getTo();
ArrayList nbrNbrEdges = nbr.getOutEdges();
boolean foundFocus = false;
for(int nni = 0; nni < nbrNbrEdges.size(); nni++){
CustomEdge nnEdge = (CustomEdge) nbrNbrEdges.get(nni);
if(((CustomNode)nnEdge.getTo()).getID() == focus.getID()) { // if nbr knows focus
// weight feedback by opinion; balance with own opinion
localWeightedOpFeedback +=
nbrEdge.getOpinion()*nnEdge.getOpinion() +
(1-nbrEdge.getOpinion())*myOpinion;
foundFocus = true;
break; // break the inner for loop--we're done with this common nbr
}
}
if(!foundFocus){
// this neighbor didn't know focus
localWeightedOpFeedback += myOpinion;
}
}
localWeightedOpFeedback =
localWeightedOpFeedback/(double)nbrEdges.size();
double op = repWeight*localWeightedOpFeedback + (1-repWeight)*myOpinion;
// here I truncate to [0,1] -- this is open to further discussion
if (op > 1) op = 1; // must...not...write...Python...
if (op < 0) op = 0; // too many languages in one head!
return op;
}
/*
///////////////////////////////////////////////////////
// formOpinion
// Input: double success, the focus' real skill
// Output: double vote, the voter's estimate of focus' skill
public double formOpinion(double fSkill, double prevOp){
double op = fSkill + model.getNormalDouble(0, getNoiseFromSkill(this.skill));
op = histWeight*prevOp + (1-histWeight)*op;
return op;
}
// new formOpinion
public double formOpinion2(double fSkill, double fRep){
// opinion = (1- repweight) * (focus' real skill + noise)
// + repweight * focus' reputation
double op = fSkill+model.getNormalDouble(0,getNoiseFromSkill(this.skill));
op = repWeight*fRep + (1-repWeight)*op;
// here I truncate to [0,1] -- this is open to further discussion
if (op > 1) op = 1; // must...not...write...Python...
if (op < 0) op = 0; // too many languages in one head!
return op;
}
*/
////////////////////////////////////////////////////////
// voteAll
/*
public void voteAll(){
ArrayList edgeList = this.getOutEdges();
double opinion = 0;
int vote = 0;
for (int i = 0; i < edgeList.size(); i++){
CustomEdge edge = (CustomEdge) edgeList.get(i);
CustomNode node = (CustomNode) edge.getTo();
opinion = formOpinion(node.getSkill(), edge.getOpinion(), node.getReputation());
edge.setOpinion(opinion);
if (opinion > 0.5)
vote = 1;
else
vote = 0;
edge.setVote(vote);
}
}
*/
// new voteAll
public void voteAll(){
ArrayList edgeList = this.getOutEdges();
double opinion = 0;
int vote = 0;
for (int i = 0; i < edgeList.size(); i++){
// for each neighbor
CustomEdge edge = (CustomEdge) edgeList.get(i);
CustomNode node = (CustomNode) edge.getTo();
// get opinion (truncated 0 to 1)
opinion = formOpinion(edge);
// set those opinions
edge.setOpinion(opinion);
// votes are opinions
edge.setVote(opinion); // Java lines get semicolons, dipshit.
}
}
////////////////////////////////////////////////////////
// calcReputation
// Input: none
// Ouput: none
public void calcReputation(){
ArrayList edgeList = this.getInEdges();
double repSum = 0;
double normSum = 0;
for (int i = 0; i < edgeList.size(); i++){
CustomEdge edge = (CustomEdge) edgeList.get(i);
CustomNode node = (CustomNode) edge.getFrom();
repSum += edge.getVote() *(intVoteValue + (1-intVoteValue)*node.getReputation());
normSum += (intVoteValue + (1-intVoteValue)*node.getReputation());
/*
if (voteType ==0){
repSum += edge.getVote();
normSum ++;
}
else if (voteType ==1){
repSum += edge.getVote() * node.getReputation();
normSum += node.getReputation();
}*/
}
reputation = repSum/normSum;
}
//***************************************************************
// Getters and Setters
public int getID() {return id;}
public void setMyPajekColor(String i) {myPajekColor = i;}
public String getMyPajekColor() {return myPajekColor;}
public double getReputation() {return reputation;}
public void setReputation(double i) {reputation = i;}
public double getSkill() {return skill;}
public void setSkill(double i) {skill = i;}
//public double getSuccess() {return success;}
//public void setSuccess(double i) {success = i;}
//***************************************************************
// Static Methods
public static void setModel(RepMod m) {model = m;}
//////////////////////////////////////////////////////////
// setUpNodeDrawing
// Input: GUIModel m, a pointer to the GUIModel
// Output: none
public static void setUpNodeDrawing (GUIModel m) {
guiModel = m;
centerColorMap = new ColorMap();
edgeColorMap = new ColorMap();
double minColor = 0.1;
for (int i = 0; i < colorMapSize; i++){
double fracColor = minColor + ( (1.0-minColor)*i/colorMapMax );
centerColorMap.mapColor(i, 0, 0, fracColor);
edgeColorMap.mapColor(i, 0, fracColor, 0);
}
}
///////////////////////////////////////////////////////////
// resetNextID
// Inputs: none
// Outputs: none
// Resets nextID. Called when the model is reset, and a
// new set of nodes is generated
public static void resetNextID(){
nextID = 0;
}
///////////////////////////////////////////////////////////
// getNoiseFromSkill
// Inputs: double skill
// Outputs: double, the noise variance
public static double getNoiseFromSkill(double skill){
return (1-skill)*noiseSlope;
}
//public static int getVoteType() {return voteType;}
//public static void setVoteType(int i) {voteType = i;}
public static double getIntVoteValue() {return intVoteValue;}
public static void setIntVoteValue(double i) {intVoteValue = i;}
public static double getHistWeight() {return histWeight;}
public static void setHistWeight(double i) {histWeight = i;}
public static double getRepWeight() {return repWeight;}
public static void setRepWeight(double w) {repWeight = w;}
public static double getNoiseSlope() {return noiseSlope;}
public static void setNoiseSlope(double i) {noiseSlope = i;}
}