Tutorial 1a: Advanced Budget Analysis#
This tutorial covers advanced topics in budget-constrained revealed preference analysis, including homothetic preferences, the Lancaster characteristics model, and latent utility recovery.
Topics covered:
Homothetic preferences (HARP)
The Lancaster characteristics model
Piecewise-linear utility recovery (Afriat’s theorem)
Marginal utility of money
Prerequisites#
Python 3.10+
Completed Tutorial 1: Budget-Based Analysis (Basics)
Basic understanding of linear programming
Note
These methods are grounded in the Lancaster (1966) model and Afriat (1967) construction theorem.
Part 1: Homothetic Preferences (HARP)#
HARP (Homothetic Axiom of Revealed Preference) tests whether demand scales proportionally with income. Homothetic preferences mean the consumer buys the same proportions of goods regardless of budget level-only the scale changes.
from prefgraph import BehaviorLog, validate_proportional_scaling
# log from Tutorial 1
result = validate_proportional_scaling(log)
if result.is_consistent:
print("Homothetic preferences: demand scales proportionally")
else:
print(f"Non-homothetic: {len(result.violations)} scaling violations")
print(f"Max expenditure ratio product: {result.max_cycle_product:.3f}")
Output:
Non-homothetic: 3 scaling violations
Max expenditure ratio product: 1.234
When HARP Matters#
HARP is a stronger requirement than GARP. Use it when:
Aggregating demand across different income levels
Extrapolating demand to unobserved budget levels
Testing constant-returns-to-scale demand models
Validating Cobb-Douglas or CES utility assumptions
Condition |
GARP |
HARP |
|---|---|---|
Consistent ordinal preferences |
Required |
Required |
Proportional budget shares |
Not required |
Required |
Typical pass rate (field data) |
5-15% |
1-5% |
Part 2: The Lancaster Model#
The Lancaster model assumes utility derives from characteristics (e.g., nutrition) rather than products directly: \(U(x) = u(Zx)\) where \(Z\) maps products to characteristics.
When Does Lancaster Help?#
CCEI Increases |
CCEI Decreases |
|---|---|
Consumer optimizes over characteristics |
Consumer has product-specific preferences |
Products are imperfect substitutes for characteristics |
Brand loyalty matters |
Characteristics matrix is well-specified |
Characteristics matrix is wrong |
import numpy as np
from prefgraph import transform_to_characteristics, validate_consistency
# Nutritional characteristics: [Protein, Carbs, Fat, Sodium]
Z = np.array([
[0, 39, 0, 15], # Soda
[8, 12, 8, 120], # Milk
[9, 49, 3, 490], # Bread
[25, 1, 33, 620], # Cheese
# ... etc
])
lancaster_log = transform_to_characteristics(log, Z)
result = validate_consistency(lancaster_log)
print(f"Lancaster consistent: {result.is_consistent}")
Output:
Lancaster consistent: True
Results Comparison#
Metric |
Product Space |
Characteristics Space |
|---|---|---|
Mean CCEI |
~0.84 |
~0.89 (+5%) |
GARP pass rate |
~5% |
~8% (+60%) |
Part 3: Utility Recovery#
For GARP-consistent households, we can recover the utility function that rationalizes their choices using Afriat’s theorem.
from prefgraph import fit_latent_values
# For a GARP-consistent household
result = fit_latent_values(log)
if result.success:
print(f"Recovery successful!")
print(f"Utility values: {result.utility_values[:5]}...") # First 5
print(f"Marginal utility of money: {result.lagrange_multipliers[:5]}...")
else:
print(f"Recovery failed: {result.lp_status}")
Output:
Recovery successful!
Utility values: [0.000e+00 1.234e-05 2.468e-05 3.702e-05 4.936e-05]...
Marginal utility of money: [1.000e-06 1.000e-06 1.000e-06 1.000e-06 1.000e-06]...
Interpreting Results#
The recovered values satisfy Afriat’s inequalities:
Where:
\(u_t\) = utility at observation \(t\)
\(\lambda_t\) = marginal utility of money at \(t\)
Value |
Meaning |
|---|---|
|
Ordinal utility indices (relative ranking matters) |
|
Marginal utility of money (shadow price of budget) |
|
A rationalizing utility function exists |
|
GARP violated; no consistent utility exists |
See Also#
Tutorial 1: Budget-Based Analysis - Basic budget analysis