Exemplo n.º 1
0
def tringulation_search_bound_constantK(inter_par, xi, K, ind_min):
    '''
    This function is the core of constant-K continuous search function.
    :param inter_par: Contains interpolation information w, v.
    :param xi: The union of xE(Evaluated points) and xU(Support points)
    :param K: Tuning parameter for constant-K, K = K*K0. K0 is the range of yE.
    :param ind_min: The correspoding index of minimum of yE.
    :return: The minimizer, xc, and minimum, yc, of continuous search function.
    '''
    inf = 1e+20
    n = xi.shape[0]
    # Delaunay Triangulation
    if n == 1:
        sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
        tri = np.zeros((xi.shape[1] - 1, 2))
        tri[:, 0] = sx[:xi.shape[1] - 1]
        tri[:, 1] = sx[1:]
        tri = tri.astype(np.int32)
    else:
        options = 'Qt Qbb Qc' if n <= 3 else 'Qt Qbb Qc Qx'
        tri = Delaunay(xi.T, qhull_options=options).simplices
        keep = np.ones(len(tri), dtype=bool)
        for i, t in enumerate(tri):
            if abs(np.linalg.det(np.hstack(
                (xi.T[t], np.ones([1, n + 1]).T)))) < 1E-15:
                keep[i] = False  # Point is coplanar, we don't want to keep it
        tri = tri[keep]
    # Search the minimum of the synthetic quadratic model
    Sc = np.zeros([np.shape(tri)[0]])
    Scl = np.zeros([np.shape(tri)[0]])
    for ii in range(np.shape(tri)[0]):
        # R2-circumradius, xc-circumcircle center
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        # x is the center of the current simplex
        x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
        Sc[ii] = interpolation.interpolate_val(
            x, inter_par) - K * (R2 - np.linalg.norm(x - xc)**2)
        if np.sum(ind_min == tri[ii, :]):
            Scl[ii] = np.copy(Sc[ii])
        else:
            Scl[ii] = inf
    # Global one
    t = np.min(Sc)
    ind = np.argmin(Sc)
    R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
    x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
    xm, ym = Constant_K_Search(x, inter_par, xc, R2, K)
    # Local one
    t = np.min(Scl)
    ind = np.argmin(Scl)
    R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
    # Notice!! ind_min may have a problem as an index
    x = np.copy(xi[:, ind_min].reshape(-1, 1))
    xml, yml = Constant_K_Search(x, inter_par, xc, R2, K)
    if yml < ym:
        xm = np.copy(xml)
        ym = np.copy(yml)
    xm = xm.reshape(-1, 1)
    ym = ym[0, 0]
    return xm, ym
Exemplo n.º 2
0
 def discrete_function_evaluation(self, x):
     '''
     Evaluate the discrete search function value at support poitns.
     :param x:
     :return:
     '''
     return (self.inter_par.inter_val(x) - min(self.yp))[0] / Utils.mindis(
         x, self.xE)[0]
Exemplo n.º 3
0
def add_sup(xE, xU, ind_min):
    '''
    To avoid duplicate values in support points for Delaunay Triangulation.
    :param xE: Evaluated points.
    :param xU: Support points.
    :param ind_min: The minimum point's index in xE.
    return: Combination of unique elements of xE and xU and the index of the minimum yp.
    '''
    xmin = xE[:, ind_min]
    xs = np.hstack((xE, xU))
    # Construct the concatenate of xE and xU and return the array that every column is unique
    x_unique = xs[:, 0].reshape(-1, 1)
    for x in xs.T:
        dis, _, _ = Utils.mindis(x.reshape(-1, 1), x_unique)
        if dis > 1e-5:
            x_unique = np.hstack((x_unique, x.reshape(-1, 1)))
    # Find the minimum point's index: ind_min
    _, ind_min_new, _ = Utils.mindis(xmin.reshape(-1, 1), x_unique)
    return x_unique, ind_min_new
Exemplo n.º 4
0
def points_neighbers_find(x, xE, xU, Bin, Ain):
    '''
    This function aims for checking whether it's activated iteration or inactivated.
    If activated: perform function evaluation.
    Else: add the point to support points.
    :param x: Minimizer of continuous search function.
    :param xE: Evaluated points.
    :param xU: Support points.
    :return: x, xE is unchanged. 
                If success == 1: active constraint, evaluate x.
                Else: Add x to xU.
    '''
    x = x.reshape(-1, 1)
    x1 = Utils.mindis(x, np.concatenate((xE, xU), axis=1))[2].reshape(-1, 1)
    active_cons = []
    b = Bin - np.dot(Ain, x)
    for i in range(len(b)):
        if b[i][0] < 1e-3:
            active_cons.append(i + 1)
    active_cons = np.array(active_cons)

    active_cons1 = []
    b = Bin - np.dot(Ain, x1)
    for i in range(len(b)):
        if b[i][0] < 1e-3:
            active_cons1.append(i + 1)
    active_cons1 = np.array(active_cons1)
    # Explain the following two criterias,both are actived constraints:
    # The first means that x is an interior point.
    # The second means that x and x1 have exactly the same constraints.
    if len(active_cons) == 0 or abs(
            min(ismember(active_cons, active_cons1)) - 1.0) < 1e-6:
        newadd = 1
        success = 1
        if xU.shape[1] != 0 and Utils.mindis(x, xU)[0] == 0:
            newadd = 0  # Point x Already exists in support points xU, x should be evaluated.
    else:
        success = 0
        newadd = 0
        xU = np.hstack((xU, x))
    return x, xE, xU, success, newadd
Exemplo n.º 5
0
def unevaluated_vertices_identification(xE, simplex):
    exist = 0
    N = simplex.shape[1]
    for i in range(N):
        vertice = simplex[:, i].reshape(-1, 1)
        val, idx, x_nn = Utils.mindis(vertice, xE)
        if val == 0:  # vertice exists in evaluated point set
            pass
        else:
            exist = 1
            break
    return exist
Exemplo n.º 6
0
def Constant_K_Search(simplex, inter_par, K, lb=[], ub=[]):
    n = simplex.shape[0]
    R2, xc = Utils.circhyp(simplex, n)
    x = np.dot(simplex, np.ones([n + 1, 1]) / (n + 1))
    costfun = lambda x: Continuous_search_cost(x, inter_par, xc, R2, K)[0]
    costjac = lambda x: Continuous_search_cost(x, inter_par, xc, R2, K)[1]
    opt = {'disp': False}
    bnds = tuple([(0, 1) for i in range(int(n))])
    res = optimize.minimize(costfun,
                            x,
                            jac=costjac,
                            method='TNC',
                            bounds=bnds,
                            options=opt)
    x = res.x
    y = res.fun
    return x, y
Exemplo n.º 7
0
def check_activated(x, xE, xU, Bin, Ain):
    # modified for Lambda Delta DOGS
    # inactive step completed
    # Add the new point to the set
    # xE: evaluation points.
    # xU: unevaluated points.
    xs, _ = add_sup(xE, xU, 1)
    # Find closest point to x
    del_general, index, x1 = Utils.mindis(x, xs)
    # Calculate the active constraints at x and x1
    ind = np.where(np.dot(Ain, x) - Bin > -1e-4)[0]
    ind1 = np.where(np.dot(Ain, x1) - Bin > -1e-4)[0]
    if len(ind) == 0 or min(ismember(ind, ind1)) == 1:
        label = 1
    else:
        label = 0
    return label
