Example #1
0
def test_constraints_func_experimental_warning() -> None:
    study = optuna.create_study(directions=["minimize", "minimize"])

    with pytest.warns(optuna.exceptions.ExperimentalWarning):
        _get_pareto_front_info(
            study=study,
            constraints_func=lambda _: [1.0],
        )
Example #2
0
def test_get_pareto_front_info_unsupported_dimensions(
    n_dims: int,
    include_dominated_trials: bool,
    constraints_func: Optional[Callable[[FrozenTrial], Sequence[float]]],
) -> None:
    study = optuna.create_study(directions=["minimize"] * n_dims)
    with pytest.raises(ValueError):
        _get_pareto_front_info(
            study=study,
            include_dominated_trials=include_dominated_trials,
            constraints_func=constraints_func,
        )
Example #3
0
def test_get_pareto_front_info_using_axis_order_and_targets(
    include_dominated_trials: bool,
    constraints_func: Optional[Callable[[FrozenTrial], Sequence[float]]],
) -> None:
    study = optuna.create_study(directions=["minimize", "minimize", "minimize"])
    with pytest.raises(ValueError):
        _get_pareto_front_info(
            study=study,
            axis_order=[0, 1, 2],
            targets=lambda t: (t.values[0], t.values[1], t.values[2]),
            include_dominated_trials=include_dominated_trials,
            constraints_func=constraints_func,
        )
Example #4
0
def test_get_pareto_front_info_invalid_target_values(
    include_dominated_trials: bool,
    constraints_func: Optional[Callable[[FrozenTrial], Sequence[float]]],
) -> None:
    study = optuna.create_study(directions=["minimize", "minimize"])
    study.optimize(lambda _: [0, 0], n_trials=3)
    with pytest.raises(ValueError):
        _get_pareto_front_info(
            study=study,
            targets=lambda t: t.values[0],
            include_dominated_trials=include_dominated_trials,
            constraints_func=constraints_func,
        )
Example #5
0
def test_get_pareto_front_info_invalid_axis_order(
    axis_order: List[int],
    include_dominated_trials: bool,
    constraints_func: Optional[Callable[[FrozenTrial], Sequence[float]]],
) -> None:
    study = optuna.create_study(directions=["minimize", "minimize"])
    with pytest.raises(ValueError):
        _get_pareto_front_info(
            study=study,
            include_dominated_trials=include_dominated_trials,
            axis_order=axis_order,
            constraints_func=constraints_func,
        )
Example #6
0
def test_get_pareto_front_info_unconstrained(
    include_dominated_trials: bool,
    axis_order: Optional[List[int]],
    targets: Optional[Callable[[FrozenTrial], Sequence[float]]],
    target_names: Optional[List[str]],
) -> None:
    if axis_order is not None and targets is not None:
        pytest.skip("skip using both axis_order and targets")

    study = create_study_2d()
    trials = study.get_trials(deepcopy=False)

    info = _get_pareto_front_info(
        study=study,
        include_dominated_trials=include_dominated_trials,
        axis_order=axis_order,
        targets=targets,
        target_names=target_names,
    )

    assert info == _ParetoFrontInfo(
        n_targets=2,
        target_names=target_names or ["Objective 0", "Objective 1"],
        best_trials_with_values=[(trials[2], [0, 2]), (trials[3], [1, 0])],
        non_best_trials_with_values=[(trials[0], [1, 2]), (trials[1], [1, 1])]
        if include_dominated_trials
        else [],
        infeasible_trials_with_values=[],
        axis_order=axis_order or [0, 1],
        include_dominated_trials=include_dominated_trials,
        has_constraints_func=False,
    )
Example #7
0
def test_get_pareto_front_info_infer_n_targets() -> None:
    study = optuna.create_study(directions=["minimize", "minimize"])
    assert _get_pareto_front_info(study).n_targets == 2

    study = optuna.create_study(directions=["minimize"] * 5)
    assert (
        _get_pareto_front_info(
            study, target_names=["target1", "target2"], targets=lambda _: [0.0, 1.0]
        ).n_targets
        == 2
    )

    study = optuna.create_study(directions=["minimize"] * 5)
    study.optimize(lambda _: [0] * 5, n_trials=1)
    assert _get_pareto_front_info(study, targets=lambda _: [0.0, 1.0]).n_targets == 2

    study = optuna.create_study(directions=["minimize"] * 2)
    with pytest.raises(ValueError):
        _get_pareto_front_info(study, targets=lambda _: [0.0, 1.0])
