diff --git a/mypy.ini b/mypy.ini index f85d85261..01d002dc2 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,7 +3,7 @@ [mypy-scipy.*,requests,pandas,compiler_gym,compiler_gym.*,gym,gym.*,gym_anm,matplotlib.*,pytest,cma,bayes_opt.*,torchvision.models,torch.*,mpl_toolkits.*,fcmaes.*,tqdm,pillow,PIL,PIL.Image,sklearn.*,pyomo.*,pyproj,IOHexperimenter.*,tensorflow,koncept.models,cv2,imquality,imquality.brisque,lpips,mixsimulator.*,networkx.*,cdt.*,pymoo,pymoo.*,bayes_optim.*,olympus.*] ignore_missing_imports = True -[mypy-nevergrad.functions.rl.agents,torchvision,torchvision.*,nevergrad.functions.games.*,nevergrad.functions.multiobjective.pyhv,nevergrad.optimization.test_doc,,pymoo,pymoo.*,pybullet,pybullet_envs,pybulletgym,pyvirtualdisplay] +[mypy-nevergrad.functions.rl.agents,torchvision,torchvision.*,nevergrad.functions.games.*,nevergrad.functions.multiobjective.pyhv,nevergrad.optimization.test_doc,,pymoo,pymoo.*,pybullet,pybullet_envs,pybulletgym,pyvirtualdisplay,aquacrop.*] ignore_missing_imports = True ignore_errors = True diff --git a/nevergrad/benchmark/experiments.py b/nevergrad/benchmark/experiments.py index 55f5817d7..25f8d9b48 100644 --- a/nevergrad/benchmark/experiments.py +++ b/nevergrad/benchmark/experiments.py @@ -21,6 +21,7 @@ from nevergrad.functions.arcoating import ARCoating from nevergrad.functions import images as imagesxp from nevergrad.functions.powersystems import PowerSystem +from nevergrad.functions.ac import NgAquacrop from nevergrad.functions.stsp import STSP from nevergrad.functions.rocket import Rocket from nevergrad.functions.mixsimulator import OptimizeMix @@ -1157,6 +1158,23 @@ def realworld(seed: tp.Optional[int] = None) -> tp.Iterator[Experiment]: yield xp +@registry.register +def aquacrop_fao(seed: tp.Optional[int] = None) -> tp.Iterator[Experiment]: + """FAO Crop simulator. Maximize yield.""" + + funcs = [NgAquacrop(i, 300.0 + 150.0 * np.cos(i)) for i in range(3, 7)] + seedg = create_seed_generator(seed) + optims = get_optimizers("basics", seed=next(seedg)) + for budget in [25, 50, 100, 200, 400, 800, 1600]: + for num_workers in [1, 30]: + if num_workers < budget: + for algo in optims: + for fu in funcs: + xp = Experiment(fu, algo, budget, num_workers=num_workers, seed=next(seedg)) + if not xp.is_incoherent: + yield xp + + @registry.register def rocket(seed: tp.Optional[int] = None, seq: bool = False) -> tp.Iterator[Experiment]: """Rocket simulator. Maximize max altitude by choosing the thrust schedule, given a total thrust. diff --git a/nevergrad/functions/ac/__init__.py b/nevergrad/functions/ac/__init__.py new file mode 100644 index 000000000..a62f6f1d9 --- /dev/null +++ b/nevergrad/functions/ac/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .ac import NgAquacrop as NgAquacrop diff --git a/nevergrad/functions/ac/ac.py b/nevergrad/functions/ac/ac.py new file mode 100644 index 000000000..cc7e557a9 --- /dev/null +++ b/nevergrad/functions/ac/ac.py @@ -0,0 +1,74 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Optimization of the FAO crop management model. +Based on +https://colab.research.google.com/github/thomasdkelly/aquacrop/blob/master/tutorials/AquaCrop_OSPy_Notebook_3.ipynb#scrollTo=YDm931IGNxCb +""" + +from nevergrad.parametrization import parameter +from ..base import ExperimentFunction +from ..base import UnsupportedExperiment as UnsupportedExperiment + +# pylint: disable=too-many-locals,too-many-statements + +# Inspired by +# https://colab.research.google.com/github/thomasdkelly/aquacrop/blob/master/tutorials/AquaCrop_OSPy_Notebook_3.ipynb#scrollTo=YDm931IGNxCb + +# In the colab it was: +# from aquacrop.classes import * +# from aquacrop.core import * + + +class NgAquacrop(ExperimentFunction): + def __init__(self, num_smts: int, max_irr_seasonal: float) -> None: + self.num_smts = num_smts + self.max_irr_seasonal = max_irr_seasonal + super().__init__(self.loss, parametrization=parameter.Array(shape=(num_smts,))) + + def loss(self, smts): + try: + import aquacrop + except ImportError: + raise UnsupportedExperiment("Please install aquacrop==0.2 for FAO aquacrop experiments") + path = aquacrop.core.get_filepath("champion_climate.txt") + wdf = aquacrop.core.prepare_weather(path) + + def run_model(smts, max_irr_season, year1, year2): + """ + Function to run model and return results for given set of soil moisture targets. + """ + + maize = aquacrop.classes.CropClass("Maize", PlantingDate="05/01") # define crop + loam = aquacrop.classes.SoilClass("ClayLoam") # define soil + init_wc = aquacrop.classes.InitWCClass( + wc_type="Pct", value=[70] + ) # define initial soil water conditions + + irrmngt = aquacrop.classes.IrrMngtClass( + IrrMethod=1, SMT=smts, MaxIrrSeason=max_irr_season + ) # define irrigation management + + # create and run model + model = aquacrop.core.AquaCropModel( + f"{year1}/05/01", f"{year2}/10/31", wdf, loam, maize, IrrMngt=irrmngt, InitWC=init_wc + ) + model.initialize() + model.step(till_termination=True) + return model.Outputs.Final + + def evaluate(smts) -> float: # ,max_irr_season,test=False): + """ + Function to run model and calculate reward (yield) for given set of soil moisture targets + """ + max_irr_season = self.max_irr_seasonal + assert len(smts) == self.num_smts + out = run_model(smts, max_irr_season, year1=2016, year2=2018) + # get yields. + reward = out["Yield (tonne/ha)"].mean() + return -reward + + return evaluate(smts) diff --git a/nevergrad/functions/ac/test_ac.py b/nevergrad/functions/ac/test_ac.py new file mode 100644 index 000000000..f86186921 --- /dev/null +++ b/nevergrad/functions/ac/test_ac.py @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +from . import ac + + +def test_ac() -> None: + func = ac.NgAquacrop(4, 12.0) + x = 50.0 * np.random.rand(func.dimension) + value = func(x) + value2 = func(x) + x = 50.0 * np.random.rand(func.dimension) + value3 = func(x) + np.testing.assert_almost_equal(value, value2) + assert value != value3