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