def plot(algorithm): pop = algorithm.pop sc = Scatter(title=algorithm.n_gen) sc.add(curve(algorithm.problem), plot_type="line", color="black") sc.add(np.column_stack([pop.get("X"), pop.get("F")]), color="red") sc.do()
termination=('n_gen', 50), seed=1, save_history=True, verbose=False) print(ret.F) with Video(GIF("animation.gif")) as vid: for algorithm in ret.history: if algorithm.n_gen % 1 == 0: X, F = algorithm.pop.get("X", "F") nds = NonDominatedSorting().do(F, only_non_dominated_front=True) other = [k for k in range(len(F)) if k not in nds] fig, (ax1, ax2) = plt.subplots(2, figsize=(8, 6)) fig.suptitle("%s - %s - Gen %s" % ("ZDT1", "NSGA2", algorithm.n_gen), fontsize=16) pcp = PCP(ax=ax1, bounds=(problem.xl, problem.xu)) pcp.add(X[other], color="blue", linewidth=0.5) pcp.add(X[nds], color="red", linewidth=2) pcp.do() sc = Scatter(ax=ax2) sc.add(F[other], color="blue") sc.add(F[nds], color="red") sc.add(problem.pareto_front(), plot_type="line") sc.do() vid.record()
for problem, name in zip([SYMPART(), SYMPARTRotated()], ["SYM-PART", "SYM-PART rotated"]): ref_dirs = get_reference_directions("das-dennis", problem.n_obj, n_partitions=20) PS = problem.pareto_set(500) PF = problem.pareto_front(500) algorithm = NSGA3(ref_dirs=ref_dirs) res = minimize(problem, algorithm, ('n_gen', 500), seed=1, verbose=False) fig_name = f"{algorithm.__class__.__name__} on {name}" # visualize decision space plot = Scatter(title="Decision Space") plot.add(PS, s=10, color='r', label="PS") plot.add(res.X, s=30, color='b', label="Obtained solutions") plot.do() plt.legend() # visualize objective space plot = Scatter(title="Objective Space") plot.add(PF, s=10, color='r', label="PF") plot.add(res.F, s=30, color='b', label="Obtained solutions") plot.do() plt.legend() plt.show()
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!") # calculate the normalized distance D = vectorized_cdist(X, X) # np.fill_diagonal(D, np.inf) norm = np.linalg.norm(problem.xu - problem.xl) D /= norm # find the best solution in the population S = np.argmin(F[:, 0]) # create the data structure to work with in order to flag survivors survivors = [S] remaining = [k for k in range(len(pop)) if k != S] # assign all solutions to the minimum first assigned_to = np.full(len(pop), S) dist = D[S, :] # never select more than actually should survive while len(survivors) < n_survive: rem = np.array(remaining) vals = np.full(len(pop), np.inf) for S in survivors: I = rem[assigned_to[rem] == S] if len(I) > 0: vals[I] = calc_metric(dist[I], F[I], p=2) select = vals.argmin() reassign = np.logical_and(D[select] < dist, F[:, 0] >= F[select, 0]) assigned_to[reassign] = select survivors.append(select) remaining = [k for k in remaining if k != select] plt.scatter(X, F) plt.scatter(X[survivors], F[survivors], color="red", marker='x') _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.show() print(survivors) # set the neighborhood for the local search for each survivor # for k in survivors: # # individual = pop[k] # # if individual has had neighbors before update them # N = individual.get("neighbors") # if N is not None: # neighbors = Population.merge(neighbors, N) # neighbors = neighbors[neighbors.get("F")[:, 0].argsort()[:10]] # # individual.set("neighbors", neighbors) return pop[survivors] # do the non-dominated sorting val = np.column_stack([-D[S, :], F[:, 0]]) fronts = NonDominatedSorting().do(val) # for each of the fronts regarding the dummy objectives for k, front in enumerate(fronts): if len(survivors) + len(front) <= n_survive: survivors.extend(front) # if we have found the splitting front else: S = F[front, 0].argmin() survivors.append(front[S]) # the extreme point for decision making _D = D[front, :][:, front] farthest = _D[S].argmax() # sort by distance to best delta_x = _D[S, :] / _D[S, farthest] delta_f = (F[front, 0] - F[S, 0]) / (F[front[farthest], 0] - F[S, 0]) f = np.column_stack([-delta_x, delta_f]) z = np.array([-1, 0]) p = 2 val = ((f - z)**p).sum(axis=1)**(1 / p) I = val.argsort()[:n_survive] pop[front[I]].set("v", val[I]) survivors.extend(front[I]) plt.scatter(X, F) plt.scatter(X[survivors], F[survivors], color="red", marker='x') _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.show() return pop[fronts[0]] X, F = pop.get("X", "F") if F.shape[1] != 1: raise ValueError( "FitnessSurvival can only used for single objective single!") # the final indices of surviving individuals survivors = [] # calculate the normalized distance D = vectorized_cdist(X, X) # np.fill_diagonal(D, np.inf) norm = np.linalg.norm(problem.xu - problem.xl) D /= norm # find the best solution in the population S = np.argmin(F[:, 0]) # create the data structure to work with in order to flag survivors survivors = [] remaining = [k for k in range(len(pop)) if k != S] while len(survivors) < n_survive: plt.figure(figsize=(5, 5)) plt.scatter(X, F, color="black", alpha=0.8, s=20, label='pop') plt.scatter(X[survivors], F[survivors], color="red", label="survivors") v = np.round(pop[survivors].get("v"), 3) for i in range(len(survivors)): x = X[survivors][i] y = F[survivors][i] plt.text(x, y, v[i], fontsize=9) plt.scatter(X[farthest], F[farthest], color="green", label="survivors") _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.legend() plt.show() return pop[survivors] survivors.append(remaining[val.argmin()]) remaining = [k for k in range(len(pop)) if k != S] plt.scatter(X, F) plt.scatter(X[survivors], F[survivors], color="red", marker='x') _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.show() return pop[fronts[0]] plt.scatter(delta_x, delta_f) plt.scatter(delta_x[nds], delta_f[nds], color="red") plt.xlabel("D") plt.ylabel("F") plt.show() pop[S].set("rank", 0) # initialize utility data structures survivors = [S] remaining = [k for k in range(len(pop)) if k != S] n_neighbors = 10 cnt = 1 while len(survivors) < n_survive: closest = D[survivors, :][:, remaining].argmin(axis=0) delta_f = F[remaining, 0] - F[np.argmin(F[:, 0]), 0] delta_x = D[closest, remaining] fitness = delta_f / delta_x S = remaining[np.argmin(fitness)] if algorithm.n_gen == 20: sc = Scatter(title=algorithm.n_gen) sc.add(curve(problem), plot_type="line", color="black") sc.add(np.column_stack([pop.get("X"), F[:, 0]]), color="purple") sc.add(np.column_stack( [pop[survivors].get("X"), pop[survivors].get("F")]), color="red", s=40, marker="x") sc.do() plt.ylim(0, 2) plt.show() plt.close() # update the survivors and remaining individuals individual = pop[S] neighbors = pop[D[S].argsort()[:n_neighbors]] # if individual has had neighbors before update them N = individual.get("neighbors") if N is not None: neighbors = Population.merge(neighbors, N) neighbors = neighbors[neighbors.get("F")[:, 0].argsort() [:n_neighbors]] individual.set("neighbors", neighbors) individual.set("rank", cnt) survivors.append(S) remaining = [k for k in remaining if k != S] cnt += 1 return pop[survivors]
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!") # calculate the normalized distance D = vectorized_cdist(X, X) np.fill_diagonal(D, np.inf) norm = np.linalg.norm(problem.xu - problem.xl) D /= norm # find the best solution in the population S = np.argmin(F[:, 0]) pop[S].set("rank", 0) # initialize utility data structures survivors = [S] remaining = [k for k in range(len(pop)) if k != S] n_neighbors = 10 cnt = 1 while len(survivors) < n_survive: closest = D[survivors, :][:, remaining].argmin(axis=0) delta_f = F[remaining, 0] - F[np.argmin(F[:, 0]), 0] delta_x = D[closest, remaining] fitness = delta_f / delta_x S = remaining[np.argmin(fitness)] if algorithm.n_gen == 20: sc = Scatter(title=algorithm.n_gen) sc.add(curve(problem), plot_type="line", color="black") sc.add(np.column_stack([pop.get("X"), F[:, 0]]), color="purple") sc.add(np.column_stack([pop[survivors].get("X"), pop[survivors].get("F")]), color="red", s=40, marker="x") sc.do() plt.ylim(0, 2) plt.show() plt.close() # update the survivors and remaining individuals individual = pop[S] neighbors = pop[D[S].argsort()[:n_neighbors]] # if individual has had neighbors before update them N = individual.get("neighbors") if N is not None: neighbors = Population.merge(neighbors, N) neighbors = neighbors[neighbors.get("F")[:, 0].argsort()[:n_neighbors]] individual.set("neighbors", neighbors) individual.set("rank", cnt) survivors.append(S) remaining = [k for k in remaining if k != S] cnt += 1 return pop[survivors]
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!") # the final indices of surviving individuals survivors = [] # calculate the normalized distance D = vectorized_cdist(X, X) # np.fill_diagonal(D, np.inf) norm = np.linalg.norm(problem.xu - problem.xl) D /= norm # find the best solution in the population S = np.argmin(F[:, 0]) # create the data structure to work with in order to flag survivors survivors = [] remaining = [k for k in range(len(pop)) if k != S] while len(survivors) < n_survive: # the extreme point for decision making farthest = D[S, :].argmax() # sort by distance to best delta_x = D[S, :] / D[S, farthest] delta_f = (F[:, 0] - F[S, 0]) / (F[farthest, 0] - F[S, 0]) f = np.column_stack([-delta_x, delta_f]) z = np.array([-1, 0]) p = 2 val = ((f - z) ** p).sum(axis=1) ** (1 / p) survivors = val.argsort()[:n_survive] pop[survivors].set("v", val[survivors]) plt.figure(figsize=(5, 5)) plt.scatter(X, F, color="black", alpha=0.8, s=20, label='pop') plt.scatter(X[survivors], F[survivors], color="red", label="survivors") v = np.round(pop[survivors].get("v"), 3) for i in range(len(survivors)): x = X[survivors][i] y = F[survivors][i] plt.text(x, y, v[i], fontsize=9) plt.scatter(X[farthest], F[farthest], color="green", label="survivors") _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.legend() plt.show() return pop[survivors] survivors.append(remaining[val.argmin()]) remaining = [k for k in range(len(pop)) if k != S] plt.scatter(X, F) plt.scatter(X[survivors], F[survivors], color="red", marker='x') _curve = curve(problem) plt.plot(_curve[:, 0], _curve[:, 1], color="black") plt.xlabel("X") plt.ylabel("F") plt.show() return pop[fronts[0]] plt.scatter(delta_x, delta_f) plt.scatter(delta_x[nds], delta_f[nds], color="red") plt.xlabel("D") plt.ylabel("F") plt.show() pop[S].set("rank", 0) # initialize utility data structures survivors = [S] remaining = [k for k in range(len(pop)) if k != S] n_neighbors = 10 cnt = 1 while len(survivors) < n_survive: closest = D[survivors, :][:, remaining].argmin(axis=0) delta_f = F[remaining, 0] - F[np.argmin(F[:, 0]), 0] delta_x = D[closest, remaining] fitness = delta_f / delta_x S = remaining[np.argmin(fitness)] if algorithm.n_gen == 20: sc = Scatter(title=algorithm.n_gen) sc.add(curve(problem), plot_type="line", color="black") sc.add(np.column_stack([pop.get("X"), F[:, 0]]), color="purple") sc.add(np.column_stack([pop[survivors].get("X"), pop[survivors].get("F")]), color="red", s=40, marker="x") sc.do() plt.ylim(0, 2) plt.show() plt.close() # update the survivors and remaining individuals individual = pop[S] neighbors = pop[D[S].argsort()[:n_neighbors]] # if individual has had neighbors before update them N = individual.get("neighbors") if N is not None: neighbors = Population.merge(neighbors, N) neighbors = neighbors[neighbors.get("F")[:, 0].argsort()[:n_neighbors]] individual.set("neighbors", neighbors) individual.set("rank", cnt) survivors.append(S) remaining = [k for k in remaining if k != S] cnt += 1 return pop[survivors]