cgelab 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cgelab-0.5.0/CHANGELOG.md +268 -0
- cgelab-0.5.0/CITATION.cff +24 -0
- cgelab-0.5.0/LICENSE +21 -0
- cgelab-0.5.0/MANIFEST.in +9 -0
- cgelab-0.5.0/PKG-INFO +252 -0
- cgelab-0.5.0/README.md +214 -0
- cgelab-0.5.0/pyproject.toml +60 -0
- cgelab-0.5.0/setup.cfg +4 -0
- cgelab-0.5.0/site/.nojekyll +0 -0
- cgelab-0.5.0/site/README.md +58 -0
- cgelab-0.5.0/site/highlight.js +38 -0
- cgelab-0.5.0/site/index.html +570 -0
- cgelab-0.5.0/site/pt-br/index.html +575 -0
- cgelab-0.5.0/site/pt-br/replications.html +210 -0
- cgelab-0.5.0/site/replications.html +213 -0
- cgelab-0.5.0/site/style.css +92 -0
- cgelab-0.5.0/src/cgelab/__init__.py +74 -0
- cgelab-0.5.0/src/cgelab/__main__.py +7 -0
- cgelab-0.5.0/src/cgelab/bridge.py +173 -0
- cgelab-0.5.0/src/cgelab/calibrate.py +625 -0
- cgelab-0.5.0/src/cgelab/cli.py +40 -0
- cgelab-0.5.0/src/cgelab/closure.py +163 -0
- cgelab-0.5.0/src/cgelab/decompose.py +431 -0
- cgelab-0.5.0/src/cgelab/diagnostics.py +113 -0
- cgelab-0.5.0/src/cgelab/dynamics.py +310 -0
- cgelab-0.5.0/src/cgelab/emissions.py +139 -0
- cgelab-0.5.0/src/cgelab/examples/__init__.py +5 -0
- cgelab-0.5.0/src/cgelab/examples/hosoe.py +135 -0
- cgelab-0.5.0/src/cgelab/examples/regions.py +70 -0
- cgelab-0.5.0/src/cgelab/examples/toy.py +244 -0
- cgelab-0.5.0/src/cgelab/export.py +820 -0
- cgelab-0.5.0/src/cgelab/functions.py +142 -0
- cgelab-0.5.0/src/cgelab/har.py +314 -0
- cgelab-0.5.0/src/cgelab/multipliers.py +292 -0
- cgelab-0.5.0/src/cgelab/physical.py +118 -0
- cgelab-0.5.0/src/cgelab/py.typed +0 -0
- cgelab-0.5.0/src/cgelab/regional.py +575 -0
- cgelab-0.5.0/src/cgelab/results.py +262 -0
- cgelab-0.5.0/src/cgelab/sam.py +177 -0
- cgelab-0.5.0/src/cgelab/scenario.py +181 -0
- cgelab-0.5.0/src/cgelab/sensitivity.py +257 -0
- cgelab-0.5.0/src/cgelab/solve.py +1041 -0
- cgelab-0.5.0/src/cgelab/spec.py +333 -0
- cgelab-0.5.0/src/cgelab/welfare.py +100 -0
- cgelab-0.5.0/src/cgelab.egg-info/PKG-INFO +252 -0
- cgelab-0.5.0/src/cgelab.egg-info/SOURCES.txt +82 -0
- cgelab-0.5.0/src/cgelab.egg-info/dependency_links.txt +1 -0
- cgelab-0.5.0/src/cgelab.egg-info/entry_points.txt +2 -0
- cgelab-0.5.0/src/cgelab.egg-info/requires.txt +12 -0
- cgelab-0.5.0/src/cgelab.egg-info/top_level.txt +1 -0
- cgelab-0.5.0/tests/conftest.py +10 -0
- cgelab-0.5.0/tests/data/hosoe_tariff_abolition.json +378 -0
- cgelab-0.5.0/tests/test_accounts.py +106 -0
- cgelab-0.5.0/tests/test_bridge.py +101 -0
- cgelab-0.5.0/tests/test_calibrate.py +73 -0
- cgelab-0.5.0/tests/test_cet_external.py +129 -0
- cgelab-0.5.0/tests/test_closures.py +96 -0
- cgelab-0.5.0/tests/test_decompose.py +84 -0
- cgelab-0.5.0/tests/test_dynamics.py +71 -0
- cgelab-0.5.0/tests/test_emissions.py +104 -0
- cgelab-0.5.0/tests/test_energy_nest.py +157 -0
- cgelab-0.5.0/tests/test_export.py +91 -0
- cgelab-0.5.0/tests/test_government_closures.py +78 -0
- cgelab-0.5.0/tests/test_har.py +111 -0
- cgelab-0.5.0/tests/test_hosoe_benchmark.py +46 -0
- cgelab-0.5.0/tests/test_hosoe_stdcge.py +61 -0
- cgelab-0.5.0/tests/test_institutions_dynamics.py +247 -0
- cgelab-0.5.0/tests/test_investment_mix.py +49 -0
- cgelab-0.5.0/tests/test_jump_roundtrip.py +66 -0
- cgelab-0.5.0/tests/test_labour.py +135 -0
- cgelab-0.5.0/tests/test_multipliers.py +156 -0
- cgelab-0.5.0/tests/test_period.py +162 -0
- cgelab-0.5.0/tests/test_physical.py +58 -0
- cgelab-0.5.0/tests/test_regions.py +111 -0
- cgelab-0.5.0/tests/test_report.py +32 -0
- cgelab-0.5.0/tests/test_results.py +85 -0
- cgelab-0.5.0/tests/test_sam.py +47 -0
- cgelab-0.5.0/tests/test_sensitivity.py +105 -0
- cgelab-0.5.0/tests/test_site_examples.py +27 -0
- cgelab-0.5.0/tests/test_tariff.py +195 -0
- cgelab-0.5.0/tests/test_trade_curves.py +139 -0
- cgelab-0.5.0/tests/test_welfare.py +89 -0
- cgelab-0.5.0/tests/test_welfare_decomposition.py +92 -0
- cgelab-0.5.0/tools/check_site_examples.py +83 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `cgelab`. Versions follow [semantic versioning](https://semver.org/);
|
|
4
|
+
before 1.0, a minor version may add to the API and a patch version only fixes.
|
|
5
|
+
|
|
6
|
+
## 0.5.0 — 2026-10-18
|
|
7
|
+
|
|
8
|
+
The first public release, on PyPI together with dsgelab 0.5. It gathers the roadmap's
|
|
9
|
+
milestones 0.3 and 0.4, which were not released on their own, and the release engineering of
|
|
10
|
+
0.5. Python 3.10 is no longer supported.
|
|
11
|
+
|
|
12
|
+
### Changed since 0.2.0
|
|
13
|
+
|
|
14
|
+
- Renamed from `cgekit` to `cgelab`: `cgekit` is taken on PyPI by an
|
|
15
|
+
unrelated project. The import name, distribution name, CLI entry point,
|
|
16
|
+
the `CGELAB_RUN_JULIA` switch and the URLs all move together.
|
|
17
|
+
|
|
18
|
+
### Added in 0.2, after 0.2.0
|
|
19
|
+
|
|
20
|
+
- Large-country trade. `ModelSpec.export_demand` puts exports on a demand curve,
|
|
21
|
+
`E / E0 = (pWe / export_price)^(-η)`, and `ModelSpec.import_supply` puts
|
|
22
|
+
imports on a supply curve, `M / M0 = (pWm / world_price)^ψ`: the equations of
|
|
23
|
+
Hosoe's `lrgcge`. A scalar or a mapping by commodity; the rest stay price
|
|
24
|
+
takers. The scenario prices become the shifts of the curves, and
|
|
25
|
+
`PeriodResult.world_export_price` and `world_import_price` hold the solved
|
|
26
|
+
world prices. The base year is unchanged. `export_demand` needs
|
|
27
|
+
`export_rule="cet"`; the regional slice refuses both. The JuMP replica carries
|
|
28
|
+
the curves as constraints, and three new round-trip cases match it to 1e-12.
|
|
29
|
+
- Import tariff and indirect tax on output, separate from the product tax on
|
|
30
|
+
absorption and inside the prices they fall on, as in Hosoe's `stdcge`.
|
|
31
|
+
`calibrate(..., tariffs=)` or `ModelSpec.tariff_account` sets the base-year
|
|
32
|
+
tariff (Hosoe's `taum`), and the Armington nest is calibrated on the
|
|
33
|
+
tariff-inclusive value of imports. `calibrate(..., output_taxes=)` or
|
|
34
|
+
`ModelSpec.indirect_tax_account` sets the output tax (Hosoe's `tauz` / IDT),
|
|
35
|
+
and the CET splits output at its tax-inclusive value, so exports carry it.
|
|
36
|
+
Government receives both as levels. `Scenario.tariff` and
|
|
37
|
+
`Scenario.output_tax` move one rate without moving the other; a tariff of
|
|
38
|
+
zero abolishes it. At the calibrated rates the base year is the SAM. The
|
|
39
|
+
JuMP replica carries the same prices.
|
|
40
|
+
- `Closure(government="saving_rate")`: government saves the base-year share
|
|
41
|
+
of its income (`Economy.gov_savrate`) and spends the rest in base-year value
|
|
42
|
+
shares. `Closure(foreign_saving_unit="foreign_currency")`: foreign saving
|
|
43
|
+
fixed in dollars under `foreign="fixed_saving"`. Together they are Hosoe's
|
|
44
|
+
closure.
|
|
45
|
+
- `cgelab.examples.hosoe`: the SAM, functional forms and closure of Hosoe,
|
|
46
|
+
Gasawa and Hashimoto's `stdcge` and, with `large_country=True`, `lrgcge`.
|
|
47
|
+
The tariff abolition of both matches a line-by-line JuMP transcription of the
|
|
48
|
+
GAMS programs (`validation/hosoe.jl`) in all 49 displayed variables, to
|
|
49
|
+
2.4e-12; `tests/test_hosoe_stdcge.py` checks it against the stored result.
|
|
50
|
+
- The JuMP replica converges from a cold start on an applied SAM. Household
|
|
51
|
+
income, spending and the Armington shares now start at base-year levels
|
|
52
|
+
instead of at 1 and at guesses; factor prices and the exchange rate still start
|
|
53
|
+
displaced, so the Python answer never enters the start.
|
|
54
|
+
- `PeriodResult.domestic_sales` and `p_domestic`: home sales of domestic output
|
|
55
|
+
and their price. `base_year_reproduction` now also checks imports and
|
|
56
|
+
exports against the SAM.
|
|
57
|
+
- Several regions. `ModelSpec.regions` and `sigma_interregional`: a CES across
|
|
58
|
+
regions of origin under the Armington nest. Accounts are `region:local`.
|
|
59
|
+
Factors clear where they are; one national numeraire stays unsolved. A single
|
|
60
|
+
labelled region reproduces the legacy solver, including on the plain toy with
|
|
61
|
+
taxes and intermediates. `examples.regions` is a hand-written two-region SAM.
|
|
62
|
+
Margins, CET, LES, migration, non-default closures, `run_path` and `to_jump`
|
|
63
|
+
are refused by name on this slice.
|
|
64
|
+
- `factor_demand_by_activity`, `real_gdp` and `sectoral_path`: employment by
|
|
65
|
+
activity, real GDP from both sides with the tax gap named, and a tidy sectoral
|
|
66
|
+
panel along a path. `PeriodResult.factor_demand_by_activity` holds the matrix
|
|
67
|
+
the solver used.
|
|
68
|
+
- A replications page on the site (`site/replications.html`, and the Portuguese pair).
|
|
69
|
+
The benchmark of Hosoe, Gasawa and Hashimoto (2004), chapter 5, as printed in the
|
|
70
|
+
GAMS library file `splcge`, reproduces: output 15 and 35, prices 1. A SAM that
|
|
71
|
+
invests nothing no longer raises on an empty investment basket.
|
|
72
|
+
- `Scenario.investment_mix`: commodity composition of the investment budget.
|
|
73
|
+
Absent, the base-year mix. Distinct from `Growth.allocation`, which shares
|
|
74
|
+
investment across capital stocks.
|
|
75
|
+
- `Closure.labour`: `full_employment` (unchanged default), `fixed_real_wage`,
|
|
76
|
+
`wage_curve` and `elastic_supply`. The three new closures refuse a labour
|
|
77
|
+
numeraire. Unemployment is not paid. `PeriodResult.employment`,
|
|
78
|
+
`unemployment` and `real_wage`. The JuMP export carries the same equations.
|
|
79
|
+
|
|
80
|
+
### Added in 0.3
|
|
81
|
+
|
|
82
|
+
- SAM multipliers and input–output analysis (`cgelab.multipliers`):
|
|
83
|
+
`accounting_multipliers` (Pyatt and Round), `fixed_price_multipliers` with
|
|
84
|
+
marginal propensities from income elasticities and an Engel-aggregation check,
|
|
85
|
+
`leontief_multipliers` (activities and commodities endogenous), `linkages`
|
|
86
|
+
(backward from the Leontief inverse, forward from the Ghosh inverse, with
|
|
87
|
+
Rasmussen indices) and `structural_paths` (Defourny and Thorbecke). The
|
|
88
|
+
Leontief inverse reproduces Miller and Blair's two-sector example; the total
|
|
89
|
+
influences of all elementary paths add up to the multiplier (Lantner's
|
|
90
|
+
identity), to 1e-10.
|
|
91
|
+
|
|
92
|
+
- National accounts (`national_accounts`): GDP at current prices by expenditure
|
|
93
|
+
and by income, which agree in every equilibrium, and GNI. Price and quantity
|
|
94
|
+
indices (`price_indices`): Laspeyres, Paasche and Fisher by component of final
|
|
95
|
+
demand, for GDP and for the terms of trade, against the base year or another
|
|
96
|
+
solved period. The government account (`government_account`,
|
|
97
|
+
`PeriodResult.government`): revenue by instrument, outlays and saving, recorded
|
|
98
|
+
by the solver at the solution. `PeriodResult.household_saving` and
|
|
99
|
+
`forced_saving`.
|
|
100
|
+
|
|
101
|
+
- Systematic sensitivity (`sensitivity`, `spec_sweep`): Stroud's degree-3
|
|
102
|
+
quadrature, exact in the mean for results up to cubic in the parameters, and
|
|
103
|
+
Monte Carlo with a fixed seed, over `Uniform`, `Normal` and `Triangular`
|
|
104
|
+
parameters. `spec_sweep` recalibrates at every point.
|
|
105
|
+
|
|
106
|
+
- Subtotals (`subtotals`, `path_decomposition`): the Harrison, Horridge and
|
|
107
|
+
Pearson decomposition of a result by groups of shocks, integrated along the
|
|
108
|
+
straight path from reference to alternative. The contributions add up to the
|
|
109
|
+
solved change, with a residual of order 1e-8 that is reported. On closed forms
|
|
110
|
+
they are the line integrals.
|
|
111
|
+
|
|
112
|
+
- Welfare decomposition (`welfare_decomposition`): Huff and Hertel's split of
|
|
113
|
+
the change in real absorption into endowment, technology, one allocative term
|
|
114
|
+
per instrument, terms of trade and the external account, integrated along the
|
|
115
|
+
path. The identity closes to below 1e-9 in ten economies and closures; it is
|
|
116
|
+
not validated against GTAP, which needs the GTAP database.
|
|
117
|
+
- `cgelab.examples.hosoe.build_simple()`: Hosoe's chapter 5 (`splcge`).
|
|
118
|
+
|
|
119
|
+
### Fixed in 0.3
|
|
120
|
+
|
|
121
|
+
- An undetermined exchange rate is refused. With fixed export shares, a
|
|
122
|
+
Cobb–Douglas Armington on every imported commodity and foreign saving fixed in
|
|
123
|
+
numeraire units, every exchange rate is an equilibrium; the solver used to
|
|
124
|
+
return whichever its start point was.
|
|
125
|
+
|
|
126
|
+
- The activity tax paid by an own-account activity never reached government:
|
|
127
|
+
households paid it in the price and the tax block counted market activities
|
|
128
|
+
only, so the base year did not reproduce and Walras was off by the tax. The
|
|
129
|
+
JuMP replica had the same omission.
|
|
130
|
+
|
|
131
|
+
### Added in 0.4
|
|
132
|
+
|
|
133
|
+
- Government targets (`Closure.government_target`, `government_adjusts`):
|
|
134
|
+
government saving held fixed (a deficit target) or total revenue held fixed
|
|
135
|
+
(revenue-neutral tax replacement), met by scaling every direct tax rate, every
|
|
136
|
+
product tax rate, or government consumption in base-year shares.
|
|
137
|
+
`PeriodResult.tax_scale` is the factor. The JuMP replica carries the same
|
|
138
|
+
closures; `Economy.gov_saving0` and `gov_revenue0` are the base-year targets.
|
|
139
|
+
|
|
140
|
+
- Emissions accounts (`add_emissions`, `emissions`) calibrated from base-year
|
|
141
|
+
totals by source (combustion in production, household and government fuel
|
|
142
|
+
use, process), and a carbon price (`Scenario.carbon_price`): a tax per unit of
|
|
143
|
+
output by emission intensity on activities, a specific tax on household fuel.
|
|
144
|
+
The revenue is reported by source and recycled by the revenue-neutral
|
|
145
|
+
closure. GDP, the welfare decomposition, subtotals and the JuMP replica carry
|
|
146
|
+
it.
|
|
147
|
+
|
|
148
|
+
- Value-added-energy nesting (`ModelSpec.energy`, `sigma_vae`,
|
|
149
|
+
`sigma_energy`): an energy bundle, a CES across fuels, substitutes for value
|
|
150
|
+
added in a CES; other intermediates stay Leontief. The carbon price on a fuel
|
|
151
|
+
enters the price each activity pays for it. With zero elasticities the nest is
|
|
152
|
+
the Leontief model exactly; with positive ones the fuel ratios meet the CES
|
|
153
|
+
first-order conditions. The JuMP replica carries the nest.
|
|
154
|
+
`PeriodResult.input_coefficients` and `value_added_per_unit` are the
|
|
155
|
+
coefficients the equilibrium used.
|
|
156
|
+
|
|
157
|
+
- GTAP-E's arrangement (`ModelSpec.energy_nest="capital"`, `energy_capital`,
|
|
158
|
+
`sigma_ke`): energy joins a capital factor in a capital-energy composite that
|
|
159
|
+
sits inside the value-added nest. With `sigma_ke = sigma_va` it collapses to the
|
|
160
|
+
value-added nest with `sigma_vae = sigma_va`, and the two solve to the same
|
|
161
|
+
equilibrium to 1e-11; capital and energy meet their first-order condition; the
|
|
162
|
+
JuMP replica carries both arrangements.
|
|
163
|
+
- The bridge to dsgelab (`cgelab.bridge`, `pip install "cgelab[dsge]"`): a
|
|
164
|
+
Ramsey CGE in which an Euler equation chooses investment and every period is
|
|
165
|
+
the SAM model. dsgelab gives its steady state, first-order solution, impulse
|
|
166
|
+
responses and perfect-foresight transitions; `announced` turns a sequence of
|
|
167
|
+
scenarios into an announced policy. In a one-good closed economy it is the
|
|
168
|
+
stochastic growth model: same steady state, transition matrices and path, to
|
|
169
|
+
1e-7. `toy.build_one_good()` is that economy; `Scenario.investment_level`
|
|
170
|
+
sets real investment under `fixed_real`.
|
|
171
|
+
|
|
172
|
+
- Physical units (`add_physical_units`, `physical`, `physical_coefficient`):
|
|
173
|
+
physical content per unit of a commodity's Armington composite and of an
|
|
174
|
+
activity's output, calibrated from base-year totals; physical supply, use by
|
|
175
|
+
agent, output and intensity of a solved period; and the translation of a
|
|
176
|
+
physical technical coefficient into a SAM entry. Supply meets use in every
|
|
177
|
+
equilibrium, margins included.
|
|
178
|
+
|
|
179
|
+
### Fixed in 0.4
|
|
180
|
+
|
|
181
|
+
- `homogeneity_test` held a fixed exchange rate at one while it scaled the
|
|
182
|
+
numeraire, so every `foreign="fixed_rate"` closure failed the test for a
|
|
183
|
+
reason that was the test's. The rate is nominal and now scales too.
|
|
184
|
+
|
|
185
|
+
### Added toward 0.7
|
|
186
|
+
|
|
187
|
+
- `read_har` and `write_har`: GEMPACK header array files, the format of the GTAP
|
|
188
|
+
database, without GEMPACK. On GTAP 10A (2014) the 86 headers harpy3 reads
|
|
189
|
+
agree with it exactly, and four GTAP identities close to single precision.
|
|
190
|
+
The data are licensed and never committed.
|
|
191
|
+
|
|
192
|
+
### Release engineering (0.5)
|
|
193
|
+
|
|
194
|
+
- CI runs the suite on Python 3.11–3.14 on Linux, macOS and Windows, and against
|
|
195
|
+
the installed wheel (`CGELAB_TEST_INSTALLED=1`), with `twine check`, both with
|
|
196
|
+
dsgelab installed so the bridge is tested. A
|
|
197
|
+
`validation` workflow runs the JuMP replica and the Hosoe transcription on
|
|
198
|
+
demand and weekly. A `release` workflow, started by pushing a tag `vX.Y.Z`,
|
|
199
|
+
checks that the tag matches the version in `pyproject.toml`, the package and
|
|
200
|
+
`CITATION.cff`, and that the dsgelab the `dsge` extra needs is on PyPI;
|
|
201
|
+
publishes to TestPyPI by trusted publishing, installs what TestPyPI serves and
|
|
202
|
+
runs the suite against it, and only then publishes to PyPI. The site's deploy
|
|
203
|
+
is skipped while the repository is private.
|
|
204
|
+
- The sdist carries what its test suite needs (`MANIFEST.in`): the fixtures, the
|
|
205
|
+
site and the tool that runs its examples. `cgelab --version` and
|
|
206
|
+
`python -m cgelab`. The README's links are absolute, so they also work on PyPI.
|
|
207
|
+
- `py.typed`; Python-version, OS and typing classifiers; the `dsge` extra, which
|
|
208
|
+
needs `dsgelab>=0.5`. The licence is declared as an SPDX expression (`MIT`),
|
|
209
|
+
with `LICENSE` as the licence file.
|
|
210
|
+
- The examples, the docs and the site import the package as `cge` and dsgelab as
|
|
211
|
+
`dsg`, and link to dsgelab's site. The site's language selector names both
|
|
212
|
+
languages with an icon.
|
|
213
|
+
- `CONTRIBUTING.md` with the definition of done and a release checklist; issue
|
|
214
|
+
and pull request templates; a known-limitations section in the README.
|
|
215
|
+
- `docs/comparison.md` in English; the Portuguese version is
|
|
216
|
+
`docs/comparison.pt-br.md`.
|
|
217
|
+
|
|
218
|
+
## 0.2.0 — 2026-09-25
|
|
219
|
+
|
|
220
|
+
The first release as a standalone package. Four gaps and two bugs, found while building a
|
|
221
|
+
regional recursive-dynamic CGE on the package, are closed. Every new `Economy` field defaults to
|
|
222
|
+
zero, so a SAM without the new flows gives the same results as 0.1.0.
|
|
223
|
+
|
|
224
|
+
### Fixed
|
|
225
|
+
|
|
226
|
+
- **CET exports were never solved.** `export_rule="cet"` was accepted by `ModelSpec` and
|
|
227
|
+
advertised, but the solver always used fixed export shares. Output now splits along the CET
|
|
228
|
+
frontier; the domestic price comes from the inverse revenue function (`cet_domestic_price`).
|
|
229
|
+
- **The external target was read from two fields.** Under `foreign="fixed_saving"` the trade
|
|
230
|
+
target came from `trade_balance0` and saving from `foreign_sav`, so moving `foreign_sav` alone
|
|
231
|
+
left a Walras residual that grew along a path. `foreign_sav` is now the single target.
|
|
232
|
+
- **Institutional flows in the SAM were dropped.** Household income was read as the row total, but
|
|
233
|
+
the solver modelled only factor income: a SAM with a direct tax, a government transfer or a
|
|
234
|
+
remittance missed its own base year (by 12% on `toy.build_with_institutions`).
|
|
235
|
+
- **LES marginal budget shares** assumed commodity spending equals income net of saving, which is
|
|
236
|
+
wrong with direct taxes or purchases made straight from an activity. They now use the calibrated
|
|
237
|
+
commodity budget (`Economy.hh_spend0`).
|
|
238
|
+
|
|
239
|
+
### Added
|
|
240
|
+
|
|
241
|
+
- `Scenario.export_price` — world export prices, read under CET and refused under fixed shares.
|
|
242
|
+
`sigma_cet` accepts a mapping by commodity.
|
|
243
|
+
- Direct taxes (`gov <- hh`), government transfers (`hh <- gov`) and remittances (`hh <-> row`),
|
|
244
|
+
with saving out of disposable income. `PeriodResult.hh_direct_tax`; welfare income is net of
|
|
245
|
+
direct tax.
|
|
246
|
+
- Factor income paid to government and abroad (`gov <- f`, `row <- f`); foreign saving is the
|
|
247
|
+
current account. `Scenario.foreign_factor_share` overrides the SAM's foreign shares.
|
|
248
|
+
- `Scenario.fdi` — foreign direct investment that raises foreign saving and, in `run_path`, adds
|
|
249
|
+
the capital it buys to a foreign-owned stock whose returns leave the economy.
|
|
250
|
+
`PathResult.foreign_capital` records it.
|
|
251
|
+
- Several capital stocks: `Growth.capital_factor` takes a sequence, `depreciation` a mapping, and
|
|
252
|
+
`allocation` shares domestic investment proportionally or by relative rent.
|
|
253
|
+
- `run_path(economy=f(year, t))` — a different `Economy` each year, for changes that are not
|
|
254
|
+
scenario fields (input coefficients, a foreign-saving path).
|
|
255
|
+
- `econ.diagnostics["unmodelled_flows"]` lists SAM cells the model does not read.
|
|
256
|
+
- The JuMP export replicates all of the above; `validation/roundtrip_jump.py` runs 16 cases
|
|
257
|
+
against Ipopt (worst deviation 3e-12). Opt-in pytest cases with `CGELAB_RUN_JULIA=1`.
|
|
258
|
+
- `toy.build_with_institutions` and `toy.build_with_specific_capital`.
|
|
259
|
+
- A `LICENSE` file, continuous integration, a published site, and the comparison with other
|
|
260
|
+
packages as `docs/comparison.md`.
|
|
261
|
+
|
|
262
|
+
## 0.1.0 — 2026-09-09
|
|
263
|
+
|
|
264
|
+
First version, developed inside a research repository: SAM container, balance gate and
|
|
265
|
+
sign-preserving RAS; calibration with margins, negative value added, LES and own-account
|
|
266
|
+
activities; within-period solution under five closures; scenarios and wedge recycling; recursive
|
|
267
|
+
dynamics; equivalent and compensating variation with composition-immune group aggregation;
|
|
268
|
+
base-year, homogeneity and Walras diagnostics; export to JuMP.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software in a publication, please cite it as below."
|
|
3
|
+
type: software
|
|
4
|
+
title: "cgelab: a general toolkit for SAM-based computable general equilibrium models in Python"
|
|
5
|
+
abstract: >-
|
|
6
|
+
Social accounting matrix handling and balancing, calibration, configurable nests and closures, CET and Armington trade, direct taxes, transfers and foreign ownership, within-period solution, recursive dynamics with several capital stocks and FDI, and welfare measurement, with base-year reproduction, homogeneity and Walras checks built in and an independent JuMP replica for validation.
|
|
7
|
+
authors:
|
|
8
|
+
- family-names: "Moreira"
|
|
9
|
+
given-names: "Gustavo Hoffmann"
|
|
10
|
+
email: "gustavo@gakusai.net"
|
|
11
|
+
orcid: "https://orcid.org/0000-0003-0827-2521"
|
|
12
|
+
version: "0.5.0"
|
|
13
|
+
date-released: "2026-10-18"
|
|
14
|
+
license: MIT
|
|
15
|
+
# A repository URL is not an archivable reference. Connect the repository to Zenodo, cut a
|
|
16
|
+
# release, and add the DOI below; that is what makes the citation stable.
|
|
17
|
+
repository-code: "https://github.com/GustavoHM/cgelab"
|
|
18
|
+
url: "https://gustavohm.github.io/cgelab/"
|
|
19
|
+
# doi: "10.5281/zenodo.XXXXXXX"
|
|
20
|
+
keywords:
|
|
21
|
+
- "computable general equilibrium"
|
|
22
|
+
- "social accounting matrix"
|
|
23
|
+
- "input-output"
|
|
24
|
+
- "Python"
|
cgelab-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gustavo Hoffmann Moreira
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cgelab-0.5.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# What the sdist needs beyond the package, so that its test suite runs from the
|
|
2
|
+
# unpacked tree: the fixtures, the site whose examples are tested, and the tool
|
|
3
|
+
# that runs them. validation/ needs Julia and stays out.
|
|
4
|
+
include CHANGELOG.md CITATION.cff
|
|
5
|
+
include tests/conftest.py
|
|
6
|
+
recursive-include tests/data *.json
|
|
7
|
+
include tools/check_site_examples.py
|
|
8
|
+
graft site
|
|
9
|
+
global-exclude .DS_Store
|
cgelab-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cgelab
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: General-purpose toolkit for SAM-based computable general equilibrium models: balancing, calibration, closures, CET trade, institutions and foreign ownership, recursive dynamics with several capital stocks, and welfare.
|
|
5
|
+
Author-email: Gustavo Hoffmann Moreira <gustavo@gakusai.net>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gustavohm.github.io/cgelab/
|
|
8
|
+
Project-URL: Documentation, https://github.com/GustavoHM/cgelab/tree/main/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/GustavoHM/cgelab
|
|
10
|
+
Project-URL: Issues, https://github.com/GustavoHM/cgelab/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/GustavoHM/cgelab/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: cge,general equilibrium,social accounting matrix,input-output,armington
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Intended Audience :: Science/Research
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.24
|
|
29
|
+
Requires-Dist: scipy>=1.10
|
|
30
|
+
Requires-Dist: pandas>=2.0
|
|
31
|
+
Provides-Extra: parquet
|
|
32
|
+
Requires-Dist: pyarrow>=14; extra == "parquet"
|
|
33
|
+
Provides-Extra: dsge
|
|
34
|
+
Requires-Dist: dsgelab>=0.5; extra == "dsge"
|
|
35
|
+
Provides-Extra: test
|
|
36
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# cgelab
|
|
40
|
+
|
|
41
|
+
[](https://github.com/GustavoHM/cgelab/actions/workflows/tests.yml)
|
|
42
|
+
[](https://gustavohm.github.io/cgelab/)
|
|
43
|
+
[](https://github.com/GustavoHM/cgelab/blob/main/LICENSE)
|
|
44
|
+
|
|
45
|
+
A general toolkit for SAM-based computable general equilibrium models in Python.
|
|
46
|
+
You supply a social accounting matrix. The package calibrates a standard nested
|
|
47
|
+
CGE from it, solves each period, runs a recursive-dynamic path and measures
|
|
48
|
+
welfare. The accounting checks that make any of it believable are built in
|
|
49
|
+
rather than left to the user.
|
|
50
|
+
|
|
51
|
+
A model is assembled from three separable objects, and keeping them separable is
|
|
52
|
+
the point:
|
|
53
|
+
|
|
54
|
+
| Object | Says |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `SAM` | what the base year **was** |
|
|
57
|
+
| `ModelSpec` | what is **assumed** about substitution and functional form |
|
|
58
|
+
| `Closure` | which balances are imposed and **who adjusts** |
|
|
59
|
+
|
|
60
|
+
Results can turn on the last two, so both travel with the results instead of
|
|
61
|
+
living in a branch inside a solver.
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pip install cgelab # from PyPI
|
|
67
|
+
pip install "cgelab[parquet]" # adds pyarrow for .parquet SAMs
|
|
68
|
+
pip install "cgelab[dsge]" # adds dsgelab, for forward-looking investment
|
|
69
|
+
pip install "cgelab @ git+https://github.com/GustavoHM/cgelab" # the current main branch
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For development:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
git clone https://github.com/GustavoHM/cgelab && cd cgelab
|
|
76
|
+
pip install -e ".[test]" && pytest
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Requires Python 3.11+, numpy, scipy and pandas. Try it with no data at all:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
cgelab # runs the bundled toy economy and prints the diagnostics
|
|
83
|
+
cgelab my_sam.csv --sigma-armington 2.0 --sigma-va 0.5 # the same on your own SAM
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Quick start
|
|
87
|
+
|
|
88
|
+
The bundled toy economy has every SAM entry written out, so the base year is
|
|
89
|
+
known on paper and this runs as it is:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
import cgelab as cge
|
|
93
|
+
from cgelab.examples import toy
|
|
94
|
+
|
|
95
|
+
sam, econ = toy.build()
|
|
96
|
+
print(cge.report(econ)) # base-year reproduction, Walras, homogeneity
|
|
97
|
+
|
|
98
|
+
base = cge.solve_period(econ)
|
|
99
|
+
shock = cge.solve_period(econ, scenario=cge.Scenario(
|
|
100
|
+
name="tax +50%", product_tax=econ.ptax * 1.5))
|
|
101
|
+
print(shock.summary())
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A counterfactual over a horizon, and its welfare incidence:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
growth = cge.Growth(labour=0.005, tfp=0.010, depreciation=0.05, discount=0.05)
|
|
108
|
+
years = range(2021, 2046)
|
|
109
|
+
|
|
110
|
+
W = cge.consumer_wedge(econ, {"c_ind": 0.03})
|
|
111
|
+
ref = cge.run_path(econ, years=years, growth=growth)
|
|
112
|
+
alt = cge.run_path(econ, years=years, growth=growth,
|
|
113
|
+
scenario=lambda y, t: cge.Scenario(consumer_wedge=W,
|
|
114
|
+
wedge_revenue_to="capital")
|
|
115
|
+
if y >= 2026 else cge.Scenario())
|
|
116
|
+
|
|
117
|
+
ev = cge.equivalent_variation(ref, alt)
|
|
118
|
+
print(cge.ev_by_group(ev, {"hh_1": "rich", "hh_2": "poor"}))
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
With your own data, the first lines change (a `.parquet` SAM needs the `parquet` extra):
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
sam = cge.SAM.read("my_sam.parquet") # or SAM.from_long(df) / SAM.from_square(df)
|
|
125
|
+
sam.check_balance() # a hard gate, not a warning
|
|
126
|
+
econ = cge.calibrate(sam, cge.ModelSpec(sigma_armington=2.0, sigma_va=0.5))
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Model structure
|
|
130
|
+
|
|
131
|
+
* **Production:** Leontief between the intermediate bundle and value added, and
|
|
132
|
+
within the intermediate bundle. A configurable nest (CES, Cobb–Douglas or
|
|
133
|
+
Leontief) combines factors inside value added.
|
|
134
|
+
* **Make:** commodity market shares are fixed at base-year proportions, so
|
|
135
|
+
activity levels follow from commodity output, `X = MSH @ Q`.
|
|
136
|
+
* **Armington:** CES between domestic and imported varieties.
|
|
137
|
+
* **Exports:** fixed shares by default, or a CET frontier that answers to world
|
|
138
|
+
export prices. The default is deliberate: the CET elasticity is the one
|
|
139
|
+
parameter of a standard CGE that input–output sources do not supply.
|
|
140
|
+
* **Households:** Cobb–Douglas or LES over commodities, out of income net of
|
|
141
|
+
direct tax, saving and payments made straight to an activity. Income includes
|
|
142
|
+
government transfers and net transfers from abroad.
|
|
143
|
+
* **Ownership:** factor income is shared among households, government and the
|
|
144
|
+
rest of the world. Returns to foreign-owned capital leave through the current
|
|
145
|
+
account, and foreign saving is the current account, not the trade balance.
|
|
146
|
+
* **Government, investment, foreign:** five closure combinations, each with its
|
|
147
|
+
own adjusting variable (see `Closure`).
|
|
148
|
+
* **Dynamics:** recursive, with one or several capital stocks accumulated from
|
|
149
|
+
their service flows, investment shared by relative rent, FDI that builds
|
|
150
|
+
foreign-owned capital, and an economy that may change year by year.
|
|
151
|
+
|
|
152
|
+
The **numeraire factor's market is deliberately not solved**. It is left to
|
|
153
|
+
Walras' law, so its residual is an independent check on the accounting rather
|
|
154
|
+
than an identity the solver was told to satisfy. It is recorded on every
|
|
155
|
+
period.
|
|
156
|
+
|
|
157
|
+
## What is in the box
|
|
158
|
+
|
|
159
|
+
| Capability | Entry point |
|
|
160
|
+
|---|---|
|
|
161
|
+
| SAM container, balance gate, sign-preserving RAS; GEMPACK/GTAP header array files | `SAM`, `read_har`, `write_har` |
|
|
162
|
+
| Calibration: coefficients, nests, taxes (tariff and output tax inside prices), margins, LES subsistence, institutional flows, a list of cells the model does not read | `calibrate` |
|
|
163
|
+
| Within-period equilibrium; investment, government (including deficit and revenue targets), foreign and labour closures | `solve_period`, `Closure` |
|
|
164
|
+
| Trade: Armington, CET, export demand and import supply curves (large country) | `ModelSpec` |
|
|
165
|
+
| Energy: a value-added-energy or capital-energy nest with interfuel substitution, emissions accounts, a carbon price, physical units | `ModelSpec.energy`, `add_emissions`, `add_physical_units` |
|
|
166
|
+
| Counterfactuals: taxes, wedges, endowments, ownership, productivity, own-account levels, world prices, FDI, the investment basket | `Scenario` |
|
|
167
|
+
| Recursive dynamics: several capital stocks, investment allocation, foreign-owned capital, a per-year economy | `run_path`, `Growth` |
|
|
168
|
+
| Forward-looking investment (a Ramsey CGE solved by dsgelab) | `cgelab.bridge` |
|
|
169
|
+
| Accounts: GDP from both sides, Laspeyres, Paasche and Fisher indices, terms of trade, the government account | `national_accounts`, `price_indices`, `government_account` |
|
|
170
|
+
| Decompositions: subtotals by shock, Huff-Hertel welfare decomposition | `subtotals`, `welfare_decomposition` |
|
|
171
|
+
| SAM multipliers, linkages, structural path analysis | `accounting_multipliers`, `linkages`, `structural_paths` |
|
|
172
|
+
| Systematic sensitivity: Stroud quadrature and Monte Carlo over elasticities | `sensitivity`, `spec_sweep` |
|
|
173
|
+
| Welfare: EV, CV and composition-immune group aggregation | `cgelab.welfare` |
|
|
174
|
+
| Base-year reproduction, homogeneity, Walras | `cgelab.diagnostics` |
|
|
175
|
+
| The same equilibrium as a JuMP model, for independent validation | `to_jump` |
|
|
176
|
+
|
|
177
|
+
## Documentation
|
|
178
|
+
|
|
179
|
+
- [Site](https://gustavohm.github.io/cgelab/): an overview with runnable examples, in English and Portuguese, and a replications page
|
|
180
|
+
- [`docs/guide.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/guide.md): the user guide, from SAM to welfare
|
|
181
|
+
- [`docs/api.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/api.md): API reference
|
|
182
|
+
- [`docs/whitepaper.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/whitepaper.md): the mathematics of calibration, the period equilibrium, recursive dynamics and welfare (in Portuguese)
|
|
183
|
+
- [`docs/design-notes.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/design-notes.md): the accounting decisions and the errors they prevent
|
|
184
|
+
- [`docs/from-scripts.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/from-scripts.md): porting an existing CGE pipeline
|
|
185
|
+
- [`docs/comparison.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/comparison.md): how this package compares with what exists, and where it does not win
|
|
186
|
+
- [`CHANGELOG.md`](https://github.com/GustavoHM/cgelab/blob/main/CHANGELOG.md), [`ROADMAP.md`](https://github.com/GustavoHM/cgelab/blob/main/ROADMAP.md), [`CONTRIBUTING.md`](https://github.com/GustavoHM/cgelab/blob/main/CONTRIBUTING.md)
|
|
187
|
+
|
|
188
|
+
## Verification
|
|
189
|
+
|
|
190
|
+
Every number the package produces is checked against something it did not
|
|
191
|
+
compute itself:
|
|
192
|
+
|
|
193
|
+
- **Hand-built SAMs** whose every entry is written out, so the base year is known on
|
|
194
|
+
paper: base-year reproduction, zero-degree homogeneity and Walras' law in every
|
|
195
|
+
closure, on every variant (margins, own-account activities, institutions, trade
|
|
196
|
+
taxes, CET, energy nests, carbon).
|
|
197
|
+
- **Closed forms and published tables**: Miller and Blair's Leontief inverse, the
|
|
198
|
+
stochastic growth model (for the bridge to dsgelab), Stroud quadrature on cubics,
|
|
199
|
+
CES first-order conditions, and the identities that hold in every equilibrium
|
|
200
|
+
(GDP from both sides, the welfare decomposition, subtotals that add up).
|
|
201
|
+
- **A published model**: the tariff abolition of Hosoe, Gasawa and Hashimoto's
|
|
202
|
+
`stdcge` and `lrgcge` against a line-by-line JuMP transcription of the GAMS
|
|
203
|
+
programs, in all 49 displayed variables, to 2.4e-12.
|
|
204
|
+
- **An independent replica**: `to_jump` writes the same equilibrium as a JuMP model
|
|
205
|
+
in which nothing is nested. `validation/roundtrip_jump.py` runs 34 cases; the
|
|
206
|
+
nested solver and Ipopt agree to 1.2e-11.
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
pytest # the suite, without external tools
|
|
210
|
+
cd validation && julia --project=. -e 'using Pkg; Pkg.instantiate()' && cd ..
|
|
211
|
+
python validation/roundtrip_jump.py # the JuMP replica
|
|
212
|
+
python validation/replicate_hosoe.py # stdcge and lrgcge
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Scope and known limitations
|
|
216
|
+
|
|
217
|
+
`cgelab` covers a single-country CGE at applied scale. It does not have the
|
|
218
|
+
maturity of GAMS or GEMPACK, and [`docs/comparison.md`](https://github.com/GustavoHM/cgelab/blob/main/docs/comparison.md) says
|
|
219
|
+
where it stands. Things to know before relying on it:
|
|
220
|
+
|
|
221
|
+
- **Several regions** share one origin nest under the Armington. Factors do not
|
|
222
|
+
migrate, and the regional slice refuses margins, CET, LES, trade taxes, energy
|
|
223
|
+
nests and most closures by name. GTAP-style bilateral trade is 0.7.
|
|
224
|
+
- **No complementarity**: activities cannot switch off, and there are no quotas,
|
|
225
|
+
price floors or capacity limits. That is 0.8.
|
|
226
|
+
- **The solver** uses finite-difference Jacobians on a few unknowns. It is fine up
|
|
227
|
+
to a few hundred accounts; each commodity put on a trade curve adds an unknown.
|
|
228
|
+
- **Fixed proportions everywhere** (`sigma_va = 0` in every activity) can leave
|
|
229
|
+
the model without a solution under full employment of every factor.
|
|
230
|
+
- **Under fixed export shares** with a Cobb-Douglas Armington, the exchange rate is
|
|
231
|
+
not determined, and `solve_period` refuses that combination; near an Armington
|
|
232
|
+
elasticity of one it is badly conditioned.
|
|
233
|
+
- **Forward-looking investment** goes through [dsgelab](https://github.com/GustavoHM/dsgelab)
|
|
234
|
+
(`pip install "cgelab[dsge]"`). `run_path` itself has no forward-looking agent.
|
|
235
|
+
- **GTAP data** can be read, but not yet aggregated or turned into a SAM, and the
|
|
236
|
+
welfare decomposition has not been compared with GTAP's own.
|
|
237
|
+
- **Platforms**: an editable install (`pip install -e`) can break silently on
|
|
238
|
+
Python 3.14 on macOS; install from the wheel if `import cgelab` fails.
|
|
239
|
+
|
|
240
|
+
## Citing
|
|
241
|
+
|
|
242
|
+
If a published result went through this package, cite it. Software is a
|
|
243
|
+
methodological input like any other, and the version matters: a number that
|
|
244
|
+
only reproduces under one version is not reproducible without it.
|
|
245
|
+
[`CITATION.cff`](https://github.com/GustavoHM/cgelab/blob/main/CITATION.cff) carries the metadata, with the author's ORCID, in
|
|
246
|
+
the format GitHub reads. A repository URL is not an archivable reference: each
|
|
247
|
+
release will be archived on Zenodo, and the DOI it receives, which will be added
|
|
248
|
+
to that file, is the reference to cite.
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
MIT. See [`LICENSE`](https://github.com/GustavoHM/cgelab/blob/main/LICENSE).
|