def calc_dist(self, pop, other=None): X = self.func(pop) if other is None: D = cdist(X, X) D[np.triu_indices(len(X))] = np.inf else: _X = self.func(other) D = cdist(X, _X) return D
def kmeans(X, centroids, n_max_iter, a_tol, n_ignore): for i in range(n_max_iter): # copy the old centroids last_centroids = np.copy(centroids) # assign all points to one of the centroids points_to_centroid = cdist(X, centroids).argmin(axis=1) centroids_to_points = [[] for _ in range(len(centroids))] for j, k in enumerate(points_to_centroid): centroids_to_points[k].append(j) for j in range(n_ignore, len(centroids_to_points)): centroids[j] = np.mean(X[centroids_to_points[j]], axis=0) project_onto_unit_simplex_recursive(centroids) centroids /= centroids.sum(axis=1)[:, None] delta = np.abs(centroids - last_centroids).sum(axis=1).mean() if delta < a_tol: break return centroids
def select_points_with_maximum_distance(X, n_select, selected=[]): n_points, n_dim = X.shape # calculate the distance matrix D = cdist(X, X) # if no selection provided pick randomly in the beginning if len(selected) == 0: selected = [np.random.randint(len(X))] # create variables to store what selected and what not not_selected = [i for i in range(n_points) if i not in selected] # remove unnecessary points dist_to_closest_selected = D[:, selected].min(axis=1) # now select the points until sufficient ones are found while len(selected) < n_select: # find point that has the maximum distance to all others index_in_not_selected = dist_to_closest_selected[not_selected].argmax() I = not_selected[index_in_not_selected] # add the closest distance to selected point is_closer = D[I] < dist_to_closest_selected dist_to_closest_selected[is_closer] = D[I][is_closer] # add it to the selected and remove from not selected selected.append(I) not_selected = np.delete(not_selected, index_in_not_selected) return selected
def _calc_score(self, X): if self.criterion == "maxmin": D = cdist(X, X) np.fill_diagonal(D, np.inf) return np.min(D) elif self.criterion == "correlation": M = np.corrcoef(X.T, rowvar=True) return -np.sum(np.tril(M, -1) ** 2) else: raise Exception("Unknown criterium.")
def selection(surviving, not_surviving, F, n_remaining): val = [] D = cdist(F, F) for i in range(n_remaining): I = not_surviving[np.argmax( np.min(D[not_surviving, :][:, surviving], 1))] surviving.append(I) not_surviving.remove(I) val.append(I) return val
def kmeans(X, centroids, n_max_iter, a_tol): for i in range(n_max_iter): # assign all points to one of the centroids points_to_centroid = cdist(X, centroids).argmin(axis=1) centroids_to_points = [[] for _ in range(len(centroids))] for j, k in enumerate(points_to_centroid): centroids_to_points[k].append(j) last_centroids = np.copy(centroids) for j in range(len(centroids_to_points)): centroids[j] = np.mean(X[centroids_to_points[j]], axis=0) if np.abs(centroids - last_centroids).sum(axis=1).mean() < a_tol: break
def iterative_igd(X, n_partitions=None, batch_size=100): n_points, n_dim = X.shape if n_partitions is None: n_partitions = get_partition_closest_to_points(n_points * n_dim * 10, n_dim) + 1 scaling = 1 + 1 / 2 dd = DasDennis(n_partitions, n_dim, scaling=scaling) val = 0 while dd.has_next(): points = dd.next(n_points=batch_size) val += cdist(points, X).min(axis=1).sum() val /= dd.number_of_points() return val
def _calc_score(self, X): if isinstance(self.criterion, str): if self.criterion == "maxmin": D = cdist(X, X) np.fill_diagonal(D, np.inf) return np.min(D) elif self.criterion == "correlation": M = np.corrcoef(X.T, rowvar=True) return -np.sum(np.tril(M, -1) ** 2) else: raise Exception("Unknown criterion.") elif callable(self.criterion): return self.criterion(X) else: raise Exception("Either provide a str or a function as a criterion!")
def criterion_maxmin(X): D = cdist(X, X) np.fill_diagonal(D, np.inf) return np.min(D)
def _do(self, problem, pop, n_survive=None, out=None, **kwargs): F = pop.get("F") assert F.shape[ 1] == 1, "This survival only works for single-objective problems" I = np.argsort(F[:, 0]) pop = pop[I] X, F = pop.get("X", "F") xl, xu = problem.bounds() X = (X - xl) / (xu - xl) func_dist = lambda _x, _X: cdist(_x[None, :], _X)[0] / (problem.n_var** 0.5) niches = np.full(len(pop), 0) crowding = np.full(len(pop), 0) penalty = np.full(len(pop), 0) leaders = [0] for i in range(1, len(pop)): # calculate the distance to all solutions with a better function value than i d = func_dist(X[i], X[:i]) closer_than_d1 = d <= self.d1 # if the distance is less than d1, then we inherit the niche if np.any(closer_than_d1): # find the first solution with distance less than d1 - lowest objective value J = np.argmax(closer_than_d1) niche = niches[J] else: # create a new niche if maximum has not reached yet if len(leaders) < self.max_niches: niche = len(leaders) leaders.append(i) # else assign the closest niche else: niche = np.argmin(func_dist(X[i], X[leaders])) niches[i] = niche closer_than_d2 = d <= self.d2 # if any other solution is in the crowding radius if np.any(closer_than_d2): # assign the crowding counter for all of them J, = np.where(closer_than_d2) crowding[J] += 1 # the penalty is defined by the crowding counter minus the allowed max. allowed crowding penalty[i] = max(0, (crowding[J]).max() - self.max_crowding) # create the niche assignment matrix A A = [[] for _ in range(niches.max() + 1)] for i, niche in enumerate(niches): A[niche].append(i) # set the local optimum rank for each niche rank = np.full(len(pop), -1) for I in A: rank[I] = np.arange(len(I)) J = np.lexsort((rank, niches, penalty)) return pop[J[:n_survive]]