Skip to content

Search space

neps.search_spaces.search_space #

Contains the SearchSpace class which is a container for hyperparameters that can be sampled, mutated, and crossed over.

SearchSpace #

SearchSpace(**hyperparameters: Parameter)

Bases: Mapping[str, Any]

A container for hyperparameters that can be sampled, mutated, and crossed over.

Provides operations for operating on and generating new configurations from the hyperparameters.

Note

The SearchSpace class is both the definition of the search space and also a configuration at the same time.

When refering to the SearchSpace as a configuration, the documentation will refer to it as a configuration or config. Otherwise, it will be referred to as a search space.

TODO

This documentation is WIP. If you have any questions, please reach out so we can know better what to document.

PARAMETER DESCRIPTION
**hyperparameters

The hyperparameters that define the search space.

TYPE: Parameter DEFAULT: {}

Source code in neps/search_spaces/search_space.py
def __init__(self, **hyperparameters: Parameter):
    """Initialize the SearchSpace with hyperparameters.

    Args:
        **hyperparameters: The hyperparameters that define the search space.
    """
    # Ensure a consistent ordering for uses throughout the lib
    _hyperparameters = sorted(hyperparameters.items(), key=lambda x: x[0])
    _fidelity_param: NumericalParameter | None = None
    _fidelity_name: str | None = None
    _has_prior: bool = False

    for name, hp in _hyperparameters:
        if hp.is_fidelity:
            if _fidelity_param is not None:
                raise ValueError(
                    "neps only supports one fidelity parameter in the pipeline space,"
                    " but multiple were given. (Hint: check you pipeline space for "
                    "multiple is_fidelity=True)"
                )

            if not isinstance(hp, NumericalParameter):
                raise ValueError(
                    "neps only suport float and integer fidelity parameters"
                )

            _fidelity_param = hp
            _fidelity_name = name

        if isinstance(hp, ParameterWithPrior) and hp.has_prior:
            _has_prior = True

    self.hyperparameters: dict[str, Parameter] = dict(_hyperparameters)
    self.fidelity: NumericalParameter | None = _fidelity_param
    self.fidelity_name: str | None = _fidelity_name
    self.has_prior: bool = _has_prior

    # TODO(eddiebergman): This should be a seperate thing most likely and not
    # in a `SearchSpace`.
    # Variables for tabular bookkeeping
    self.custom_grid_table: pd.Series | pd.DataFrame | None = None
    self.raw_tabular_space: SearchSpace | None = None
    self.has_tabular: bool = False

has_fidelity property #

has_fidelity: bool

Check if the search space has a fidelity parameter.

add_hyperparameter #

add_hyperparameter(name: str, hp: Parameter) -> None

Add a hyperparameter to the search space.

PARAMETER DESCRIPTION
name

The name of the hyperparameter.

TYPE: str

hp

The hyperparameter to add.

TYPE: Parameter

Source code in neps/search_spaces/search_space.py
def add_hyperparameter(self, name: str, hp: Parameter) -> None:
    """Add a hyperparameter to the search space.

    Args:
        name: The name of the hyperparameter.
        hp: The hyperparameter to add.
    """
    self.hyperparameters[str(name)] = hp
    self.hyperparameters = dict(
        sorted(self.hyperparameters.items(), key=lambda x: x[0])
    )

clone #

clone(*, _with_tabular: bool = False) -> SearchSpace

Create a copy of the search space.

Source code in neps/search_spaces/search_space.py
def clone(self, *, _with_tabular: bool = False) -> SearchSpace:
    """Create a copy of the search space."""
    new_copy = self.__class__(
        **{k: v.clone() for k, v in self.hyperparameters.items()}
    )
    if _with_tabular and self.has_tabular:
        assert self.custom_grid_table is not None
        assert self.raw_tabular_space is not None
        new_copy.set_custom_grid_space(
            grid_table=self.custom_grid_table,
            raw_space=self.raw_tabular_space,
        )

    return new_copy

compute_prior #

compute_prior(
    *, log: bool = False, ignore_fidelity: bool = False
) -> float

Compute the prior probability of the search space.

This is better know as the pdf of the configuraiton in the search space, or a relative measure of how likely this configuration is under the search space.

PARAMETER DESCRIPTION
log

Whether to compute the log of the prior.

TYPE: bool DEFAULT: False

ignore_fidelity

Whether to ignore the fidelity parameter when computing the prior.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
float

The likelihood of the configuration in the search space.

