Research code for nitrogen resource allocation experiments with CropGym crop simulations, WOFOST/PCSE model dynamics, LP baselines, and neural adaptive Gaussian-process bandit allocators.
The Python package is named cropgym.
.
├── cropgym/ # Importable Python package
│ ├── envs/ # Crop simulation and allocation environments
│ ├── agents/ # Bandit models and neural-network utilities
│ ├── utils/ # Rewards, plotting, callbacks, scenario helpers, evaluation tools
│ ├── utils_soil/ # SoilGrids extraction and soil-file generation utilities
│ ├── configs/ # Crop, soil, site, weather, scenario, price, and PCSE config assets
│ ├── train_allocator.py # Bandit allocator training loops
│ ├── run_scenarios.py # Regional and farm-level simulation/evaluation runner
│ ├── fit_lp.py # LP and SPSA baseline precomputation
│ └── fit_nue_response.py # NUE/N-surplus response fitting
├── scripts/ # Command-line entry points for reproduction workflows
├── tests/ # Unit and environment smoke tests
├── notebooks/ # Result exploration and plotting notebooks
└── pyproject.toml # Package metadata and uv dependency specification
This project was developed with Python 3.11.9 and is configured for Python >=3.11,<3.13.
The pyproject.toml expects a compatible editable PCSE checkout at ../pcse:
parent-directory/
├── pcse/
└── CropGym-BanditResourceAllocation/
Install with uv:
cd CropGym-BanditResourceAllocation
uv python install 3.11
uv syncIf you want to use Comet logging, create a local comet/api file containing your API key. Without that file, the code falls back to local logging.
Run the focused unit tests:
uv run pytest testsCheck that the package imports and registers the predefined single-field environments:
uv run python -c "import cropgym; print(cropgym._CONFIG_PATH)"The core reproduction workflow is:
- Prepare or verify scenario and soil configuration files.
- Run crop simulations for regional farms and years.
- Fit response models and LP/SPSA allocation baselines.
- Train and evaluate bandit resource allocators.
- Inspect results with the notebook in
notebooks/.
Scenario YAML files are stored under cropgym/configs/scenarios/. Soil assets are stored under cropgym/configs/soil/, and the repository already includes the scenario and SoilGrids files used by the current experiments.
For new coordinate-based scenarios, generate one SoilGrids soil file with:
uv run python scripts/generate_soilgrids_soil_file.py --longitude 6.656 --latitude 52.966The helper below can generate missing soil files from scenario YAMLs when those YAMLs are organized as <region>/<year>/farmer_*.yaml:
uv run python scripts/pull_scenarios_soils.py --year 2020Run the rule-of-thumb baseline across the default test years, with optional aggregation:
uv run python -m cropgym.run_scenarios \
--regions all \
--years 0 \
--baseline ROT \
--scenario full_budget \
--num_workers 1 \
--aggregateRun only one global farm:
uv run python -m cropgym.run_scenarios \
--farm 0 \
--baseline ROT \
--scenario full_budget \
--aggregateFit offline LP responses from an evaluation pickle:
uv run python -m cropgym.fit_lp \
--mode offline_fit \
--file_path results/ROT/<evaluation-file>.pkluv run python -m cropgym.fit_nue_response \
--file_path results/ROT/<evaluation-file>.pkl \
--train_years 2015,2016,2017,2018,2019 \
--tag ROTTrain the default resource allocation bandit:
uv run python scripts/training_resource_allocation.py \
--baseline ROT \
--rounds 300 \
--years 2 \
--eval_steps 10 \
--method ucb \
--bandit_action_mode factored \
--no_cometTrain for a single farm:
uv run python scripts/training_resource_allocation.py \
--farm 0 \
--baseline ROT \
--rounds 300 \
--method ucb \
--no_cometGenerated artifacts are written to local experiment folders:
models/: trained allocator checkpointsresults/: scenario outputs, LP outputs, fitted responses, and evaluation pickleslogs/: local training logsplots/: generated diagnostic figuresresume/: resumed training state
These folders are intentionally not required for importing cropgym; they are produced by reproduction runs.