ContactCenters
V. 0.9.9.

umontreal.iro.lecuyer.contactcenters.router
Class AgentsPrefRouterWithDelays

java.lang.Object
  extended by umontreal.iro.lecuyer.contactcenters.router.Router
      extended by umontreal.iro.lecuyer.contactcenters.router.AgentsPrefRouter
          extended by umontreal.iro.lecuyer.contactcenters.router.AgentsPrefRouterWithDelays
All Implemented Interfaces:
NewContactListener

public class AgentsPrefRouterWithDelays
extends AgentsPrefRouter

Extends the agents' preference-based router to support delays for routing, and allow priority to change with waiting time. Often, a contact has to wait for some time before it can overflow to groups of backup agents. Delays are used to favor the usage of primary agents as opposed to backup agents which are kept for customers which have waited long enough. The priority of a waiting contact may also change if it is waiting long enough. This router allows the user to input such delays, and to set up several different matrices of ranks for priority to be a piecewise-constant function of the waiting time.

Data structures.

This router uses the same structures as the agents' preference-based router without delays, with an additional I×K matrix of delays, and optional extra group-to-type matrices of ranks associated with minimal waiting times. Each delay d (i, k) is a finite positive number indicating the minimal time a contact of type k must wait to be accepted for service by an agent in group i.

Each extra matrix of ranks defines a function $ \rGT$[j](i, k) which associates a matrix of ranks with the minimal waiting time wj. Let w0 = 0 and $ \rGT$[0](i, k) = $ \rGT$(i, k). So if no extra matrix of ranks is given, we have only $ \rGT$[0](i, k), the default matrix of ranks used by the agents' preference-based routing policy without delays.

Note that fixing d (i, k) = 0 for all i and k, and omitting extra matrices of ranks reverts to the original agents' preference-based routing without delays.

Basic routing scheme.

We now describe more specifically how the routing with delays works. Let dk, 1, dk, 2,… be the delays d (⋅, k) sorted in increasing order, with duplicates eliminated, and dk, 0 = 0. When a contact of type k arrives, it can be served only by agents whose group i satisfies d (i, k) = 0 in addition to the conditions imposed by the agents' preference-based routing policy. If a contact is queued as no free agent is available to serve it, an event is scheduled to try routing the contact again after a delay dk, 1. During this so-called rerouting, the delay condition becomes Wd (i, k), where W is the time the contact has waited in queue so far. If this second agent selection fails, a third trial happens after a delay dk, 2 - dk, 1. More generally, reroutings happen for each delay dk, j, for j = 1, 2,…, unless the contact is accepted by an agent, or abandons. Consequently, as its waiting time increases, the contact can be accepted by a wider range of agents.

Contact selection is done in a similar way as with the agents' preference-based routing policy, except that delays d (i, k), and extra matrices of ranks $ \rGT$[j](i, k) are taken into account while determining the rank for a pair (i, k). More specifically, let Wk be the longest waiting time among all queued contacts of type k. First, the rank of a queued contact of type k is infinite (so the call cannot leave the queue) if its waiting time Wk is smaller than the delay d (i, k). On the other hand, if Wkd (i, k), the rank is given by $ \rGT$[j'](i, k) where j' = $ \htmax${j : Wkwj} is the index of the matrix of ranks applying to the queued contact. If j' > 0, we check the other queued contacts of type k to determine if another queued contact has a smaller rank, i.e., an higher priority. For each scanned queued contact, we check the delay condition and stop scanning as soon as Wk < d (i, k) or j' = 0.

The default behavior of this policy can be altered by two switches: overflow transfer, and longest waiting time modes. When overflow transfer is turned ON, a contact gaining access to some agent groups after waiting some delay also loses access to the original agent groups. When longest waiting time is turned OFF, the contact selection gives priority to pairs (i, k) with small delays d (i, k).

Overflow transfer mode.

In this mode, turned off by default, the delay condition for the jth rerouting (j + 1th agent selection) becomes dk, jq < dk, j+1, j starting with 0, while the original condition is dk, jq. With this variant, when a contact has waited sufficient long to overflow to a new set of agent groups, it cannot be served by the original agent groups. Overflow can then be considered as a transfer in a new section of the contact center.

Longest waiting time mode.

In this mode, turned on by default, contact selection is performed in a single pass, in a way similar to the contact selection of the policy without delays. However, the delay condition is enforced to restrict contact-to-agent assignment.

