def test_dominates_complete_vs_incomplete(t1_state: TrialState) -> None:

    directions = [StudyDirection.MINIMIZE, StudyDirection.MAXIMIZE]

    t1 = create_trial(values=[0, 2], state=t1_state)
    t2 = create_trial(values=[1, 1], state=TrialState.COMPLETE)

    assert _dominates(t2, t1, list(directions))
    assert not _dominates(t1, t2, list(directions))
def test_dominates_1d_not_equal(v1: float, v2: float) -> None:
    t1 = create_trial(values=[v1])
    t2 = create_trial(values=[v2])

    assert _dominates(t1, t2, [StudyDirection.MINIMIZE])
    assert not _dominates(t2, t1, [StudyDirection.MINIMIZE])

    assert _dominates(t2, t1, [StudyDirection.MAXIMIZE])
    assert not _dominates(t1, t2, [StudyDirection.MAXIMIZE])
def test_dominates_invalid() -> None:
    directions = [StudyDirection.MINIMIZE, StudyDirection.MAXIMIZE]

    # The numbers of objectives for `t1` and `t2` don't match.
    t1 = create_trial(values=[1])  # One objective.
    t2 = create_trial(values=[1, 2])  # Two objectives.
    with pytest.raises(ValueError):
        _dominates(t1, t2, directions)

    # The numbers of objectives and directions don't match.
    t1 = create_trial(values=[1])  # One objective.
    t2 = create_trial(values=[1])  # One objective.
    with pytest.raises(ValueError):
        _dominates(t1, t2, directions)
def test_dominates_2d() -> None:
    directions = [StudyDirection.MINIMIZE, StudyDirection.MAXIMIZE]

    # Check all pairs of trials consisting of these values, i.e.,
    # [-inf, -inf], [-inf, -1], [-inf, 1], [-inf, inf], [-1, -inf], ...
    # These values should be specified in ascending order.
    vals = [-float("inf"), -1, 1, float("inf")]

    # The following table illustrates an example of dominance relations.
    # "d" cells in the table dominates the "t" cell in (MINIMIZE, MAXIMIZE) setting.
    #
    #                        value1
    #        ╔═════╤═════╤═════╤═════╤═════╗
    #        ║     │ -∞  │ -1  │  1  │  ∞  ║
    #        ╟─────┼─────┼─────┼─────┼─────╢
    #        ║ -∞  │     │     │  d  │  d  ║
    #        ╟─────┼─────┼─────┼─────┼─────╢
    #        ║ -1  │     │     │  d  │  d  ║
    # value0 ╟─────┼─────┼─────┼─────┼─────╢
    #        ║  1  │     │     │  t  │  d  ║
    #        ╟─────┼─────┼─────┼─────┼─────╢
    #        ║  ∞  │     │     │     │     ║
    #        ╚═════╧═════╧═════╧═════╧═════╝
    #
    # In the following code, we check that for each position of "t" cell, the relation
    # above holds.

    # Generate the set of all possible indices.
    all_indices = set(
        (i, j) for i in range(len(vals)) for j in range(len(vals)))
    for (t_i, t_j) in all_indices:
        # Generate the set of all indices that dominates the current index.
        dominating_indices = set((d_i, d_j) for d_i in range(t_i + 1)
                                 for d_j in range(t_j, len(vals)))
        dominating_indices -= {(t_i, t_j)}

        for (d_i, d_j) in dominating_indices:
            trial1 = create_trial(values=[vals[t_i], vals[t_j]])
            trial2 = create_trial(values=[vals[d_i], vals[d_j]])
            assert _dominates(trial2, trial1, directions)

        for (d_i, d_j) in all_indices - dominating_indices:
            trial1 = create_trial(values=[vals[t_i], vals[t_j]])
            trial2 = create_trial(values=[vals[d_i], vals[d_j]])
            assert not _dominates(trial2, trial1, directions)
Beispiel #5
0
def test_constrained_dominates_feasible_vs_feasible(
        direction1: StudyDirection, direction2: StudyDirection,
        constraints_list: List[List[float]]) -> None:
    directions = [direction1, direction2]
    # Check all pairs of trials consisting of these values, i.e.,
    # [-inf, -inf], [-inf, -1], [-inf, 1], [-inf, inf], [-1, -inf], ...
    values_list = [
        [x, y]
        for x in [-float("inf"), -1, 1, float("inf")]
        for y in [-float("inf"), -1, 1, float("inf")]
    ]
    values_constraints_list = [(vs, cs) for vs in values_list
                               for cs in constraints_list]

    # The results of _constrained_dominates match _dominates in all feasible cases.
    for (values1, constraints1) in values_constraints_list:
        for (values2, constraints2) in values_constraints_list:
            t1 = _create_frozen_trial(0, values1, constraints1)
            t2 = _create_frozen_trial(1, values2, constraints2)
            assert _constrained_dominates(t1, t2, directions) == _dominates(
                t1, t2, directions)
Beispiel #6
0
def _constrained_dominates(trial0: FrozenTrial, trial1: FrozenTrial,
                           directions: Sequence[StudyDirection]) -> bool:
    """Checks constrained-domination.

    A trial x is said to constrained-dominate a trial y, if any of the following conditions is
    true:
    1) Trial x is feasible and trial y is not.
    2) Trial x and y are both infeasible, but solution x has a smaller overall constraint
    violation.
    3) Trial x and y are feasible and trial x dominates trial y.
    """

    constraints0 = trial0.system_attrs.get(_CONSTRAINTS_KEY)
    constraints1 = trial1.system_attrs.get(_CONSTRAINTS_KEY)

    if constraints0 is None:
        warnings.warn(f"Trial {trial0.number} does not have constraint values."
                      " It will be dominated by the other trials.")

    if constraints1 is None:
        warnings.warn(f"Trial {trial1.number} does not have constraint values."
                      " It will be dominated by the other trials.")

    if constraints0 is None and constraints1 is None:
        # Neither Trial x nor y has constraints values
        return _dominates(trial0, trial1, directions)

    if constraints0 is not None and constraints1 is None:
        # Trial x has constraint values, but y doesn't.
        return True

    if constraints0 is None and constraints1 is not None:
        # If Trial y has constraint values, but x doesn't.
        return False

    assert isinstance(constraints0, (list, tuple))
    assert isinstance(constraints1, (list, tuple))

    if len(constraints0) != len(constraints1):
        raise ValueError(
            "Trials with different numbers of constraints cannot be compared.")

    if trial0.state != TrialState.COMPLETE:
        return False

    if trial1.state != TrialState.COMPLETE:
        return True

    satisfy_constraints0 = all(v <= 0 for v in constraints0)
    satisfy_constraints1 = all(v <= 0 for v in constraints1)

    if satisfy_constraints0 and satisfy_constraints1:
        # Both trials satisfy the constraints.
        return _dominates(trial0, trial1, directions)

    if satisfy_constraints0:
        # trial0 satisfies the constraints, but trial1 violates them.
        return True

    if satisfy_constraints1:
        # trial1 satisfies the constraints, but trial0 violates them.
        return False

    # Both trials violate the constraints.
    violation0 = sum(v for v in constraints0 if v > 0)
    violation1 = sum(v for v in constraints1 if v > 0)
    return violation0 < violation1
def test_dominates_1d_equal(v: float, direction: StudyDirection) -> None:
    assert not _dominates(create_trial(values=[v]), create_trial(values=[v]),
                          [direction])