Skip to content

Commit

Permalink
Add SymuBeliefsAndInfluence docs
Browse files Browse the repository at this point in the history
  • Loading branch information
lmorisse committed May 18, 2020
1 parent 9968a7c commit c3c1d02
Show file tree
Hide file tree
Showing 15 changed files with 601 additions and 345 deletions.
467 changes: 467 additions & 0 deletions Symu source code/SymuEngine/Classes/Agents/Agent.TaskManagement.cs

Large diffs are not rendered by default.

328 changes: 1 addition & 327 deletions Symu source code/SymuEngine/Classes/Agents/Agent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace SymuEngine.Classes.Agents
/// An abstract base class for agents.
/// You must define your own agent derived classes derived
/// </summary>
public abstract class Agent
public abstract partial class Agent
{
private byte _newInteractionCounter;

Expand Down Expand Up @@ -1205,53 +1205,6 @@ protected virtual void ActClassKey(Message message)

#endregion

#region Capacity

/// <summary>
/// Describe the agent capacity
/// </summary>
public AgentCapacity Capacity { get; } = new AgentCapacity();

/// <summary>
/// Set the initial capacity for the new step based on SetInitialCapacity, working day,
/// By default = Initial capacity if it's a working day, 0 otherwise
/// If resetRemainingCapacity set to true, Remaining capacity is reset to Initial Capacity value
/// </summary>
public void HandleCapacity(bool resetRemainingCapacity)
{
// Intentionally no test on Agent that must be able to perform tasks
// && Cognitive.TasksAndPerformance.CanPerformTask
// Example : internet access don't perform task, but is online
if (IsPerformingTask())
{
SetInitialCapacity();
if (Cognitive.TasksAndPerformance.CanPerformTask)
{
Environment.IterationResult.Capacity += Capacity.Initial;
}
}
else
{
Capacity.Initial = 0;
}

if (resetRemainingCapacity)
{
Capacity.Reset();
}
}

/// <summary>
/// Use to set the baseline value of the initial capacity
/// </summary>
/// <returns></returns>
public virtual void SetInitialCapacity()
{
Capacity.Initial = 1;
}

#endregion

#region Subscribe

private void ActSubscribe(Message message)
Expand Down Expand Up @@ -1325,284 +1278,5 @@ public void Unsubscribe(AgentId agentId, byte subject)
}

#endregion

#region Tasks management

/// <summary>
/// Override this method to specify how an agent will get new tasks to complete
/// By default, if worker can't perform task or has reached the maximum number of tasks,
/// he can't ask for more tasks, just finished the tasks in the taskManager
/// </summary>
public virtual void GetNewTasks()
{
}
/// <summary>
/// Post a task in the TasksProcessor
/// </summary>
/// <param name="task"></param>
/// <remarks>Don't use TaskProcessor.Post directly to handle the OnBeforeTaskPost event</remarks>
public void Post(SymuTask task)
{
if (task == null)
{
throw new ArgumentNullException(nameof(task));
}

OnBeforePostTask(task);
if (!task.IsBlocked)
{
TaskProcessor.Post(task);
}
}
/// <summary>
/// Post a task in the TasksProcessor
/// </summary>
/// <param name="tasks"></param>
/// <remarks>Don't use TaskProcessor.Post directly to handle the OnBeforeTaskPost event</remarks>
public void Post(IEnumerable<SymuTask> tasks)
{
if (tasks is null)
{
throw new ArgumentNullException(nameof(tasks));
}

foreach (var task in tasks)
{
OnBeforePostTask(task);
if (!task.IsBlocked)
{
TaskProcessor.Post(task);
}
}
}

/// <summary>
/// EventHandler triggered before the event TaskProcessor.Post(task)
/// By default CheckBlockerBeliefs
/// If task must be posted, use task.Blockers
/// </summary>
/// <param name="task"></param>
protected virtual void OnBeforePostTask(SymuTask task)
{
CheckBlockerBeliefs(task);
}

/// <summary>
/// Work on the next task
/// </summary>
public void WorkInProgress(SymuTask task)
{
if (task == null)
{
Status = AgentStatus.Available;
return;
}

// The task may be blocked, try to unlock it
TryRecoverBlockedTask(task);
// Agent may discover new blockers
CheckBlockers(task);
// Task may have been blocked
// Capacity may have been used for blockers
if (!task.IsBlocked && Capacity.HasCapacity)
{
WorkOnTask(task);
}

if (Capacity.HasCapacity)
// We start a new loop on the current tasks of the agent
{
SwitchingContextModel();
}
}

/// <summary>
/// Simulate the work on a specific task
/// </summary>
/// <param name="task"></param>
public virtual float WorkOnTask(SymuTask task)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

float timeSpent;
if (TimeStep.Type == TimeStepType.Intraday)
{
timeSpent = Math.Min(Environment.Organization.Models.Intraday, Capacity.Actual);
}
else
{
timeSpent = Cognitive.TasksAndPerformance.TasksLimit.LimitSimultaneousTasks
// Mono tasking
? Math.Min(task.Weight, Capacity.Actual)
// Multi tasking
: Math.Min(task.Weight / 2, Capacity.Actual);
}

