def evaluate(mth, run_i, seed):
    print(mth, run_i, seed, '===== start =====', flush=True)

    def objective_function(x):
        res = problem.evaluate(x)
        return np.array(res['objs']).reshape(1, -1)

    # random seed
    np.random.seed(seed)

    # Initial evaluations
    X_init = gpflowopt.design.LatinHyperCube(initial_runs, domain).generate()
    # X_init = gpflowopt.design.RandomDesign(initial_runs, domain).generate()
    # fix numeric problem
    if hasattr(problem, 'lb') and hasattr(problem, 'ub'):
        eps = 1e-8
        X_init = np.maximum(X_init, problem.lb + eps)
        X_init = np.minimum(X_init, problem.ub - eps)
    Y_init = np.vstack([objective_function(X_init[i, :]) for i in range(X_init.shape[0])])

    # One model for each objective
    objective_models = [gpflow.gpr.GPR(X_init.copy(), Y_init[:, [i]].copy(),
                                       gpflow.kernels.Matern52(domain.size, ARD=True))
                        for i in range(Y_init.shape[1])]
    for model in objective_models:
        model.likelihood.variance = 0.01

    hvpoi = gpflowopt.acquisition.HVProbabilityOfImprovement(objective_models)
    # First setup the optimization strategy for the acquisition function
    # Combining MC step followed by L-BFGS-B
    acquisition_opt = gpflowopt.optim.StagedOptimizer([gpflowopt.optim.MCOptimizer(domain, optimizer_mc_times),
                                                       gpflowopt.optim.SciPyOptimizer(domain)])

    # Then run the BayesianOptimizer for (max_runs-init_num) iterations
    optimizer = BayesianOptimizer_modified(domain, hvpoi, optimizer=acquisition_opt, verbose=True)
    result = optimizer.optimize(objective_function, n_iter=max_runs-initial_runs)

    # Save result
    # pf = optimizer.acquisition.pareto.front.value
    # pf, dom = gpflowopt.pareto.non_dominated_sort(hvpoi.data[1])
    pf = gpflowopt.pareto.Pareto(optimizer.acquisition.data[1]).front.value
    X, Y = optimizer.acquisition.data
    time_list = [0.] * initial_runs + optimizer.time_list
    hv_diffs = []
    for i in range(Y.shape[0]):
        # hv = gpflowopt.pareto.Pareto(Y[:i+1]).hypervolume(problem.ref_point)    # ref_point problem
        hv = Hypervolume(problem.ref_point).compute(Y[:i+1])
        hv_diff = problem.max_hv - hv
        hv_diffs.append(hv_diff)

    # plot for debugging
    if plot_mode == 1:
        plot_pf(problem, problem_str, mth, pf, Y_init)

    return hv_diffs, pf, X, Y, time_list
def evaluate(mth, run_i, seed):
    print(mth, run_i, seed, '===== start =====', flush=True)

    def objective_function(config):
        res = problem.evaluate_config(config)
        res['config'] = config
        return res

    bo = SMBO(
        objective_function,
        cs,
        num_objs=problem.num_objs,
        num_constraints=0,
        surrogate_type=surrogate_type,  # default: gp
        acq_type=acq_type,  # default: ehvi
        acq_optimizer_type=acq_optimizer_type,  # default: random_scipy
        initial_runs=initial_runs,  # default: 2 * (problem.dim + 1)
        init_strategy=init_strategy,  # default: sobol
        max_runs=max_runs,
        ref_point=problem.ref_point,
        time_limit_per_trial=time_limit_per_trial,
        task_id=task_id,
        random_state=seed)

    # bo.run()
    hv_diffs = []
    time_list = []
    global_start_time = time.time()
    for i in range(max_runs):
        config, trial_state, _, objs = bo.iterate()
        global_time = time.time() - global_start_time
        print(seed, i, objs, config, trial_state, 'time=', global_time)
        hv = Hypervolume(problem.ref_point).compute(
            bo.get_history().get_pareto_front())
        hv_diff = problem.max_hv - hv
        print(seed, i, 'hypervolume =', hv)
        print(seed, i, 'hv diff =', hv_diff)
        hv_diffs.append(hv_diff)
        time_list.append(global_time)
    config_list = bo.get_history().configurations
    perf_list = bo.get_history().perfs
    pf = np.asarray(bo.get_history().get_pareto_front())

    # plot for debugging
    if plot_mode == 1:
        Y_init = None
        plot_pf(problem, problem_str, mth, pf, Y_init)

    return hv_diffs, pf, config_list, perf_list, time_list
