Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ introduce breaking changes to configuration and outputs.
(`market_response.elasticities.demand`, central values from the Green et
al. 2013 meta-regression). Ordinary solves previously had no
demand-side valuation at all unless a config enabled the consumer-values /
piecewise-utility mechanism; the demand component replaces that pattern (the
two are mutually exclusive, and `food_utility_piecewise` remains available
for configs that keep it, with `market_response.components.demand: false`).
piecewise-utility mechanism; the demand component replaces that mechanism
(removed below).
The demand curves' cost appears as its own `demand_response` category in the
objective breakdown. Demand groups whose marginal utility is still positive
at the outer end of the sampled range have their unbounded expansion tail
Expand Down Expand Up @@ -345,6 +344,19 @@ introduce breaking changes to configuration and outputs.

### Removed

- The legacy demand-side mechanisms superseded by the `market_response` demand
component: the consumer-values workflow (baseline dual extraction and its
`results/{name}/consumer_values/` outputs), `food_utility_piecewise`
(piecewise utility blocks calibrated from consumer values),
`food_incentives` (flat per-food objective adjustments), and the
`optimal_taxes` workflow. Configs using these keys must migrate to
`market_response.components.demand` (with a calibrated artefact set for
their structure) or, for fixed-diet runs, `validation.enforce_baseline_diet`.
The GSA and documentation-figure configs now use the demand component, and
GSA runs no longer need a locally solved `baseline` scenario. The cost
calibration's tight-band solve now keeps the diet pinned to baseline instead
of using utility blocks, and the legacy `stability` calibration runs under
the base config's own demand regime.
- The MARS surrogate method; supported surrogates are now `pce`, `rf`, `xgb`
and `mlp`.
- Unused configuration keys `health.ssb_sugar_g_per_100g`,
Expand Down
29 changes: 10 additions & 19 deletions config/calibration/cost.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# -------------------------------
# Generates production cost calibration corrections for crops, grassland,
# and animals by:
# 1. Solving a baseline scenario (enforce_baseline_diet, no stability)
# → extracts consumer values for piecewise food utility
# 2. Solving a calibration scenario (piecewise utility + hard production
# stability at ±1%) → extracts duals as cost corrections
# 1. Solving a baseline scenario (enforce_baseline_diet, hard production
# stability at +/-5%) to absorb residual supply/demand mismatch
# 2. Solving a calibration scenario (enforce_baseline_diet, hard production
# stability at +/-1%) → extracts duals as cost corrections
#
# Usage:
# tools/calibrate cost
Expand All @@ -25,7 +25,7 @@
name: "calibration"

scenarios:
# Step 1: Baseline solve to extract consumer values / utility blocks.
# Step 1: Baseline solve.
#
# Production stability is enabled with a +/-5 % band so that the food
# p_set duals reflect the marginal cost of supply under realistic
Expand Down Expand Up @@ -59,11 +59,13 @@ scenarios:
enable_slack: true
diet:
enabled: false
food_utility_piecewise:
enabled: false

# Step 2: Calibration solve with tight production stability
# Step 2: Calibration solve with tight production stability. The diet stays
# pinned to baseline (matching step 1), so the tight-band duals measure the
# marginal cost of holding observed production under the observed diet.
cost_calibration:
validation:
enforce_baseline_diet: true
deviation_penalty:
enabled: true
penalty_mode: "hard"
Expand All @@ -85,12 +87,6 @@ scenarios:
enable_slack: true
diet:
enabled: false
food_utility_piecewise:
enabled: true

# Enable piecewise utility at base level (blocks get built from baseline)
food_utility_piecewise:
enabled: true

# Later-step calibration (lower-triangle rule): the market-response curves
# and their intercept artefact must not influence the cost duals.
Expand All @@ -102,11 +98,6 @@ cost_calibration:
generate: true # Generate calibration from solved model
scenario: "cost_calibration"

# Override the default consumer_values.baseline_scenario ("baseline") to
# point at the renamed scenario above.
consumer_values:
baseline_scenario: "cost_baseline"

validation:
use_actual_yields: true
# Cap slack-driven duals at the upper end of realistic food wholesale
Expand Down
5 changes: 0 additions & 5 deletions config/calibration/feed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ validation:
disable_spared_grassland: true
slack_marginal_cost: 10

# The enforced-baseline validation solve is incompatible with piecewise
# food utility; disable it regardless of the base config's setting.
food_utility_piecewise:
enabled: false

cost_calibration:
enabled: false

Expand Down
5 changes: 0 additions & 5 deletions config/calibration/food_demand.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ validation:
disable_spared_grassland: true
slack_marginal_cost: 10

# The enforced-baseline validation solve is incompatible with piecewise
# food utility; disable it regardless of the base config's setting.
food_utility_piecewise:
enabled: false

# Skip downstream calibrations so this step is order-independent.
cost_calibration:
enabled: false
Expand Down
5 changes: 0 additions & 5 deletions config/calibration/food_waste.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ validation:
disable_spared_grassland: true
slack_marginal_cost: 10

# The enforced-baseline validation solve is incompatible with piecewise
# food utility; disable it regardless of the base config's setting.
food_utility_piecewise:
enabled: false

# Skip downstream calibrations so this step is order-independent.
cost_calibration:
enabled: false
Expand Down
3 changes: 0 additions & 3 deletions config/calibration/market_response.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ health:
deviation_penalty:
enabled: false

food_utility_piecewise:
enabled: false

