Menus#
Menu choices. HM counts how many choices to discard to restore consistency.
Menu analysis tests whether choices from finite sets follow a stable ranking. There are no prices or budgets. The input is a sequence of menus paired with whichever option was picked from each one.
Subtype |
Input Class |
Description |
|---|---|---|
Deterministic |
|
menus → single choices (e.g., which product was clicked) |
Stochastic |
|
menus → choice frequencies (e.g., 60% A, 30% B, 10% C) |
Risk / Lotteries |
|
lotteries → choices (e.g., gamble A vs gamble B) |
from prefgraph import MenuChoiceLog, validate_menu_sarp, compute_menu_efficiency
# 4 observations: each menu is a set of item indices, choice is which was picked
log = MenuChoiceLog(
menus=[
frozenset({0, 1, 2}), # menu 1: {Pizza, Burger, Salad}
frozenset({1, 2, 3}), # menu 2: {Burger, Salad, Pasta}
frozenset({0, 3}), # menu 3: {Pizza, Pasta}
frozenset({0, 1, 3}), # menu 4: {Pizza, Burger, Pasta}
],
choices=[0, 1, 0, 0], # picked Pizza, Burger, Pizza, Pizza
item_labels=["Pizza", "Burger", "Salad", "Pasta"],
)
# SARP: are there any preference cycles? (stricter than WARP)
sarp = validate_menu_sarp(log)
# HM: fraction of choices consistent with a single ranking
hm = compute_menu_efficiency(log)
print(f"SARP consistent: {sarp.is_consistent}")
print(f"HM efficiency: {hm.efficiency_index:.2f}")
SARP consistent: True
HM efficiency: 1.00
Deterministic data feeds directly into Engine.analyze_menus() for batch Rust processing. Stochastic and risk data use the per-user Functions API because their inputs do not map to the tuple format the batch engine expects. The axioms and scores are identical across paths.