TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/salesforce/ai-economist/llms.txt
Use this file to discover all available pages before exploring further.
redistribution.py module contains two components that handle fiscal policy in Foundation simulations: WealthRedistribution for simple equal redistribution, and PeriodicBracketTax for a full-featured bracket tax system with multiple policy models. The file also defines a related helper component SimpleLabor (in simple_labor.py) covered at the end of this page.
WealthRedistribution
Class name:WealthRedistribution — registry name "WealthRedistribution".
A passive component that redistributes the total coin endowment of all mobile agents as evenly as possible at every timestep. It adds no actions and no observations.
How it works
On eachcomponent_step():
- Sums the inventory and escrow coin across all agents:
tc = sum(inventory_coin + escrow_coin). - Computes the equal target share:
target = tc / n_agents. - Sets each agent’s inventory coin to
target - agent_escrow_coin.
Coin.
PeriodicBracketTax
Class name:PeriodicBracketTax — registry name "PeriodicBracketTax", component type "PeriodicTax".
Periodically collects income taxes from agents using a configurable marginal bracket schedule and redistributes the total tax revenue as an equal lump-sum payment to all agents. Supports four tax policy models including a learned planner, US federal rates, the Saez optimal formula, and user-supplied fixed rates.
Required world entities: Coin. Applies to both BasicMobileAgent and BasicPlanner.
Constructor parameters
When
True, forces all tax rates to 0 while preserving the full observation space. Useful for controlled no-tax baseline comparisons.Which policy determines tax rates each period.
| Value | Description |
|---|---|
"model_wrapper" | Tax rates set by the planner agent’s actions |
"saez" | Rates computed from the Saez (2001) optimal taxation formula |
"us-federal-single-filer-2018-scaled" | Scaled US federal 2018 single-filer rates |
"fixed-bracket-rates" | Rates supplied in fixed_bracket_rates |
Length of one tax period in environment timesteps. Taxes are updated at the start and collected at the end of each period. Must be
> 0.Minimum allowable marginal tax rate for any bracket. Must be
>= 0.Maximum allowable marginal tax rate for any bracket. Must be
<= 1.Step size between discrete rate options available to the planner. Only applies when
tax_model == "model_wrapper". Must be > 0 and < 1. A value of 0.05 gives rate choices [0.0, 0.05, 0.10, ..., 1.0].Number of tax brackets. Must be
>= 2. Ignored when bracket_spacing == "us-federal" (which always uses 7 brackets).Income level (in coin) at the left edge of the top bracket. Must be
>= 10. Ignored for "us-federal" bracket spacing.Divisor applied to US federal bracket cutoffs when
bracket_spacing == "us-federal". Must be > 0.How bracket cutoff incomes are spaced.
| Value | Description |
|---|---|
"us-federal" | Uses scaled 2018 US federal cutoffs (7 brackets, ignores n_brackets and top_bracket_cutoff) |
"linear" | Linearly spaced from 0 to top_bracket_cutoff |
"log" | Logarithmically spaced from 0 to top_bracket_cutoff |
Required when
tax_model == "fixed-bracket-rates". A list of fixed marginal rates, one per bracket. All values must be in [0, 1] and the list length must equal the number of brackets.Pareto welfare weights used in the Saez formula. Only applies when
tax_model == "saez".| Value | Weight |
|---|---|
"inverse_income" | 1 / max(1, income) |
"uniform" | 1 for all agents |
If provided, uses this fixed elasticity value in the Saez formula instead of estimating it empirically via OLS regression. Must be
>= 0. Only applies when tax_model == "saez".A two-element list
[warmup_steps, slope] defining a tax annealing schedule. During warmup, the maximum tax rate is gradually increased from 0 to rate_max. Default is no annealing.Tax period cycle
Each timestepcomponent_step() advances a cycle counter:
- First day of a new period (
tax_cycle_pos == 1): New tax rates are computed and applied according to the chosentax_model. - Last day of the period (
tax_cycle_pos >= period):enact_taxes()is called, which:- Computes each agent’s income for the period as
current_total_endowment - last_period_endowment. - Applies the bracket schedule to compute taxes owed.
- Deducts taxes from each agent’s inventory coin (never from escrow).
- Distributes an equal lump-sum
net_tax_revenue / n_agentsto every agent.
- Computes each agent’s income for the period as
Tax bracket configuration
Brackets are defined bybracket_cutoffs (left edges) and bracket_edges (left + right edges, where the top bracket extends to infinity).
The US federal 2018 brackets (before usd_scaling) use cutoffs at:
$0, $9,700, $39,475, $84,200, $160,725, $204,100, $510,300 with rates 10%, 12%, 22%, 24%, 32%, 35%, 37%.
Planner actions (model_wrapper mode)
When tax_model == "model_wrapper" and taxes are not disabled, the BasicPlanner receives one action sub-space per bracket:
| Action name | Size | Description |
|---|---|---|
TaxIndexBracket_{cutoff:03d} | n_disc_rates | Selects the marginal rate index for this bracket |
These actions are only unmasked on the first timestep of each new tax period (
tax_cycle_pos == 1). On all other timesteps the planner is forced to take a no-op.Saez tax policy
Whentax_model == "saez", the component adapts Saez’s theoretical optimal income tax formula to the discrete bracket setting:
- Maintains a rolling buffer of
(income, marginal_rate)pairs sampled across agent-periods. - Estimates income elasticity via OLS regression on
log(income)vs.log(1 - marginal_rate). - Computes binned welfare weights
g(z)and inverse Pareto parametersA(z). - Derives marginal rates via
tau(z) = (1 - g(z)) / (1 - g(z) + A(z) * elasticity). - Maps the resulting schedule onto the configured tax brackets.
FixedBracketTax / US federal rates
"fixed-bracket-rates": Rates provided viafixed_bracket_ratesare applied unchanged each period, capped byrate_max."us-federal-single-filer-2018-scaled": The statutory 2018 rates[10%, 12%, 22%, 24%, 32%, 35%, 37%]are applied, scaled byusd_scalingon bracket cutoffs, and capped byrate_max.
Observations
Agent observations
1.0 if taxes will be collected this timestep, 0.0 otherwise.1.0 if this is the first day of a new tax period, 0.0 otherwise.Fractional position within the current tax period (
tax_cycle_pos / period).Sorted array of all agents’ incomes from the previous tax period (normalized by
period).Current marginal tax rates for each bracket.
The marginal rate that would apply to this agent’s current income-to-date.
Planner observations (keyed "p{agent_idx}" per agent)
Agent’s normalized income from the last tax period.
Marginal rate that was applied to this agent in the last period.
Marginal rate that would apply to this agent’s current income-to-date.
Metrics
Average marginal rate used for this bracket over the episode.
Fraction of observed agent-periods that fell within this bracket.
Mean effective (not marginal) tax rate across all agent-periods. Not reported when
disable_taxes=True.Total coin collected as taxes over the episode.
Episode-average effective tax rate paid by the agent with the lowest total coin endowment.
Episode-average effective tax rate paid by the agent with the highest total coin endowment.
Running estimate of income elasticity. Only present when
tax_model == "saez".Dense log
get_dense_log() returns a list with one entry per timestep. Entries are empty except on tax days. Tax-day entries include:
Array of marginal tax rates applied this period.
Array of bracket left-edge cutoff incomes.
Per-agent tax data with fields:
income, tax_paid, marginal_rate, effective_rate, lump_sum.SimpleLabor
Class name:SimpleLabor — registry name "SimpleLabor" (defined in simple_labor.py).
SimpleLabor is a companion component intended for use with PeriodicBracketTax in the one-step-economy scenario. It simplifies labor to a 1-D choice: agents select how many hours to work (0–100) and earn income equal to hours * skill, where skill is pre-assigned from a sorted Pareto distribution.
Key parameters
When
True, all non-zero labor actions are masked on the environment’s first step. This allows the planner to set tax rates before agents choose their labor supply.Upper bound on sampled skill values. Skills are drawn from a Pareto distribution and clipped to this maximum.
Shape parameter of the Pareto distribution used to sample agent skills.
Action space
100 discrete actions — actionk means working k hours. Action 0 is no-op (0 hours). Income earned = k * agent.state["skill"].
Agent state fields
Wage rate assigned to the agent. Determined by rank-ordering Pareto samples so each agent consistently occupies a skill rank across episodes.
Cumulative coin earned by this agent through labor this episode.