question

Ruben Mariduena avatar image
1 Like"
Ruben Mariduena asked Jason Lightfoot commented

How to create activity sequences based on availability rather than a set order?

Please see graph attached (non-sequential-inspections.png). I'm trying to create an inspection process in Process Flow where instead of having a set order for the inspections (A then B then C), the inspections are completed based the availability of the specialized workers. There are 3 inspections that need to be completed on each of the pieces but they are not dependent of each other, meaning the can be done in any order. While inspection A is being done on piece 1, Inspection B can be done on piece 2 without piece 2 having had inspection A done on it yet. Inspection B can go back to piece 1 once its free and inspections A can go to piece 3 if piece 2 is busy with inspection C. The reason for this is that workers are not waiting on each other to perform their specific inspections on pieces and can streamline the process. Is this possible?

FlexSim 18.0.3
process flowsequences
5 |100000

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

Cliff King avatar image
1 Like"
Cliff King answered Jason Lightfoot commented

I used a process flow list representing each of the flow items to be inspected and the remaining inspections required on each one ("InspA", "InspB" and "InspC"). As inspections are performed, I reset the corresonding label on the item to 0.

I used a General ProcessFlow to represent the items needing inspection, and a Task Executer ProcessFlow to represent the tasks of an inspector that I attached (i.e. instantiated) to each of the five operators in the 3D model.

As an operator finishes the tasks associated with inspecting a single item, it pulls another item from the list that needs an inspection type matching the type of operator. I put a label on each of the five operator called InspType that indicates which type of inspection the particular operator can perform (i.e. "InspA", "InspB" and "InspC"). Every flow item has three labels by these same names and the value of labels is either a 1 indicating it still needs that type of inspection or a 0 meaning that inspection has already been performed.

The "Pull Item from List" activity uses a query to decide which item to pull from the list and inspect next. I had some fun experimenting with the query and observing the difference in model performance. In the attached model, the query currently reads "WHERE token.InspLabel ORDER BY (InspA + InspB + InspC)" so that the operators will choose to inspect items that already have some inspections done on them ahead of items with no inspections done yet. You might try removing the ORDER BY part and compare.

Let me know if you need anything explained in the model.

inspabc.fsm


inspabc.fsm (61.8 KiB)
· 4
5 |100000

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

Ruben Mariduena avatar image Ruben Mariduena commented ·

Thank you for the solution, I just implemented it in my model and it worker great. The only question I have is in the "Decide (another inspection needed?)" activity. With the code that is there how does this work to make the model know is true or false situation? I also see a similar situation in the "pull item from list" where it doesn't pull a value if it has a value of zero in the specific column. I'm just trying to understand how does the program analyze these situations to know what it needs to do.

0 Likes 0 ·
Cliff King avatar image Cliff King Ruben Mariduena commented ·

Let me try and explain...

This is the condition I used in the decide activity:

token.ItemToInspect.InspA + token.ItemToInspect.InspB + token.ItemToInspect.InspC

To understand this full expression, we first need to understand its parts. In this TaskExecuter ProcessFlow, a single token is created for each instance of the flow that I have attached to each of the Operators in the model. I use the token to step through the tasks that I want an operator to do during the simulation. The same token keeps looping through the process flow for a specific operator throughout the simulation.

In the "Pull Item from List" activity, I get a reference to the actual flow item in the 3D model associated with the line item I pull from the List and record it on the token's ItemToInspect label. Therefore, the expression token.ItemToInspect will give me a direct reference to the flow item in the 3D model that the operator just chose to inspect.

The expression token.ItemToInspect.InspA gets me the value of the flow item's label named InspA. The three labels named InspA, InspB and InspC were initially set on each of the 20 flow items created in the model by the Schedule Source activity in the other ProcessFlow. All three label values were initially set to a value of 1. The "Push Item to List" activity in that same ProcessFlow is what created our initial list of flow items and corresponding columns for each of the three labels on the items. A value of 1 for these labels/columns indicates that the flow item needs that particular test conducted. A value of 0 indicates that the test has already been conducted.