Example #8
0
def plot_pareto_front(
    study: Study,
    *,
    target_names: Optional[List[str]] = None,
    include_dominated_trials: bool = True,
    axis_order: Optional[List[int]] = None,
    targets: Optional[Callable[[FrozenTrial], Sequence[float]]] = None,
) -> "Axes":
    """Plot the Pareto front of a study.

    .. seealso::
        Please refer to :func:`optuna.visualization.plot_pareto_front` for an example.

    Example:

        The following code snippet shows how to plot the Pareto front of a study.

        .. plot::

            import optuna


            def objective(trial):
                x = trial.suggest_float("x", 0, 5)
                y = trial.suggest_float("y", 0, 3)

                v0 = 4 * x ** 2 + 4 * y ** 2
                v1 = (x - 5) ** 2 + (y - 5) ** 2
                return v0, v1


            study = optuna.create_study(directions=["minimize", "minimize"])
            study.optimize(objective, n_trials=50)

            optuna.visualization.matplotlib.plot_pareto_front(study)

    Args:
        study:
            A :class:`~optuna.study.Study` object whose trials are plotted for their objective
            values. ``study.n_objectives`` must be eigher 2 or 3.
        target_names:
            Objective name list used as the axis titles. If :obj:`None` is specified,
            "Objective {objective_index}" is used instead. If ``targets`` is specified
            for a study that does not contain any completed trial,
            ``target_name`` must be specified.
        include_dominated_trials:
            A flag to include all dominated trial's objective values.
        axis_order:
            A list of indices indicating the axis order. If :obj:`None` is specified,
            default order is used. ``axis_order`` and ``targets`` cannot be used at the same time.

            .. warning::
                Deprecated in v3.0.0. This feature will be removed in the future. The removal of
                this feature is currently scheduled for v5.0.0, but this schedule is subject to
                change. See https://github.com/optuna/optuna/releases/tag/v3.0.0.
        targets:
            A function that returns a tuple of target values to display.
            The argument to this function is :class:`~optuna.trial.FrozenTrial`.
            ``targets`` must be :obj:`None` or return 2 or 3 values.
            ``axis_order`` and ``targets`` cannot be used at the same time.
            If your study has more than 4 objectives, ``targets`` must be specified.

            .. note::
                Added in v3.0.0 as an experimental feature. The interface may change in newer
                versions without prior notice.
                See https://github.com/optuna/optuna/releases/tag/v3.0.0.

    Returns:
        A :class:`matplotlib.axes.Axes` object.
    """

    _imports.check()

    info = _get_pareto_front_info(study, target_names,
                                  include_dominated_trials, axis_order, None,
                                  targets)

    if info.n_targets == 2:
        return _get_pareto_front_2d(info)
    elif info.n_targets == 3:
        return _get_pareto_front_3d(info)
    else:
        raise ValueError(
            "`plot_pareto_front` function only supports 2 or 3 targets."
            " you used {} targets now.".format(info.n_targets))
