def _adapt(self): pop = self.pop X, F = pop.get("X", "F") sbest = self.sbest w, c1, c2, = self.w, self.c1, self.c2 # get the average distance from one to another for normalization D = norm_eucl_dist(self.problem, X, X) mD = D.sum(axis=1) / (len(pop) - 1) _min, _max = mD.min(), mD.max() # get the average distance to the best g_D = norm_eucl_dist(self.problem, sbest.get("X"), X).mean() f = (g_D - _min) / (_max - _min + 1e-32) S = np.array([ S1_exploration(f), S2_exploitation(f), S3_convergence(f), S4_jumping_out(f) ]) strategy = S.argmax() + 1 delta = 0.05 + (np.random.random() * 0.05) if strategy == 1: c1 += delta c2 -= delta elif strategy == 2: c1 += 0.5 * delta c2 -= 0.5 * delta elif strategy == 3: c1 += 0.5 * delta c2 += 0.5 * delta elif strategy == 4: c1 -= delta c2 += delta c1 = max(1.5, min(2.5, c1)) c2 = max(1.5, min(2.5, c2)) if c1 + c2 > 4.0: c1 = 4.0 * (c1 / (c1 + c2)) c2 = 4.0 * (c2 / (c1 + c2)) w = 1 / (1 + 1.5 * np.exp(-2.6 * f)) self.f = f self.strategy = strategy self.c1 = c1 self.c2 = c2 self.w = w
def _do(self, problem, pop, n_survive, out=None, algorithm=None, **kwargs): X, F = pop.get("X", "F") if F.shape[1] != 1: raise ValueError( "FitnessSurvival can only used for single objective single!") n_neighbors = 5 # calculate the normalized euclidean distances from each solution to another D = norm_eucl_dist(problem, X, X, fill_diag_with_inf=True) # set the neighborhood for each individual for k, individual in enumerate(pop): # the neighbors in the current population neighbors = pop[D[k].argsort()[:n_neighbors]] # get the neighbors of the current individual and merge N = individual.get("neighbors") if N is not None: rec = [] h = set() for n in N: for entry in n.get("neighbors"): if entry not in h: rec.append(entry) h.add(entry) neighbors = Population.merge(neighbors, rec) # keep only the closest solutions to the individual _D = norm_eucl_dist(problem, individual.X[None, :], neighbors.get("X"))[0] # find only the closest neighbors closest = _D.argsort()[:n_neighbors] individual.set("crowding", _D[closest].mean()) individual.set("neighbors", neighbors[closest]) best = F[:, 0].argmin() print(F[best], pop[best].get("crowding")) # plt.scatter(F[:, 0], pop.get("crowding")) # plt.show() pop.set("_F", pop.get("F")) pop.set("F", np.column_stack([F, -pop.get("crowding")])) pop = RankAndCrowdingSurvival().do(problem, pop, n_survive) pop.set("F", pop.get("_F")) return pop
def do(self, problem, pop, n_survive, **kwargs): # calculate the distance from each individual to another - pre-processing for the clearing X = pop.get("X") D = norm_eucl_dist(problem, X, X) def func_select_by_constraint_violation(pop): CV = pop.get("CV") return CV[:, 0].argmin() I = select_by_clearing(pop, D, n_survive, func_select_by_constraint_violation) return pop[I]
def _initialize(self): self.pop = self.initialization.do(self.problem, self.pop_size, algorithm=self) self.evaluator.eval(self.problem, self.pop, algorithm=self) X = self.pop.get("X") D = norm_eucl_dist(self.problem, X, X) S = select_by_clearing(self.pop, D, self.n_parallel, func_select_by_objective) self.solvers = [] for s in S: solver = self.func_create_solver(self.problem, self.pop[s].X) self.solvers.append(solver)
def do(self, problem, pop, n_survive, **kwargs): # sort them by cv sorted_by_cv = pop.get("CV")[:, 0].argsort() pop = pop[sorted_by_cv] if self.clearing: # calculate the distance from each individual to another - pre-processing for the clearing X = pop.get("X") D = norm_eucl_dist(problem, X, X) # select by clearing using the order defined before I = select_by_clearing(pop, D, n_survive, func_select_from_sorted, delta=self.clearing_delta) return pop[I] else: return pop[:n_survive]
def _do(self, problem, pop, n_survive, out=None, **kwargs): F = pop.get("F") if F.shape[1] != 1: raise ValueError( "FitnessSurvival can only used for single objective single!") # this basically sorts the population by constraint and objective value pop = FitnessSurvival().do(problem, pop, len(pop)) # calculate the distance from each individual to another - pre-processing for the clearing X = pop.get("X") D = norm_eucl_dist(problem, X, X) # initialize the clearing strategy clearing = EpsilonClearing(D, self.epsilon) # initialize the iteration and rank i the beginning iter, rank = 1, 1 # also solutions that have been found in the first iteration iter_one = None # until the number of selected individuals are less than expected survivors while len(clearing.selected()) < n_survive: # get all the remaining indices remaining = clearing.remaining() # if no individuals are left because of clearing - perform a reset if len(remaining) == 0 or (self.n_max_each_iter is not None and rank > self.n_max_each_iter): # reset and retrieve the newly available indices clearing.reset() remaining = clearing.remaining() # increase the iteration counter and start over from rank 1 iter += 1 rank = 1 # get the individual of the first iteration - needed for niche assignment iter_one = np.where( pop.get("iter") == 1)[0] if iter_one is None else iter_one # since the population is ordered by F and CV it is always the first index k = remaining[0] # set the attribute to the selected individual pop[k].set("iter", iter) pop[k].set("rank", rank) # in the first iteration set the niche counter for each solution equal to rank if iter == 1: pop[k].set("niche", rank) else: closest_iter_one = iter_one[D[k][iter_one].argmin()] niche = pop[closest_iter_one].get("niche") pop[k].set("niche", niche) clearing.select(k) rank += 1 # retrieve all individuals being selected S = clearing.selected() return pop[S]