Skip to content

Undesired sub-trajectory behavior #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mmarks13 opened this issue Apr 27, 2017 · 7 comments
Closed

Undesired sub-trajectory behavior #91

mmarks13 opened this issue Apr 27, 2017 · 7 comments
Labels

Comments

@mmarks13
Copy link

I have put together some example code to reproduce the issue I'm having. In an attempt to keep my code clean, I have set up multiple sub-trajectories; however, as you can see by the output, the arrivals don't continue on the trajectory from which they started, after going down a shared sub-trajectory. It seems as though all arrivals continue down the trajectory of the first arrival to hit the sub-trajectory (see logging).

#'#Define Case Paths

#Trajectory to send signal to start Milling. 
#In real life milling starts at the end of the day and runs overnight. 
Milling_Start <- trajectory() %>%
  log_("Start_Milling") %>%
  send("Start_Milling")

#'##sub-paths for parts of the process with more detail or shared trajectories across materials

Milling_SubTraj <-   trajectory("Milling_SubTraj") %>%
  #When Start_Mill signal is sent, all cases in wait() will be sent here.
  trap("Start_Milling",
       handler =
         trajectory () %>%
         set_capacity("Mill",5) %>% #temporarily set capacity equal to 5 as another way to do batching.
         seize("Mill", 1) %>%
         timeout(10) %>%
         set_capacity("Mill",0) %>% #set capacity to zero to prevent more cases from moving through.
         release("Mill", 1)
  ) %>%
  #Upon a signal reception, the arrival stops the current waiting activity and executes the handler if provided. Then, the execution returns to the activity following the point of the interruption:
  wait() %>%
  #if a case has gotten here, Milling is complete. Unsubscribe the case from the Start_Milling signal.
  untrap("Start_Milling") %>%
  log_(function(attrs) paste("done milling - material", attrs[["material"]],sep=''))


#'##Path for each material##
Material1 <- trajectory("Material1_Path") %>%
  set_attribute("material", 1) %>%
  log_("Entering Milling on Material1 trajectory") %>%
  join(Milling_SubTraj) %>%
  log_("Exiting Milling on Material1 trajectory")


Material2 <- trajectory("Material2_Path") %>%
  set_attribute("material", 2) %>%
  log_("Entering Milling on Material2 trajectory") %>%
  join(Milling_SubTraj) %>%
  log_("Exiting Milling on Material2 trajectory")


Material3 <- trajectory("Material3") %>%
  set_attribute("material", 3) %>%
  log_("Entering Milling on Material3 trajectory") %>%
  join(Milling_SubTraj) %>%
  log_("Exiting Milling on Material3 trajectory")



#'Overall Path
#'build overall path based on the pct of each material coming into the system. The case will go down a trajectory based on the material prob. 
Overall_Path <- trajectory() %>%
  #'branch to different materials
  branch(function() sample(c(1,2,3),1,replace=TRUE,prob= c(.33,.33,.33)),continue=c(T,T,T),
         Material1,
         Material2,
         Material3) 



#'#Run Simulation
#############################################################################

runtime <- 30 #minutes

env <- simmer()
env %>%
  add_resource("Mill", 5) %>%
  add_generator("Case", Overall_Path,at(1,2,3,4,5), mon = 2) %>%
  add_generator("Milling_Start", Milling_Start, at(10)) %>%
  run(runtime)



#All cases continue after milling on the trajectory of the first case to enter the milling trajectory.  
># 1: Case0: Entering Milling on Material1 trajectory
># 2: Case1: Entering Milling on Material3 trajectory
># 3: Case2: Entering Milling on Material2 trajectory
># 4: Case3: Entering Milling on Material2 trajectory
># 5: Case4: Entering Milling on Material1 trajectory
># 10: Milling_Start0: Start_Milling
># 20: Case0: done milling - material1
># 20: Case1: done milling - material3
># 20: Case2: done milling - material2
># 20: Case3: done milling - material2
># 20: Case4: done milling - material1
># 20: Case0: Exiting Milling on Material1 trajectory
># 20: Case1: Exiting Milling on Material1 trajectory
># 20: Case2: Exiting Milling on Material1 trajectory
># 20: Case3: Exiting Milling on Material1 trajectory
># 20: Case4: Exiting Milling on Material1 trajectory
># simmer environment: anonymous | now: 20 | next: 
># { Resource: Mill | monitored: 1 | server status: 0(0) | queue status: 0(Inf) }
># { Generator: Case | monitored: 2 | n_generated: 5 }
># { Generator: Milling_Start | monitored: 1 | n_generated: 1 }

@Enchufa2 Enchufa2 added the bug label Apr 27, 2017
@Enchufa2
Copy link
Member

Thanks for the report. The problem is that the handler is not being cloned. A smaller reproducible example:

a <- trajectory(verbose = TRUE) %>% 
  trap("asdf",
       handler=
         trajectory(verbose = TRUE) %>% 
         timeout(1)
  )
