6. Visualization

Amplify-BBOpt also has simple functionality for visualizing the black-box optimization history. Let us use the example program introduced in “Kernel-QA Optimizer.”

After performing optimization with the optimizer instance optimizer used in the Kernel-QA optimizer page, you can construct a history plot using the plot_history function based on the History class instance obtained with fetch_history method as follows.

Hide code cell source
from datetime import timedelta

from amplify import FixstarsClient
from amplify_bbopt import (
    DatasetGenerator,
    KernelQAOptimizer,
    RealVariable,
    blackbox,
)

from utils.pseudo_simulators import pseudo_wing_simulator as wing_simulator


# Black-box function with decision variables
@blackbox
def my_blackbox_func(
    wing_width: float = RealVariable(bounds=(1, 20), nbins=100),
    wing_height: float = RealVariable(bounds=(1, 5), nbins=20),
    wing_angle: float = RealVariable(bounds=(0, 45), nbins=20),
) -> float:
    """
    This black-box function executes wing_simulator() and returns
    the negative lift-drag ratio for a given wing's width, height, and angle.
    """
    lift, drag = wing_simulator(wing_width, wing_height, wing_angle)
    return -lift / drag  # value to minimize


# Generate initial training data set
num_init_data = 10
data = DatasetGenerator(objective=my_blackbox_func).generate(
    num_samples=num_init_data
)

# Set up solver client
client = FixstarsClient()
client.parameters.timeout = timedelta(milliseconds=2000)  # 2 seconds
# client.token = "xxxxxxxxxxx"  # Enter your Amplify API token.

# Instantiate the kernel-QA optimizer
optimizer = KernelQAOptimizer(
    data=data, client=client, objective=my_blackbox_func
)
print(optimizer)

# Perform kernel-QA optimization for [num_cycles] cycles
optimizer.optimize(num_cycles=10)

# Print results
print(f"{optimizer.best_solution=}")  # Solution (optimal input)
print(f"{optimizer.best_objective=:.3e}")  # Objective function value
Hide code cell output
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #0/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #1/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #2/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #3/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #4/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #5/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #6/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #7/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #8/10 initial data for my_blackbox_func
amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #9/10 initial data for my_blackbox_func
num variables: 3
num elemental variables: 3
num amplify variables: 137
optimizer client: FixstarsClient
objective weight: 1.0
--------------------
trainer class: ModelKernelTrainer
model class: ModelKernel
model params: {beta: 0.0, gamma: 0.0}
reg_param: 1

