question

Chandler avatar image
1 Like"
Chandler asked Chandler commented

(HC) Queue for multple processes, do first available, but remain in queue?

I am completing some model logic and need to find a better solution for something.

Currently, at registration/triage, my patients get a list of the imaging types that they will need. Once they get to the imaging process group they go through a sequence of Decide components that checks whether they need certain imaging processes.

  • 1.1 They check to see if they need an imaging step.
    • a. If they don't need that one, they will proceed to check the next imaging process
    • b If they do need that one they branch off
      • i. If they succeed at acquiring the resource, they go through the process and the imaging tyoe is removed from their list
      • ii. If they fail at acquiring the resource, they bounce back out and move to check for the next process. (2.1, 3.1...)
  • 2. If they do not need any or fail to acquire all imaging, they check to see if they still need any imaging.
    • a. If they do, they go back through this loop
    • b. If they don't (imaging all complete), they exit the loop.

What I need is a way to have a patient who needs an imaging process but fails to acquire it to remain in the queue (but still advance to check for the next imaging. If Xray is backed up but CT is free, we need to have the patient do CT while waiting for xray)

I would think that this is managed in a list for each imaging room... on a failed acquire, the token is pushed to the list. At the same time, all attempts to acquire can only succeed/be made by the person who is last on the list. (It has to be their turn)

I think I could make that logic, but I think it's odd that I can't push to the end of a list with built in components and I wonder if it's a signal that I'm thinking about this wrong.

  • I'd rather say: if patient == list[1]
  • than: if patient == list[list.length]

--

Would a global list be the correct way to manage this? Do I need to create a child token to sit in the queue?

Thanks!

FlexSim 23.1.1
healthcarelistsqueuing
· 7
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Julie Weller avatar image Julie Weller commented ·

Hi @Chandler! Maybe instead on thinking about pushing onto a list in order (which by default I'm not sure that they have an order at all), I would consider pulling based on the age of the token. That label is automatically built into a global list, and you could just query the list based on the age (you can change it to ASC or DESC based on if you want the oldest person on the list or the newest). The trickiest part would be the fact that lists require the token to stay there. You could experiment with using a max wait timer and the leave on list option. Another idea, would be to create a child token like you suggested.

Another idea would be to use an array and adding the patient to the end. That would be another way to allow you to maintain the order they were added and wouldn't require a child token. However, it would mean you'd need to check if the object is currently busy before popping it off the array, but you'd have to do that with a list too...

Do you think that would work for you? It's hard to know for sure without being able to experiment on the model :)

1 Like 1 ·
Chandler avatar image Chandler Julie Weller commented ·
Yes I think that would work. (Sorry I haven't shared a model - I wanted to try to get this question out quickly and didn't have time to cull our client info from the model for posting)


To be clear? Are you describing an SQL order by query? (I'd like to make an attempt and if it's not working out I can save out a model of the relevant content.)

0 Likes 0 ·
Chandler avatar image Chandler Chandler commented ·
Oh I just realized, if I understand you correctly, using the age of the token wouldn't work unless I do create a child token to push to the list, which seems unnecessary. Perhaps I'm wrong about that though.


Just some more thoughts...

The push to list activity has an option to insert at the front of the list ... by default working as a stack. I could also do that by using a label on the imaging resource.

0 Likes 0 ·
Show more comments
Show more comments
Felix Möhlmann avatar image Felix Möhlmann commented ·
I have a question that my answer would depend on. In your example of the patient first doing CT while waiting for Xray, could another patient acquire and start the Xray while the first patient is doing CT? Or should the Xray be acquired by the first patient as soon as it becomes available and stay idle until the CT is done?
1 Like 1 ·
Chandler avatar image Chandler Felix Möhlmann commented ·
That's an insightful question!


Yes, I would like for people who are currently engaged in another imaging process to be allowed to be skipped over for another process, exactly as you described, so they don't tie up all of the processes at once.

My needs in order:

  1. First - to allow queuing and get the oldest request to always acquire and process first.
  2. Then - Allow other patients to always skip over the oldest request if the person who made it is busy.
  3. Finally - Control when a newer request is allowed to skip:
    1. Patient A is in Xray and has the oldest request for CT. We could check some parameters for Patient A (acuity, or the processing time of Xray), and then allow or deny Patient B to skip past them based on those conditions.
If it's simple enough to address all of these at the same time, then I'm open to that.
0 Likes 0 ·

1 Answer

Felix Möhlmann avatar image
1 Like"
Felix Möhlmann answered Chandler commented

My thoughts on this:

The third point from your comment is what makes this somewhat tricky. Since a 'better' patient might arrive, a location should only ever get acquired by a patient that can start to use it immediately. With a list, you would have to keep track of the current 'best' candidate, who gets to acquire the location as soon as both him and the location are free.

Keeping track of that best candidate doesn't really get any easier by using a list. So in the attached model I don't actually use any list.

A patient token creates a child token for each process the patient has to go through. These run through a subflow where they first check if the respective location is currently available (denoted by a label on the location object). Either because nobody has reserved it yet or because the new patient has a higher "Acuity" value than the one that current is pending to use the location.

If the location is available the token can continue. It has to enter a zone that only lets a single token per patient enter at a time. Tokens that wait in the "Enter Zone" activity can thus be preempted by newly arriving patients.

If the location is not available, the token is send to a "Wait for Event" activity (so are tokens that are preempted during their wait to enter the zone). Whenever a patient finishes a process, a message is send to the Process Flow and the tokens that need to acquired that location are released from the "Wait for Event" to try to 'acquire' it again. Another zone orders them by their "StartTime" label (age of the token) and spaces them out using a "Breathe" delay, so any label updates after the check happen before the next token enters the Decide activity.

flexible-process-order-fm.fsm


· 5
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Chandler avatar image Chandler commented ·

Wow! ...that was fun.

I didn't quite understand your approach so I took some time to dissect it. After picking it apart and rebuilding it like this...

1692400621826.png

flexible-process-order-fm_7.fsm

... what you were doing finally clicked, and I see now it's very elegant. (I'm also immediately adopting the practice of using green color to indicate the presence of custom code)

