Skip to content

Utils

get_constraint_satisfaction_mask(evaluations, constraint_bounds=None)

Return boolean mask indicating which evaluations satisfy the constraints.

Parameters:

Name Type Description Default
evaluations List[blackboxopt.evaluation.Evaluation]

List of evaluations to check.

required
constraint_bounds Optional[Dict[str, Tuple[Optional[float], Optional[float]]]]

For each constraint name a tuple of (lower, upper) bounds. A constraint is satisfied when lower <= value <= upper, where None means no bound on that side. If None, all evaluations are considered feasible.

None

Returns:

Type Description
ndarray

Boolean numpy array with True for feasible evaluations.

Source code in blackboxopt/visualizations/utils.py
def get_constraint_satisfaction_mask(
    evaluations: List[Evaluation],
    constraint_bounds: Optional[
        Dict[str, Tuple[Optional[float], Optional[float]]]
    ] = None,
) -> np.ndarray:
    """Return boolean mask indicating which evaluations satisfy the constraints.

    Args:
        evaluations: List of evaluations to check.
        constraint_bounds: For each constraint name a tuple of (lower, upper) bounds.
            A constraint is satisfied when lower <= value <= upper, where None means
            no bound on that side. If None, all evaluations are considered feasible.

    Returns:
        Boolean numpy array with True for feasible evaluations.
    """
    if constraint_bounds is None:
        return np.ones(len(evaluations), dtype=bool)

    mask = np.ones(len(evaluations), dtype=bool)
    for i, e in enumerate(evaluations):
        if e.constraints is None:
            mask[i] = False
            continue
        for name, (lower, upper) in constraint_bounds.items():
            value = e.constraints.get(name)
            if value is None:
                mask[i] = False
                break
            if lower is not None and value < lower:
                mask[i] = False
                break
            if upper is not None and value > upper:
                mask[i] = False
                break
    return mask

get_incumbent_objective_over_iterations(objective, objective_values, feasible_mask)

Compute incumbent trace over iterations considering only feasible evaluations.

Parameters:

Name Type Description Default
objective Objective

The objective specification.

required
objective_values ndarray

Array of objective values for all evaluations.

required
feasible_mask ndarray

Boolean mask indicating feasible evaluations.

required

Returns:

Type Description

Tuple of (iterations, incumbent_values) arrays for step-line plotting.

Source code in blackboxopt/visualizations/utils.py
def get_incumbent_objective_over_iterations(
    objective: Objective,
    objective_values: np.ndarray,
    feasible_mask: np.ndarray,
):
    """Compute incumbent trace over iterations considering only feasible evaluations.

    Args:
        objective: The objective specification.
        objective_values: Array of objective values for all evaluations.
        feasible_mask: Boolean mask indicating feasible evaluations.

    Returns:
        Tuple of (iterations, incumbent_values) arrays for step-line plotting.
    """
    iterations = np.arange(1, len(objective_values) + 1)

    feasible_iterations = iterations[feasible_mask]
    feasible_values = objective_values[feasible_mask]

    if len(feasible_values) == 0:
        return np.array([]), np.array([])

    return _get_incumbent_trace(
        objective, feasible_iterations, feasible_values, float(iterations[-1])
    )

get_incumbent_objective_over_time_single_fidelity(objective, objective_values, times, fidelities, target_fidelity)

Filter for results with given target fidelity and generate incumbent trace.

Source code in blackboxopt/visualizations/utils.py
def get_incumbent_objective_over_time_single_fidelity(
    objective: Objective,
    objective_values: np.ndarray,
    times: np.ndarray,
    fidelities: np.ndarray,
    target_fidelity: float,
):
    """Filter for results with given target fidelity and generate incumbent trace."""
    # filter out fidelity and take min/max of objective_values
    idx = np.logical_and(fidelities == target_fidelity, np.isfinite(objective_values))
    return _get_incumbent_trace(
        objective, times[idx], objective_values[idx], np.nanmax(times)
    )

patch_plotly_io_to_html(method)

Patch plotly.io.to_html with additional javascript to improve usability.

Might become obsolete, when https://github.com/plotly/plotly.js/issues/998 gets fixed.

Injects <script>-tag with content from to_html_patch.js at the end of the HTML output. But only, if the chart title starts with "[BBO]" (to minimize side effects, if the user uses plotly.io for something else).

plotly.io.to_html is also internally used for figure.show() and figure.to_html(), so this is covered, too.

Parameters:

Name Type Description Default
method Callable

Original plotly.io.to_html method.

required

Returns:

Type Description
Callable

Patched method.

Source code in blackboxopt/visualizations/utils.py
def patch_plotly_io_to_html(method: Callable) -> Callable:
    """Patch `plotly.io.to_html` with additional javascript to improve usability.

    Might become obsolete, when https://github.com/plotly/plotly.js/issues/998 gets
    fixed.

    Injects `<script>`-tag with content from `to_html_patch.js` at the end of the HTML
    output. But only, if the chart title starts with "[BBO]" (to minimize side
    effects, if the user uses `plotly.io` for something else).

    `plotly.io.to_html` is also internally used for `figure.show()` and
    `figure.to_html()`, so this is covered, too.

    Args:
        method: Original `plotly.io.to_html` method.

    Returns:
        Patched method.
    """

    @wraps(method)
    def wrapped(*args, **kwargs):
        html = method(*args, **kwargs)

        # Test if title text contains "[BBO]"
        if html.find('"title":{"text":"[BBO]') < 0:
            return html

        js = importlib.resources.read_text(
            blackboxopt.visualizations, "to_html_patch.js"
        )
        html_to_inject = f"<script>{js}</script>"
        insert_idx = html.rfind("</body>")
        if insert_idx >= 0:
            # Full html page got rendered, inject <script> before <\body>
            html = html[:insert_idx] + html_to_inject + html[insert_idx:]
        else:
            # Only chart part got rendered: append <script> at the end
            html = html + html_to_inject

        return html

    return wrapped