def _do(self, pop, off, size, return_sorted_idx=False, out=None, **kwargs): if off is not None: pop.merge(off) fronts = NonDominatedRank.calc_as_fronts(pop.F, pop.G) rank = NonDominatedRank.calc_from_fronts(fronts) crowding = np.zeros(pop.F.shape[0]) for front in fronts: cd_of_front = RankAndCrowdingSurvival.calc_crowding_distance(pop.F[front, :]) crowding[front] = cd_of_front sorted_idx = sorted(range(pop.size()), key=lambda x: (rank[x], -crowding[x])) if return_sorted_idx: return sorted_idx # now truncate the population sorted_idx = sorted_idx[:size] pop.filter(sorted_idx) rank = rank[sorted_idx] crowding = crowding[sorted_idx] if out is not None: out['rank'] = rank out['crowding'] = crowding return pop
def _do(self, pop, size, data, return_sorted_idx=False): fronts = NonDominatedRank.calc_as_fronts(pop.F, pop.G) rank = NonDominatedRank.calc_from_fronts(fronts) crowding = np.zeros(pop.F.shape[0]) for front in fronts: cd_of_front = RankAndCrowdingSurvival.calc_crowding_distance( pop.F[front, :]) crowding[front] = cd_of_front sorted_idx = sorted(range(pop.size()), key=lambda x: (rank[x], -crowding[x])) if return_sorted_idx: return sorted_idx # now truncate the population sorted_idx = sorted_idx[:size] pop.filter(sorted_idx) rank = rank[sorted_idx] crowding = crowding[sorted_idx] if data is not None: data.rank = rank data.crowding = crowding return pop
def _do(self, pop, off, n_survive, return_only_index=False, **kwargs): fronts = NonDominatedRank.calc_as_fronts(pop.F, pop.G) # all indices to survive survival = [] for front in fronts: if len(survival) + len(front) > n_survive: break survival.extend(front) # filter the front to only relevant entries pop.filter(survival + front) survival = list(range(0, len(survival))) last_front = np.arange(len(survival), pop.size()) # Indices of last front members that survived survived = [] # if the last front needs to be splitted n_remaining = n_survive - len(survival) if n_remaining > 0: F_min, F_max = pop.F.min(axis=0), pop.F.max(axis=0) dist_matrix, self.ref_points = calc_ref_dist_matrix(pop.F, self.orig, weights=data.weights, n_obj=self.n_obj) point_distance_matrix = calc_dist_matrix(pop.F[last_front, :], pop.F[last_front, :], F_min=F_min, F_max=F_max) niche_of_individuals = np.argmin(dist_matrix, axis=1) min_dist_matrix = dist_matrix[np.arange(len(dist_matrix)), niche_of_individuals] # for each reference direction the niche count niche_count = np.zeros(len(self.ref_points)) for i in niche_of_individuals[survival]: niche_count[i] += 1 # relative index now to dist and the niches min_dist_matrix = min_dist_matrix[last_front] niche_of_individuals = niche_of_individuals[last_front] # boolean array of elements that survive if true survival_last_front = np.full(len(last_front), False) while n_remaining > 0: # all niches where new individuals can be assigned to next_niches_list = np.unique(niche_of_individuals[np.logical_not(survival_last_front)]) # pick a niche with minimum assigned individuals - break tie if necessary next_niche_count = niche_count[next_niches_list] next_niche = np.where(next_niche_count == next_niche_count.min())[0] next_niche = next_niche[random.randint(0, len(next_niche))] next_niche = next_niches_list[next_niche] # indices of individuals in last front to assign niche to next_ind = np.where(niche_of_individuals[np.logical_not(survival_last_front)] == next_niche)[0] next_ind = np.where(np.logical_not(survival_last_front))[0][next_ind] # Pick the closest point next_ind = next_ind[np.argmin(min_dist_matrix[next_ind])] # Find surrounding points within trust region surrounding_points = np.where(point_distance_matrix[next_ind] < self.epsilon)[0] # Clear points in trust region survival_last_front[surrounding_points] = True # Add selected point to survived population survived.append(next_ind) if np.all(survival_last_front): survival_last_front = np.full(len(last_front), False) survival_last_front[survived] = True niche_count[next_niche] += 1 n_remaining -= 1 survival.extend(last_front[survived]) if return_only_index: return survival # now truncate the population pop.filter(survival)
def solve( self, problem, evaluator, seed=1, return_only_feasible=True, return_only_non_dominated=True, history=None, ): """ Solve a given problem by a given evaluator. The evaluator determines the termination condition and can either have a maximum budget, hypervolume or whatever. The problem can be any problem the algorithm is able to solve. Parameters ---------- problem: class Problem to be solved by the algorithm evaluator: class object that evaluates and saves the number of evaluations and determines the stopping condition seed: int Random seed for this run. Before the algorithm starts this seed is set. return_only_feasible : bool If true, only feasible solutions are returned. return_only_non_dominated : bool If true, only the non dominated solutions are returned. Otherwise, it might be - dependend on the algorithm - the final population Returns ------- X: matrix Design space F: matrix Objective space G: matrix Constraint space """ # set the random seed for generator pymoo.rand.random.seed(seed) # just to be sure also for the others seed = pymoo.rand.random.randint(0, 100000) random.seed(seed) np.random.seed(seed) # this allows to provide only an integer instead of an evaluator object if not isinstance(evaluator, Evaluator): evaluator = Evaluator(evaluator) # call the algorithm to solve the problem X, F, G = self._solve(problem, evaluator) if return_only_feasible: if G is not None and G.shape[0] == len(F) and G.shape[1] > 0: cv = Problem.calc_constraint_violation(G)[:, 0] X = X[cv <= 0, :] F = F[cv <= 0, :] if G is not None: G = G[cv <= 0, :] if return_only_non_dominated: idx_non_dom = NonDominatedRank.calc_as_fronts(F, G)[0] X = X[idx_non_dom, :] F = F[idx_non_dom, :] if G is not None: G = G[idx_non_dom, :] return X, F, G
def _do(self, pop, off, n_survive, return_only_index=False, **kwargs): data = kwargs['data'] fronts = NonDominatedRank.calc_as_fronts(pop.F, pop.G) # all indices to survive survival = [] for front in fronts: if len(survival) + len(front) > n_survive: break survival.extend(front) # filter the front to only relevant entries pop.filter(survival + front) survival = list(range(0, len(survival))) last_front = np.arange(len(survival), pop.size()) N, self.asf, self.extreme, F_min, F_max = normalize_by_asf_interceptions( np.vstack((pop.F, data.ref_points)), len(fronts[0]), prev_asf=self.asf, prev_S=self.extreme, return_bounds=True) z_ = (data.ref_points - F_min) / (F_max - F_min ) # Normalized reference points data.F_min, data.F_max = F_min, F_max self.ref_dirs = get_ref_dirs_from_points(z_, self.n_obj, data.ref_pop_size, alpha=data.mu, method=data.method, p=data.p) data.ref_dirs = self.ref_dirs # if the last front needs to be split n_remaining = n_survive - len(survival) if n_remaining > 0: dist_matrix = calc_perpendicular_dist_matrix(N, self.ref_dirs) niche_of_individuals = np.argmin(dist_matrix, axis=1) dist_to_niche = dist_matrix[np.arange(len(dist_matrix)), niche_of_individuals] # for each reference direction the niche count niche_count = np.zeros(len(self.ref_dirs)) for i in niche_of_individuals[survival]: niche_count[i] += 1 # relative index to dist and the niches just of the last front dist_to_niche = dist_to_niche[last_front] niche_of_individuals = niche_of_individuals[last_front] # boolean array of elements that are considered for each iteration remaining_last_front = np.full(len(last_front), True) while n_remaining > 0: # all niches where new individuals can be assigned to next_niches_list = np.unique( niche_of_individuals[remaining_last_front]) # pick a niche with minimum assigned individuals - break tie if necessary next_niche_count = niche_count[next_niches_list] next_niche = np.where( next_niche_count == next_niche_count.min())[0] next_niche = next_niche[random.randint(0, len(next_niche))] next_niche = next_niches_list[next_niche] # indices of individuals that are considered and assign to next_niche next_ind = np.where( np.logical_and(niche_of_individuals == next_niche, remaining_last_front))[0] if len(next_ind) == 1: next_ind = next_ind[0] elif niche_count[next_niche] == 0: next_ind = next_ind[np.argmin(dist_to_niche[next_ind])] else: next_ind = next_ind[random.randint(0, len(next_ind))] remaining_last_front[next_ind] = False survival.append(last_front[next_ind]) niche_count[next_niche] += 1 n_remaining -= 1 if return_only_index: return survival # now truncate the population pop.filter(survival)
def _do(self, pop, n_survive, data, return_only_index=False): fronts = NonDominatedRank.calc_as_fronts(pop.F, pop.G) # all indices to survive survival = [] for front in fronts: if len(survival) + len(front) > n_survive: break survival.extend(front) # filter the front to only relevant entries pop.filter(survival + front) survival = list(range(0, len(survival))) last_front = np.arange(len(survival), pop.size()) N = normalize_by_asf_interceptions(pop.F, return_bounds=False) #N = normalize(pop.F, np.zeros(pop.F.shape[1]), np.ones(pop.F.shape[1])) #N = normalize(pop.F, np.zeros(pop.F.shape[1]), np.ones(pop.F.shape[1])) # if the last front needs to be splitted n_remaining = n_survive - len(survival) if n_remaining > 0: dist_matrix = calc_perpendicular_dist_matrix(N, self.ref_dirs) niche_of_individuals = np.argmin(dist_matrix, axis=1) min_dist_matrix = dist_matrix[np.arange(len(dist_matrix)), niche_of_individuals] # for each reference direction the niche count niche_count = np.zeros(len(self.ref_dirs)) for i in niche_of_individuals[survival]: niche_count[i] += 1 # relative index now to dist and the niches min_dist_matrix = min_dist_matrix[last_front] niche_of_individuals = niche_of_individuals[last_front] # boolean array of elements that survive if true survival_last_front = np.full(len(last_front), False) while n_remaining > 0: # all niches where new individuals can be assigned to next_niches_list = np.unique( niche_of_individuals[np.logical_not(survival_last_front)]) # pick a niche with minimum assigned individuals - break tie if necessary next_niche_count = niche_count[next_niches_list] next_niche = np.where( next_niche_count == next_niche_count.min())[0] next_niche = next_niche[random.randint(0, len(next_niche))] next_niche = next_niches_list[next_niche] # indices of individuals in last front to assign niche to next_ind = np.where(niche_of_individuals[np.logical_not( survival_last_front)] == next_niche)[0] next_ind = np.where( np.logical_not(survival_last_front))[0][next_ind] if len(next_ind) == 1: next_ind = next_ind[0] elif niche_count[next_niche] == 0: next_ind = next_ind[np.argmin(min_dist_matrix[next_ind])] else: next_ind = next_ind[random.randint(0, len(next_ind))] survival_last_front[next_ind] = True niche_count[next_niche] += 1 n_remaining -= 1 survival.extend(last_front[survival_last_front]) if return_only_index: return survival # now truncate the population pop.filter(survival) return pop