Pathway Allocation Functions¶
Pathway allocation functions generate annual emission allocation shares over time.
Overview¶
All pathway allocation approaches return a PathwayAllocationResult containing:
approach: Name of the allocation approach usedparameters: Dictionary of parameters used in the calculationrelative_shares_pathway_emissions: DataFrame of annual shares (sum to 1.0 each year)
Per Capita Pathways¶
equal_per_capita¶
fair_shares.library.allocations.pathways.per_capita.equal_per_capita ¶
equal_per_capita(
population_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
preserve_first_allocation_year_shares: bool = False,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Equal per capita pathway allocation based on population shares.
Allocates emissions in proportion to population, with no adjustments for historical responsibility or economic capability.
Mathematical Foundation
Mode 1: Dynamic shares (preserve_first_allocation_year_shares=False, default)
Population shares are calculated at each year from first_allocation_year onwards. This accounts for changes in relative population shares over time:
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\)
- \(P(g, t)\): Population of country \(g\) at year \(t\)
- \(\sum_{g'} P(g', t)\): Total world population at year \(t\)
Mode 2: Preserved shares (preserve_first_allocation_year_shares=True)
Population shares calculated at the first_allocation_year are preserved across all periods. This means the relative allocation between groups remains constant:
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\) (constant for all \(t \geq t_a\))
- \(P(g, t_a)\): Population of country \(g\) at first allocation year \(t_a\)
- \(\sum_{g'} P(g', t_a)\): Total world population at first allocation year
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for each group of interest. |
required |
first_allocation_year
|
int
|
First year that should be used for calculating the allocation. This must be a column in population_ts. See docs/science/parameter-effects.md#allocation_year for how this affects country shares |
required |
emission_category
|
str
|
Emission category to include in the output. |
required |
preserve_first_allocation_year_shares
|
bool
|
If False (default), shares are calculated at each year from first_allocation_year onwards. If True, shares calculated at the first_allocation_year are preserved across all periods. |
False
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
Notes
The equal per capita principle treats the atmosphere as a finite shared resource with equal claims per person. It serves as a widely used baseline in climate equity analysis.
When to Use
- As a baseline to compare against adjusted approaches
- When transparency and simplicity are priorities
- As a reference point before applying responsibility or capability adjustments
See docs/science/allocations.md for theoretical grounding and limitations.
Examples:
>>> from fair_shares.library.utils import create_example_data
>>> data = create_example_data()
>>> result = equal_per_capita(
... population_ts=data["population"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... )
Converting units...
>>> # Check that shares sum to 1.0 at each year
>>> shares = result.relative_shares_pathway_emissions
>>> shares_2020 = shares["2020"]
>>> bool(abs(shares_2020.sum() - 1.0) < 1e-10)
True
>>> # China and India have similar populations, so similar shares
>>> bool(shares_2020.loc["CHN"].item() > 0.3) # China has large population
True
>>> bool(shares_2020.loc["IND"].item() > 0.3) # India has large population too
True
See Also
per_capita_adjusted : With pre-allocation responsibility/capability adjustments per_capita_adjusted_gini : With Gini-adjusted GDP
per_capita_adjusted¶
fair_shares.library.allocations.pathways.per_capita.per_capita_adjusted ¶
per_capita_adjusted(
population_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
country_actual_emissions_ts: (
TimeseriesDataFrame | None
) = None,
gdp_ts: TimeseriesDataFrame | None = None,
pre_allocation_responsibility_weight: float = 0.0,
capability_weight: float = 0.0,
pre_allocation_responsibility_year: int = 1990,
pre_allocation_responsibility_per_capita: bool = True,
pre_allocation_responsibility_exponent: float = 1.0,
pre_allocation_responsibility_functional_form: str = "asinh",
capability_per_capita: bool = True,
capability_exponent: float = 1.0,
capability_functional_form: str = "asinh",
max_deviation_sigma: float | None = 2.0,
preserve_first_allocation_year_shares: bool = False,
historical_discount_rate: float = 0.0,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Per capita pathway allocation with pre-allocation responsibility and capability adjustments.
Extends equal per capita by incorporating:
- Responsibility adjustment: Countries with higher historical emissions receive smaller allocations
- Capability adjustment: Countries with higher GDP (per capita or absolute) receive smaller allocations
Mathematical Foundation
Mode 1: Dynamic adjusted shares (preserve_first_allocation_year_shares=False, default)
Shares are computed by adjusting population at each year:
Where the adjusted population is:
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\)
- \(P_{\text{adj}}(g, t)\): Adjusted population of country \(g\) at year \(t\)
- \(P(g, t)\): Actual population of country \(g\) at year \(t\)
- \(R(g)\): Responsibility adjustment factor (constant over time, equals 1.0 if not used)
- \(C(g, t)\): Capability adjustment factor (time-varying, equals 1.0 if not used)
Mode 2: Preserved adjusted shares (preserve_first_allocation_year_shares=True)
Shares calculated at first_allocation_year are broadcast across all years.
Responsibility Adjustment
The responsibility metric is based on cumulative historical emissions from pre_allocation_responsibility_year to first_allocation_year.
For per capita responsibility (:code:pre_allocation_responsibility_per_capita=True, default):
Where:
- \(R(g)\): Responsibility adjustment factor (inverse - higher emissions = lower allocation)
- \(E(g, t)\): Emissions of country \(g\) in year \(t\)
- \(t_h\): Historical responsibility start year
- \(t_a\): First allocation year
- \(w_r\): Normalized responsibility weight
- \(e_r\): Responsibility exponent
For absolute responsibility (:code:pre_allocation_responsibility_per_capita=False):
Capability Adjustment
The capability metric is based on cumulative GDP per capita from
first_allocation_year up to year :math:t.
For per capita capability (:code:capability_per_capita=True, default):
Where:
- \(C(g, t)\): Capability adjustment factor (inverse - higher cumulative GDP per capita = lower allocation)
- \(\text{GDP}(g, t')\): Gross domestic product of country \(g\) in year \(t'\)
- \(w_c\): Normalized capability weight
- \(e_c\): Capability exponent
For absolute capability (:code:capability_per_capita=False):
Deviation Constraint
When :code:max_deviation_sigma is provided, shares are constrained to prevent
extreme deviations from equal per capita. The constraint limits allocations to
within :math:\sigma standard deviations of the equal per capita baseline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for per capita calculations. |
required |
first_allocation_year
|
int
|
Starting year for the allocation. See docs/science/parameter-effects.md#allocation_year for how this affects country shares |
required |
emission_category
|
str
|
The emission category (e.g., 'co2-ffi', 'all-ghg'). |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame | None
|
Country emissions for responsibility calculation. Required if pre_allocation_responsibility_weight > 0. |
None
|
gdp_ts
|
TimeseriesDataFrame | None
|
GDP time series for capability adjustment. Required if capability_weight > 0. |
None
|
pre_allocation_responsibility_weight
|
float
|
Weight for responsibility adjustment (0-1). Higher historical emissions -> smaller allocation. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 See docs/science/parameter-effects.md#pre_allocation_responsibility_weight for real allocation examples showing how this affects country shares |
0.0
|
capability_weight
|
float
|
Weight for capability adjustment (0-1). Higher cumulative GDP per capita -> smaller allocation. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 See docs/science/parameter-effects.md#capability_weight for real allocation examples showing how this affects country shares |
0.0
|
pre_allocation_responsibility_year
|
int
|
First year of responsibility window [pre_allocation_responsibility_year, first_allocation_year]. Default: 1990 |
1990
|
pre_allocation_responsibility_per_capita
|
bool
|
If True, use per capita emissions for responsibility. Default: True |
True
|
pre_allocation_responsibility_exponent
|
float
|
Exponent for responsibility adjustment calculation. Default: 1.0 |
1.0
|
pre_allocation_responsibility_functional_form
|
str
|
Functional form for responsibility adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
capability_exponent
|
float
|
Exponent for capability adjustment calculation. Default: 1.0 |
1.0
|
capability_functional_form
|
str
|
Functional form for capability adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
max_deviation_sigma
|
float | None
|
Maximum allowed deviation from equal per capita baseline. Constrains allocations to remain within a statistically reasonable range of the equal per capita baseline, preventing extreme adjustments. If None, no constraint is applied. |
2.0
|
preserve_first_allocation_year_shares
|
bool
|
If False (default), shares are calculated at each year. If True, shares calculated at first_allocation_year are preserved across all periods. |
False
|
historical_discount_rate
|
float
|
Discount rate for historical emissions (0.0 to <1.0). When > 0, earlier emissions are weighted less via (1 - rate)^(reference_year - t). Implements natural CO2 removal rationale (Dekker Eq. 5). Default: 0.0 (no discounting). |
0.0
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
Notes
This approach operationalizes Common But Differentiated Responsibilities and Respective Capabilities (CBDR-RC) by combining:
- Historical Responsibility (Polluter Pays Principle): Adjusts allocations based on cumulative historical emissions — countries that contributed more to the problem bear greater obligations
- Capability (Ability to Pay Principle): Adjusts based on economic resources — countries with greater capacity bear greater obligations
Parameter choices involve normative judgments that should be made transparently:
- Choice of start year for historical responsibility
- Whether to use per capita or absolute metrics
- Choice of GDP indicator (PPP vs. MER)
- Transformation of indicators onto allocation scales
See docs/science/allocations.md for theoretical grounding.
Examples:
>>> from fair_shares.library.utils import create_example_data
>>> data = create_example_data()
>>> # Equal weights for responsibility and capability (50/50 split)
>>> result = per_capita_adjusted(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... gdp_ts=data["gdp"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.5,
... capability_weight=0.5,
... )
Converting units...
>>> # Check that shares sum to 1.0
>>> shares = result.relative_shares_pathway_emissions
>>> shares_2020 = shares["2020"]
>>> bool(abs(shares_2020.sum() - 1.0) < 1e-10)
True
>>> # High emitters like USA should have smaller shares than equal per capita
>>> equal_pc_result = equal_per_capita(
... population_ts=data["population"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... )
Converting units...
>>> equal_pc_shares = equal_pc_result.relative_shares_pathway_emissions["2020"]
>>> # USA has lower share with adjustments due to high historical emissions + GDP
>>> bool(shares_2020.loc["USA"].item() < equal_pc_shares.loc["USA"].item())
True
See Also
equal_per_capita : Without adjustments per_capita_adjusted_gini : With Gini-adjusted GDP
per_capita_adjusted_gini¶
fair_shares.library.allocations.pathways.per_capita.per_capita_adjusted_gini ¶
per_capita_adjusted_gini(
population_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
country_actual_emissions_ts: (
TimeseriesDataFrame | None
) = None,
gdp_ts: TimeseriesDataFrame | None = None,
gini_s: DataFrame | None = None,
pre_allocation_responsibility_weight: float = 0.0,
capability_weight: float = 0.0,
pre_allocation_responsibility_year: int = 1990,
pre_allocation_responsibility_per_capita: bool = True,
pre_allocation_responsibility_exponent: float = 1.0,
pre_allocation_responsibility_functional_form: str = "asinh",
capability_per_capita: bool = True,
capability_exponent: float = 1.0,
capability_functional_form: str = "asinh",
income_floor: float = 7500.0,
max_gini_adjustment: float = 0.8,
max_deviation_sigma: float | None = 2.0,
preserve_first_allocation_year_shares: bool = False,
historical_discount_rate: float = 0.0,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Per capita pathway allocation with pre-allocation responsibility, capability, and Gini adjustments.
The most comprehensive variant, incorporating:
- Responsibility adjustment: Countries with higher historical emissions receive smaller allocations
- Capability adjustment: Countries with higher Gini-adjusted GDP (per capita or absolute) receive smaller allocations
- Gini adjustment: GDP is adjusted for income inequality within countries
Mathematical Foundation
Similar to :func:per_capita_adjusted, but capability uses Gini-adjusted GDP
to account for income inequality within countries.
Gini Adjustment Process
GDP is adjusted using an interpretation of the Greenhouse Development
Rights (GDR) framework's capability metric (note: GDR was designed for
burden-sharing; fair-shares adapts its capability calculation for
entitlement allocation). Only income above a development threshold counts
as capability. When combined with the income floor, higher inequality
means more national income sits above the threshold — increasing measured
capability. See
:func:~fair_shares.library.utils.math.allocation.calculate_gini_adjusted_gdp
for the full mathematical derivation.
Capability Adjustment with Gini-Adjusted GDP
For per capita capability (:code:capability_per_capita=True, default):
Where:
- \(C(g, t)\): Capability adjustment factor using Gini-adjusted GDP
- \(\text{GDP}^{\text{adj}}(g, t')\): Gini-adjusted GDP in year \(t'\)
- \(P(g, t')\): Population in year \(t'\)
- \(t_a\): First allocation year
- \(w_c\): Normalized capability weight
- \(e_c\): Capability exponent
For absolute capability (:code:capability_per_capita=False):
Gini Adjustment Effect
When combined with the income floor, higher inequality means more national
income sits above the development threshold, creating larger per-person
excesses. Countries with high inequality and high GDP thus receive smaller
emission allocations (higher measured capability = more ability to pay).
See :func:~fair_shares.library.utils.math.allocation.calculate_gini_adjusted_gdp
for worked examples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for per capita calculations. |
required |
first_allocation_year
|
int
|
Starting year for the allocation. See docs/science/parameter-effects.md#allocation_year for how this affects country shares |
required |
emission_category
|
str
|
The emission category (e.g., 'co2-ffi', 'all-ghg'). |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame | None
|
Country emissions for responsibility calculation. Required if pre_allocation_responsibility_weight > 0. |
None
|
gdp_ts
|
TimeseriesDataFrame | None
|
GDP time series for capability adjustment. Required if capability_weight > 0 or gini_s provided. |
None
|
gini_s
|
DataFrame | None
|
Gini coefficients for GDP inequality adjustment. When provided, GDP is adjusted to reflect income distribution within countries. |
None
|
pre_allocation_responsibility_weight
|
float
|
Weight for responsibility adjustment (0-1). Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
capability_weight
|
float
|
Weight for capability adjustment (0-1). Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
pre_allocation_responsibility_year
|
int
|
First year of responsibility window. Default: 1990 |
1990
|
pre_allocation_responsibility_per_capita
|
bool
|
If True, use per capita emissions for responsibility. Default: True |
True
|
pre_allocation_responsibility_exponent
|
float
|
Exponent for responsibility adjustment calculation. Default: 1.0 |
1.0
|
pre_allocation_responsibility_functional_form
|
str
|
Functional form for responsibility adjustment. Default: 'asinh' |
'asinh'
|
capability_exponent
|
float
|
Exponent for capability adjustment calculation. Default: 1.0 |
1.0
|
capability_functional_form
|
str
|
Functional form for capability adjustment. Default: 'asinh' |
'asinh'
|
income_floor
|
float
|
Income floor for Gini adjustment (in USD PPP per capita). Income below this threshold is excluded from capability calculations, adapted from the Greenhouse Development Rights (GDR) development threshold [Baer 2013] (GDR was designed for burden-sharing; fair-shares uses its capability metric in an entitlement allocation context). Default: 7500.0 See docs/science/parameter-effects.md#income_floor for real allocation examples showing how this affects country shares |
7500.0
|
max_gini_adjustment
|
float
|
Maximum reduction factor from GDR threshold adjustment (0-1). Limits how much the development threshold deduction can reduce effective GDP. Default: 0.8 |
0.8
|
max_deviation_sigma
|
float | None
|
Maximum allowed deviation from equal per capita baseline. Constrains allocations to remain within a statistically reasonable range of the equal per capita baseline, preventing extreme adjustments. If None, no constraint is applied. |
2.0
|
preserve_first_allocation_year_shares
|
bool
|
If False (default), shares are calculated at each year. If True, shares calculated at first_allocation_year are preserved across all periods. |
False
|
historical_discount_rate
|
float
|
Discount rate for historical emissions (0.0 to <1.0). When > 0, earlier emissions are weighted less via (1 - rate)^(reference_year - t). Implements natural CO2 removal rationale (Dekker Eq. 5). Default: 0.0 (no discounting). |
0.0
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
Notes
This approach extends capability-based allocation by incorporating intra-national
inequality via the GDR development threshold (adapted for entitlement
allocation from GDR's burden-sharing context). Only income above the
development threshold counts toward capability. When combined with the income
floor, higher inequality means more national income sits above the threshold.
See :func:~fair_shares.library.utils.math.allocation.calculate_gini_adjusted_gdp
for the mathematical formulation.
When to Use
- When capability assessment should account for income distribution within countries
- When the development threshold (income floor) should affect capability measurement
- For comprehensive allocation incorporating population, historical responsibility, and inequality-adjusted capability
See docs/science/allocations.md for theoretical grounding.
Examples:
>>> from fair_shares.library.utils import create_example_data
>>> data = create_example_data()
>>> # Equal weights with Gini adjustment
>>> result = per_capita_adjusted_gini(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... gdp_ts=data["gdp"],
... gini_s=data["gini"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.5,
... capability_weight=0.5,
... )
Converting units...
>>> # Check that shares sum to 1.0
>>> shares = result.relative_shares_pathway_emissions
>>> shares_2020 = shares["2020"]
>>> bool(abs(shares_2020.sum() - 1.0) < 1e-10)
True
>>> # Verify approach is correctly identified
>>> result.approach
'per-capita-adjusted-gini'
>>> # Verify all countries have valid shares (between 0 and 1)
>>> bool((shares_2020 >= 0).all() and (shares_2020 <= 1).all())
True
>>> # Compare to non-Gini version - shares will differ due to inequality adjustment
>>> result_no_gini = per_capita_adjusted(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... gdp_ts=data["gdp"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.5,
... capability_weight=0.5,
... )
Converting units...
>>> shares_no_gini = result_no_gini.relative_shares_pathway_emissions["2020"]
>>> # Gini adjustment changes the allocation pattern
>>> bool(not shares_2020.equals(shares_no_gini))
True
See Also
equal_per_capita : Without adjustments per_capita_adjusted : Without Gini adjustment
Convergence Pathways¶
per_capita_convergence¶
fair_shares.library.allocations.pathways.per_capita_convergence.per_capita_convergence ¶
per_capita_convergence(
population_ts: TimeseriesDataFrame,
country_actual_emissions_ts: TimeseriesDataFrame,
first_allocation_year: int,
convergence_year: int,
emission_category: str,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Per capita convergence pathway blending grandfathering and equal per capita.
This approach transitions from grandfathering (GF) to equal per capita (EPC) from allocation time, \(t_{a}\), to convergence time, \(t_{conv}\), using a linear weight \(M(t)\). It implements a variant of Contraction and Convergence [GCI 2003], where global emissions contract while per capita emissions converge to equality by a target date.
Mathematical Foundation
Baseline Shares at Allocation Time
Grandfathering and equal per capita shares at allocation time are calculated as:
Where:
- \(E(g, t_{a})\): Emissions of country \(g\) at first allocation year \(t_a\)
- \(P(g, t_{a})\): Population of country \(g\) at first allocation year \(t_a\)
Time-Dependent Blending Weight
The transition weight \(M(t)\) controls the blend between grandfathering and equal per capita:
- \(M(t) = 1\) for \(t \le t_{a}\) (full grandfathering at start)
- \(M(t) = \frac{t_{conv} - t}{t_{conv} - t_{a}}\) for \(t_{a} < t < t_{conv}\)
- \(M(t) = 0\) for \(t \ge t_{conv}\) (full equal per capita at convergence)
Blended Allocation
The final allocation blends the two principles:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Timeseries of population for each group of interest. |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame
|
Timeseries of emissions for each group of interest. |
required |
first_allocation_year
|
int
|
First year that should be used for calculating the allocation. This must be a column in both population and emissions. |
required |
convergence_year
|
int
|
Year by which allocations fully converge to equal per capita. |
required |
emission_category
|
str
|
Emission category to include in the output. |
required |
group_level
|
str
|
Level in index specifying group information. Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Level in index specifying units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
The unit registry to use for calculations. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Container with relative shares for pathway emissions allocation. The TimeseriesDataFrame contains all years from first_allocation_year onwards with shares that sum to 1 across groups for the specified emission category. |
Notes
When to Use
- Academic comparison with Contraction and Convergence scenarios
- Exploring sensitivity of allocations to transition period length
- When a gradual transition from status quo is explicitly desired
Limitations
- Does not incorporate historical responsibility for past emissions
- Does not incorporate capability/ability to pay
- The grandfathering starting point lacks ethical basis (see referenced docs)
For allocations grounded in CBDR-RC principles, consider using per_capita_adjusted or cumulative_per_capita_convergence approaches.
Examples:
Calculate per capita convergence allocation transitioning from current emission shares to equal per capita shares over a 30-year period.
>>> from fair_shares.library.utils import create_example_data
>>> data = create_example_data(
... countries=["USA", "CHN", "IND"], years=[2020, 2030, 2050]
... )
>>> result = per_capita_convergence(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... first_allocation_year=2020,
... convergence_year=2050,
... emission_category="co2-ffi",
... )
>>> result.approach
'per-capita-convergence'
>>> result.parameters["convergence_year"]
2050
>>> # Result contains relative shares that blend from current emissions
>>> # (grandfathering) at 2020 to equal per capita at 2050
>>> result.relative_shares_pathway_emissions.sum(axis=0).round(3)
2020 1.000
2030 1.000
2050 1.000
dtype: float64
See Also
per_capita_adjusted : Equal per capita with pre-allocation responsibility/capability adjustments cumulative_per_capita_convergence : Convergence accounting for cumulative emissions
cumulative_per_capita_convergence¶
fair_shares.library.allocations.pathways.cumulative_per_capita_convergence.cumulative_per_capita_convergence ¶
cumulative_per_capita_convergence(
population_ts: TimeseriesDataFrame,
country_actual_emissions_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
world_scenario_emissions_ts: TimeseriesDataFrame,
max_deviation_sigma: float | None = 2.0,
max_convergence_speed: float = 0.9,
strict: bool = True,
historical_start_year: int | None = None,
convergence_method: str = "minimum-speed",
convergence_year: int | None = None,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Pure cumulative per capita convergence allocation without adjustments.
Allocates emissions based on cumulative population shares, converging from initial emission shares to cumulative per capita targets over time.
Mathematical Foundation
Convergence Dynamics
The allocation shares evolve through exponential convergence:
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\)
- \(A^{\infty}(g)\): Long-run target share that each year converges toward
- \(\lambda\): Convergence speed (automatically determined to be minimum feasible)
Initial Shares
Initial shares at first_allocation_year are based on actual emissions:
Where:
- \(A(g, t_a)\): Initial allocation share for country \(g\) at first allocation year
- \(E(g, t_a)\): Actual emissions of country \(g\) at year \(t_a\)
- \(t_a\): First allocation year
- \(\sum_{g'} E(g', t_a)\): Total world emissions at first allocation year
Cumulative Target Shares
The cumulative target shares are based on cumulative population:
Where:
- \(T_{\text{cum}}(g)\): Cumulative target share for country \(g\)
- \(P(g, t)\): Population of country \(g\) at year \(t\)
- \(\sum_{t \geq t_a} P(g, t)\): Cumulative population of country \(g\) from allocation year onwards
- \(\sum_{g'} \sum_{t \geq t_a} P(g', t)\): Total cumulative world population from allocation year onwards
Convergence Speed Determination
The convergence speed \(\lambda\) is automatically determined to be the minimum speed that ensures cumulative allocations match targets:
Where:
- \(w(t)\): Year weight for year \(t\), defined as \(w(t) = \frac{W(t)}{\sum_{t' \geq t_a} W(t')}\)
- \(W(t)\): World emissions in year \(t\) from the scenario pathway
Deviation Constraint
When :code:max_deviation_sigma is provided, cumulative target shares are
constrained to prevent extreme deviations from equal cumulative per capita:
Where:
- \(T_{\text{equal}}(g)\): Equal cumulative per capita baseline share
- \(\sigma\): Maximum deviation parameter (e.g., 2.0 standard deviations)
- \(s\): Population-weighted standard deviation of unconstrained cumulative targets
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for calculating cumulative per capita shares. |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame
|
Country emissions for calculating initial shares at first_allocation_year. |
required |
world_scenario_emissions_ts
|
TimeseriesDataFrame
|
World emissions pathway defining the time horizon and year weights. |
required |
first_allocation_year
|
int
|
Starting year for the allocation. |
required |
emission_category
|
str
|
The emission category (e.g., 'co2-ffi', 'all-ghg'). |
required |
max_deviation_sigma
|
float | None
|
Maximum allowed deviation from equal per capita baseline in terms of population-weighted standard deviations. If provided, constrains each group's share to be within ±max_deviation_sigma standard deviations from the baseline equal per capita share. If None, no constraint is applied. |
2.0
|
max_convergence_speed
|
float
|
Maximum allowed convergence speed (0 to 1.0). Lower values create smoother pathways but may become infeasible. Default: 0.9. |
0.9
|
strict
|
bool
|
If True (default), raise error for infeasible convergence. If False, use nearest feasible solution with warnings. |
True
|
historical_start_year
|
int | None
|
If provided, cumulative population for target shares is computed from this year instead of first_allocation_year. Must be <= first_allocation_year. Shifts entitlements toward historically populous countries (e.g. China, India pre-industrial) when early start years like 1850 are used. Default: None (use first_allocation_year). |
None
|
convergence_method
|
str
|
Convergence algorithm to use. "minimum-speed" (default): exponential convergence with binary-search for minimum feasible speed. "sine-deviation" (Dekker Eqs. 7-8): iterative sine-shaped correction from a PCC baseline; requires convergence_year. |
'minimum-speed'
|
convergence_year
|
int | None
|
Year by which allocations converge to equal per capita. Required when convergence_method='sine-deviation'. Must be > first_allocation_year. Default: None. |
None
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
See Also
cumulative_per_capita_convergence_adjusted : With pre-allocation responsibility/capability adjustments cumulative_per_capita_convergence_adjusted_gini : With Gini-adjusted GDP
Notes
Theoretical grounding:
For theoretical foundations, use cases, and limitations, see: docs/science/allocations.md#convergence-mechanism-theoretical-foundations
For translating the egalitarian tradition (which grounds the equal per capita principle) into pathway allocations, see: docs/science/principle-to-code.md#convergence-pathway-approaches
For CBDR-RC principles (responsibility and capability), use cumulative_per_capita_convergence_adjusted or cumulative_per_capita_convergence_adjusted_gini.
Convergence Speed
The convergence speed is automatically determined to be the minimum speed
that ensures cumulative targets are met, creating the smoothest possible
transition path while still achieving equity goals. The strict parameter
controls whether an error is raised if exact targets cannot be achieved.
Examples:
Basic usage with default parameters:
>>> from fair_shares.library.utils import create_example_data
>>> from fair_shares.library.allocations.pathways import (
... cumulative_per_capita_convergence,
... )
>>> # Create example data
>>> data = create_example_data(
... countries=["USA", "CHN", "IND"], years=[2020, 2030, 2050]
... )
>>> # Run allocation with strict=False for limited time horizon
>>> result = cumulative_per_capita_convergence(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... strict=False, # Accept approximate targets with limited data
... )
Converting units...
>>> # Check approach is correct
>>> result.approach
'cumulative-per-capita-convergence'
>>> # Shares sum to 1.0 at each year
>>> shares = result.relative_shares_pathway_emissions
>>> bool(abs(shares["2020"].sum() - 1.0) < 1e-10)
True
Adjust convergence behavior with strict=False for approximate targets:
>>> result_approx = cumulative_per_capita_convergence(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... strict=False, # Accept approximate targets
... max_convergence_speed=0.5, # Slower, smoother convergence
... )
Converting units...
>>> # Check for warnings about deviations
>>> if result_approx.country_warnings:
... print("Some targets approximate:", result_approx.country_warnings)
Remove deviation constraints for unconstrained targets:
>>> result_unconstrained = cumulative_per_capita_convergence(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... max_deviation_sigma=None, # No constraints on target shares
... strict=False, # Needed for limited data
... )
Converting units...
cumulative_per_capita_convergence_adjusted¶
fair_shares.library.allocations.pathways.cumulative_per_capita_convergence.cumulative_per_capita_convergence_adjusted ¶
cumulative_per_capita_convergence_adjusted(
population_ts: TimeseriesDataFrame,
country_actual_emissions_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
world_scenario_emissions_ts: TimeseriesDataFrame,
gdp_ts: TimeseriesDataFrame | None = None,
pre_allocation_responsibility_weight: float = 0.0,
capability_weight: float = 0.0,
pre_allocation_responsibility_year: int = 1990,
pre_allocation_responsibility_per_capita: bool = True,
pre_allocation_responsibility_exponent: float = 1.0,
pre_allocation_responsibility_functional_form: str = "asinh",
capability_per_capita: bool = True,
capability_exponent: float = 1.0,
capability_functional_form: str = "asinh",
max_deviation_sigma: float | None = 2.0,
max_convergence_speed: float = 0.9,
strict: bool = True,
historical_start_year: int | None = None,
historical_discount_rate: float = 0.0,
convergence_method: str = "minimum-speed",
convergence_year: int | None = None,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Cumulative per capita convergence with pre-allocation responsibility and capability adjustments.
Extends cumulative per capita convergence by incorporating:
- Responsibility adjustment: Countries with higher historical emissions receive smaller allocations
- Capability adjustment: Countries with higher GDP receive smaller allocations
Mathematical Foundation
Convergence Dynamics
The allocation shares evolve through exponential convergence (same as base approach):
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\)
- \(A^{\infty}(g)\): Long-run target share
- \(\lambda\): Convergence speed (automatically determined)
Initial shares at first_allocation_year are based on actual emissions.
Cumulative Target Shares with Adjustments
Target shares are computed by adjusting cumulative population for historical responsibility and economic capability:
Where the adjusted population is:
Where:
- \(T_{\text{cum}}(g)\): Cumulative target share for country \(g\)
- \(P_{\text{adj}}(g)\): Adjusted cumulative population
- \(P_{\text{cum}}(g) = \sum_{t \geq t_a} P(g, t)\): Cumulative population from allocation year onwards
- \(R(g)\): Responsibility adjustment factor (equals 1.0 if not used)
- \(C(g)\): Capability adjustment factor (equals 1.0 if not used)
Responsibility Adjustment
The responsibility metric is based on cumulative historical emissions from pre_allocation_responsibility_year to first_allocation_year.
For per capita responsibility (:code:pre_allocation_responsibility_per_capita=True, default):
Where:
- \(R(g)\): Responsibility adjustment factor (inverse - higher emissions = lower allocation)
- \(E(g, t)\): Emissions of country \(g\) in year \(t\)
- \(t_h\): Historical responsibility start year
- \(t_a\): First allocation year
- \(w_r\): Normalized responsibility weight
- \(e_r\): Responsibility exponent
For absolute responsibility (:code:pre_allocation_responsibility_per_capita=False):
Capability Adjustment
The capability metric is based on cumulative GDP from first_allocation_year onwards.
For per capita capability (:code:capability_per_capita=True, default):
Where:
- \(C(g)\): Capability adjustment factor (inverse - higher cumulative GDP per capita = lower allocation)
- \(\text{GDP}(g, t)\): Gross domestic product of country \(g\) in year \(t\)
- \(w_c\): Normalized capability weight
- \(e_c\): Capability exponent
For absolute capability (:code:capability_per_capita=False):
Deviation Constraint
When :code:max_deviation_sigma is provided, adjusted cumulative target shares
are constrained to prevent extreme deviations from equal cumulative per capita.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for per capita calculations and responsibility adjustment. |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame
|
Country emissions for initial shares and responsibility calculation. |
required |
world_scenario_emissions_ts
|
TimeseriesDataFrame
|
World emissions pathway defining time horizon and year weights. |
required |
first_allocation_year
|
int
|
Starting year for the allocation. |
required |
emission_category
|
str
|
The emission category (e.g., 'co2-ffi', 'all-ghg'). |
required |
gdp_ts
|
TimeseriesDataFrame | None
|
GDP time series for capability adjustment. Required if capability_weight > 0. |
None
|
pre_allocation_responsibility_weight
|
float
|
Weight for responsibility adjustment (0-1). Higher historical emissions -> smaller allocation. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
capability_weight
|
float
|
Weight for capability adjustment (0-1). Higher GDP -> smaller allocation. Applies from the first allocation year onwards (contrast with pre-allocation responsibility, which looks backward from it). Requires gdp_ts. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
pre_allocation_responsibility_year
|
int
|
First year of responsibility window [pre_allocation_responsibility_year, first_allocation_year]. Default: 1990 |
1990
|
pre_allocation_responsibility_per_capita
|
bool
|
If True, use per capita emissions for responsibility. Default: True |
True
|
pre_allocation_responsibility_exponent
|
float
|
Exponent for responsibility adjustment calculation. Default: 1.0 |
1.0
|
pre_allocation_responsibility_functional_form
|
str
|
Functional form for responsibility adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
capability_per_capita
|
bool
|
If True, use per capita GDP for capability. Default: True |
True
|
capability_exponent
|
float
|
Exponent for capability adjustment calculation. Default: 1.0 |
1.0
|
capability_functional_form
|
str
|
Functional form for capability adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
max_deviation_sigma
|
float | None
|
Maximum allowed deviation from equal per capita baseline in terms of population-weighted standard deviations. If None, no constraint is applied. |
2.0
|
max_convergence_speed
|
float
|
Maximum allowed convergence speed (0 to 1.0). Lower values create smoother pathways but may become infeasible. Default: 0.9 |
0.9
|
strict
|
bool
|
If True (default), raise error for infeasible convergence. If False, use nearest feasible solution with warnings. |
True
|
historical_start_year
|
int | None
|
If provided, cumulative population for target shares is computed from this year instead of first_allocation_year. Must be <= first_allocation_year. Shifts entitlements toward historically populous countries. Default: None (use first_allocation_year). |
None
|
historical_discount_rate
|
float
|
Discount rate for historical emissions (0.0 to <1.0). When > 0, earlier emissions are weighted less via (1 - rate)^(reference_year - t). Implements natural CO2 removal rationale (Dekker Eq. 5). Default: 0.0 (no discounting). |
0.0
|
convergence_method
|
str
|
Convergence algorithm to use. "minimum-speed" (default): exponential convergence with binary-search for minimum feasible speed. "sine-deviation" (Dekker Eqs. 7-8): iterative sine-shaped correction from a PCC baseline; requires convergence_year. |
'minimum-speed'
|
convergence_year
|
int | None
|
Year by which allocations converge to equal per capita. Required when convergence_method='sine-deviation'. Must be > first_allocation_year. Default: None. |
None
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
See Also
cumulative_per_capita_convergence : Without adjustments cumulative_per_capita_convergence_adjusted_gini : With Gini-adjusted GDP
Notes
Theoretical grounding:
For theoretical foundations and CBDR-RC principles, see: docs/science/allocations.md#convergence-mechanism-theoretical-foundations docs/science/allocations.md#4-common-but-differentiated-responsibilities-cbdr-rc
For translating equity principles into pathway allocations, see: docs/science/principle-to-code.md#convergence-pathway-approaches docs/science/principle-to-code.md#cbdr-rc
This approach incorporates historical responsibility and capability adjustments to operationalize Common But Differentiated Responsibilities and Respective Capabilities (CBDR-RC). Higher past emissions and higher GDP -> smaller allocation.
Examples:
Basic usage with equal responsibility and capability weights:
>>> from fair_shares.library.utils import create_example_data
>>> from fair_shares.library.allocations.pathways import (
... cumulative_per_capita_convergence_adjusted,
... )
>>> # Create example data
>>> data = create_example_data(
... countries=["USA", "CHN", "IND"], years=[2020, 2030, 2050]
... )
>>> # Run allocation with adjustments and strict=False for limited data
>>> result = cumulative_per_capita_convergence_adjusted(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... gdp_ts=data["gdp"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.5, # 50% adjustment for historical emissions
... capability_weight=0.5, # 50% adjustment for GDP
... strict=False, # Accept approximate targets with limited data
... )
Converting units...
>>> # Check results - high emitters get less than pure per-capita
>>> result.approach
'cumulative-per-capita-convergence-adjusted'
>>> # Shares sum to 1.0 at each year
>>> shares = result.relative_shares_pathway_emissions
>>> bool(abs(shares["2020"].sum() - 1.0) < 1e-10)
True
Adjust convergence speed for smoother pathways:
>>> result_smooth = cumulative_per_capita_convergence_adjusted(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... gdp_ts=data["gdp"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.3,
... capability_weight=0.3,
... max_convergence_speed=0.5,
... strict=False,
... )
Converting units...
>>> # Check for warnings if targets couldn't be met exactly
>>> if result_smooth.country_warnings:
... print("Approximate targets:", result_smooth.country_warnings)
Emphasize responsibility over capability:
>>> result_responsibility = cumulative_per_capita_convergence_adjusted(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... gdp_ts=data["gdp"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.7,
... capability_weight=0.3,
... strict=False,
... )
Converting units...
>>> # Historical emitters penalized more than in equal-weight case
>>> result_responsibility.parameters["pre_allocation_responsibility_weight"]
0.7
cumulative_per_capita_convergence_adjusted_gini¶
fair_shares.library.allocations.pathways.cumulative_per_capita_convergence.cumulative_per_capita_convergence_adjusted_gini ¶
cumulative_per_capita_convergence_adjusted_gini(
population_ts: TimeseriesDataFrame,
country_actual_emissions_ts: TimeseriesDataFrame,
first_allocation_year: int,
emission_category: str,
world_scenario_emissions_ts: TimeseriesDataFrame,
gdp_ts: TimeseriesDataFrame | None = None,
gini_s: DataFrame | None = None,
pre_allocation_responsibility_weight: float = 0.0,
capability_weight: float = 0.0,
pre_allocation_responsibility_year: int = 1990,
pre_allocation_responsibility_per_capita: bool = True,
pre_allocation_responsibility_exponent: float = 1.0,
pre_allocation_responsibility_functional_form: str = "asinh",
capability_per_capita: bool = True,
capability_exponent: float = 1.0,
capability_functional_form: str = "asinh",
income_floor: float = 7500.0,
max_gini_adjustment: float = 0.8,
max_deviation_sigma: float | None = 2.0,
max_convergence_speed: float = 0.9,
strict: bool = True,
historical_start_year: int | None = None,
historical_discount_rate: float = 0.0,
convergence_method: str = "minimum-speed",
convergence_year: int | None = None,
group_level: str = "iso3c",
unit_level: str = "unit",
ur: PlainRegistry = get_default_unit_registry(),
) -> PathwayAllocationResult
Cumulative per capita convergence with Gini-adjusted GDP and full adjustments.
The most comprehensive variant, incorporating:
- Responsibility adjustment: Countries with higher historical emissions receive smaller allocations
- Capability adjustment: Countries with higher GDP receive smaller allocations
- Gini adjustment: GDP is adjusted for income inequality within countries
Mathematical Foundation
Convergence Dynamics
The allocation shares evolve through exponential convergence (same as base approach):
Where:
- \(A(g, t)\): Allocation share for country \(g\) at year \(t\)
- \(A^{\infty}(g)\): Long-run target share
- \(\lambda\): Convergence speed (automatically determined)
Initial shares at first_allocation_year are based on actual emissions.
Cumulative Target Shares with Adjustments
Target shares are computed by adjusting cumulative population for historical responsibility and Gini-adjusted economic capability:
Where the adjusted population is:
Where:
- \(T_{\text{cum}}(g)\): Cumulative target share for country \(g\)
- \(P_{\text{adj}}(g)\): Adjusted cumulative population
- \(P_{\text{cum}}(g) = \sum_{t \geq t_a} P(g, t)\): Cumulative population from allocation year onwards
- \(R(g)\): Responsibility adjustment factor (equals 1.0 if not used)
- \(C_{\text{Gini}}(g)\): Gini-adjusted capability factor (equals 1.0 if not used)
Gini Adjustment Process
GDP is adjusted using an interpretation of the Greenhouse Development
Rights (GDR) framework's capability metric (note: GDR was designed for
burden-sharing; fair-shares adapts its capability calculation for
entitlement allocation). Only income above a development threshold counts
as capability. When combined with the income floor, higher inequality
means more national income sits above the threshold — increasing measured
capability. See
:func:~fair_shares.library.utils.math.allocation.calculate_gini_adjusted_gdp
for the full mathematical derivation.
Responsibility Adjustment
Identical to adjusted convergence (see that function for details).
For per capita responsibility (:code:pre_allocation_responsibility_per_capita=True, default):
Where:
- \(E(g, t)\): Emissions of country \(g\) in year \(t\)
- \(t_h\): Historical responsibility start year
- \(t_a\): First allocation year
- \(w_r\): Normalized responsibility weight
- \(e_r\): Responsibility exponent
Capability Adjustment with Gini-Adjusted GDP
The capability metric uses Gini-adjusted GDP to account for income inequality.
For per capita capability (:code:capability_per_capita=True, default):
Where:
- \(C_{\text{Gini}}(g)\): Gini-adjusted capability factor (inverse - higher adjusted GDP = lower allocation)
- \(\text{GDP}^{\text{adj}}(g, t)\): Gini-adjusted GDP in year \(t\)
- \(w_c\): Normalized capability weight
- \(e_c\): Capability exponent
For absolute capability (:code:capability_per_capita=False):
Gini Adjustment Effect
When combined with the income floor, higher inequality means more national
income sits above the development threshold, creating larger per-person
excesses. Countries with high inequality and high GDP thus receive smaller
emission allocations (higher measured capability = more ability to pay).
See :func:~fair_shares.library.utils.math.allocation.calculate_gini_adjusted_gdp
for worked examples.
Deviation Constraint
When :code:max_deviation_sigma is provided, adjusted cumulative target shares
are constrained to prevent extreme deviations from equal cumulative per capita.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population_ts
|
TimeseriesDataFrame
|
Population time series for per capita calculations and responsibility adjustment. |
required |
country_actual_emissions_ts
|
TimeseriesDataFrame
|
Country emissions for initial shares and responsibility calculation. |
required |
world_scenario_emissions_ts
|
TimeseriesDataFrame
|
World emissions pathway defining time horizon and year weights. |
required |
first_allocation_year
|
int
|
Starting year for the allocation. |
required |
emission_category
|
str
|
The emission category (e.g., 'co2-ffi', 'all-ghg'). |
required |
gdp_ts
|
TimeseriesDataFrame | None
|
GDP time series for capability adjustment. Required if capability_weight > 0 or gini_s provided. |
None
|
gini_s
|
DataFrame | None
|
Gini coefficients for GDP inequality adjustment. When provided, GDP is adjusted to reflect income distribution within countries. |
None
|
pre_allocation_responsibility_weight
|
float
|
Weight for responsibility adjustment (0-1). Higher historical emissions -> smaller allocation. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
capability_weight
|
float
|
Weight for capability adjustment (0-1). Higher GDP -> smaller allocation. Applies from the first allocation year onwards (contrast with pre-allocation responsibility, which looks backward from it). Requires gdp_ts. Must satisfy: pre_allocation_responsibility_weight + capability_weight <= 1.0 |
0.0
|
pre_allocation_responsibility_year
|
int
|
First year of responsibility window [pre_allocation_responsibility_year, first_allocation_year]. Default: 1990 |
1990
|
pre_allocation_responsibility_per_capita
|
bool
|
If True, use per capita emissions for responsibility. Default: True |
True
|
pre_allocation_responsibility_exponent
|
float
|
Exponent for responsibility adjustment calculation. Default: 1.0 |
1.0
|
pre_allocation_responsibility_functional_form
|
str
|
Functional form for responsibility adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
capability_per_capita
|
bool
|
If True, use per capita GDP for capability. Default: True |
True
|
capability_exponent
|
float
|
Exponent for capability adjustment calculation. Default: 1.0 |
1.0
|
capability_functional_form
|
str
|
Functional form for capability adjustment ('asinh', 'power', 'linear'). Default: 'asinh' |
'asinh'
|
income_floor
|
float
|
Income floor for Gini adjustment (in USD). Income below this threshold is excluded from capability calculations. Default: 7500.0 |
7500.0
|
max_gini_adjustment
|
float
|
Maximum reduction factor from GDR threshold adjustment (0-1). Limits how much the development threshold deduction can reduce effective GDP. Default: 0.8 |
0.8
|
max_deviation_sigma
|
float | None
|
Maximum allowed deviation from equal per capita baseline in terms of population-weighted standard deviations. If None, no constraint is applied. |
2.0
|
max_convergence_speed
|
float
|
Maximum allowed convergence speed (0 to 1.0). Lower values create smoother pathways but may become infeasible. Default: 0.9 |
0.9
|
strict
|
bool
|
If True (default), raise error for infeasible convergence. If False, use nearest feasible solution with warnings. |
True
|
historical_start_year
|
int | None
|
If provided, cumulative population for target shares is computed from this year instead of first_allocation_year. Must be <= first_allocation_year. Shifts entitlements toward historically populous countries. Default: None (use first_allocation_year). |
None
|
historical_discount_rate
|
float
|
Discount rate for historical emissions (0.0 to <1.0). When > 0, earlier emissions are weighted less via (1 - rate)^(reference_year - t). Implements natural CO2 removal rationale (Dekker Eq. 5). Default: 0.0 (no discounting). |
0.0
|
convergence_method
|
str
|
Convergence algorithm to use. "minimum-speed" (default): exponential convergence with binary-search for minimum feasible speed. "sine-deviation" (Dekker Eqs. 7-8): iterative sine-shaped correction from a PCC baseline; requires convergence_year. |
'minimum-speed'
|
convergence_year
|
int | None
|
Year by which allocations converge to equal per capita. Required when convergence_method='sine-deviation'. Must be > first_allocation_year. Default: None. |
None
|
group_level
|
str
|
Index level name for grouping (typically 'iso3c'). Default: 'iso3c' |
'iso3c'
|
unit_level
|
str
|
Index level name for units. Default: 'unit' |
'unit'
|
ur
|
PlainRegistry
|
Pint unit registry for unit conversions. |
get_default_unit_registry()
|
Returns:
| Type | Description |
|---|---|
PathwayAllocationResult
|
Relative shares over time, summing to unity each year. |
See Also
cumulative_per_capita_convergence : Without adjustments cumulative_per_capita_convergence_adjusted : Without Gini adjustment
Notes
Theoretical grounding:
For theoretical foundations, intra-national equity, and Gini adjustment rationale, see: docs/science/allocations.md#convergence-mechanism-theoretical-foundations docs/science/allocations.md#gini-adjustment-for-within-country-inequality
For translating equity principles into pathway allocations, see: docs/science/principle-to-code.md#convergence-pathway-approaches docs/science/principle-to-code.md#subsistence-protection
This approach extends the adjusted convergence method by incorporating
Gini-adjusted GDP to account for income inequality within countries. The
income_floor parameter implements the subsistence vs. luxury emissions
distinction. When combined with the income floor, higher inequality means
more national income sits above the threshold — increasing measured capability.
Examples:
Basic usage with Gini-adjusted GDP:
>>> from fair_shares.library.utils import create_example_data
>>> from fair_shares.library.allocations.pathways import (
... cumulative_per_capita_convergence_adjusted_gini,
... )
>>> # Create example data
>>> data = create_example_data(
... countries=["USA", "CHN", "BRA"], years=[2020, 2030, 2050]
... )
>>> # Run allocation with Gini adjustment
>>> result = cumulative_per_capita_convergence_adjusted_gini(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... gdp_ts=data["gdp"],
... gini_s=data["gini"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.5, # 50% adjustment for historical emissions
... capability_weight=0.5, # 50% adjustment for Gini-adjusted GDP
... )
Converting units...
>>> # Check results - Gini adjustment included
>>> result.approach
'cumulative-per-capita-convergence-gini-adjusted'
Adjust Gini parameters to control inequality weighting:
>>> # Custom Gini parameters
>>> result_custom_gini = (
... cumulative_per_capita_convergence_adjusted_gini(
... population_ts=data["population"],
... country_actual_emissions_ts=data["emissions"],
... world_scenario_emissions_ts=data["world_emissions"],
... gdp_ts=data["gdp"],
... gini_s=data["gini"],
... first_allocation_year=2020,
... emission_category="co2-ffi",
... pre_allocation_responsibility_weight=0.3,
... capability_weight=0.3,
... income_floor=5000.0, # Lower income floor
... max_gini_adjustment=0.9, # Allow stronger inequality adjustment
... max_convergence_speed=0.5, # Slower convergence
... strict=False, # Accept approximate targets if exact infeasible
... )
... )
Converting units...
>>> # With income floor, high inequality means more income above threshold
>>> result_custom_gini.approach
'cumulative-per-capita-convergence-gini-adjusted'
See Also¶
- Budget Allocations: Fixed cumulative budgets
- Scientific Documentation: Allocation Approaches: Theoretical foundations
- country-fair-shares Guide: Conceptual overview