How to branch based on which of 2 generators an entity comes from

231 views
Skip to first unread message

L Mico

unread,
May 4, 2016, 1:58:09 PM5/4/16
to simmer...@googlegroups.com
Hi friends, 

I'd like to have two generators (with different probability functions), whose entities go through the same trajectory but branch based on which generator they come from.  I am not sure how to access this info (i.e. which method to use) at the branch point about which gen they came from - in the example they are dogs or cats.   Basic code below, which needs the branch decision function to be modified.  Please let me know if any of this does not make sense.

Thanks & Cheers,

Lindsay 

###########

t0 <- create_trajectory("my trajectory") %>%
        seize("receptionist", 1) %>% #Both dogs and cats go to the receptionist
        timeout(function() max(0,rnorm(1,5,2))) %>%
        release("receptionist", 1) %>%
        ##Here is where I want to branch depending on what generator made the entity
        branch(function() sample(1:2, 1), merge=c(TRUE, TRUE), ##Replace 'sample()' with a new function
                create_trajectory("cats") %>%
                        seize("catDoc", 1) %>%
                        timeout(function() max(0,rnorm(1,30,10))) %>%
                        release("catDoc", 1),
                create_trajectory("cats") %>%
                        seize("dogDoc", 1) %>%
                        timeout(function() max(0,rnorm(1,30,10))) %>%
                        release("dogDoc", 1)
       )

env <- simmer("Lab6") %>%
        add_resource("receptionist", 1) %>%
        add_resource("catDoc", 1) %>%
        add_resource("dogDoc", 1) %>%
        add_generator("cat", t0, function() rexp(1,rate = (1/45)), mon = 2) %>%  
        add_generator("dog", t0, function() rexp(1,rate = (1/30)), mon = 2) %>%
        run(until=720) #720 = 12 hours * 60 min


--
“The time will come when diligent research over long periods will bring to light things which now lie hidden."

Seneca the Younger 

Iñaki Úcar

unread,
May 4, 2016, 3:17:20 PM5/4/16
to simmer-devel

Hi Lindsay,

The whole point behind the concept of trajectory is being a common path for arrivals of the same type. If you have two types of arrivals, cats and dogs, the natural way to model this problem with simmer is having two distinct trajectories, because they do different things even though they share some activities. In terms of your example,

t.cat <- create_trajectory("cat") %>%
  seize("receptionist", 1) %>% #Both dogs and cats go to the receptionist

  timeout(function() max(0,rnorm(1,5,2))) %>%
  release("receptionist", 1
) %>%
  seize("catDoc", 1) %>%
  timeout(function() max(0,rnorm(1,30,10))) %>%
  release("catDoc", 1)

t.dog <- create_trajectory("dog") %>%
  seize("receptionist", 1) %>% #Both dogs and cats go to the receptionist

  timeout(function() max(0,rnorm(1,5,2))) %>%
  release("receptionist", 1
) %>%
  seize("dogDoc", 1) %>%
  timeout(function() max(0,rnorm(1,30,10))) %>%
  release("dogDoc", 1)

env <- simmer("Lab6") %>%
  add_resource("receptionist", 1) %>%
  add_resource("catDoc", 1) %>%
  add_resource("dogDoc", 1) %>%
  add_generator("cat", t.cat, function() rexp(1,rate = (1/45)), mon = 2) %>%  
  add_generator("dog", t.dog, function() rexp(1,rate = (1/30)), mon = 2) %>%
  run(until=720) #720 = 12 hours * 60 min

Regards,
Iñaki


--
You received this message because you are subscribed to the Google Groups "simmer-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel...@googlegroups.com.
To post to this group, send email to simmer...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/simmer-devel/CAC3jZor8OoXV9BOkOM-p%2Bg_uPLqU_5twqj4M9Snm9pRDM-RWVg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.



--

Iñaki Úcar

unread,
May 4, 2016, 3:27:54 PM5/4/16
to simmer-devel

I think the previous email answered the question. But, as a side discussion, certainly it would be nice not to have to repeat the common activities in each trajectory. So I’ll examine the possibility of adding trajectories, of trajectory concatenation, as a future feature. This way, we could define

t.common <- create_trajectory("common") %>%
  seize("receptionist", 1) %>% #Both dogs and cats go to the receptionist

  timeout(function() max(0,rnorm(1,5,2))) %>%
  release("receptionist", 1)

t.cat <- create_trajectory("cat"
) %>%
  seize("catDoc", 1) %>%
  timeout(function() max(0,rnorm(1,30,10))) %>%
  release("catDoc", 1)

t.dog <- create_trajectory("dog") %>%
  seize("dogDoc", 1) %>%
  timeout(function() max(0,rnorm(1,30,10))) %>%
  release("dogDoc", 1)

