Example #1
0
    def set_trial_param(self, trial_id, param_name, param_value_internal,
                        distribution):
        # type: (int, str, float, distributions.BaseDistribution) -> bool

        with self._lock:
            self.check_trial_is_updatable(trial_id,
                                          self.trials[trial_id].state)

            # Check param distribution compatibility with previous trial(s).
            if param_name in self.param_distribution:
                distributions.check_distribution_compatibility(
                    self.param_distribution[param_name], distribution)

            # Check param has not been set; otherwise, return False.
            if param_name in self.trials[trial_id].params:
                return False

            # Set param distribution.
            self.param_distribution[param_name] = distribution

            # Set param.
            self.trials[trial_id].params[
                param_name] = distribution.to_external_repr(
                    param_value_internal)
            self.trials[trial_id].distributions[param_name] = distribution

            return True
Example #2
0
    def _set_trial_param_without_commit(
        self,
        session: orm.Session,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        trial = models.TrialModel.find_or_raise_by_id(trial_id, session)
        self.check_trial_is_updatable(trial_id, trial.state)

        trial_param = models.TrialParamModel.find_by_trial_and_param_name(
            trial, param_name, session)

        if trial_param is not None:
            # Raise error in case distribution is incompatible.
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(
                    trial_param.distribution_json), distribution)

            trial_param.param_value = param_value_internal
            trial_param.distribution_json = distributions.distribution_to_json(
                distribution)
        else:
            trial_param = models.TrialParamModel(
                trial_id=trial_id,
                param_name=param_name,
                param_value=param_value_internal,
                distribution_json=distributions.distribution_to_json(
                    distribution),
            )

            trial_param.check_and_add(session)
Example #3
0
    def set_trial_param(self, trial_id, param_name, param_value_internal,
                        distribution):
        # type: (int, str, float, distributions.BaseDistribution) -> bool

        session = self.scoped_session()

        trial = models.TrialModel.find_or_raise_by_id(trial_id, session)
        trial_param = \
            models.TrialParamModel.find_by_trial_and_param_name(trial, param_name, session)

        if trial_param is not None:
            # Raise error in case distribution is incompatible.
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(
                    trial_param.distribution_json), distribution)

            # Return False when distribution is compatible but parameter has already been set.
            return False

        param = models.TrialParamModel(
            trial_id=trial_id,
            param_name=param_name,
            param_value=param_value_internal,
            distribution_json=distributions.distribution_to_json(distribution))

        param.check_and_add(session)
        commit_success = self._commit_with_integrity_check(session)

        return commit_success
    def set_trial_param(self, trial_id, param_name, param_value_internal,
                        distribution):
        # type: (int, str, Union[float, Dict], distributions.BaseDistribution) -> bool

        with self._lock:
            # Check param distribution compatibility with previous trial(s).
            if param_name in self.param_distribution:
                distributions.check_distribution_compatibility(
                    self.param_distribution[param_name], distribution)

            # Check param has not been set; otherwise, return False.
            param_value_external = distribution.to_external_repr(
                param_value_internal)
            if param_name in self.trials[trial_id].params:
                return False

            # Set param distribution.
            self.param_distribution[param_name] = distribution

            # Set param.
            self.trials[trial_id].params_in_internal_repr[
                param_name] = param_value_internal
            self.trials[trial_id].params[param_name] = param_value_external

            return True
Example #5
0
    def set_trial_param(self, trial_id, param_name, param_value_internal,
                        distribution):
        # type: (int, str, float, distributions.BaseDistribution) -> bool

        self.check_trial_is_updatable(trial_id, self.get_trial(trial_id).state)

        # Check param distribution compatibility with previous trial(s).
        study_id = self.get_study_id_from_trial_id(trial_id)
        param_distribution = self._get_study_param_distribution(study_id)
        if param_name in param_distribution:
            distributions.check_distribution_compatibility(
                param_distribution[param_name], distribution)

        trial = self.get_trial(trial_id)
        # Check param has not been set; otherwise, return False.
        if param_name in trial.params:
            return False

        with self._redis.pipeline() as pipe:
            pipe.multi()
            # Set study param distribution.
            param_distribution[param_name] = distribution
            pipe.set(self._key_study_param_distribution(study_id),
                     pickle.dumps(param_distribution))

            # Set params.
            trial.params[param_name] = distribution.to_external_repr(
                param_value_internal)
            trial.distributions[param_name] = distribution
            pipe.set(self._key_trial(trial_id), pickle.dumps(trial))
            pipe.execute()

        return True