I'm still not certain that it's perfect for my use. For example, I can't check where someone is in the queue, as I can in my version. But the more I refine it the closer I get to what you have built.

I could also see a case in your version where a new token enters the subflow while older tokens are in the wait for event activity, and this happens at the right microsecond, that new token could bypass the queue. (Or is that impossible for a reason I don't know?)

I will continue to solve this challenge and update here when it's resolved! I haven't decided whether it is important enough for me to have the list that I need to develop it further, or just use something like what you have made.

---

For info, here is what my version does:

  1. The token receives the patient's unique ID on a label, and I assign patient.busy = 0
  2. Patients are not in the queue, so they are added.
    1. token.inQueue = 1
    2. A child token is created and pushed to the list, where there are fields for token.Acuity, pushTime, and patient.busy
    3. The child token is added to the parent's list of tokens in queue.
  3. A parent token pulls the top token on the list (but leaves it there)
    1. ORDER BY busy ASC, acuity ASC, pushTime ASC
  4. Check to see if the pulled token is in the parent's list of queued tokens:
    1. Yes: parent attempts to enter the zone.
    2. No: parent waits for its number to be called.
  5. Once in the zone (max 1 token) the parent pulls its child token from the list and removes it. The child is sunk. token.inQueue = 0.
  6. The parent token's label patient.busy = 1, then it processes, then the label is set back to 0.

I had been using a 30 sec inter-arrival source in a general process flow to ping the wait for event with the name of the first patient in the queue, but I changed that to be a message sent by the token after completing a process.

0 Likes 0 ·
Felix Möhlmann avatar image Felix Möhlmann Chandler commented ·
Yes, you are correct. A newly arriving token could potentially skip ahead of the waiting tokens in my model when it enters the subflow in the same instant another token finishes the process.

However, since the walking times and the process time itself are all non-integer values, the chance of a new arrival happening at that exact time should be practically zero if it is not directly triggered by the process finishing.

I guess to be on the safe side, you could set the Wait for Event activity to also trigger whenever a new token enters the subflow, so that the Queue Strategy of the Pull Order zone would come into effect.

0 Likes 0 ·
Chandler avatar image Chandler Felix Möhlmann commented ·
How would you implement this code if the patients are waiting for one of a group of locations instead of for a specific location? Let's say we have two rooms for processNum = 1 - we can't just set the label to "inUse".


I am trying to use a global variable and increment/decrement its value while patients are processing, so instead of checking whether the resource is in use, I'm checking whether the number in the variable is less than the length of the group associated with the location resource.


Is there any way you would recommend instead of that? For example, if global variables are not necessary in this case. I was getting errors when I tried to increment/decrement a value using the set variable activity.

0 Likes 0 ·
Show more comments