From f956d45f829e4c3fe366cc8b5e012dcc3944f91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lafage?= Date: Tue, 28 Nov 2023 15:53:20 +0100 Subject: [PATCH] Fix doc build: remove test assertion from run method (#484) * Remove test assertion from run method * Fix import * Skip hierarchy tests when CS not installed * Avoid test code duplication --- smt/applications/tests/test_mixed_integer.py | 486 ++++--------------- smt/utils/test/test_design_space.py | 8 +- 2 files changed, 105 insertions(+), 389 deletions(-) diff --git a/smt/applications/tests/test_mixed_integer.py b/smt/applications/tests/test_mixed_integer.py index 5cc42d063..c43a13dd8 100644 --- a/smt/applications/tests/test_mixed_integer.py +++ b/smt/applications/tests/test_mixed_integer.py @@ -6,6 +6,7 @@ import unittest import numpy as np import itertools +import os try: import matplotlib @@ -27,6 +28,7 @@ IntegerVariable, OrdinalVariable, CategoricalVariable, + HAS_CONFIG_SPACE, ) import smt.utils.design_space as ds @@ -720,193 +722,48 @@ def run_hierarchical_design_space_example(self): y_sv = sm.predict_variances(Xt)[:, 0] var_RMSE = np.linalg.norm(y_sv) / len(Yt) - self.assertTrue(pred_RMSE < 1e-7) + assert pred_RMSE < 1e-7 print("Pred_RMSE", pred_RMSE) - self.assertTrue( - np.linalg.norm( - sm.predict_values( - np.array( - [ - [0, 2, 1, 0.75], - [1, 2, 1, 0.66], - [0, 2, 1, 0.75], - ] - ) - )[:, 0] - - sm.predict_values( - np.array( - [ - [0, 2, 2, 0.75], - [1, 1, 2, 0.66], - [0, 2, 0, 0.75], - ] - ) - )[:, 0] - ) - < 1e-8 - ) - self.assertTrue( - np.linalg.norm( - sm.predict_values(np.array([[0, 0, 2, 0.25]])) - - sm.predict_values(np.array([[0, 0, 2, 0.8]])) - ) - > 1e-8 - ) - - def run_hierarchical_design_space_example_CR_categorical_decreed(self): - import numpy as np - from smt.utils.design_space import ( - DesignSpace, - FloatVariable, - IntegerVariable, - OrdinalVariable, - CategoricalVariable, - ) - from smt.applications.mixed_integer import MixedIntegerKrigingModel - from smt.surrogate_models import MixIntKernelType, MixHrcKernelType, KRG - - ds = DesignSpace( - [ - CategoricalVariable( - ["A", "B"] - ), # x0 categorical: A or B; order is not relevant - CategoricalVariable( - ["C", "D", "E"] - ), # x1 ordinal: C, D or E; order is relevant - CategoricalVariable( - ["tata", "tutu", "toto"] - ), # x2 integer between 0 and 2 (inclusive): 0, 1, 2 - FloatVariable(0, 1), # c3 continuous between 0 and 1 - ] - ) - - # Declare that x1 is acting if x0 == A - ds.declare_decreed_var(decreed_var=1, meta_var=0, meta_value="A") - - # Nested hierarchy is possible: activate x2 if x1 == C or D - # Note: only if ConfigSpace is installed! pip install smt[cs] - ds.declare_decreed_var(decreed_var=2, meta_var=1, meta_value=["C", "D"]) - - # It is also possible to explicitly forbid two values from occurring simultaneously - # Note: only if ConfigSpace is installed! pip install smt[cs] - # ds.add_value_constraint( - # var1=0, value1="A", var2=2, value2=["tata","tutu"] - # ) # Forbid x0 == A && x2 == 0 or 1 - # Sample the design space - # Note: is_acting_sampled specifies for each design variable whether it is acting or not - Xt, is_acting_sampled = ds.sample_valid_x(100, random_state=42) - rng = np.random.default_rng(42) - Yt = 4 * rng.random(100) - 2 + Xt[:, 0] + Xt[:, 1] - Xt[:, 2] - Xt[:, 3] - # Correct design vectors: round discrete variables, correct hierarchical variables - x_corr, is_acting = ds.correct_get_acting( - np.array( - [ - [0, 0, 2, 0.25], - [0, 2, 1, 0.75], - [1, 2, 1, 0.66], - ] - ) - ) + self._sm = sm # to be ignored: just used for automated test - # Observe the hierarchical behavior: - self.assertTrue( - np.all( - is_acting - == np.array( + @unittest.skipIf( + not HAS_CONFIG_SPACE, "Hierarchy ConfigSpace dependency not installed" + ) + def test_hierarchical_design_space_example(self): + self.run_hierarchical_design_space_example() + np.testing.assert_almost_equal( + self._sm.predict_values( + np.array( [ - [True, True, True, True], - [ - True, - True, - False, - True, - ], # x2 is not acting if x1 != C or D (0 or 1) - [ - True, - False, - False, - True, - ], # x1 is not acting if x0 != A, and x2 is not acting because x1 is not acting + [0, 2, 1, 0.75], + [1, 2, 1, 0.66], + [0, 2, 1, 0.75], ] ) - ) - ) - self.assertTrue( - np.all( - x_corr - == np.array( + )[:, 0], + self._sm.predict_values( + np.array( [ - [0, 0, 2, 0.25], + [0, 2, 2, 0.75], + [1, 1, 2, 0.66], [0, 2, 0, 0.75], - # x2 is not acting, so it is corrected ("imputed") to its non-acting value (0 for discrete vars) - [1, 0, 0, 0.66], # x1 and x2 are imputed ] ) - ) - ) - - sm = MixedIntegerKrigingModel( - surrogate=KRG( - design_space=ds, - categorical_kernel=MixIntKernelType.CONT_RELAX, - hierarchical_kernel=MixHrcKernelType.ALG_KERNEL, - theta0=[1e-2], - corr="abs_exp", - n_start=5, - ), - ) - sm.set_training_values(Xt, Yt) - sm.train() - y_s = sm.predict_values(Xt)[:, 0] - pred_RMSE = np.linalg.norm(y_s - Yt) / len(Yt) - - y_sv = sm.predict_variances(Xt)[:, 0] - var_RMSE = np.linalg.norm(y_sv) / len(Yt) - - self.assertTrue( - np.linalg.norm( - sm.predict_values( - np.array( - [ - [0, 2, 1, 0.75], - [1, 2, 1, 0.66], - [0, 2, 1, 0.75], - ] - ) - )[:, 0] - - sm.predict_values( - np.array( - [ - [0, 2, 2, 0.75], - [1, 1, 2, 0.66], - [0, 2, 0, 0.75], - ] - ) - )[:, 0] - ) - < 1e-8 + )[:, 0], ) self.assertTrue( np.linalg.norm( - sm.predict_values(np.array([[0, 0, 2, 0.25]])) - - sm.predict_values(np.array([[0, 0, 2, 0.8]])) + self._sm.predict_values(np.array([[0, 0, 2, 0.25]])) + - self._sm.predict_values(np.array([[0, 0, 2, 0.8]])) ) > 1e-8 ) - def run_hierarchical_design_space_example_GD_categorical_decreed(self): - import numpy as np - from smt.utils.design_space import ( - DesignSpace, - FloatVariable, - IntegerVariable, - OrdinalVariable, - CategoricalVariable, - ) - from smt.applications.mixed_integer import MixedIntegerKrigingModel - from smt.surrogate_models import MixIntKernelType, MixHrcKernelType, KRG - + @unittest.skipIf( + not HAS_CONFIG_SPACE, "Hierarchy ConfigSpace dependency not installed" + ) + def test_hierarchical_design_space_example_all_categorical_decreed(self): ds = DesignSpace( [ CategoricalVariable( @@ -952,204 +809,63 @@ def run_hierarchical_design_space_example_GD_categorical_decreed(self): ) # Observe the hierarchical behavior: - self.assertTrue( - np.all( - is_acting - == np.array( + np.testing.assert_array_equal( + is_acting, + np.array( + [ + [True, True, True, True], [ - [True, True, True, True], - [ - True, - True, - False, - True, - ], # x2 is not acting if x1 != C or D (0 or 1) - [ - True, - False, - False, - True, - ], # x1 is not acting if x0 != A, and x2 is not acting because x1 is not acting - ] - ) - ) - ) - self.assertTrue( - np.all( - x_corr - == np.array( + True, + True, + False, + True, + ], # x2 is not acting if x1 != C or D (0 or 1) [ - [0, 0, 2, 0.25], - [0, 2, 0, 0.75], - # x2 is not acting, so it is corrected ("imputed") to its non-acting value (0 for discrete vars) - [1, 0, 0, 0.66], # x1 and x2 are imputed - ] - ) - ) - ) - - sm = MixedIntegerKrigingModel( - surrogate=KRG( - design_space=ds, - categorical_kernel=MixIntKernelType.GOWER, - hierarchical_kernel=MixHrcKernelType.ALG_KERNEL, - theta0=[1e-2], - corr="abs_exp", - n_start=5, + True, + False, + False, + True, + ], # x1 is not acting if x0 != A, and x2 is not acting because x1 is not acting + ] ), ) - sm.set_training_values(Xt, Yt) - sm.train() - y_s = sm.predict_values(Xt)[:, 0] - pred_RMSE = np.linalg.norm(y_s - Yt) / len(Yt) - - y_sv = sm.predict_variances(Xt)[:, 0] - var_RMSE = np.linalg.norm(y_sv) / len(Yt) - - self.assertTrue( - np.linalg.norm( - sm.predict_values( - np.array( - [ - [0, 2, 1, 0.75], - [1, 2, 1, 0.66], - [0, 2, 1, 0.75], - ] - ) - )[:, 0] - - sm.predict_values( - np.array( - [ - [0, 2, 2, 0.75], - [1, 1, 2, 0.66], - [0, 2, 0, 0.75], - ] - ) - )[:, 0] - ) - < 1e-8 - ) - self.assertTrue( - np.linalg.norm( - sm.predict_values(np.array([[0, 0, 2, 0.25]])) - - sm.predict_values(np.array([[0, 0, 2, 0.8]])) - ) - > 1e-8 - ) - - def run_hierarchical_design_space_example_HH_categorical_decreed(self): - import numpy as np - from smt.utils.design_space import ( - DesignSpace, - FloatVariable, - IntegerVariable, - OrdinalVariable, - CategoricalVariable, - ) - from smt.applications.mixed_integer import MixedIntegerKrigingModel - from smt.surrogate_models import MixIntKernelType, MixHrcKernelType, KRG - - ds = DesignSpace( - [ - CategoricalVariable( - ["A", "B"] - ), # x0 categorical: A or B; order is not relevant - CategoricalVariable( - ["C", "D", "E"] - ), # x1 ordinal: C, D or E; order is relevant - CategoricalVariable( - ["tata", "tutu", "toto"] - ), # x2 integer between 0 and 2 (inclusive): 0, 1, 2 - FloatVariable(0, 1), # c3 continuous between 0 and 1 - ] - ) - - # Declare that x1 is acting if x0 == A - ds.declare_decreed_var(decreed_var=1, meta_var=0, meta_value="A") - - # Nested hierarchy is possible: activate x2 if x1 == C or D - # Note: only if ConfigSpace is installed! pip install smt[cs] - ds.declare_decreed_var(decreed_var=2, meta_var=1, meta_value=["C", "D"]) - - # It is also possible to explicitly forbid two values from occurring simultaneously - # Note: only if ConfigSpace is installed! pip install smt[cs] - # ds.add_value_constraint( - # var1=0, value1="A", var2=2, value2=["tata","tutu"] - # ) # Forbid x0 == A && x2 == 0 or 1 - # Sample the design space - # Note: is_acting_sampled specifies for each design variable whether it is acting or not - Xt, is_acting_sampled = ds.sample_valid_x(100, random_state=42) - rng = np.random.default_rng(42) - Yt = 4 * rng.random(100) - 2 + Xt[:, 0] + Xt[:, 1] - Xt[:, 2] - Xt[:, 3] - # Correct design vectors: round discrete variables, correct hierarchical variables - x_corr, is_acting = ds.correct_get_acting( + np.testing.assert_array_equal( + x_corr, np.array( [ [0, 0, 2, 0.25], - [0, 2, 1, 0.75], - [1, 2, 1, 0.66], + [0, 2, 0, 0.75], + # x2 is not acting, so it is corrected ("imputed") to its non-acting value (0 for discrete vars) + [1, 0, 0, 0.66], # x1 and x2 are imputed ] - ) + ), ) - # Observe the hierarchical behavior: - self.assertTrue( - np.all( - is_acting - == np.array( - [ - [True, True, True, True], - [ - True, - True, - False, - True, - ], # x2 is not acting if x1 != C or D (0 or 1) - [ - True, - False, - False, - True, - ], # x1 is not acting if x0 != A, and x2 is not acting because x1 is not acting - ] - ) + for mixint_kernel in [ + MixIntKernelType.CONT_RELAX, + MixIntKernelType.GOWER, + MixIntKernelType.HOMO_HSPHERE, + ]: + sm = MixedIntegerKrigingModel( + surrogate=KRG( + design_space=ds, + categorical_kernel=mixint_kernel, + hierarchical_kernel=MixHrcKernelType.ALG_KERNEL, + theta0=[1e-2], + corr="abs_exp", + n_start=5, + ), ) - ) - self.assertTrue( - np.all( - x_corr - == np.array( - [ - [0, 0, 2, 0.25], - [0, 2, 0, 0.75], - # x2 is not acting, so it is corrected ("imputed") to its non-acting value (0 for discrete vars) - [1, 0, 0, 0.66], # x1 and x2 are imputed - ] - ) - ) - ) - - sm = MixedIntegerKrigingModel( - surrogate=KRG( - design_space=ds, - categorical_kernel=MixIntKernelType.HOMO_HSPHERE, - hierarchical_kernel=MixHrcKernelType.ALG_KERNEL, - theta0=[1e-2], - corr="abs_exp", - n_start=5, - ), - ) - sm.set_training_values(Xt, Yt) - sm.train() - y_s = sm.predict_values(Xt)[:, 0] - pred_RMSE = np.linalg.norm(y_s - Yt) / len(Yt) + sm.set_training_values(Xt, Yt) + sm.train() + y_s = sm.predict_values(Xt)[:, 0] + pred_RMSE = np.linalg.norm(y_s - Yt) / len(Yt) - y_sv = sm.predict_variances(Xt)[:, 0] - var_RMSE = np.linalg.norm(y_sv) / len(Yt) + y_sv = sm.predict_variances(Xt)[:, 0] + var_RMSE = np.linalg.norm(y_sv) / len(Yt) - self.assertTrue( - np.linalg.norm( + np.testing.assert_almost_equal( sm.predict_values( np.array( [ @@ -1158,8 +874,8 @@ def run_hierarchical_design_space_example_HH_categorical_decreed(self): [0, 2, 1, 0.75], ] ) - )[:, 0] - - sm.predict_values( + )[:, 0], + sm.predict_values( np.array( [ [0, 2, 2, 0.75], @@ -1167,17 +883,15 @@ def run_hierarchical_design_space_example_HH_categorical_decreed(self): [0, 2, 0, 0.75], ] ) - )[:, 0] + )[:, 0], ) - < 1e-8 - ) - self.assertTrue( - np.linalg.norm( - sm.predict_values(np.array([[0, 0, 2, 0.25]])) - - sm.predict_values(np.array([[0, 0, 2, 0.8]])) + self.assertTrue( + np.linalg.norm( + sm.predict_values(np.array([[0, 0, 2, 0.25]])) + - sm.predict_values(np.array([[0, 0, 2, 0.8]])) + ) + > 1e-8 ) - > 1e-8 - ) def run_hierarchical_variables_Goldstein(self): import numpy as np @@ -1344,6 +1058,7 @@ def f3(x1, x2, x4, z1, z3, z4, x5, cos_term): y_sv = sm.predict_variances(Xt)[:, 0] var_RMSE = np.linalg.norm(y_sv) / len(Yt) + @unittest.skipIf(int(os.getenv("RUN_SLOW", 0)) < 1, "too slow") def test_hierarchical_variables_NN(self): problem = HierarchicalNeuralNetwork() ds = problem.design_space @@ -1403,28 +1118,25 @@ def test_hierarchical_variables_NN(self): self.assertTrue(pred_RMSE < 1e-7) print("Pred_RMSE", pred_RMSE) self.assertTrue(var_RMSE < 1e-7) - self.assertTrue( - np.linalg.norm( - sm.predict_values( - np.array( - [ - [0, -1, -2, 8, 0, 2, 0, 0], - [1, -1, -2, 16, 1, 2, 1, 0], - [2, -1, -2, 32, 2, 2, 1, -2], - ] - ) - )[:, 0] - - sm.predict_values( - np.array( - [ - [0, -1, -2, 8, 0, 2, 10, 10], - [1, -1, -2, 16, 1, 2, 1, 10], - [2, -1, -2, 32, 2, 2, 1, -2], - ] - ) - )[:, 0] - ) - < 1e-8 + np.testing.assert_almost_equal( + sm.predict_values( + np.array( + [ + [0, -1, -2, 8, 0, 2, 0, 0], + [1, -1, -2, 16, 1, 2, 1, 0], + [2, -1, -2, 32, 2, 2, 1, -2], + ] + ) + )[:, 0], + sm.predict_values( + np.array( + [ + [0, -1, -2, 8, 0, 2, 10, 10], + [1, -1, -2, 16, 1, 2, 1, 10], + [2, -1, -2, 32, 2, 2, 1, -2], + ] + ) + )[:, 0], ) self.assertTrue( np.linalg.norm( diff --git a/smt/utils/test/test_design_space.py b/smt/utils/test/test_design_space.py index cb6523c0a..f6fff1a0b 100644 --- a/smt/utils/test/test_design_space.py +++ b/smt/utils/test/test_design_space.py @@ -422,7 +422,9 @@ def test_design_space_hierarchical(self): assert len(seen_x) == 16 assert len(seen_is_acting) == 2 - @unittest.skipIf(not HAS_CONFIG_SPACE, "Hierarchy dependencies not installed") + @unittest.skipIf( + not HAS_CONFIG_SPACE, "Hierarchy ConfigSpace dependency not installed" + ) def test_design_space_hierarchical_config_space(self): ds = DesignSpace( [ @@ -537,7 +539,9 @@ def _is_conditionally_acting(self) -> np.ndarray: RuntimeError, lambda: ds.sample_valid_x(10, random_state=42) ) - @unittest.skipIf(not HAS_CONFIG_SPACE, "Hierarchy dependencies not installed") + @unittest.skipIf( + not HAS_CONFIG_SPACE, "Hierarchy ConfigSpace dependency not installed" + ) def test_restrictive_value_constraint(self): ds = DesignSpace( [