Example #6
0
    def _suggest(self, name: str, distribution: BaseDistribution) -> Any:

        storage = self.storage
        trial_id = self._trial_id

        trial = storage.get_trial(trial_id)

        if name in trial.distributions:
            # No need to sample if already suggested.
            distributions.check_distribution_compatibility(
                trial.distributions[name], distribution)
            param_value = distribution.to_external_repr(
                storage.get_trial_param(trial_id, name))
        else:
            if self._is_fixed_param(name, distribution):
                param_value = storage.get_trial_system_attrs(
                    trial_id)["fixed_params"][name]
            elif distribution.single():
                param_value = distributions._get_single_value(distribution)
            elif self._is_relative_param(name, distribution):
                param_value = self.relative_params[name]
            else:
                study = pruners._filter_study(self.study, trial)
                param_value = self.study.sampler.sample_independent(
                    study, trial, name, distribution)

            param_value_in_internal_repr = distribution.to_internal_repr(
                param_value)
            storage.set_trial_param(trial_id, name,
                                    param_value_in_internal_repr, distribution)

        return param_value
Example #7
0
    def set_trial_param(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        with self._lock:
            trial = self._get_trial(trial_id)

            self.check_trial_is_updatable(trial_id, trial.state)

            study_id = self._trial_id_to_study_id_and_number[trial_id][0]
            # Check param distribution compatibility with previous trial(s).
            if param_name in self._studies[study_id].param_distribution:
                distributions.check_distribution_compatibility(
                    self._studies[study_id].param_distribution[param_name],
                    distribution)

            # Set param distribution.
            self._studies[study_id].param_distribution[
                param_name] = distribution

            # Set param.
            trial = copy.copy(trial)
            trial.params = copy.copy(trial.params)
            trial.params[param_name] = distribution.to_external_repr(
                param_value_internal)
            trial.distributions = copy.copy(trial.distributions)
            trial.distributions[param_name] = distribution
            self._set_trial(trial_id, trial)
Example #8
0
    def set_trial_param(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        self._check_trial_id(trial_id)
        self.check_trial_is_updatable(trial_id, self.get_trial(trial_id).state)

        # Check param distribution compatibility with previous trial(s).
        study_id = self.get_study_id_from_trial_id(trial_id)
        param_distribution = self._get_study_param_distribution(study_id)
        if param_name in param_distribution:
            distributions.check_distribution_compatibility(
                param_distribution[param_name], distribution)

        trial = self.get_trial(trial_id)

        with self._redis.pipeline() as pipe:
            pipe.multi()
            # Set study param distribution.
            param_distribution[param_name] = distribution
            pipe.set(self._key_study_param_distribution(study_id),
                     pickle.dumps(param_distribution))

            # Set params.
            trial.params[param_name] = distribution.to_external_repr(
                param_value_internal)
            trial.distributions[param_name] = distribution
            pipe.set(self._key_trial(trial_id), pickle.dumps(trial))
            pipe.execute()
Example #9
0
    def _set_trial_param_without_commit(self, session, trial_id, param_name,
                                        param_value_internal, distribution):
        # type: (orm.Session, int, str, float, distributions.BaseDistribution) -> bool

        trial = models.TrialModel.find_or_raise_by_id(trial_id, session)
        self.check_trial_is_updatable(trial_id, trial.state)

        trial_param = \
            models.TrialParamModel.find_by_trial_and_param_name(trial, param_name, session)

        if trial_param is not None:
            # Raise error in case distribution is incompatible.
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(
                    trial_param.distribution_json), distribution)

            # Terminate transaction explicitly to avoid connection timeout during transaction.
            self._commit(session)
            # Return False when distribution is compatible but parameter has already been set.
            return False

        param = models.TrialParamModel(
            trial_id=trial_id,
            param_name=param_name,
            param_value=param_value_internal,
            distribution_json=distributions.distribution_to_json(distribution))

        param.check_and_add(session)

        return True
Example #10
0
    def set_trial_param(self, trial_id, param_name, param_value_internal,
                        distribution):
        # type: (int, str, float, distributions.BaseDistribution) -> bool

        with self._lock:
            trial = self._get_trial(trial_id)

            self.check_trial_is_updatable(trial_id, trial.state)

            study_id = self._trial_id_to_study_id_and_number[trial_id][0]
            # Check param distribution compatibility with previous trial(s).
            if param_name in self._studies[study_id].param_distribution:
                distributions.check_distribution_compatibility(
                    self._studies[study_id].param_distribution[param_name],
                    distribution)

            # Check param has not been set; otherwise, return False.
            if param_name in trial.params:
                return False

            # Set param distribution.
            self._studies[study_id].param_distribution[
                param_name] = distribution

            # Set param.
            trial = copy.copy(trial)
            trial.params = copy.copy(trial.params)
            trial.params[param_name] = distribution.to_external_repr(
                param_value_internal)
            trial.distributions = copy.copy(trial.distributions)
            trial.distributions[param_name] = distribution
            self._set_trial(trial_id, trial)

            return True
Example #11
0
    def set_trial_param(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        self.check_trial_is_updatable(trial_id, self.get_trial(trial_id).state)

        # Check param distribution compatibility with previous trial(s).
        study_id = self.get_study_id_from_trial_id(trial_id)
        param_distribution = self._get_study_param_distribution(study_id)
        if param_name in param_distribution:
            distributions.check_distribution_compatibility(
                param_distribution[param_name], distribution)

        trial = self.get_trial(trial_id)

        queries: Mapping[Union[str, bytes], Union[bytes, float, int, str]]
        queries = dict()

        # Set study param distribution.
        param_distribution[param_name] = distribution
        queries[self._key_study_param_distribution(study_id)] = pickle.dumps(
            param_distribution)

        # Set params.
        trial.params[param_name] = distribution.to_external_repr(
            param_value_internal)
        trial.distributions[param_name] = distribution
        queries[self._key_trial(trial_id)] = pickle.dumps(trial)

        self._redis.mset(queries)
Example #12
0
    def _check_compatibility_with_previous_trial_param_distributions(self, session):
        # type: (orm.Session) -> None

        trial = TrialModel.find_or_raise_by_id(self.trial_id, session)

        previous_record = session.query(TrialParamModel).join(TrialModel). \
            filter(TrialModel.study_id == trial.study_id). \
            filter(TrialParamModel.param_name == self.param_name).first()
        if previous_record is not None:
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(previous_record.distribution_json),
                distributions.json_to_distribution(self.distribution_json))
Example #13
0
    def set_trial_param(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        with self._lock:
            cached_trial = self._get_cached_trial(trial_id)
            if cached_trial is not None:
                self._check_trial_is_updatable(cached_trial)

                study_id, _ = self._trial_id_to_study_id_and_number[trial_id]
                cached_dist = self._studies[study_id].param_distribution.get(
                    param_name, None)
                if cached_dist:
                    distributions.check_distribution_compatibility(
                        cached_dist, distribution)
                else:
                    # On cache miss, check compatibility against previous trials in the database
                    # and INSERT immediately to prevent other processes from creating incompatible
                    # ones. By INSERT, it is assumed that no previous entry has been persisted
                    # already.
                    self._backend._check_and_set_param_distribution(
                        study_id, trial_id, param_name, param_value_internal,
                        distribution)
                    self._studies[study_id].param_distribution[
                        param_name] = distribution

                params = copy.copy(cached_trial.params)
                params[param_name] = distribution.to_external_repr(
                    param_value_internal)
                cached_trial.params = params

                dists = copy.copy(cached_trial.distributions)
                dists[param_name] = distribution
                cached_trial.distributions = dists

                if cached_dist:  # Already persisted in case of cache miss so no need to update.
                    updates = self._get_updates(trial_id)
                    updates.params[param_name] = param_value_internal
                    updates.distributions[param_name] = distribution
                    self._flush_trial(trial_id)
                return

        self._backend.set_trial_param(trial_id, param_name,
                                      param_value_internal, distribution)
Example #14
0
    def _is_relative_param(self, name, distribution):
        # type: (str, BaseDistribution) -> bool

        if name not in self.relative_params:
            return False

        if name not in self.relative_search_space:
            raise ValueError("The parameter '{}' was sampled by `sample_relative` method "
                             "but it is not contained in the relative search space.".format(name))

        relative_distribution = self.relative_search_space[name]
        distributions.check_distribution_compatibility(relative_distribution, distribution)

        param_value = self.relative_params[name]
        param_value_in_internal_repr = distribution.to_internal_repr(param_value)
        return distribution._contains(param_value_in_internal_repr)
Example #15
0
    def _is_compatible(self, trial: FrozenTrial) -> bool:

        # Thanks to `intersection_search_space()` function, in sequential optimization,
        # the parameters of complete trials are always compatible with the search space.
        #
        # However, in distributed optimization, incompatible trials may complete on a worker
        # just after an intersection search space is calculated on another worker.

        for name, distribution in self._search_space.items():
            if name not in trial.params:
                return False

            distributions.check_distribution_compatibility(distribution, trial.distributions[name])
            param_value = trial.params[name]
            param_internal_value = distribution.to_internal_repr(param_value)
            if not distribution._contains(param_internal_value):
                return False

        return True
Example #16
0
    def set_trial_param(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        with self._lock:
            cached_trial = self._get_cached_trial(trial_id)
            if cached_trial is not None:
                self._check_trial_is_updatable(cached_trial)

                study_id, _ = self._trial_id_to_study_id_and_number[trial_id]
                cached_dist = self._studies[study_id].param_distribution.get(
                    param_name, None)
                if cached_dist:
                    distributions.check_distribution_compatibility(
                        cached_dist, distribution)
                else:
                    self._backend._check_or_set_param_distribution(
                        trial_id, param_name, param_value_internal,
                        distribution)
                    self._studies[study_id].param_distribution[
                        param_name] = distribution

                params = copy.copy(cached_trial.params)
                params[param_name] = distribution.to_external_repr(
                    param_value_internal)
                cached_trial.params = params

                dists = copy.copy(cached_trial.distributions)
                dists[param_name] = distribution
                cached_trial.distributions = dists

                if cached_dist:
                    updates = self._get_updates(trial_id)
                    updates.params[param_name] = param_value_internal
                    updates.distributions[param_name] = distribution
                return

        self._backend.set_trial_param(trial_id, param_name,
                                      param_value_internal, distribution)
Example #17
0
    def _check_and_set_param_distribution(
        self,
        study_id: int,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        session = self.scoped_session()

        # Acquire lock.
        #
        # Assume that study exists.
        models.StudyModel.find_by_id(study_id, session, for_update=True)

        models.TrialModel.find_or_raise_by_id(trial_id, session)

        previous_record = (
            session.query(models.TrialParamModel)
            .join(models.TrialModel)
            .filter(models.TrialModel.study_id == study_id)
            .filter(models.TrialParamModel.param_name == param_name)
            .first()
        )
        if previous_record is not None:
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(previous_record.distribution_json),
                distribution,
            )

        session.add(
            models.TrialParamModel(
                trial_id=trial_id,
                param_name=param_name,
                param_value=param_value_internal,
                distribution_json=distributions.distribution_to_json(distribution),
            )
        )

        # Release lock.
        session.commit()
Example #18
0
    def _suggest(self, name, distribution):
        # type: (str, BaseDistribution) -> Any

        if name not in self._params:
            raise ValueError('The value of the parameter \'{}\' is not found. Please set it at '
                             'the construction of the FixedTrial object.'.format(name))

        value = self._params[name]
        param_value_in_internal_repr = distribution.to_internal_repr(value)
        if not distribution._contains(param_value_in_internal_repr):
            raise ValueError("The value {} of the parameter '{}' is out of "
                             "the range of the distribution {}.".format(value, name, distribution))

        if name in self._distributions:
            distributions.check_distribution_compatibility(self._distributions[name], distribution)

        self._suggested_params[name] = value
        self._distributions[name] = distribution

        return value
Example #19
0
    def _suggest(self, name: str, distribution: BaseDistribution) -> Any:

        if name not in self._params:
            raise ValueError(
                "The value of the parameter '{}' is not found. Please set it at "
                "the construction of the FrozenTrial object.".format(name))

        value = self._params[name]
        param_value_in_internal_repr = distribution.to_internal_repr(value)
        if not distribution._contains(param_value_in_internal_repr):
            warnings.warn("The value {} of the parameter '{}' is out of "
                          "the range of the distribution {}.".format(
                              value, name, distribution))

        if name in self._distributions:
            distributions.check_distribution_compatibility(
                self._distributions[name], distribution)

        self._distributions[name] = distribution

        return value
Example #20
0
    def _check_or_set_param_distribution(
        self,
        trial_id: int,
        param_name: str,
        param_value_internal: float,
        distribution: distributions.BaseDistribution,
    ) -> None:

        session = self.scoped_session()

        # Acquire a lock of this trial.
        trial = models.TrialModel.find_by_id(trial_id,
                                             session,
                                             for_update=True)
        if trial is None:
            raise KeyError(models.NOT_FOUND_MSG)

        previous_record = (session.query(models.TrialParamModel).join(
            models.TrialModel).filter(
                models.TrialModel.study_id == trial.study_id).filter(
                    models.TrialParamModel.param_name == param_name).first())
        if previous_record is not None:
            distributions.check_distribution_compatibility(
                distributions.json_to_distribution(
                    previous_record.distribution_json),
                distribution,
            )
        else:
            session.add(
                models.TrialParamModel(
                    trial_id=trial_id,
                    param_name=param_name,
                    param_value=param_value_internal,
                    distribution_json=distributions.distribution_to_json(
                        distribution),
                ))

        # Release lock.
        session.commit()
Example #21
0
def test_check_distribution_compatibility() -> None:

    # test the same distribution
    for key in EXAMPLE_JSONS.keys():
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS[key], EXAMPLE_DISTRIBUTIONS[key])

    # test different distribution classes
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["u"], EXAMPLE_DISTRIBUTIONS["l"]),
    )

    # test dynamic value range (CategoricalDistribution)
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["c2"],
            distributions.CategoricalDistribution(choices=("Roppongi",
                                                           "Akasaka")),
        ),
    )

    # test dynamic value range (except CategoricalDistribution)
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["u"],
        distributions.UniformDistribution(low=-3.0, high=-2.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["l"],
        distributions.LogUniformDistribution(low=0.1, high=1.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["du"],
        distributions.DiscreteUniformDistribution(low=-1.0, high=11.0, q=3.0),
    )
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["iu"],
        distributions.IntUniformDistribution(low=-1, high=1))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["ilu"],
        distributions.IntLogUniformDistribution(low=1, high=13),
    )