Source code in neps/search_spaces/search_space.py
def compute_prior(self, *, log: bool = False, ignore_fidelity: bool = False) -> float:
    """Compute the prior probability of the search space.

    This is better know as the `pdf` of the configuraiton in the search space, or a
    relative measure of how likely this configuration is under the search space.

    Args:
        log: Whether to compute the log of the prior.
        ignore_fidelity: Whether to ignore the fidelity parameter when
            computing the prior.


    Returns:
        The likelihood of the configuration in the search space.
    """
    density_value = 0.0 if log else 1.0
    op = operator.add if log else operator.mul

    prior_hps = (
        hp
        for hp in self.hyperparameters.values()
        if isinstance(hp, ParameterWithPrior) and hp.has_prior
    )

    for hyperparameter in prior_hps:
        if ignore_fidelity and hyperparameter.is_fidelity:
            continue

        hp_prior = hyperparameter.compute_prior(log=log)
        density_value = op(density_value, hp_prior)

    return density_value

crossover #

crossover(
    config2: SearchSpace,
    crossover_probability_per_hyperparameter: float = 1.0,
    patience: int = 50,
    crossover_strategy: str = "simple",
) -> tuple[SearchSpace, SearchSpace]

Crossover this configuration with another.

PARAMETER DESCRIPTION
config2

The other search space to crossover with.

TYPE: SearchSpace

crossover_probability_per_hyperparameter

The probability of crossing over each hyperparameter.

TYPE: float DEFAULT: 1.0

patience

The number of times to try to crossover a valid value for a hyperparameter.

TYPE: int DEFAULT: 50

crossover_strategy

The strategy to use for crossover.

TYPE: str DEFAULT: 'simple'

RETURNS DESCRIPTION
tuple[SearchSpace, SearchSpace]

A tuple of the two new configurations.

Source code in neps/search_spaces/search_space.py
def crossover(
    self,
    config2: SearchSpace,
    crossover_probability_per_hyperparameter: float = 1.0,
    patience: int = 50,
    crossover_strategy: str = "simple",
) -> tuple[SearchSpace, SearchSpace]:
    """Crossover this configuration with another.

    Args:
        config2: The other search space to crossover with.
        crossover_probability_per_hyperparameter: The probability of crossing over
            each hyperparameter.
        patience: The number of times to try to crossover a valid value for a
            hyperparameter.
        crossover_strategy: The strategy to use for crossover.

    Returns:
        A tuple of the two new configurations.
    """
    if crossover_strategy == "simple":
        new_config1, new_config2 = self._simple_crossover(
            config2=config2,
            crossover_probability_per_hyperparameter=crossover_probability_per_hyperparameter,
            patience=patience,
        )
    else:
        raise NotImplementedError("No such crossover strategy!")

    if len(self.hyperparameters.keys()) != len(new_config1):
        raise Exception("Cannot crossover")

    return SearchSpace(**new_config1), SearchSpace(**new_config2)

get_normalized_hp_categories #

get_normalized_hp_categories(
    *, ignore_fidelity: bool = False
) -> dict[
    Literal["continuous", "categorical", "graphs"],
    list[Any],
]

Get the normalized values for each hyperparameter in the configuraiton.

PARAMETER DESCRIPTION
ignore_fidelity

Whether to ignore the fidelity parameter when getting the normalized values.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
dict[Literal['continuous', 'categorical', 'graphs'], list[Any]]

A dictionary of the normalized values for each hyperparameter, separated by type.

Source code in neps/search_spaces/search_space.py
def get_normalized_hp_categories(
    self,
    *,
    ignore_fidelity: bool = False,
) -> dict[Literal["continuous", "categorical", "graphs"], list[Any]]:
    """Get the normalized values for each hyperparameter in the configuraiton.

    Args:
        ignore_fidelity: Whether to ignore the fidelity parameter when getting the
            normalized values.

    Returns:
        A dictionary of the normalized values for each hyperparameter,
        separated by type.
    """
    hps: dict[Literal["continuous", "categorical", "graphs"], list[Any]] = {
        "continuous": [],
        "categorical": [],
        "graphs": [],
    }
    for hp in self.values():
        if ignore_fidelity and hp.is_fidelity:
            continue

        if isinstance(hp, ConstantParameter):
            continue

        # TODO(eddiebergman): Not sure this covers all graph parameters but a search
        # for `def value` that have a property decorator is all that could have
        # worked previously for graphs
        if isinstance(hp, GraphParameter):
            hps["graphs"].append(hp.value)

        elif isinstance(hp, CategoricalParameter):
            assert hp.value is not None
            hp_value = hp.value_to_normalized(hp.value)
            hps["categorical"].append(hp_value)

        # TODO(eddiebergman): Technically integer is not continuous
        elif isinstance(hp, NumericalParameter):
            assert hp.value is not None
            hp_value = hp.value_to_normalized(hp.value)
            hps["continuous"].append(hp_value)
        else:
            raise NotImplementedError(f"Unknown Parameter type: {type(hp)}\n{hp}")

    return hps

