@@ -14,28 +14,41 @@ class acquisition(object):
1414 def __init__ (self , gpsurrogate ):
1515 assert isinstance (gpsurrogate , GaussianProcess ) # add something here
1616 self .gpsurrogate = gpsurrogate
17+ self .has_gradient = False
1718
1819 # Abstract method to evaluate the acquisition function at x.
1920 def evaluate (self , x : np .ndarray ) -> np .ndarray :
2021 raise NotImplementedError ("Child class of acquisition should implement method evaluate" )
2122
23+ # Abstract method to evaluate the gradient of acquisition function at x.
24+ def eval_g (self , x : np .ndarray ) -> np .ndarray :
25+ raise NotImplementedError ("Child class of acquisition should implement method evaluate" )
2226
2327# A subclass of acquisition, implementing the Lower Confidence Bound (LCB) acquisition function.
2428class LCBacquisition (acquisition ):
2529 def __init__ (self , gpsurrogate , beta = 3.0 ):
2630 super ().__init__ (gpsurrogate )
2731 self .beta = beta
32+ self .has_gradient = True
2833
2934 # Method to evaluate the acquisition function at x.
3035 def evaluate (self , x : np .ndarray ) -> np .ndarray :
3136 mu = self .gpsurrogate .mean (x )
32- sig = self .gpsurrogate .variance (x )
33- return mu - self .beta * np .sqrt (sig )
37+ sig2 = self .gpsurrogate .variance (x )
38+ return mu - self .beta * np .sqrt (sig2 )
39+
40+ def eval_g (self , x : np .ndarray ) -> np .ndarray :
41+ mu = self .gpsurrogate .mean (x )
42+ sig2 = self .gpsurrogate .variance (x )
43+ dsig2_dx = self .gpsurrogate .variance_gradient (x )
44+ dmu_dx = self .gpsurrogate .mean_gradient (x )
45+ return dmu_dx - 0.5 * self .beta * dsig2_dx / np .sqrt (sig2 )
3446
3547# A subclass of acquisition, implementing the Expected improvement (EI) acquisition function.
3648class EIacquisition (acquisition ):
3749 def __init__ (self , gpsurrogate ):
3850 super ().__init__ (gpsurrogate )
51+ self .has_gradient = True
3952
4053 # Method to evaluate the acquisition function at x.
4154 def evaluate (self , x : np .ndarray ) -> np .ndarray :
@@ -47,12 +60,41 @@ def evaluate(self, x : np.ndarray) -> np.ndarray:
4760
4861 retval = []
4962 if sig .size == 1 and np .abs (sig ) > 1e-12 :
50- arg0 = (y_min - pred ) / sig
51- retval = (y_min - pred ) * norm .cdf (arg0 ) + sig * norm .pdf (arg0 )
63+ z = (y_min - pred ) / sig
64+ retval = (y_min - pred ) * norm .cdf (z ) + sig * norm .pdf (z )
5265 retval *= - 1.
5366 elif sig .size == 1 and np .abs (sig ) <= 1e-12 :
5467 retval = 0.0
5568 elif sig .size > 1 :
56- NotImplementedError ("TODO --- Not implemented yet!" )
69+ raise NotImplementedError ("TODO --- Not implemented yet!" )
5770
5871 return retval
72+
73+ def eval_g (self , x : np .ndarray ) -> np .ndarray :
74+ y_data = self .gpsurrogate .training_y
75+ y_min = y_data [np .argmin (y_data [:, 0 ])]
76+
77+ mean = self .gpsurrogate .mean (x )
78+ sig2 = self .gpsurrogate .variance (x )
79+ sig = np .sqrt (sig2 )
80+
81+ grad_EI = None
82+ if sig .size == 1 and np .abs (sig ) > 1e-12 :
83+ dmean_dx = self .gpsurrogate .mean_gradient (x )
84+ dsig2_dx = self .gpsurrogate .variance_gradient (x )
85+ dsig_dx = 0.5 * dsig2_dx / sig
86+
87+ z = (y_min - mean ) / sig
88+ ncdf = norm .cdf (z )
89+ npdf = norm .pdf (z )
90+ EI = (y_min - mean ) * ncdf + sig * npdf
91+
92+ dz_dx = - dmean_dx / sig - (y_min - mean ) * dsig_dx / sig ** 2
93+ grad_EI = - dmean_dx * ncdf + dsig_dx * npdf
94+ grad_EI *= - 1.
95+ elif sig .size == 1 and np .abs (sig ) <= 1e-12 :
96+ grad_EI = 0.0
97+ elif sig .size > 1 :
98+ raise NotImplementedError ("TODO --- Not implemented yet!" )
99+
100+ return grad_EI
0 commit comments