market_response:
enabled: true
pin_baseline: true
Expand Down
18 changes: 4 additions & 14 deletions config/calibration/stability.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# Drives the land and animal-feed deviation simultaneously to
# `target_deviation_pct` (default 5% of observed 2020 totals) by running
# Broyden's quasi-Newton iteration in log-log coordinates. Each iteration is
# one paired solve (baseline with `enforce_baseline_diet=true` to derive
# consumer values, then main with piecewise utility active).
# one paired solve (baseline with `enforce_baseline_diet=true`, then main
# under the base config's own demand regime).
#
# Warm-starts from an existing calibrated YAML when one exists on disk;
# otherwise uses the seed values in `deviation_penalty.calibration.seeds`.
Expand All @@ -25,24 +25,14 @@
name: "calibration"

# Pin the calibration regime explicitly: the main solve inherits these
# values (the baseline solve is always forced to 0/0 in the script so that
# consumer values reflect raw revealed preferences).
# values (the baseline solve is always forced to 0/0 in the script,
# independent of any policy regime under investigation).
emissions:
ghg_pricing_enabled: false
health:
enabled: false
value_per_yll: 0

# Block-based diminishing marginal utility for food consumption (used by main
# solves; baseline solves disable this inside the calibration script).
food_utility_piecewise:
enabled: true

# Fallback consumer_values baseline; the script overrides this per iteration
# to point at that iteration's baseline scenario.
consumer_values:
baseline_scenario: "_cal_baseline_iter00"

validation:
use_actual_yields: true

Expand Down
24 changes: 1 addition & 23 deletions config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -312,36 +312,14 @@ market_response:
# consumption groups are fixed to zero, like their supply counterparts. It
# is fitted sequentially against the calibrated production curves, because a
# joint pin cannot identify how a commodity-chain wedge is split between
# supply and demand. It replaces
# food_utility_piecewise and food_incentives (mutually exclusive with both).
# supply and demand.
components:
crops: true
multi_crops: true
grassland: true
animals: true
demand: true

# --- section: food_incentives ---
food_incentives:
enabled: false # When true, food-level incentives are applied to the objective
sources: []

# --- section: consumer_values ---
consumer_values:
baseline_scenario: "baseline" # Scenario name for consumer values extraction (must have enforce_baseline_diet=true)

# --- section: food_utility_piecewise ---
food_utility_piecewise:
enabled: false # When true, use piecewise diminishing marginal utility for food consumption
n_blocks: 4
decline_factor: 0.7 # Multiplicative utility decay by block (0 < factor <= 1)
total_width_multiplier: 2.0 # Total incentivized quantity as multiple of baseline consumption
min_block_width_mt: 0.00001 # Minimum width floor (Mt/year) for each utility block to avoid tiny upper bounds

# --- section: optimal_taxes ---
optimal_taxes:
enabled: false # When true, enables the optimal taxes/subsidies workflow

# --- section: land ---
land:
regional_limit: 1.0 # fraction of each region's potential cropland that is made available.
Expand Down
73 changes: 0 additions & 73 deletions config/schemas/config.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ required:
- netcdf
- numerics
- validation
- consumer_values
- food_incentives
- food_utility_piecewise
- optimal_taxes
- land
- water
- water_scarcity
Expand Down Expand Up @@ -301,64 +297,6 @@ properties:
minimum: 0
description: "Maximum relative increase from baseline area (e.g., 0.5 = +50%)"

food_incentives:
type: object
required: [enabled, sources]
additionalProperties: false
properties:
enabled:
type: boolean
description: "When true, food-level incentives are applied to the objective"
sources:
type: array
items:
type: string
description: "Paths to food incentives CSVs (may include {name} placeholder)"

consumer_values:
type: object
required: [baseline_scenario]
additionalProperties: false
properties:
baseline_scenario:
type: string
description: "Scenario name used for consumer values extraction (must have enforce_baseline_diet=true)"

food_utility_piecewise:
type: object
required: [enabled, n_blocks, decline_factor, total_width_multiplier, min_block_width_mt]
additionalProperties: false
properties:
enabled:
type: boolean
description: "When true, apply piecewise diminishing marginal utility for food consumption"
n_blocks:
type: integer
minimum: 1
description: "Number of utility blocks per (food, country)"
decline_factor:
type: number
exclusiveMinimum: 0
maximum: 1
description: "Multiplicative marginal-utility decay by block index"
total_width_multiplier:
type: number
exclusiveMinimum: 0
description: "Total incentivized quantity as multiple of baseline consumption"
min_block_width_mt:
type: number
minimum: 0
description: "Minimum per-block width floor (Mt/year) applied at solve time for numerical robustness"

optimal_taxes:
type: object
required: [enabled]
additionalProperties: false
properties:
enabled:
type: boolean
description: "When true, enables the optimal taxes/subsidies workflow"

land:
type: object
required: [regional_limit, reforestation_cap, land_use_cost_usd_per_ha, conversion_cost_forest_usd_per_ha, conversion_cost_nonforest_usd_per_ha, investment_horizon, discount_rate]
Expand Down Expand Up @@ -2568,17 +2506,6 @@ properties:
rr_low (q=0) and rr_high (q=1) for each dose-response curve.

allOf:
- not:
required: [food_incentives, food_utility_piecewise]
properties:
food_incentives:
properties:
enabled:
const: true
food_utility_piecewise:
properties:
enabled:
const: true
- not:
required: [cost_calibration, market_response]
properties:
Expand Down
Loading