Exemplo n.º 8
0
def adaptivek_search_cost_snopt(x):
    x = x.reshape(-1, 1)
    folder = folder_path()
    var_opt = io.loadmat(folder + "/opt_info.mat")

    n = var_opt['n'][0, 0]
    xc = var_opt['xc']
    R2 = var_opt['R2'][0, 0]
    y0 = var_opt['y0'][0, 0]
    nF = var_opt['nF'][0, 0]
    A = var_opt['A']
    y_safe = var_opt['y_safe']
    L_safe = var_opt['L_safe'][0, 0]

    # Initialize the output F and G.
    F = np.zeros(nF)

    method = var_opt['inter_par_method'][0]
    inter_par = interpolation.Inter_par(method=method)
    inter_par.w = var_opt['inter_par_w']
    inter_par.v = var_opt['inter_par_v']
    inter_par.xi = var_opt['inter_par_xi']

    p = interpolation.interpolate_val(x, inter_par)
    e = R2 - np.linalg.norm(x - xc)**2
    gp = interpolation.interpolate_grad(x, inter_par)
    ge = -2 * (x - xc)

    de = (1e-10 if abs(p - y0) < 1e-10 else p - y0)

    F[0] = -e / de  # K0 = 0 because only at 1st iteration we only have 1 function evaluation.
    val, idx, x_nn = Utils.mindis(x, inter_par.xi)
    F[-1] = y_safe[idx] - L_safe * np.linalg.norm(x - x_nn)

    if n > 1:  # nD data has n+1 simplex bounds.
        F[1:-1] = (np.dot(
            A, x)).T[0]  # broadcast input array from (3,1) into shape (3).

    DM = -ge / de + e * gp / de**2
    G = np.hstack(
        (DM.flatten(),
         (-L_safe * (x - x_nn) / np.linalg.norm(x - x_nn)).flatten()))

    return F, G
Exemplo n.º 9
0
def lorenz_noise_eval(x, t):
    h = 0.001
    ROOT = os.getcwd()
    file_name = 'points.mat'
    file_path = os.path.join(ROOT, file_name)

    data = io.loadmat(file_path)
    xE = data['xE']
    index = Utils.mindis(x, xE)[1]

    points_eval_data_path = os.path.join(ROOT,
                                         'AllPoints/pt' + str(index) + '.mat')
    points_eval_data = io.loadmat(points_eval_data_path)
    zs = points_eval_data['zs'][0]

    length = int(min((t / h), 1000))
    xx = uq.data_moving_average(zs, length)
    sig = np.sqrt(uq.stationary_statistical_learning_reduced(xx, 18)[0])
    return sig
Exemplo n.º 10
0
    def initial_calc1D(self, adogs):
        """
        Plot the initial objective function together with the uncertainty of 1D parameter space.
        :return:
        """

        adogs.func_prior_xE = np.linspace(adogs.physical_lb[0],
                                          adogs.physical_ub[0], self.size)
        adogs.func_prior_yE = np.zeros(adogs.func_prior_xE.shape[0])
        adogs.func_prior_sigma = np.zeros(adogs.func_prior_xE.shape[0])
        for i in range(self.size):
            adogs.func_prior_yE[i] = adogs.truth_eval(adogs.func_prior_xE[i],
                                                      adogs.T0)
            adogs.func_prior_sigma[i] = adogs.sigma_eval(
                adogs.func_prior_xE[i], adogs.T0) * 2

        # For the evaluated data point, the uncertainty has been reduced
        for i in range(adogs.xE.shape[0]):
            val, idx, xmin = Utils.mindis(adogs.xE[:, i], adogs.func_prior_xE)
            if val < 1e-10:
                adogs.func_prior_sigma[idx] = adogs.sigma[i]
Exemplo n.º 11
0
def lorenz_func_eval(x, t):
    h = 0.001
    ROOT = os.getcwd()
    file_name = 'points.mat'
    file_path = os.path.join(ROOT, file_name)
    if not os.path.exists(file_path):
        # First function evaluation, create data points and save it in file
        data = {'xE': x}
        index = 0
        type = 'identify'

        io.savemat(file_path, data)

    else:
        data = io.loadmat(file_path)
        xE = data['xE']
        val, idx, _ = Utils.mindis(x, xE)
        if val < 1e-6:
            # x has already been evaluated
            index = idx
            type = 'additional'
        else:
            index = xE.shape[1]
            type = 'identify'

            xE = np.hstack((xE, x))
            data = {'xE': xE}

            io.savemat(file_path, data)

    l = lorenz.Lorenz(x, t, h, 23.57, index, type)
    l.lorenz_eval()

    # J, sig = l.main()
    # return J, sig

    return l.J
Exemplo n.º 12
0
    def constant_surrogate_solver(self):
        '''
        Surrogate solver using constant K algorithm iteratively perform additional sampling/ mesh refinement/
        identifying sampling.
        :return:
        '''
        self.iter += 1

        self.K0 = np.ptp(self.yE, axis=0)
        self.inter_par = interpolation.InterParams(self.xE)
        self.yp = self.inter_par.regressionparameterization(
            self.yE, self.sigma)
        # Calculate the discrete function.

        self.sd = np.amin(
            (self.yp, 2 * self.yE - self.yp), 0) - self.L * self.sigma
        ind_min = np.argmin(self.yp)

        self.yd = np.amin(self.sd)
        self.index_min_yd = np.argmin(self.sd)
        self.xd = np.copy(self.xE[:, self.index_min_yd].reshape(-1, 1))

        self.yu = np.zeros(self.xU.shape[1])
        if self.xU.shape[1] != 0:
            for ii in range(self.xU.shape[1]):
                self.yu[ii] = self.discrete_function_evaluation(self.xU[:, ii])
        else:
            pass

        if self.xU.shape[1] != 0 and np.amin(self.yu) < np.min(self.yp):
            ind = np.argmin(self.yu)
            self.xc = np.copy(self.xU[:, ind].reshape(-1, 1))
            self.yc = -np.inf
            self.xU = scipy.delete(self.xU, ind, 1)
        else:
            while 1:
                xs, ind_min = cartesian_grid.add_sup(self.xE, self.xU, ind_min)
                xc, self.yc, result = constantK.tringulation_search_bound_constantK(
                    self.inter_par, xs, self.K * self.K0, ind_min)
                if self.inter_par.inter_val(xc) < min(self.yp):
                    self.xc = np.round(xc * self.ms) / self.ms
                    break
                else:
                    self.xc = np.round(xc * self.ms) / self.ms
                    if Utils.mindis(self.xc, self.xE)[0] < 1e-6:
                        break
                    self.xE, self.xU, success, newadd = cartesian_grid.points_neighbers_find(
                        self.xc, self.xE, self.xU, self.Bin, self.Ain)
                    if success == 1:
                        break
                    else:
                        self.yu = np.hstack(
                            (self.yu,
                             self.discrete_function_evaluation(self.xc)))
                if self.xU.shape[1] != 0 and np.amin(self.yu) < np.min(
                        self.yp):
                    xc_discrete = self.discrete_function_evaluation(self.xc)
                    if np.amin(self.yu) < xc_discrete:
                        ind = np.argmin(self.yu)
                        self.xc = np.copy(self.xU[:, ind].reshape(-1, 1))
                        self.yc = -np.inf
                        self.xU = scipy.delete(self.xU, ind, 1)

        if self.yd < self.yc:
            self.iter_type = 'sdmin'
            self.T[self.index_min_yd] += self.dt
            self.yE[self.index_min_yd] = self.func_eval(
                self.xd, self.T[self.index_min_yd])
            self.sigma[self.index_min_yd] = self.sigma_eval(
                self.xd, self.T[self.index_min_yd])
            self.iteration_summary_matrix[self.iter] = {
                'x': self.xd.tolist(),
                'y': self.yE[self.index_min_yd],
                'T': self.T[self.index_min_yd],
                'sig': self.sigma[self.index_min_yd]
            }
            if self.T[self.index_min_yd] >= self.Tmax:
                # Function evaluation has reached the limit, refine the mesh
                # TODO refine the mesh here??????
                # tODO or, directly goes to eval xc min?
                # TODO cuz xcmin is the initial evaluation, not expensive
                self.Tmax_reached = True
            else:
                self.Tmax_reached = False

        else:
            if Utils.mindis(self.xc, self.xE)[0] < 1e-6:
                self.iter_type = 'refine'
                self.K *= 2
                self.ms *= 2
                self.L += self.L0

            else:
                self.iter_type = 'scmin'
                self.T = np.hstack((self.T, self.T0))
                self.xE = np.hstack((self.xE, self.xc))
                self.yE = np.hstack((self.yE, self.func_eval(self.xc,
                                                             self.T0)))
                self.sigma = np.hstack(
                    (self.sigma, self.sigma_eval(self.xc, self.T0)))
                self.iteration_summary_matrix[self.iter] = {
                    'x': self.xc.tolist(),
                    'y': self.yE[-1],
                    'T': self.T0,
                    'sig': self.sigma[-1]
                }

        if self.save_fig:
            self.iter_plot(self)
        if self.iter_summary:
            self.plot.summary_display(self)