Example #22
0
def test_check_distribution_compatibility():
    # type: () -> None

    # test the same distribution
    for key in EXAMPLE_JSONS.keys():
        distributions.check_distribution_compatibility(EXAMPLE_DISTRIBUTIONS[key],
                                                       EXAMPLE_DISTRIBUTIONS[key])

    # test different distribution classes
    pytest.raises(
        ValueError, lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS['u'], EXAMPLE_DISTRIBUTIONS['l']))

    # test dynamic value range (CategoricalDistribution)
    pytest.raises(
        ValueError, lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS['c2'],
            distributions.CategoricalDistribution(choices=('Roppongi', 'Akasaka'))))

    # test dynamic value range (except CategoricalDistribution)
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS['u'], distributions.UniformDistribution(low=-3.0, high=-2.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS['l'], distributions.LogUniformDistribution(low=-0.1, high=1.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS['du'],
        distributions.DiscreteUniformDistribution(low=-1.0, high=10.0, q=3.))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS['iu'], distributions.IntUniformDistribution(low=-1, high=1))
Example #23
0
def test_check_distribution_compatibility() -> None:

    # test the same distribution
    for key in EXAMPLE_JSONS:
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS[key], EXAMPLE_DISTRIBUTIONS[key])

    # test different distribution classes
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["i"], EXAMPLE_DISTRIBUTIONS["fl"]),
    )

    # test compatibility between IntDistributions.
    distributions.check_distribution_compatibility(EXAMPLE_DISTRIBUTIONS["id"],
                                                   EXAMPLE_DISTRIBUTIONS["i"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["i"], EXAMPLE_DISTRIBUTIONS["il"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["il"], EXAMPLE_DISTRIBUTIONS["id"])

    # test compatibility between FloatDistributions.
    distributions.check_distribution_compatibility(EXAMPLE_DISTRIBUTIONS["fd"],
                                                   EXAMPLE_DISTRIBUTIONS["f"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["f"], EXAMPLE_DISTRIBUTIONS["fl"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["fl"], EXAMPLE_DISTRIBUTIONS["fd"])

    # test dynamic value range (CategoricalDistribution)
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["c2"],
            distributions.CategoricalDistribution(choices=("Roppongi",
                                                           "Akasaka")),
        ),
    )

    # test dynamic value range (except CategoricalDistribution)
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["i"],
        distributions.IntDistribution(low=-3, high=2))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["il"],
        distributions.IntDistribution(low=1, high=13, log=True))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["id"],
        distributions.IntDistribution(low=-3, high=2, step=2))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["f"],
        distributions.FloatDistribution(low=-3.0, high=-2.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["fl"],
        distributions.FloatDistribution(low=0.1, high=1.0, log=True))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["fd"],
        distributions.FloatDistribution(low=-1.0, high=11.0, step=0.5))