get_search_space_grid #

get_search_space_grid(
    *,
    size_per_numerical_hp: int = 10,
    include_endpoints: bool = True
) -> list[SearchSpace]

Get a grid of configurations from the search space.

For NumericalParameter hyperparameters, the parameter size_per_numerical_hp= is used to determine a grid. If there are any duplicates, e.g. for an IntegerParameter, then we will remove duplicates.

For CategoricalParameter hyperparameters, we include all the choices in the grid.

For ConstantParameter hyperparameters, we include the constant value in the grid.

TODO

Does not support graph parameters currently.

PARAMETER DESCRIPTION
size_per_numerical_hp

The size of the grid for each numerical hyperparameter.

TYPE: int DEFAULT: 10

include_endpoints

Whether to include the endpoints of the grid.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
list[SearchSpace]

A list of configurations from the search space.

Source code in neps/search_spaces/search_space.py
def get_search_space_grid(
    self,
    *,
    size_per_numerical_hp: int = 10,
    include_endpoints: bool = True,
) -> list[SearchSpace]:
    """Get a grid of configurations from the search space.

    For [`NumericalParameter`][neps.search_spaces.NumericalParameter] hyperparameters,
    the parameter `size_per_numerical_hp=` is used to determine a grid. If there are
    any duplicates, e.g. for an
    [`IntegerParameter`][neps.search_spaces.IntegerParameter], then we will
    remove duplicates.

    For [`CategoricalParameter`][neps.search_spaces.CategoricalParameter]
    hyperparameters, we include all the choices in the grid.

    For [`ConstantParameter`][neps.search_spaces.ConstantParameter] hyperparameters,
    we include the constant value in the grid.

    !!! note "TODO"

        Does not support graph parameters currently.

    Args:
        size_per_numerical_hp: The size of the grid for each numerical hyperparameter.
        include_endpoints: Whether to include the endpoints of the grid.

    Returns:
        A list of configurations from the search space.
    """
    param_ranges = []
    for hp in self.hyperparameters.values():
        # NOTE(eddiebergman): This is a temporary fix to avoid graphs
        # If this is resolved, please update the docstring!
        if isinstance(hp, GraphParameter):
            raise ValueError("Trying to create a grid for graphs!")

        if isinstance(hp, CategoricalParameter):
            param_ranges.append(hp.choices)
            continue

        if isinstance(hp, ConstantParameter):
            param_ranges.append([hp.value])
            continue

        if isinstance(hp, NumericalParameter):
            grid = hp.grid(
                size=size_per_numerical_hp,
                include_endpoint=include_endpoints,
            )
            _grid = np.clip(grid, hp.lower, hp.upper).astype(np.float64)
            _grid = (
                _grid.astype(np.int64) if isinstance(hp, IntegerParameter) else _grid
            )
            _grid = np.unique(grid).tolist()
            param_ranges.append(grid)
            continue

        raise NotImplementedError(f"Unknown Parameter type: {type(hp)}\n{hp}")

    full_grid = product(*param_ranges)

    return [
        SearchSpace(
            **{
                name: ConstantParameter(value=value)  # type: ignore
                for name, value in zip(self.hyperparameters.keys(), config_values)
            }
        )
        for config_values in full_grid
    ]

get_vectorial_dim #

get_vectorial_dim() -> (
    dict[Literal["continuous", "categorical"], int] | None
)

Get the vectorial dimension of the search space.

The count of NumericalParameter are put under the key "continuous" and the count of CategoricalParameter are put under the key "categorical" in the return dict.

If there are no numerical or categorical hyperparameters or constant parameters, then None is returned.

RETURNS DESCRIPTION
dict[Literal['continuous', 'categorical'], int] | None

The vectorial dimension

