| Title: | Simulate Outcomes of a Latent State Reinforcement Learning Model |
|---|---|
| Description: | Simulates outcomes of an updated version of the latent state reinforcement learning model originally described in Cochran and Cisler (2019) <doi:10.1371/journal.pcbi.1007331>. The package is designed to create results under all reasonable experiment setups, including different reinforcement schedules, number of cues, number of phases, and number of options per trial. Participants can be simulated using either fixed parameters or parameters drawn from a distribution. |
| Authors: | Martin Benada [aut, cre] |
| Maintainer: | Martin Benada <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 1.0.0 |
| Built: | 2026-09-18 08:59:46 UTC |
| Source: | https://github.com/cran/latentState |
Simulates outcomes of an updated version of the latent state reinforcement learning model originally described in Cochran and Cisler (2019) doi:10.1371/journal.pcbi.1007331. The package is designed to create results under all reasonable experiment setups, including different reinforcement schedules, number of cues, number of phases, and number of options per trial. Participants can be simulated using either fixed parameters or parameters drawn from a distribution.
Maintainer: Martin Benada [email protected]
Authors:
Martin Benada [email protected]
Useful links:
run()
Constructs the c_vec (cue array) and win (reward array)
needed for the my_world argument of run(), letting you
specify an exact trial-by-trial cue and reward sequence instead of
having one randomly generated from phase_def.
make_world(trial_patterns, reward, L = 10, features = NULL)make_world(trial_patterns, reward, L = 10, features = NULL)
trial_patterns |
Character vector, one element per trial, giving
the cues shown on each arm. Use letters for cues, |
reward |
Numeric vector, or list of numeric vectors. Gives the
reward value for each trial, applied identically to every arm on that
trial regardless of which arm is later chosen by the agent (unlike
|
L |
Integer. The total number of latent states the resulting
|
features |
Character vector, or |
A list with three elements, matching the format run()
expects for my_world:
c_vecArray (D x C x L x A x ntrials) of 0/1
cue activations, indicating which cues are active on each arm and
trial, identical across every latent state.
winArray (D x A x ntrials) of reward values,
with the same value broadcast across every arm on a given trial.
type_seqA one-element list wrapping
trial_patterns, matching the phase-structured format
run() produces internally.
my_world <- make_world( trial_patterns = c("A", "A", "B", "A", "B"), reward = c(1, 0, 1, 1, 0), L = 10 ) phase_def <- list(phase1 = list(trials = list(A = 3, B = 2))) result <- run(phase_def, n = 1, my_world = my_world)my_world <- make_world( trial_patterns = c("A", "A", "B", "A", "B"), reward = c(1, 0, 1, 1, 0), L = 10 ) phase_def <- list(phase1 = list(trials = list(A = 3, B = 2))) result <- run(phase_def, n = 1, my_world = my_world)
Overlays results from multiple run() calls (e.g. different
groups, conditions, or parameter settings) on the same plots, allowing
direct visual comparison. Cues are distinguished by color and groups by
line type (or by color alone, for the presentation-based plots).
plot_compare( ..., plot = FALSE, plot_avg = FALSE, fixed_axis = TRUE, plot_sd = FALSE, plot_label = FALSE, plot_shown = FALSE, plot_cue = FALSE, plot_appear = FALSE )plot_compare( ..., plot = FALSE, plot_avg = FALSE, fixed_axis = TRUE, plot_sd = FALSE, plot_label = FALSE, plot_shown = FALSE, plot_cue = FALSE, plot_appear = FALSE )
... |
One or more outputs of |
plot |
Logical. If |
plot_avg |
Logical. If |
fixed_axis |
Logical. If |
plot_sd |
Logical. If |
plot_label |
Logical. If |
plot_shown |
Logical. If |
plot_cue |
Logical. If |
plot_appear |
Logical. If |
No return value. Called for its side effect of producing one or
more base R plots comparing latent-state values across the supplied
groups. Invisibly returns NULL.
phase_def <- list(phase1 = list(trials = list(A = 20, B = 20))) ctrl <- run(phase_def, n = 5, alpha0 = "0.1") treatment <- run(phase_def, n = 5, alpha0 = "0.3") plot_compare(ctrl = ctrl, treatment = treatment, plot_avg = TRUE)phase_def <- list(phase1 = list(trials = list(A = 20, B = 20))) ctrl <- run(phase_def, n = 5, alpha0 = "0.1") treatment <- run(phase_def, n = 5, alpha0 = "0.3") plot_compare(ctrl = ctrl, treatment = treatment, plot_avg = TRUE)
Simulates outcomes of an updated latent-state reinforcement learning model (based on Cochran & Cisler, 2019) across one or more participants, under a user-specified experimental design. For full mathematical details of the underlying latent-state learning model, including changes from the original Cochran & Cisler model, see the supplementary materials on OSF: https://osf.io/2whcu
run( phase_def, n = 1, seed = 42, alpha0 = "0.2", alpha1 = "0.05", alpha2 = "0.05", gamma = "0.01", eta = "1.2", delta = "0.6", sigma0 = "0.5", tau = "10", lambda = "1", pseudo = NULL, block = NULL, probabilistic = FALSE, features = NULL, V_noise_sd = 0, ncop = 10, group = "ctrl", prev = 0, ITI = NULL, ezITI = NULL, chi = "1", contextShift = NULL, my_world = NULL, initialex = NULL, plot = FALSE, plot_all = FALSE, plot_label = FALSE, plot_arm = FALSE, plot_mu = FALSE, plot_mu_all = FALSE, plot_shown = FALSE, plot_cue = FALSE, plot_sd = FALSE, plot_raw = FALSE, plot_raw_all = FALSE, plot_q = FALSE, plot_q_all = FALSE, plot_sigma = FALSE, plot_sigma_all = FALSE, plot_appears = FALSE, fixed_axis = TRUE )run( phase_def, n = 1, seed = 42, alpha0 = "0.2", alpha1 = "0.05", alpha2 = "0.05", gamma = "0.01", eta = "1.2", delta = "0.6", sigma0 = "0.5", tau = "10", lambda = "1", pseudo = NULL, block = NULL, probabilistic = FALSE, features = NULL, V_noise_sd = 0, ncop = 10, group = "ctrl", prev = 0, ITI = NULL, ezITI = NULL, chi = "1", contextShift = NULL, my_world = NULL, initialex = NULL, plot = FALSE, plot_all = FALSE, plot_label = FALSE, plot_arm = FALSE, plot_mu = FALSE, plot_mu_all = FALSE, plot_shown = FALSE, plot_cue = FALSE, plot_sd = FALSE, plot_raw = FALSE, plot_raw_all = FALSE, plot_q = FALSE, plot_q_all = FALSE, plot_sigma = FALSE, plot_sigma_all = FALSE, plot_appears = FALSE, fixed_axis = TRUE )
phase_def |
A named list defining the task structure. Each element
represents one phase of the experiment and must contain two entries,
A simple example using a single reward dimension and one option per
trial is shown below. In phase 1, cue
phase_def <- list(
phase1 = list(
trials = list(A = 6, AB = 6),
rewards = list(c(A = 1))
),
phase2 = list(
trials = list(A = 8, AB = 16)
)
)
In experiments with multiple arms (choices), indicate the cues shown on
each arm within a trial type name, separating arms with See Examples below for a |
n |
Integer. The number of participants to simulate. Each participant
is run independently through the full task defined by |
seed |
Integer. A random seed passed to |
alpha0 |
Character string. The learning rate controlling how quickly
associative strengths ( |
alpha1 |
Character string. The learning rate controlling how quickly
the variance estimate ( |
alpha2 |
Character string. The learning rate controlling how quickly
the effort matrix ( |
gamma |
Character string. Controls the rate at which latent-state
beliefs drift toward a uniform distribution over active states between
trials. This same drift also determines the prior belief
assigned to a newly created latent state: when a new state is added, it
is initialized with a prior belief of |
eta |
Character string. The change-point threshold: a new latent
state is created once the accumulated change-point statistic reaches or
exceeds this value. Must evaluate to a non-negative numeric value,
where higher values make new-state creation less likely (requiring
stronger, sustained evidence of a change before splitting off a new
state). Passed as a string so it can specify either a fixed value (e.g.
|
delta |
Character string. A penalty that makes it harder for a new
latent state to be created. Each trial, this penalty is subtracted from
the evidence accumulating for a new state; if the evidence that trial
isn't strong enough to outweigh the penalty, the accumulated evidence
for a new state will decrease rather than increase. Higher
values raise the bar for what counts as strong enough evidence, so with
a large |
sigma0 |
Character string. The agent's initial assumption about how
much variability in outcomes is "expected," used to judge whether a
prediction error is surprising enough to be considered evidence for a new state. A
higher |
tau |
Character string. The inverse temperature parameter controlling
how deterministic choices are. Higher values make the agent more likely
to consistently pick the option with the highest expected value, while
lower values make choices more random, giving lower-valued options a
better chance of being picked anyway. Must evaluate to a positive
numeric value. Passed as a string so it can specify either a fixed
value (e.g. |
lambda |
Character string. Controls how much more strongly beliefs
update on trials that are especially informative about which latent
state is active. Informativeness is measured by how unevenly the
evidence favors one state over the others on that trial.
When one state clearly stands out, |
pseudo |
Integer or |
block |
Integer, numeric vector, or |
probabilistic |
Logical. If |
features |
Character vector, or To track only a subset of these – for example, dropping |
V_noise_sd |
Numeric. Standard deviation of Gaussian noise added to
the agent's associative strengths ( |
ncop |
Integer >= 1. Maximum number of latent states the agent can create. Default is 10. |
group |
Character. Label for this batch's experimental group
(e.g. |
prev |
Integer. Offset added to subject IDs in the long-format
output ( |
ITI |
List of numeric vectors, or For example, with |
ezITI |
List, or For example, with |
chi |
Character. The number of "rumination" iterations the agent
performs on a single trial's outcome before moving to the next trial.
Higher values let the agent update its associative strengths
repeatedly from the same outcome, simulating extra "thinking time"
between trials. The actual number of iterations used is capped by the
|
contextShift |
Numeric vector, or For example, |
my_world |
List, or |
initialex |
Numeric array, or |
plot |
Logical. If |
plot_all |
Logical. Same as |
plot_label |
Logical. If |
plot_arm |
Logical. If |
plot_mu |
Logical. If |
plot_mu_all |
Logical. Same as |
plot_shown |
Logical. If |
plot_cue |
Logical. If |
plot_sd |
Logical. If |
plot_raw |
Logical. If |
plot_raw_all |
Logical. Same as |
plot_q |
Logical. If |
plot_q_all |
Logical. Same as |
plot_sigma |
Logical. If |
plot_sigma_all |
Logical. Same as |
plot_appears |
Logical. If |
fixed_axis |
Logical. If |
A list of length n, one element per participant. Each
element is itself a list containing:
arm_chosenInteger vector of length ntrials
giving the arm chosen by the agent on each trial.
win_receivedMatrix (ntrials x D) of the reward
outcome received on each trial, for each reward dimension.
lsbMatrix (ntrials x L) of latent-state
beliefs at the start of each trial, where ncop is the total
number of latent states.
LmaxInteger vector of length ntrials giving
the number of active latent states at each trial.
qNumeric vector of length ntrials giving the
change-point statistic after that trial's reward but before any
new-state creation/reset (the value used for plotting).
sigmaNumeric vector of length ntrials giving
the agent's variance estimate at the start of each trial.
muArray (ntrials x D x A) of the
overall expected value V of each arm, for each reward
dimension, before the agent's choice on each trial.
mu_rawArray (ntrials x D x L x A) of the
unweighted expected value of each arm, shown separately for each latent
state, for each reward dimension.
VNamed list with one entry per base cue, each a
matrix (ntrials x D) of that cue's overall
associative strength over trials.
V_cueNamed list with one entry per base cue, each a matrix (presentations x D) of that cue's own overall value, recorded only on trials where the cue was shown.
V_rawNamed list with one entry per base cue, each an
array (ntrials x D x L) of that cue's raw (unweighted)
associative strength in every latent state over trials.
V_shownNamed list with one entry per trial type
(e.g. "A", "AB"), each a matrix (presentations x D)
of the agent's total V whenever that exact trial type was the
chosen arm.
V_appearNamed list with one entry per base cue, each a matrix (presentations x D) of the agent's total V on the chosen arm, recorded whenever that cue was part of the chosen arm.
BArray (ntrials x C x C x D x L) giving the
effort matrix, which governs cue associability, for every cue
pair, reward dimension, and latent state, at every trial.
parThe full parameter and task configuration used to
generate this participant. The most useful pieces are ls
(the exact parameters used
for this participant, e.g. alpha0, eta, delta)
and tau (the inverse-temperature parameter used). The
remaining fields (D, C, A, ntrials,
base_cues, ITI, etc.) describe the task's structure and
are mainly used internally (e.g. by plot_compare()) to
recover cue counts, trial counts, and timing.
worldList of the two arrays defining what was
presented each trial: c_vec (D x C x L x A x
ntrials), which cues were active per dimension, latent state,
and arm; and win (D x A x ntrials), the reward
generated for each arm and dimension, regardless of the agent's
choice. Also includes type_seq, which is a list
showing the order of cues presented to this participant.
longList (one entry per phase) of data frames
combining every cue type presented in that phase, in long format,
for D = 1 only, intended for running an ANOVA using the
ezANOVA package. Columns are: subject, the participant ID
(i + prev, offset so IDs don't collide across combined
run() calls); group, the batch label from the
group argument; cue_type, the trial type or arm
segment (e.g. "A", "AB") this row belongs to;
presentation, the ordinal position of this row among all
presentations of that cue type within this phase; V, the
agent's overall associative value on that presentation; and, when
block is specified, block, the block number that
presentation falls into.
Cochran, A. L., & Cisler, J. M. (2019). A flexible and generalizable model of online latent-state learning. PLOS Computational Biology, 15(9). doi:10.1371/journal.pcbi.1007331
phase_def <- list( phase1 = list( trials = list( A_B = 20, B_A = 10, AB_C = 12, C_AB = 6, B_0 = 5 ), rewards = list( D1 = c(A = 0.80, B = 0.20, AB = 0.50), D2 = c(A = 0.60, B = 0.00, AB = 0.00) ) ), phase2 = list( trials = list( A_B = 15, B_A = 15, AB_C = 8, C_AB = 8 ), rewards = list( D1 = c(A = 0.10, B = 0.50, C = 0.00, AB = 0.25), D2 = c(A = 0.00, B = 0.60, AB = 0.00) ) ) ) result <- run(phase_def, n = 5)phase_def <- list( phase1 = list( trials = list( A_B = 20, B_A = 10, AB_C = 12, C_AB = 6, B_0 = 5 ), rewards = list( D1 = c(A = 0.80, B = 0.20, AB = 0.50), D2 = c(A = 0.60, B = 0.00, AB = 0.00) ) ), phase2 = list( trials = list( A_B = 15, B_A = 15, AB_C = 8, C_AB = 8 ), rewards = list( D1 = c(A = 0.10, B = 0.50, C = 0.00, AB = 0.25), D2 = c(A = 0.00, B = 0.60, AB = 0.00) ) ) ) result <- run(phase_def, n = 5)