Simmer in R: Modelling changes in server capacity based on queue length and durationcolumn sum based on row lengthStoring Frequency Count of Simulation Function Output in RFilter row names based on string lengthSimmer R package: Modeling 2 Patients Arriving with Constant Inter-Arrival TimeQ: Model a Function based on EquationsChanging length of lines in a legend.wav file length/duration without reading in the fileVariable Lengths Differ Error on Predictive modelExtract change duration in RHow to define starting state of queueing model in r simmer?

What is the most common end of life issue for a car?

Finding minimum time for vehicle to reach to its destination

Did the IBM PC use the 8088's NMI line?

How do campaign rallies gain candidates votes?

Decreasing star size

How to deal with a player who makes bad characters and kills them?

Leaf-Spine network without routing

Does the Intel 8086 CPU have user mode and kernel mode?

Request for a Latin phrase as motto "God is highest/supreme"

Vertical tennis ball into fancy new enumerate

Use cases for M-0 & C-0?

How acidic does a mixture have to be for milk to curdle?

Why is drive/partition number still used?

Does academia have a lazy work culture?

Is it legal to use cash pulled from a credit card to pay the monthly payment on that credit card?

What is this spacecraft tethered to another spacecraft in LEO (vintage)

Why isn't there any 9.5 digit multimeter or higher?

Twelve past eleven at the police station

Does a Rogue's Evasion work for spells?

Converting 8V AC to 8V DC - bridge rectifier gets very hot while idling

How to die in Goat Simulator

Is there a reason why I should not use the HaveIBeenPwned API to warn users about exposed passwords?

Interrupt pin type on the 6502

How to apply the changes to my `.zshrc` file after edit?



Simmer in R: Modelling changes in server capacity based on queue length and duration


column sum based on row lengthStoring Frequency Count of Simulation Function Output in RFilter row names based on string lengthSimmer R package: Modeling 2 Patients Arriving with Constant Inter-Arrival TimeQ: Model a Function based on EquationsChanging length of lines in a legend.wav file length/duration without reading in the fileVariable Lengths Differ Error on Predictive modelExtract change duration in RHow to define starting state of queueing model in r simmer?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















I am attempting to model a system as follows:



Arrivals generate according to a predefined schedule and have known processing times supplied by a dataframe. There is a single server with a capacity equal to min_daemons at the beginning of the simulation. Simple so far, but the nxt part gets tricky: this capacity can vary on the interval [min_daemons , max_daemons] throughout the simulation according to the following algorithm:



If at any time during the simulation, the queue length reaches or exceeds the value of incr_count, and remains at or above this level for incr_delay, then an additional unit of capacity is added to the main server. This can happen at any time, provided that the capacity at no time exceeds max_daemons.



The reverse is also true. If at any time, the queue length is less than decr_count, and remains at or below this level for decr_delay, a unit of capacity is removed, potentially down to a level of min_daemons.



I created a trajectory for all arrivals that branches off when the conditions for changing server capacity above are met. The problem with this is that the changes in capacity are always tied to an arrival event. What I really want is a process independent of the arrival trajectory that monitors the queue length at all times and makes appropriate capacity changes.



I considered alternatively accomplishing this with some sort of dummy arrival process, say at every second of the simulation, but I wasn't sure if I could prevent the dummy arrivals from competing with the true arrivals for server capacity.



#instantiate simulation environment
env <- simmer("queues") %>% add_resource("daemon",1) %>% add_global("incr_start",99999) %>% add_global("decr_start",99999)

