Economy and production API¶
Used by the economy guide and all optimization showcases.
For returned columns, see the production dictionary and economy-report dictionary.
EconomyState(context, market, households) composes EconomyContext,
MarketState, and PopState. All four are exported from vic3_analysis.
Flat attribute reads are preserved; constructors and replacements use the
component fields. market.context must be the exact same object as context.
Components own read-only copies of their arrays; constructing a complete state
does not copy its context or evaluate dependent results.
EconomyContext stores realized signed building_goods_flow quantities shaped
as configurations × goods, trade, workers, and workforce ratio. It derives goods
input/output totals and fixed orders. MarketState stores prices and derives
building surplus/deficit and GDP from those prices and the shared context.
PopState stores wealth, demand, and optional pop_income and pop_expenses.
Its derived pop_balance is None unless both finances exist. Nominal/market
solves leave these finances unevaluated; df_pop() reports balances as NaN.
Economy.prepare_context(context) returns a context with prepared baskets and
scales, computing only missing fields and returning a fully prepared context
unchanged. goods_buy_packages is an optional immutable GoodsBuyPackages object with
read-only quantities (wealth × goods) and ascending integer wealth labels;
it defaults to None. Construct it with GoodsBuyPackages(wealth=..., quantities=...)
or clear it with goods_buy_packages=None. consumption_scales is an optional
read-only configuration-by-profession array. Goods and profession axes follow
the owning economy's indexes. Existing solves leave these fields unprepared.
Economy.evaluate_wealth(context, pop_wealth) returns (market, households)
for one fixed wealth assignment. It automatically prepares missing context
baskets and scales, calculates demand and market prices, then evaluates income
and expenses at those prices. Balance is derived from the returned finances.
The market references the prepared context: fully prepared inputs retain their
identity; incomplete inputs produce a new context without modifying the original.
Compose the results with EconomyState(market.context, market, households).
See evaluating fixed wealth.
Economy.iterate(context, market, households, *, rtol=1e-9, atol=1e-8) returns
matching (MarketState, PopState) after one simultaneous one-tier wealth
transition. Initialize through evaluate_wealth() first: iteration trusts
economic consistency, requires evaluated finances and prepared consecutive
tiers, and shares the supplied context. An unchanged assignment returns the
same components. See iterating wealth
for affordability thresholds and numerical comparisons.
Economy.solve(..., method="equilibrium", initial_wealth=None,
max_iterations=1000, rtol=1e-9, atol=1e-8) calculates endogenous household
demand and returns a complete, verified state with equilibrium_diagnostics.
Fixed goods_import and goods_export orders are added independently to
supply and demand. The optional initial wealth is a full
configuration/profession integer matrix. Nominal/market modes ignore these
controls and leave diagnostics as None.
EquilibriumDiagnostics and EquilibriumError are exported from vic3_analysis.
The immutable diagnostics distinguish stationary wealth from financial
sustainability: unaffordable floor households and unfunded building losses
are flags on successful results. Errors retain .state and .diagnostics
for cycles, exhausted iterations, evaluation failures, and final-verification
failures. Setup/initial-evaluation errors remain ValueError. See
solving equilibrium for exception
handling and diagnostic fields.
Economy.pop_income(state) returns a fresh writable float64 matrix
of weekly cooperative income totals aligned to configurations × professions.
It allocates each configuration's positive surplus using employee counts times
profession wage weights, including professions with paid_private_wage=False.
It adds dependent earnings from profession dependent_wage values, converted
from annual to weekly amounts.
See the cooperative income guide
for accounting assumptions and failure behavior.
EconomyContext and Economy.solve() accept keyword-only workforce_ratio=1.0.
This uniform worker share must be in (0, 1]; dependents_per_worker is cached
as (1 - workforce_ratio) / workforce_ratio. pops and total_employment
count workers; total_population includes dependents. Scenario.workforce_ratio
passes the same assumption to optimizer-created states.
Economy.goods_buy_packages(state_or_context) returns immutable GoodsBuyPackages,
reusing prepared baskets when available. Its wealth labels and quantities
matrix are read-only; goods columns follow economy.goods_index order.
Economy.df_goods_buy_packages(source) exports a fresh mutable DataFrame from
an EconomyState, EconomyContext, or GoodsBuyPackages, copying both quantities and
wealth labels. The index is named wealth and columns follow goods_index.
The raw Economy.df_buy_packages input table remains separate and unchanged.
Economy.pop_consumption_scales(state_or_context) returns a fresh writable
float64 matrix of dimensionless household scales:
pops / 10_000 * consumption_mult * (1 + 0.5 * dependents_per_worker).
pop_buy_orders() and pop_expenses() accept keyword-only
goods_buy_packages: GoodsBuyPackages | None = None and consumption_scales=None to reuse baskets and scales
independently. Each omitted argument uses its prepared context value before
falling back to calculation. Explicit and prepared baskets share the same
selection and alignment checks; DataFrame basket arguments are rejected.
Supplied scales are authoritative, finite, nonnegative,
population-shaped, and zero for empty cells; profession multipliers are not
recomputed. Refresh them when the population assumptions change.
Economy.pop_expenses(state) returns a fresh writable float64 matrix
of weekly household consumption expenses aligned to configurations × professions.
It prices each wealth basket at the state's market prices and applies the
household scale. It does not change wealth, demand, or pop_balance.
See household expenses for validation,
reuse conditions, and an explicit income - expenses example.
production_table
¶
production_table(
df_buildings: DataFrame,
df_goods: DataFrame,
df_pm: DataFrame,
df_tech: DataFrame | None = None,
df_pop_types: DataFrame | None = None,
) -> DataFrame
Build the production table of all building configurations.
For every building, enumerates every combination of production methods
(one per production-method group) and aggregates the per-method
employment (total and per profession) and net goods flows (positive =
output, negative = input). When pop types are supplied, wage-normalized
employment is the sum of each profession's employment multiplied by its
wage weight, restricted to pop types whose paid_private_wage flag is
true (defaulting to true when undefined). The
infrastructure_usage_per_level
column holds the net per-level footprint: the building group's usage
minus the state_infrastructure_add generation summed over the chosen
production methods, so provider configurations (ports, railways, urban
centers) carry negative values under the full-employment nominal model.
Buildings without a construction cost are
kept with a construction cost of 0. Each row also records the
technologies required to unlock the configuration (the building's own
unlocking technologies followed by those of every chosen production
method, de-duplicated in order of first appearance). When technology data
is supplied, each row also records the earliest era at which the
configuration becomes available (the maximum era of those technologies,
0 when none). Nominal values are evaluated at the
goods table's base prices; the profit ratio columns follow plain division
semantics (x / 0 is inf and 0 / 0 is NaN).
Each input_ratio_goods_<good> column is the good's physical net-input
quantity divided by the total physical net-input quantity across all
goods. Outputs and zero net flows contribute 0, and configurations
without net inputs receive 0 in every input-ratio column. These ratios
are quantity-based analytical measures; Victoria 3's prestige-goods
throughput bonus instead uses the proportion of gross input base value.
Parameters:
-
(df_buildings¶DataFrame) –Buildings table (
BuildingsParser.to_dataframe()ortables/buildings.csv) withkey,building_group,urbanization,infrastructure_usage_per_level,required_construction_points,production_method_groups, andunlocking_technologiescolumns. Optionaleconomy_of_scaleandis_subsistencecolumns determine economy-of-scale eligibility; missing columns default to false. -
(df_goods¶DataFrame) –Goods table (
goodsortables/goods.csv) withkeyandcostcolumns. Its row order fixes thegoods_<good>column order of the result. -
(df_pm¶DataFrame) –Production-methods table (
ProductionMethodParser.to_dataframe()ortables/production_methods.csv) withbuilding,production_method_group,production_method,unlocking_technologies,employment,employment_<profession>,state_infrastructure_add, andgoods_<good>columns (the state-infrastructure column is zero-filled with a warning when absent). -
(df_tech¶DataFrame | None, default:None) –Optional technology table (
technologyortables/technology.csv) withkeyanderacolumns. When omitted,eraandunlocking_tech_localizationare not produced. -
(df_pop_types¶DataFrame | None, default:None) –Optional pop-types table (
PopTypesParser.to_dataframe()ortables/pop_types.csv) withkeyandwage_weightcolumns, plus an optionalpaid_private_wagecolumn. Missing private-wage flags default to true, including when the column is absent in older game data. When the table is omitted, the wage-normalized employment columns are not produced.
Returns:
-
DataFrame–A
DataFramewith one row per building configuration. The -
DataFrame–"production_method"column holds the chosen production methods -
DataFrame–concatenated with
+. The remaining columns are"building", -
DataFrame–"building_group","parent_group","land_usage", -
DataFrame–"is_subsistence","discoverable_resource", -
DataFrame–"depletable_resource","economy_of_scale","urbanization", -
DataFrame–"infrastructure_usage_per_level"(net of the configuration's -
DataFrame–state_infrastructure_addgeneration), optional"era", -
DataFrame–"unlocking_tech","employment", optional -
DataFrame–"wage_normalized_employment","construction_cost", -
DataFrame–"value_goods_inputs_nominal","value_goods_outputs_nominal", -
DataFrame–"profit_nominal","profit_margin_nominal", -
DataFrame–"profit_per_capita_nominal", -
DataFrame–optional
"profit_per_wage_normalized_employment_nominal", and -
DataFrame–"profit_per_construction_cost_nominal", followed by one -
DataFrame–goods_<good>column per good, each immediately followed by its -
DataFrame–input_ratio_goods_<good>column, and one -
DataFrame–employment_<profession>column per profession.
Raises:
-
ValueError–If a supplied technology table is missing an unlocking technology, or if a supplied pop-types table cannot uniquely provide a valid private-wage weight for each employment profession.
Source code in src/vic3_analysis/analysis/production.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | |
Economy
dataclass
¶
Economy(
game_dir: str | Path | None = None,
df_production: DataFrame | None = None,
df_goods: DataFrame | None = None,
df_pop_types: DataFrame | None = None,
*,
df_pop_needs: DataFrame | None = None,
df_buy_packages: DataFrame | None = None,
language: str | None = None,
)
Builds EconomyState instances from building-level vectors.
Wraps production, goods, pop-types, pop-needs, and buy-package tables parsed
from the Victoria 3 game files and lazily caches the coefficients needed to derive
prices, supply, demand, employment, and wealth for a given
building_levels vector.
Input tables are defensively copied. Public DataFrames remain mutable,
but editing them is unsupported because cached coefficients are not
invalidated. Construct a new Economy when model data changes. Cached
indexes are tuples and cached arrays are owned and read-only. Starting
wealth uses int64; other numeric coefficients use float64.
Attributes:
-
df_production(DataFrame) –The production table with missing metadata default-filled.
-
df_goods(DataFrame) –The goods table DataFrame.
-
df_pop_types(DataFrame) –The pop-types table DataFrame.
-
df_pop_needs(DataFrame) –Per-category goods, substitution weights, shares, and defaults.
-
df_buy_packages(DataFrame) –Need values at base prices per 10,000 workers by integer wealth.
Parameters:
-
(game_dir¶str | Path | None, default:None) –Path to the Victoria 3
gamedirectory. IfNonethe directory is located automatically viaget_vic3_directory. Ignored for any table whose DataFrame is passed directly. -
(df_production¶DataFrame | None, default:None) –Pre-built production table DataFrame. When provided, overrides the table that would otherwise be generated by
production_table. Useful for reusing a filtered or cached table. -
(df_goods¶DataFrame | None, default:None) –Pre-built goods table DataFrame. When provided, overrides the table that would otherwise be generated by
goods. -
(df_pop_types¶DataFrame | None, default:None) –Pre-built pop-types table DataFrame. When provided, overrides the table that would otherwise be generated by
PopTypesParser. -
(df_pop_needs¶DataFrame | None, default:None) –Pre-built substitution definitions. When omitted, parsed by
PopNeedsParser. -
(df_buy_packages¶DataFrame | None, default:None) –Pre-built wealth packages. When omitted, parsed by
buy_packages. -
(language¶str | None, default:None) –Optional Victoria 3 localization language used only when parsing tables internally. Explicit DataFrames are authoritative and are not modified.
Methods:
-
economy_of_scale_bonuses–Return per-configuration economy-of-scale throughput bonuses.
-
goods_input_matrix–Return writable gross inputs using the cached unscaled matrix.
-
goods_output_matrix–Return writable gross outputs using the cached unscaled matrix.
-
prepare_context–Return a context with reusable baskets and consumption scales.
-
evaluate_wealth–Evaluate demand, market prices, and finances at fixed household wealth.
-
iterate–Apply one simultaneous wealth transition and evaluate matching results.
-
goods_buy_packages–Calculate weekly goods packages per 10,000 standard workers by wealth.
-
pop_consumption_scales–Return household consumption as multiples of a standard buy package.
-
pop_buy_orders–Calculate weekly population buy orders for the represented workers.
-
pop_expenses–Return weekly household expenses for target goods consumption.
-
pop_income–Return disposable cooperative and dependent household income.
-
pop_income_tax–Recompute weekly household taxes funding operating losses.
-
market_prices_variance–Calculate the market prices variance from base prices.
-
market_prices–Calculate market prices from buy and sell orders.
-
construction_cost–Calculate the total construction cost for an
EconomyState. -
arable_land_consumption–Return the total arable land consumed by an economy state.
-
levels_per_building–Return total levels per building across all PM configurations.
-
solve–Solve for an
EconomyStatefrom a building-level vector. -
df_goods_buy_packages–Export standard goods baskets as an independent, mutable DataFrame.
-
df_buildings–Export an
EconomyState's building registry to a DataFrame. -
df_market–Export an
EconomyState's market stats to a DataFrame. -
df_pop–Export an
EconomyState's pop employment and wealth to a DataFrame.
Source code in src/vic3_analysis/analysis/economy/model.py
building_index
cached
property
¶
Return production-configuration keys in production-table row order.
Each key combines the row's building and production-method strings with
"+". The resulting order defines the alignment of building-level
vectors and the rows of building matrices.
goods_index
cached
property
¶
Return good keys in goods-table row order.
This order defines the alignment of goods vectors and the columns of goods matrices.
producible_goods
cached
property
¶
Return goods that have at least one producer configuration.
Returns:
-
str–A tuple of good keys that can be produced by at least one building
-
...–configuration in the production table.
pop_index
cached
property
¶
Return profession keys in pop-types-table row order.
This order defines the alignment of profession vectors and employment matrix columns.
base_prices
cached
property
¶
Return Victoria 3 base prices aligned to goods_index.
goods_input_matrix_unscaled
cached
property
¶
Cached read-only gross inputs per level, without throughput scaling.
goods_output_matrix_unscaled
cached
property
¶
Cached read-only gross outputs per level, without throughput scaling.
employment_matrix
cached
property
¶
Return employment by production configuration and profession.
Rows align to building_index and columns align to
pop_index. Values are the number of employees per building
level; missing profession columns are filled with zero.
pop_wealth_init
cached
property
¶
Return read-only int64 starting wealth aligned to pop_index.
pop_wage_weights
cached
property
¶
Return all professions' cooperative wage weights in pop_index order.
employment_vector
cached
property
¶
Total employment per building level, aligned to production-table rows.
Returns:
-
ndarray–A 1-D array of shape
(n_buildings,)giving the total employment -
ndarray–of each building configuration per level (
"employment"column, -
ndarray–missing values zero-filled).
construction_cost_vector
cached
property
¶
Return per-level construction cost aligned to building_index.
infrastructure_vector
cached
property
¶
Cached infrastructure usage per level; missing values default to zero.
arable_land_vector
cached
property
¶
Return arable-land consumption per production configuration.
Returns:
-
ndarray–A float vector aligned to the production table, with
1.0for -
ndarray–agricultural, plantation, ranching, and subsistence land-use
-
ndarray–configurations and
0.0otherwise.
economy_of_scale_bonuses
¶
economy_of_scale_bonuses(
building_levels: ndarray[tuple[int], dtype[float64]],
level_cap: float = 20.0,
) -> ndarray
Return per-configuration economy-of-scale throughput bonuses.
Levels are summed across all production-method configurations of each
building. Eligible configurations receive one percentage point of
throughput per total building level, capped by level_cap. Returned
values are additive bonuses (for example, 0.2 for +20%), not full
multipliers.
Parameters:
-
(building_levels¶ndarray[tuple[int], dtype[float64]]) –Production-row-aligned building levels.
-
(level_cap¶float, default:20.0) –Maximum number of levels contributing to the bonus.
Returns:
-
ndarray–A 1-D bonus vector aligned to the production table.
Raises:
-
ValueError–If building_levels is not aligned to the production table or level_cap is negative or non-finite.
Source code in src/vic3_analysis/analysis/economy/model.py
goods_input_matrix
¶
goods_input_matrix(
throughput_multipliers: ndarray[
tuple[int], dtype[float64]
]
| None = None,
) -> ndarray
Return writable gross inputs using the cached unscaled matrix.
Source code in src/vic3_analysis/analysis/economy/model.py
goods_output_matrix
¶
goods_output_matrix(
throughput_multipliers: ndarray[
tuple[int], dtype[float64]
]
| None = None,
) -> ndarray
Return writable gross outputs using the cached unscaled matrix.
Source code in src/vic3_analysis/analysis/economy/model.py
prepare_context
¶
prepare_context(context: EconomyContext) -> EconomyContext
Return a context with reusable baskets and consumption scales.
Compute only missing prepared fields. Existing fields are authoritative; a fully prepared context is returned unchanged. No household wealth, demand, prices, or finances are evaluated. Clear affected fields before refreshing changed production, trade, or population assumptions.
Source code in src/vic3_analysis/analysis/economy/model.py
evaluate_wealth
¶
evaluate_wealth(
context: EconomyContext, pop_wealth: ndarray
) -> tuple[MarketState, PopState]
Evaluate demand, market prices, and finances at fixed household wealth.
Prepare missing context baskets and consumption scales, preserving any supplied prepared fields. Calculate demand first, then market prices from total buy orders and fixed sell orders, and finally cooperative income and household expenses at those same prices.
Parameters:
-
(context¶EconomyContext) –Fixed production, trade, and worker counts aligned to this economy. Prepared baskets and scales are optional.
-
(pop_wealth¶ndarray) –Non-negative integer wealth matrix aligned to configurations and professions. Occupied tiers need baskets; empty cells may use undefined tiers.
Returns:
-
MarketState–Matching market and household components, in that order, with
-
PopState–read-only arrays and fully evaluated household finances. Wealth
-
tuple[MarketState, PopState]–values are preserved. The market shares the supplied context when
-
tuple[MarketState, PopState]–fully prepared; otherwise it references a newly prepared context.
-
tuple[MarketState, PopState]–Compose a complete snapshot with
-
tuple[MarketState, PopState]–EconomyState(market.context, market, households).
Raises:
-
ValueError–If context inputs or wealth are invalid or misaligned, preparation fails, occupied tiers lack baskets, income cannot be allocated, or calculated results are non-finite.
Notes
Inputs and model tables are unchanged. This evaluates one wealth assignment without affordability limits or wealth transitions.
Source code in src/vic3_analysis/analysis/economy/model.py
iterate
¶
iterate(
context: EconomyContext,
market: MarketState,
households: PopState,
*,
rtol: float = 1e-09,
atol: float = 1e-08,
) -> tuple[MarketState, PopState]
Apply one simultaneous wealth transition and evaluate matching results.
Initialize with evaluate_wealth() and pass its prepared market context.
Inputs must be consistent: this method validates alignment and finances,
but trusts their economic consistency without reevaluating the old wealth.
Decrease below 98% of current cost; otherwise increase at or above 102%
of next-tier cost, using previous prices and household scales. Each
threshold accepts equality within atol + rtol * max(income, threshold).
Decreases take precedence. Empty cells and bounded tiers are preserved.
Returns:
-
MarketState–Matching read-only market and population components sharing
context. -
PopState–If wealth is unchanged, the exact supplied components are returned.
-
tuple[MarketState, PopState]–A step is numerical rather than a simulated week and makes no
-
tuple[MarketState, PopState]–convergence or financial-sustainability claim.
Raises:
-
ValueError–If tolerances, context identity, prepared tiers, component axes, prices, or finances are invalid, or calculations fail.
Source code in src/vic3_analysis/analysis/economy/model.py
goods_buy_packages
¶
goods_buy_packages(
state: EconomyState | EconomyContext,
) -> GoodsBuyPackages
Calculate weekly goods packages per 10,000 standard workers by wealth.
Convert the model's wealth-by-category values to goods quantities using
the supplied state's substitution shares and the model's base prices:
wealth_category_values @ category_purchase_shares / base_prices.
Substitution uses effective supply, configured weights, minimum/maximum
supply shares, and default goods as described by pop_buy_orders.
Parameters:
-
(state¶EconomyState | EconomyContext) –Snapshot or context aligned to this economy. Prepared context baskets are reused when present; otherwise only building inputs/outputs, imports, and exports are used.
Returns:
-
GoodsBuyPackages–Immutable
GoodsBuyPackageswith ascending int64wealthlabels and -
GoodsBuyPackages–read-only float64
quantitiesingoods_indexcolumn order. -
GoodsBuyPackages–Prepared context baskets are returned unchanged after validating
-
GoodsBuyPackages–goods alignment; otherwise all tiers in
df_buy_packagesare -
GoodsBuyPackages–calculated. Quantities are goods units per week per 10,000 standard
-
GoodsBuyPackages–workers, with zero for unconsumed goods. Inputs are unchanged.
-
GoodsBuyPackages–Use
Economy.df_goods_buy_packagesfor a mutable DataFrame export.
Raises:
-
ValueError–If goods flows are misaligned, negative, or non-finite, base prices are not positive, or package/substitution definitions are invalid or reference missing categories/goods.
Notes
Packages are independent of represented population, workforce ratio, occupied wealth, profession consumption multipliers, market prices, and existing population demand. Culture, prestige goods, local-state effects, and weekly adjustment are not modeled. Subtracting half of non-pop demand from supply is community-derived, documented by the Needs wiki rather than game-file comments. Clamping negative effective supply to zero is a model convention.
References
common/buy_packages/00_buy_packages.txt: category values by integer wealth.common/pop_needs/00_pop_needs.txt: substitution weights, supply-share limits, and default goods.- Needs wiki, Formulas: scaling per 10,000 workers and substitution, including the community-derived half-non-pop-demand deduction.
- Official developer diary #13: wealth-dependent needs and valuation at goods' base prices.
Source code in src/vic3_analysis/analysis/economy/model.py
pop_consumption_scales
¶
pop_consumption_scales(
state: EconomyState | EconomyContext,
) -> ndarray
Return household consumption as multiples of a standard buy package.
Calculate pops / 10_000 * consumption_mult * (1 + 0.5 *
dependents_per_worker). Missing profession multipliers default to one.
Workers and dependents share a wealth tier; dependents consume half as
much per person. Wealth values, prices, and goods flows are not used.
Parameters:
-
(state¶EconomyState | EconomyContext) –Snapshot or context with aligned worker counts. Prepared context scales are copied when present. Snapshot wealth must also have the population shape.
Returns:
-
ndarray–A fresh, owned, writable float64 matrix aligned to configurations
-
ndarray–and professions. Values are dimensionless multiples of weekly
-
ndarray–goods packages per 10,000 standard workers. Reuse them while worker
-
ndarray–counts, workforce ratio, and profession multipliers remain fixed.
-
ndarray–The state and model tables are unchanged.
Raises:
-
ValueError–If household shapes, worker counts, profession keys, or consumption multipliers are invalid, or scales overflow.
Source code in src/vic3_analysis/analysis/economy/model.py
pop_buy_orders
¶
pop_buy_orders(
state: EconomyState,
*,
goods_buy_packages: GoodsBuyPackages | None = None,
consumption_scales: ndarray | None = None,
) -> ndarray
Calculate weekly population buy orders for the represented workers.
Prepared context baskets and scales are reused when their explicit
arguments are omitted. Without prepared baskets, each need category's
effective supply is
max(sell_orders - 0.5 * (building_goods_input + exports), 0).
Divide each eligible good's effective supply by the category total,
clip that share to its configured minimum and maximum, multiply by
its configured weight, and normalize these purchase weights. Share
limits apply before normalization; they do not cap final purchases.
With zero effective supply, start from zero shares, retaining any
configured minimum shares. If all purchase weights are zero, use the
category's default good exclusively.
Each occupied cell's integer wealth selects a buy package, whose
category values are measured in pounds at base prices per 10,000
workers. Multiply worker counts by 1 + 0.5 * dependents_per_worker,
scale by consumption_mult / 10_000, distribute by
normalized purchase weights, and divide by goods' base prices to
obtain units per week. Household scales are aggregated by wealth before
allocating goods baskets, without a building-by-profession-by-goods tensor.
Parameters:
-
(state¶EconomyState) –Snapshot aligned to this economy's building, profession, and goods indexes. Workers and their dependents consume at the same wealth tier; dependents consume half as much per person. Empty cells need no wealth package.
-
(goods_buy_packages¶GoodsBuyPackages | None, default:None) –Optional immutable
GoodsBuyPackages, as returned bygoods_buy_packages. Wealth labels must cover every occupied tier. Quantity columns must followgoods_indexorder; column count is checked against the economy. Construction validates and sorts wealth labels and quantities together. Supplied baskets are scaled directly by worker- equivalent population and profession consumption multipliers, without substitution or base-price conversion, and remain fixed when supply changes. Unused state goods flows and raw need/package tables are not validated in this mode. The baskets are unchanged. -
(consumption_scales¶ndarray | None, default:None) –Optional precomputed matrix returned by
pop_consumption_scales. Supplied values are authoritative, finite, non-negative, and shaped likepops; empty cells must have zero scale. They already include all population factors, so profession multipliers are not read or reapplied. The caller ensures scales remain valid for the population assumptions. The matrix is unchanged.
Returns:
-
ndarray–A fresh writable float64 vector of shape
(n_goods,)aligned -
ndarray–to
goods_index, suitable forPopState.pop_buy_orders. -
ndarray–The state is unchanged.
Raises:
-
TypeError–If supplied baskets are not a
GoodsBuyPackagesinstance. -
ValueError–If relevant state arrays are misaligned, quantities are negative or non-finite, base prices are not positive, occupied wealth tiers are undefined, or model tables have invalid definitions or missing category/goods references. Also raised for invalid supplied package labels, quantities, or consumption scales, or non-finite calculated demand.
Notes
The half-non-pop-demand deduction is community-derived and
documented by the Needs wiki; it is not confirmed by the comments
in the game files. Clamping negative effective supply to zero is
this model's convention. This is target consumption, without
weekly adjustment, culture, prestige goods, local-state effects,
demographic changes, or wealth feedback. Market prices and
existing state.pop_buy_orders do not influence the result.
References
common/pop_needs/00_pop_needs.txt: substitution weights, minimum/maximum supply shares, comments on their meaning, and default goods.common/buy_packages/00_buy_packages.txt: category values indexed by integer wealth.common/pop_types/: professionconsumption_multvalues.- Needs wiki, Formulas: population scaling and detailed substitution formulas. The non-pop-demand deduction is attributed there to community reverse engineering: https://www.reddit.com/r/victoria3/comments/yudc80/pop_needs_consumer_good_substitution_and_why_oil/
- Official developer diary #13: wealth-dependent needs and valuation using goods' base prices.
Source code in src/vic3_analysis/analysis/economy/model.py
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
pop_expenses
¶
pop_expenses(
state: EconomyState,
*,
goods_buy_packages: GoodsBuyPackages | None = None,
consumption_scales: ndarray | None = None,
) -> ndarray
Return weekly household expenses for target goods consumption.
Value each occupied wealth tier's standard goods basket at the state's
market prices, then multiply by its household consumption scale. This
uses the same baskets and scales as pop_buy_orders, without a
configuration-by-profession-by-goods tensor.
Parameters:
-
(state¶EconomyState) –Snapshot with aligned household matrices, finite non-negative worker counts, and finite non-negative goods-aligned market prices. Zero prices are valid. Empty cells need no wealth basket.
-
(goods_buy_packages¶GoodsBuyPackages | None, default:None) –Optional goods baskets with the same contract as in
pop_buy_orders. When omitted, reuse prepared context baskets or callgoods_buy_packages(state). Supplied baskets bypass unused goods flows, base prices, and raw needs/package definitions. -
(consumption_scales¶ndarray | None, default:None) –Optional authoritative precomputed household scales, with the same contract as in
pop_buy_orders. When omitted, reuse context scales or calculate them.
Returns:
-
ndarray–A fresh, owned, writable float64 matrix shaped like
state.pops -
ndarray–containing household totals in pounds per week. Empty cells have
-
ndarray–zero expenses. Inputs, model tables, and
pop_balanceare unchanged.
Raises:
-
TypeError–If supplied baskets are not a
GoodsBuyPackagesinstance. -
ValueError–If relevant state inputs, baskets, or scales are invalid, occupied tiers are undefined, or calculated costs are non-finite.
Notes
Expenses price target consumption without affordability restrictions, rationing, taxes, or wealth transitions. Prices affect expenses but do not affect the basket quantities or consumption scales.
Source code in src/vic3_analysis/analysis/economy/model.py
pop_income
¶
pop_income(state: EconomyState) -> ndarray
Return disposable cooperative and dependent household income.
Each configuration distributes all of its positive building_surplus
in proportion to state.pops * wage_weight. Every profession is
included regardless of paid_private_wage; zero weights receive no
cooperative income. Configurations are independent, including those of the same
building type. Losses pay zero cooperative wages and remain visible
through state.building_deficit, before any optional operating-loss subsidy.
Add pops * dependents_per_worker * dependent_wage / 52 for household
dependent earnings; missing annual dependent wages default to zero.
Parameters:
-
(state¶EconomyState) –Snapshot aligned to this economy's configuration, goods, and profession indexes. Stored signed flows and market prices are authoritative; production and throughput are not reconstructed.
Returns:
-
ndarray–A fresh writable float64 matrix shaped like
state.popscontaining -
ndarray–total household income in £ per week for each configuration-profession
-
ndarray–group, rather than per-worker rates. The state and model tables are unchanged.
Raises:
-
ValueError–If relevant arrays are misaligned or non-finite, prices, populations, or wage weights are negative, profession keys are invalid, wage weights are missing, used dependent wages are invalid, calculated income is non-finite, or a configuration has positive surplus but no positive recipient weight.
Notes
This is a simplified worker-cooperative accounting policy. It applies
proportional income tax when context.subsidize_operating_losses is enabled.
Losses exceeding total gross income raise ValueError. It excludes
transfers, subsistence income, reserves, and household expenses, and
does not change wealth or pop_balance. Dependent earnings do not
reduce building surplus or increase production GDP.
Source code in src/vic3_analysis/analysis/economy/model.py
pop_income_tax
¶
pop_income_tax(state: EconomyState) -> ndarray
Recompute weekly household taxes funding operating losses.
Returns a fresh matrix aligned to state.pops. The context policy
taxes cooperative and dependent earnings proportionally, or returns
zeros when disabled. Raises ValueError if losses cannot be financed.
Source code in src/vic3_analysis/analysis/economy/model.py
market_prices_variance
¶
market_prices_variance(state: EconomyState) -> ndarray
Calculate the market prices variance from base prices.
Parameters:
-
(state¶EconomyState) –The
EconomyStateto evaluate (as produced bysolve).
Returns:
-
ndarray–A 1-D array of shape
(n_goods,)containing the market prices variance.
Source code in src/vic3_analysis/analysis/economy/model.py
market_prices
¶
market_prices(
buy_orders: ndarray[tuple[int], dtype[float64]],
sell_orders: ndarray[tuple[int], dtype[float64]],
) -> ndarray
Calculate market prices from buy and sell orders.
Parameters:
-
(buy_orders¶ndarray[tuple[int], dtype[float64]]) –1-D array of non-negative buy orders aligned to the goods table.
-
(sell_orders¶ndarray[tuple[int], dtype[float64]]) –1-D array of non-negative sell orders aligned to the goods table.
Returns:
-
ndarray–A float64 array of prices aligned to
goods_index.
Raises:
-
ValueError–If either input is not a 1-D goods-aligned array, does not contain finite values, or contains negative values.
Source code in src/vic3_analysis/analysis/economy/model.py
construction_cost
¶
construction_cost(state: EconomyState) -> float
Calculate the total construction cost for an EconomyState.
Parameters:
-
(state¶EconomyState) –The
EconomyStateto evaluate (as produced bysolve).
Returns:
-
float–The dot product of
building_levelswith the per-configuration -
float–construction cost vector.
Source code in src/vic3_analysis/analysis/economy/model.py
arable_land_consumption
¶
arable_land_consumption(state: EconomyState) -> float
Return the total arable land consumed by an economy state.
Each building level consumes one unit of arable land when its building group is agricultural, plantation, ranching, or subsistence land use.
Parameters:
-
(state¶EconomyState) –The
EconomyStatewhose land consumption is summed.
Returns:
-
float–The sum of building-configuration levels in arable-land-consuming
-
float–building groups.
Raises:
-
ValueError–If the state's building-level vector is not aligned to the production table.
Source code in src/vic3_analysis/analysis/economy/model.py
levels_per_building
¶
levels_per_building(
state: EconomyState,
) -> dict[str, float]
Return total levels per building across all PM configurations.
Building levels in EconomyState are aligned to production-table
rows, where one building can appear in many production-method
configurations. This method aggregates those configuration levels by
building key while preserving the buildings' first-appearance order in
df_production.
Parameters:
-
(state¶EconomyState) –The
EconomyStatewhose levels are aggregated.
Returns:
-
dict[str, float]–A mapping from every building key in the production table to its
-
dict[str, float]–total level. Unused buildings are included with value
0.0.
Raises:
-
ValueError–If the state's building-level vector is not aligned to the production table.
Source code in src/vic3_analysis/analysis/economy/model.py
solve
¶
solve(
building_levels: ndarray[tuple[int], dtype[float64]],
method: str = "nominal",
goods_import: ndarray[tuple[int], dtype[float64]]
| None = None,
goods_export: ndarray[tuple[int], dtype[float64]]
| None = None,
throughput_multipliers: ndarray[
tuple[int], dtype[float64]
]
| None = None,
economy_of_scale_level_cap: float = 0.0,
*,
workforce_ratio: float = 1.0,
subsidize_operating_losses: bool | None = None,
initial_wealth: ndarray | None = None,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
) -> EconomyState
Solve for an EconomyState from a building-level vector.
Parameters:
-
(building_levels¶ndarray[tuple[int], dtype[float64]]) –1-D array of shape
(n_buildings,)specifying the level of each building configuration in the production table. -
(method¶str, default:'nominal') –The solving method to use.
"nominal"uses base prices;"market"derives prices from supplied orders;"equilibrium"iterates household wealth and endogenous consumption demand. Nominal and market modes leave household demand at zero. -
(goods_import¶ndarray[tuple[int], dtype[float64]] | None, default:None) –Non-negative finite 1-D array of shape
(n_goods,)adding sell orders. Defaults to zeros. -
(goods_export¶ndarray[tuple[int], dtype[float64]] | None, default:None) –Non-negative finite 1-D array of shape
(n_goods,)adding buy orders. Defaults to zeros. A good may have both import and export orders. -
(throughput_multipliers¶ndarray[tuple[int], dtype[float64]] | None, default:None) –Optional 1-D array of shape
(n_buildings,)scaling each configuration's gross goods inputs and outputs. Defaults to no scaling. -
(economy_of_scale_level_cap¶float, default:0.0) –Maximum building level contributing to economy of scale. The default
0.0disables the effect; use20.0to cap the throughput bonus at +20%. -
(workforce_ratio¶float, default:1.0) –Economy-wide workers / total population in
(0, 1]. Defaults to1.0for worker-only accounting. -
(subsidize_operating_losses¶bool | None, default:None) –Equilibrium-only proportional tax on all household income to fund operating losses. None (the default) enables it for equilibrium and disables it for other modes. Pass False to disable it explicitly. No payroll is guaranteed; unaffordable losses fail the solve.
-
(initial_wealth¶ndarray | None, default:None) –Equilibrium-only full configuration/profession matrix. Defaults to profession starting tiers. Occupied tiers must have baskets.
-
(max_iterations¶int, default:1000) –Positive integer limit on equilibrium transition steps, excluding initialization and verification. Defaults to 1000.
-
(rtol¶float, default:1e-09) –Non-negative relative tolerance for equilibrium thresholds and final verification. Defaults to
1e-9. -
(atol¶float, default:1e-08) –Non-negative absolute tolerance, in weekly household pounds for affordability and building pounds for losses. Defaults to
1e-8. Equilibrium controls are ignored by nominal and market modes.
Returns:
-
EconomyState–An
EconomyStatedescribing the resulting state. Equilibrium results -
EconomyState–include diagnostics; floor unaffordability and unsubsidized losses are flags
-
EconomyState–and do not prevent numerical convergence. With subsidies enabled,
-
EconomyState–operating losses exceeding household income raise EquilibriumError
-
EconomyState–with status insufficient_income and the failing pre-tax snapshot.
Raises:
-
ValueError–If method is unsupported, if building_levels is not 1-D or its length does not match the number of rows in the production table, if goods_import or goods_export is not a non-negative finite goods-aligned vector, or if throughput_multipliers is not aligned to the production table, or if the economy-of-scale cap is negative or non-finite, or if workforce_ratio is outside
(0, 1]or non-finite. Equilibrium rejects invalid controls, initial wealth, prepared tiers, or initial evaluation. -
EquilibriumError–On cycles, exhausted iterations, subsequent calculation failures, or failed final verification; retains the last evaluated state.
Source code in src/vic3_analysis/analysis/economy/model.py
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | |
df_goods_buy_packages
¶
df_goods_buy_packages(
source: EconomyState
| EconomyContext
| GoodsBuyPackages,
) -> DataFrame
Export standard goods baskets as an independent, mutable DataFrame.
Parameters:
-
(source¶EconomyState | EconomyContext | GoodsBuyPackages) –A snapshot or context from which to calculate or reuse baskets, or immutable
GoodsBuyPackageswith columns ingoods_indexorder.
Returns:
-
DataFrame–A fresh DataFrame with ascending int64 index named
wealthand -
DataFrame–float64 goods quantities in
goods_indexcolumn order. Quantities -
DataFrame–are weekly units per 10,000 standard workers. Both data and labels
-
DataFrame–are copied; editing the report does not modify its source.
Raises:
-
TypeError–If source is not a state, context, or
GoodsBuyPackages. -
ValueError–If goods alignment or basket calculation is invalid.
Source code in src/vic3_analysis/analysis/economy/model.py
df_buildings
¶
df_buildings(state: EconomyState) -> DataFrame
Export an EconomyState's building registry to a DataFrame.
Parameters:
-
(state¶EconomyState) –The
EconomyStateto export (as produced bysolve).
Returns:
-
DataFrame–An independent, mutable
DataFramewith columns"building", -
DataFrame–"production_method","level","construction_cost", -
DataFrame–"building_surplus","profit_per_capita"and"employment", -
DataFrame–followed by signed
goods_<good>flows in goods-index order and -
DataFrame–employment_<profession>counts in pop-index order. Flows and surplus -
DataFrame–are weekly realized totals; surplus is value added before wages at state
-
DataFrame–prices. Profit per capita divides surplus by employed workers, excluding
-
DataFrame–dependents, and is NaN for zero employment. Rows have strictly positive
-
DataFrame–levels and are sorted by
"level"descending.
Source code in src/vic3_analysis/analysis/economy/model.py
df_market
¶
df_market(state: EconomyState) -> DataFrame
Export an EconomyState's market stats to a DataFrame.
Parameters:
-
(state¶EconomyState) –The
EconomyStateto export (as produced bysolve).
Returns:
-
DataFrame–A
DataFramewith columns"goods","market_prices", -
DataFrame–"market_prices_variance","sell_orders","buy_orders", -
DataFrame–"building_goods_input","building_goods_output", -
DataFrame–"imports","exports"and"pop_needs", filtered to goods -
DataFrame–with non-zero
sell_ordersorbuy_ordersand sorted by -
DataFrame–"sell_orders"descending.
Source code in src/vic3_analysis/analysis/economy/model.py
df_pop
¶
df_pop(state: EconomyState) -> DataFrame
Export an EconomyState's pop employment and wealth to a DataFrame.
Each row describes one profession, aggregating the per-building arrays in state.
Parameters:
-
(state¶EconomyState) –The
EconomyStateto export (as produced bysolve).
Returns:
-
DataFrame–A
DataFramewith columns"profession","employment", -
DataFrame–"employment_share","dependents","population", -
DataFrame–"avg_wealth","total_wealth"and -
DataFrame–"pop_balance", filtered to professions with non-zero employment -
DataFrame–and sorted by
"employment"descending.
Source code in src/vic3_analysis/analysis/economy/model.py
EconomyContext
dataclass
¶
EconomyContext(
building_levels: ndarray,
building_goods_flow: ndarray,
goods_import: ndarray,
goods_export: ndarray,
pops: ndarray,
*,
workforce_ratio: float = 1.0,
subsidize_operating_losses: bool = True,
goods_buy_packages: GoodsBuyPackages | None = None,
consumption_scales: ndarray | None = None,
)
Fixed production, trade, and population inputs shared by snapshots.
Direct array inputs are owned, read-only copies; immutable GoodsBuyPackages
objects are shared. Goods columns follow the owning economy's
goods_index; population columns follow its pop_index.
Prepared consumption data is optional and remains fixed as wealth and
prices change. Clear affected prepared fields when changing their inputs,
then call Economy.prepare_context to refresh them.
Attributes:
-
building_levels(ndarray) –Levels per production configuration.
-
building_goods_flow(ndarray) –Realized weekly signed quantities by configuration and good, including throughput and economy-of-scale bonuses.
-
goods_import(ndarray) –Non-negative weekly import quantities by good.
-
goods_export(ndarray) –Non-negative weekly export quantities by good. The same good may have both import and export orders.
-
goods_trade_flow(ndarray) –Derived net imports (imports minus exports).
-
imports(ndarray) –Read-only alias for goods_import.
-
exports(ndarray) –Read-only alias for goods_export.
-
pops(ndarray) –Employed-worker counts by configuration and profession.
-
workforce_ratio(float) –Workers / total population, in
(0, 1]. -
subsidize_operating_losses(bool) –Fund operating losses by taxing all household income proportionally; no payroll guarantee. Defaults to True.
-
goods_buy_packages(GoodsBuyPackages | None) –Optional immutable goods baskets with their wealth labels, shared across contexts and snapshots.
-
consumption_scales(ndarray | None) –Optional dimensionless basket multiples, shaped like
popsand zero in empty cells.
-
API Reference
Economy and production API
Economyprepare_context
goods_trade_flow
cached
property
¶
Return read-only net imports, preserving gross orders separately.
building_goods_input
cached
property
¶
Return total weekly input quantities, splitting signs before summing.
building_goods_output
cached
property
¶
Return total weekly output quantities, splitting signs before summing.
sell_orders
cached
property
¶
Calculate the sell orders for each good.
Returns:
-
ndarray–The sell orders vector, computed as the sum of building_goods_output and imports
dependents_per_worker
cached
property
¶
Return the number of dependents per employed worker.
total_employment
cached
property
¶
Return the employed-worker headcount, excluding dependents.
total_population
cached
property
¶
Return workers plus their dependents, using the uniform workforce ratio.
employment_by_profession
cached
property
¶
Calculate total employment per profession.
Returns:
-
ndarray–A 1-D array of shape
(n_professions,)giving the column sums of -
ndarray–pops.
profession_shares
cached
property
¶
Calculate each profession's share of total employment.
Returns:
-
ndarray–A 1-D array of shape
(n_professions,)summing to1.0, or -
ndarray–all zeros when total employment is zero.
non_pop_buy_orders
cached
property
¶
Return weekly industrial input and export orders by good.
GoodsBuyPackages
dataclass
¶
Owned, read-only goods baskets and their ascending wealth labels.
Attributes:
-
wealth(ndarray) –Unique positive int64 wealth tiers, sorted on construction.
-
quantities(ndarray) –Weekly goods quantities per 10,000 standard workers, shaped as wealth tiers × goods in the owning economy's
goods_indexorder. Rows are sorted withwealth.
Empty tiers are allowed with a quantities matrix of shape (0, n_goods).
MarketState
dataclass
¶
MarketState(
context: EconomyContext, market_prices: ndarray
)
Prices and building finances for a shared fixed economy context.
Attributes:
-
context(EconomyContext) –Fixed inputs shared with the enclosing
EconomyState. -
market_prices(ndarray) –Goods-aligned prices in pounds per unit.
-
API Reference
Economy and production API
Economy
- API Reference Economy and production API
Methods:
-
gdp–Calculate the weekly or annual GDP from net goods and prices.
building_surplus
cached
property
¶
Return weekly goods value added per configuration before wages (£).
building_deficit
cached
property
¶
Return weekly operating losses before subsidies per configuration (£).
gdp_weekly
cached
property
¶
Calculate the weekly GDP from net goods and prices.
Returns:
-
float–The sum of ``(building_goods_output - building_goods_input)
-
float–- market_prices`` (weekly).
gdp
¶
gdp(annual: bool = False) -> float
Calculate the weekly or annual GDP from net goods and prices.
Parameters:
-
(annual¶bool, default:False) –If
True, multiply the weekly GDP by 52 to annualise it.
Returns:
-
float–The sum of ``(building_goods_output - building_goods_input)
-
float–- market_prices`` (weekly), or 52 times that value when annual
-
float–is set.
Source code in src/vic3_analysis/analysis/economy/states.py
PopState
dataclass
¶
PopState(
pop_wealth: ndarray,
pop_buy_orders: ndarray,
pop_income: ndarray | None = None,
pop_expenses: ndarray | None = None,
*,
pop_income_tax: ndarray | None = None,
)
Changing household wealth, demand, and optional weekly finances.
Wealth, income, and expenses use configuration-by-profession matrices;
demand is goods-aligned. None finances mean unevaluated, including for
nominal and market solves. Balance is derived only when both are supplied.
Attributes:
-
pop_wealth(ndarray) –Non-negative integer wealth tiers.
-
pop_buy_orders(ndarray) –Weekly household goods demand.
-
pop_income(ndarray | None) –Optional disposable household income in pounds per week.
-
pop_income_tax(ndarray | None) –Optional household tax funding operating losses, in pounds per week. Evaluated untaxed states contain zero taxes.
-
pop_expenses(ndarray | None) –Optional total consumption expenses in pounds per week.
-
API Reference
Economy and production API
Economy
- API Reference Economy and production API
EconomyState
dataclass
¶
EconomyState(
context: EconomyContext,
market: MarketState,
households: PopState,
*,
equilibrium_diagnostics: EquilibriumDiagnostics
| None = None,
)
Complete snapshot composed from fixed context, market, and population.
Components share immutable data without copying production arrays. Familiar flat attribute reads forward to their owners; constructors and replacements use the component fields. Composition does not evaluate household finances or establish consistency between supplied wealth, demand, and prices.
Attributes:
-
context(EconomyContext) –Fixed production, trade, population, and prepared consumption.
-
market(MarketState) –Prices and building finances referencing this exact context.
-
households(PopState) –Household wealth, demand, and optional finances.
-
equilibrium_diagnostics(EquilibriumDiagnostics | None) –Optional solver outcome and financial flags.
- API Reference
- API Reference
Methods:
-
gdp–Return weekly GDP, or annual GDP when requested.
-
gdp_per_capita–Calculate the weekly or annual GDP per capita.
goods_trade_flow
property
¶
Return net imports from context.goods_trade_flow.
goods_buy_packages
property
¶
goods_buy_packages: GoodsBuyPackages | None
Return context.goods_buy_packages.
building_goods_output
property
¶
Return context.building_goods_output.
employment_by_profession
property
¶
Return context.employment_by_profession.
pop_income_tax
property
¶
Return weekly household taxes funding operating losses.
pop_income_before_tax
property
¶
Return gross weekly household income.
buy_orders
cached
property
¶
Calculate the buy orders for each good.
Returns:
-
ndarray–The buy orders vector, computed as the sum of building_goods_input, exports and population buy orders.
total_wealth_by_profession
cached
property
¶
Return read-only employment-weighted wealth sums by profession.
Values sum pop_wealth * pops over configurations, excluding
dependents. Divide by workforce_ratio for population-weighted totals.
average_wealth
cached
property
¶
Calculate the employment-weighted average wealth.
With a uniform workforce ratio and dependents sharing household wealth,
this also equals total_wealth / total_population.
Returns:
-
float–The weighted average of
wealthbyemployment, or0.0 -
float–when total employment is zero.
total_wealth
cached
property
¶
Calculate total population-weighted wealth, including dependents.
Returns:
-
float–The sum of
pop_wealth * pops / workforce_ratio. This is a -
float–population-weighted sum of wealth tiers, not a monetary stock.
average_wealth_by_profession
cached
property
¶
Calculate the employment-weighted average wealth per profession.
Returns:
-
ndarray–A 1-D array of shape
(n_professions,); entries are0.0 -
ndarray–where a profession has no employment.
wealth_distribution
cached
property
¶
Calculate weighted wealth-distribution statistics across pops.
Returns:
-
dict[str, float]–A dict with keys
"min","mean","median","std"and -
dict[str, float]–"max"of wealth, weighted by employment. All values are0.0 -
dict[str, float]–when there is no employment.
gini_wealth
cached
property
¶
Calculate the Gini coefficient of the wealth distribution.
Returns:
-
float–A float in
[0, 1](0= perfectly equal,1= maximally -
float–unequal), weighted by employment. Returns
0.0when there is no -
float–employment or no total wealth.
gdp
¶
gdp_per_capita
¶
gdp_per_capita(annual: bool = False) -> float
Calculate the weekly or annual GDP per capita.
Parameters:
-
(annual¶bool, default:False) –If
True, multiply the weekly GDP by 52 to annualise it.
Returns:
-
float–The GDP per capita, computed as
gdp(annual) / total_population, -
float–or
0.0when total population is zero.
Source code in src/vic3_analysis/analysis/economy/states.py
EquilibriumDiagnostics
dataclass
¶
EquilibriumDiagnostics(
status: Literal[
"converged",
"cycle",
"max_iterations",
"evaluation_failed",
"verification_failed",
"insufficient_income",
],
iterations: int,
increasing_cells: tuple[tuple[int, int], ...] = (),
decreasing_cells: tuple[tuple[int, int], ...] = (),
unaffordable_floor_cells: tuple[
tuple[int, int], ...
] = (),
loss_buildings: tuple[int, ...] = (),
cycle_start: int | None = None,
cycle_length: int | None = None,
)
Numerical outcome and financial flags for an equilibrium snapshot.
Attributes:
-
status(Literal['converged', 'cycle', 'max_iterations', 'evaluation_failed', 'verification_failed', 'insufficient_income']) –converged,cycle,max_iterations,evaluation_failed,verification_failed, orinsufficient_income. Convergence means wealth is stationary, including at its boundaries; it does not promise financial sustainability. -
iterations(int) –Completed transition steps, excluding initialization and verification.
-
increasing_cells(tuple[tuple[int, int], ...]) –Configuration/profession coordinates requiring advancement.
-
decreasing_cells(tuple[tuple[int, int], ...]) –Configuration/profession coordinates requiring a lower tier.
-
unaffordable_floor_cells(tuple[tuple[int, int], ...]) –Occupied minimum-tier cells below their affordability threshold. These cannot move down and do not prevent convergence.
-
loss_buildings(tuple[int, ...]) –Configuration indices with material unfunded weekly losses.
-
cycle_start(int | None) –First iteration of a repeated assignment, or None.
-
cycle_length(int | None) –Number of transitions in the detected cycle, or None.
Coordinates follow Economy.building_index and Economy.pop_index.
Tuple fields contain immutable Python integer indices in row-major order.
-
API Reference
Economy and production API
EconomyState
EquilibriumError
¶
EquilibriumError(message: str, state: EconomyState)
Bases: RuntimeError
Failure after initialization, retaining the last evaluated snapshot.
Attributes:
-
state–Immutable last evaluated state with solver diagnostics attached.
-
diagnostics–The same diagnostics object as on
state.
Cycles and iteration exhaustion do not prove that no equilibrium exists.
Calculation failures retain the original exception through __cause__.