Example #9
0
def plot_pareto_front(
    study: Study,
    *,
    target_names: Optional[List[str]] = None,
    include_dominated_trials: bool = True,
    axis_order: Optional[List[int]] = None,
    constraints_func: Optional[Callable[[FrozenTrial],
                                        Sequence[float]]] = None,
    targets: Optional[Callable[[FrozenTrial], Sequence[float]]] = None,
) -> "Axes":
    """Plot the Pareto front of a study.

    .. seealso::
        Please refer to :func:`optuna.visualization.plot_pareto_front` for an example.

    Example:

        The following code snippet shows how to plot the Pareto front of a study.

        .. plot::

            import optuna


            def objective(trial):
                x = trial.suggest_float("x", 0, 5)
                y = trial.suggest_float("y", 0, 3)

                v0 = 4 * x ** 2 + 4 * y ** 2
                v1 = (x - 5) ** 2 + (y - 5) ** 2
                return v0, v1


            study = optuna.create_study(directions=["minimize", "minimize"])
            study.optimize(objective, n_trials=50)

            optuna.visualization.matplotlib.plot_pareto_front(study)

    Args:
        study:
            A :class:`~optuna.study.Study` object whose trials are plotted for their objective
            values. ``study.n_objectives`` must be either 2 or 3 when ``targets`` is :obj:`None`.
        target_names:
            Objective name list used as the axis titles. If :obj:`None` is specified,
            "Objective {objective_index}" is used instead. If ``targets`` is specified
            for a study that does not contain any completed trial,
            ``target_name`` must be specified.
        include_dominated_trials:
            A flag to include all dominated trial's objective values.
        axis_order:
            A list of indices indicating the axis order. If :obj:`None` is specified,
            default order is used. ``axis_order`` and ``targets`` cannot be used at the same time.

            .. warning::
                Deprecated in v3.0.0. This feature will be removed in the future. The removal of
                this feature is currently scheduled for v5.0.0, but this schedule is subject to
                change. See https://github.com/optuna/optuna/releases/tag/v3.0.0.
        constraints_func:
            An optional function that computes the objective constraints. It must take a
            :class:`~optuna.trial.FrozenTrial` and return the constraints. The return value must
            be a sequence of :obj:`float` s. A value strictly larger than 0 means that a
            constraint is violated. A value equal to or smaller than 0 is considered feasible.
            This specification is the same as in, for example,
            :class:`~optuna.integration.NSGAIISampler`.

            If given, trials are classified into three categories: feasible and best, feasible but
            non-best, and infeasible. Categories are shown in different colors. Here, whether a
            trial is best (on Pareto front) or not is determined ignoring all infeasible trials.
        targets:
            A function that returns a tuple of target values to display.
            The argument to this function is :class:`~optuna.trial.FrozenTrial`.
            ``targets`` must be :obj:`None` or return 2 or 3 values.
            ``axis_order`` and ``targets`` cannot be used at the same time.
            If ``study.n_objectives`` is neither 2 nor 3, ``targets`` must be specified.

            .. note::
                Added in v3.0.0 as an experimental feature. The interface may change in newer
                versions without prior notice.
                See https://github.com/optuna/optuna/releases/tag/v3.0.0.

    Returns:
        A :class:`matplotlib.axes.Axes` object.
    """

    _imports.check()

    info = _get_pareto_front_info(study, target_names,
                                  include_dominated_trials, axis_order,
                                  constraints_func, targets)

    if info.n_targets == 2:
        return _get_pareto_front_2d(info)
    elif info.n_targets == 3:
        return _get_pareto_front_3d(info)
    else:
        assert False, "Must not reach here"
Example #10
0
def test_get_pareto_front_info_invalid_number_of_target_names() -> None:
    study = optuna.create_study(directions=["minimize", "minimize"])
    with pytest.raises(ValueError):
        _get_pareto_front_info(study=study, target_names=["Foo"])
Example #11
0
            study=study,
            constraints_func=lambda _: [1.0],
        )


@pytest.mark.parametrize(
    "plotter",
    [
        optuna.visualization._pareto_front._get_pareto_front_plot,
        optuna.visualization.matplotlib._pareto_front._get_pareto_front_plot,
    ],
)
@pytest.mark.parametrize(
    "info_template",
    [
        _get_pareto_front_info(create_study_2d()),
        _get_pareto_front_info(create_study_3d()),
    ],
)
@pytest.mark.parametrize("include_dominated_trials", [True, False])
@pytest.mark.parametrize("has_constraints_func", [True, False])
def test_get_pareto_front_plot(
    plotter: Callable[[_ParetoFrontInfo], Any],
    info_template: _ParetoFrontInfo,
    include_dominated_trials: bool,
    has_constraints_func: bool,
) -> None:

    info = info_template
    if not include_dominated_trials:
        info = info._replace(include_dominated_trials=False, non_best_trials_with_values=[])