1# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2#
3# This source code is licensed under the MIT license found in the
4# LICENSE file in the root directory of this source tree.
5
6import typing as tp
7import numpy as np
8from nevergrad.common import testing
9from . import corefuncs
10
11
12@testing.parametrized(**{name: (name, func) for name, func in corefuncs.registry.items()})
13def testcorefuncs_function(name: str, func: tp.Callable[..., tp.Any]) -> None:
14    x = np.random.normal(0, 1, 100)
15    outputs = []
16    for _ in range(2):
17        np.random.seed(12)
18        outputs.append(func(x))
19    np.testing.assert_equal(outputs[0], outputs[1], f"Function {name} is not deterministic")
20
21
22@testing.parametrized(
23    expe1=([6, 4, 2, 1, 9], 4, 5, 3),
24    expe2=([6, 6, 7, 1, 9], 4, 5, 3),
25    expe3=([1, 1, 7, 1, 9], 3, 5, 2),
26    expe4=([0, 0, 7, 1, 9], 3, 4, 2),
27    expe5=([0, 1, 1, 1], 1, 2, 0),
28    expe6=([1, 1, 1, 1], 2, 4, 1),
29    expe7=([1, 0, 0, 0], 3, 4, 2),
30    expe_0lead=([0, 1, 0, 1], 0, 0, -1),
31)  # jump was assumed correct (verify?)
32def test_base_functions(
33    x: tp.List[float], onemax_expected: float, leadingones_expected: float, jump_expected: float
34) -> None:
35    for name, expected in [
36        ("onemax", onemax_expected),
37        ("leadingones", leadingones_expected),
38        ("jump", jump_expected),
39    ]:
40        func = corefuncs.DiscreteFunction(name)
41        np.testing.assert_equal(func(x), expected, err_msg=f"Wrong output for {name}")
42
43
44def test_genzcornerpeak_inf() -> None:
45    y = np.array([-np.inf, -np.inf])
46    output = corefuncs.genzcornerpeak(y)
47    np.testing.assert_equal(output, np.inf)
48    output = corefuncs.minusgenzcornerpeak(y)
49    np.testing.assert_equal(output, -np.inf)
50
51
52@testing.parametrized(
53    cigar=(corefuncs.cigar, 8604785.43824, None),
54    hm=(corefuncs.hm, 15.85037, None),
55    griewank=(corefuncs.griewank, 0.70028, None),
56    sphere=(corefuncs.sphere, 9.043029, None),
57    sphere1=(corefuncs.sphere1, 10.329029, None),
58    sphere2=(corefuncs.sphere2, 35.615029, None),
59    sphere4=(corefuncs.sphere4, 158.187029, None),
60    sphere_m=(corefuncs.sphere, 30, [1, 2, 3, 4]),
61    elliptic=(corefuncs.ellipsoid, 262389.541996, None),
62    altelliptic=(corefuncs.altellipsoid, 609313.71475, None),
63    rosenbrock=(corefuncs.rosenbrock, 1967.57859, None),
64    rosenbrock_m=(corefuncs.rosenbrock, 2705, [1, 2, 3, 4]),
65    ackley=(corefuncs.ackley, 4.7298473, None),
66    schwefel=(corefuncs.schwefel_1_2, 128.709765, None),
67    ackley_m=(corefuncs.ackley, 2.254444, [0.1, 0.2, 0.3]),
68    schwefel_m=(corefuncs.schwefel_1_2, 146, [1, 2, 3, 4]),
69    genzgaussianpeakintegral=(corefuncs.genzgaussianpeakintegral, 0.10427, None),
70    minusgenzgaussianpeakintegral=(corefuncs.minusgenzgaussianpeakintegral, -0.10427, None),
71    linear=(corefuncs.linear, 0.57969, None),
72)
73def test_core_function_values(
74    func: tp.Callable[[np.ndarray], float], expected: float, data: tp.Optional[tp.List[float]]
75) -> None:
76    if data is None:
77        data = [0.662, -0.217, -0.968, 1.867, 0.101, 0.575, 0.199, 1.576, 1.006, 0.182, -0.092, 0.466]
78    value = func(np.array(data))
79    np.testing.assert_almost_equal(value, expected, decimal=5)
80
81
82def test_styblinksitang() -> None:
83    np.random.seed(12)
84    data = [0.662, -0.217, -0.968, 1.867, 0.101, 0.575, 0.199, 1.576, 1.006, 0.182, -0.092, 0.466]
85    value = corefuncs._styblinksitang(np.array(data), noise=0.1)
86    np.testing.assert_almost_equal(value, 421.374940, decimal=5)
87