Source code in neps/search_spaces/search_space.py
def get_vectorial_dim(self) -> dict[Literal["continuous", "categorical"], int] | None:
    """Get the vectorial dimension of the search space.

    The count of [`NumericalParameter`][neps.search_spaces.NumericalParameter]
    are put under the key `#!python "continuous"` and the count of
    [`CategoricalParameter`][neps.search_spaces.CategoricalParameter] are put under
    the key `#!python "categorical"` in the return dict.

    If there are no numerical or categorical hyperparameters **or constant**
    parameters, then `None` is returned.

    Returns:
        The vectorial dimension
    """
    if not any(
        isinstance(hp, (NumericalParameter, CategoricalParameter, ConstantParameter))
        for hp in self.values()
    ):
        return None

    features: dict[Literal["continuous", "categorical"], int] = {
        "continuous": 0,
        "categorical": 0,
    }
    for hp in self.values():
        if isinstance(hp, ConstantParameter):
            pass
        elif isinstance(hp, GraphParameter):
            # TODO(eddiebergman): This was what the old behaviour would do...
            pass
        elif isinstance(hp, CategoricalParameter):
            features["categorical"] += 1
        elif isinstance(hp, NumericalParameter):
            features["continuous"] += 1
        else:
            raise NotImplementedError(f"Unknown Parameter type: {type(hp)}\n{hp}")

    return features

hp_values #

hp_values() -> dict[str, Any]

Get the values for each hyperparameter in this configuration.

Source code in neps/search_spaces/search_space.py
def hp_values(self) -> dict[str, Any]:
    """Get the values for each hyperparameter in this configuration."""
    return {
        hp_name: hp if isinstance(hp, GraphParameter) else hp.value
        for hp_name, hp in self.hyperparameters.items()
    }

is_equal_value #

is_equal_value(
    other: SearchSpace,
    *,
    include_fidelity: bool = True,
    on_decimal: int = 8
) -> bool

Check if the configuration is equal to another configuration.

Warning

This does NOT check that the entire SearchSpace is equal (and thus it is not a dunder method), but only checks the configuration values.

PARAMETER DESCRIPTION
other

The other configuration to compare to.

TYPE: SearchSpace

include_fidelity

Whether to include the fidelity parameter in the comparison.

TYPE: bool DEFAULT: True

on_decimal

The decimal to round to when comparing float values.

TYPE: int DEFAULT: 8

RETURNS DESCRIPTION
bool

Whether the configuration values are equal.

Source code in neps/search_spaces/search_space.py
def is_equal_value(
    self,
    other: SearchSpace,
    *,
    include_fidelity: bool = True,
    on_decimal: int = 8,
) -> bool:
    """Check if the configuration is equal to another configuration.

    !!! warning

        This does **NOT** check that the entire `SearchSpace` is equal (and thus it is
        not a dunder method), but only checks the configuration values.

    Args:
        other: The other configuration to compare to.
        include_fidelity: Whether to include the fidelity parameter in the comparison.
        on_decimal: The decimal to round to when comparing float values.

    Returns:
        Whether the configuration values are equal.
    """
    if self.hyperparameters.keys() != other.hyperparameters.keys():
        return False

    for hp_key, this_hp in self.hyperparameters.items():
        if this_hp.is_fidelity and (not include_fidelity):
            continue

        other_hp = other.hyperparameters[hp_key]
        if not isinstance(other_hp, type(this_hp)):
            return False

        if isinstance(this_hp.value, float):
            this_norm = this_hp.value_to_normalized(this_hp.value)
            other_norm = other_hp.value_to_normalized(other_hp.value)  # type: ignore
            if np.round(this_norm - other_norm, on_decimal) != 0:
                return False
        elif this_hp.value != other_hp.value:
            return False

    return True

load_from #

load_from(
    config: Mapping[str, Any | GraphParameter]
) -> None

Load a configuration from a dictionary, setting all the values.

Source code in neps/search_spaces/search_space.py
def load_from(self, config: Mapping[str, Any | GraphParameter]) -> None:
    """Load a configuration from a dictionary, setting all the values."""
    for name, val in config.items():
        self.hyperparameters[name].load_from(val)

mutate #

mutate(
    *,
    parent: SearchSpace | None = None,
    mutation_rate: float = 1.0,
    mutation_strategy: Literal["smbo"] = "smbo",
    patience: int = 50,
    **kwargs: Any
) -> SearchSpace

Mutate the search space.

PARAMETER DESCRIPTION
parent

The parent configuration to mutate from.

TYPE: SearchSpace | None DEFAULT: None

mutation_rate

The rate at which to mutate the search space.

TYPE: float DEFAULT: 1.0

mutation_strategy

The strategy to use for mutation.

TYPE: Literal['smbo'] DEFAULT: 'smbo'

patience

The number of times to try to mutate a valid value for a hyperparameter.

TYPE: int DEFAULT: 50

**kwargs

Additional keyword arguments to pass to the mutation strategy.

TYPE: Any DEFAULT: {}

