示例#1
0
    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
示例#2
0
    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
示例#3
0
    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)
示例#4
0
    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
示例#5
0
 def _filter_fast(self):
     filtered_pop = NonDominatedRank.get_non_dominated(
         self.whole_pop, self.curr_pop)
     return filtered_pop
示例#6
0
    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