Exemplo n.º 13
0
interpolation_plot = 0
subplot_plot = 0
store_plot = 1  # The indicator to store ploting results as png.
nff = 1  # Number of experiments

# Algorithm choice:
sc = "AdaptiveK"  # The type of continuous search function
alg_name = 'DDOGS/'

# Calculate the Initial trinagulation points
num_iter = 0  # Represents how many iteration the algorithm goes
Nm = 8  # Initial mesh grid size
L_refine = 0  # Initial refinement sign

# Truth function
fun, lb, ub, y0, xmin, fname = Utils.test_fun(fun_arg, n)
func_eval = partial(Utils.fun_eval, fun, lb, ub)
# safe constraints
safe_fun, lb, ub, safe_name, L_safe = Utils.test_safe_fun(safe_fun_arg, n)
safe_eval = partial(Utils.fun_eval, safe_fun, lb, ub)

xU = Utils.bounds(np.zeros([n, 1]), np.ones([n, 1]), n)
Ain = np.concatenate((np.identity(n), -np.identity(n)), axis=0)
Bin = np.concatenate((np.ones((n, 1)), np.zeros((n, 1))), axis=0)

regret = np.zeros((nff, iter_max))
estimate = np.zeros((nff, iter_max))
datalength = np.zeros((nff, iter_max))
mesh = np.zeros((nff, iter_max))

for ff in range(nff):
Exemplo n.º 14
0
    def __init__(self,
                 bounds,
                 func_eval,
                 noise_eval,
                 truth_eval,
                 options,
                 A=None,
                 b=None):
        """
        Alpha DOGS is an efficient optimization algorithm for time-averaged statistics.
        :param bounds           :   The physical bounds of the input for the test problem,
                                    e.g. lower bound = [0, 0, 0] while upper bound = [1, 1, 1] then
                                    bnds = np.hstack((np.zeros((3,1)), np.ones((3,1))))

        :param func_eval        :   The objective function

        :param noise_eval       :   The function for noise evaluation

        :param truth_eval       :   The function to evaluate the truth values

        :param A                :   The linear constraints of parameter space

        :param b                :   The linear constraints of parameter space

        :param options          :   The options for alphaDOGS
        """
        # n: The dimension of input parameter space
        self.n = bounds.shape[0]
        # physical lb & ub: Normalize the physical bounds
        self.physical_lb = bounds[:, 0].reshape(-1, 1)
        self.physical_ub = bounds[:, 1].reshape(-1, 1)
        # lb & ub: The normalized search bounds
        self.lb = np.zeros((self.n, 1))
        self.ub = np.ones((self.n, 1))

        # ms: The mesh size for each iteration. This is the initial definition.
        self.initial_mesh_size = options.get_option('Initial mesh size')
        self.ms = 2**self.initial_mesh_size
        self.num_mesh_refine = options.get_option('Number of mesh refinement')
        self.max_mesh_size = 2**(self.initial_mesh_size + self.num_mesh_refine)

        self.iter = 0

        # Define the surrogate model
        if options.get_option('Constant surrogate') and options.get_option(
                'Adaptive surrogate'):
            raise ValueError(
                'Constant and Adaptive surrogate both activated. Set one to False then rerun code.'
            )
        elif not options.get_option(
                'Constant surrogate') and not options.get_option(
                    'Adaptive surrogate'):
            raise ValueError(
                'Constant and Adaptive surrogate both inactivated. Set one to True then rerun code.'
            )
        elif options.get_option('Constant surrogate'):
            self.surrogate_type = 'c'
        elif options.get_option('Adaptive surrogate'):
            self.surrogate_type = 'a'
        else:
            pass

        if self.surrogate_type == 'c':
            # Define the parameters for discrete and continuous constant search function
            self.L = options.get_option('Constant L')
            self.L0 = self.L
            self.K = options.get_option('Constant K')

        elif self.surrogate_type == 'a':
            self.y0 = options.get_option('Target value')

        # Define the linear constraints, Ax <= b. if A and b are None type, set them to be the box domain constraints.
        if (A and b) is None:
            self.Ain = np.concatenate(
                (np.identity(self.n), -np.identity(self.n)), axis=0)
            self.Bin = np.concatenate((np.ones(
                (self.n, 1)), np.zeros((self.n, 1))),
                                      axis=0)
        else:
            pass

        # Define the statistics for time length
        self.T0 = options.get_option('Initial time length')
        self.dt = options.get_option('Incremental time step')
        self.eval_times = options.get_option('Maximum evaluation times')
        self.Tmax = self.T0 + self.eval_times * self.dt
        self.Tmax_reached = None

        if options.get_option('Scipy solver') and options.get_option(
                'Snopt solver'):
            raise ValueError('More than one optimization solver specified!')
        elif not options.get_option('Scipy solver') and not options.get_option(
                'Snopt solver'):
            raise ValueError('No optimization solver specified!')
        elif options.get_option('Scipy solver'):
            self.solver_type = 'scipy'
        elif options.get_option('Snopt solver'):
            self.solver_type = 'snopy'
        else:
            pass

        # Initialize the function evaluation, noise sigma evaluation and truth function evaluation.
        # capsulate those three functions with physical bounds
        self.func_eval = partial(Utils.fun_eval, func_eval, self.physical_lb,
                                 self.physical_ub)
        self.sigma_eval = partial(Utils.fun_eval, noise_eval, self.physical_lb,
                                  self.physical_ub)
        self.truth_eval = partial(Utils.fun_eval, truth_eval, self.physical_lb,
                                  self.physical_ub)

        # Define the global optimum and its values
        if options.get_option('Global minimizer known'):
            self.xmin = Utils.normalize_bounds(
                options.get_option('Global minimizer'), self.physical_lb,
                self.physical_ub)
            self.y0 = options.get_option('Target value')
        else:
            self.xmin = None
            self.y0 = None

        # Define the iteration type for each sampling iteration.
        self.iter_type = None

        # Define the initial sites and their function evaluations
        if options.get_option('Initial sites known'):
            physical_initial_sites = options.get_option('Initial sites')
            # Normalize the bound
            self.xE = Utils.normalize_bounds(physical_initial_sites,
                                             self.physical_lb,
                                             self.physical_ub)
        else:
            self.xE = Utils.random_initial(self.n, 2 * self.n, self.ms,
                                           self.Ain, self.Bin, self.xU)

        if options.get_option('Initial function values') is not None:
            self.yE = options.get_option('Initial function values')
            self.T = self.T0 * np.ones(self.xE.shape[1], dtype=float)
            self.sigma = options.get_option('Initial funtion noise')
        else:
            # Compute the function values, time length, and noise level at initial sites
            self.yE = np.zeros(self.xE.shape[1])
            self.T = self.T0 * np.ones(self.xE.shape[1], dtype=float)
            self.sigma = np.zeros(self.xE.shape[1])

            for i in range(2 * self.n):
                self.yE[i] = self.func_eval(self.xE[:, i], self.T[i])
                self.sigma[i] = self.sigma_eval(self.xE[:, i], self.T0)

        self.iteration_summary_matrix = {}
        # Define the initial support points
        self.xU = Utils.bounds(self.lb, self.ub, self.n)
        self.xU = Utils.unique_support_points(self.xU, self.xE)
        self.yu = None

        self.K0 = np.ptp(self.yE, axis=0)
        # Define the interpolation
        self.inter_par = None
        self.yp = None

        # Define the discrete search function
        self.sd = None

        # Define the minimizer of continuous search function, parameter to be evaluated, xc & yc.
        self.xc = None
        self.yc = None

        # Define the minimizer of discrete search function
        self.xd = None
        self.yd = None
        self.index_min_yd = None

        # Although it is stochastic, just display the behavior instead of the actual data to show the trend.
        # Define the name of directory to store the figures
        self.algorithm_name = options.solverName

        #  ==== Plot section here ====
        self.plot = plot.PlotClass()

        # Define the parameter to save image or no, and what format to save for images
        self.save_fig = options.get_option('Plot saver')
        self.fig_format = options.get_option('Figure format')

        # Generate the folder path
        self.func_path = options.get_option(
            'Objective function name')  # Function folder, e.g. Lorenz
        self.current_path = None  # Directory path
        self.plot_folder = None  # Plot storage folder
        self.folder_path_generator()  # Determine the folder paths above
        self.func_name = options.get_option(
            'Objective function name'
        )  # Define the name of the function called.

        # All the prior function values should be provided by user, instead of solver calculating those values.
        # Generate the plot of test function
        self.func_initial_prior = True
        # The objective function values are stored in func_prior_yE
        # for the future iteration, just change the point of func_prior_sigma that is close to the evaluated point
        self.func_prior_xE_2DX = None
        self.func_prior_xE_2DY = None
        self.func_prior_xE_2DZ = None

        if options.get_option('Function prior file path') is not None:
            self.func_prior_file_name = options.get_option(
                'Function prior file path')
            data = io.loadmat(self.func_prior_file_name)
            # The prior data must have the following keyword
            self.func_prior_xE = data['x']
            self.func_prior_yE = data['y'][0]
            self.func_prior_sigma = data['sigma'][0] * 2
            if self.n == 1:
                # Define the range of plot in y-axis
                self.plot_ylow = np.min(self.func_prior_yE) * 2
                self.plot_yupp = np.max(self.func_prior_yE) * 2

        else:
            self.func_prior_file_name = None
            if options.get_option('Function evaluation cheap') and self.n < 3:
                if self.n == 1:
                    self.plot.initial_calc1D(self)
                elif self.n == 2:
                    self.plot.initial_calc2D(self)
                else:
                    pass
                if self.n == 1:
                    # Define the range of plot in y-axis
                    self.plot_ylow = np.min(self.func_prior_yE) * 2
                    self.plot_yupp = np.max(self.func_prior_yE) * 2

            else:
                self.func_initial_prior = False
                self.func_prior_xE = None
                self.func_prior_yE = None
                # Define the range of plot in y-axis
                self.plot_ylow = np.min(self.yE) * 2
                self.plot_yupp = np.max(self.yE) * 2

                print(
                    'Function evaluation is expensive and no file that contains prior function values information '
                    'is found.')
                if self.n >= 3:
                    print(
                        'Parameter space dimenion > 3, the plot for each iteration is unavailable.'
                    )

        if self.save_fig and self.func_initial_prior:
            if self.n == 1:
                self.initial_plot = self.plot.initial_plot1D
                self.iter_plot = self.plot.plot1D
            elif self.n == 2:
                self.initial_plot = self.plot.initial_plot2D
                self.iter_plot = self.plot.plot2D
            else:
                self.initial_plot = None
                print(
                    "Parameter space higher than 2, set 'Plot saver' to be False."
                )
            self.initial_plot(self)

        self.iter_summary = options.get_option('Iteration summary')
        self.optm_summary = options.get_option('Optimization summary')
