Source code for smt_optim.benchmarks.misc.mf_borehole

from functools import partial
import warnings

import numpy as np

from smt_optim.benchmarks.base import BenchmarkProblem


[docs] class MFBorehole(BenchmarkProblem): """ Reference: (with 2 fidelity levels) Xiong, S., Qian, P. Z., & Wu, C. J. (2013). Sequential design and analysis of high-accuracy and low-accuracy computer codes. Technometrics, 55(1), 37-46. (with 3 fidelity levels) Tran, A., Wildey, T., & McCann, S. (2020). sMF-BO-2CoGP: A sequential multi-fidelity constrained Bayesian optimization framework for design applications. Journal of Computing and Information Science in Engineering, 20(3), 031007. """ def __init__(self): super().__init__() self.num_dim = 8 self.num_cstr = 0 self.num_fidelity = 2 self.num_obj = 1 self.bounds = np.array( [ [0.05, 0.15], [100, 50_000], [63_070, 115_600], [990, 1_110], [63.1, 116], [700, 820], [1_120, 1680], [9_855, 12_045], ] ) self.objective = [ partial(self.func, A=1.5), partial(self.func, A=1.0), ]
[docs] def set_num_fid(self, num_fidelity): if num_fidelity not in [2, 3]: warnings.warn( "MF Borehole can have 2 or 3 fidelity levels. Defaulting to 2." ) num_fidelity = 2 if num_fidelity == 2: self.objective = [ partial(self.func, A=5, B=1.5), partial(self.func, A=2 * np.pi, B=1.0), ] else: self.objective = [ partial(self.func, A=7, B=0.5), partial(self.func, A=5, B=1.5), partial(self.func, A=2 * np.pi, B=1.0), ] self.num_fidelity = len(self.objective)
[docs] def func(self, x, A=2 * np.pi, B=1.0): term1 = A * x[2] * (x[3] - x[5]) term2 = np.log10(x[1] / x[0]) term3 = ( B + (2 * x[6] * x[2]) / (np.log(x[1] / x[0]) * x[0] ** 2 * x[7]) + x[2] / x[4] ) return term1 / (term2 * term3)
if __name__ == "__main__": import scipy.optimize as so prob = MFBorehole() x0 = np.array([7.0e-02, 2.0e02, 7.0e04, 1.0e03, 1.0e02, 7.5e02, 1.4e03, 1.0e04]) x_ref = np.array( [ 5.00000000e-02, 2.00184597e02, 6.99999998e04, 9.90000000e02, 9.69866639e01, 8.20000000e02, 1.68000000e03, 9.96047429e03, ] ) res = so.minimize(prob.objective[-1], x0, bounds=prob.bounds, method="SLSQP") # print(res.fun) # print(res.x) print(np.linalg.norm(res.x - x_ref)) prob.set_num_fid(2) print(len(prob.objective)) prob.set_num_fid(3) print(len(prob.objective))