agent_urban_planning.AhlfeldtABMEngine

class AhlfeldtABMEngine(params, *, shock_distribution='frechet', num_agents=1000000, batch_size=10000, seed=None, store_agent_samples=0, **kwargs)[source]

Bases: AhlfeldtUtilityEngine

Monte Carlo argmax decision engine with configurable shock distribution.

The ABM substitute for V1’s closed-form softmax. Drives paper variants V2 (Fréchet shocks) and V3 (variance-matched Gaussian shocks). Replaces the Fréchet softmax step with an explicit per-agent argmax over drawn shocks, while keeping the rest of the Ahlfeldt FOC machinery (housing market clearing, firm labor FOC) unchanged. The exposed empirical choice matrix last_choice_probabilities lets AhlfeldtMarket consume the result as if it came from the closed-form path. Most users should configure this through UtilityEngine rather than instantiating it directly.

Parameters:
  • params (AhlfeldtParams) – Structural parameters.

  • shock_distribution (str) – "frechet" for V2 or "normal" for V3 (variance-matched to Gumbel so V2 vs V3 is a pure shape test).

  • num_agents (int) – Number of Monte Carlo replicates M.

  • batch_size (int) – Per-batch chunk size for memory bookkeeping.

  • seed (Optional[int]) – Optional integer seed. Passed to the parent class.

  • store_agent_samples (int) – Cap on per-agent sample records to retain for diagnostics. 0 (default) skips sampling.

  • **kwargs – Forwarded to AhlfeldtUtilityEngine.

Raises:

ValueError – If shock_distribution is not "frechet" / "normal", or if num_agents / batch_size is non-positive.

Examples

>>> import agent_urban_planning as aup
>>> # Prefer the public wrapper:
>>> # engine = aup.UtilityEngine(params, mode="argmax", noise="frechet")

References

Ahlfeldt, G. M., Redding, S. J., Sturm, D. M., Wolf, N. (2015). The economics of density: Evidence from the Berlin Wall. Econometrica, 83(6), 2127-2189.

decide_batch(agents, environment, zone_options, prices)[source]

Run M independent argmax-over-shocks draws and aggregate the results.

Builds a shared utility matrix V[i, j] once, then in batches of self.batch_size draws independent (N, N) shock tensors, adds them to V, and takes per-agent argmax to produce the empirical choice matrix consumed by AhlfeldtMarket.

Parameters:
  • agents (list[Agent]) – Canonical agent list (typically length 1 — a single representative type — since preferences are homogeneous across all M Monte Carlo replicates). The number of MC agents is controlled by self.num_agents, not len(agents).

  • environment – The Environment carrying zones and travel-time matrix.

  • zone_options (list[str]) – Allowed zones.

  • prices (dict) – Mapping zone -> Q_i.

Return type:

list[LocationChoice]

Returns:

List of LocationChoice, one per input agent. self.last_choice_probabilities is set to the empirical M-sample choice matrix.

Examples

>>> import agent_urban_planning as aup
>>> # engine = aup.UtilityEngine(params, mode="argmax", noise="frechet",
>>> #                            num_agents=1_000_000)
>>> # choices = engine.decide_batch([rep_agent], env, zones, prices)