Exemplo n.º 15
0
    def continuous_search_plot1D(self, adogs):
        '''
        Plot the continuous search function.
        :return:
        '''
        xU = Utils.bounds(adogs.lb, adogs.ub, adogs.n)
        if adogs.iter_type == 'scmin' and Utils.mindis(adogs.xc, xU)[0] > 1e-6:
            xi = np.hstack((adogs.xE[:, :-1], adogs.xU))
        else:
            xi = np.hstack((adogs.xE, adogs.xU))

        sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
        tri = np.zeros((xi.shape[1] - 1, 2))
        tri[:, 0] = sx[:xi.shape[1] - 1]
        tri[:, 1] = sx[1:]
        tri = tri.astype(np.int32)

        num_plot_points = 2000
        xe_plot = np.zeros((tri.shape[0], num_plot_points))
        e_plot = np.zeros((tri.shape[0], num_plot_points))
        sc_plot = np.zeros((tri.shape[0], num_plot_points))

        for ii in range(len(tri)):
            simplex_range = np.copy(xi[:, tri[ii, :]])

            # Discretized mesh grid on x direction in one simplex
            x = np.linspace(simplex_range[0, 0], simplex_range[0, 1],
                            num_plot_points)

            # Circumradius and circumcenter for current simplex
            R2, xc = Utils.circhyp(xi[:, tri[ii, :]], adogs.n)

            for jj in range(len(x)):
                # Interpolation p(x)
                p = adogs.inter_par.inter_val(x[jj])

                # Uncertainty function e(x)
                e_plot[ii, jj] = (R2 - np.linalg.norm(x[jj] - xc)**2)

                # Continuous search function s(x)
                sc_plot[ii, jj] = p - adogs.K * adogs.K0 * e_plot[ii, jj]

            xe_plot[ii, :] = np.copy(x)

        for i in range(len(tri)):
            # Plot the uncertainty function e(x)
            # plt.plot(xe_plot[i, :], e_plot[i, :] - 5.5, c='g', label=r'$e(x)$')
            # Plot the continuous search function sc(x)
            plt.plot(xe_plot[i, :],
                     sc_plot[i, :],
                     'r--',
                     zorder=20,
                     label=r'$S_c(x)$')

        yc_min = sc_plot.flat[np.abs(xe_plot - adogs.xc).argmin()]
        plt.scatter(adogs.xc,
                    yc_min,
                    c=(1, 0.769, 0.122),
                    marker='D',
                    zorder=15,
                    label=r'min $S_c(x)$')