And then, we could simply concatenate them (tentative syntax follows):

env %>%
  add_generator("cat", t.common + t.cat, function() rexp(1,rate = (1/45)), mon = 2) %>%  
  add_generator("dog", t.common + t.dog, function() rexp(1,rate = (1/30)), mon = 2)

Opinions welcome!

Regards,
Iñaki

L Mico

unread,
May 4, 2016, 3:57:44 PM5/4/16
to simmer...@googlegroups.com

That definitely makes sense - I had considered that as an option but wanted to be sure there was not a more succinct solution.

Thank you much!  Your quick and thorough responses are super helpful and appreciated.

Cheers

L

Bart Smeets

unread,
May 4, 2016, 4:31:07 PM5/4/16
to simmer-devel
Completely support this functionality. I would be nice however to keep the trajectory definition part out of the generators. For example:

t.common <- create_trajectory("common") %>%
  seize
(
"receptionist", 1) %>% #Both dogs and cats go to the receptionist
  timeout
(
function() max(0,rnorm(1,5,2))) %>%
  release
(
"receptionist", 1)

t.cat <- create_trajectory("cat"
) %>%
  include
(t.common) %>%
  seize
(
"catDoc", 1) %>%
  timeout
(
function() max(0,rnorm(1,30,10))) %>%
  release
(
"catDoc", 1)

t
.dog <- create_trajectory(
"dog") %>%
  include(t.common) %>%

  seize(
"dogDoc", 1) %>%
  timeout
(
function() max(0,rnorm(1,30,10))) %>%
  release
(
"dogDoc", 1)

What do you think?

Op woensdag 4 mei 2016 21:27:54 UTC+2 schreef Iñaki Úcar:
To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel+unsubscribe@googlegroups.com.

Iñaki Úcar

unread,
May 4, 2016, 5:27:53 PM5/4/16
to simmer-devel

I like your proposal for two reasons:

  • It’s easier to implement at R level (at C++ level, it’s still necessary to clone the whole chain of activities and it will be a mess; but that’s a future-Iñaki’s problem :-D ).
  • It’s cleaner when the common part is located just in the middle of a larger trajectory.

So I vote for it. Do you think it would be preferable include(t.common) instead of concatenate(t.common)? Other? I’m just brainstorming. I have no favorite.


To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "simmer-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel...@googlegroups.com.

To post to this group, send email to simmer...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

L Mico

unread,
May 5, 2016, 4:44:07 PM5/5/16
to simmer...@googlegroups.com
If it is just a matter of nomenclature, I find concatenate() to be more intuitive. 


For more options, visit https://groups.google.com/d/optout.



--

Justin Howe

unread,
May 6, 2017, 10:17:07 PM5/6/17
to simmer-devel
Just another point to note in your solution design (which happens to be a problem I'm running into).

Since Markovian arrival distributions have additive means, it is MUCH simpler to NOT create different arrival generators for the same phenomena. For example, the arrival rate of emergency room patients = the weighted average of the arrival rates for gun shot wounds vs all non-gun shot wounds. This could be modeled in 2 ways:
1) Create two trajectories.
2) Create a single arrivel trajectory, and assign an attribute 'Gun Shot Wound' based on the historical proportion that gun shot wounds comprise of total emergency room patients.

While option 1 is intuitive, it doesn't scale to multiple attributes. For example, if I had 10 'reasons' to visit the emergency room (attribute 1), and I wanted to model 10 phases of the moon (attribute 2), I would need to create 100 generators. (Not tenable)

So it would be GREAT if we can reference the attribute for 'this' trajectory and use it as an input to functions.

Iñaki Úcar

unread,
May 7, 2017, 5:48:52 AM5/7/17
to simmer-devel

Of course, it depends on the simulation. But from the performance point of view, it is always better to define multiple trajectories and multiple generators. You can create them in a very easy way, with very few lines of code, using lapply, and the performance gains are huge (see this example).

Iñaki


--
You received this message because you are subscribed to the Google Groups "simmer-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel+unsubscribe@googlegroups.com.

To post to this group, send email to simmer...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Dominique Cirkel

unread,
May 10, 2017, 5:45:13 AM5/10/17
to simmer-devel
I'd have to say I find Barts include() a lot more intuitive.
However, both would be easy to work with.

Kind regards

Op woensdag 4 mei 2016 23:27:53 UTC+2 schreef Iñaki Úcar:

Iñaki Úcar

unread,
May 10, 2017, 5:50:55 AM5/10/17
to simmer-devel
Finally, as you probably know, the selected verb for this functionality was "join()".

Iñaki

To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel+unsubscribe@googlegroups.com.

To post to this group, send email to simmer...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages