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#

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

HARP vs GARP#

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#

Product Space vs Characteristics Space#

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:

\[u_s - u_t \leq \lambda_t p_t \cdot (x_s - x_t) \quad \forall s, t\]

Where:

  • \(u_t\) = utility at observation \(t\)

  • \(\lambda_t\) = marginal utility of money at \(t\)

Utility Recovery Interpretation#

Value

Meaning

utility_values

Ordinal utility indices (relative ranking matters)

lagrange_multipliers

Marginal utility of money (shadow price of budget)

success=True

A rationalizing utility function exists

success=False

GARP violated; no consistent utility exists

See Also#