RETURNS DESCRIPTION
SearchSpace

The mutated search space.

Source code in neps/search_spaces/search_space.py
def mutate(
    self,
    *,
    parent: SearchSpace | None = None,
    mutation_rate: float = 1.0,
    mutation_strategy: Literal["smbo"] = "smbo",
    patience: int = 50,
    **kwargs: Any,
) -> SearchSpace:
    """Mutate the search space.

    Args:
        parent: The parent configuration to mutate from.
        mutation_rate: The rate at which to mutate the search space.
        mutation_strategy: The strategy to use for mutation.
        patience: The number of times to try to mutate a valid value for a
            hyperparameter.
        **kwargs: Additional keyword arguments to pass to the mutation strategy.

    Returns:
        The mutated search space.
    """
    if mutation_strategy == "smbo":
        args = {
            "parent": parent,
            "mutation_rate": mutation_rate,
            "mutation_strategy": "local_search",  # fixing property for SMBO mutation
        }
        kwargs.update(args)
        new_config = self._smbo_mutation(patience=patience, **kwargs)
    else:
        raise NotImplementedError("No such mutation strategy!")

    return SearchSpace(**new_config)

sample #

sample(
    *,
    user_priors: bool = False,
    patience: int = 1,
    ignore_fidelity: bool = True
) -> SearchSpace

Sample a configuration from the search space.

PARAMETER DESCRIPTION
user_priors

Whether to use user priors when sampling.

TYPE: bool DEFAULT: False

patience

The number of times to try to sample a valid value for a hyperparameter.

TYPE: int DEFAULT: 1

ignore_fidelity

Whether to ignore the fidelity parameter when sampling.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
SearchSpace

A sampled configuration from the search space.

Source code in neps/search_spaces/search_space.py
def sample(
    self,
    *,
    user_priors: bool = False,
    patience: int = 1,
    ignore_fidelity: bool = True,
) -> SearchSpace:
    """Sample a configuration from the search space.

    Args:
        user_priors: Whether to use user priors when sampling.
        patience: The number of times to try to sample a valid value for a
            hyperparameter.
        ignore_fidelity: Whether to ignore the fidelity parameter when sampling.

    Returns:
        A sampled configuration from the search space.
    """
    sampled_hps: dict[str, Parameter] = {}

    for name, hp in self.hyperparameters.items():
        if hp.is_fidelity and ignore_fidelity:
            sampled_hps[name] = hp.clone()
            continue

        for _ in range(patience):
            try:
                if user_priors and isinstance(hp, ParameterWithPrior):
                    sampled_hps[name] = hp.sample(user_priors=user_priors)
                else:
                    sampled_hps[name] = hp.sample()
                break
            except ValueError:
                logger.warning(
                    f"Could not sample valid value for hyperparameter {name}!"
                )
        else:
            raise ValueError(
                f"Could not sample valid value for hyperparameter {name}"
                f" in {patience} tries!"
            )

    return SearchSpace(**sampled_hps)

sample_default_configuration #

sample_default_configuration(
    *,
    patience: int = 1,
    ignore_fidelity: bool = True,
    ignore_missing_defaults: bool = False
) -> SearchSpace

Sample the default configuration from the search space.

By default, if there is no default set for a hyperparameter, an error will be raised. If ignore_missing_defaults=True, then a sampled value will be used instead.

PARAMETER DESCRIPTION
patience

The number of times to try to sample a valid value for a hyperparameter.

TYPE: int DEFAULT: 1

ignore_fidelity

Whether to ignore the fidelity parameter when sampling.

TYPE: bool DEFAULT: True

ignore_missing_defaults

Whether to ignore missing defaults when setting the default configuration.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
SearchSpace

The default configuration.

Source code in neps/search_spaces/search_space.py
def sample_default_configuration(
    self,
    *,
    patience: int = 1,
    ignore_fidelity: bool = True,
    ignore_missing_defaults: bool = False,
) -> SearchSpace:
    """Sample the default configuration from the search space.

    By default, if there is no default set for a hyperparameter, an error will be
    raised. If `ignore_missing_defaults=True`, then a sampled value will be used
    instead.

    Args:
        patience: The number of times to try to sample a valid value for a
            hyperparameter.
        ignore_fidelity: Whether to ignore the fidelity parameter when sampling.
        ignore_missing_defaults: Whether to ignore missing defaults when setting
            the default configuration.

    Returns:
        The default configuration.
    """
    # Sample a random config and then set the defaults if there are any
    config = self.sample(patience=patience, ignore_fidelity=ignore_fidelity)
    for hp_name, hp in self.hyperparameters.items():
        if hp.is_fidelity and ignore_fidelity:
            continue

        if hp.default is None:
            if not ignore_missing_defaults:
                raise ValueError(f"No defaults specified for {hp} in the space.")

            # Use the sampled value instead
        else:
            config[hp_name].set_value(hp.default)

    return config

