Esempio n. 1
0
    def run(self, disp=True, infeasible=None):
        """
        Run multi objective unconstrained Bayesian optimization.

        Args:
            disp (bool): Display process or not. Defaults to True

        Returns:
            xupdate (nparray): Array of design variables updates.
            yupdate (nparray): Array of objectives updates
            metricall (nparray): Array of metric values of the updates.

        """

        self.nup = 0  # Number of current iteration
        self.Xall = self.kriglist[0].KrigInfo['X']
        self.yall = np.zeros(shape=[
            np.size(self.kriglist[0].KrigInfo["y"], axis=0),
            len(self.kriglist)
        ])
        for ii in range(np.size(self.yall, axis=1)):
            self.yall[:, ii] = self.kriglist[ii].KrigInfo["y"][:, 0]

        if infeasible is not None:
            self.yall = np.delete(self.yall.copy(), infeasible, 0)
            self.Xall = np.delete(self.Xall.copy(), infeasible, 0)
        else:
            pass

        self.ypar, _ = searchpareto.paretopoint(self.yall)

        print("Begin multi-objective Bayesian optimization process.")
        if self.autoupdate and disp:
            print(
                f"Update no.: {self.nup+1}, F-count: {np.size(self.Xall,0)}, "
                f"Maximum no. updates: {self.moboInfo['nup']+1}")
        else:
            pass

        # If the optimizer is ParEGO, create a scalarized Kriging
        if self.moboInfo['acquifunc'].lower() == 'parego':
            self.KrigScalarizedInfo = deepcopy(self.kriglist[0].KrigInfo)
            self.KrigScalarizedInfo['y'] = paregopre(self.yall)
            self.scalkrig = Kriging(self.KrigScalarizedInfo,
                                    standardization=True,
                                    standtype='default',
                                    normy=False,
                                    trainvar=False)
            self.scalkrig.train(disp=False)
        else:
            pass

        # Perform update on design space
        if self.moboInfo['acquifunc'].lower() == 'ehvi':
            self.ehviupdate(disp)
        elif self.moboInfo['acquifunc'].lower() == 'parego':
            self.paregoupdate(disp)
        else:
            raise ValueError(self.moboInfo["acquifunc"],
                             " is not a valid acquisition function.")

        # Finish optimization and return values
        if disp:
            print("Optimization finished, now creating the final outputs.")

        if self.multiupdate == 0 or self.multiupdate == 1:
            xupdate = self.Xall[-self.moboInfo['nup']:, :]
            yupdate = self.yall[-self.moboInfo['nup']:, :]
            supdate = self.spredall[-self.moboInfo['nup']:, :]
        else:
            xupdate = self.Xall[(-self.moboInfo['nup'] * self.multiupdate):, :]
            yupdate = self.yall[(-self.moboInfo['nup'] * self.multiupdate):, :]
            supdate = self.spredall[(-self.moboInfo['nup'] *
                                     self.multiupdate):, :]
        metricall = self.metricall

        return xupdate, yupdate, supdate, metricall