def evaluate(mth, run_i, seed):
    print(mth, run_i, seed, '===== start =====', flush=True)

    def objective_function(x: torch.Tensor):
        # Caution: unnormalize and maximize
        x = unnormalize(x, bounds=problem_bounds)
        x = x.cpu().numpy().astype(np.float64)  # caution
        res = problem.evaluate(x)
        objs = [-y for y in res['objs']]
        return objs

    hv_diffs = []
    time_list = []
    global_start_time = time.time()

    # random seed
    np.random.seed(seed)
    torch.manual_seed(seed)

    # call helper functions to generate initial training data and initialize model
    train_x, train_obj = generate_initial_data(initial_runs,
                                               objective_function, time_list,
                                               global_start_time)
    mll, model = initialize_model(train_x, train_obj)

    # for plot
    X_init = train_x.cpu().numpy().astype(np.float64)
    Y_init = -1 * train_obj.cpu().numpy().astype(np.float64)
    # calculate hypervolume of init data
    for i in range(initial_runs):
        train_obj_i = train_obj[:i + 1]
        # compute pareto front
        pareto_mask = is_non_dominated(train_obj_i)
        pareto_y = train_obj_i[pareto_mask]
        # compute hypervolume
        volume = hv.compute(pareto_y)
        hv_diff = problem.max_hv - volume
        hv_diffs.append(hv_diff)

    # run (max_runs - initial_runs) rounds of BayesOpt after the initial random batch
    for iteration in range(initial_runs + 1, max_runs + 1):
        t0 = time.time()
        try:
            # fit the models
            fit_gpytorch_model(mll)

            # define the qEHVI acquisition modules using a QMC sampler
            sampler = SobolQMCNormalSampler(num_samples=MC_SAMPLES)
            # partition non-dominated space into disjoint rectangles
            partitioning = NondominatedPartitioning(
                num_outcomes=problem.num_objs, Y=train_obj)
            qEHVI = qExpectedHypervolumeImprovement(
                model=model,
                ref_point=problem.ref_point.tolist(
                ),  # use known reference point
                partitioning=partitioning,
                sampler=sampler,
            )
            # optimize and get new observation
            new_x, new_obj = optimize_acqf_and_get_observation(
                qEHVI, objective_function, time_list, global_start_time)
        except Exception as e:
            step = 2
            print(
                '===== Exception in optimization loop, restart with 1/%d of training data: %s'
                % (step, str(e)))
            if refit == 1:
                mll, model = initialize_model(train_x[::step],
                                              train_obj[::step])
            else:
                mll, model = initialize_model(
                    train_x[::step],
                    train_obj[::step],
                    model.state_dict(),
                )
            # fit the models
            fit_gpytorch_model(mll)

            # define the qEHVI acquisition modules using a QMC sampler
            sampler = SobolQMCNormalSampler(num_samples=MC_SAMPLES)
            # partition non-dominated space into disjoint rectangles
            partitioning = NondominatedPartitioning(
                num_outcomes=problem.num_objs, Y=train_obj[::step])
            qEHVI = qExpectedHypervolumeImprovement(
                model=model,
                ref_point=problem.ref_point.tolist(
                ),  # use known reference point
                partitioning=partitioning,
                sampler=sampler,
            )
            # optimize and get new observation
            new_x, new_obj = optimize_acqf_and_get_observation(
                qEHVI, objective_function, time_list, global_start_time)
            assert len(time_list) == iteration

        # update training points
        train_x = torch.cat([train_x, new_x])
        train_obj = torch.cat([train_obj, new_obj])

        # update progress
        # compute pareto front
        pareto_mask = is_non_dominated(train_obj)
        pareto_y = train_obj[pareto_mask]
        # compute hypervolume
        volume = hv.compute(pareto_y)
        hv_diff = problem.max_hv - volume
        hv_diffs.append(hv_diff)

        # reinitialize the models so they are ready for fitting on next iteration
        # use the current state dict to speed up fitting
        # Note: they find improved performance from not warm starting the model hyperparameters
        # using the hyperparameters from the previous iteration
        if refit == 1:
            mll, model = initialize_model(train_x, train_obj)
        else:
            mll, model = initialize_model(
                train_x,
                train_obj,
                model.state_dict(),
            )

        t1 = time.time()
        print(
            "Iter %d: x=%s, perf=%s, hv_diff=%f, time=%.2f, global_time=%.2f" %
            (iteration, unnormalize(new_x, bounds=problem_bounds), -new_obj,
             hv_diff, t1 - t0, time_list[-1]),
            flush=True)

    # Save result
    X = unnormalize(train_x, bounds=problem_bounds).cpu().numpy().astype(
        np.float64)  # caution
    Y = -1 * train_obj.cpu().numpy().astype(np.float64)
    # compute pareto front
    pareto_mask = is_non_dominated(train_obj)
    pareto_y = train_obj[pareto_mask]
    pf = -1 * pareto_y.cpu().numpy().astype(np.float64)

    # plot for debugging
    if plot_mode == 1:
        plot_pf(problem, problem_str, mth, pf, Y_init)

    return hv_diffs, pf, X, Y, time_list