Source code for deepcave.evaluators.epm.utils

# Copyright 2021-2024 The DeepCAVE Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#  noqa: D400
"""
# Utils

This module provides a utility to get the types
as well as the bounds of the Hyperparameters.
"""

from typing import List, Optional, Tuple

import numpy as np
from ConfigSpace import ConfigurationSpace
from ConfigSpace.hyperparameters import (
    BetaFloatHyperparameter,
    BetaIntegerHyperparameter,
    CategoricalHyperparameter,
    Constant,
    NormalFloatHyperparameter,
    NormalIntegerHyperparameter,
    OrdinalHyperparameter,
    UniformFloatHyperparameter,
    UniformIntegerHyperparameter,
)


[docs] def get_types( config_space: ConfigurationSpace, instance_features: Optional[np.ndarray] = None, ) -> Tuple[List[int], List[Tuple[float, float]]]: """ Return the types of the Hyperparameters. Also return the bounds of the Hyperparameters and instance features. Parameters ---------- config_space : ConfigurationSpace The configuration space. instance_features : Optional[np.ndarray], optional The instance features. Default is None. Returns ------- Tuple[List[int], List[Tuple[float, float]]] The types of the Hyperparameters, as well as the bounds and instance features. Raises ------ ValueError Inactive parameters not supported for Beta and Normal Hyperparameters. TypeError If the Hyperparameter Type is unknown. """ # Extract types vector for rf from config space and the bounds types = [0] * len(list(config_space.values())) bounds = [(np.nan, np.nan)] * len(types) for i, param in enumerate(list(config_space.values())): parents = config_space.parents_of[param.name] if len(parents) == 0: can_be_inactive = False else: can_be_inactive = True if isinstance(param, (CategoricalHyperparameter)): n_cats = len(param.choices) if can_be_inactive: n_cats = len(param.choices) + 1 types[i] = n_cats bounds[i] = (int(n_cats), np.nan) elif isinstance(param, (OrdinalHyperparameter)): n_cats = len(param.sequence) types[i] = 0 if can_be_inactive: bounds[i] = (0, int(n_cats)) else: bounds[i] = (0, int(n_cats) - 1) elif isinstance(param, Constant): # for constants types are simply set to 0 which makes it a numerical # parameter if can_be_inactive: bounds[i] = (2, np.nan) types[i] = 2 else: bounds[i] = (0, np.nan) types[i] = 0 # and the bounds are left to be 0 for now elif isinstance(param, UniformFloatHyperparameter): # Are sampled on the unit hypercube thus the bounds # are always 0.0, 1.0 if can_be_inactive: bounds[i] = (-1.0, 1.0) else: bounds[i] = (0, 1.0) elif isinstance(param, UniformIntegerHyperparameter): if can_be_inactive: bounds[i] = (-1.0, 1.0) else: bounds[i] = (0, 1.0) elif isinstance(param, NormalFloatHyperparameter): if can_be_inactive: raise ValueError( "Inactive parameters not supported for Beta and Normal Hyperparameters" ) bounds[i] = (param.lower_vectorized, param.upper_vectorized) # type: ignore elif isinstance(param, NormalIntegerHyperparameter): if can_be_inactive: raise ValueError( "Inactive parameters not supported for Beta and Normal Hyperparameters" ) bounds[i] = (param.lower_vectorized, param.upper_vectorized) # type: ignore elif isinstance(param, BetaFloatHyperparameter): if can_be_inactive: raise ValueError( "Inactive parameters not supported for Beta and Normal Hyperparameters" ) bounds[i] = (param.lower_vectorized, param.upper_vectorized) # type: ignore elif isinstance(param, BetaIntegerHyperparameter): if can_be_inactive: raise ValueError( "Inactive parameters not supported for Beta and Normal Hyperparameters" ) bounds[i] = (param.lower_vectorized, param.upper_vectorized) # type: ignore elif not isinstance( param, ( UniformFloatHyperparameter, UniformIntegerHyperparameter, OrdinalHyperparameter, CategoricalHyperparameter, NormalFloatHyperparameter, NormalIntegerHyperparameter, BetaFloatHyperparameter, BetaIntegerHyperparameter, ), ): raise TypeError("Unknown hyperparameter type %s" % type(param)) if instance_features is not None: types = types + [0] * instance_features.shape[1] return types, bounds