serialize #

serialize() -> dict[str, Hashable]

Serialize the configuration to a dictionary that can be written to disk.

Source code in neps/search_spaces/search_space.py
def serialize(self) -> dict[str, Hashable]:
    """Serialize the configuration to a dictionary that can be written to disk."""
    serialized_config = {}
    for name, hp in self.hyperparameters.items():
        if hp.value is None:
            raise ValueError(
                f"Hyperparameter {name} has no value set and can't" " be serialized!"
            )
        serialized_config[name] = hp.serialize_value(hp.value)
    return serialized_config

set_custom_grid_space #

set_custom_grid_space(
    grid_table: Series | DataFrame,
    raw_space: SearchSpace | ConfigurationSpace,
) -> None

Set a custom grid space for the search space.

This function is used to set a custom grid space for the pipeline space.

Warning

The type check and the table format requirement is loose and can break certain components.

Note

Only to be used if a custom set of hyperparameters from the search space is to be sampled or used for acquisition functions.

Source code in neps/search_spaces/search_space.py
def set_custom_grid_space(
    self,
    grid_table: pd.Series | pd.DataFrame,
    raw_space: SearchSpace | CS.ConfigurationSpace,
) -> None:
    """Set a custom grid space for the search space.

    This function is used to set a custom grid space for the pipeline space.

    !!! warning

        The type check and the table format requirement is loose and
        can break certain components.

    Note:
        Only to be used if a custom set of hyperparameters from the search space
        is to be sampled or used for acquisition functions.
    """
    if grid_table is None or raw_space is None:
        raise ValueError(
            "Both grid_table and raw_space must be set!\n"
            "A table or list of fixed configs must be supported with a "
            "continuous space representing the type and bounds of each "
            "hyperparameter for accurate modeling."
        )

    self.custom_grid_table = grid_table
    self.raw_tabular_space = (
        SearchSpace(**raw_space)
        if not isinstance(raw_space, SearchSpace)
        else raw_space
    )
    self.has_tabular = True

set_defaults_to_current_values #

set_defaults_to_current_values() -> None

Update the configuration/search space to use the current values as defaults.

Source code in neps/search_spaces/search_space.py
def set_defaults_to_current_values(self) -> None:
    """Update the configuration/search space to use the current values as defaults."""
    for hp in self.hyperparameters.values():
        if isinstance(hp, NumericalParameter):
            hp.set_default(hp.value)

set_hyperparameters_from_dict #

set_hyperparameters_from_dict(
    hyperparameters: Mapping[str, Any],
    *,
    defaults: bool = True,
    values: bool = True,
    confidence: str = "low",
    delete_previous_defaults: bool = False,
    delete_previous_values: bool = False,
    overwrite_constants: bool = False
) -> None

Set the hyperparameters from a dictionary of values.

Constant Hyperparameters

ConstantParameter hyperparameters have only a single possible value and hence only a single possible default. If overwrite_constants= is False, then it will remain unchanged and ignore the new value.

If overwrite_constants= is True, then the constant hyperparameter will be updated, requiring both defaults=True and values=True to be set.

The arguments delete_previous_defaults and delete_previous_values are ignored for ConstantParameter.

PARAMETER DESCRIPTION
hyperparameters

The dictionary of hyperparameters to set with values.

TYPE: Mapping[str, Any]

defaults

Whether to set the defaults to these values.

TYPE: bool DEFAULT: True

values

Whether to set the value of the hyperparameters to these values.

TYPE: bool DEFAULT: True

confidence

The confidence score to use when setting the default. Only applies if defaults=True.

TYPE: str DEFAULT: 'low'

delete_previous_defaults

Whether to delete the previous defaults.

TYPE: bool DEFAULT: False

delete_previous_values

Whether to delete the previous values.

TYPE: bool DEFAULT: False

overwrite_constants

Whether to overwrite constant hyperparameters.

TYPE: bool DEFAULT: False

RAISES DESCRIPTION
ValueError

If the value is invalid for the hyperparameter.

