Optimization API¶
Used in the optimization guide, resource-limited optimization, and supply-chain examples.
Scenario
dataclass
¶
Scenario(
objective: str = "automation",
min_goods_balance: float | None = 0.0,
banned_pms: tuple[str, ...] = (),
building_level_caps: tuple[tuple[str, float], ...] = (),
banned_building_groups: tuple[str, ...] = (),
throughput_multipliers: tuple[
tuple[str, float], ...
] = (),
era_cap: int | None = None,
construction_cost_cap: float | None = None,
employment_cap: float | None = None,
arable_land_cap: float | None = None,
min_net_infrastructure: float | None = None,
urbanization_per_center: float | None = None,
name: str | None = None,
goods_import: tuple[tuple[str, float], ...] = (),
goods_export: tuple[tuple[str, float], ...] = (),
workforce_ratio: float = 1.0,
)
An immutable optimization recipe expressed as data.
The optimizer interpreting a scenario owns all economy-dependent compilation. This object records assumptions interpreted by the nominal, market, and equilibrium formulations.
min_goods_balance sets the minimum weekly balance for every good:
building output plus imports minus building inputs and exports. Household
consumption is excluded. The default of 0.0 requires nonnegative
balances; negative floors allow deficits, and None disables the floor.
min_net_infrastructure sets minimum infrastructure generation minus
consumption, weighted by building levels. 0.0 prevents a deficit;
positive minima require spare capacity, negative minima allow a bounded
deficit, and None leaves infrastructure unconstrained.
goods_import and goods_export record fixed weekly (good, amount)
pairs with non-negative amounts. Imports add sell orders; exports add buy
orders. Repeated entries are summed, and a good may be both imported and
exported. These orders enter the goods-balance constraint when enabled.
workforce_ratio is the uniform worker share of total population.
It defaults to 1.0; employment constraints still count only workers.
- API Reference
Methods:
-
display_name–Return the explicit name or one derived from the export goods basket.
display_name
¶
Return the explicit name or one derived from the export goods basket.
Source code in src/vic3_analysis/optimize/scenario.py
BaseOptimizer
¶
BaseOptimizer(model: Economy)
Bases: ABC
Abstract base for economy-bound optimization formulations.
- API Reference Optimization API
Methods:
-
compile–Compile scenario into the concrete optimizer's problem type.
-
summary–Return a fresh one-row report of the latest returned solution.
Attributes:
-
goods_input_matrix(ndarray) –Return the current problem's adjusted input matrix.
-
goods_output_matrix(ndarray) –Return the current problem's adjusted output matrix.
-
goods_matrix(ndarray) –Return the current problem's adjusted net-goods matrix.
-
gdp_vector(ndarray) –Return the current problem's nominal GDP vector.
-
throughput_multipliers(ndarray) –Return the current problem's per-configuration multipliers.
Source code in src/vic3_analysis/optimize/base.py
goods_input_matrix
property
¶
Return the current problem's adjusted input matrix.
goods_output_matrix
property
¶
Return the current problem's adjusted output matrix.
goods_matrix
property
¶
Return the current problem's adjusted net-goods matrix.
throughput_multipliers
property
¶
Return the current problem's per-configuration multipliers.
summary
¶
Return a fresh one-row report of the latest returned solution.
GDP is reported weekly and annually; gdp_per_capita is annual.
Employment counts workers, population includes dependents, and wealth
is a population-weighted tier. Infrastructure usage is consumption
minus generation. Construction cost and arable-land consumption use
the model's existing accounting. throughput_multiplier is NaN
unless all compiled configuration multipliers are equal.
Reporting never solves or evaluates the problem again. Binding a new
problem clears the retained solution. Equilibrium searches that return
a verified state on budget exhaustion remain reportable even when
search_success is false.
Raises:
-
ValueError–If the current problem has no returned solution.
Source code in src/vic3_analysis/optimize/base.py
LinearProblem
dataclass
¶
LinearProblem(
economy: Economy,
scenario: Scenario,
throughput_multipliers: ndarray,
input_matrix: ndarray,
output_matrix: ndarray,
net_matrix: ndarray,
gdp_vector: ndarray,
goods_import: ndarray,
goods_export: ndarray,
A_ub: ndarray | None,
b_ub: ndarray | None,
A_eq: ndarray | None,
b_eq: ndarray | None,
bounds: Bounds,
inequality_slices: ConstraintSlices,
equality_slices: ConstraintSlices,
objective_vector: ndarray,
)
Bases: _CompiledProblem
A compiled nominal linear optimization problem.
-
API Reference
Optimization API
NominalOptimizercompile
-
API Reference
Optimization API
NominalOptimizer
Methods:
-
linprog_args–Return coefficients as
linprogkeyword arguments.
linprog_args
¶
Return coefficients as linprog keyword arguments.
NominalOptimizer
¶
NominalOptimizer(model: Economy)
Bases: BaseOptimizer[LinearProblem]
Compile and solve nominal-price scenarios as linear programmes.
Methods:
-
compile–Compile scenario into an inspectable linear problem.
-
solve–Compile and solve scenario, returning its optimal economy state.
-
solve_problem–Solve a previously compiled linear problem.
-
import_marginals–Return objective sensitivities to increasing imports by good.
Source code in src/vic3_analysis/optimize/base.py
compile
¶
compile(scenario: Scenario) -> LinearProblem
Compile scenario into an inspectable linear problem.
Source code in src/vic3_analysis/optimize/nominal.py
solve
¶
solve(scenario: Scenario) -> EconomyState
Compile and solve scenario, returning its optimal economy state.
solve_problem
¶
solve_problem(problem: LinearProblem) -> EconomyState
Solve a previously compiled linear problem.
Source code in src/vic3_analysis/optimize/nominal.py
import_marginals
¶
Return objective sensitivities to increasing imports by good.
Values align to the goods index and measure the minimized LP objective change per additional imported unit under the goods-balance floor.
Source code in src/vic3_analysis/optimize/nominal.py
MarketProblem
dataclass
¶
MarketProblem(
economy: Economy,
scenario: Scenario,
throughput_multipliers: ndarray,
input_matrix: ndarray,
output_matrix: ndarray,
net_matrix: ndarray,
gdp_vector: ndarray,
goods_import: ndarray,
goods_export: ndarray,
A_ub: ndarray | None,
b_ub: ndarray | None,
A_eq: ndarray | None,
b_eq: ndarray | None,
bounds: Bounds,
inequality_slices: ConstraintSlices,
equality_slices: ConstraintSlices,
objective: Callable[[ndarray], float],
jacobian: Callable[[ndarray], ndarray],
warm_start: LinearProblem,
)
Bases: _CompiledProblem
A compiled nonlinear market-price optimization problem.
-
API Reference
Optimization API
MarketOptimizercompile
-
API Reference
Optimization API
MarketOptimizer
-
API Reference
Optimization API
MarketOptimizersolve_problem
MarketOptimizer
¶
MarketOptimizer(model: Economy)
Bases: BaseOptimizer[MarketProblem]
Compile and solve scenarios with endogenous national market prices.
Methods:
-
compile–Compile scenario into an inspectable nonlinear market problem.
-
solve–Compile and solve scenario with endogenous market prices.
-
solve_problem–Solve a previously compiled market problem.
Source code in src/vic3_analysis/optimize/base.py
compile
¶
compile(scenario: Scenario) -> MarketProblem
Compile scenario into an inspectable nonlinear market problem.
Source code in src/vic3_analysis/optimize/market.py
solve
¶
solve(
scenario: Scenario,
*,
x0: ndarray | None = None,
options: Mapping[str, object] | None = None,
) -> EconomyState
Compile and solve scenario with endogenous market prices.
Source code in src/vic3_analysis/optimize/market.py
solve_problem
¶
solve_problem(
problem: MarketProblem,
*,
x0: ndarray | None = None,
options: Mapping[str, object] | None = None,
) -> EconomyState
Solve a previously compiled market problem.
Source code in src/vic3_analysis/optimize/market.py
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 | |
EquilibriumProblem
dataclass
¶
EquilibriumProblem(
economy: Economy,
scenario: Scenario,
throughput_multipliers: ndarray,
input_matrix: ndarray,
output_matrix: ndarray,
net_matrix: ndarray,
gdp_vector: ndarray,
goods_import: ndarray,
goods_export: ndarray,
A_ub: ndarray | None,
b_ub: ndarray | None,
A_eq: ndarray | None,
b_eq: ndarray | None,
bounds: Bounds,
inequality_slices: ConstraintSlices,
equality_slices: ConstraintSlices,
warm_start: LinearProblem,
initial_wealth: ndarray,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
*,
subsidize_operating_losses: bool = True,
)
Bases: _CompiledProblem
An immutable equilibrium-search recipe bound to one economy.
Arrays retain full economy index order. initial_wealth is copied and
reused for every evaluation, making results independent of earlier trials.
warm_start is a nominal GDP LP over the same linear feasible region.
Evaluation rebuilds supply-dependent baskets for each building mix.
-
API Reference
Optimization API
EquilibriumOptimizercompile
Methods:
-
evaluate–Solve household equilibrium at full-index nonnegative building levels.
-
objective–Return the negative, unscaled metric after solving equilibrium.
evaluate
¶
evaluate(levels: ndarray) -> EconomyState
Solve household equilibrium at full-index nonnegative building levels.
Scenario feasibility is checked by the optimizer, separately from this
physical evaluation. Invalid model inputs raise ValueError; failed
equilibrium iteration raises EquilibriumError with its snapshot.
Source code in src/vic3_analysis/optimize/equilibrium.py
objective
¶
Return the negative, unscaled metric after solving equilibrium.
EquilibriumOptimizer
¶
EquilibriumOptimizer(model: Economy)
Bases: BaseOptimizer[EquilibriumProblem]
Search continuous building levels using verified household equilibria.
This is a deterministic local heuristic, without a global-optimum or smooth-objective stationarity guarantee. Population varies with employment. Numerical equilibrium permits the existing financial warning flags.
-
API Reference
Optimization API
SupplyChainEquilibriumOptimizer
Methods:
-
summary–Extend the solution report with search and equilibrium diagnostics.
-
compile–Compile shared constraints and freeze the equilibrium evaluation seed.
-
solve–Compile and search a scenario, returning the best verified equilibrium.
-
solve_problem–Search a compiled problem over a bounded, feasible linear region.
Source code in src/vic3_analysis/optimize/base.py
summary
¶
Extend the solution report with search and equilibrium diagnostics.
Evaluation counts exclude final verification, matching result.
Financial warning counts do not imply equilibrium non-convergence.
Source code in src/vic3_analysis/optimize/equilibrium.py
compile
¶
compile(
scenario: Scenario,
*,
initial_wealth: ndarray | None = None,
subsidize_operating_losses: bool = True,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
) -> EquilibriumProblem
Compile shared constraints and freeze the equilibrium evaluation seed.
Supports gdp, gdp_per_capita, and average_wealth. Household
consumption is endogenous; imports and exports are fixed external orders.
Goods-balance floors include trade and exclude household consumption.
subsidize_operating_losses funds losses through proportional taxes
on cooperative and dependent income, without guaranteeing payroll.
Source code in src/vic3_analysis/optimize/equilibrium.py
solve
¶
solve(
scenario: Scenario,
*,
x0: ndarray | None = None,
options: Mapping[str, object] | None = None,
log_every: int = 100,
initial_wealth: ndarray | None = None,
subsidize_operating_losses: bool = True,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
) -> EconomyState
Compile and search a scenario, returning the best verified equilibrium.
options accepts COBYLA's rhobeg, tol, catol, disp,
and f_target plus a hard maxiter trial limit (default 20,000).
max_iterations separately limits each household equilibrium solve.
subsidize_operating_losses enables income-tax-funded operating losses;
trials needing more than all household income are rejected.
log_every sets the trial interval for INFO progress summaries when
this module's logger is enabled; it must be a positive integer.
See solve_problem for search termination and failure diagnostics.
Source code in src/vic3_analysis/optimize/equilibrium.py
solve_problem
¶
solve_problem(
problem: EquilibriumProblem,
*,
x0: ndarray | None = None,
options: Mapping[str, object] | None = None,
log_every: int = 100,
) -> EconomyState
Search a compiled problem over a bounded, feasible linear region.
Return the best feasible equilibrium even on budget exhaustion; inspect
result.success and result.message for search termination.
result.x and unscaled result.fun describe the returned state.
result.solver_result retains raw COBYLA output (or None if it
was skipped or interrupted by the hard budget). nfev counts
distinct consecutive trials, including
rejected points; equilibrium_evaluations counts inner solve attempts.
The initial trial counts against the budget; final verification does not.
equilibrium_failures counts failures by status and
last_equilibrium_error retains the last failed inner solve.
Enable vic3_analysis.optimize.equilibrium at INFO for lifecycle
events and summaries every log_every trials (default 100, positive
integer). DEBUG additionally reports uncached trials and incumbents.
Logging uses actual maximizing metrics in explicit units, independently
of native COBYLA disp. Library code never configures log handlers.
Raises:
-
ValueError–For invalid inputs, infeasible/unbounded regions, or no feasible converged equilibrium (with diagnostics on
result). -
EquilibriumError–If fresh verification of the selected state fails.
Source code in src/vic3_analysis/optimize/equilibrium.py
SupplyChainEquilibriumProblem
dataclass
¶
SupplyChainEquilibriumProblem(
economy: Economy,
scenario: Scenario,
throughput_multipliers: ndarray,
input_matrix: ndarray,
output_matrix: ndarray,
net_matrix: ndarray,
gdp_vector: ndarray,
goods_import: ndarray,
goods_export: ndarray,
A_ub: ndarray | None,
b_ub: ndarray | None,
A_eq: ndarray | None,
b_eq: ndarray | None,
bounds: Bounds,
inequality_slices: ConstraintSlices,
equality_slices: ConstraintSlices,
warm_start: LinearProblem,
initial_wealth: ndarray,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
*,
subsidize_operating_losses: bool = True,
chain_index: tuple[str, ...],
chain_matrix: ndarray,
building_problem: EquilibriumProblem,
_owner: object = object(),
)
Bases: EquilibriumProblem
Chain-coordinate constraints with building-coordinate economic accounting.
bounds, constraint columns, and warm_start decision coefficients
follow chain_index. Production matrices and wealth retain the
original economy indexes. Physical evaluation delegates to building_problem.
-
API Reference
Optimization API
SupplyChainEquilibriumOptimizercompile
Methods:
-
to_building_levels–Map chain coordinates using this problem's immutable coefficients.
-
evaluate–Solve equilibrium after transforming a nonnegative chain vector.
to_building_levels
¶
Map chain coordinates using this problem's immutable coefficients.
evaluate
¶
evaluate(levels: ndarray) -> EconomyState
Solve equilibrium after transforming a nonnegative chain vector.
SupplyChainEquilibriumOptimizer
¶
SupplyChainEquilibriumOptimizer(
economy: Economy, df_building_levels: DataFrame
)
Bases: EquilibriumOptimizer
Optimize nonnegative chain levels using the existing equilibrium search.
x0 and result.x contain chain levels. Returned states and
result.building_levels contain the recipe matrix times result.x. Fixed
recipes restrict the search space; they do not guarantee financial viability.
DataFrame rows are aligned by configuration key to the economy; all-NaN columns are skipped with a warning. Shared configurations receive the sum of chain contributions, without normalization of coefficients.
Methods:
-
summary–Add the recipe count to the report of the verified building state.
-
validate_building_levels–Validate, align, and copy recipes, warning when failed columns are skipped.
-
to_building_levels–Map a finite nonnegative chain vector to building configurations.
-
compile–Compile building constraints and the nominal warm start into chains.
-
solve_problem–Search chain coordinates and verify the original building constraints.
Attributes:
-
chain_index(tuple[str, ...]) –Return surviving recipe labels in chain-vector order.
-
df_building_levels(DataFrame) –Return an independent copy of the aligned production-unit-by-chain matrix.
Source code in src/vic3_analysis/optimize/supply_chain.py
chain_index
property
¶
Return surviving recipe labels in chain-vector order.
df_building_levels
property
¶
Return an independent copy of the aligned production-unit-by-chain matrix.
summary
¶
Add the recipe count to the report of the verified building state.
chain_count counts recipe columns; configuration_count counts
building configurations. Economy metrics use mapped building levels.
Source code in src/vic3_analysis/optimize/supply_chain.py
validate_building_levels
staticmethod
¶
Validate, align, and copy recipes, warning when failed columns are skipped.
Rows must match building_index exactly; column order is preserved.
All-NaN columns are omitted. Each remaining recipe must have finite,
nonnegative coefficients and at least one positive coefficient. Returned
float coefficients retain the caller's units without normalization.
Source code in src/vic3_analysis/optimize/supply_chain.py
to_building_levels
¶
Map a finite nonnegative chain vector to building configurations.
compile
¶
compile(
scenario: Scenario,
*,
initial_wealth: ndarray | None = None,
subsidize_operating_losses: bool = True,
max_iterations: int = 1000,
rtol: float = 1e-09,
atol: float = 1e-08,
) -> SupplyChainEquilibriumProblem
Compile building constraints and the nominal warm start into chains.
Source code in src/vic3_analysis/optimize/supply_chain.py
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 | |
solve_problem
¶
solve_problem(
problem: EquilibriumProblem,
*,
x0: ndarray | None = None,
options: Mapping[str, object] | None = None,
log_every: int = 100,
) -> EconomyState
Search chain coordinates and verify the original building constraints.