Skip to content

Commit bf93de6

Browse files
committed
fix sources to properly restore distributions and trajectories, closes #324
1 parent ff5179e commit bf93de6

File tree

9 files changed

+84
-39
lines changed

9 files changed

+84
-39
lines changed

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: simmer
22
Type: Package
33
Title: Discrete-Event Simulation for R
4-
Version: 4.4.6.5
4+
Version: 4.4.6.6
55
Authors@R: c(
66
person("Iñaki", "Ucar", email="iucar@fedoraproject.org",
77
role=c("aut", "cph", "cre"), comment=c(ORCID="0000-0001-6403-5550")),

NEWS.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# simmer devel
22

33
- Fix `set_source()` to avoid leaking arrivals from the old source (#322).
4+
- Fix sources to properly restore distributions and trajectories (#324).
45

56
# simmer 4.4.6.4
67

inst/include/simmer/process/arrival.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (C) 2015-2016 Bart Smeets and Iñaki Ucar
2-
// Copyright (C) 2016-2023 Iñaki Ucar
2+
// Copyright (C) 2016-2024 Iñaki Ucar
33
//
44
// This file is part of simmer.
55
//
@@ -58,16 +58,16 @@ namespace simmer {
5858

5959
/**
6060
* Constructor.
61-
* @param sim a pointer to the simulator
62-
* @param name the name
63-
* @param mon int that indicates whether this entity must be monitored
64-
* @param order priority, preemptible, restart
65-
* @param first_activity the first activity of a user-defined R trajectory
61+
* @param sim a pointer to the simulator
62+
* @param name the name
63+
* @param mon int that indicates whether this entity must be monitored
64+
* @param order priority, preemptible, restart
65+
* @param head the first activity of a user-defined R trajectory
6666
*/
6767
Arrival(Simulator* sim, const std::string& name, int mon, Order order,
68-
Activity* first_activity, int priority = 0, Source* src = NULL)
68+
Activity* head, int priority = 0, Source* src = NULL)
6969
: Process(sim, name, mon, priority), order(order), src(src), paused(0),
70-
sync(new Arrival*(NULL)), clones(new int(0)), activity(first_activity),
70+
sync(new Arrival*(NULL)), clones(new int(0)), activity(head),
7171
timer(NULL), dropout(NULL), batch(NULL), act_shd(new ActVec())
7272
{ init(); }
7373

inst/include/simmer/process/datasrc.h

+19-9
Original file line numberDiff line numberDiff line change
@@ -30,37 +30,46 @@ namespace simmer {
3030
const REnv& trj, RData data, int batch, const std::string& col_time,
3131
const VEC<std::string>& col_attrs, const OPT<std::string>& col_priority,
3232
const OPT<std::string>& col_preemptible, const OPT<std::string>& col_restart)
33-
: Source(sim, name_prefix, mon, trj, Order()), source(data), batch(batch),
33+
: Source(sim, name_prefix, mon, trj, Order()), source_(data), batch(batch),
3434
col_time(col_time), col_attrs(col_attrs), col_priority(col_priority),
35-
col_preemptible(col_preemptible), col_restart(col_restart) { set_source_impl(data); }
35+
col_preemptible(col_preemptible), col_restart(col_restart) { reset(); }
36+
37+
void reset() {
38+
Source::reset();
39+
source = source_;
40+
set_source_impl(source);
41+
}
3642

3743
void run() {
3844
double delay = 0;
3945
int i = 0;
4046

4147
while (i++ != batch) {
42-
if (time.size() <= count || check_stop(time[count]))
48+
if (time.size() <= index || check_stop(time[index]))
4349
return;
44-
delay += time[count];
50+
delay += time[index];
4551

4652
Arrival* arrival = new_arrival(delay);
4753

4854
for (size_t j = 0; j < col_attrs.size(); ++j)
49-
arrival->set_attribute(col_attrs[j], attrs[j][count-1]);
55+
arrival->set_attribute(col_attrs[j], attrs[j][index]);
5056

5157
if (col_priority)
52-
arrival->order.set_priority(priority[count-1]);
58+
arrival->order.set_priority(priority[index]);
5359
if (col_preemptible)
54-
arrival->order.set_preemptible(preemptible[count-1]);
60+
arrival->order.set_preemptible(preemptible[index]);
5561
if (col_restart)
56-
arrival->order.set_restart(restart[count-1]);
62+
arrival->order.set_restart(restart[index]);
63+
64+
index++;
5765
}
5866
// schedule the generator
5967
sim->schedule(delay, this, Source::priority);
6068
}
6169

6270
private:
63-
RData source;
71+
int index;
72+
RData source_, source;
6473
int batch;
6574
std::string col_time;
6675
VEC<std::string> col_attrs;
@@ -91,6 +100,7 @@ namespace simmer {
91100
if (col_restart && !df.containsElementNamed((*col_restart).c_str()))
92101
Rcpp::stop("column '%s' not present", *col_restart);
93102

103+
index = 0;
94104
source = df;
95105
time = source[col_time];
96106
attrs.clear();

inst/include/simmer/process/generator.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ namespace simmer {
3131
public:
3232
Generator(Simulator* sim, const std::string& name_prefix, int mon,
3333
const REnv& trj, const RFn& dist, const Order& order)
34-
: Source(sim, name_prefix, mon, trj, order), source(dist) {}
34+
: Source(sim, name_prefix, mon, trj, order), source_(dist), source(dist)
35+
{ reset(); }
3536

3637
void reset() {
3738
Source::reset();
39+
source = source_;
3840
RFn reset_fun(source.attr("reset"));
3941
reset_fun();
4042
}
@@ -57,7 +59,7 @@ namespace simmer {
5759
}
5860

5961
private:
60-
RFn source;
62+
RFn source_, source;
6163

6264
void set_source_impl(const std::any& new_source) {
6365
if (new_source.type() != typeid(RFn))

inst/include/simmer/process/source.h

+12-12
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ namespace simmer {
6363
*/
6464
Source(Simulator* sim, const std::string& name_prefix, int mon,
6565
const REnv& trj, const Order& order)
66-
: Process(sim, name_prefix, mon, PRIORITY_MIN), count(0), order(order),
67-
first_activity(internal::head(trj)), trj(trj) {}
66+
: Process(sim, name_prefix, mon, PRIORITY_MIN), order(order), trj_(trj) {}
6867

6968
virtual void reset() {
7069
count = 0;
70+
trj = trj_;
71+
head = internal::head(trj);
7172
ahead.clear();
7273
}
7374

@@ -81,7 +82,7 @@ namespace simmer {
8182
return Process::deactivate();
8283
}
8384

84-
int get_n_generated() const { return count; }
85+
int get_count() const { return count; }
8586

8687
REnv get_trajectory() const { return trj; }
8788

@@ -93,27 +94,23 @@ namespace simmer {
9394

9495
void set_trajectory(const REnv& new_trj) {
9596
trj = new_trj;
96-
first_activity = internal::head(trj);
97+
head = internal::head(trj);
9798
}
9899

99100
protected:
100-
int count; /**< number of arrivals generated */
101-
Order order;
102-
Activity* first_activity;
103-
104101
Arrival* new_arrival(double delay) {
105102
// format the name and create the next arrival
106103
std::string arr_name = MakeString() << name << count++;
107104
Arrival* arrival = new Arrival(
108-
sim, arr_name, is_monitored(), order, first_activity, count, this);
105+
sim, arr_name, is_monitored(), order, head, count, this);
109106
ahead.emplace(arrival);
110107

111108
if (sim->verbose) sim->print("source", name, "new", arr_name,
112109
MakeString() << (sim->now() + delay));
113110

114111
// schedule the arrival
115-
sim->schedule(delay, arrival, first_activity && first_activity->priority ?
116-
first_activity->priority : count);
112+
sim->schedule(delay, arrival, head && head->priority ?
113+
head->priority : count);
117114

118115
return arrival;
119116
}
@@ -129,7 +126,10 @@ namespace simmer {
129126
}
130127

131128
private:
132-
REnv trj;
129+
int count; /**< number of arrivals generated */
130+
Order order;
131+
Activity* head;
132+
REnv trj_, trj;
133133
ArrSet ahead;
134134

135135
virtual void set_source_impl(const std::any& new_source) = 0;

src/process.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2014 Bart Smeets
22
// Copyright (C) 2015 Iñaki Ucar and Bart Smeets
3-
// Copyright (C) 2015-2023 Iñaki Ucar
3+
// Copyright (C) 2015-2024 Iñaki Ucar
44
//
55
// This file is part of simmer.
66
//
@@ -35,7 +35,7 @@ Vector<RTYPE> get_param(SEXP sim_, const VEC<std::string>& names,
3535

3636
//[[Rcpp::export]]
3737
SEXP get_n_generated_(SEXP sim_, const std::vector<std::string>& names) {
38-
return get_param<INTSXP,int>(sim_, names, std::mem_fn(&Source::get_n_generated));
38+
return get_param<INTSXP,int>(sim_, names, std::mem_fn(&Source::get_count));
3939
}
4040

4141
//[[Rcpp::export]]

tests/testthat/test-simmer-dataframe.R

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2018-2023 Iñaki Ucar
1+
# Copyright (C) 2018-2024 Iñaki Ucar
22
#
33
# This file is part of simmer.
44
#
@@ -93,13 +93,28 @@ test_that("generates the expected amount", {
9393
})
9494

9595
test_that("data sources are reset", {
96-
DF <- data.frame(time=rep(1, 3))
97-
9896
expect_equal(3, simmer(verbose = env_verbose) %>%
99-
add_dataframe("dummy", trajectory(), DF) %>%
97+
add_dataframe("dummy", trajectory(), data.frame(time=rep(1, 3))) %>%
10098
run() %>% reset() %>% run() %>%
10199
get_mon_arrivals() %>% nrow()
102100
)
101+
102+
t <- trajectory() %>%
103+
set_source("dummy", data.frame(time=10)) %>%
104+
set_trajectory("dummy", trajectory() %>% timeout(1))
105+
106+
env <- simmer(verbose = env_verbose) %>%
107+
add_dataframe("dummy", t, data.frame(time=0))
108+
109+
df1 <- env %>%
110+
run() %>%
111+
get_mon_arrivals()
112+
df2 <- env %>%
113+
reset() %>%
114+
run() %>%
115+
get_mon_arrivals()
116+
117+
expect_equal(df1, df2)
103118
})
104119

105120
test_that("priorities are set", {

tests/testthat/test-simmer-generator.R

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Copyright (C) 2015 Iñaki Ucar and Bart Smeets
2-
# Copyright (C) 2015-2023 Iñaki Ucar
2+
# Copyright (C) 2015-2024 Iñaki Ucar
33
#
44
# This file is part of simmer.
55
#
@@ -58,6 +58,23 @@ test_that("generators are reset", {
5858
run() %>% reset() %>% run() %>%
5959
get_mon_arrivals() %>% nrow()
6060
)
61+
62+
t <- trajectory() %>%
63+
set_source("dummy", at(10)) %>%
64+
set_trajectory("dummy", trajectory() %>% timeout(1))
65+
66+
env <- simmer(verbose = env_verbose) %>%
67+
add_generator("dummy", t, at(0))
68+
69+
df1 <- env %>%
70+
run() %>%
71+
get_mon_arrivals()
72+
df2 <- env %>%
73+
reset() %>%
74+
run() %>%
75+
get_mon_arrivals()
76+
77+
expect_equal(df1, df2)
6178
})
6279

6380
test_that("preemptible < priority shows a warning", {

0 commit comments

Comments
 (0)