Skip to content

Commit 23cae6c

Browse files
committed
Actually add the intregration test
1 parent 0d6e80b commit 23cae6c

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
"""Integration tests for calibration utility module"""
2+
3+
import unittest
4+
from functools import partial
5+
6+
import pandas as pd
7+
import numpy as np
8+
from scipy.optimize import NonlinearConstraint
9+
10+
from climada.entity import ImpactFuncSet, ImpactFunc
11+
12+
from climada.util.calibrate.impact_func import (
13+
Input,
14+
ScipyMinimizeOptimizer,
15+
cost_func_rmse,
16+
)
17+
from climada.util.calibrate.test.test_calibrate import hazard, exposure
18+
19+
20+
class TestScipyMinimizeOptimizer(unittest.TestCase):
21+
"""Test the TestScipyMinimizeOptimizer"""
22+
23+
def setUp(self) -> None:
24+
"""Prepare input for optimization"""
25+
self.hazard = hazard()
26+
self.hazard.frequency = np.ones_like(self.hazard.event_id)
27+
self.hazard.date = self.hazard.frequency
28+
self.hazard.event_name = ["event"] * len(self.hazard.event_id)
29+
self.exposure = exposure()
30+
self.events = [10, 1]
31+
self.data = pd.DataFrame(
32+
data={"a": [3, 1], "b": [0.2, 0.01]}, index=self.events
33+
)
34+
self.cost_func = partial(
35+
cost_func_rmse, impact_proc=lambda impact: impact.impact_at_reg(["a", "b"])
36+
)
37+
self.impact_func_gen = lambda slope: ImpactFuncSet(
38+
[
39+
ImpactFunc(
40+
intensity=np.array([0, 10]),
41+
mdd=np.array([0, 10 * slope]),
42+
paa=np.ones(2),
43+
id=1,
44+
)
45+
]
46+
)
47+
self.input = Input(
48+
self.hazard, self.exposure, self.data, self.cost_func, self.impact_func_gen
49+
)
50+
51+
def test_single(self):
52+
"""Test with single parameter"""
53+
optimizer = ScipyMinimizeOptimizer(self.input)
54+
output = optimizer.run(params_init={"slope": 0.1})
55+
56+
# Result should be nearly exact
57+
self.assertTrue(output.success)
58+
self.assertAlmostEqual(output.params["slope"], 1.0)
59+
self.assertAlmostEqual(output.target, 0.0)
60+
61+
def test_bound(self):
62+
"""Test with single bound"""
63+
self.input.bounds = {"slope": (-1.0, 0.91)}
64+
optimizer = ScipyMinimizeOptimizer(self.input)
65+
output = optimizer.run(params_init={"slope": 0.1})
66+
67+
# Result should be very close to the bound
68+
self.assertTrue(output.success)
69+
self.assertGreater(output.params["slope"], 0.89)
70+
self.assertAlmostEqual(output.params["slope"], 0.91, places=2)
71+
72+
def test_multiple_constrained(self):
73+
"""Test with multiple constrained parameters"""
74+
# Set new generator
75+
self.input.impact_func_gen = lambda intensity_1, intensity_2: ImpactFuncSet(
76+
[
77+
ImpactFunc(
78+
intensity=np.array([0, intensity_1, intensity_2]),
79+
mdd=np.array([0, 1, 3]),
80+
paa=np.ones(3),
81+
id=1,
82+
)
83+
]
84+
)
85+
86+
# Constraint: param[0] < param[1] (intensity_1 < intensity_2)
87+
self.input.constraints = NonlinearConstraint(
88+
lambda params: params[0] - params[1], -np.inf, 0.0
89+
)
90+
self.input.bounds = {"intensity_1": (0, 3.1), "intensity_2": (0, 3.1)}
91+
92+
# Run optimizer
93+
optimizer = ScipyMinimizeOptimizer(self.input)
94+
output = optimizer.run(
95+
params_init={"intensity_1": 2, "intensity_2": 2},
96+
)
97+
98+
# Check results (low accuracy)
99+
self.assertTrue(output.success)
100+
self.assertAlmostEqual(output.params["intensity_1"], 1.0, places=3)
101+
self.assertAlmostEqual(output.params["intensity_2"], 3.0, places=3)
102+
self.assertAlmostEqual(output.target, 0.0, places=3)

0 commit comments

Comments
 (0)