Commits

littledot5566 committed cea538a

Added dynamic sim.
Added charting libs.

Comments (0)

Files changed (8)

src/sim/DynamicTask.java

 			for (Agent a : agentList) {
 				if (a.getTasksCompleted() == tasksCompletedForLevelUp) {
 					double agentCorrectnessThreshould = a.getCorrectnessRate();
-//					corretnessForLevelUp = Math.random();
+					// corretnessForLevelUp = Math.random();
 					if (a.getRankStatus() < rankLevelsNum - 1
 							&& agentCorrectnessThreshould >= corretnessForLevelUp) {
 						a.setRankStatus(a.getRankStatus() + 1);
 	 */
 	private Vector<Agent> updateAgentStatus(Vector<Agent> agentList,
 			boolean isNewTask) {
-		// TODO Auto-generated method stub
+
 		if (pay.size() != 0) {
 			if (isNewTask) {
 				for (Agent a : agentList) {

src/sim/Main.java

 
 import java.util.Vector;
 
+import org.jfree.data.category.DefaultCategoryDataset;
+
+import sim.shengdean.DynamicSimulation;
 import sim.shengdean.StaticSimulation;
 
 /*
 
 public class Main {
 
+	public static int tasks = 10000;
+	public static int agents = 50;
+	public static double avgPay = 50;
+	public static double minPay = 20;
+	public static double maxPay = 60;
+	public static double agntVariance = 0.2;
+
 	public static void main(String[] args) {
 		Vector<Integer> dynamicPaid = new Vector<Integer>();
 		int levels = 5;
 			dynamicPaid.add(40 + factor);
 		}
 
-		Simulator s = new Simulator(10000, 50, 50); // 10000 tasks, 50 agents, $50 flat pay
-		s.runStaticSimulation();
-		s.runDynamicSimulation(dynamicPaid, levels, tasksCompletedForLevelUp);
+		// Simulator s = new Simulator(10000, 50, 50); // 10000 tasks, 50 agents, $50 flat pay
+		// s.runStaticSimulation();
+		// s.runDynamicSimulation(dynamicPaid, levels, tasksCompletedForLevelUp);
 
 		// ShengDean static sim
-		StaticSimulation ss = new StaticSimulation(10000, 50, 50);
-		ss.run();
-	}
 
+		for (int i = 0; i < 1; i++) {
+			System.err.println("STATIC" + i);
+			StaticSimulation ss = new StaticSimulation(
+					tasks,
+					agents, agntVariance,
+					avgPay);
+			ss.run();
+			ss.chart();
+
+			System.err.println("DYNAMIC" + i);
+			DynamicSimulation ds = new DynamicSimulation(
+					tasks,
+					agents, agntVariance,
+					minPay, maxPay, avgPay);
+			ds.run1();
+
+			boolean more;
+			do {
+				more = ds.run2();
+			} while (more);
+
+			ds.report();
+			ds.chart();
+		}
+	}
 }

src/sim/Simulator.java

 		this.dynamicTaskPay = dynamicPaid;
 		this.rankLevelsNum = levels;
 		this.tasksCompletedForLevelUp = tasksCompletedForLevelUp;
+
 		DynamicTask dt = new DynamicTask(dynamicTaskPay, taskNum, rankLevelsNum);
 		this.agentList = genAgents(numOfAgents);
 		int remainTask = dt.getTotalTask();

src/sim/shengdean/Agent.java

 package sim.shengdean;
 
+import java.util.ArrayList;
+
 import cern.jet.random.Normal;
 import cern.jet.random.engine.RandomEngine;
 
-/*
- * Author: Tzu-Yang (Ben). Yu
- *
- */
-
-public class Agent {
+public class Agent implements Comparable<Agent> {
 	// answers should form a normal distribution
 	public int _id;
 	public double _mean;
 	public double _variance;
 	public Normal _dist;
 
+	public ArrayList<Task> _completed = new ArrayList<Task>();
+
+	public double _score;
+	public ArrayList<Double> _pastScore = new ArrayList<Double>();
+
 	public Agent(int id, double mean, double var) {
 		_id = id;
 		_mean = mean;
 		_dist = new Normal(_mean, _variance, RandomEngine.makeDefault());
 	}
 
+	public double doTask(Task task) {
+		task._worker = this;
+		_completed.add(task);
+
+		// generate results from normal distribution
+		double res = calculateAccuracy();
+		return task._accuracy = res;
+	}
+
+	public double calculateAccuracy() {
+		double acc = _dist.nextDouble();
+		// System.out.println("acc=" + acc);
+		return Math.max(0, Math.min(1, acc));
+	}
+
+	/**
+	 * XXX: Calculate score based on previous work history. Used for ranking.
+	 */
+	public double calculateScore() {
+		int n = _completed.size();
+		double score = 0;
+		double mul = 1.0;
+
+		for (int i = n - 1; i >= n - 10 && i >= 0; i--) {
+			Task task = _completed.get(i);
+			score += task._accuracy * mul;
+			mul -= 0.1;
+		}
+
+		_pastScore.add(score);
+
+		return _score = score;
+	}
+
+	/**
+	 * XXX: Given a pay value, calculate the agent's attraction to the job.
+	 */
+	public double calculateAttraction(double pay, double basePay) {
+		// naive linear function
+		// return 0.5 * (pay / basePay);
+		// y = x^2 / 2 * avg^2
+		return pay * pay / (2 * basePay * basePay);
+	}
+
+	@Override
+	public int compareTo(Agent o) {
+		double com = _score - o._score;
+
+		if (com < 0)
+			return -1;
+		else if (com == 0)
+			return 0;
+		else
+			return 1;
+	}
 }

src/sim/shengdean/Charter.java

+package sim.shengdean;
+
+import java.util.ArrayList;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.CategoryAxis;
+import org.jfree.chart.axis.CategoryLabelPositions;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.DatasetRenderingOrder;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.renderer.category.LineAndShapeRenderer;
+import org.jfree.data.category.DefaultCategoryDataset;
+
+public class Charter {
+
+	public static void chartAccuracy(ArrayList<Agent> agents) {
+
+		DefaultCategoryDataset accData = new DefaultCategoryDataset();
+
+		for (int i = 0; i < agents.size(); i++) {
+			Agent agent = agents.get(i);
+			double totalAcc = 0;
+
+			// calculate avg accuracy for each agent
+			for (int j = 0; j < agent._completed.size(); j++) {
+				Task task = agent._completed.get(j);
+				totalAcc += task._accuracy;
+			}
+
+			// compare avg accuracy and set accuracy
+			accData.addValue(totalAcc / agent._completed.size(), "Avg Accuracy", ""
+					+ i);
+			accData.addValue(agent._mean, "Expected Avg Accuracy", "" + i);
+		}
+
+		JFreeChart accChart = ChartFactory.createBarChart(
+				"AccuracyChart",         // chart title
+				"Agent ID",               // domain axis label
+				"Accuracy",                  // range axis label
+				accData,                  		// data
+				PlotOrientation.VERTICAL, // orientation
+				true,                     // include legend
+				true,                     // tooltips?
+				false                     // URLs?
+				);
+
+		CategoryPlot accPlot = accChart.getCategoryPlot();
+		final CategoryAxis accDomainAxis = accPlot.getDomainAxis();
+		accDomainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
+
+		ChartFrame accFrame = new ChartFrame("", accChart);
+		accFrame.pack();
+		accFrame.setVisible(true);
+	}
+
+	public static void chartPay(ArrayList<Agent> agents) {
+		DefaultCategoryDataset payData = new DefaultCategoryDataset();
+		DefaultCategoryDataset taskData = new DefaultCategoryDataset();
+
+		for (int i = 0; i < agents.size(); i++) {
+			Agent agent = agents.get(i);
+			double totalPay = 0;
+
+			for (int j = 0; j < agent._completed.size(); j++) {
+				Task task = agent._completed.get(j);
+				totalPay += task._pay;
+			}
+
+			taskData.addValue(agent._completed.size(), "No of Tasks", "" + i);
+			payData.addValue(totalPay, "Total Pay", "" + i);
+		}
+
+		JFreeChart payChart = ChartFactory.createBarChart(
+				"WorkChart",         			// chart title
+				"Agent ID",               // domain axis label
+				"$",                  // range axis label
+				payData,                  		// data
+				PlotOrientation.VERTICAL, // orientation
+				true,                     // include legend
+				true,                     // tooltips?
+				false                     // URLs?
+				);
+
+		CategoryPlot plot = payChart.getCategoryPlot();
+		plot.setDataset(1, taskData);
+		plot.mapDatasetToRangeAxis(1, 1);
+
+		final CategoryAxis domainAxis = plot.getDomainAxis();
+		domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
+		final ValueAxis axis2 = new NumberAxis("No of Tasks Completed");
+		plot.setRangeAxis(1, axis2);
+
+		final LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();
+		renderer2.setToolTipGenerator(new StandardCategoryToolTipGenerator());
+		plot.setRenderer(1, renderer2);
+		plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
+
+		ChartFrame payFrame = new ChartFrame("", payChart);
+		payFrame.pack();
+		payFrame.setVisible(true);
+	}
+
+	public static void chartScore(ArrayList<Agent> agents) {
+		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
+
+		for (int i = 0; i < agents.size(); i++) {
+			// if (i == 0 || i == 25 || i == 49) {
+			ArrayList<Double> scores = agents.get(i)._pastScore;
+
+			for (int j = 0; j < scores.size(); j++) {
+				dataset.addValue(scores.get(j), "" + i, "" + j);
+			}
+			// }
+		}
+
+		JFreeChart chart = ChartFactory.createLineChart(
+				"Score Chart",       // chart title
+				"Task no.",                    // domain axis label
+				"Score",                   // range axis label
+				dataset,                   // data
+				PlotOrientation.VERTICAL,  // orientation
+				true,                      // include legend
+				true,                      // tooltips
+				false                      // urls
+				);
+
+		ChartFrame frame = new ChartFrame("", chart);
+		frame.pack();
+		frame.setVisible(true);
+	}
+}

src/sim/shengdean/DynamicSimulation.java

+package sim.shengdean;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.CategoryAxis;
+import org.jfree.chart.axis.CategoryLabelPositions;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.DatasetRenderingOrder;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.renderer.category.LineAndShapeRenderer;
+import org.jfree.data.category.DefaultCategoryDataset;
+
+public class DynamicSimulation {
+
+	public int _numTasks;
+	public int _numAgents;
+	public double _minPay;
+	public double _maxPay;
+	public double _avgPay;
+
+	ArrayList<Agent> _agents = new ArrayList<Agent>();
+
+	ArrayList<Task> _tasks = new ArrayList<Task>();
+	public int _taskIndex; // next incomplete task
+
+	public int _payStrategy;
+	ArrayList<Integer> _brackets = new ArrayList<Integer>();
+
+	public DynamicSimulation(int tasks, int agents, double agntVar,
+			double minPay, double maxPay, double avgPay) {
+
+		if (minPay > maxPay)
+			throw new IllegalArgumentException("minPay > maxPay");
+
+		_numTasks = tasks;
+		_numAgents = agents;
+		_minPay = minPay;
+		_maxPay = maxPay;
+		_avgPay = avgPay;
+
+		// generate agents
+		for (int i = 0; i < agents; i++) {
+			_agents.add(new Agent(i, Math.random(), agntVar));
+		}
+
+		// generate tasks
+		for (int i = 0; i < tasks; i++) {
+			_tasks.add(new Task(i));
+		}
+	}
+
+	public void run1() {
+		// all agents do 1 task
+		for (int i = 0; i < _numAgents; i++) {
+			Agent agent = _agents.get(i);
+			Task task = _tasks.get(i);
+
+			agent.doTask(task);
+			agent.calculateScore();
+		}
+
+		// sort agents based on ranking
+		Collections.sort(_agents, Collections.reverseOrder());
+
+		_taskIndex = 50;
+	}
+
+	public boolean run2() {
+		Random rand = new Random();
+
+		// subsequent rounds
+		for (int i = 0; i < _numAgents; i++) {
+
+			// XXX: calculate adjusted pay
+			double factor = (_numAgents - i) / (double) (_numAgents);
+			double pay = _minPay + (double) (_maxPay - _minPay) * factor;
+			// System.out.format("i=%d f=%f p=%f ", i, factor, pay);
+
+			// calculate agent's attraction to the task
+			Agent agent = _agents.get(i);
+			double attraction = agent.calculateAttraction(pay, _avgPay);
+			double disgust = rand.nextDouble();
+			// System.out.format("attr=%f disg=%f\n", attraction, disgust);
+
+			// agent accepts the task
+			if (disgust < attraction) {
+				Task task = _tasks.get(_taskIndex++);
+				task._pay = pay;
+
+				agent.doTask(task);
+				agent.calculateScore();
+
+				// no more tasks
+				if (_taskIndex == _tasks.size()) {
+					Collections.sort(_agents, Collections.reverseOrder());
+					return false;
+				}
+			}
+		}
+
+		Collections.sort(_agents, Collections.reverseOrder());
+		return true;
+	}
+
+	public void report() {
+		double totalRes = 0;
+		double totalPay = 0;
+
+		for (int i = 0; i < _numTasks; i++) {
+			Task task = _tasks.get(i);
+			totalRes += task._accuracy;
+			totalPay += task._pay;
+		}
+
+		double avgRes = totalRes / _numTasks;
+		System.out.format("res: %f / %d = %f\npay: %f\n", totalRes, _numTasks,
+				avgRes, totalPay);
+	}
+
+	/**
+	 * Generate charts.
+	 */
+	public void chart() {
+		Charter.chartAccuracy(_agents);
+		Charter.chartPay(_agents);
+		Charter.chartScore(_agents);
+	}
+}

src/sim/shengdean/StaticSimulation.java

 import java.util.ArrayList;
 import java.util.Random;
 
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.CategoryAxis;
+import org.jfree.chart.axis.CategoryLabelPositions;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.DatasetRenderingOrder;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.renderer.category.LineAndShapeRenderer;
+import org.jfree.data.category.DefaultCategoryDataset;
+
 public class StaticSimulation {
 
 	public int _numTasks;
 	public int _numAgents;
+	public double _basePay;
 
-	ArrayList<Agent> _Agents = new ArrayList<Agent>();
-	ArrayList<Task> _Tasks = new ArrayList<Task>();
+	ArrayList<Agent> _agents = new ArrayList<Agent>();
+	ArrayList<Task> _tasks = new ArrayList<Task>();
 
-	public StaticSimulation(int tasks, int agents, int pay) {
+	public StaticSimulation(int tasks, int agents, double agntVar, double pay) {
 		_numTasks = tasks;
 		_numAgents = agents;
+		_basePay = pay;
 
 		// generate agents
 		for (int i = 0; i < agents; i++) {
-			_Agents.add(new Agent(i, Math.random(), 0.4D));
+			_agents.add(new Agent(i, Math.random(), agntVar));
 		}
 
 		// generate tasks
 		for (int i = 0; i < tasks; i++) {
-			_Tasks.add(new Task(i, pay));
+			_tasks.add(new Task(i, pay));
 		}
 	}
 
 		for (int i = 0; i < _numTasks; i++) {
 			// random worker is assigned
 			int agentID = rand.nextInt(_numAgents);
-			Agent agent = _Agents.get(agentID);
-			Task task = _Tasks.get(i);
-			task._worker = agent;
+			Agent agent = _agents.get(agentID);
+			Task task = _tasks.get(i);
 
-			// generate results from normal distribution
-			double res = Math.max(0, Math.min(1, agent._dist.nextDouble()));
-			task._result = res;
+			double res = agent.doTask(task);
 
 			sum += res;
 		}
 
 		double avg = sum / _numTasks;
-		System.out.format("avg: %f / %d = %f", sum, _numTasks, avg);
+		System.out.format("res: %f / %d = %f\npay: %f\n", sum, _numTasks, avg,
+				_basePay * _numTasks);
+	}
+
+	/**
+	 * Generate charts.
+	 */
+	public void chart() {
+		Charter.chartAccuracy(_agents);
+		Charter.chartPay(_agents);
+		Charter.chartScore(_agents);
 	}
 }

src/sim/shengdean/Task.java

 
 public class Task {
 	public int _id;
-	public int _pay;
+	public double _pay;
 
 	public Agent _worker;
-	public double _result;
+	public double _accuracy;
 
-	public Task(int id, int pay) {
+	public Task(int id) {
+		_id = id;
+	}
+
+	public Task(int id, double pay) {
 		_id = id;
 		_pay = pay;
 	}