Esempio n. 2
0
    def enrich(self, xnext):
        """
        Evaluate and enrich experimental design.

        Args:
            xnext: Next design variable(s) to be evaluated.

        Returns:
            None
        """
        # Evaluate new sample
        if type(self.kriglist[0].KrigInfo['problem']) == str:
            if np.ndim(xnext) == 1:
                ynext = evaluate(xnext, self.kriglist[0].KrigInfo['problem'])
            else:
                ynext = np.zeros(shape=[np.size(xnext, 0), len(self.kriglist)])
                for ii in range(np.size(xnext, 0)):
                    ynext[ii, :] = evaluate(
                        xnext[ii, :], self.kriglist[0].KrigInfo['problem'])
        elif callable(self.kriglist[0].KrigInfo['problem']):
            ynext = self.kriglist[0].KrigInfo['problem'](xnext)
        else:
            raise ValueError(
                'KrigInfo["problem"] is not a string nor a callable function!')

        if self.krigconstlist is not None:
            for idx, constobj in enumerate(self.krigconstlist):
                if type(constobj.KrigInfo['problem']) == str:
                    ynext_const = evaluate(xnext, constobj.KrigInfo['problem'])
                elif callable(constobj.KrigInfo['problem']):
                    ynext_const = constobj.KrigInfo['problem'](xnext).reshape(
                        -1, 1)
                else:
                    raise ValueError(
                        'KrigConstInfo["problem"] is not a string nor a callable function!'
                    )
                constobj.KrigInfo['X'] = np.vstack(
                    (constobj.KrigInfo['X'], xnext))
                constobj.KrigInfo['y'] = np.vstack(
                    (constobj.KrigInfo['y'], ynext_const))
                constobj.standardize()
                constobj.train(disp=False)
        else:
            pass

        # Treatment for failed solutions, Reference : "Forrester, A. I., Sóbester, A., & Keane, A. J. (2006). Optimization with missing data.
        # Proceedings of the Royal Society A: Mathematical, Physical and Engineering Sciences, 462(2067), 935-945."
        if np.isnan(ynext).any() is True:
            for jj in range(len(self.kriglist)):
                SSqr, y_hat = self.kriglist[jj].predict(
                    xnext, ['SSqr', 'pred'])
                ynext[0, jj] = y_hat + SSqr

        # Enrich experimental design
        self.yall = np.vstack((self.yall, ynext))
        self.Xall = np.vstack((self.Xall, xnext))
        self.ypar, I = searchpareto.paretopoint(
            self.yall)  # Recompute non-dominated solutions

        if self.moboInfo['acquifunc'] == 'ehvi':
            for index, krigobj in enumerate(self.kriglist):
                krigobj.KrigInfo['X'] = self.Xall
                krigobj.KrigInfo['y'] = self.yall[:, index].reshape(-1, 1)
                krigobj.standardize()
                krigobj.train(disp=False)
        elif self.moboInfo['acquifunc'] == 'parego':
            self.KrigScalarizedInfo['X'] = self.Xall
            self.KrigScalarizedInfo['y'] = paregopre(self.yall)
            self.scalkrig = Kriging(self.KrigScalarizedInfo,
                                    standardization=True,
                                    standtype='default',
                                    normy=False,
                                    trainvar=False)
            self.scalkrig.train(disp=False)
            for index, krigobj in enumerate(self.kriglist):
                krigobj.KrigInfo['X'] = self.Xall
                krigobj.KrigInfo['y'] = self.yall[:, index].reshape(-1, 1)
                krigobj.standardize()
                krigobj.train(disp=False)
        else:
            raise ValueError(self.moboInfo["acquifunc"],
                             " is not a valid acquisition function.")

        # Save data
        if self.savedata:
            I = I.astype(int)
            Xbest = self.Xall[I, :]
            sio.savemat(self.moboInfo["filename"], {
                "xbest": Xbest,
                "ybest": self.ypar
            })