Exemplo n.º 16
0
def continuous_search_1d_plot(xE, fun_eval):
    '''
    Given evaluated points set xE, and the objective function. Plot the
    interpolation, uncertainty function and continuous search function.
    :param xE:          evaluated points set xE
    :param fun_eval:    obj function
    :return:
    '''
    N = xE.shape[1]
    yE = np.zeros(N)
    for i in range(N):
        yE[i] = fun_eval(xE[:, i])
    inter_par = interpolation.Inter_par(method='NPS')
    inter_par, _ = interpolation.interpolateparameterization(xE, yE, inter_par)

    x = np.linspace(0, 1, 1000)
    y, yp = np.zeros(x.shape), np.zeros(x.shape)

    for i in range(x.shape[0]):
        y[i] = fun_eval(x[i])
        yp[i] = interpolation.interpolate_val(x[i], inter_par)

    xi = np.copy(xE)
    sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
    tri = np.zeros((xi.shape[1] - 1, 2))
    tri[:, 0] = sx[:xi.shape[1] - 1]
    tri[:, 1] = sx[1:]
    tri = tri.astype(np.int32)

    xe = np.copy(xi)
    xe_plot = np.zeros((tri.shape[0], 2000))
    e_plot = np.zeros((tri.shape[0], 2000))
    sc_plot = np.zeros((tri.shape[0], 2000))

    n = xE.shape[0]
    K = 3
    for ii in range(len(tri)):
        temp_x = np.copy(xi[:, tri[ii, :]])
        x_ = np.linspace(temp_x[0, 0], temp_x[0, 1], 2000)
        temp_Sc = np.zeros(len(x_))
        temp_e = np.zeros(len(x_))
        p = np.zeros(len(x_))
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        for jj in range(len(x_)):
            p[jj] = interpolation.interpolate_val(x_[jj], inter_par)
            temp_e[jj] = (R2 - np.linalg.norm(x_[jj] - xc)**2)
            temp_Sc[jj] = p[jj] - K * temp_e[jj]

        e_plot[ii, :] = temp_e
        xe_plot[ii, :] = x_
        sc_plot[ii, :] = temp_Sc

    sc_min = np.min(sc_plot, axis=1)
    index_r = np.argmin(sc_min)
    index_c = np.argmin(sc_plot[index_r, :])
    sc_min_x = xe_plot[index_r, index_c]
    sc_min = min(np.min(sc_plot, axis=1))

    plt.figure()
    plt.plot(x, y, c='k')
    plt.plot(x, yp, c='b')
    for i in range(len(tri)):
        plt.plot(xe_plot[i, :], sc_plot[i, :], c='r')
        plt.plot(xe_plot[i, :], 3 * e_plot[i, :] - 2.3, c='g')
    plt.scatter(xE, yE, c='b', marker='s')
    plt.scatter(sc_min_x, sc_min, c='r', marker='s')
    plt.ylim(-2.5, 2)
    # plt.gca().axes.get_yaxis().set_visible(False)
    plt.show()
    return
Exemplo n.º 17
0
def safe_continuous_constantK_search_1d_plot(xE, xU, fun_eval, safe_eval,
                                             L_safe, K, xc_min, Nm):
    '''
    Given evaluated points set xE, and the objective function. Plot the
    interpolation, uncertainty function and continuous search function.
    :param xE:
    :param xU:
    :param fun_eval:
    :param safe_eval:
    :param L_safe:
    :param K:
    :param xc_min:
    :param Nm:
    :return:
    '''
    N = xE.shape[1]
    yE = np.zeros(N)
    for i in range(N):
        yE[i] = fun_eval(xE[:, i])
    inter_par = interpolation.Inter_par(method='NPS')
    inter_par, _ = interpolation.interpolateparameterization(xE, yE, inter_par)

    x = np.linspace(0, 1, 1000)
    y, yp = np.zeros(x.shape), np.zeros(x.shape)

    for i in range(x.shape[0]):
        y[i] = fun_eval(x[i])
        yp[i] = interpolation.interpolate_val(x[i], inter_par)

    xi = np.hstack((xE, xU))
    sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
    tri = np.zeros((xi.shape[1] - 1, 2))
    tri[:, 0] = sx[:xi.shape[1] - 1]
    tri[:, 1] = sx[1:]
    tri = tri.astype(np.int32)

    xe_plot = np.zeros((tri.shape[0], 2000))
    e_plot = np.zeros((tri.shape[0], 2000))
    sc_plot = np.zeros((tri.shape[0], 2000))

    n = xE.shape[0]
    for ii in range(len(tri)):
        temp_x = np.copy(xi[:, tri[ii, :]])
        simplex = xi[:, tri[ii, :]]

        # Determine if the boundary corner exists or not in simplex
        exist = 0
        for i in range(simplex.shape[1]):
            vertice = simplex[:, i].reshape(-1, 1)
            val, _, _ = Utils.mindis(vertice, xE)
            if val == 0:
                pass
            else:
                exist = 1
                break

        x_ = np.linspace(temp_x[0, 0], temp_x[0, 1], 2000)
        temp_Sc = np.zeros(len(x_))
        temp_e = np.zeros(len(x_))
        p = np.zeros(len(x_))
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        for jj in range(len(x_)):
            p[jj] = interpolation.interpolate_val(x_[jj], inter_par)

            if exist == 0:
                temp_e[jj] = (R2 - np.linalg.norm(x_[jj] - xc)**2)
            else:
                val, _, _ = Utils.mindis(x_[jj], xE)
                temp_e[jj] = val**(2)
            # val, idx, vertex = Utils.mindis(x_[jj], xE)
            # c = 0.1
            # temp_e[jj] = (val + c) ** (1/2) - c ** (1/2)
            temp_Sc[jj] = p[jj] - K * temp_e[jj]

        e_plot[ii, :] = temp_e
        xe_plot[ii, :] = x_
        sc_plot[ii, :] = temp_Sc

    # The minimizer of continuous search must be subject to safe constraints.
    # sc_min = np.min(sc_plot, axis=1)
    # index_r = np.argmin(sc_min)
    # index_c = np.argmin(sc_plot[index_r, :])
    # sc_min_x = xe_plot[index_r, index_c]
    # sc_min = min(np.min(sc_plot, axis=1))

    safe_plot = {}
    ## plot the safe region
    for ii in range(xE.shape[1]):
        y_safe = safe_eval(xE[:, ii])

        safe_index = []
        y_safe_plot = []
        safe_eval_lip = lambda x: y_safe - L_safe * np.sqrt(
            np.dot((x - xE[:, ii]).T, x - xE[:, ii]))
        for i in range(x.shape[0]):
            safe_val = safe_eval_lip(x[i])
            y_safe_plot.append(safe_val[0])
            if safe_val > 0:
                safe_index.append(i)
        name = str(ii)
        safe_plot[name] = [safe_index, y_safe_plot]

    # ==================  First plot =================
    fig = plt.figure()
    plt.subplot(2, 1, 1)
    # plot the essentials for DeltaDOGS
    plt.plot(x, y, c='k')
    plt.plot(x, yp, c='b')

    for i in range(len(tri)):

        if i == 0 or i == len(tri) - 1:
            amplify_factor = 3
        else:
            amplify_factor = 50

        plt.plot(xe_plot[i, :], sc_plot[i, :], c='r')
        plt.plot(xe_plot[i, :], amplify_factor * e_plot[i, :] - 5.5, c='g')
    plt.scatter(xE, yE, c='b', marker='s')

    yc_min = sc_plot.flat[np.abs(xe_plot - xc_min).argmin()]
    plt.scatter(xc_min, yc_min, c='r', marker='^')

    # plot the safe region in cyan
    xlow, xupp = safe_region_plot(x, safe_plot)
    y_vertical = np.linspace(-2, 2, 100)
    xlow_y_vertical = xlow * np.ones(100)
    xupp_y_vertical = xupp * np.ones(100)
    plt.plot(xlow_y_vertical, y_vertical, color='cyan', linestyle='--')
    plt.plot(xupp_y_vertical, y_vertical, color='cyan', linestyle='--')

    plt.ylim(-6.5, 3.5)
    plt.gca().axes.get_yaxis().set_visible(False)

    # ==================  Second plot =================
    plt.subplot(2, 1, 2)

    y_safe_all = np.zeros(x.shape)
    for i in range(x.shape[0]):
        y_safe_all[i] = safe_eval(x[i])
    plt.plot(x, y_safe_all)
    zero_indicator = np.zeros(x.shape)
    plt.plot(x, zero_indicator, c='k')

    x_scatter = np.hstack((xE, xc_min))
    y_scatter = np.zeros(x_scatter.shape[1])
    for i in range(x_scatter.shape[1]):
        ind = np.argmin(np.abs(x_scatter[:, i] - x))
        y_scatter[i] = y_safe_all[ind]

    plt.scatter(x_scatter[:, :-1][0], y_scatter[:-1], c='b', marker='s')
    plt.scatter(x_scatter[:, -1], y_scatter[-1], c='r', marker='^')

    # plot the safe region
    xlow, xupp = safe_region_plot(x, safe_plot)
    low_idx = np.argmin(np.abs(xlow - x))
    upp_idx = np.argmin(np.abs(xupp - x))
    ylow_vertical = np.linspace(y_safe_all[low_idx], 2, 100)
    yupp_vertical = np.linspace(y_safe_all[upp_idx], 2, 100)
    xlow_y_vertical = xlow * np.ones(100)
    xupp_y_vertical = xupp * np.ones(100)
    plt.plot(xlow_y_vertical, ylow_vertical, color='cyan', linestyle='--')
    plt.plot(xupp_y_vertical, yupp_vertical, color='cyan', linestyle='--')
    plt.ylim(-1, 2.2)
    plt.gca().axes.get_yaxis().set_visible(False)

    # plt.show()
    current_path = os.path.dirname(
        os.path.abspath(inspect.getfile(inspect.currentframe())))
    plot_folder = current_path[:-5] + "/plot/DDOGS/0"

    num_iter = xE.shape[1] - 1 + math.log(Nm / 8, 2)
    plt.savefig(plot_folder + '/pic' + str(int(num_iter)) + '.png',
                format='png',
                dpi=250)
    plt.close(fig)
    return
