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 os 7from unittest import SkipTest 8import warnings 9import typing as tp 10import pytest 11import numpy as np 12from nevergrad.common import testing 13from . import core 14from . import photonics 15 16 17@testing.parametrized( 18 bragg=("bragg", [2.93, 2.18, 2.35, 2.12, 45.77, 37.99, 143.34, 126.55]), 19 morpho=("morpho", [280.36, 52.96, 208.16, 72.69, 89.92, 60.37, 226.69, 193.11]), 20 chirped=("chirped", [170.18, 56.48, 82.04, 48.17, 45.77, 37.99, 143.34, 126.55]), 21) 22def test_photonics_bounding_methods(pb: str, expected: tp.List[float]) -> None: 23 func = core.Photonics(pb, 8, bounding_method="tanh") 24 np.random.seed(24) 25 x = np.random.normal(0, 1, size=8) 26 output = func.parametrization.spawn_child().set_standardized_data(x).value.ravel() 27 np.testing.assert_almost_equal(output, expected, decimal=2) 28 29 30@testing.parametrized( 31 # bragg domain (n=60): [2,3]^30 x [30,180]^30 32 bragg=("bragg", [2.5, 2.5, 2.5, 2.5, 105.0, 105.0, 105.0, 105.0]), 33 # chirped domain (n=60): [30,170]^60 34 chirped=("chirped", [105.0, 105.0, 105.0, 105.0, 105.0, 105.0, 105.0, 105.0]), 35 # morpho domain (n=60): [0,300]^15 x [0,600]^15 x [30,600]^15 x [0,300]^15 36 morpho=("morpho", [150.0, 150.0, 300.0, 300.0, 315.0, 315.0, 150.0, 150.0]), 37) 38def test_photonics_mean(pb: str, expected: tp.List[float]) -> None: 39 func = core.Photonics(pb, 8) 40 all_x = func.parametrization.value 41 output = all_x.ravel() 42 np.testing.assert_almost_equal(output, expected, decimal=2) 43 44 45def test_morpho_bounding_method_constraints() -> None: 46 func = core.Photonics("morpho", 60, bounding_method="arctan") 47 x = np.random.normal(0, 5, size=60) # std 5 to play with boundaries 48 output1 = func.parametrization.spawn_child().set_standardized_data(x) 49 output2 = output1.sample() 50 for output in (output1, output2): 51 assert np.all(output.value >= 0) 52 assert np.all(output.value[[0, 3], :] <= 300) 53 assert np.all(output.value[[1, 2], :] <= 600) 54 assert np.all(output.value[2, :] >= 30) 55 56 57def test_photonics_bragg_recombination() -> None: 58 func = core.Photonics("bragg", 8) 59 # func.parametrization.set_recombination(ng.p.mutation.RavelCrossover()) # type: ignore 60 func.parametrization.random_state.seed(24) 61 arrays = [func.parametrization.spawn_child() for _ in range(2)] 62 arrays[0].value = [[2, 2, 2, 2], [35, 35, 35, 35]] 63 arrays[1].value = [[3, 3, 3, 3], [45, 45, 45, 45]] 64 arrays[0].recombine(arrays[1]) 65 expected = [[3, 2, 2, 2], [45, 35, 35, 35]] 66 np.testing.assert_array_equal(arrays[0].value, expected) 67 68 69def test_photonics_custom_mutation() -> None: 70 func = core.Photonics("morpho", 16, rolling=True) 71 param = func.parametrization.spawn_child() 72 for _ in range(10): 73 param.mutate() 74 # as tuple 75 func = core.Photonics("morpho", 16, rolling=True, as_tuple=True) 76 func.evaluation_function(func.parametrization) 77 78 79def test_photonics_error() -> None: 80 # check error 81 photo = core.Photonics("bragg", 16) 82 np.testing.assert_raises(AssertionError, photo, np.zeros(12)) 83 with warnings.catch_warnings(record=True) as ws: 84 output = photo(np.zeros(16)) 85 # one warning on Ubuntu, two warnings with Windows 86 assert any(isinstance(w.message, RuntimeWarning) for w in ws) 87 np.testing.assert_almost_equal(output, float("inf")) 88 89 90@pytest.mark.parametrize("method", ["clipping", "arctan", "tanh", "constraint"]) # type: ignore 91@pytest.mark.parametrize("name", ["bragg", "morpho", "chirped"]) # type: ignore 92def test_no_warning(name: str, method: str) -> None: 93 with warnings.catch_warnings(record=True) as w: 94 core.Photonics(name, 24, bounding_method=method) 95 assert not w, f"Got a warning at initialization: {w[0]}" 96 97 98@testing.parametrized( 99 # morpho=("morpho", 100, 1.1647), # too slow 100 chirped=("chirped", 150, 0.94439), 101 bragg=("bragg", 2.5, 0.93216), 102) 103def test_photonics_values(name: str, value: float, expected: float) -> None: 104 if name == "morpho" and os.environ.get("CIRCLECI", False): 105 raise SkipTest("Too slow in CircleCI") 106 photo = core.Photonics(name, 16) 107 np.testing.assert_almost_equal(photo(value * np.ones(16)), expected, decimal=4) 108 109 110GOOD_CHIRPED = [ 111 89.04887416, 112 109.54188095, 113 89.74520725, 114 121.81700431, 115 179.99830918, 116 124.38222473, 117 95.31017129, 118 116.0239629, 119 92.92345776, 120 118.06108198, 121 179.99965859, 122 116.89288181, 123 88.90191494, 124 110.30816229, 125 93.11974992, 126 137.42629858, 127 118.81810084, 128 110.74139708, 129 85.15270955, 130 100.9382438, 131 81.44070951, 132 100.6382896, 133 84.97336252, 134 110.59252719, 135 134.89164276, 136 121.84205195, 137 89.28450356, 138 106.72776991, 139 85.77168797, 140 102.33562547, 141] 142 143 144EPS_AND_D = [ # photosic realistic 145 2.0000, 146 3.0000, 147 2.1076, 148 2.0000, 149 3.0000, 150 2.5783, 151 2.0000, 152 3.0000, 153 2.0000, 154 3.0000, 155 90.0231, 156 78.9789, 157 72.8369, 158 99.9577, 159 82.7487, 160 62.7583, 161 104.1682, 162 139.9002, 163 93.3356, 164 75.6039, 165] 166 167 168@testing.parametrized( 169 morpho=("morpho", 1.127904, None), 170 chirped=("chirped", 0.594587, None), 171 good_chirped=("chirped", 0.275923, np.array([GOOD_CHIRPED])), # supposed to be better 172 bragg=("bragg", 0.96776, None), 173 photosic_realistic=("cf_photosic_realistic", 0.0860257, np.array(EPS_AND_D).reshape((2, -1))), 174 photosic_reference=("cf_photosic_reference", 0.431072, None), 175) 176def test_photonics_values_random(name: str, expected: float, data: tp.Optional[np.ndarray]) -> None: 177 if name == "morpho" and os.environ.get("CIRCLECI", False): 178 raise SkipTest("Too slow in CircleCI") 179 size = data.size if data is not None else (16 if name != "morpho" else 4) 180 photo = core.Photonics(name, size) 181 if data is None: 182 x = np.random.RandomState(12).normal(0, 1, size=size) 183 candidate = photo.parametrization.spawn_child().set_standardized_data(x) 184 else: 185 candidate = photo.parametrization.spawn_child(new_value=data) 186 np.testing.assert_almost_equal(photo(candidate.value), expected, decimal=4) 187 np.testing.assert_almost_equal(photo.evaluation_function(candidate), expected, decimal=4) 188 189 190def test_photosic_reference() -> None: 191 debut = np.array([79, 102]) 192 fin = np.array([100, 70]) 193 dbr = np.tile(np.array([147, 120]), 3) 194 X = np.concatenate([debut, dbr, fin]) 195 cf_test = photonics.cf_photosic_reference(X) 196 np.testing.assert_almost_equal(cf_test, 0.09069397) 197 198 199def test_photosic_realist() -> None: 200 cf_test = photonics.cf_photosic_realistic(np.array(EPS_AND_D)) 201 np.testing.assert_almost_equal(cf_test, 0.08602574254532869) 202