A process-oriented and trajectory-based Discrete-Event Simulation
(DES) package for R. It is designed as a generic yet powerful framework. The
architecture encloses a robust and fast simulation core written in 'C++' with
automatic monitoring capabilities. It provides a rich and flexible R API that
revolves around the concept of trajectory, a common path in the simulation
model for entities of the same type. Documentation about 'simmer' is provided
by several vignettes included in this package, via the paper by Ucar, Smeets
& Azcorra (2018,
get_resources()retrieve a character vector of source/resource names defined in a simulation environment.
get_trajectory()retrieves a trajectory to which a given source is attached.
random-available(#156). These are the same as the existing non-
availableones, but they exclude unavailable resources (capacity set to zero). Thus, if all resources are unavailable, an error is raised.
-DRCPP_PROTECTED_EVAL(Rcpp >= 0.12.17.4) as
when_activated()convenience function to easily generate arrivals on demand from trajectories (#161 closing #160).
*_globalversions should be used instead.
simmerlicense has been changed to GPL >= 2.
inst/include(#147 closing #145). Therefore, from now on it is possible to extend the C++ API from another package by listing
LinkingTofield in the DESCRIPTION file.
monitorconstructor enables the development of new monitoring backends in other packages (179f656, as part of #147).
log_activity has a new argument
levelwhich determines whether the message is printed depending on a global
log_leveldefined in the
set_globalgain a new argument to automatically initialise new attributes (#157). Useful to update counters and indexes in a single line, without initialisation boilerplate.
-DRCPP_PROTECTED_EVAL(Rcpp >= 0.12.17.3), which provides fast evaluation of R expressions by leveraging the new stack unwinding protection API (R >= 3.5.0).
add_dataframeenables the attachment of precomputed data, in the form of a data frame, to a trajectory. It can be used instead of (or along with)
add_generator. The most notable advantage over the latter is that
add_dataframeis able to automatically set attributes and prioritisation values per arrival based on columns of the provided data frame (#140 closing #123).
set_distribution(). It works both for generators and data sources (275a09c, as part of #140).
simmer()constructor gains a new argument
monto provide different types of monitors. By default, monitoring is performed in-memory, as usual. Additionally, monitoring can be offloaded to disk through
monitor_csv, which produce flat delimited files. But more importantly, the C++ interface has been refactorised to enable the development of new monitoring backends (#146 closing #119).
runmethod (3e6aae9, as part of #140).
clonenow accept lists of trajectories, in the same way as
join, so that there is no need to use
branch) is recycled if only one value is provided but several sub-trajectories are defined (#143).
timeout_from_attribute()activity makes it easier to set a timeout based on an attribute (#129).
set_queue_size()get a new argument
modwhich, if set to
"*", modifies the corresponding value instead of substituting it. This makes it easier to increment, decrement or scale one of these values (#130).
*_selected()versions for the already available resource getters:
dataargument. It was there for historical reasons and probably nobody was using it (851d34b).
set_global()by extension) can set multiple attributes at once by providing vectors of
values(or functions returning such
get_global()by extension) can retrieve multiple
ostreamafter formatting (9ff11f8).
get_name()retrieves the arrival name.
get_attribute()retrieves an attribute by name. The old method of retrieving them by providing a function with one argument is deprecated in favour of
get_attribute(), and will be removed in version 3.7.x.
get_prioritization()retrieves the three prioritization values (
restart) of the active arrival.
get_global(), equivalent to
trap()'s handler cloning and associated test (#91).
resourcesis a function (#92).
rollback()'s default behaviour to
times=Inf, i.e., infinite loop (#95).
timeout()returns a missing value (#96 and #97).
rep()S3 method for trajectories (7fa515e).
simmer.plotpackage (on CRAN) already covers these features among others.
Suggestsare not installed (e40e5b6).
everyparameter to the
from_to()convenience function (9d68887).
[[, for trajectories (1847898). Think about trajectories as lists of activities and these operators will do (almost) everything you expect. As a side effect, the generics
tail()automatically work with trajectories also as expected.
length()method to obtain the number of first-level activities in a trajectory (f86375a). Useful in combination with the subsetting operators.
create_trajectory()has been deprecated in favor of
plot_attributes()have been deprecated and will be removed in the next release in order to minimise dependencies (5b43f2b). We plan to release a new package on CRAN covering these features and new ones.
get_prev_activity()(f86375a). These methods were only useful for development purposes and nobody should be using them. And it was never a good idea to directly expose external pointers.
renege_if()activity triggers reneging upon reception of a signal broadcasted with
queue_size_strict=TRUE: arrivals were not being dropped (#83).
set_capacity()with a preemptive resource when the old value was
Inf: arrivals were not being preempted (63beb2c).
set_queue_size()become activities (#77). Just like
release(), they have the associated
set_queue_size_selected()for a joint use together with
deactivate()activities allow an arrival to start or stop a generator, respectively, from inside a trajectory (#80).
set_distribution()activities allow an arrival to install a new trajectory or distribution, respectively, in a generator from inside a trajectory (#80).
wait()can be used to send signals, wait for signals, trap them and launch asynchronous handlers.
log_()activity simply prints messages for debugging purposes (eaa4554).
get_mon_arrivals(ongoing = TRUE)(#73).
run(until)runs the simulation exactly until
until, instead of until the first event scheduled at a time >=
restart) has been moved from
add_generator()(#69). This leads to a more natural interpretation of prioritization values as attributes of arrivals from the same generator, rather than attributes of a
seize(). Still, prioritization values can be redefined dynamically from inside a trajectory with the new activity
seize_selected()(#49). This feature allows us to fine-tune what happens to an arrival if it cannot seize a resource: instead of getting dropped, it may execute a given sub-trajectory.
clone()implements the workflow pattern in which an entity is processed in multiple parallel threads. The user can define a different sub-trajectory for each clone. With
synchronize(), multiple parallel clones converge and are synchronized: only one continues (the first or the last to arrive), and the others are removed.
separate()activities (#45). They can be used to implement a rollercoaster process:
batch()collects a number of arrivals before they can continue processing as a block, and
separate()splits a previously established batch.
renege_abort()activities (#58). They can be used to set or unset a timer after which the arrival will abandon.
0, the arrival skips the
branch()and continues to the next activity instead of throwing an
index out of rangeerror (#70).
branch()'s deprecated argument
join()activity to concatenate trajectories (#50).
add_resource()to guarantee the queue size limit with preemption (#59).
end_time - start_time. All versions 3.2.x are affected by this bug.
preemptiblein the documentation of
preemptibleto be equal or greater than
mergeparameter name to
continue. The old name is deprecated (#57).
match.arg()in multiple-choice arguments (#55).
branch()backwards linking and count (#56).
release()in two steps to deal properly with capacity changes at the same point in time (#64).
every()is deprecated due to #65.
queue_sizecan change over time following a user-defined scheduling, which can be generated with the new function
until=Infis allowed now (f47baa9).
t=3, queue=2meant that, until
t=3, the queue had 2 customers, and at
t=3the system changed (because of a new arrival or a new departure). The idea was to keep the values and time vectors aligned (see #28). But from this moment on, the resources are monitored _after changing the status of the system. This is more consistent with what a user would expect, and more consistent with the behaviour of other related R functions (e.g., see
stepfun(), from the
statspackage). Wrapping up and from now on,
t=3, queue=2means that some event happened at
t=3whose immediate and subsequent result was a queue with 2 customers.
preemptive=TRUE. Arrivals in the server can be preempted on a
seize()has three basic properties:
priority: already present in previous versions.
priorityvalue greater than this may preempt the present
restart: whether the current task (a
timeout()activity, for instance) should be restarted if the arrival is preempted.
from_to()convenience functions (8e524cd).
branch()activity now provides attributes to its
optionfunction, as the other activities (#42).
get_mon_arrivals()returned the start/activity/end times per arrival for the whole trajectory. This behaviour remains, but additionally,
get_mon_arrivals(per_resource = TRUE)returns these times per resource, so that it is possible to retrieve queueing/system times per resource.
get_mon_*()functions accept a single simulation environment as well as a list of environments representing several replications (5ee2725). A new column (
replication) in the resulting data frame indicates the corresponding replication number.
rollback()activity (#17 and #22).
selfvisibly, instead of invisibly (#35).
from()convenience functions (29cccd2 and 7cfdd90).
add_skip_event()function to implement a more flexible and user-friendly branching method.
narrivals beforehand, this release leverages the concept of generator of arrivals, which is faster and more flexible. At the same time, the concept of trajectory as a chain of activities is implemented entirely in C++ internally. Our tests show that simmer is even faster than SimPy when it comes to simulate queueing networks.