Exemplo n.º 18
0
def triangulation_search_bound_snopt(inter_par, xi, y0, ind_min, y_safe,
                                     L_safe):
    # reddir is a vector
    inf = 1e+20
    n = xi.shape[0]  # The dimension of the reduced model.

    # 0: Build up the Delaunay triangulation based on reduced subspace.
    if n == 1:
        sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
        tri = np.zeros((xi.shape[1] - 1, 2))
        tri[:, 0] = sx[:xi.shape[1] - 1]
        tri[:, 1] = sx[1:]
        tri = tri.astype(np.int32)
    else:
        options = 'Qt Qbb Qc' if n <= 3 else 'Qt Qbb Qc Qx'
        tri = Delaunay(xi.T, qhull_options=options).simplices
        keep = np.ones(len(tri), dtype=bool)
        for i, t in enumerate(tri):
            if abs(np.linalg.det(np.hstack(
                (xi.T[t], np.ones([1, n + 1]).T)))) < 1E-15:
                keep[i] = False  # Point is coplanar, we don't want to keep it
        tri = tri[keep]
    # Sc contains the continuous search function value of the center of each Delaunay simplex

    # 1: Identify the minimizer of adaptive K continuous search function
    Sc = np.zeros([np.shape(tri)[0]])
    Scl = np.zeros([np.shape(tri)[0]])
    for ii in range(np.shape(tri)[0]):
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        if R2 < inf:
            # initialize with body center of each simplex
            x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
            Sc[ii] = (interpolation.interpolate_val(x, inter_par) -
                      y0) / (R2 - np.linalg.norm(x - xc)**2)
            if np.sum(ind_min == tri[ii, :]):
                Scl[ii] = np.copy(Sc[ii])
            else:
                Scl[ii] = inf
        else:
            Scl[ii] = inf
            Sc[ii] = inf

    if np.min(Sc) < 0:
        func = 'p'
        # The minimum of Sc is negative, minimize p(x) instead.
        Scp = np.zeros(tri.shape[0])
        for ii in range(tri.shape[0]):
            x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
            Scp[ii] = interpolation.interpolate_val(x, inter_par)
        # Globally minimize p(x)
        ind = np.argmin(Scp)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
        xm, ym = adaptiveK_p_snopt_min(x, inter_par, y_safe, L_safe)
        result = 'glob'
    else:
        func = 'sc'
        # Global one, the minimum of Sc has the minimum value of all circumcenters.

        ind = np.argmin(Sc)
        R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
        # x is the center of this simplex
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))

        # First find minimizer xr on reduced model, then find the 2D point corresponding to xr. Constrained optm.
        A_simplex, b_simplex = Utils.search_simplex_bounds(xi[:, tri[ind, :]])
        lb_simplex = np.min(xi[:, tri[ind, :]], axis=1)
        ub_simplex = np.max(xi[:, tri[ind, :]], axis=1)

        xm, ym = adaptiveK_search_snopt_min(x, inter_par, xc, R2, y0, K0,
                                            A_simplex, b_simplex, lb_simplex,
                                            ub_simplex, y_safe, L_safe)
        # Local one

        ind = np.argmin(Scl)
        R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))

        A_simplex, b_simplex = Utils.search_simplex_bounds(xi[:, tri[ind, :]])
        lb_simplex = np.min(xi[:, tri[ind, :]], axis=1)
        ub_simplex = np.max(xi[:, tri[ind, :]], axis=1)
        xml, yml = adaptiveK_search_snopt_min(x, inter_par, xc, R2, y0, K0,
                                              A_simplex, b_simplex, lb_simplex,
                                              ub_simplex, y_safe, L_safe)
        if yml < ym:
            xm = np.copy(xml)
            ym = np.copy(yml)
            result = 'local'
        else:
            result = 'glob'
    return xm, ym, result, func