Source code in neps/search_spaces/search_space.py
def set_hyperparameters_from_dict(  # noqa: C901
    self,
    hyperparameters: Mapping[str, Any],
    *,
    defaults: bool = True,
    values: bool = True,
    # TODO(eddiebergman): The existence of this makes me think
    # all hyperparameters that accept confidence should use the same keys
    confidence: str = "low",
    delete_previous_defaults: bool = False,
    delete_previous_values: bool = False,
    overwrite_constants: bool = False,
) -> None:
    """Set the hyperparameters from a dictionary of values.

    !!! note "Constant Hyperparameters"

        [`ConstantParameter`][neps.search_spaces.ConstantParameter] hyperparameters
        have only a single possible value and hence only a single possible default.
        If `overwrite_constants=` is `False`, then it will remain unchanged and
        ignore the new value.

        If `overwrite_constants=` is `True`, then the constant hyperparameter will
        be updated, requiring both `defaults=True` and `values=True` to be set.

        The arguments `delete_previous_defaults` and `delete_previous_values` are
        ignored for [`ConstantParameter`][neps.search_spaces.ConstantParameter].

    Args:
        hyperparameters: The dictionary of hyperparameters to set with values.
        defaults: Whether to set the defaults to these values.
        values: Whether to set the value of the hyperparameters to these values.
        confidence: The confidence score to use when setting the default.
            Only applies if `defaults=True`.
        delete_previous_defaults: Whether to delete the previous defaults.
        delete_previous_values: Whether to delete the previous values.
        overwrite_constants: Whether to overwrite constant hyperparameters.

    Raises:
        ValueError: If the value is invalid for the hyperparameter.
    """
    if values is False and defaults is False:
        raise ValueError("At least one of `values` or `defaults` must be True.")

    for hp_key, current_hp in self.hyperparameters.items():
        new_hp_value = hyperparameters.get(hp_key, NotSet)
        if isinstance(new_hp_value, _NotSet):
            continue

        # Handle constants specially as they have particular logic which
        # is different from the other hyperparameters
        if isinstance(current_hp, ConstantParameter):
            if not overwrite_constants:
                continue

            if not (defaults and values):
                raise ValueError(
                    "Cannot have a constant parameter with a seperate default and"
                    " and value. Please provide both `values=True` and"
                    " `defaults=True` if passing `overwrite_constants=True`"
                    f" with a new value for the constant '{hp_key}'."
                )

            current_hp.set_constant_value(new_hp_value)
            continue

        if delete_previous_defaults:
            current_hp.set_default(None)

        if delete_previous_values:
            current_hp.set_value(None)

        if defaults:
            current_hp.set_default(new_hp_value)
            if isinstance(current_hp, ParameterWithPrior):
                current_hp.set_default_confidence_score(confidence)

        if values:
            current_hp.set_value(new_hp_value)

set_to_max_fidelity #

set_to_max_fidelity() -> None

Set the configuration to the maximum fidelity.

Source code in neps/search_spaces/search_space.py
def set_to_max_fidelity(self) -> None:
    """Set the configuration to the maximum fidelity."""
    if self.fidelity is None:
        raise ValueError("No fidelity parameter in the search space!")

    self.fidelity.set_value(self.fidelity.upper)

pipeline_space_from_configspace #

pipeline_space_from_configspace(
    configspace: ConfigurationSpace,
) -> dict[str, Parameter]

Constructs the Parameter objects from a [ConfigurationSpace][ConfigSpace.configuration_space.ConfigurationSpace].

PARAMETER DESCRIPTION
configspace

The configuration space to construct the pipeline space from.

TYPE: ConfigurationSpace

RETURNS DESCRIPTION
dict[str, Parameter]

A dictionary where keys are parameter names and values are parameter objects.

Source code in neps/search_spaces/search_space.py
def pipeline_space_from_configspace(
    configspace: CS.ConfigurationSpace,
) -> dict[str, Parameter]:
    """Constructs the [`Parameter`][neps.search_spaces.parameter.Parameter] objects
    from a [`ConfigurationSpace`][ConfigSpace.configuration_space.ConfigurationSpace].

    Args:
        configspace: The configuration space to construct the pipeline space from.

    Returns:
        A dictionary where keys are parameter names and values are parameter objects.
    """
    pipeline_space = {}
    parameter: Parameter
    if any(configspace.get_conditions()) or any(configspace.get_forbiddens()):
        raise NotImplementedError(
            "The ConfigurationSpace has conditions or forbidden clauses, "
            "which are not supported by neps."
        )

    for hyperparameter in configspace.get_hyperparameters():
        if isinstance(hyperparameter, CS.Constant):
            parameter = ConstantParameter(value=hyperparameter.value)
        elif isinstance(hyperparameter, CS.CategoricalHyperparameter):
            parameter = CategoricalParameter(
                hyperparameter.choices,
                default=hyperparameter.default_value,
            )
        elif isinstance(hyperparameter, CS.OrdinalHyperparameter):
            parameter = CategoricalParameter(
                hyperparameter.sequence,
                default=hyperparameter.default_value,
            )
        elif isinstance(hyperparameter, CS.UniformIntegerHyperparameter):
            parameter = IntegerParameter(
                lower=hyperparameter.lower,
                upper=hyperparameter.upper,
                log=hyperparameter.log,
                default=hyperparameter.default_value,
            )
        elif isinstance(hyperparameter, CS.UniformFloatHyperparameter):
            parameter = FloatParameter(
                lower=hyperparameter.lower,
                upper=hyperparameter.upper,
                log=hyperparameter.log,
                default=hyperparameter.default_value,
            )
        else:
            raise ValueError(f"Unknown hyperparameter type {hyperparameter}")
        pipeline_space[hyperparameter.name] = parameter
    return pipeline_space

