This always annoys me so I usually just ignore it but this time it has prompted me to ask the question...
I am animating agents queuing for a resource using a path to represent the queue. I have a moveTo block to move my agents to a node which is placed at the front of the queue. When the queue is empty and an agent arrives to be serviced, it looks great as the agent moves to the end of the queue path and smoothly progresses along the path to the front of the queue where the node is located.
However, if there are multiple agents in the queue then new agents will move to the queue path and move all the way to the front of the queue (where the node is located) and then jump back to their correct position on the queue path.
If I put the node at the back end of the queue then the animation looks great when the agents arrive as they join the queue behind others already there but when the agent at the front of the queue seizes the resource they are waiting for it jumps to the back of the queue and then proceeds along the queue to the resource node.
Any ideas on how to get this to animate correctly?
You can achieve this simply using a Conveyor block to represent the 'shuffling along' queue (with some specific configuration), but it's worth considering the wider picture (which also helps understand why trying to add a MoveTo block to a Service with its queue along a path cannot achieve what you want).
A process model can include model-relevant spatiality where movement times are important. (As well as the MoveTo block, blocks such as RackPick/Store and Service blocks with "Send seized resources" checked implicitly include movement.) However, typically you don't: a Service block with the queue being along a path is using the path just to provide some visual representation of the queue. In the underlying model agents arrive instantly into the queue from the upstream block and instantly enter the delay when a resource is free — that is the process abstraction of the model. Hence trying to 'fix the animation' with a previous MoveTo block or similar will not work because the Service block is not supposed to be representing such a conception of its queue (so agents will 'spring back' to the reality of the underlying behaviour as you observed). Additionally, a 'properly animated queue' would be obscuring the underlying basis of the model (making it seem as if that movement is being explicitly modelled when it isn't).
A Conveyor does conceptually capture agents which have to stay a certain distance apart and (for an accumulating conveyor) explicitly models agents moving along when there is free space. So, although it may seem counterintuitive, this is actually a 'correct' detailed conceptualisation of a moving human queue (which also of course matches an actual conveyor).
To make it work as you want it, you need to make the size of the agents (just from the conveyor's perspective) such that you only have the required number of people in your queue (now a conveyor), with the following Service block just having a capacity 1 queue (which thus represents the 'front of the queue person' only) — Service blocks can't have a capacity 0 queue. You can use a Point Node as the location for this single-entry queue which is just beyond the end of the conveyor path (so that this effectively represents the first position in the queue) — see below.
You then want the agent length on the conveyor to represent your 'queue slot length' which requires specifying the queue capacity (a variable in my example), so something like
path.length(METER) / (queueCapacity - 1)
where path is your conveyor path. (The conveyor represents all queue 'slots' except the first, hence why we subtract 1 above.)
You could also encapsulate all of this as a custom ServiceWithMovingQueue block or similar.
Note that the Queue before the Conveyor is needed in case the conveyor has no room for an arriving agent (i.e., the 'conceptual queue' is full). If you wanted to be particularly realistic you'd have to decide what happens in real-life and explicitly model that (e.g., overflow queue, agent leaves, etc.).
P.S. Another alternative is to use the Pedestrian library, where Service with Lines space markup is designed to model this: partial example flow below. However, that means switching your agents to be pedestrians (participating in the pedestrian modelling underlying physics model for movement) and back again which is performance-intensive (and can cause some bizarre movement in some cases due to the physics). Plus, because the pedestrian library has no explicit concept of resources for pedestrian services, you'd have to do something like have resource pool capacity changes influence which service points were open or not. (The service points within a Service with Lines markup have functions like setSuspended so you can dynamically set them as 'open' or 'closed', in this case linked to whether resources are on-shift to man them.)
P.P.S. Note that, from a modelling accuracy perspective, capturing the 'real' movement in a human queue is typically irrelevant because
If the queue's empty, the time to move from the end to the front is typically negligible compared to the service time (and, even if it's not negligible, a service which generally has a queue present means this extra movement is only relevant for a tiny proportion of arrivals — see below).
If the queue's not empty, people move up whilst others are being served so there is no delay in terms of the service (which can always accept the next person 'immediately' after finishing with someone because they are already at the front of the queue).
This cannot be fixed with the existing blocks of the process modeling library.
Nevertheless, if you use the pedestrian library, this problem doesn't occur, maybe you can consider using it if the animation is that important, at the cost of processing speed of your model
The only other way to actually do it, is by creating your own Agent-Based model to handle the behavior of agents in a queue, but this is not very straight forward.
Now, if you think about operation time, there is no difference for the process statistics if an agent moves like it does or if it moves to the end of the line, so in terms of results, you shouldn't be worried about it
Related
I have implemented a Device2Device-capable LTE scheduler for the SimuLTE framework for OMNeT++. It needs to reassign resource blocks. In typical LTE networks, each resource blocks is assigned to at most 1 node. With the advent of D2D, uplink resource blocks can be reassigned to D2D users.
The simulator knows both resource blocks and bands. A band is a logical collection of transmission frequencies. If numBands == numRBs then each band corresponds to one resource block.
So to try things out, I set numRbs = 1 = numBands and have two nodes. My scheduler simply assigns the first band to the first node, and then attempts to reassign the same band to the second node. The SchedulingResult tells me I should TERMINATE here - which seems like reassignment is not supported at all.
However, both nodes transmit UDP packets and if I run the simulation to the end, I find that both actually got to send out the same number of packets. Going through the logs I find that every 5th scheduling round (the number 5 might be specific to my setup), the second node still gets the TERMINATE answer, but is granted a resource block anyway. This seems to happen within the eNodeB Main Loop. How, why, what's going on? Does anyone know?
Turns out that one of the two notions of bands and resource blocks are obsolete and likely to be removed in a later version. Users of the framework should set numBands==numRBs! The number of resource blocks is absolute, so this means that per band there's going to be one resource block available.
Note that band reassignment is not currently supported. Trying to do so will always end in the TERMINATE answer as described in the question, because there's a check that makes sure that the number of unassigned resource blocks is >0, which is not true if the band has already been assigned (and therefore the resource block linked to it).
I am learning Paxos algorithm (http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf) and there is one point I do not understand.
We know that events follow a timely order, and it happens when, say, events 1-5 and 10 are decided, but 6-9 and 11 thereafter are not yet. In the paper above, it says we simply fill in the gap between 6-9 with no-op values, and simply record new events from 11 and on.
So in this case, since event 10 is already recorded, we know some kinds of events must have happened between 5 and 10 but are not recorded by Paxos due to some failures. If we simply fill in no-op values, these events will lost in our recording.
Even worse, if, as the paper I linked above says, events are in fact commands from the client, then missing a few commands in the middle might make the entire set of operations illegal (if none of the commands can be skipped or the order of them matters).
So why is it still legit for Paxos to fill no-op values for gaps between events? (If the entire set of records might be invalid because of no-op values as I concerned above.) Also, is there a better way to recover from such gaps instead of using no-op?
This is a multi-part answer.
Proposing no-op values is the way to discover commands that haven't got to the node yet. We don't simply fill each slot in the gap with a no-op command: we propose each slot is filled with a no-op. If any of the peers have accepted a command already, it will return that command in the Prepare-ack message and the proposer will use that command in the Accept round instead of the no-op.
For example, assume a node was behind a temporary network partition and was unable to play with the others for slots 6-9. It knows it missed out upon learning the command in slot 10. It then proposes no-ops to learn what was decided in those slots.
Practical implementations also have an out-of-band learning protocol to learn lots of transitions in bulk.
A command isn't a command until it is fully decided; until then it is just a proposed command. Paxos is about choosing between contending commands from multiple clients. Clients must be prepared to have their commands rejected because another client's was chosen instead.
Practical implementations are all about choosing the order of client commands. Their world view is that of a write-ahead log, and they are placing the commands in that log. They retry in the next slot if they're command wasn't chosen. (There are many ways to reduce the contention; Lamport mentions forwarding requests to a leader, such as is done in Multi-Paxos.)
Practical systems also have some means to know if the command is invalid before proposing it; such as knowing a set of reads and a set of writes. This is important for two reasons. First, it's an asynchronous, multi-client system and anything could have changed by the time the client's command has reached the server. Second, if two concurrent commands do not conflict then both should be able to succeed.
The system model allows commands (messages) to be lost by the network anyway. If a message is lost, the client is expected to eventually retry the request; so it is fine to drop some of them. If the commands of a client have to executed in client order, then either the client only sends commands synchronously; or the commands have to be ordered at a higher level in the library and kept in some client-session object before being executed.
AFAIK the Zab protocol guarantees client-order, if you don't want to implement that at a higher level.
I am not clear on the idea of a Queue. It seems that this term is ambiguous or at least I am confused about it.
While it seems that the most common explanation of a queue (e.g. in wikipedia) is that it is an Abstract Data Type that adheres to the FIFO principle, in practice this term appears to have a broader meaning.
For example, we have
Priority Queues where each item is retrieve according to a priority,
we have a stack which also is a form of inverse queue (LIFO),
we have message queues, which seem to be just a list of items with no
ordering, there by classifying a simple list as a queue etc
So could someone please help me out here on why exactly a queue has so many different meanings?
A queue is inherently a data structure following the FIFO principle as its default nature.
Let us treat this queue as a queue in our natural day-to-day lives. Take an example of a queue on the railway station for purchasing tickets.
Normal queue: The person standing front-most in the queue gets the ticket, and any new person arriving stands at the end of the queue, waiting for his turn to get a ticket.
Priority queue: Suppose you are a VIP standing in the middle of that queue. The ticket vendor immediately notices you, and calls you to the front of the queue to get your tickets, even though its not your turn to purchase. Had you not been important, the queue would have kept playing its usual role, but as soon as any element is considered more important than the other, its picked up, irrespective of its position in the queue. But otherwise, the default nature of the queue remains the same.
Stack: Let's not confuse it with the queue at all. The purpose of the stack is inherently different from that of a queue. Take an example of dishes washed and kept in your kitchen, where the last dish washed is the first one to be picked for serving. So, stack and queue have a different role to play in different situations, and should not be confused with each other.
Message queue: As is the case with priority queue, the default nature of this queue is that the message that comes first is read first, while the upcoming messages line up in the queue waiting for their turn, unless a message is considered more important than the other and is called to the front of the queue before its usual turn.
So, the default nature of any type of queue remains the same, it continues to follow its FIFO principle unless its made to do otherwise, in special circumstances.
Hope it helps
In general, a queue models a waiting area where items enter and are eventually selected and removed. However, different queues can have different scheduling policies such as First-In-First-Out (FIFO), Last-In-First-Out (LIFO), Priority, or Random. For example, queueing theory addresses all of these as queues.
However, in computer science/programming, we typically use the word "queue" to refer specifically to FIFO queues, and use the other words (stack, priority queue, etc.) for the other scheduling policies. In practice, you should assume FIFO when you hear the word queue, but don't completely rule out the possibility that the speaker might be using the word more generally.
As an aside, similar issues arise with the word "heap" which, depending on context, might refer to a specific implementation of priority queues or to priority queues in general (or, in a mostly unrelated meaning, to an area of memory used for dynamic allocation).
Priority Queue: Its not a queue. Take a look: http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html it does not implement the Queue interface.
Stack: Its not a queue. Take a look: http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html it does not implement the Queue interface.
Message queue: I do not know what it is.
Queue: Queue has only one meaning, whoever comes first also get served first.
Queue ADT: It is an interface, meaning it has bunch of functions. Most common ones: add-adds to the end of the line, remove-removes from the beginning of the line. http://docs.oracle.com/javase/7/docs/api/java/util/Queue.html
I am using the Birman-Schiper-Stephenson protocol of distributed system with the current assumption that peer set of any node doesn't change. As the protocol dictates, the messages which have come out of causal order to a node have to be put in a 'delay queue'. My problem is with the organisation of the delay queue where we must implement some kind of order with the messages. After deciding the order we will have to make a 'Wake-Up' protocol which would efficiently search the queue after the current timestamp is modified to find out if one of the delayed messages can be 'woken-up' and accepted.
I was thinking of segregating the delayed messages into bins based on the points of difference of their vector-timestamps with the timestamp of this node. But the number of bins can be very large and maintaining them won't be efficient.
Please suggest some designs for such a queue(s).
Sorry about the delay -- didn't see your question until now. Anyhow, if you look at Isis2.codeplex.com you'll see that in Isis2, I have a causalsend implementation that employs the same vector timestamp scheme we described in the BSS paper. What I do is to keep my messages in a partial order, sorted by VT, and then when a delivery occurs I can look at the delayed queue and deliver off the front of the queue until I find something that isn't deliverable. Everything behind it will be undeliverable too.
But in fact there is a deeper insight here: you actually never want to allow the queue of delayed messages to get very long. If the queue gets longer than a few messages (say, 50 or 100) you run into the problem that the guy with the queue could be holding quite a few bytes of data and may start paging or otherwise running slowly. So it becomes a self-perpetuating cycle in which because he has a queue, he is very likely to be dropping messages and hence enqueuing more and more. Plus in any case from his point of view, the urgent thing is to recover that missed message that caused the others to be out of order.
What this adds up to is that you need a flow control scheme in which the amount of pending asynchronous stuff is kept small. But once you know the queue is small, searching every single element won't be very costly! So this deeper perspective says flow control is needed no matter what, and then because of flow control (if you have a flow control scheme that works) the queue is small, and because the queue is small, the search won't be costly!
My company currently services their clients using a Windows-based fat-client app that has workflow processing embedded in it. Basically, the customer inserts a set of documents to the beginning of the workflow, the documents are processed through a number of workflow steps and then after a period of time the output is presented to the customer. We currently scale up for larger customers by installing the application on other machines and let the cluster of machines work on different document subsets. Not ideal but with minimal changes to the application it did allow us to easily scale up to our current level.
The problem we now face is that as our customers have provided us with larger document sets we find ourselves spending more than expected on machines, IT support, etc... So, we have started to think about re-architecting the platform to make it scaleable. A feature of our solution is that each document can be processed independently of one another. Also we have 10 workflow steps of which two of the steps take up about 90% of the processing time.
One idea we are mulling over is to add a workflow step field to the document schema to track which workflow step has been completed for the document. We can then throw the entire cluster of machines to work on a single document set. A single machine would not be responsible for sequentially processing a document through all workflow steps but queries the db for the next document/workflow step pair and perform that processing. Does this sound like a reasonable approach? Any suggestions?
Thanks in advance.
While I'm not sure what specific development environment you are working with, I have had to deal with some similar workflows where we have a varied number of source documents, various steps, etc. all with different performance characteristics.
Assuming you have a series of independent steps - i.e. Step A's work product is the input for Step B, and step B's product is the input for step C, etc. I would look at message queueing as a potential solution.
For example, all new documents are tossed into a queue. One or more listener apps hit the queue and grab the next available document to perform step A. As step A completes, a link to the output product and/or relevant data are tossed into another queue. a separate listener app pulls from this second queue into step B, etc. until the final output product is created.
In this way, you use one queue for the holding area between each discreet step, and can scale up or down any individual process between the queues.
For example, we use this to go from some data transformations, through a rendering process, and out to a spooler. The data is fast, the renderings are CPU bound, and the printing is I/O bound, but each individual step can be scaled out based on need.
You could (technically) use a DB for this - but a message queue and/or a service bus would likely serve you better.
Hopefully that points you in the right direction!