Exemplo n.º 19
0
def tringulation_search_bound(inter_par, xi, y0, K0, ind_min):
    inf = 1e+20
    n = xi.shape[0]
    xm, ym = interpolation.inter_min(xi[:, ind_min], inter_par)
    sc_min = inf
    # cse=1
    if ym > y0:
        ym = inf
    # cse =2
    # construct Deluanay tringulation
    if n == 1:
        sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
        tri = np.zeros((xi.shape[1] - 1, 2))
        tri[:, 0] = sx[:xi.shape[1] - 1]
        tri[:, 1] = sx[1:]
        tri = tri.astype(np.int32)
    else:
        options = 'Qt Qbb Qc' if n <= 3 else 'Qt Qbb Qc Qx'
        tri = Delaunay(xi.T, qhull_options=options).simplices
        keep = np.ones(len(tri), dtype=bool)
        for i, t in enumerate(tri):
            if abs(np.linalg.det(np.hstack(
                (xi.T[t], np.ones([1, n + 1]).T)))) < 1E-15:
                keep[i] = False  # Point is coplanar, we don't want to keep it
        tri = tri[keep]

    Sc = np.zeros([np.shape(tri)[0]])
    Scl = np.zeros([np.shape(tri)[0]])
    for ii in range(np.shape(tri)[0]):
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        # if R2 != np.inf:
        if R2 < inf:
            # initialze with body center of each simplex
            x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
            Sc[ii] = (interpolation.interpolate_val(x, inter_par) -
                      y0) / (R2 - np.linalg.norm(x - xc)**2)
            if np.sum(ind_min == tri[ii, :]):
                Scl[ii] = np.copy(Sc[ii])
            else:
                Scl[ii] = inf
        else:
            Scl[ii] = inf
            Sc[ii] = inf

    # Global one
    if np.min(Sc) < 0:
        func = 'p'
        # The minimum of Sc is negative, minimize p(x) instead.
        Scp = np.zeros(tri.shape[0])
        Scpl = np.zeros(tri.shape[0])
        for ii in range(tri.shape[0]):
            x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
            Scp[ii] = interpolation.interpolate_val(x, inter_par)
            if np.sum(ind_min == tri[ii, :]):
                Scpl[ii] = np.copy(Scp[ii])
            else:
                Scpl[ii] = inf
        else:
            Scpl[ii] = inf
            Scp[ii] = inf
        # Globally minimize p(x)
        ind = np.argmin(Scp)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
        simplex_bnds = Utils.search_bounds(xi[:, tri[ind, :]])
        xm, ym = AdaptiveK_Search_p(x, inter_par, simplex_bnds)
        # Locally minimize p(x)
        ind = np.argmin(Scpl)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
        simplex_bnds = Utils.search_bounds(xi[:, tri[ind, :]])
        xml, yml = AdaptiveK_Search_p(x, inter_par, simplex_bnds)

    else:
        func = 'sc'
        # Minimize sc(x).
        # Global one, the minimum of Sc has the minimum value of all circumcenters.
        ind = np.argmin(Sc)
        R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
        simplex_bnds = Utils.search_bounds(xi[:, tri[ind, :]])
        xm, ym = Adaptive_K_Search(x, inter_par, xc, R2, y0, K0, simplex_bnds)
        # Local one
        ind = np.argmin(Scl)
        R2, xc = Utils.circhyp(xi[:, tri[ind, :]], n)
        x = np.dot(xi[:, tri[ind, :]], np.ones([n + 1, 1]) / (n + 1))
        simplex_bnds = Utils.search_bounds(xi[:, tri[ind, :]])
        xml, yml = Adaptive_K_Search(x, inter_par, xc, R2, y0, K0,
                                     simplex_bnds)
    if yml < ym:
        xm = np.copy(xml)
        ym = np.copy(yml)
        result = 'local'
    else:
        result = 'glob'
    xm = xm.reshape(-1, 1)
    ym = ym[0, 0]

    return xm, ym, result, func
Exemplo n.º 20
0
def vertex_find(A, b, lb, ub):
    '''
    Find the vertices of a simplex;
    Ax<b: Linear constraints;
    lb<x<ub: actual constraints;
    Attension: Do not try to include lb&ub inside A&b matrix.
    Example:
    A = np.array([[-1, 1],[1, -1]])
    b = np.array([[0.5], [0.5]])
    lb = np.zeros((2, 1))
    ub = np.ones((2, 1))
    :param A:
    :param b:
    :param lb:
    :param ub:
    :return:
    '''
    if A.shape[0] == 0 and b.shape[0] == 0:
        if len(lb) != 0 and len(ub) != 0:
            Vertex = Utils.bounds(lb, ub, len(lb))
        else:
            Vertex = []
            raise ValueError('All inputs A, b, lb and ub have dimension 0.')
    else:
        if len(lb) != 0:
            Vertex = np.matrix([[], []])
            m = A.shape[0]
            n = A.shape[1]
            if m == 0:
                Vertex = Utils.bounds(lb, ub, len(lb))
            else:
                for r in range(min(n, m) + 1):
                    from itertools import combinations
                    nlist = np.arange(1, m + 1)
                    C = np.array([list(c) for c in combinations(nlist, r)])
                    nlist2 = np.arange(1, n + 1)
                    D = np.array([list(d) for d in combinations(nlist2, n - r)])
                    if r == 0:
                        F = Utils.bounds(lb, ub, n)
                        for kk in range(F.shape[1]):
                            x = np.copy(F[:, kk]).reshape(-1, 1)
                            if np.all(np.dot(A, x) - b < 0):
                                Vertex = np.column_stack((Vertex, x))
                    else:
                        for ii in range(len(C)):
                            index_A = np.copy(C[ii])
                            v1 = np.arange(1, m + 1)
                            index_A_C = np.setdiff1d(v1, index_A)
                            A1 = np.copy(A[index_A - 1, :])
                            b1 = np.copy(b[index_A - 1])
                            for jj in range(len(D)):
                                index_B = np.copy(D[jj])
                                v2 = np.arange(1, n + 1)
                                index_B_C = np.setdiff1d(v2, index_B)
                                if len(index_B) != 0 and len(index_B_C) != 0:
                                    F = Utils.bounds(lb[index_B - 1], ub[index_B - 1], n - r)
                                    A11 = np.copy(A1[:, index_B - 1])
                                    A12 = np.copy(A1[:, index_B_C - 1])
                                    for kk in range(F.shape[1]):
                                        A11 = np.copy(A1[:, index_B - 1])
                                        A12 = np.copy(A1[:, index_B_C - 1])
                                        xd = np.linalg.lstsq(A12, b1 - np.dot(A11, F[:, kk].reshape(-1, 1)), rcond=None)[0]
                                        x = np.zeros((n, 1))
                                        x[index_B - 1] = np.copy(F[:, kk])
                                        x[index_B_C - 1] = np.copy(xd)
                                        if r == m or (np.dot(A[index_A_C - 1, :], x) - b[index_A_C - 1]).min() < 0:
                                            if (x - ub).max() < 1e-6 and (x - lb).min() > -1e-6 and Utils.mindis(x, Vertex)[0] > 1e-6:
                                                Vertex = np.column_stack((Vertex, x))
        else:
            m = A.shape[0]
            n = A.shape[1]
            from itertools import combinations
            nlist = np.arange(1, m + 1)
            C = np.array([list(c) for c in combinations(nlist, n)])
            Vertex = np.empty(shape=[n, 0])
            for ii in range(len(C)):
                index_A = np.copy(C[ii])
                v1 = np.arange(1, m + 1)
                index_A_C = np.setdiff1d(v1, index_A)
                A1 = np.copy(A[index_A - 1, :])
                b1 = np.copy(b[index_A - 1])
                A2 = np.copy(A[index_A_C - 1])
                b2 = np.copy(b[index_A_C - 1])
                x = np.linalg.lstsq(A1, b1, rcond=None)[0]
                if (np.dot(A2, x) - b2).max() < 1e-6:
                    Vertex = np.column_stack((Vertex, x))
        # cant plot Vertex directly. must transform it into np.array.
    return np.array(Vertex)
