agent_urban_planning.HousingMarket

class HousingMarket(price_elasticity=0.5, initial_damping=0.3, convergence_threshold=0.01, stall_threshold=1e-06, stall_window=10, max_iterations=1000, max_price_change_pct=0.5, verbose=False)[source]

Bases: object

Elasticity-based tatonnement with adaptive damping and two-segment clearing.

The legacy Singapore-style market clearer. Each zone has two housing segments: HDB (public) supply from zone.housing_supply whose prices adjust by tatonnement, and private supply from zone.private_supply whose prices are held exogenous. Agents with income above the HDB income ceiling are routed to the private segment; all others compete for HDB units. Convergence is evaluated on the HDB segment only. Budget constraints are enforced dynamically: at each iteration, each agent’s choice set is filtered by affordability at current prices.

Parameters:
  • price_elasticity (float) – Demand elasticity |eta| used to size the tatonnement step Delta p = (lambda / |eta|) * (excess / supply) * p. Defaults to 0.5 (Phang & Wong 1997 HDB estimate).

  • initial_damping (float) – Starting damping lambda. Adapts each iteration. Defaults to 0.3.

  • convergence_threshold (float) – Maximum absolute excess demand at which clearing is declared converged. Defaults to 0.01.

  • stall_threshold (float) – Minimum iter-to-iter residual change to avoid being flagged as stalled.

  • stall_window (int) – Consecutive stalled iterations before damping is boosted (and after the boost, the run terminates).

  • max_iterations (int) – Iteration cap on the tatonnement loop.

  • max_price_change_pct (float) – Per-iteration cap on relative price moves. Defaults to 0.5 (50%).

  • verbose (bool) – Whether to print progress.

Examples

>>> import agent_urban_planning as aup
>>> # Typically obtained from SimulationEngine.run() rather than built directly:
>>> # market = aup.HousingMarket(price_elasticity=0.5)
>>> # result = market.clear(population, environment, engine)

References

Phang, S.-Y., Wong, W. K. (1997). Government Policies and Private Housing Prices in Singapore. Urban Studies.

Scarf, H. (1973). The Computation of Economic Equilibria. Yale University Press.

clear(population, environment, engine, resume_state=None, checkpoint_callback=None, cache_path=None)[source]

Run tatonnement to find equilibrium prices and allocations.

Iteratively asks the decision engine to allocate the population, measures excess demand per zone, and updates HDB prices via the elasticity rule until either convergence or the stall/iteration cap is reached. Private-segment agents are placed once before the loop because their prices are exogenous.

Parameters:
  • population (AgentPopulation) – The AgentPopulation to allocate.

  • environment (Environment) – The Environment whose zones price.

  • engine (DecisionEngine) – A DecisionEngine invoked once per iteration via decide_batch (or decide if no batch path).

  • resume_state (Optional[dict]) – Optional checkpoint dict from a prior run to continue clearing from where it left off.

  • checkpoint_callback (Optional[Callable[[dict], None]]) – Optional callable receiving a JSON-serializable checkpoint dict at every iteration.

  • cache_path (Optional[str]) – Optional path to a disk-backed LLM cache, passed to engines that accept caches via set_cache.

Return type:

MarketResult

Returns:

A MarketResult with equilibrium prices, agent allocations, convergence info, and per-iteration history.

Examples

>>> import agent_urban_planning as aup
>>> # market = aup.HousingMarket()
>>> # result = market.clear(population, environment, engine)
>>> # result.converged
True