If this option is disabled, contact selection is performed using the following multiple-passes process. When an agent in group i becomes free, it first searches for a contact whose type k satisfies d (i, k) = 0. Then, it searches for contacts for which d (i, k)≤dk, 1, for contacts for which d (i, k)≤dk, 2, etc., in that order. This gives higher priority to contacts with small minimal delay, because they can be served by a more restricted set of agents.

The latter behavior of this router is especially appropriate if delays are functions of the distance between the contact and the agent. For local contacts, d (i, k) is small, while it is large for remote contacts. The router then always gives priority to local assignments. However, it is often simpler and more intuitive to use the single-pass contact selection.


Field Summary
 
Fields inherited from class umontreal.iro.lecuyer.contactcenters.router.AgentsPrefRouter
bestAgent, bestGroup, bestQueue, bestQueuedContact, ranksGT, ranksTG, weightsGT, weightsTG
 
Fields inherited from class umontreal.iro.lecuyer.contactcenters.router.Router
BLOCKTYPE_CANTQUEUE, BLOCKTYPE_NOLINE, BLOCKTYPE_QUEUEFULL, DEQUEUETYPE_BEGINSERVICE, DEQUEUETYPE_FANTOM, DEQUEUETYPE_NOAGENT, DEQUEUETYPE_TRANSFER, dqTypeRet
 
Constructor Summary
AgentsPrefRouterWithDelays(double[][] ranksGT, double[][] delaysGT)
          Constructs a new agents' preference-based router with matrix of ranks ranksGT and delays matrix delaysGT.
AgentsPrefRouterWithDelays(double[][] ranksTG, double[][] ranksGT, double[][] delaysGT)
          Constructs a new agents' preference-based router with matrix of ranks ranksTG defining how contacts prefer agents, ranksGT defining how agents prefer contacts, and delaysGT for routing delays.
AgentsPrefRouterWithDelays(double[][] ranksTG, double[][] ranksGT, double[][] weightsTG, double[][] weightsGT, double[][] delaysGT)
          Constructs a new agents' preference-based router with matrix of ranks ranksTG defining how contacts prefer agents, and ranksGT defining how agents prefer contacts.
 
Method Summary
protected  boolean checkFreeAgents(AgentGroup group, Agent agent)
          This method is called when the agent agent in agent group group becomes free.
 double getDelayGT(int i, int k)
          Returns d (i, k) for the given agent group index i, and contact type identifier k.
 double[][] getDelaysGT()
          Returns the delays matrix used by this router.
 String getDescription()
           
 boolean getLongestWaitingTimeStatus()
          Returns true if the router uses a single-phase agent selection based on the longest waiting time.
 boolean getOverflowTransferStatus()
          Returns true if the overflow transfer mode is enabled.
protected  double getRankForAgentSelection(int k, int i)
          Determines the rank to be used for agent selection for contact type k, and agent in group i.
protected  double getRankForContactSelection(int i, int k)
          Determines the rank to be used for contact selection for contact type k, when an agent in group i becomes free.
protected  double getReroutingDelay(DequeueEvent dqEv, int numReroutingsDone)
          Returns the delay, in simulation time units, after which a queued contact should be rerouted.
protected  double getScoreForAgentSelection(Contact ct, AgentGroup testGroup, Agent testAgent)
          Returns the score for contact ct associated with agent group testGroup and agent testAgent.
protected  EndServiceEvent selectAgent(Contact ct)
          Begins the service of the contact contact by trying to assign it a free agent.
protected  EndServiceEvent selectAgent(DequeueEvent dqEv, int numReroutingsDone)
          Selects an agent for serving a queued contact in the context of rerouting.
protected  void selectWaitingQueue(AgentGroup group, Agent agent, double bestRank, boolean[] qCandidates, int numCandidates)
          Selects the queued contact for an agent agent in group group, with waiting queue candidates qCandidates.
 void setDelaysGT(double[][] delaysGT)
          Sets the delays matrix of this router to delaysGT.
 void setLongestWaitingTimeStatus(boolean longestWaitingTime)
          Sets the longest waiting time mode to longestWaitingTime.
 void setOverflowTransferStatus(boolean overflowTransfer)
          Sets the overflow transfer mode to overFlowTransfer.
 void setRanksGT(double minWaitingTime, double[][] ranksGT)
          Sets the matrix of ranks used for selecting contacts which have waited at least minWaitingTime.
 String toLongString()
          Returns a string representation of detailed information about the router.
 