Esempio n. 3
0
    def simultpredehvi(self, disp=False, pool=None):
        """
        Perform multi updates on EHVI MOBO using Kriging believer method.

        Args:
            disp (bool, optional): Print progress. Defaults to True.
            pool (int, optional): A multiprocessing.Pool instance.
                Will be passed to functions for use, if specified.
                Defaults to None.

        Returns:
            xalltemp (np.ndarray): [n_kb, n_dv] array of update design
                variable values.
            yalltemp (np.ndarray): [n_kb, n_obj] array of update
                objective values.
            salltemp (np.ndarray): [n_kb, n_obj] array of update
                objective uncertainty values.
            metricall (np.ndarray): [n_kb, 1] array of update metric
                values.
        """
        n_krig = len(self.kriglist)
        n_dv = self.kriglist[0].KrigInfo["nvar"]

        krigtemp = [deepcopy(obj) for obj in self.kriglist]
        yprednext = np.zeros([n_krig])
        sprednext = np.zeros([n_krig])

        xalltemp = np.empty([self.multiupdate, n_dv])
        yalltemp = np.empty([self.multiupdate, n_krig])
        salltemp = np.empty([self.multiupdate, n_krig])
        metricall = np.empty([self.multiupdate, 1])

        ypartemp = self.ypar
        yall = self.yall

        for ii in range(self.multiupdate):
            t1 = time.time()
            if disp:
                print(f"update number {ii+1}")

            xnext, metrictemp = run_multi_opt(
                krigtemp,
                self.moboInfo,
                ypartemp,
                krigconstlist=self.krigconstlist,
                cheapconstlist=self.cheapconstlist,
                pool=pool)

            bound = np.vstack((-np.ones([1, n_dv]), np.ones([1, n_dv])))

            for jj, krig in enumerate(krigtemp):
                yprednext[jj], sprednext[jj] = krig.predict(
                    xnext, ['pred', 's'])
                krig.KrigInfo['X'] = np.vstack((krig.KrigInfo['X'], xnext))
                krig.KrigInfo['y'] = np.vstack(
                    (krig.KrigInfo['y'], yprednext[jj]))
                krig.standardize()
                krig.KrigInfo["F"] = compute_regression_mat(
                    krig.KrigInfo["idx"], krig.KrigInfo["X_norm"], bound,
                    np.ones([n_dv]))
                krig.KrigInfo = likelihood(krig.KrigInfo['Theta'],
                                           krig.KrigInfo,
                                           mode='all',
                                           trainvar=krig.trainvar)

            xalltemp[ii, :] = xnext[:]
            yalltemp[ii, :] = yprednext[:]
            salltemp[ii, :] = sprednext[:]
            metricall[ii, :] = metrictemp

            yall = np.vstack((yall, yprednext))
            ypartemp, _ = searchpareto.paretopoint(yall)

            if disp:
                print(f"time: {time.time() - t1:.2f} s")

        return xalltemp, yalltemp, salltemp, metricall
Esempio n. 4
0
    def simultpredehvi(self, disp=False):
        """
        Perform multi updates on EHVI MOBO using Kriging believer method.

        Returns:
             xalltemp (nparray) : Array of design variables updates.
             yalltemp (nparray) : Array of objectives value updates.
             metricall (nparray) : Array of metric of the updates.
        """

        krigtemp = [0] * len(self.kriglist)
        for index, obj in enumerate(self.kriglist):
            krigtemp[index] = deepcopy(obj)
        yprednext = np.zeros(shape=[len(krigtemp)])
        sprednext = np.zeros(shape=[len(krigtemp)])
        ypartemp = self.ypar
        yall = self.yall

        for ii in range(self.multiupdate):
            t1 = time.time()
            if disp:
                print(f"update number {ii+1}")
            else:
                pass

            xnext, metrictemp = run_multi_opt(krigtemp, self.moboInfo,
                                              ypartemp, self.krigconstlist,
                                              self.cheapconstlist)
            bound = np.vstack(
                (-np.ones(shape=[1, krigtemp[0].KrigInfo["nvar"]]),
                 np.ones(shape=[1, krigtemp[0].KrigInfo["nvar"]])))

            for jj in range(len(krigtemp)):
                yprednext[jj], sprednext[jj] = krigtemp[jj].predict(
                    xnext, ['pred', 's'])
                krigtemp[jj].KrigInfo['X'] = np.vstack(
                    (krigtemp[jj].KrigInfo['X'], xnext))
                krigtemp[jj].KrigInfo['y'] = np.vstack(
                    (krigtemp[jj].KrigInfo['y'], yprednext[jj]))
                krigtemp[jj].standardize()
                krigtemp[jj].KrigInfo["F"] = compute_regression_mat(
                    krigtemp[jj].KrigInfo["idx"],
                    krigtemp[jj].KrigInfo["X_norm"], bound,
                    np.ones(shape=[krigtemp[jj].KrigInfo["nvar"]]))
                krigtemp[jj].KrigInfo = likelihood(
                    krigtemp[jj].KrigInfo['Theta'],
                    krigtemp[jj].KrigInfo,
                    mode='all',
                    trainvar=krigtemp[jj].trainvar)

            if ii == 0:
                xalltemp = deepcopy(xnext)
                yalltemp = deepcopy(yprednext)
                salltemp = deepcopy(sprednext)
                metricall = deepcopy(metrictemp)
            else:
                xalltemp = np.vstack((xalltemp, xnext))
                yalltemp = np.vstack((yalltemp, yprednext))
                salltemp = np.vstack((salltemp, sprednext))
                metricall = np.vstack((metricall, metrictemp))

            yall = np.vstack((yall, yprednext))
            ypartemp, _ = searchpareto.paretopoint(yall)

            if disp:
                print("time: ", time.time() - t1, " s")

        return [xalltemp, yalltemp, salltemp, metricall]