a
#> trajectory: anonymous, 2 activities
#> { Activity: Trap         |         0 <- 0x431f5e0 -> 0         | signals: [asdf] }
#>   Fork 1, stop,  trajectory: anonymous, 1 activities
#>   { Activity: Timeout      | 0x431f5e0 <- 0x443dd20 -> 0         | delay: 1 }
a$clone()
#> trajectory: anonymous, 2 activities
#> { Activity: Trap         |         0 <- 0x3ead180 -> 0         | signals: [asdf] }
#>   Fork 1, stop,  trajectory: anonymous, 1 activities
#>   { Activity: Timeout      | 0x3ead180 <- 0x443dd20 -> 0         | delay: 1 }

The pointer to the timeout activity, 0x443dd20, should change.

@Enchufa2
Copy link
Member

Try now with the current master version, please.

@mmarks13
Copy link
Author

I'm sorry, but I don't understand. Based on my understanding of your reply, I made the following changes and am getting the same results. Can you please elaborate and/or point me towards some documentation that could help me understand? Thank you!

#'#Define Case Paths
#############################################################################################################

#Trajectory to send signal to start Milling. 
#In real life milling starts at the end of the day and runs overnight. 
Milling_Start <- trajectory() %>%
  log_("Start_Milling") %>%
  send("Start_Milling")

#'##sub-paths for parts of the process with more detail or shared trajectories across materials

Milling_SubTraj <-   trajectory("Milling_SubTraj",verbose = T) %>%
  #When Start_Mill signal is sent, all cases in wait() will be sent here.
  trap("Start_Milling",
       handler =
         trajectory (verbose = T) %>%
         set_capacity("Mill",5) %>% #temporarily set capacity equal to 5 as another way to do batching.
         seize("Mill", 1) %>%
         timeout(10) %>%
         set_capacity("Mill",0) %>% #set capacity to zero to prevent more cases from moving through.
         release("Mill", 1)
  ) %>%
  #Upon a signal reception, the arrival stops the current waiting activity and executes the handler if provided. Then, the execution returns to the activity following the point of the interruption:
  wait() %>%
  #if a case has gotten here, Milling is complete. Unsubscribe the case from the Start_Milling signal.
  untrap("Start_Milling") %>%
  log_(function(attrs) paste("done milling - material", attrs[["material"]],sep=''))


#'##Path for each material##
Material1 <- trajectory("Material1_Path") %>%
  set_attribute("material", 1) %>%
  log_("Entering Milling on Material1 trajectory") %>%
  join(Milling_SubTraj$clone()) %>%
  log_("Exiting Milling on Material1 trajectory")


Material2 <- trajectory("Material2_Path") %>%
  set_attribute("material", 2) %>%
  log_("Entering Milling on Material2 trajectory") %>%
  join(Milling_SubTraj$clone()) %>%
  log_("Exiting Milling on Material2 trajectory")


Material3 <- trajectory("Material3") %>%
  set_attribute("material", 3) %>%
  log_("Entering Milling on Material3 trajectory") %>%
  join(Milling_SubTraj$clone()) %>%
  log_("Exiting Milling on Material3 trajectory")



#'Overall Path
#'build overall path based on the pct of each material coming into the system. The case will go down a trajectory based on the material prob. 
Overall_Path <- trajectory() %>%
  #'branch to different materials
  branch(function() sample(c(1,2,3),1,replace=TRUE,prob= c(.33,.33,.33)),continue=c(T,T,T),
         Material1,
         Material2,
         Material3) 



#'#Run Simulation
#############################################################################################################

runtime <- 30 #minutes

env <- simmer()
env %>%
  add_resource("Mill", 5) %>%
  add_generator("Case", Overall_Path,at(1,2,3,4,5), mon = 2) %>%
  add_generator("Milling_Start", Milling_Start, at(10)) %>%
  run(runtime)


#All cases continue after milling on the trajectory of the first case to enter the milling trajectory.

@Enchufa2
Copy link
Member

Sorry, you don't need to change your code. Forget my first message, I was simply pointing at the cause of the bug for my own record. The bug should be solved with the last patch, so you need to reinstall the package from GitHub with devtools:

devtools::install_github("r-simmer/simmer")

And then try your code again, please.

@mmarks13
Copy link
Author

That worked. Thank you!

When can we expect to see this in CRAN? I've got a few other people using this package at our company.

@Enchufa2
Copy link
Member

Yes, you can, eventually. Now that the package is mature enough, I'm trying to establish a reasonable release cycle, i.e., a new release every two/three months. Given that the last release was about a month ago, this patch will reach CRAN in a month or two. In the meantime, please tell your colleagues to reinstall from GitHub whenever this feature is critical.

Thanks again for the report.

@mmarks13
Copy link
Author

Great! Thank you for your prompt reply and your work on this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants