Beispiel #1
0
    def simultpredparego(self, pool=None):
        """
        Perform multi updates on ParEGO MOBO by varying the weighting function.

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

        Returns:
             xalltemp (nparray) : Array of design variables updates.
             yalltemp (nparray) : Array of objectives value updates.
             metricall (nparray) : Array of metric of the updates.
        """
        idxs = np.random.choice(11, self.multiupdate)
        scalinfotemp = deepcopy(self.KrigScalarizedInfo)
        xalltemp = self.Xall[:, :]
        yalltemp = self.yall[:, :]
        yprednext = np.zeros(shape=[len(self.kriglist)])

        for ii, idx in enumerate(idxs):
            print(f"update number {ii + 1}")
            scalinfotemp['X'] = xalltemp
            scalinfotemp['y'] = paregopre(yalltemp, idx)
            krigtemp = Kriging(scalinfotemp,
                               standardization=True,
                               standtype='default',
                               normy=False,
                               trainvar=False)
            krigtemp.train(disp=False, pool=pool)
            x_n, met_n = run_single_opt(krigtemp,
                                        self.moboInfo,
                                        krigconstlist=self.krigconstlist,
                                        cheapconstlist=self.cheapconstlist,
                                        pool=pool)
            xnext = x_n
            metricnext = met_n
            for jj, krigobj in enumerate(self.kriglist):
                yprednext[jj] = krigobj.predict(xnext, ['pred'])
            if ii == 0:
                xallnext = deepcopy(xnext)
                yallnext = deepcopy(yprednext)
                metricall = deepcopy(metricnext)
            else:
                xallnext = np.vstack((xallnext, xnext))
                yallnext = np.vstack((yallnext, yprednext))
                metricall = np.vstack((metricall, metricnext))

        yalltemp = np.vstack((yalltemp, yprednext))
        xalltemp = np.vstack((xalltemp, xnext))

        return xallnext, yallnext, metricall
Beispiel #2
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
Beispiel #3
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
            })
Beispiel #4
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