pipeline_space_from_yaml #

pipeline_space_from_yaml(
    config: str | Path | dict,
) -> dict[str, Parameter]

Reads configuration details from a YAML file or a dictionary and constructs a pipeline space dictionary.

PARAMETER DESCRIPTION
config

Path to the YAML file or a dictionary containing

TYPE: str | Path | dict

RETURNS DESCRIPTION
dict[str, Parameter]

dict[str, Parameter]: A dictionary where keys are parameter names and values are parameter objects.

RAISES DESCRIPTION
SearchSpaceFromYamlFileError

Raised if there are issues with the YAML file's

Source code in neps/search_spaces/search_space.py
def pipeline_space_from_yaml(  # noqa: C901, PLR0912
    config: str | Path | dict,
) -> dict[str, Parameter]:
    """Reads configuration details from a YAML file or a dictionary and constructs a
    pipeline space dictionary.

    Args:
        config (str | Path | dict): Path to the YAML file or a dictionary containing
        parameter configurations.

    Returns:
        dict[str, Parameter]: A dictionary where keys are parameter names and values
        are parameter objects.

    Raises:
        SearchSpaceFromYamlFileError: Raised if there are issues with the YAML file's
        format, contents, or if the dictionary is invalid.
    """
    try:
        if isinstance(config, (str, Path)):
            # try to load the YAML file
            try:
                yaml_file_path = Path(config)
                with yaml_file_path.open("r") as file:
                    config = yaml.safe_load(file)
                if not isinstance(config, dict):
                    raise ValueError(
                        "The loaded pipeline_space is not a valid dictionary. Please "
                        "ensure that you use a proper structure. See the documentation "
                        "for more details."
                    )
            except FileNotFoundError as e:
                raise FileNotFoundError(
                    f"Unable to find the specified file for 'pipeline_space' at "
                    f"'{config}'. Please verify the path specified in the "
                    f"'pipeline_space' argument and try again."
                ) from e
            except yaml.YAMLError as e:
                raise ValueError(f"The file at {config} is not a valid YAML file.") from e

        # Initialize the pipeline space
        pipeline_space: dict[str, Parameter] = {}

        # Iterate over the items in the YAML configuration
        for name, details in config.items():
            # get parameter type
            param_type = deduce_type(name, details)

            # init parameter by checking type
            if param_type in ("int", "integer"):
                # Integer Parameter
                formatted_details = formatting_int(name, details)
                pipeline_space[name] = IntegerParameter(**formatted_details)
            elif param_type == "float":
                # Float Parameter
                formatted_details = formatting_float(name, details)
                pipeline_space[name] = FloatParameter(**formatted_details)
            elif param_type in ("cat", "categorical"):
                # Categorical parameter
                formatted_details = formatting_cat(name, details)
                pipeline_space[name] = CategoricalParameter(**formatted_details)
            elif param_type == "const":
                # Constant parameter
                formatted_details = formatting_const(details)  # type: ignore
                pipeline_space[name] = ConstantParameter(formatted_details)
            else:
                # Handle unknown parameter type
                raise TypeError(
                    f"Unsupported parameter with details: {details} for '{name}'.\n"
                    f"Supported Types for argument type are:\n"
                    "For integer parameter: int, integer\n"
                    "For float parameter: float\n"
                    "For categorical parameter: cat, categorical\n"
                    "Constant parameter was not detect\n"
                )
    except (KeyError, TypeError, ValueError, FileNotFoundError) as e:
        raise SearchSpaceFromYamlFileError(e) from e

    return pipeline_space