amplify-bbopt | 2024/10/04 04:56:54 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:54 | INFO | #1/10 optimization cycle, constraint wt: 7.77e+00
amplify-bbopt | 2024/10/04 04:56:54 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:56:57 | INFO | num_iterations: 21
amplify-bbopt | 2024/10/04 04:56:57 | INFO | y_hat=-6.202e+00, best objective=-6.202e+00
amplify-bbopt | 2024/10/04 04:56:57 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:56:57 | INFO | #2/10 optimization cycle, constraint wt: 1.24e+01
amplify-bbopt | 2024/10/04 04:56:57 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:00 | INFO | num_iterations: 19
amplify-bbopt | 2024/10/04 04:57:00 | INFO | y_hat=-6.244e+00, best objective=-6.244e+00
amplify-bbopt | 2024/10/04 04:57:00 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:00 | INFO | #3/10 optimization cycle, constraint wt: 1.25e+01
amplify-bbopt | 2024/10/04 04:57:00 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:06 | INFO | num_iterations: 19
amplify-bbopt | 2024/10/04 04:57:06 | INFO | modifying solution (11, is_frequent=False), {'wing_width': np.float64(19.808080808080806), 'wing_height': np.float64(2.263157894736842), 'wing_angle': np.float64(7.105263157894736)} --> {'wing_width': np.float64(17.12121212121212), 'wing_height': np.float64(1.631578947368421), 'wing_angle': np.float64(2.3684210526315788)}.
amplify-bbopt | 2024/10/04 04:57:06 | INFO | y_hat=-6.991e+00, best objective=-6.991e+00
amplify-bbopt | 2024/10/04 04:57:06 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:06 | INFO | #4/10 optimization cycle, constraint wt: 1.40e+01
amplify-bbopt | 2024/10/04 04:57:06 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:11 | INFO | num_iterations: 20
amplify-bbopt | 2024/10/04 04:57:11 | INFO | y_hat=-7.054e+00, best objective=-7.054e+00
amplify-bbopt | 2024/10/04 04:57:11 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:11 | INFO | #5/10 optimization cycle, constraint wt: 1.41e+01
amplify-bbopt | 2024/10/04 04:57:11 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:13 | INFO | num_iterations: 21
amplify-bbopt | 2024/10/04 04:57:13 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.12121212121212), 'wing_height': np.float64(1.631578947368421), 'wing_angle': np.float64(7.105263157894736)} --> {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)}.
amplify-bbopt | 2024/10/04 04:57:13 | INFO | y_hat=-8.808e+00, best objective=-8.808e+00
amplify-bbopt | 2024/10/04 04:57:13 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:13 | INFO | #6/10 optimization cycle, constraint wt: 1.76e+01
amplify-bbopt | 2024/10/04 04:57:13 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:16 | INFO | num_iterations: 22
amplify-bbopt | 2024/10/04 04:57:16 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)} --> {'wing_width': np.float64(2.5353535353535355), 'wing_height': np.float64(2.052631578947368), 'wing_angle': np.float64(21.31578947368421)}.
amplify-bbopt | 2024/10/04 04:57:16 | INFO | y_hat=-1.179e+00, best objective=-8.808e+00
amplify-bbopt | 2024/10/04 04:57:16 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:16 | INFO | #7/10 optimization cycle, constraint wt: 1.76e+01
amplify-bbopt | 2024/10/04 04:57:16 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:18 | INFO | num_iterations: 22
amplify-bbopt | 2024/10/04 04:57:18 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)} --> {'wing_width': np.float64(9.06060606060606), 'wing_height': np.float64(2.6842105263157894), 'wing_angle': np.float64(0.0)}.
amplify-bbopt | 2024/10/04 04:57:18 | INFO | y_hat=-2.888e+00, best objective=-8.808e+00
amplify-bbopt | 2024/10/04 04:57:18 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:18 | INFO | #8/10 optimization cycle, constraint wt: 1.76e+01
amplify-bbopt | 2024/10/04 04:57:18 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:21 | INFO | num_iterations: 22
amplify-bbopt | 2024/10/04 04:57:21 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)} --> {'wing_width': np.float64(1.0), 'wing_height': np.float64(1.4210526315789473), 'wing_angle': np.float64(0.0)}.
amplify-bbopt | 2024/10/04 04:57:21 | INFO | y_hat=-6.798e-01, best objective=-8.808e+00
amplify-bbopt | 2024/10/04 04:57:21 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:21 | INFO | #9/10 optimization cycle, constraint wt: 1.76e+01
amplify-bbopt | 2024/10/04 04:57:21 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:24 | INFO | num_iterations: 23
amplify-bbopt | 2024/10/04 04:57:24 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)} --> {'wing_width': np.float64(13.858585858585858), 'wing_height': np.float64(3.1052631578947367), 'wing_angle': np.float64(28.421052631578945)}.
amplify-bbopt | 2024/10/04 04:57:24 | INFO | y_hat=-3.540e+00, best objective=-8.808e+00
amplify-bbopt | 2024/10/04 04:57:24 | INFO | ----------------------------------------
amplify-bbopt | 2024/10/04 04:57:24 | INFO | #10/10 optimization cycle, constraint wt: 1.76e+01
amplify-bbopt | 2024/10/04 04:57:24 | INFO | model corrcoef: 1.000, beta: 0.0
amplify-bbopt | 2024/10/04 04:57:26 | INFO | num_iterations: 22
amplify-bbopt | 2024/10/04 04:57:26 | INFO | modifying solution (1, is_frequent=False), {'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)} --> {'wing_width': np.float64(5.797979797979798), 'wing_height': np.float64(3.526315789473684), 'wing_angle': np.float64(35.526315789473685)}.
amplify-bbopt | 2024/10/04 04:57:26 | INFO | y_hat=-1.488e+00, best objective=-8.808e+00
optimizer.best_solution={'wing_width': np.float64(17.505050505050505), 'wing_height': np.float64(1.0), 'wing_angle': np.float64(23.684210526315788)}
optimizer.best_objective=-8.808e+00
from amplify_bbopt import plot_history

fig = plot_history(history=optimizer.fetch_history())
fig.show()

Here, the plot shows the evolution of the found minimum value of the black-box objective function in the thick red line. The objective function values at each evaluation are shown in the grey thin line: the negative and zero cycle region for the initial training data construction phase and the positive cycle region for the optimization iterations.

For annealing-based optimizers, the open-diamond symbol shows whether the solution obtained from annealing is unique (unique solution) or the found solution was not unique; thus, the Amplify-BBOpt generated an alternative solution based on the annealing result.