/** * */ package internetz; import github.TaskSkillsPool; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import logger.PjiitOutputter; import repast.simphony.random.RandomHelper; import strategies.Aggregate; import strategies.CentralAssignmentTask; import strategies.GreedyAssignmentTask; import strategies.ProportionalTimeDivision; import strategies.Strategy; import tasks.CentralAssignmentOrders; import argonauts.GranulatedChoice; import argonauts.PersistJobDone; import constants.Constraints; /** * Task is a collection of a three-element set of skill, number of work units, * and work done. Literally, a representation of a simulation Task object. * * @since 1.0 * @version 1.4 * @author Oskar Jarczyk */ public class Task { private static int idIncrementalCounter = 0; public static double START_ARG_MIN = 1.002; public static double START_ARG_MAX = -0.002; private String name; private int id; private Map<String, TaskInternals> skills = new HashMap<String, TaskInternals>(); //private double persistTaskAdvance = 0; private Map<Skill, Double> persistAdvance = new HashMap<Skill, Double>(); public Task() { this.id = ++idIncrementalCounter; this.name = "Task_" + this.id; say("Task object " + this + " created"); } public void addSkill(String key, TaskInternals taskInternals) { skills.put(key, taskInternals); } public void removeSkill(String key) { skills.remove(key); } public TaskInternals getTaskInternals(String key) { return skills.get(key); } public TaskInternals getRandomTaskInternals(){ return (TaskInternals) skills.values(). toArray()[RandomHelper.nextIntFromTo(0, skills.size() - 1)]; } public synchronized void initialize(int countAll) { TaskSkillsPool.fillWithSkills(this, countAll); say("Task object initialized with id: " + this.id); } public Map<String, TaskInternals> getTaskInternals() { return skills; } public void setTaskInternals(Map<String, TaskInternals> skills) { this.skills = skills; } public int countTaskInternals() { return skills.size(); } public synchronized void setId(int id) { this.id = id; } public synchronized int getId() { return this.id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double argmax() { double argmax = START_ARG_MAX; for (TaskInternals skill : skills.values()) { double p = skill.getProgress(); if (p > argmax) argmax = skill.getProgress(); } return argmax; } /** * Less CPU ticks to get both of them * * @return Aggregate - argmax and argmin for all taskinternals {argmax, * argmin} */ public Aggregate argmaxmin() { Aggregate arg = new Aggregate(START_ARG_MAX, START_ARG_MIN); for (TaskInternals skill : skills.values()) { double p = skill.getProgress(); if (p < arg.argmin) arg.argmin = skill.getProgress(); if (p > arg.argmax) arg.argmax = skill.getProgress(); } return arg; } public double argmin() { double argmin = START_ARG_MIN; for (TaskInternals skill : skills.values()) { double p = skill.getProgress(); if (p < argmin) argmin = skill.getProgress(); } return argmin; } public double getSimplifiedAdvance(Skill skill){ double persistTaskAdvance = 0; TaskInternals ti = this.getTaskInternals(skill.getName()); if (ti == null){ persistAdvance.put(skill, 1.); //persistTaskAdvance += 1 / this.getTaskInternals().size(); } else { double progress = ti.getProgress(); persistAdvance.put(skill, progress); //persistTaskAdvance += (progress-before) / this.getTaskInternals().size(); } for (Double d : persistAdvance.values()){ persistTaskAdvance += d; } return (persistTaskAdvance / ( (double)persistAdvance.values().size() )); } /** * Gets the general completion of the Task. Calculates work done inside the * Skills and divides by the number of skills. * * @return Always the value between [0;1] */ public double getGeneralAdvance() { double result = 0; double count = 0; for (TaskInternals skill : skills.values()) { double progress = skill.getProgress(); say("skill " + skill.getSkill().getName() + " progress " + progress); result += progress > 1. ? 1. : progress; say("result " + result); persistAdvance.put(skill.getSkill(), progress); count ++; } say("skills count " + count); if (count == 0){ // all TaskInternals are gone, thus the Task is finished 100% ! return 1; } assert count > 0.; // avoid dividing by 0; result = (result / count); assert result >= 0.; assert result <= 1.; //persistTaskAdvance = result; return result; } /** * For an Agent, get skills common with argument Collection<TaskInternals> * skillsValues return intersection of agent skills and argument skillsValue * * @param agent * @param skillsValues * @return return intersection of agent skills and argument skillsValue */ private Collection<TaskInternals> computeIntersection(Agent agent, Collection<TaskInternals> skillsValues) { Collection<TaskInternals> returnCollection = new ArrayList<TaskInternals>(); for (TaskInternals singleTaskInternal : skillsValues) { if (agent .getAgentInternals(singleTaskInternal.getSkill().getName()) != null) { returnCollection.add(singleTaskInternal); } } return returnCollection; } public void workOnTaskCentrallyControlled(Agent agent) { List<Skill> skillsImprovedList = new ArrayList<Skill>(); CentralAssignmentOrders cao = agent.getCentralAssignmentOrders(); CentralAssignmentTask centralAssignmentTask = new CentralAssignmentTask(); TaskInternals taskInternal = this .getTaskInternals(cao.getChosenSkillName()); assert taskInternal != null; sanity("Choosing Si:{" + taskInternal.getSkill().getName() + "} inside Ti:{" + this.toString() + "}"); Experience experience = agent.getAgentInternalsOrCreate( cao.getChosenSkillName()).getExperience(); double delta = experience.getDelta(); centralAssignmentTask.increment(this, taskInternal, 1, delta); experience.increment(1); if (SimulationParameters.deployedTasksLeave) TaskPool.considerEnding(this); skillsImprovedList.add(taskInternal.getSkill()); PersistJobDone.addContribution(agent, this, skillsImprovedList); } public Boolean workOnTaskFromContinuum(Agent agent, GranulatedChoice granulated, Strategy.SkillChoice strategy) { return workOnTask(agent, strategy); } public Boolean workOnTask(Agent agent, Strategy.SkillChoice strategy) { Collection<TaskInternals> intersection; List<Skill> skillsImprovedList = new ArrayList<Skill>(); intersection = computeIntersection(agent, skills.values()); GreedyAssignmentTask greedyAssignmentTask = new GreedyAssignmentTask(); TaskInternals singleTaskInternal = null; double highest = -1.; assert intersection != null; //if ((SimulationParameters.granularity) && (intersection.size() < 1)) // return false; // happens when agent tries to work on // task with no intersection of skills //assert intersection.size() > 0; // assertion for the rest of cases if (intersection.size() < 1){ intersection = skills.values(); // experience - genesis action needed! if (intersection.size() < 1) return false; } switch (strategy) { case PROPORTIONAL_TIME_DIVISION: say(Constraints.INSIDE_PROPORTIONAL_TIME_DIVISION); ProportionalTimeDivision proportionalTimeDivision = new ProportionalTimeDivision(); for (TaskInternals singleTaskInternalFromIntersect : new CopyOnWriteArrayList<TaskInternals>( intersection)) { sanity("Choosing Si:{" + singleTaskInternalFromIntersect.getSkill().getName() + "} inside Ti:{" + singleTaskInternalFromIntersect.toString() + "}"); double n = intersection.size(); double alpha = 1d / n; Experience experience = agent.getAgentInternalsOrCreate( singleTaskInternalFromIntersect.getSkill().getName()) .getExperience(); double delta = experience.getDelta(); proportionalTimeDivision.increment(this, singleTaskInternalFromIntersect, 1, alpha, delta); experience.increment(alpha); skillsImprovedList.add(singleTaskInternalFromIntersect .getSkill()); } break; case GREEDY_ASSIGNMENT_BY_TASK: say(Constraints.INSIDE_GREEDY_ASSIGNMENT_BY_TASK); CopyOnWriteArrayList<TaskInternals> copyIntersection = new CopyOnWriteArrayList<TaskInternals>( intersection); /** * Tutaj sprawdzamy nad ktorymi taskami juz pracowano w tym tasku, i * bierzemy wlasnie te najbardziej rozpoczete. Jezeli zaden nie jest * rozpoczety, to bierzemy losowy */ for (TaskInternals searchTaskInternal : copyIntersection) { if (searchTaskInternal.getWorkDone().d > highest) { highest = searchTaskInternal.getWorkDone().d; singleTaskInternal = searchTaskInternal; } } /** * zmienna highest zawsze jest w przedziale od [0..*] */ assert highest > -1.; /** * musimy miec jakis pojedynczy task internal (skill) nad ktorym * bedziemy pracowac.. */ assert singleTaskInternal != null; { sanity("Choosing Si:{" + singleTaskInternal.getSkill().getName() + "} inside Ti:{" + singleTaskInternal.toString() + "}"); // int n = skills.size(); // double alpha = 1 / n; Experience experience = agent.getAgentInternalsOrCreate( singleTaskInternal.getSkill().getName()) .getExperience(); double delta = experience.getDelta(); greedyAssignmentTask.increment(this, singleTaskInternal, 1, delta); experience.increment(1); skillsImprovedList.add(singleTaskInternal.getSkill()); } break; case CHOICE_OF_AGENT: say(Constraints.INSIDE_CHOICE_OF_AGENT); /** * Pracuj wylacznie nad tym skillem, w ktorym agent ma najwiecej * doswiadczenia */ for (TaskInternals searchTaskInternal : new CopyOnWriteArrayList<TaskInternals>( intersection)) { if (agent.describeExperience(searchTaskInternal.getSkill()) > highest) { highest = agent.describeExperience(searchTaskInternal .getSkill()); singleTaskInternal = searchTaskInternal; } } /** * zmienna highest zawsze jest w przedziale od [0..*] */ assert highest != -1.; /** * musimy miec jakis pojedynczy task internal (skill) nad ktorym * bedziemy pracowac.. */ assert singleTaskInternal != null; { sanity("Choosing Si:{" + singleTaskInternal.getSkill().getName() + "} inside Ti:{" + singleTaskInternal.toString() + "}"); Experience experience = agent.getAgentInternalsOrCreate( singleTaskInternal.getSkill().getName()) .getExperience(); double delta = experience.getDelta(); greedyAssignmentTask.increment(this, singleTaskInternal, 1, delta); experience.increment(1); skillsImprovedList.add(singleTaskInternal.getSkill()); } break; case RANDOM: say(Constraints.INSIDE_RANDOM); List<TaskInternals> intersectionToShuffle = new ArrayList<TaskInternals>(); for(TaskInternals taskInternalsR : intersection){ intersectionToShuffle.add(taskInternalsR); } Collections.shuffle(intersectionToShuffle); TaskInternals randomTaskInternal = (intersectionToShuffle).get( RandomHelper.nextIntFromTo(0, intersectionToShuffle.size() - 1)); { sanity("Choosing Si:{" + randomTaskInternal.getSkill().getName() + "} inside Ti:{" + randomTaskInternal.toString() + "}"); Experience experience = agent.getAgentInternalsOrCreate( randomTaskInternal.getSkill().getName()) .getExperience(); double delta = experience.getDelta(); greedyAssignmentTask.increment(this, randomTaskInternal, 1, delta); experience.increment(1); skillsImprovedList.add(randomTaskInternal.getSkill()); } break; default: assert false; // there is no default method, so please never happen break; } if (SimulationParameters.deployedTasksLeave) TaskPool.considerEnding(this); if (skillsImprovedList.size() > 0) { PersistJobDone.addContribution(agent, this, skillsImprovedList); return true; } else { return false; } } public boolean isClosed() { boolean result = true; for (TaskInternals taskInternals : skills.values()) { if (taskInternals.getWorkDone().d < taskInternals.getWorkRequired().d) { result = false; break; } } return result; } /** * Returns a collection of skills inside internals of current task * * @return Collection of skills inside all TaskInternals */ public Collection<Skill> getSkills() { ArrayList<Skill> skillCollection = new ArrayList<Skill>(); Collection<TaskInternals> internals = this.getTaskInternals().values(); for (TaskInternals ti : internals) { skillCollection.add(ti.getSkill()); } return skillCollection; } @Override public String toString() { return "Task " + id + " " + name; } @Override public int hashCode() { return name.hashCode() * id; } @Override public boolean equals(Object obj) { if ((this.name.toLowerCase().equals(((Task) obj).name.toLowerCase())) && (this.id == ((Task) obj).id)) return true; else return false; } private void say(String s) { PjiitOutputter.say(s); } private void sanity(String s) { PjiitOutputter.sanity(s); } // public double getPersistTaskAdvance() { // return persistTaskAdvance; // } // // public void setPersistTaskAdvance(double persistTaskAdvance) { // this.persistTaskAdvance = persistTaskAdvance; // } }