run <- trajectory() %>%
branch(option = function() if (get_queue_count(env,"daemon") >= incr_count) 1
else if (get_queue_count(env,"daemon") <= decr_count) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment?")
%>% branch(option = function() if (now(env) - get_global(env,"incr_start") >= incr_delay
& get_capacity(env,"daemon") < max_daemons) 1
else if (get_global(env,"incr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has exceeded count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = 1, mod="+")
,
trajectory("update incr start")
%>% set_global("incr_start",now(env))
%>% log_("Queue count is now above increment count. Starting increment timer.")
,
trajectory("do nothing")
%>% log_("Did not meet increment criteria. Doing nothing.")
)
,
trajectory("decrement?")
%>% branch(option = function() if (now(env) - get_global(env,"decr_start") >= decr_delay
& get_capacity(env,"daemon") > min_daemons) 1
else if (get_global(env,"decr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("decrement")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has been less than count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = -1, mod="+")
,
trajectory("update decr start")
%>% set_global("decr_start",now(env))
%>% log_("Queue count is now below decrement count. Starting decrement timer.")
,
trajectory("do nothing")
%>% log_("Did not meet decrement criteria. Doing nothing.")
)
,
trajectory("reset_timer")
%>% log_("Did not meet criteria to increment or decrement. Resetting timers.")
%>% set_global("decr_start", values = 99999)
%>% set_global("decr_start", values = 99999)
) %>%
seize("daemon") %>%
log_("Now running") %>%
log_(function () paste(get_queue_count(env,"daemon")," runs in the queue.")) %>%
timeout_from_attribute("service") %>%
release("daemon") %>%
log_("Run complete")

env %>%
add_dataframe("run", run, arr,time="absolute") %>%
run(200)


I need to do some more debugging to verify that the simulation is working as I intended, but I fully understand that this model is wrong. I can hope that the design doesn't compromise it's validity too much, but I also want to get feedback on how I could design something that's truer to real life.










share|improve this question

















  • 1





    What is the question? Where is your model going wrong? How do you know it is wrong?

    – Corey Levinson
    Mar 26 at 19:13











  • Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

    – Jack Rossi
    Mar 26 at 19:55

















0















I am attempting to model a system as follows:



Arrivals generate according to a predefined schedule and have known processing times supplied by a dataframe. There is a single server with a capacity equal to min_daemons at the beginning of the simulation. Simple so far, but the nxt part gets tricky: this capacity can vary on the interval [min_daemons , max_daemons] throughout the simulation according to the following algorithm:



If at any time during the simulation, the queue length reaches or exceeds the value of incr_count, and remains at or above this level for incr_delay, then an additional unit of capacity is added to the main server. This can happen at any time, provided that the capacity at no time exceeds max_daemons.



The reverse is also true. If at any time, the queue length is less than decr_count, and remains at or below this level for decr_delay, a unit of capacity is removed, potentially down to a level of min_daemons.



I created a trajectory for all arrivals that branches off when the conditions for changing server capacity above are met. The problem with this is that the changes in capacity are always tied to an arrival event. What I really want is a process independent of the arrival trajectory that monitors the queue length at all times and makes appropriate capacity changes.



I considered alternatively accomplishing this with some sort of dummy arrival process, say at every second of the simulation, but I wasn't sure if I could prevent the dummy arrivals from competing with the true arrivals for server capacity.



#instantiate simulation environment
env <- simmer("queues") %>% add_resource("daemon",1) %>% add_global("incr_start",99999) %>% add_global("decr_start",99999)

run <- trajectory() %>%
branch(option = function() if (get_queue_count(env,"daemon") >= incr_count) 1
else if (get_queue_count(env,"daemon") <= decr_count) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment?")
%>% branch(option = function() if (now(env) - get_global(env,"incr_start") >= incr_delay
& get_capacity(env,"daemon") < max_daemons) 1
else if (get_global(env,"incr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has exceeded count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = 1, mod="+")
,
trajectory("update incr start")
%>% set_global("incr_start",now(env))
%>% log_("Queue count is now above increment count. Starting increment timer.")
,
trajectory("do nothing")
%>% log_("Did not meet increment criteria. Doing nothing.")
)
,
trajectory("decrement?")
%>% branch(option = function() if (now(env) - get_global(env,"decr_start") >= decr_delay
& get_capacity(env,"daemon") > min_daemons) 1
else if (get_global(env,"decr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("decrement")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has been less than count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = -1, mod="+")
,
trajectory("update decr start")
%>% set_global("decr_start",now(env))
%>% log_("Queue count is now below decrement count. Starting decrement timer.")
,
trajectory("do nothing")
%>% log_("Did not meet decrement criteria. Doing nothing.")
)
,
trajectory("reset_timer")
%>% log_("Did not meet criteria to increment or decrement. Resetting timers.")
%>% set_global("decr_start", values = 99999)
%>% set_global("decr_start", values = 99999)
) %>%
seize("daemon") %>%
log_("Now running") %>%
log_(function () paste(get_queue_count(env,"daemon")," runs in the queue.")) %>%
timeout_from_attribute("service") %>%
release("daemon") %>%
log_("Run complete")

env %>%
add_dataframe("run", run, arr,time="absolute") %>%
run(200)


I need to do some more debugging to verify that the simulation is working as I intended, but I fully understand that this model is wrong. I can hope that the design doesn't compromise it's validity too much, but I also want to get feedback on how I could design something that's truer to real life.










share|improve this question

















  • 1





    What is the question? Where is your model going wrong? How do you know it is wrong?

    – Corey Levinson
    Mar 26 at 19:13











  • Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

    – Jack Rossi
    Mar 26 at 19:55













0












0








0








I am attempting to model a system as follows:



Arrivals generate according to a predefined schedule and have known processing times supplied by a dataframe. There is a single server with a capacity equal to min_daemons at the beginning of the simulation. Simple so far, but the nxt part gets tricky: this capacity can vary on the interval [min_daemons , max_daemons] throughout the simulation according to the following algorithm:



If at any time during the simulation, the queue length reaches or exceeds the value of incr_count, and remains at or above this level for incr_delay, then an additional unit of capacity is added to the main server. This can happen at any time, provided that the capacity at no time exceeds max_daemons.



The reverse is also true. If at any time, the queue length is less than decr_count, and remains at or below this level for decr_delay, a unit of capacity is removed, potentially down to a level of min_daemons.



I created a trajectory for all arrivals that branches off when the conditions for changing server capacity above are met. The problem with this is that the changes in capacity are always tied to an arrival event. What I really want is a process independent of the arrival trajectory that monitors the queue length at all times and makes appropriate capacity changes.



I considered alternatively accomplishing this with some sort of dummy arrival process, say at every second of the simulation, but I wasn't sure if I could prevent the dummy arrivals from competing with the true arrivals for server capacity.



#instantiate simulation environment
env <- simmer("queues") %>% add_resource("daemon",1) %>% add_global("incr_start",99999) %>% add_global("decr_start",99999)

run <- trajectory() %>%
branch(option = function() if (get_queue_count(env,"daemon") >= incr_count) 1
else if (get_queue_count(env,"daemon") <= decr_count) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment?")
%>% branch(option = function() if (now(env) - get_global(env,"incr_start") >= incr_delay
& get_capacity(env,"daemon") < max_daemons) 1
else if (get_global(env,"incr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has exceeded count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = 1, mod="+")
,
trajectory("update incr start")
%>% set_global("incr_start",now(env))
%>% log_("Queue count is now above increment count. Starting increment timer.")
,
trajectory("do nothing")
%>% log_("Did not meet increment criteria. Doing nothing.")
)
,
trajectory("decrement?")
%>% branch(option = function() if (now(env) - get_global(env,"decr_start") >= decr_delay
& get_capacity(env,"daemon") > min_daemons) 1
else if (get_global(env,"decr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("decrement")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has been less than count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = -1, mod="+")
,
trajectory("update decr start")
%>% set_global("decr_start",now(env))
%>% log_("Queue count is now below decrement count. Starting decrement timer.")
,
trajectory("do nothing")
%>% log_("Did not meet decrement criteria. Doing nothing.")
)
,
trajectory("reset_timer")
%>% log_("Did not meet criteria to increment or decrement. Resetting timers.")
%>% set_global("decr_start", values = 99999)
%>% set_global("decr_start", values = 99999)
) %>%
seize("daemon") %>%
log_("Now running") %>%
log_(function () paste(get_queue_count(env,"daemon")," runs in the queue.")) %>%
timeout_from_attribute("service") %>%
release("daemon") %>%
log_("Run complete")

env %>%
add_dataframe("run", run, arr,time="absolute") %>%
run(200)


I need to do some more debugging to verify that the simulation is working as I intended, but I fully understand that this model is wrong. I can hope that the design doesn't compromise it's validity too much, but I also want to get feedback on how I could design something that's truer to real life.










share|improve this question














I am attempting to model a system as follows:



Arrivals generate according to a predefined schedule and have known processing times supplied by a dataframe. There is a single server with a capacity equal to min_daemons at the beginning of the simulation. Simple so far, but the nxt part gets tricky: this capacity can vary on the interval [min_daemons , max_daemons] throughout the simulation according to the following algorithm:



If at any time during the simulation, the queue length reaches or exceeds the value of incr_count, and remains at or above this level for incr_delay, then an additional unit of capacity is added to the main server. This can happen at any time, provided that the capacity at no time exceeds max_daemons.



The reverse is also true. If at any time, the queue length is less than decr_count, and remains at or below this level for decr_delay, a unit of capacity is removed, potentially down to a level of min_daemons.



I created a trajectory for all arrivals that branches off when the conditions for changing server capacity above are met. The problem with this is that the changes in capacity are always tied to an arrival event. What I really want is a process independent of the arrival trajectory that monitors the queue length at all times and makes appropriate capacity changes.



I considered alternatively accomplishing this with some sort of dummy arrival process, say at every second of the simulation, but I wasn't sure if I could prevent the dummy arrivals from competing with the true arrivals for server capacity.



#instantiate simulation environment
env <- simmer("queues") %>% add_resource("daemon",1) %>% add_global("incr_start",99999) %>% add_global("decr_start",99999)

run <- trajectory() %>%
branch(option = function() if (get_queue_count(env,"daemon") >= incr_count) 1
else if (get_queue_count(env,"daemon") <= decr_count) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment?")
%>% branch(option = function() if (now(env) - get_global(env,"incr_start") >= incr_delay
& get_capacity(env,"daemon") < max_daemons) 1
else if (get_global(env,"incr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("increment")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has exceeded count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = 1, mod="+")
,
trajectory("update incr start")
%>% set_global("incr_start",now(env))
%>% log_("Queue count is now above increment count. Starting increment timer.")
,
trajectory("do nothing")
%>% log_("Did not meet increment criteria. Doing nothing.")
)
,
trajectory("decrement?")
%>% branch(option = function() if (now(env) - get_global(env,"decr_start") >= decr_delay
& get_capacity(env,"daemon") > min_daemons) 1
else if (get_global(env,"decr_start")==99999) 2
else 3
,
continue = c(T, T, T)
,
trajectory("decrement")
%>% log_(function () paste("Queue size is: ",get_queue_count(env,"daemon")))
%>% log_(function ()
paste("Queue has been less than count for ",now(env)-get_global(env,"incr_start")," seconds."))
%>% set_capacity(resource = "daemon", value = -1, mod="+")
,
trajectory("update decr start")
%>% set_global("decr_start",now(env))
%>% log_("Queue count is now below decrement count. Starting decrement timer.")
,
trajectory("do nothing")
%>% log_("Did not meet decrement criteria. Doing nothing.")
)
,
trajectory("reset_timer")
%>% log_("Did not meet criteria to increment or decrement. Resetting timers.")
%>% set_global("decr_start", values = 99999)
%>% set_global("decr_start", values = 99999)
) %>%
seize("daemon") %>%
log_("Now running") %>%
log_(function () paste(get_queue_count(env,"daemon")," runs in the queue.")) %>%
timeout_from_attribute("service") %>%
release("daemon") %>%
log_("Run complete")

env %>%
add_dataframe("run", run, arr,time="absolute") %>%
run(200)


I need to do some more debugging to verify that the simulation is working as I intended, but I fully understand that this model is wrong. I can hope that the design doesn't compromise it's validity too much, but I also want to get feedback on how I could design something that's truer to real life.







r event-simulation






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 26 at 18:50









Jack RossiJack Rossi

1




1







  • 1





    What is the question? Where is your model going wrong? How do you know it is wrong?

    – Corey Levinson
    Mar 26 at 19:13











  • Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

    – Jack Rossi
    Mar 26 at 19:55












  • 1





    What is the question? Where is your model going wrong? How do you know it is wrong?

    – Corey Levinson
    Mar 26 at 19:13











  • Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

    – Jack Rossi
    Mar 26 at 19:55







1




1





What is the question? Where is your model going wrong? How do you know it is wrong?

– Corey Levinson
Mar 26 at 19:13





What is the question? Where is your model going wrong? How do you know it is wrong?

– Corey Levinson
Mar 26 at 19:13













Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

– Jack Rossi
Mar 26 at 19:55





Paragraphs 5 and 6 are the question. My code executes without error, but the model is not correct, and I can't figure out how to implement it correctly with the standard simmer tools. The true system is constantly checking for times when the queue exceeds a range of lengths for a certain amount of time, at which point it adjusts the capacity of the server. My model is only capable of making this adjustment when there is a new arrival.

– Jack Rossi
Mar 26 at 19:55












1 Answer
1






active

oldest

votes


















0














Checking the status at regular intervals defeats the entire purpose of having discrete events. We have here an asynchronous process, so the proper way to model this is by using signals.



We need to ask ourselves: when could the queue...




  1. increase? When an arrival hits the seize() activity. So before trying to seize the resource, we need to check the number of enqueued arrivals and act accordingly:



    • If it's equal to decr_count, a signal must be sent to cancel any attempt to decrease the server's capacity.

    • If it's equal to incr_count - 1, a signal must be sent to request an increase of the server's capacity.

    • Do nothing otherwise.



  2. decrease? When an arrival is served (i.e., continues to the next activity following seize(). So after seizing the resource, we also need to check the number of enqueued arrivals:



    • If it's equal to incr_count - 1, a signal must be sent to cancel any attempt to increase the server's capacity.

    • If it's equal to decr_count, a signal must be sent to request a decrease of the server's capacity.

    • Do nothing otherwise.


The procedure for checking the number of enqueued arrivals and deciding what kind of signal is needed, if any, can be bundled in a reusable function (let's call it check_queue) as follows:



library(simmer)

env <- simmer()

check_queue <- function(.trj, resource, mod, lim_queue, lim_server)
.trj %>% branch(
function()
if (get_queue_count(env, resource) == lim_queue[1])
return(1)
if (get_queue_count(env, resource) == lim_queue[2] &&
get_capacity(env, resource) != lim_server)
return(2)
0 # pass
,
continue = c(TRUE, TRUE),
trajectory() %>% send(paste("cancel", mod[1])),
trajectory() %>% send(mod[2])
)


main <- trajectory() %>%
check_queue("resource", c("-", "+"), c(decr_count, incr_count-1), max_daemons) %>%
seize("resource") %>%
check_queue("resource", c("+", "-"), c(incr_count-1, decr_count), min_daemons) %>%
timeout_from_attribute("service") %>%
release("resource")


In this way, the main trajectory is quite simple. Then, we need a couple of processes to receive such signals and increase/decrease the capacity after some delay:



change_capacity <- function(resource, mod, delay, limit) 
trajectory() %>%
untrap(paste("cancel", mod)) %>%
trap(mod) %>%
wait() %>%
# signal received
untrap(mod) %>%
trap(paste("cancel", mod),
handler = trajectory() %>%
# cancelled! start from the beginning
rollback(Inf)) %>%
timeout(delay) %>%
set_capacity(resource, as.numeric(paste0(mod, 1)), mod="+") %>%
# do we need to keep changing the capacity?
rollback(2, check=function() get_capacity(env, resource) != limit) %>%
# start from the beginning
rollback(Inf)


incr_capacity <- change_capacity("resource", "+", incr_delay, max_daemons)
decr_capacity <- change_capacity("resource", "-", decr_delay, min_daemons)


Finally, we add the resource, our processes and the data to the simulation environment:



env %>%
add_resource("resource", min_daemons) %>%
add_generator("incr", incr_capacity, at(0)) %>%
add_generator("decr", decr_capacity, at(0)) %>%
add_dataframe("arrival", main, data)


Please note that I didn't check this code. It may require some adjustments, but the general idea is there.






share|improve this answer























  • Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

    – Jack Rossi
    May 9 at 15:45










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55364348%2fsimmer-in-r-modelling-changes-in-server-capacity-based-on-queue-length-and-dura%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Checking the status at regular intervals defeats the entire purpose of having discrete events. We have here an asynchronous process, so the proper way to model this is by using signals.



We need to ask ourselves: when could the queue...




  1. increase? When an arrival hits the seize() activity. So before trying to seize the resource, we need to check the number of enqueued arrivals and act accordingly:



    • If it's equal to decr_count, a signal must be sent to cancel any attempt to decrease the server's capacity.

    • If it's equal to incr_count - 1, a signal must be sent to request an increase of the server's capacity.

    • Do nothing otherwise.



  2. decrease? When an arrival is served (i.e., continues to the next activity following seize(). So after seizing the resource, we also need to check the number of enqueued arrivals:



    • If it's equal to incr_count - 1, a signal must be sent to cancel any attempt to increase the server's capacity.

    • If it's equal to decr_count, a signal must be sent to request a decrease of the server's capacity.

    • Do nothing otherwise.


The procedure for checking the number of enqueued arrivals and deciding what kind of signal is needed, if any, can be bundled in a reusable function (let's call it check_queue) as follows:



library(simmer)

env <- simmer()

check_queue <- function(.trj, resource, mod, lim_queue, lim_server)
.trj %>% branch(
function()
if (get_queue_count(env, resource) == lim_queue[1])
return(1)
if (get_queue_count(env, resource) == lim_queue[2] &&
get_capacity(env, resource) != lim_server)
return(2)
0 # pass
,
continue = c(TRUE, TRUE),
trajectory() %>% send(paste("cancel", mod[1])),
trajectory() %>% send(mod[2])
)


main <- trajectory() %>%
check_queue("resource", c("-", "+"), c(decr_count, incr_count-1), max_daemons) %>%
seize("resource") %>%
check_queue("resource", c("+", "-"), c(incr_count-1, decr_count), min_daemons) %>%
timeout_from_attribute("service") %>%
release("resource")


In this way, the main trajectory is quite simple. Then, we need a couple of processes to receive such signals and increase/decrease the capacity after some delay:



change_capacity <- function(resource, mod, delay, limit) 
trajectory() %>%
untrap(paste("cancel", mod)) %>%
trap(mod) %>%
wait() %>%
# signal received
untrap(mod) %>%
trap(paste("cancel", mod),
handler = trajectory() %>%
# cancelled! start from the beginning
rollback(Inf)) %>%
timeout(delay) %>%
set_capacity(resource, as.numeric(paste0(mod, 1)), mod="+") %>%
# do we need to keep changing the capacity?
rollback(2, check=function() get_capacity(env, resource) != limit) %>%
# start from the beginning
rollback(Inf)


incr_capacity <- change_capacity("resource", "+", incr_delay, max_daemons)
decr_capacity <- change_capacity("resource", "-", decr_delay, min_daemons)


Finally, we add the resource, our processes and the data to the simulation environment:



env %>%
add_resource("resource", min_daemons) %>%
add_generator("incr", incr_capacity, at(0)) %>%
add_generator("decr", decr_capacity, at(0)) %>%
add_dataframe("arrival", main, data)


Please note that I didn't check this code. It may require some adjustments, but the general idea is there.






share|improve this answer























  • Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

    – Jack Rossi
    May 9 at 15:45















0














Checking the status at regular intervals defeats the entire purpose of having discrete events. We have here an asynchronous process, so the proper way to model this is by using signals.



We need to ask ourselves: when could the queue...




  1. increase? When an arrival hits the seize() activity. So before trying to seize the resource, we need to check the number of enqueued arrivals and act accordingly:



    • If it's equal to decr_count, a signal must be sent to cancel any attempt to decrease the server's capacity.

    • If it's equal to incr_count - 1, a signal must be sent to request an increase of the server's capacity.

    • Do nothing otherwise.



  2. decrease? When an arrival is served (i.e., continues to the next activity following seize(). So after seizing the resource, we also need to check the number of enqueued arrivals:



    • If it's equal to incr_count - 1, a signal must be sent to cancel any attempt to increase the server's capacity.

    • If it's equal to decr_count, a signal must be sent to request a decrease of the server's capacity.

    • Do nothing otherwise.


The procedure for checking the number of enqueued arrivals and deciding what kind of signal is needed, if any, can be bundled in a reusable function (let's call it check_queue) as follows:



library(simmer)

env <- simmer()

check_queue <- function(.trj, resource, mod, lim_queue, lim_server)
.trj %>% branch(
function()
if (get_queue_count(env, resource) == lim_queue[1])
return(1)
if (get_queue_count(env, resource) == lim_queue[2] &&
get_capacity(env, resource) != lim_server)
return(2)
0 # pass
,
continue = c(TRUE, TRUE),
trajectory() %>% send(paste("cancel", mod[1])),
trajectory() %>% send(mod[2])
)


main <- trajectory() %>%
check_queue("resource", c("-", "+"), c(decr_count, incr_count-1), max_daemons) %>%
seize("resource") %>%
check_queue("resource", c("+", "-"), c(incr_count-1, decr_count), min_daemons) %>%
timeout_from_attribute("service") %>%
release("resource")


In this way, the main trajectory is quite simple. Then, we need a couple of processes to receive such signals and increase/decrease the capacity after some delay:



change_capacity <- function(resource, mod, delay, limit) 
trajectory() %>%
untrap(paste("cancel", mod)) %>%
trap(mod) %>%
wait() %>%
# signal received
untrap(mod) %>%
trap(paste("cancel", mod),
handler = trajectory() %>%
# cancelled! start from the beginning
rollback(Inf)) %>%
timeout(delay) %>%
set_capacity(resource, as.numeric(paste0(mod, 1)), mod="+") %>%
# do we need to keep changing the capacity?
rollback(2, check=function() get_capacity(env, resource) != limit) %>%
# start from the beginning
rollback(Inf)


incr_capacity <- change_capacity("resource", "+", incr_delay, max_daemons)
decr_capacity <- change_capacity("resource", "-", decr_delay, min_daemons)


Finally, we add the resource, our processes and the data to the simulation environment:



env %>%
add_resource("resource", min_daemons) %>%
add_generator("incr", incr_capacity, at(0)) %>%
add_generator("decr", decr_capacity, at(0)) %>%
add_dataframe("arrival", main, data)


Please note that I didn't check this code. It may require some adjustments, but the general idea is there.






share|improve this answer























  • Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

    – Jack Rossi
    May 9 at 15:45













0












0








0







Checking the status at regular intervals defeats the entire purpose of having discrete events. We have here an asynchronous process, so the proper way to model this is by using signals.



We need to ask ourselves: when could the queue...




  1. increase? When an arrival hits the seize() activity. So before trying to seize the resource, we need to check the number of enqueued arrivals and act accordingly:



    • If it's equal to decr_count, a signal must be sent to cancel any attempt to decrease the server's capacity.

    • If it's equal to incr_count - 1, a signal must be sent to request an increase of the server's capacity.

    • Do nothing otherwise.



  2. decrease? When an arrival is served (i.e., continues to the next activity following seize(). So after seizing the resource, we also need to check the number of enqueued arrivals:



    • If it's equal to incr_count - 1, a signal must be sent to cancel any attempt to increase the server's capacity.

    • If it's equal to decr_count, a signal must be sent to request a decrease of the server's capacity.

    • Do nothing otherwise.


The procedure for checking the number of enqueued arrivals and deciding what kind of signal is needed, if any, can be bundled in a reusable function (let's call it check_queue) as follows:



library(simmer)

env <- simmer()

check_queue <- function(.trj, resource, mod, lim_queue, lim_server)
.trj %>% branch(
function()
if (get_queue_count(env, resource) == lim_queue[1])
return(1)
if (get_queue_count(env, resource) == lim_queue[2] &&
get_capacity(env, resource) != lim_server)
return(2)
0 # pass
,
continue = c(TRUE, TRUE),
trajectory() %>% send(paste("cancel", mod[1])),
trajectory() %>% send(mod[2])
)


main <- trajectory() %>%
check_queue("resource", c("-", "+"), c(decr_count, incr_count-1), max_daemons) %>%
seize("resource") %>%
check_queue("resource", c("+", "-"), c(incr_count-1, decr_count), min_daemons) %>%
timeout_from_attribute("service") %>%
release("resource")


In this way, the main trajectory is quite simple. Then, we need a couple of processes to receive such signals and increase/decrease the capacity after some delay:



change_capacity <- function(resource, mod, delay, limit) 
trajectory() %>%
untrap(paste("cancel", mod)) %>%
trap(mod) %>%
wait() %>%
# signal received
untrap(mod) %>%
trap(paste("cancel", mod),
handler = trajectory() %>%
# cancelled! start from the beginning
rollback(Inf)) %>%
timeout(delay) %>%
set_capacity(resource, as.numeric(paste0(mod, 1)), mod="+") %>%
# do we need to keep changing the capacity?
rollback(2, check=function() get_capacity(env, resource) != limit) %>%
# start from the beginning
rollback(Inf)


incr_capacity <- change_capacity("resource", "+", incr_delay, max_daemons)
decr_capacity <- change_capacity("resource", "-", decr_delay, min_daemons)


Finally, we add the resource, our processes and the data to the simulation environment:



env %>%
add_resource("resource", min_daemons) %>%
add_generator("incr", incr_capacity, at(0)) %>%
add_generator("decr", decr_capacity, at(0)) %>%
add_dataframe("arrival", main, data)


Please note that I didn't check this code. It may require some adjustments, but the general idea is there.






share|improve this answer













Checking the status at regular intervals defeats the entire purpose of having discrete events. We have here an asynchronous process, so the proper way to model this is by using signals.



We need to ask ourselves: when could the queue...




  1. increase? When an arrival hits the seize() activity. So before trying to seize the resource, we need to check the number of enqueued arrivals and act accordingly:



    • If it's equal to decr_count, a signal must be sent to cancel any attempt to decrease the server's capacity.

    • If it's equal to incr_count - 1, a signal must be sent to request an increase of the server's capacity.

    • Do nothing otherwise.



  2. decrease? When an arrival is served (i.e., continues to the next activity following seize(). So after seizing the resource, we also need to check the number of enqueued arrivals:



    • If it's equal to incr_count - 1, a signal must be sent to cancel any attempt to increase the server's capacity.

    • If it's equal to decr_count, a signal must be sent to request a decrease of the server's capacity.

    • Do nothing otherwise.


The procedure for checking the number of enqueued arrivals and deciding what kind of signal is needed, if any, can be bundled in a reusable function (let's call it check_queue) as follows:



library(simmer)

env <- simmer()

check_queue <- function(.trj, resource, mod, lim_queue, lim_server)
.trj %>% branch(
function()
if (get_queue_count(env, resource) == lim_queue[1])
return(1)
if (get_queue_count(env, resource) == lim_queue[2] &&
get_capacity(env, resource) != lim_server)
return(2)
0 # pass
,
continue = c(TRUE, TRUE),
trajectory() %>% send(paste("cancel", mod[1])),
trajectory() %>% send(mod[2])
)


main <- trajectory() %>%
check_queue("resource", c("-", "+"), c(decr_count, incr_count-1), max_daemons) %>%
seize("resource") %>%
check_queue("resource", c("+", "-"), c(incr_count-1, decr_count), min_daemons) %>%
timeout_from_attribute("service") %>%
release("resource")


In this way, the main trajectory is quite simple. Then, we need a couple of processes to receive such signals and increase/decrease the capacity after some delay:



change_capacity <- function(resource, mod, delay, limit) 
trajectory() %>%
untrap(paste("cancel", mod)) %>%
trap(mod) %>%
wait() %>%
# signal received
untrap(mod) %>%
trap(paste("cancel", mod),
handler = trajectory() %>%
# cancelled! start from the beginning
rollback(Inf)) %>%
timeout(delay) %>%
set_capacity(resource, as.numeric(paste0(mod, 1)), mod="+") %>%
# do we need to keep changing the capacity?
rollback(2, check=function() get_capacity(env, resource) != limit) %>%
# start from the beginning
rollback(Inf)


incr_capacity <- change_capacity("resource", "+", incr_delay, max_daemons)
decr_capacity <- change_capacity("resource", "-", decr_delay, min_daemons)


Finally, we add the resource, our processes and the data to the simulation environment:



env %>%
add_resource("resource", min_daemons) %>%
add_generator("incr", incr_capacity, at(0)) %>%
add_generator("decr", decr_capacity, at(0)) %>%
add_dataframe("arrival", main, data)


Please note that I didn't check this code. It may require some adjustments, but the general idea is there.







share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 27 at 18:34









Iñaki ÚcarIñaki Úcar

2932 silver badges9 bronze badges




2932 silver badges9 bronze badges












  • Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

    – Jack Rossi
    May 9 at 15:45

















  • Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

    – Jack Rossi
    May 9 at 15:45
















Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

– Jack Rossi
May 9 at 15:45





Thanks so much for this! I found your explanation to be extremely helpful, and you code to be remarkably functional. The only thing I had to change was the check function in the rollback, so that it again checks that the queue is greater than increment count or less than decrement count.

– Jack Rossi
May 9 at 15:45








Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55364348%2fsimmer-in-r-modelling-changes-in-server-capacity-based-on-queue-length-and-dura%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해