Methods inherited from class umontreal.iro.lecuyer.contactcenters.router.AgentsPrefRouter
canServe, checkWaitingQueues, getAgentSelectionScore, getContactSelectionScore, getGroupToTypeMap, getRankGT, getRanksGT, getRanksTG, getRankTG, getScoreForContactSelection, getStreamAgentSelection, getStreamContactSelection, getTypeToGroupMap, getWaitingQueueType, getWeightGT, getWeightsGT, getWeightsTG, getWeightTG, needsDetailedAgentGroup, selectAgent, selectContact, selectWaitingQueue, setAgentSelectionScore, setContactSelectionScore, setRanksGT, setRanksTG, setStreamAgentSelection, setStreamContactSelection, setWeightsGT, setWeightsTG
 
Methods inherited from class umontreal.iro.lecuyer.contactcenters.router.Router
addExitedContactListener, agentReroutingEventsIterator, beginService, clearExitedContactListeners, contactReroutingEventsIterator, dequeued, endContact, endService, enqueued, exitBlocked, exitDequeued, exitServed, formatAgentGroups, formatWaitingQueues, getAgentGroup, getAgentGroupListener, getAgentGroups, getAgentReroutingEvents, getContactFactory, getContactReroutingEvents, getCurrentQueueSize, getDialers, getExitedContactListeners, getNeededWaitingQueueComparator, getNeededWaitingQueueStructure, getNumAgentGroups, getNumContactTypes, getNumWaitingQueues, getReroutingDelay, getTotalQueueCapacity, getWaitingQueue, getWaitingQueueListener, getWaitingQueues, init, isKeepingReroutingEvents, mustClearWaitingQueue, newContact, notifyBlocked, notifyDequeued, notifyServed, removeExitedContactListener, restore, save, selectContact, selectWaitingQueue, setAgentGroup, setClearWaitingQueue, setClearWaitingQueues, setContactFactory, setKeepingReroutingEvents, setTotalQueueCapacity, setWaitingQueue, startDialers, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

AgentsPrefRouterWithDelays

public AgentsPrefRouterWithDelays(double[][] ranksGT,
                                  double[][] delaysGT)
Constructs a new agents' preference-based router with matrix of ranks ranksGT and delays matrix delaysGT. The given matrices must be rectangular with one row per agent group, and one column per contact type. They define the functions $ \rGT$(i, k) (with $ \rTG$(k, i) = $ \rGT$(i, k)), and d (i, k), respectively. The weights matrices are initialized with 1's.

Parameters:
ranksGT - the contact selection matrix of ranks being used.
delaysGT - the delays matrix.
Throws:
NullPointerException - if ranksGT or delaysGT are null.
IllegalArgumentException - if the ranks or delays 2D array are not rectangular.

AgentsPrefRouterWithDelays

public AgentsPrefRouterWithDelays(double[][] ranksTG,
                                  double[][] ranksGT,
                                  double[][] delaysGT)
Constructs a new agents' preference-based router with matrix of ranks ranksTG defining how contacts prefer agents, ranksGT defining how agents prefer contacts, and delaysGT for routing delays. The given matrices must be rectangular. The weights matrices are initialized with 1's.

Parameters:
ranksTG - the matrix of ranks defining how contacts prefer agents.
ranksGT - the matrix of ranks defining how agents prefer contacts.
delaysGT - the delays matrix.
Throws:
NullPointerException - if ranksGT, ranksTG, or delaysGT are null.
IllegalArgumentException - if the given 2D arrays are not rectangular.

AgentsPrefRouterWithDelays

public AgentsPrefRouterWithDelays(double[][] ranksTG,
                                  double[][] ranksGT,
                                  double[][] weightsTG,
                                  double[][] weightsGT,
                                  double[][] delaysGT)
Constructs a new agents' preference-based router with matrix of ranks ranksTG defining how contacts prefer agents, and ranksGT defining how agents prefer contacts. The weights matrices are set to weightsTG, and weightsGT. The delays matrix is set to delaysGT. The given matrices must be rectangular.

Parameters:
ranksTG - the matrix of ranks defining how contacts prefer agents.
ranksGT - the matrix of ranks defining how agents prefer contacts.
weightsTG - the weights matrix defining $ \wTG$(k, i).
weightsGT - the weights matrix defining $ \wGT$(i, k).
delaysGT - the delays matrix.
Throws:
NullPointerException - if ranksGT, ranksTG, weightsTG, weightsGT, or delaysGT are null.
IllegalArgumentException - if the 2D arrays are not rectangular.
Method Detail

getDelaysGT

public double[][] getDelaysGT()
Returns the delays matrix used by this router.

Returns:
the delays matrix.

getDelayGT

public double getDelayGT(int i,
                         int k)
Returns d (i, k) for the given agent group index i, and contact type identifier k.

Parameters:
i - the queried agent group index.
k - the queried contact type identifier.
Returns:
the delay d (i, k).

setDelaysGT

public void setDelaysGT(double[][] delaysGT)
Sets the delays matrix of this router to delaysGT.

Parameters:
delaysGT - the new delays matrix.
Throws:
NullPointerException - if delaysGT is null.
IllegalArgumentException - if delaysGT is not rectangular.

getOverflowTransferStatus

public boolean getOverflowTransferStatus()
Returns true if the overflow transfer mode is enabled. By default, this returns false.

Returns:
the status of the overflow transfer mode.

setOverflowTransferStatus

public void setOverflowTransferStatus(boolean overflowTransfer)
Sets the overflow transfer mode to overFlowTransfer.

Parameters:
overflowTransfer - the new status of the mode.
See Also:
getOverflowTransferStatus()

getLongestWaitingTimeStatus

public boolean getLongestWaitingTimeStatus()
Returns true if the router uses a single-phase agent selection based on the longest waiting time.

Returns:
the status of the longest waiting time mode.

setLongestWaitingTimeStatus

public void setLongestWaitingTimeStatus(boolean longestWaitingTime)
Sets the longest waiting time mode to longestWaitingTime.

Parameters:
longestWaitingTime - the new status of the mode.
See Also:
getLongestWaitingTimeStatus()

setRanksGT

public void setRanksGT(double minWaitingTime,
                       double[][] ranksGT)
Sets the matrix of ranks used for selecting contacts which have waited at least minWaitingTime.

Parameters:
minWaitingTime - the minimum waiting time.
ranksGT - the matrix of ranks for this minimal waiting time.

getRankForContactSelection

protected double getRankForContactSelection(int i,
                                            int k)
Description copied from class: AgentsPrefRouter
Determines the rank to be used for contact selection for contact type k, when an agent in group i becomes free. By default, this returns $ \rGT$(i, k), but subclasses may override this method for the rank to depend on some state of the system.

Overrides:
getRankForContactSelection in class AgentsPrefRouter
Parameters:
i - the agent group index.
k - the contact type index.
Returns:
the rank associated with (i, k).

selectWaitingQueue

protected void selectWaitingQueue(AgentGroup group,
                                  Agent agent,
                                  double bestRank,
                                  boolean[] qCandidates,
                                  int numCandidates)
Description copied from class: AgentsPrefRouter
Selects the queued contact for an agent agent in group group, with waiting queue candidates qCandidates. The waiting queues k for which qCandidates[k] is true share the same minimal rank and contain at least one contact. The method must store the selected waiting queue in the field AgentsPrefRouter.bestQueue and possibly the contact to be removed in the AgentsPrefRouter.bestQueuedContact. If AgentsPrefRouter.bestQueuedContact is null, the first contact in the best queue will be used. If no waiting queue can be selected, AgentsPrefRouter.bestQueue must be set to null.

The default implementation selects the waiting queue with the greatest score as computed by AgentsPrefRouter.getScoreForContactSelection(AgentGroup,DequeueEvent), and the best queued contact is always null. This method can be overridden to use an alternate selection scheme, e.g., randomly selecting a queued contact.

Overrides:
selectWaitingQueue in class AgentsPrefRouter
Parameters:
group - the agent group containing the free agent.
agent - the free agent.
bestRank - the best rank found when searching for candidates.
qCandidates - the waiting queue candidates contacts can be pulled from.

getRankForAgentSelection

protected double getRankForAgentSelection(int k,
                                          int i)
Description copied from class: AgentsPrefRouter
Determines the rank to be used for agent selection for contact type k, and agent in group i. By default, this returns $ \rTG$(k, i), but subclasses may override this method for the rank to depend on some state of the system.

Overrides:
getRankForAgentSelection in class AgentsPrefRouter
Parameters:
k - the contact type index.
i - the agent group index.
Returns:
the rank associated with (k, i).

