1

I'd like to code a simulation where all Items (A, B, C, ...) arriving are first disassembled into 2 parts. Item.subpart1 undergoes OPERATION1 directly and Item.subpart2 is collected in a batch (size = 4) before being processed with OPERATION2. After processing, I want all parts of the same item to be reassembled and not mixed with parts from other items (ie, subpart1 from A goes with subpart2 from A only).

I've tried parallel tasks to split the subparts trajectories and also tried to collect all Items.subparts2 in a batch of size 4.

library(simmer)
library(simmer.plot)
library(simmer.bricks)

items <- LETTERS[1:10]

traj <- function(item) {
  trajectory() %>%
    visit("operator", 10, 1) %>%    # disassemble the incoming item 
    set_global(paste0("subpart1_", item), 1) %>%
    set_global(paste0("subpart2_", item), 1) %>%
    set_global("CountSubparts2", mod ="+", 1) %>%

    do_parallel(
      # OPERATION 1
      trajectory() %>%
        visit("Machine1", 150, 1) %>%
        set_global(paste0("subpart1_", item), 0) %>%
        set_global(paste0("subpart1_", item, "_processed"), 1)
      ,
      # OPERATION 2
      trajectory() %>%
        batch(n = 4, timeout = 0, name = "POOL_PARTS") %>%
        separate() %>%
        visit("Machine2", 200, 1) %>%
        set_global(paste0("subpart2_", item, "_processed"), 1)  %>%
        set_global("CountSubparts2", 0) 
      , .env = env, wait = TRUE
    ) %>%
    visit("operator", 10, 1)    # reassemble the items
}    

env <- simmer()
env %>%
  add_resource("operator", 1) %>%
  add_resource("Machine1", capacity = 1, queue_size = 0, 2) %>%
  add_resource("Machine2", capacity = 1, queue_size = 0, 1)

for (i in items) env %>%
  add_generator(i, traj(i), at(0), mon = 2)

env %>% run(1000)

ressources <- get_mon_resources(env)
ressources %>% plot(metric = "utilization")
ressources %>% plot(metric = "usage")

attributs <- env %>% get_mon_attributes()  
attributs  %>% plot(key = "CountSubparts2")

The problem is : First, I expected CountSubparts2 to increase up to 4 and then decrase to 0 after OPERATION 2. Here, CountSubparts2 keeps increasing. Second, I can't find a way to explicitly tell simmer to : "reassemble subpart1_A_processed and subpart2_A_processed. Do the same for B, C,etc."

What am I missing ?

Thank you for your help !

  • You missed a `-` in the second `set_global` for `CountSubparts2`. And I'm not sure I understand your second question. When your parts leave the trajectory, they are reassembled, right? That's recorded in the `end_time`. – Iñaki Úcar Nov 13 '19 at 22:44
  • Thank you for your reply ! Concerning my first question, I've changed the set_global statement to 0, to empty the batch after OPERATION 2, but I'm still missing thomething. In fact, CountSubparts2 has nothing to do with the simulation. I added it as a counter for debugging purpose. OPERATION2 seems to be blocked until the end of the simulation and all the Subpart2_xx keep accumulating in the batch until the end instead of being released 4 by 4. – Arnaud Coqueblin Nov 14 '19 at 20:45
  • For my second question, I guess the subparts are indeed reassembled at the end of the simulation, but I would like to keep track of the assembly/reassembly process with the get_attribute function : for example, item A arrives at t=0, is disassembled at t=10, and reassembled at t=xx, and so on. How can I set a global attribute programmatically after OPERATION1 and 2 ? To do this, I would have to tell simmer something like "if (subpart1_A_processed == 1 & subpart2_A_processed == 1) set_global("A_reassembled", 1)". But I would have to write smthg similar for every item. Is there a simpler way ? – Arnaud Coqueblin Nov 14 '19 at 21:01

1 Answers1

0

I think your simulation model works ok. You have a couple of issues:

  1. The first issue is with the counter. You need to use set_global("CountSubparts2", mod="+", -1) to decrement the counter. You will see it go down once, basically because you've set queue_size=0 in your machines, so only one item makes it to the end of the simulation, and the rest of them are rejected.
  2. do_parallel with wait=TRUE ensures that the first subpart waits for the other to be machined, and then only the original arrival reaches the final operator. So just add set_global(paste0(item, "_reassembled"), mod="+", 1) at the end of the trajectory and you're good to go.
Iñaki Úcar
  • 935
  • 1
  • 5
  • 11
  • Thank you so much for your help. The simulation works fine, but still not quite as I wanted. The variable "CountSubparts2" is decreasing (-1) just once, and when I change queue_size=Inf, it decreases (-1) 4 times (A, then B, then C, then D, that's what I see with get_mon_arrivals(env, per_resource = TRUE) ). I'd like to see "CountSubparts2" decrease (-4) several times, till 0, ie (ABCD then EFGH then IJ). Machine2 is supposed to operate on batches of 4. I'm working on another solution for OPERATION2 as a seperate generator activated when CountSubparts2 == 4. I'll post it when I'm done. – Arnaud Coqueblin Nov 20 '19 at 06:51
  • Apart from setting the queues to Inf, you need to run the simulation for a longer time to see the counter decrease. And it will decrease to 2, not to zero. Why? You are putting 10 parts (from A0 to J0) in the trajectory, so you see the count going up to 10. But then, you process subparts in batches of 4. 4 + 4, the counter goes down to 2, and the remaining 2 parts are stuck in the batch because no other subparts arrive. – Iñaki Úcar Nov 20 '19 at 15:25