def test_check_distribution_compatibility() -> None:

    # test the same distribution
    for key in EXAMPLE_JSONS:
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS[key], EXAMPLE_DISTRIBUTIONS[key])
        # We need to create new objects to compare NaNs.
        # See https://github.com/optuna/optuna/pull/3567#pullrequestreview-974939837.
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS[key],
            distributions.json_to_distribution(EXAMPLE_JSONS[key]))

    # test different distribution classes
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["i"], EXAMPLE_DISTRIBUTIONS["fl"]),
    )

    # test compatibility between IntDistributions.
    distributions.check_distribution_compatibility(EXAMPLE_DISTRIBUTIONS["id"],
                                                   EXAMPLE_DISTRIBUTIONS["i"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["i"], EXAMPLE_DISTRIBUTIONS["il"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["il"], EXAMPLE_DISTRIBUTIONS["id"])

    # test compatibility between FloatDistributions.
    distributions.check_distribution_compatibility(EXAMPLE_DISTRIBUTIONS["fd"],
                                                   EXAMPLE_DISTRIBUTIONS["f"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["f"], EXAMPLE_DISTRIBUTIONS["fl"])

    with pytest.raises(ValueError):
        distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["fl"], EXAMPLE_DISTRIBUTIONS["fd"])

    # test dynamic value range (CategoricalDistribution)
    pytest.raises(
        ValueError,
        lambda: distributions.check_distribution_compatibility(
            EXAMPLE_DISTRIBUTIONS["c2"],
            distributions.CategoricalDistribution(choices=("Roppongi",
                                                           "Akasaka")),
        ),
    )

    # test dynamic value range (except CategoricalDistribution)
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["i"],
        distributions.IntDistribution(low=-3, high=2))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["il"],
        distributions.IntDistribution(low=1, high=13, log=True))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["id"],
        distributions.IntDistribution(low=-3, high=2, step=2))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["f"],
        distributions.FloatDistribution(low=-3.0, high=-2.0))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["fl"],
        distributions.FloatDistribution(low=0.1, high=1.0, log=True))
    distributions.check_distribution_compatibility(
        EXAMPLE_DISTRIBUTIONS["fd"],
        distributions.FloatDistribution(low=-1.0, high=11.0, step=0.5))