Esempio n. 5
0
    def _run(self, disp=True, infeasible=None, pool=None):
        """
        Run multi objective unconstrained Bayesian optimization.

        Args:
            disp (bool, optional): Print progress. Defaults to True.
            infeasible (np.ndarray, optional): Indices of infeasible
                samples to delete. Defaults to None.
            pool (int, optional): A multiprocessing.Pool instance.
                Will be passed to functions for use, if specified.
                Defaults to None.

        Returns:
            xalltemp (np.ndarray): [n_kb, n_dv] array of update design
                variable values.
            yalltemp (np.ndarray): [n_kb, n_obj] array of update
                objective values.
            salltemp (np.ndarray): [n_kb, n_obj] array of update
                objective uncertainty values.
            metricall (np.ndarray): [n_kb, 1] array of update metric
                values.
        """
        self.nup = 0  # Number of current iteration
        self.Xall = self.kriglist[0].KrigInfo['X']
        n_samp = self.kriglist[0].KrigInfo["nsamp"]
        n_krig = len(self.kriglist)
        self.yall = np.zeros([n_samp, n_krig])
        for ii in range(n_krig):
            self.yall[:, ii] = self.kriglist[ii].KrigInfo["y"][:, 0]

        if infeasible is not None:
            self.yall = np.delete(self.yall.copy(), infeasible, 0)
            self.Xall = np.delete(self.Xall.copy(), infeasible, 0)

        self.ypar, _ = searchpareto.paretopoint(self.yall)

        print("Begin multi-objective Bayesian optimization process.")
        if self.autoupdate and disp:
            print(f"Update no.: {self.nup + 1}, F-count: {n_samp}, "
                  f"Maximum no. updates: {self.moboInfo['nup'] + 1}")

        # If the optimizer is ParEGO, create a scalarized Kriging
        if self.moboInfo['acquifunc'].lower() == 'parego':
            self.KrigScalarizedInfo = deepcopy(self.kriglist[0].KrigInfo)
            self.KrigScalarizedInfo['y'] = paregopre(self.yall)
            self.scalkrig = Kriging(self.KrigScalarizedInfo,
                                    standardization=True,
                                    standtype='default',
                                    normy=False,
                                    trainvar=False)
            self.scalkrig.train(disp=False, pool=pool)

        # Perform update on design space
        if self.moboInfo['acquifunc'].lower().startswith('ehvi'):
            self.ehviupdate(disp, pool=pool)
        elif self.moboInfo['acquifunc'].lower() == 'parego':
            self.paregoupdate(disp, pool=pool)
        else:
            raise ValueError(f"{self.moboInfo['acquifunc']} is not a valid "
                             f"acquisition function.")

        # Finish optimization and return values
        if disp:
            print("Optimization finished, now creating the final outputs.")

        xupdate = self.Xall[(-self.moboInfo['nup'] * self.multiupdate):, :]
        yupdate = self.yall[(-self.moboInfo['nup'] * self.multiupdate):, :]
        supdate = self.spredall[(-self.moboInfo['nup'] * self.multiupdate):, :]
        metricall = self.metricall

        return xupdate, yupdate, supdate, metricall