PEP template (Pyomo)¶
The PEP-1-1 v2.1 port — see the templates overview for context.
PEP index sets for the Pyomo model.
Wraps the calibrated PEPModelState.sets (the single source of truth produced by
PEPModelCalibrator) so the Pyomo builder never redefines set members. Adds the one
derived set the equations need: I1 = I \ {walras_i} (all commodities except the
Walras/redundant-market commodity, default agr) — used by the composite-good market
clearing EQ84 (agr is dropped and handled by the WALRAS/LEON slack).
- Default pep2 members (from PEPModelState):
H = [hrp, hup, hrr, hur] households F = [firm] firms K = [cap, land] capital types L = [usk, sk] labor types J = [agr, ind, ser, adm] production sectors I = [agr, food, othind, ser, adm] commodities (note: J ≠ I — PEP make matrix) AG = [hrp, hup, hrr, hur, firm, gvt, row] all agents AGNG = AG {gvt} non-government agents AGD = AG {row} domestic agents
- class equilibria.templates.pep_pyomo.pep_pyomo_sets.PEPSets(H=<factory>, F=<factory>, K=<factory>, L=<factory>, J=<factory>, I=<factory>, AG=<factory>, AGNG=<factory>, AGD=<factory>, walras_i='agr')[source]¶
Bases:
objectIndex sets for the PEP Pyomo model, sourced from a calibrated PEPModelState.
- Parameters:
PEP calibrated parameters for the Pyomo model.
Wraps PEPModelState blocks (production/income/trade/consumption/les_parameters/gdp)
into one flat, case-preserving lookup so the equation rules read parameters by their
GAMS-style names (e.g. P["io","agr"], P["beta_VA","agr"], P["KDO","cap","agr"]).
Benchmark levels end in O (KDO, YHO, IMO, …). CES/share params keep their block
names (rho_VA, beta_KD, B_XT, sigma_M, …). Derived params that the cyipopt solver
computes in _extract_parameters (gamma_INV, gamma_GVT, sigma_*, eta, kmob) are
recomputed here from the same benchmark inputs so the Pyomo model is self-contained.
- class equilibria.templates.pep_pyomo.pep_pyomo_parameters.PEPParams(state)[source]¶
Bases:
objectFlat calibrated-parameter accessor over a PEPModelState.
p[name]→ scalar or dict;p[name, i]/p[name, i, j]→ indexed value. Missing indexed entries return 0.0 (matches the GAMS$-masked default), missing names raise KeyError (a real typo, not a benign zero).- Parameters:
state (Any)
PEP CGE model as a Pyomo ConcreteModel — Vars + all ~96 EQ Constraints.
Faithful port of the cyipopt residual system (pep_model_equations.py). Each residual f(x)=0 becomes a Pyomo Constraint lhs == rhs. Sets/params come from PEPSets/PEPParams (which wrap the calibrated PEPModelState). The $-masks of the GAMS/residual code are resolved at construction from the *O/*O0 benchmark params (an equation instance is built only where its benchmark level is non-zero), matching the cyipopt active-set.
- Builder entry point: build_pep_model(state, variant=”base”, form=”nlp”) -> ConcreteModel.
variant: “base” (EQ1..EQ98 + WALRAS) | “objdef” (adds OBJDEF: OBJ==0, free OBJ) form: “nlp” (min 0 over the equality system) | “mcp” (walras⊥LEON, e fixed numeraire)
- equilibria.templates.pep_pyomo.pep_pyomo_equations.build_pep_model(state, variant='base', form='nlp')[source]¶
PEP equation blocks as Pyomo Constraints — faithful to pep_model_equations.py.
Each EQn residual f=0 becomes lhs == rhs. Equations are instantiated only over their active index sets (the GAMS $-masks, precomputed in idx). Constraints are named eqN (lowercase) with the GAMS index suffix in the Constraint’s own index.
attach_all_blocks(m, S, P, idx, variant) -> int attaches every block, returns the count.
- equilibria.templates.pep_pyomo.pep_pyomo_blocks.attach_all_blocks(m, S, P, idx, variant)[source]¶
- Return type:
Counterfactual scenarios for the PEP model — the ** 6.4 Simulations block of PEP-1-1_v2_1.gms, applied to the CALIBRATED STATE before build_pep_model.
GAMS applies a scenario by fixing a benchmark-derived rate (e.g. ttix.fx(i)=ttixO(i)*0.75) right before the solve. Since the Pyomo port derives every model rate from the calibrated state’s *O benchmarks (PEPParams reads state.trade[‘ttixO’] etc.), the faithful analog is to scale that benchmark IN THE STATE, then build — the model then carries the shocked rate everywhere GAMS’s fixed variable would. This keeps the builder scenario-agnostic (the scenario is external, exactly as in the .gms).
SIM1 (the one uncommented simulation in the reference .gms): a 25% cut to the export-tax rate — ttix.fx(i) = ttixO(i)*0.75. (The comment says “all indirect tax rates” but only the ttix line is active; GAMS is the source of truth, so only ttix is scaled.)
- equilibria.templates.pep_pyomo.pep_pyomo_scenarios.apply_sim1_export_tax_cut(state, factor=0.75)[source]¶
Scale the export-tax benchmark ttixO in-place by factor (default 0.75 = −25%, the reference SIM1). Mutates and returns state so PEPParams derives the shocked ttix. Idempotent only per fresh calibration — call on a newly calibrated state, not twice.
Solve the PEP Pyomo model and read variable values out.
NLP form: IPOPT on the raw model with nlp_scaling_method=none (faithful to GAMS,
which solves the raw model; the GTAP saga proved Pyomo’s default gradient pre-scaling
steers IPOPT to a wrong basin — see project_gtap7_altertax_ref_and_nlp_scaling).
MCP form: PATH via path-capi-python (walras⊥LEON free-row, e fixed numeraire), mirroring the GTAP MCP path. Falls back to a clear error if PATH is unavailable.
The benchmark BASE reproduces the SAM, so seeding at *O levels and solving should return
residual≈0 (the cyipopt solver early-exits there) — that is the parity anchor.
- class equilibria.templates.pep_pyomo.pep_pyomo_solver.PEPSolveResult(code: 'int', max_residual: 'float', values: 'dict[str, Any]'=<factory>, message: 'str' = '')[source]¶
Bases:
object