The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

masc: Multi-Attribute Search and Choice Model in R

Lifecycle: experimental

Overview

The masc package implements the Multi-Attribute Search and Choice (MASC) model, a hierarchical Bayesian framework for understanding how people make decisions between options with multiple attributes. Based on the work by Gluth, Deakin, & Rieskamp (2026), this package simulates:

Installation

# Install from CRAN
install.packages("masc")

# Or the development version from GitHub
devtools::install_github("kiante-fernandez/masc")

Basic Usage

Simple Random Trials

library(masc)

# Generate 5 random trials
results <- rMASC(
  n = 5,
  w = c(0.5, 0.3, 0.2)  # weights for attributes
)

# View results
print(results$results)

Custom Attribute Values

# Create trial data
trial_data <- data.frame(
  # Option 1's attributes across 3 trials
  opt1_att1 = c(4.5, 4.2, 4.8),  # Attribute 1 values
  opt1_att2 = c(3.2, 3.5, 3.1),  # Attribute 2 values
  opt1_att3 = c(2.8, 2.9, 2.7),  # Attribute 3 values
  # Option 2's attributes across 3 trials
  opt2_att1 = c(3.8, 3.9, 3.7),  # Attribute 1 values
  opt2_att2 = c(4.1, 4.0, 4.2),  # Attribute 2 values
  opt2_att3 = c(3.1, 3.3, 3.0)   # Attribute 3 values
)

# Run model with custom data
results <- rMASC(
  data = trial_data,
  w = c(0.5, 0.3, 0.2)  # weights for attributes
)

Correlated Attributes (MASC-C)

By default attributes are treated as independent, reproducing the original MASC model. Supplying a correlation structure switches on the multivariate MASC-C belief update, in which observing one attribute updates beliefs about correlated attributes (“belief spread”). Positive correlations speed up decisions; negative correlations slow them down.

# Decision maker exploits a positive correlation structure (rho = 0.6)
results <- rMASC(
  n = 100,
  w = c(0.5, 0.3, 0.2),
  Sigma_true   = 0.6,   # stimuli are positively correlated
  Sigma_belief = 0.6    # and the agent knows it (matched beliefs)
)

# Full correlation matrices are also accepted, and the agent's beliefs may
# differ from the true environment (belief-environment mismatch):
Sigma <- matrix(c(1.0, 0.5, -0.3,
                  0.5, 1.0,  0.0,
                 -0.3, 0.0,  1.0), 3, 3, byrow = TRUE)
results <- rMASC(n = 100, w = c(0.5, 0.3, 0.2),
                 Sigma_true = Sigma, Sigma_belief = 0)  # agent assumes independence

When Sigma_belief is diagonal (or 0) the model reduces exactly to the original univariate MASC update.

Example use

library(masc)
library(ggplot2)
library(dplyr)
library(tidyr)
library(patchwork)

# Set simulation parameters
params <- list(
  n = 100,              # Number of trials
  n_options = 2,        # Number of choice options
  n_attributes = 3,     # Number of attributes per option
  w = c(0.5, 0.3, 0.2), # Weights for each attribute
  sigma = 1,            # Sampling noise
  alpha = 3,            # Search sensitivity
  delta = 0.01,         # Threshold increment
  theta = 0.01,         # Initial threshold
  lambda = 1,           # Prior precision
  max_steps = 100       # Maximum fixations allowed
)

# Run simulation
set.seed(123)
results <- do.call(rMASC, params)

# Process choice proportions
choice_props <- results$results %>%
  mutate(Choice = factor(response, labels = c("Option1", "Option2"))) %>%
  group_by(Choice) %>%
  summarise(Proportion = n()/100)

# Process fixation data
total_counts <- numeric(params$n_options * params$n_attributes)
for(trial in results$raw) {
  fix_seq <- trial$fix_sequence
  trial_counts <- table(factor(fix_seq, 
                               levels = 1:(params$n_options * params$n_attributes)))
  total_counts <- total_counts + as.numeric(trial_counts)
}

# Create Option-Attribute-Pair (OAP) data
all_props <- total_counts / sum(total_counts)
oap_data <- data.frame(Proportion = all_props) %>%
  mutate(oap_number = 1:length(all_props)) %>%
  mutate(
    Option = paste0("Opt", ceiling(oap_number/3)),
    Attribute = paste0("Att", ((oap_number-1) %% 3) + 1)
  ) %>%
  select(Option, Attribute, Proportion)

# Define consistent theme
theme_masc <- function() {
  theme_classic() +
    theme(
      plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12, face = "bold"),
      axis.text = element_text(size = 11),
      legend.position = "bottom"
    )
}

# Create visualizations
# 1. Fixation Distribution
p1 <- ggplot(results$results, aes(x = rt, fill = factor(response))) +
  geom_histogram(position = "dodge", bins = 30, color = "white") +
  scale_fill_manual(values = c("#2171B5", "#CB181D"),
                    labels = c("Choice = Option1", "Choice = Option2")) +
  labs(title = "Number of Fixations", x = "Number of Fixations", y = "Count") +
  theme_masc()

# 2. Choice Probability
p2 <- ggplot(choice_props, aes(x = "", y = Proportion, fill = Choice)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = sprintf("%.2f", Proportion)), 
            position = position_stack(vjust = 0.5),
            color = "white", 
            size = 4) +
  scale_fill_manual(values = c("#2171B5", "#CB181D")) +
  labs(title = "Choice Probability", y = "Proportion", x = "Response") +
  theme_masc() +
  scale_y_continuous(limits = c(0, 1), breaks = seq(0, 1, 0.1))

# 3. OAP Heatmap
p3 <- ggplot(oap_data, aes(x = Attribute, y = Option, fill = Proportion)) +
  geom_tile(color = "white") +
  scale_fill_distiller(palette = "Blues", direction = 1) +
  geom_text(aes(label = sprintf("%.4f", Proportion)), size = 4) +
  labs(title = "Fixation Proportions by Option-Attribute Pair") +
  theme_masc()

# Combine plots
combined_plot <- p1 + p2 + p3 +
  plot_layout(ncol = 2) +
  plot_annotation(
    title = "Example: MASC Model Simulation Results",
    theme = theme(plot.title = element_text(size = 20, face = "bold", hjust = 0.5))
  )

# Display plot
print(combined_plot)

Function Parameters

The rMASC() function accepts the following parameters:

Output Structure

The function returns a list containing:

The raw component contains a list where each element corresponds to a trial and includes:

Reference

Gluth, S., Deakin, J., & Rieskamp, J. (2026). A theory of multiattribute search and choice. Psychological Review. https://doi.org/10.1037/rev0000614

License

This package is released under the MIT License.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.