OK, so back to the conditional expression, what does it mean? First of all, you need to know that any nonzero value for a conditional expression in the software indicates a "true" result, and a zero value indicates a "false" result. In my conditional expression, I added up the values of all three inspection labels (InspA + InspB + InspC), because I want the expression to be true if any of the inspection labels is still a 1.

There are a couple other key concepts you may want to understand in order to grasp what's going on here. First of all, it's important to understand that "current" is a direct pointer to the operator that is attached to the TaskExecuter process flow.

Outside the looping part of the TaskExecuter process flow, I use a Scheduled Source to create a single token, and then in the Assign Labels activity I create two labels on the token as follows:

The InspLabel's value is a string concatenation of "Insp" and the value of the InspType label of the current operator. If you take a look at the labels of the operators, you notice I gave each of them an InspType label with string value of "A", "B", or "C" depending on the type of inspection the operator is supposed to do. Therefore, the token in this TaskExecuter process flow will have an InspLabel with a string value of either "InspA", "InspB" or "InspC". Don't get this confused with the labels I put on the flow items in the model by those same names. I simply plan on using the InspLabel of the token to tell me which of the three labels on the flow items I'm concerned with when attempting to pull work from the List for the current operator who just cares about doing one type of inspection! You'll see how this gets used in the definition of the next label.

The second label I assign to the token I named Query and it will be used to define the actual SQL query in the "Pull Item from List" activity. Rather than write the query on the pull from list activity, I decided to write the query expression on a label of the token for effeciency reasons and use the label as the query. This way the query expression wouldn't need to be built (via concatenation) every time the token looped around the process flow again.

If you open the code window for the value I assign to the Query label, this is what you'll see:

Line 10 shows you the string concatenation I use to build the query expression. When this expression is evaluated for OperatorA1 or OperatorA2 (who both have an "A" for their InspType label and therefore the InspLabel label of the token will be "InspA"), the expression will be: "WHERE InspA ORDER BY (InspA + InspB +InspC)".

The part that comes directly after the WHERE is a lot like a conditional expression in that it will be true for any nonzero value. Well if the InspA column in the List contains a value of 1 then it will be true and the item will be pulled from the list when the query is evaluated by the "Pull Item from List" activity.

Hopefully my long dialog makes some since to you. Let me know if you still have questions.

0 Likes 0 ·
Ruben Mariduena avatar image Ruben Mariduena Cliff King commented ·

It made perfect sense, the parts I didn't know were that the zero and non-zero values already meant "false" and "true" results in the software and how they could also be applied as pull conditions. Thank you for the explanation.

0 Likes 0 ·
Jason Lightfoot avatar image Jason Lightfoot ♦♦ commented ·

This solution doesn't scale well - please refer to this post for one that does.

0 Likes 0 ·
Kari Payton avatar image
0 Likes"
Kari Payton answered Ruben Mariduena commented
@Ruben Mariduena

One way I can think of is to use a few conditional decides along with a global table and resources. In the example, there's an individual flow for each item but it's the same logic repeated. This is so that the item can only be inspected by one operator at a time.

The first decide is to see if the item has been inspected by that inspector. So it looks at a table and see's if it's a 1 (yes) or 0 (no) for that inspector. If yes it then checks if the inspector is free. If yes the inspection happens and the table value is changes to 1. If no then it moves on to the next process. Then at the end there's a check if all inspections are done. If yes then it ends of no then it loops through again to find which inspection hasn't been done. Hope this helps answer the question! inspection-example.fsm


· 1
5 |100000

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

Ruben Mariduena avatar image Ruben Mariduena commented ·

Thank you for your answer Kari. This would have worked if I had a small amount of items to inspect but in my case is in the thousands so it would have been hard to create a column for each.

0 Likes 0 ·