@@ -13,11 +13,12 @@ Trial <- R6::R6Class(
1313 observations = NULL ,
1414 outcomes = NULL ,
1515 metadata = list (),
16+ label = NULL ,
1617
1718 # ' @description Initialize a Trial with a model and functions
1819 # ' @param model An AgentBasedModel instance
1920 # ' @param metadata Label-value metadata store for trial information
20- initialize = function (model , metadata = list ()) {
21+ initialize = function (model , metadata = list (), label = NULL ) {
2122
2223 # Sync internal variables with user-provided.
2324 self $ model <- model
@@ -35,38 +36,25 @@ Trial <- R6::R6Class(
3536 # ' @param legacy_behavior The maladaptive behavior treated as "adaptation failure"
3637 # ' @param adaptive_behavior The behavior treated as "adaptation success"
3738 run = function (
38- stop = 50 , legacy_behavior = " Legacy" , adaptive_behavior = " Adaptive" ) {
39+ stop = 50 , legacy_behavior = " Legacy" ,
40+ adaptive_behavior = " Adaptive" , observe = " behavior" ) {
3941
4042 step <- 0
4143
4244 self $ model $ set_parameter(" legacy_behavior" , legacy_behavior )
4345 self $ model $ set_parameter(" adaptive_behavior" , adaptive_behavior )
4446 step <- 0
47+
4548 obs_list <- list ()
46- n_agents <- length(self $ model $ agents )
47-
48- obs_list [[1 ]] <- tibble :: tibble(
49- Step = 0 ,
50- agent = vapply(self $ model $ agents ,
51- \(a ) a $ name , character (1 )),
52- Behavior = vapply(self $ model $ agents ,
53- \(a ) as.character(a $ behavior_current ), character (1 )),
54- Fitness = vapply(self $ model $ agents ,
55- \(a ) a $ fitness_current , numeric (1 )),
56- label = self $ label
57- )
5849
5950 # Get learning and iteration functions from the model's learning strategy.
6051 lstrat <- self $ model $ get_parameter(" model_dynamics" )
6152 partner_selection <- lstrat $ get_partner_selection()
6253 interaction <- lstrat $ get_interaction()
6354 model_step <- lstrat $ get_model_step()
64-
65- # Main iteration loop.
66- while (TRUE ) {
67-
68- step <- step + 1
69-
55+
56+ repeat {
57+ # --- run one model step ---
7058 # Partner selection and interaction with selected partner.
7159 for (agent in self $ model $ agents ) {
7260 partner <- NULL
@@ -80,41 +68,40 @@ Trial <- R6::R6Class(
8068 if (! is.null(model_step )) {
8169 model_step(self $ model )
8270 }
83-
84- # Update observations.
85- obs_list [[step + 1 ]] <- tibble :: tibble(
86- Step = step ,
87- agent = vapply(self $ model $ agents , \(a ) a $ name , character (1 )),
88- Behavior = vapply(self $ model $ agents , \(a ) as.character(a $ behavior_current ), character (1 )),
89- Fitness = vapply(self $ model $ agents , \(a ) a $ fitness_current , numeric (1 )),
71+
72+ # --- collect observations via dispatcher ---
73+ obs_list [[step + 1 ]] <- observe_dispatch(
74+ self $ model ,
75+ type = observe ,
76+ step = step ,
9077 label = self $ label
9178 )
92-
93- # Stop when stop function returns TRUE or max steps reached.
94- if (is.function(stop )) {
95- if (stop(self $ model )) {
96- break
97- }
98- } else if (step > = stop ) {
99- break
100- }
101- } # End main iteration loop
102-
103- behaviors <- unlist(
104- purrr :: map(
105- self $ model $ agents , \(a ) as.character(a $ get_behavior())
106- ),
107- use.names = FALSE
108- )
79+
80+ # --- stopping condition ---
81+ step <- step + 1
82+ if (is.numeric(stop ) && step > = stop ) break
83+ if (is.function(stop ) && stop(self $ model )) break
84+ }
85+
86+ # bind all observations
10987 self $ observations <- dplyr :: bind_rows(obs_list )
110-
111- self $ outcomes $ adaptation_success <-
112- length(unique(behaviors )) == 1 &&
88+
89+ # if we observe behavior, identify whether this is adaptive success or not
90+ if (observe == " behavior" ) {
91+ behaviors <- unlist(
92+ purrr :: map(
93+ self $ model $ agents , \(a ) as.character(a $ get_behavior())
94+ ),
95+ use.names = FALSE
96+ )
97+ self $ outcomes $ adaptation_success <-
98+ length(unique(behaviors )) == 1 &&
11399 unique(behaviors ) == adaptive_behavior
100+
101+ self $ outcomes $ fixation_steps <- step
102+ }
114103
115- self $ outcomes $ fixation_steps <- step
116-
117- invisible (self )
104+ return (invisible (self ))
118105 },
119106
120107 # ' Add or update metadata in a Trial object
@@ -187,14 +174,15 @@ fixated <- function(model) {
187174# ' trial <- run_trial(model, stop = 10)
188175# ' @export
189176run_trial <- function (model ,
177+ observe = " behavior" ,
190178 stop = socmod :: fixated ,
191179 legacy_behavior = " Legacy" ,
192180 adaptive_behavior = " Adaptive" ,
193181 metadata = list ()) {
194-
182+
195183 # Initialize, run, and return a new Trial object.
196184 return (
197- Trial $ new(model = model , metadata = metadata )$ run(
185+ Trial $ new(model = model , metadata = metadata )$ run(
198186 stop = stop , legacy_behavior = legacy_behavior ,
199187 adaptive_behavior = adaptive_behavior
200188 )
@@ -234,7 +222,7 @@ run_trial <- function(model,
234222# ' )
235223# ' @export
236224run_trials <- function (model_generator , n_trials_per_param = 10 ,
237- stop = 10 , .progress = TRUE ,
225+ stop = 10 , .progress = TRUE , observe = " behavior " ,
238226 syncfile = NULL , overwrite = FALSE , ... ) {
239227
240228 # Check if syncfile is given...
@@ -270,7 +258,8 @@ run_trials <- function(model_generator, n_trials_per_param = 10,
270258
271259 run_trial(
272260 model , stop , legacy_behavior , adaptive_behavior ,
273- metadata = list (replication_id = param_list $ replication_id )
261+ metadata = list (replication_id = param_list $ replication_id ),
262+ observe = observe
274263 )
275264 },
276265 .progress = .progress
0 commit comments