Exemplo n.º 21
0
def triangulation_search_bound_snopt(inter_par, xi, K, ind_min, y_safe,
                                     L_safe):
    # reddir is a vector
    inf = 1e+20
    n = xi.shape[0]  # The dimension of the reduced model.
    xE = inter_par.xi
    # 0: Build up the Delaunay triangulation based on reduced subspace.
    if n == 1:
        sx = sorted(range(xi.shape[1]), key=lambda x: xi[:, x])
        tri = np.zeros((xi.shape[1] - 1, 2))
        tri[:, 0] = sx[:xi.shape[1] - 1]
        tri[:, 1] = sx[1:]
        tri = tri.astype(np.int32)
    else:
        options = 'Qt Qbb Qc' if n <= 3 else 'Qt Qbb Qc Qx'
        tri = Delaunay(xi.T, qhull_options=options).simplices
        keep = np.ones(len(tri), dtype=bool)
        for i, t in enumerate(tri):
            if abs(np.linalg.det(np.hstack(
                (xi.T[t], np.ones([1, n + 1]).T)))) < 1E-15:
                keep[i] = False  # Point is coplanar, we don't want to keep it
        tri = tri[keep]
    # Sc contains the continuous search function value of the center of each Delaunay simplex

    # 1: Identify the minimizer of adaptive K continuous search function
    Sc = np.zeros([np.shape(tri)[0]])
    Scl = np.zeros([np.shape(tri)[0]])
    for ii in range(np.shape(tri)[0]):
        R2, xc = Utils.circhyp(xi[:, tri[ii, :]], n)
        if R2 < inf:
            # initialize with body center of each simplex
            x = np.dot(xi[:, tri[ii, :]], np.ones([n + 1, 1]) / (n + 1))
            exist = unevaluated_vertices_identification(xE, xi[:, tri[ii, :]])
            if exist == 0:
                Sc[ii] = interpolation.interpolate_val(
                    x, inter_par) - K * (R2 - np.linalg.norm(x - xc)**2)
            else:
                val, idx, x_nn = Utils.mindis(x, xE)
                Sc[ii] = interpolation.interpolate_val(x,
                                                       inter_par) - K * val**2

            # discrete min
            # val, idx, vertex = Utils.mindis(x, xE)
            # c = 0.1
            # e = (val + c) ** (1/2) - c ** (1/2)
            # Sc[ii] = interpolation.interpolate_val(x, inter_par) - K * e

            if np.sum(ind_min == tri[ii, :]):
                Scl[ii] = np.copy(Sc[ii])
            else:
                Scl[ii] = inf
        else:
            Scl[ii] = inf
            Sc[ii] = inf

    # Global one, the minimum of Sc has the minimum value of all circumcenters.
    ind = np.argmin(Sc)
    xm, ym = constantk_search_snopt_min(xi[:, tri[ind, :]], inter_par, K,
                                        y_safe, L_safe)

    # Local one
    ind = np.argmin(Scl)
    xml, yml = constantk_search_snopt_min(xi[:, tri[ind, :]], inter_par, K,
                                          y_safe, L_safe)
    if yml < ym:
        xm = np.copy(xml)
        ym = np.copy(yml)
        result = 'local'
    else:
        result = 'glob'
    return xm, ym, result
Exemplo n.º 22
0
def constantk_search_snopt_min(simplex, inter_par, K, y_safe, L_safe):
    '''
    The function F is composed as:  1st        - objective
                                    2nd to nth - simplex bounds
                                    n+1 th ..  - safe constraints
    :param x0        :     The mass-center of delaunay simplex
    :param inter_par :
    :param xc        :
    :param R2:
    :param y0:
    :param K0:
    :param A_simplex:
    :param b_simplex:
    :param lb_simplex:
    :param ub_simplex:
    :param y_safe:
    :param L_safe:
    :return:
    '''
    xE = inter_par.xi
    n = xE.shape[0]

    # Determine if the boundary corner exists in simplex, if boundary corner detected:
    # e(x) = || x - x' ||^2_2
    # else, e(x) is the regular uncertainty function.
    exist = unevaluated_vertices_identification(xE, simplex)

    # -------  ADD THE FOLLOWING LINE WHEN DEBUGGING --------
    # simplex = xi[:, tri[ind, :]]
    # -------  ADD THE FOLLOWING LINE WHEN DEBUGGING --------

    # Find the minimizer of the search fucntion in a simplex using SNOPT package.
    R2, xc = Utils.circhyp(simplex, n)
    # x is the center of this simplex
    x = np.dot(simplex, np.ones([n + 1, 1]) / (n + 1))

    # First find minimizer xr on reduced model, then find the 2D point corresponding to xr. Constrained optm.
    A_simplex, b_simplex = Utils.search_simplex_bounds(simplex)
    lb_simplex = np.min(simplex, axis=1)
    ub_simplex = np.max(simplex, axis=1)

    inf = 1.0e+20

    m = n + 1  # The number of constraints which is determined by the number of simplex boundaries.
    assert m == A_simplex.shape[0], 'The No. of simplex constraints is wrong'

    # TODO: multiple safe constraints in future.
    # nF: The number of problem functions in F(x), including the objective function, linear and nonlinear constraints.
    # ObjRow indicates the number of objective row in F(x).
    ObjRow = 1

    # solve for constrained minimization of safe learning within each open ball of the vertices of simplex.
    # Then choose the one with the minimum continuous function value.
    x_solver = np.empty(shape=[n, 0])
    y_solver = []

    for i in range(n + 1):

        vertex = simplex[:, i].reshape(-1, 1)
        # First find the y_safe[vertex]:
        val, idx, x_nn = Utils.mindis(vertex, xE)
        if val > 1e-10:
            # This vertex is a boundary corner point. No safe-guarantee, we do not optimize around support points.
            continue
        else:
            # TODO: multiple safe constraints in future.
            safe_bounds = y_safe[idx]

            if n > 1:
                # The first function in F(x) is the objective function, the rest are m simplex constraints.
                # The last part of functions in F(x) is the safe constraints.
                # In high dimension, A_simplex make sure that linear_derivative_A won't be all zero.
                nF = 1 + m + 1  # the last 1 is the safe constraint.
                Flow = np.hstack((-inf, b_simplex.T[0], -safe_bounds))
                Fupp = inf * np.ones(nF)

                # The lower and upper bounds of variables x.
                xlow = np.copy(lb_simplex)
                xupp = np.copy(ub_simplex)

                # For the nonlinear components, enter any nonzero value in G to indicate the location
                # of the nonlinear derivatives (in this case, 2).

                # A must be properly defined with the correct derivative values.
                linear_derivative_A = np.vstack((np.zeros(
                    (1, n)), A_simplex, np.zeros((1, n))))
                nonlinear_derivative_G = np.vstack((2 * np.ones(
                    (1, n)), np.zeros((m, n)), 2 * np.ones((1, n))))

            else:

                # For 1D problem, the simplex constraint is defined in x bounds.
                # TODO multiple safe cons.
                # 2 = 1 obj + 1 safe con. Plus one redundant constraint to make matrix A suitable.
                nF = 2 + 1
                Flow = np.array([-inf, -safe_bounds, -inf])
                Fupp = np.array([inf, inf, inf])
                xlow = np.min(simplex) * np.ones(n)
                xupp = np.max(simplex) * np.ones(n)

                linear_derivative_A = np.vstack((np.zeros(
                    (1, n)), np.zeros((1, n)), np.ones((1, n))))
                nonlinear_derivative_G = np.vstack((2 * np.ones(
                    (2, n)), np.zeros((1, n))))

            x0 = x.T[0]

            # -------  ADD THE FOLLOWING LINE WHEN DEBUGGING --------
            # cd dogs
            # -------  ADD THE FOLLOWING LINE WHEN DEBUGGING --------

            save_opt_for_snopt_ck(n, nF, inter_par, xc, R2, K, A_simplex,
                                  L_safe, vertex, exist)

            # Since adaptiveK using ( p(x) - f0 ) / e(x), the objective function is nonlinear.
            # The constraints are generated by simplex bounds, all linear.

            options = SNOPT_options()
            options.setOption('Infinite bound', inf)
            options.setOption('Verify level', 3)
            options.setOption('Verbose', False)
            options.setOption('Print level', -1)
            options.setOption('Scale option', 2)
            options.setOption('Print frequency', -1)
            options.setOption('Summary', 'No')

            result = snopta(dogsobj,
                            n,
                            nF,
                            x0=x0,
                            name='DeltaDOGS_snopt',
                            xlow=xlow,
                            xupp=xupp,
                            Flow=Flow,
                            Fupp=Fupp,
                            ObjRow=ObjRow,
                            A=linear_derivative_A,
                            G=nonlinear_derivative_G,
                            options=options)

            x_solver = np.hstack((x_solver, result.x.reshape(-1, 1)))
            y_solver.append(result.objective)

    y_solver = np.array(y_solver)
    y = np.min(y_solver)
    x = x_solver[:, np.argmin(y_solver)].reshape(-1, 1)

    return x, y