getScoreForAgentSelection

protected double getScoreForAgentSelection(Contact ct,
                                           AgentGroup testGroup,
                                           Agent testAgent)
Description copied from class: AgentsPrefRouter
Returns the score for contact ct associated with agent group testGroup and agent testAgent. When selecting an agent for contact ct, if there are several agent groups with the same minimal rank, the agent group with the greatest score is selected. Returning a negative infinite score prevents an agent group from being selected. The default AgentsPrefRouter.selectAgent(Contact,double,boolean[],int) method calls this method with testAgent = null if testGroup is not an instance of DetailedAgentGroup, otherwise the method is called with testAgent = testGroup.getLongestIdleAgent().

By default, this returns a score depending on the return value of AgentsPrefRouter.getAgentSelectionScore(). This can return the longest weighted idle time (the default), the weighted number of free agents, or the weight only. See AgentSelectionScore for more information.

Overrides:
getScoreForAgentSelection in class AgentsPrefRouter
Parameters:
ct - the contact being assigned an agent.
testGroup - the tested agent group.
testAgent - the tested agent, can be null.
Returns:
the score given to the association between the contact and the agent.

getReroutingDelay

protected double getReroutingDelay(DequeueEvent dqEv,
                                   int numReroutingsDone)
Description copied from class: Router
Returns the delay, in simulation time units, after which a queued contact should be rerouted. The value of numReroutingsDone gives the number of preceding reroutings, and dqEv is the dequeue event. If this delay is negative, infinite, or NaN, no rerouting happens for the contact. numReroutings will be -1 when this method is called at the time the contact is queued. By default, this method returns Double.POSITIVE_INFINITY.

Overrides:
getReroutingDelay in class Router
Parameters:
dqEv - the dequeue event representing the queued contact.
numReroutingsDone - the number of reroutings so far.
Returns:
the rerouting delay.

selectAgent

protected EndServiceEvent selectAgent(Contact ct)
Description copied from class: Router
Begins the service of the contact contact by trying to assign it a free agent. The method must select an agent group with a free agent (or a specific free agent), start the service, and return the end-service event if the service was started, or null otherwise.

Overrides:
selectAgent in class AgentsPrefRouter
Parameters:
ct - the contact being routed to an agent.
Returns:
the end-service event representing the started service, or null if the contact could not be served immediately.

checkFreeAgents

protected boolean checkFreeAgents(AgentGroup group,
                                  Agent agent)
Description copied from class: Router
This method is called when the agent agent in agent group group becomes free. If the given agent is null, the method assumes that one or more arbitrary agents in the group became free. The method must select a contact to be transferred to the free agent. The selected contacts come from waiting queues, and must be removed from the queues with dequeue type Router.DEQUEUETYPE_BEGINSERVICE before they are transferred to agents. The method returns true if and only if at least one free agent could be made busy.

The default implementation calls Router.selectContact(AgentGroup,Agent) to get a new dequeue event representing the removed contact, extracts the contact, and routes it to an agent, until group has no more free agent.

Overrides:
checkFreeAgents in class Router
Parameters:
group - the affected agent group.
agent - the agent having ended its service.
Returns:
true if some free agents became busy, false otherwise.

selectAgent

protected EndServiceEvent selectAgent(DequeueEvent dqEv,
                                      int numReroutingsDone)
Description copied from class: Router
Selects an agent for serving a queued contact in the context of rerouting. The event dqEv is used to represent the dequeued contact, while numReroutingsDone indicates the number of reroutings that has happened so far. The method should return the end-service event corresponding to the contact's new service by an agent, or null for the contact to stay in queue.

Overrides:
selectAgent in class Router
Parameters:
dqEv - the dequeue event representing the queued contact.
numReroutingsDone - the number of preceding reroutings.
Returns:
the end-service event, or null.

getDescription

public String getDescription()
Overrides:
getDescription in class AgentsPrefRouter

toLongString

public String toLongString()
Description copied from class: Router
Returns a string representation of detailed information about the router. This returns a string representation of each associated waiting queue and agent group and routing policies. For a short, one-line description, Router.toString() should be used.

Overrides:
toLongString in class AgentsPrefRouter
Returns:
a string representation of detailed information about the router.

ContactCenters
V. 0.9.9.

To submit a bug or ask questions, send an e-mail to Richard Simard.