timeSpent = Math.Min(task.WorkToDo, timeSpent);
task.WorkToDo -= timeSpent;
if (task.WorkToDo < Tolerance)
{
SetTaskDone(task);
}
else
{
UpdateTask(task);
}

// As the agent work on task that requires knowledge, the agent can't forget the associate knowledge today
foreach (var knowledgeId in task.KnowledgesBits.KnowledgeIds)
{
ForgettingModel.UpdateForgettingProcess(knowledgeId, task.KnowledgesBits.GetBits(knowledgeId));
}

Capacity.Decrement(timeSpent);
return timeSpent;
}

/// <summary>
/// Set the task done in task manager
/// </summary>
/// <param name="task"></param>
public void SetTaskDone(SymuTask task)
{
TaskProcessor.PushDone(task);
}

/// <summary>
/// Update the task as the agent has worked on it, but not complete it
/// </summary>
/// <param name="task"></param>
public void UpdateTask(SymuTask task)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

task.Update(TimeStep.Step);
}

/// <summary>
/// Launch a recovery for all the blockers
/// </summary>
/// <param name="task"></param>
private void TryRecoverBlockedTask(SymuTask task)
{
foreach (var blocker in task.Blockers.FilterBlockers(TimeStep.Step))
{
blocker.Update(TimeStep.Step);
TryRecoverBlocker(task, blocker);
}
}

/// <summary>
/// Launch a recovery for the blocker
/// </summary>
/// <param name="task"></param>
/// <param name="blocker"></param>
protected virtual void TryRecoverBlocker(SymuTask task, Blocker blocker)
{
}

/// <summary>
/// Check if there are blockers today on the task
/// </summary>
/// <param name="task"></param>
private void CheckBlockers(SymuTask task)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

if (!Environment.Organization.Models.MultipleBlockers && task.IsBlocked)
// One blocker at a time
{
return;
}

CheckNewBlockers(task);
}

/// <summary>
/// Launch a recovery for the blocker
/// </summary>
/// <param name="task"></param>
public virtual void CheckNewBlockers(SymuTask task)
{
}
/// <summary>
/// Check Task.KnowledgesBits against Agent.expertise
/// </summary>
public void CheckBlockerBeliefs(SymuTask task)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

if (task.Parent is Message)
{
return;
}

foreach (var knowledgeId in task.KnowledgesBits.KnowledgeIds)
{
CheckBlockerBelief(task, knowledgeId);
}
}
public void CheckBlockerBelief(SymuTask task, ushort knowledgeId)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

var taskBits = task.KnowledgesBits.GetBits(knowledgeId);
float mandatoryScore = 0;
float requiredScore = 0;
byte mandatoryIndex = 0;
byte requiredIndex = 0;
Cognitive.KnowledgeAndBeliefs.CheckBelief(knowledgeId, taskBits, ref mandatoryScore, ref requiredScore,
ref mandatoryIndex, ref requiredIndex);
CheckBlockerBelief(task, knowledgeId, mandatoryScore, requiredScore, mandatoryIndex, requiredIndex);
}

protected virtual void CheckBlockerBelief(SymuTask task, ushort knowledgeId, float mandatoryScore, float requiredScore, byte mandatoryIndex, byte requiredIndex)
{
if (!(mandatoryScore <= -Cognitive.InternalCharacteristics.RiskAversionThreshold))
{
return;
}

// Prevent the agent from acting on a particular belief
// mandatoryScore is not enough => agent don't want to do the task, the task is blocked
var blocker = AddBlocker(task, Murphy.IncompleteBelief, knowledgeId, mandatoryIndex);
TryRecoverBlocker(task, blocker);
}

public Blocker AddBlocker(SymuTask task, int murphyType, object parameter, object parameter2)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}

var blocker = task.Blockers.Add(murphyType, TimeStep.Step, parameter, parameter2);
Environment.IterationResult.Blockers.AddBlockerInProgress(TimeStep.Step);
return blocker;
}

/// <summary>
/// Switching context may have an impact on the agent capacity
/// </summary>
public virtual void SwitchingContextModel()
{
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public void AddBelief(ushort knowledgeId, BeliefLevel beliefLevel)
/// Check belief required by a task against the worker expertise
/// </summary>
/// <param name="beliefId"></param>
/// <param name="taskBitIndexes">KnowledgeBot indexes of the task that must be checked against agent's beliefs</param>
/// <param name="taskBitIndexes">KnowledgeBit indexes of the task that must be checked against agent's beliefs</param>
/// <param name="mandatoryCheck"></param>
/// <param name="requiredCheck"></param>
/// <param name="mandatoryIndex"></param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public OrganizationEntity(string name) : base(0, ClassKey, name)
/// </summary>
public List<Knowledge> Knowledges { get; } = new List<Knowledge>();

/// <summary>
/// List of the /Maydays handle in the simulation
/// </summary>
public MurphyCollection Murphies { get; } = new MurphyCollection();

public ushort NextEntityIndex()
{
return EntityIndex++;
Expand Down
Binary file added docs/_static/SymuBeliefsAndInfluence.PNG
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c3c1d02

Please sign in to comment.