package internetz; import github.DataSetProvider; import github.TaskSkillFrequency; import github.TaskSkillsPool; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import logger.EndRunLogger; import logger.PjiitLogger; import logger.PjiitOutputter; import logger.SanityLogger; import logger.ValidationLogger; import logger.ValidationOutputter; import org.apache.log4j.LogManager; import repast.simphony.context.DefaultContext; import repast.simphony.engine.environment.RunEnvironment; import repast.simphony.engine.environment.RunState; import repast.simphony.engine.schedule.ISchedulableAction; import repast.simphony.engine.schedule.ISchedule; import repast.simphony.engine.schedule.Schedule; import repast.simphony.engine.schedule.ScheduleParameters; import repast.simphony.engine.schedule.ScheduledMethod; import repast.simphony.random.RandomHelper; import repast.simphony.util.collections.IndexedIterable; import strategies.CentralPlanning; import strategies.Strategy; import strategies.StrategyDistribution; import test.AgentTestUniverse; import test.Model; import test.TaskTestUniverse; import utils.DescribeUniverseBulkLoad; import utils.LaunchStatistics; import utils.NamesGenerator; import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList; import argonauts.PersistAdvancement; import argonauts.PersistJobDone; import argonauts.PersistRewiring; import au.com.bytecode.opencsv.CSVWriter; import constants.Constraints; import constants.ModelFactory; /** * COIN network emergence simulator, a Repast Simphony 2.1 multi-agent social * simulation for modeling task allocation techniques and behavior of * collaborators in websites like GitHub and Wikipedia. Works on both Windows * and Linux environments. * * Code repository https://github.com/wikiteams/aon-emerging-wikiteams * * Repast License: The Repast suite software and documentation is licensed under * a "New BSD" style license. Please note that Repast Simphony uses a variety of * tools and third party external libraries each having its own compatible * license, including software released under the Eclipse Public License, the * Common Public License, the GNU Library General Public License and other * licenses. * * Simulation (Project) uses library "Common Beanutils" which is licensed under * Apache License * * Project uses ini4j library which is licensed under Apache License. * * @version 1.4.1 "Tardis" * @category Agent-organized Social Simulations * @since 1.0 * @author Oskar Jarczyk (since 1.0+), Blazej Gruszka (1.3+) * @see 1) github markdown 2) "On the effectiveness of emergent task allocation" */ public class InternetzCtx extends DefaultContext<Object> { private StrategyDistribution strategyDistribution; private ModelFactory modelFactory; private SkillFactory skillFactory; private LaunchStatistics launchStatistics; private Schedule schedule = new Schedule(); private String[] universe = null; private TaskPool taskPool = new TaskPool(); private AgentPool agentPool = new AgentPool(); private List<Agent> listAgent; private CentralPlanning centralPlanningHq; @SuppressWarnings("unused") private boolean shutdownInitiated = false; private boolean alreadyFlushed = false; public InternetzCtx() { super("InternetzCtx"); try { initializeLoggers(); RandomHelper.setSeed(SimulationParameters.randomSeed); RandomHelper.init(); clearStaticHeap(); say("Super object InternetzCtx loaded"); // getting parameters of simulation say(Constraints.LOADING_PARAMETERS); SimulationParameters.init(); if (SimulationParameters.multipleAgentSets) { universe = DescribeUniverseBulkLoad.init(); } launchStatistics = new LaunchStatistics(); modelFactory = new ModelFactory(SimulationParameters.model_type); say("Starting simulation with model: " + modelFactory.toString()); if (modelFactory.getFunctionality().isValidation()) initializeValidationLogger(); // TODO: implement mixed strategy distribution strategyDistribution = new StrategyDistribution(); // initialize skill pools skillFactory = new SkillFactory(); skillFactory.buildSkillsLibrary(); say("SkillFactory parsed all skills from CSV file"); } catch (IOException e) { e.printStackTrace(); say(Constraints.ERROR_INITIALIZING_PJIITLOGGER); } catch (Exception exc) { say(exc.toString()); exc.printStackTrace(); say(Constraints.ERROR_INITIALIZING_PJIITLOGGER_AO_PARAMETERS); } try { DataSetProvider dsp = new DataSetProvider( SimulationParameters.dataSetAll); AgentSkillsPool.instantiate(dsp.getAgentSkillDataset()); say("Instatiated AgentSkillsPool"); TaskSkillsPool.instantiate(dsp.getTaskSkillDataset()); say("Instatied TaskSkillsPool"); strategyDistribution .setType(SimulationParameters.strategyDistribution); strategyDistribution.setSkillChoice(modelFactory, SimulationParameters.skillChoiceAlgorithm); strategyDistribution.setTaskChoice(modelFactory, SimulationParameters.taskChoiceAlgorithm); strategyDistribution.setTaskMinMaxChoice(modelFactory, SimulationParameters.taskMinMaxChoiceAlgorithm); } catch (Exception exc) { exc.printStackTrace(); say(Constraints.UNKNOWN_EXCEPTION); } this.addSubContext(agentPool); this.addSubContext(taskPool); initializeTasks(); initializeAgents(); say("Task choice algorithm is " + SimulationParameters.taskChoiceAlgorithm); sanity("Number of teams created " + this.getObjects(Task.class).size()); sanity("Number of agents created " + this.getObjects(Agent.class).size()); sanity("Algorithm tested: " + SimulationParameters.taskChoiceAlgorithm); try { outputAgentSkillMatrix(); } catch (IOException e) { say(Constraints.IO_EXCEPTION); e.printStackTrace(); } catch (NullPointerException nexc) { say(Constraints.UNKNOWN_EXCEPTION); nexc.printStackTrace(); } if (SimulationParameters.forceStop) RunEnvironment.getInstance().endAt(SimulationParameters.numSteps); buildCentralPlanner(); buildExperienceReassessment(); buildAgentsWithdrawns(); decideAboutGranularity(); decideAboutCutPoint(); PersistAdvancement.calculateAll(taskPool); // TODO: later add req that if at least 1 agent uses Preferential... List<ISchedulableAction> actions = schedule.schedule(this); say(actions.toString()); } private void initializeLoggers() throws IOException { // System.setErr(new PrintStream(new // FileOutputStream("error_console.log"))); // actually this little bastard is not working, find out why ? PjiitLogger.init(); say(Constraints.LOGGER_INITIALIZED); SanityLogger.init(); sanity(Constraints.LOGGER_INITIALIZED); EndRunLogger.init(); EndRunLogger.buildHeaders(buildFinalMessageHeader()); } private void initializeAgents() { Model model = modelFactory.getFunctionality(); if (model.isNormal() && model.isValidation()) { throw new UnsupportedOperationException(); } else if (model.isNormal()) { addAgents(); } else if (model.isSingleValidation()) { listAgent = new ArrayList<Agent>(); AgentTestUniverse.init(); initializeValidationAgents(); } else if (model.isValidation()) { listAgent = new ArrayList<Agent>(); AgentTestUniverse.init(); initializeValidationAgents(); } } private void initializeValidationAgents() { for (Agent agent : AgentTestUniverse.DATASET) { say("Adding validation agent to pool.."); Strategy strategy = new Strategy( strategyDistribution.getTaskStrategy(agent), strategyDistribution.getTaskMaxMinStrategy(agent), strategyDistribution.getSkillStrategy(agent)); agent.setStrategy(strategy); listAgent.add(agent); say(agent.toString() + " added to pool."); // Required adding agent to context // this.add(agent); agentPool.add(agent); } } protected void initializeTasks() { Model model = modelFactory.getFunctionality(); if (model.isNormal() && model.isValidation()) { throw new UnsupportedOperationException(); } else if (model.isNormal()) { initializeTasksNormally(); } else if (model.isSingleValidation()) { TaskTestUniverse.init(); initalizeValidationTasks(); } else if (model.isValidation()) { TaskTestUniverse.init(); initalizeValidationTasks(); } else { assert false; // should never happen } } private void initalizeValidationTasks() { for (Task task : TaskTestUniverse.DATASET) { say("Adding validation task to pool.."); taskPool.addTask(task.getName(), task); taskPool.add(task); agentPool.add(task); } } private void initializeTasksNormally() { Integer howMany = SimulationParameters.multipleAgentSets ? Integer .parseInt(universe[1]) : SimulationParameters.taskCount; for (int i = 0; i < howMany; i++) { Task task = new Task(); say("Creating task.."); taskPool.addTask(task.getName(), task); say("Initializing task.."); task.initialize(howMany); taskPool.add(task); agentPool.add(task); } launchStatistics.taskCount = taskPool.getCount(); } private void initializeValidationLogger() { ValidationLogger.init(); say(Constraints.VALIDATION_LOGGER_INITIALIZED); validation("---------------------------------------------------------"); } private void outputAgentSkillMatrix() throws IOException { CSVWriter writer = new CSVWriter(new FileWriter("input_a1.csv"), ',', CSVWriter.NO_QUOTE_CHARACTER); for (Agent agent : listAgent) { for (AgentInternals __agentInternal : agent.getAgentInternals()) { ArrayList<String> entries = new ArrayList<String>(); entries.add(agent.getNick()); entries.add(__agentInternal.getExperience().getValue() + ""); entries.add(__agentInternal.getSkill().getName()); String[] stockArr = new String[entries.size()]; stockArr = entries.toArray(stockArr); writer.writeNext(stockArr); } } writer.close(); } private void addAgents() { Integer agentCnt = SimulationParameters.multipleAgentSets ? Integer .parseInt(universe[0]) : SimulationParameters.agentCount; listAgent = NamesGenerator.getnames(agentCnt); for (int i = 0; i < agentCnt; i++) { Agent agent = listAgent.get(i); Strategy strategy = new Strategy( strategyDistribution.getTaskStrategy(agent), strategyDistribution.getTaskMaxMinStrategy(agent), strategyDistribution.getSkillStrategy(agent)); agent.setStrategy(strategy); say(agent.toString()); say("in add aggent i: " + i); // Required adding agent to context // this.add(agent); for (AgentInternals ai : agent.getAgentInternals()) { assert ai.getExperience().getValue() > 0; say("For a=" + agent.toString() + " delta is " + ai.getExperience().getDelta()); say("For a=" + agent.toString() + " value is " + ai.getExperience().getValue()); say("For a=" + agent.toString() + " top is " + ai.getExperience().getTop()); } agentPool.add(agent); } launchStatistics.agentCount = agentPool.size() - launchStatistics.taskCount; } public void clearStaticHeap() { say("Clearing static data from previous simulation"); PersistJobDone.clear(); PersistAdvancement.clear(); PersistRewiring.clear(); TaskSkillsPool.clear(); SkillFactory.skills.clear(); NamesGenerator.clear(); TaskPool.clearTasks(); AgentSkillsPool.clear(); Agent.totalAgents = 0; TaskSkillsPool.static_frequency_counter = 0; TaskSkillFrequency.clear(); AgentSkillsFrequency.clear(); } @ScheduledMethod(start = 1, interval = 1, priority = ScheduleParameters.FIRST_PRIORITY) public void finishSimulation() { say("finishSimulation() check launched"); EnvironmentEquilibrium.setActivity(false); if (taskPool.getCount() < 1) { say("count of taskPool is < 1, finishing simulation"); finalMessage(buildFinalMessage()); shutdownInitiated = true; RunEnvironment.getInstance().endRun(); cleanAfter(); } } private String buildFinalMessage() { return RunState.getInstance().getRunInfo().getBatchNumber() + "," + RunState.getInstance().getRunInfo().getRunNumber() + "," + RunEnvironment.getInstance().getCurrentSchedule() .getTickCount() + "," + launchStatistics.agentCount + "," + launchStatistics.taskCount + "," + getTaskLeft() + "," + launchStatistics.expDecay + "," + launchStatistics.fullyLearnedAgentsLeave + "," + launchStatistics.experienceCutPoint + "," + launchStatistics.granularity + "," + launchStatistics.granularityType + "," + SimulationParameters.granularityObstinacy + "," + strategyDistribution.getTaskChoice() + "," + SimulationParameters.fillAgentSkillsMethod + "," + SimulationParameters.agentSkillPoolDataset + "," + SimulationParameters.taskSkillPoolDataset + "," + strategyDistribution.getSkillChoice() + "," + strategyDistribution.getTaskMinMaxChoice() + "," + TaskSkillFrequency.tasksCheckSum + "," + AgentSkillsFrequency.tasksCheckSum; } private int getTaskLeft() { int left = 0; for (Task task : taskPool.getObjects(Task.class)){ if(task.getClass().getName().equals("internetz.Task")){ if ( (task.getTaskInternals().size() > 0) && (task.getGeneralAdvance() < 1.) ){ left++; } } } return left; } private String buildFinalMessageHeader() { return "Batch Number" + "," + "Run Number" + "," + "Tick Count" + "," + "Agents count" + "," + "Tasks count" + "," + "Tasks left" + "," + "Experience decay" + "," + "Fully-learned agents leave" + "," + "Exp cut point" + "," + "Granularity" + "," + "Granularity type" + "," + "Granularity obstinancy" + "," + "Task choice strategy" + "," + "fillAgentSkillsMethod" + "," + "agentSkillPoolDataset" + "," + "taskSkillPoolDataset" + "," + "Skill choice strategy" + "," + "Task MinMax choice" + "," + "Task dataset checksum" + "," + "Agent dataset checksum"; } @ScheduledMethod(start = 1, interval = 1, priority = ScheduleParameters.LAST_PRIORITY) public void checkForActivity() { say("checkForActivity() check launched"); if (EnvironmentEquilibrium.getActivity() == false) { say("EnvironmentEquilibrium.getActivity() returns false!"); finalMessage(buildFinalMessage()); shutdownInitiated = true; RunEnvironment.getInstance().endRun(); cleanAfter(); } } private void cleanAfter() { if (!alreadyFlushed) { LogManager.shutdown(); alreadyFlushed = true; } } private void say(String s) { PjiitOutputter.say(s); } private void validation(String s) { ValidationOutputter.say(s); } private void validationError(String s) { ValidationOutputter.error(s); } private void validationFatal(String s) { ValidationOutputter.fatal(s); } private void sanity(String s) { PjiitOutputter.sanity(s); } private void finalMessage(String s) { if (modelFactory.getFunctionality().isValidation()) { validation(s); } EndRunLogger.finalMessage(s); } public void centralPlanning() { say("CentralPlanning scheduled method launched, listAgent.size(): " + listAgent.size() + " taskPool.size(): " + taskPool.size()); // Zeroing agents orders centralPlanningHq.zeroAgentsOrders(listAgent); centralPlanningHq.centralPlanningCalc(listAgent, taskPool); } /** * Here I need to schedule method manually because i don't know if central * planer is enabled for the simulation whether not. */ public void buildCentralPlanner() { say("buildCentralPlanner lunched !"); if (strategyDistribution.getTaskChoice().equals("central")) { centralPlanningHq = new CentralPlanning(); say("Central planner initiating....."); ISchedule schedule = RunEnvironment.getInstance() .getCurrentSchedule(); ScheduleParameters params = ScheduleParameters.createRepeating(1, 1, ScheduleParameters.FIRST_PRIORITY); schedule.schedule(params, this, "centralPlanning"); say("Central planner initiated and awaiting for call !"); } } public synchronized void experienceReassess() { try { IndexedIterable<Object> agentObjects = agentPool .getObjects(Agent.class); for (Object agent : agentObjects) { String type = agent.getClass().getName(); if (type.equals("internetz.Agent")) { say("Checking if I may have to decrease exp of " + (((Agent) agent).getNick())); // use persist job done Map<Integer, List<Skill>> c = PersistJobDone .getSkillsWorkedOn(((Agent) agent).getNick()); if ((c == null) || (c.size() < 1)) { // agent didn't work on // anything yet ! continue; // move on to next agent in pool } List<Skill> __s = c.get(Integer .valueOf((int) RunEnvironment.getInstance() .getCurrentSchedule().getTickCount())); List<Skill> s = __s == null ? new ArrayList<Skill>() : __s; Collection<AgentInternals> aic = ((Agent) agent) .getAgentInternals(); CopyOnWriteArrayList aicconcurrent = new CopyOnWriteArrayList( aic); for (Object ai : aicconcurrent) { if (s.contains(((AgentInternals) ai).getSkill())) { // was working on this, don't decay } else { // decay this experience by beta < 1 if (SimulationParameters.allowSkillDeath) { boolean result = ((AgentInternals) ai) .decayExperienceWithDeath(); if (result) { ((Agent) agent).removeSkill( ((AgentInternals) ai).getSkill(), false); } } else { double value = ((AgentInternals) ai) .decayExperience(); if (value == 0) { say("Experience of agent " + (((Agent) agent).getNick()) + " wasn't decreased because it's already low"); } else say("Experience of agent " + (((Agent) agent).getNick()) + " decreased and is now " + value); } } } } } } catch (Exception exc) { validationFatal(exc.toString()); validationError(exc.getMessage()); exc.printStackTrace(); } finally { say("Regular method run for expDecay finished for this step."); } } /** * Here I need to schedule method manually because I don't know if expDecay * is enabled for the simulation whether not. */ public void buildExperienceReassessment() { say("buildExperienceReassessment lunched !"); if (SimulationParameters.experienceDecay) { int reassess = RandomHelper.nextIntFromTo(0, 1); // I want in results both expDecay off and on! // thats why randomize to use both if (reassess == 0) { SimulationParameters.experienceDecay = false; launchStatistics.expDecay = false; } else if (reassess == 1) { SimulationParameters.experienceDecay = true; launchStatistics.expDecay = true; say("Exp decay initiating....."); ISchedule schedule = RunEnvironment.getInstance() .getCurrentSchedule(); ScheduleParameters params = ScheduleParameters.createRepeating( 1, 1, ScheduleParameters.LAST_PRIORITY); schedule.schedule(params, this, "experienceReassess"); say("Experience decay initiated and awaiting for call !"); } else assert false; // reassess is always 0 or 1 } } public synchronized void agentsWithdrawns() { try { IndexedIterable<Object> agentObjects = agentPool .getObjects(Agent.class); CopyOnWriteArrayList acconcurrent = new CopyOnWriteArrayList(); for (Object object : agentObjects) { acconcurrent.add(object); } for (Object agent : acconcurrent) { if (agent.getClass().getName().equals("internetz.Agent")) { say("Checking if I may have to force " + (((Agent) agent).getNick()) + " to leave"); Collection<AgentInternals> aic = ((Agent) agent) .getAgentInternals(); CopyOnWriteArrayList aicconcurrent = new CopyOnWriteArrayList( aic); boolean removal = true; for (Object ai : aicconcurrent) { if (((AgentInternals) ai).getExperience().getDelta() < 1.) { say("Agent " + (((Agent) agent).getNick()) + " didn't reach maximum in skill " + ((AgentInternals) ai).getSkill()); removal = false; } } if (removal) { say("Agent " + (((Agent) agent).getNick()) + " don't have any more skills. Removing agent"); agentPool.remove(agent); } } } } catch (Exception exc) { validationFatal(exc.toString()); validationError(exc.getMessage()); exc.printStackTrace(); } finally { say("Eventual forcing agents to leave check finished!"); } } /** * Here I need to schedule method manually because I don't know if * fullyLearnedAgentsLeave is enabled for the simulation whether not. */ public void buildAgentsWithdrawns() { say("buildAgentsWithdrawns lunched !"); if (SimulationParameters.fullyLearnedAgentsLeave) { int reassess = RandomHelper.nextIntFromTo(0, 1); // I want in results both expDecay off and on! // thats why randomize to use both if (reassess == 0) { SimulationParameters.fullyLearnedAgentsLeave = false; launchStatistics.fullyLearnedAgentsLeave = false; } else if (reassess == 1) { SimulationParameters.fullyLearnedAgentsLeave = true; launchStatistics.fullyLearnedAgentsLeave = true; say("Agents withdrawns initiating....."); ISchedule schedule = RunEnvironment.getInstance() .getCurrentSchedule(); ScheduleParameters params = ScheduleParameters.createRepeating( 1, 1, ScheduleParameters.LAST_PRIORITY + 1); schedule.schedule(params, this, "agentsWithdrawns"); say("Agents withdrawns initiated and awaiting for call !"); } else assert false; // reassess is always 0 or 1 } } private void decideAboutGranularity() { if (SimulationParameters.granularity) { if (SimulationParameters.granularityType.equals("DISTRIBUTED")) { int threePossibilities = RandomHelper.nextIntFromTo(1, 2); switch (threePossibilities) { case 1: SimulationParameters.granularity = false; launchStatistics.granularity = false; launchStatistics.granularityType = "OFF"; break; // case 2: // SimulationParameters.granularity = true; // launchStatistics.granularity = true; // SimulationParameters.granularityType = "TASKANDSKILL"; // launchStatistics.granularityType = "TASKANDSKILL"; // TODO: i need to think it over more case 2: SimulationParameters.granularity = true; launchStatistics.granularity = true; SimulationParameters.granularityType = "TASKONLY"; launchStatistics.granularityType = "TASKONLY"; break; // case 3: // SimulationParameters.granularity = true; // launchStatistics.granularity = true; // SimulationParameters.granularityType = "TASKONLY"; // launchStatistics.granularityType = "TASKONLY"; // break; default: break; } } } else { launchStatistics.granularity = false; launchStatistics.granularityType = "OFF"; } } private void decideAboutCutPoint() { if (SimulationParameters.experienceCutPoint) { int twoPossibilities = RandomHelper.nextIntFromTo(0, 1); switch (twoPossibilities) { case 0: SimulationParameters.experienceCutPoint = false; launchStatistics.experienceCutPoint = false; break; case 1: SimulationParameters.experienceCutPoint = true; launchStatistics.experienceCutPoint = true; break; default: break; } } else { launchStatistics.experienceCutPoint = false; } } }