Exemplo n.º 1
0
    def _do(self, problem, pop, parents, **kwargs):

        # get the X of parents and count the matings
        X = pop.get("X")[parents.T]
        _, n_matings, n_var = X.shape

        # the mask do to the crossover
        M = np.full((n_matings, n_var), False)

        # start point of crossover
        n = random.randint(0, n_var, size=len(pop))

        # the probabilities are calculated beforehand
        r = random.random((n_matings, n_var)) < self.prob

        # create for each individual the crossover range
        for i in range(n_matings):

            # the actual index where we start
            start = n[i]
            for j in range(problem.n_var):

                # the current position where we are pointing to
                current = (start + j) % problem.n_var

                # replace only if random value keeps being smaller than CR
                if r[i, current]:
                    M[i, current] = True
                else:
                    break

        _X = crossover_mask(X, M)
        return pop.new("X", _X)
Exemplo n.º 2
0
def comp_by_dom_and_crowding(pop, P, crowding, **kwargs):

    if P.shape[1] != 2:
        raise ValueError("Only implemented for binary tournament!")

    S = np.zeros((P.shape[0], 1), dtype=np.int)

    for i, p in enumerate(P):

        rel = Dominator.get_relation(pop.F[P[i, 0], :], pop.F[P[i, 1], :])

        # first by domination
        if rel == 1:
            S[i, 0] = P[i, 0]
        elif rel == -1:
            S[i, 0] = P[i, 1]

        # then by crowding
        else:
            if crowding[P[i, 0]] > crowding[P[i, 1]]:
                S[i, 0] = P[i, 0]
            elif crowding[P[i, 1]] > crowding[P[i, 0]]:
                S[i, 0] = P[i, 1]
            else:
                S[i, 0] = P[i, random.randint(0, 2)]
    return S
Exemplo n.º 3
0
    def _next(self, pop):

        # iterate for each member of the population in random order
        for i in random.perm(len(pop)):

            # all neighbors of this individual and corresponding weights
            N = self.neighbors[i, :]

            if random.random() < self.prob_neighbor_mating:
                parents = N[random.perm(self.n_neighbors)][:self.crossover.n_parents]
            else:
                parents = random.perm(self.pop_size)[:self.crossover.n_parents]

            # do recombination and create an offspring
            off = self.crossover.do(self.problem, pop, parents[None, :])
            off = self.mutation.do(self.problem, off)
            off = off[random.randint(0, len(off))]

            # evaluate the offspring
            self.evaluator.eval(self.problem, off)

            # update the ideal point
            self.ideal_point = np.min(np.vstack([self.ideal_point, off.F]), axis=0)

            # calculate the decomposed values for each neighbor
            FV = self._decomposition.do(pop[N].get("F"), weights=self.ref_dirs[N, :], ideal_point=self.ideal_point)
            off_FV = self._decomposition.do(off.F[None, :], weights=self.ref_dirs[N, :], ideal_point=self.ideal_point)

            # get the absolute index in F where offspring is better than the current F (decomposed space)
            I = np.where(off_FV < FV)[0]
            pop[N[I]] = off

        return pop
Exemplo n.º 4
0
def comp_by_rank_and_crowding(pop, P, **kwargs):

    if P.shape[1] != 2:
        raise ValueError("Only implemented for binary tournament!")

    rank = kwargs['data']['rank']
    crowding = kwargs['data']['crowding']

    # the winner of the tournament selection
    S = np.zeros((P.shape[0], 1), dtype=np.int)

    for i, p in enumerate(P):

        # first by rank
        if rank[P[i, 0]] < rank[P[i, 1]]:
            S[i, 0] = P[i, 0]
        elif rank[P[i, 1]] < rank[P[i, 0]]:
            S[i, 0] = P[i, 1]

        # then by crowding
        else:
            if crowding[P[i, 0]] > crowding[P[i, 1]]:
                S[i, 0] = P[i, 0]
            elif crowding[P[i, 1]] > crowding[P[i, 0]]:
                S[i, 0] = P[i, 1]
            else:
                S[i, 0] = P[i, random.randint(0, 2)]
    return S
    def _do(self, p, parents, children, **kwargs):

        n_var = parents.shape[2]
        n_offsprings = parents.shape[0]

        # do the crossover
        if self.type == "binomial":

            # uniformly for each individual and each entry
            r = random.random(size=(n_offsprings, n_var)) < self.prob

        elif self.type == "exponential":

            r = np.full((n_offsprings, n_var), False)

            # start point of crossover
            n = random.randint(0, n_var, size=n_var)
            # length of chromosome to do the crossover
            L = np.argmax((random.random(n_offsprings) > self.prob), axis=1)

            # create for each individual the crossover range
            for i in range(n_offsprings):
                for l in range(L[i] + 1):
                    r[i, (n[i] + l) % n_var] = True

        else:
            raise Exception(
                "Unknown crossover type. Either binomial or exponential.")

        # the so called donor vector
        children[:, :] = parents[:, 0]

        if self.variant == "DE/rand/1":
            trial = parents[:,
                            3] + self.weight * (parents[:, 1] - parents[:, 2])
        else:
            raise Exception("DE variant %s not known." % self.variant)

        # set only if larger than F_CR
        children[r] = trial[r]

        # bounce back into bounds
        if self.bounce_back_in_bounds:
            smaller_than_min, larger_than_max = p.xl > children, p.xu < children
            children[smaller_than_min] = (p.xl +
                                          (p.xl - children))[smaller_than_min]
            children[larger_than_max] = (p.xu -
                                         (children - p.xu))[larger_than_max]
Exemplo n.º 6
0
    def sample(self, problem, pop, n_samples, **kwargs):

        # loop until n_samples are met
        m, counter = problem.n_var, 0
        val = np.full((n_samples, m), np.nan)
        while True:
            for i in range(m):
                val[counter, i] = random.randint(low=problem.xl[i],
                                                 high=problem.xu[i] + 1)
            if problem.is_valid(val[counter, :]):
                counter += 1

            if counter >= n_samples:
                break

        return pop.new("X", val)
Exemplo n.º 7
0
def lf_minimize(problem,
                method,
                method_args={},
                termination=('n_gen', 200),
                **kwargs):
    """

    Minimization of function of one or more variables, objectives and constraints.

    This is used as a convenience function to execute several algorithms with default settings which turned
    out to work for a test problems. However, evolutionary computations utilizes the idea of customizing a
    meta-algorithm. Customizing the algorithm using the object oriented interface is recommended to improve the
    convergence.

    Parameters
    ----------

    problem : pymop.problem
        A problem object defined using the pymop framework. Either existing test problems or custom problems
        can be provided. please have a look at the documentation.
    method : string
        Algorithm that is used to solve the problem.
    method_args : dict
        Additional arguments to initialize the algorithm object
    termination : tuple
        The termination criterium that is used to stop the algorithm when the result is satisfying.

    Returns
    -------
    res : Result
        The optimization result represented as a ``Result`` object.

    """

    # create an evaluator defined by the termination criterium
    if not isinstance(termination, Termination):
        termination = get_termination(*termination, pf=kwargs.get('pf', None))

    # set a random random seed if not provided
    if 'seed' not in kwargs:
        kwargs['seed'] = random.randint(1, 10000)

    algorithm = lf_get_alorithm(method)(**method_args)
    res = algorithm.solve(problem, termination, **kwargs)

    return res
Exemplo n.º 8
0
def comp_by_rank_and_crowding(pop, indices, data):
    if len(indices) != 2:
        raise ValueError("Only implemented for binary tournament!")

    first = indices[0]
    second = indices[1]

    if data.rank[first] < data.rank[second]:
        return first
    elif data.rank[second] < data.rank[first]:
        return second
    else:
        if data.crowding[first] > data.crowding[second]:
            return first
        elif data.crowding[second] > data.crowding[first]:
            return second
        else:
            return indices[random.randint(0, 2)]
Exemplo n.º 9
0
def minimize(problem,
             method,
             termination,
             **kwargs):
    """

    Minimization of function of one or more variables, objectives and constraints.

    This is used as a convenience function to execute several algorithms with default settings which turned
    out to work for a test problems. However, evolutionary computations utilizes the idea of customizing a
    meta-algorithm. Customizing the algorithm using the object oriented interface is recommended to improve the
    convergence.

    Parameters
    ----------

    problem : pymop.problem
        A problem object defined using the pymop framework. Either existing test problems or custom problems
        can be provided. please have a look at the documentation.

    method : :class:`~pymoo.model.algorithm.Algorithm`
        The algorithm object that should be used for the optimization.

    termination : tuple
        The termination criterium that is used to stop the algorithm when the result is satisfying.

    Returns
    -------
    res : :class:`~pymoo.model.result.Result`
        The optimization result represented as an object.

    """

    # create an evaluator defined by the termination criterium
    if not isinstance(termination, Termination):
        termination = get_termination(*termination)

    # set a random random seed if not provided
    if 'seed' not in kwargs:
        kwargs['seed'] = random.randint(1, 10000)

    res = method.solve(problem, termination, **kwargs)

    return res
Exemplo n.º 10
0
    def _do(self, problem, pop, algorithm, **kwargs):

        X = pop.get("X")
        off = algorithm.off
        _X = off.get("X")

        # do the crossover
        if self.variant == "bin":
            # uniformly for each individual and each entry
            r = random.random(size=(len(off), problem.n_var)) < self.CR

        elif self.variant == "exp":

            # start point of crossover
            r = np.full((len(off), problem.n_var), False)

            # start point of crossover
            n = random.randint(0, problem.n_var, size=len(off))
            # length of chromosome to do the crossover
            L = random.random((len(off), problem.n_var)) < self.CR

            # create for each individual the crossover range
            for i in range(len(off)):
                # the actual index where we start
                start = n[i]
                for j in range(problem.n_var):

                    # the current position where we are pointing to
                    current = (start + j) % problem.n_var

                    # replace only if random value keeps being smaller than CR
                    if L[i, current]:
                        r[i, current] = True
                    else:
                        break

        else:
            raise Exception(
                "Unknown crossover type. Either binomial or exponential.")

        X[r] = _X[r]
        return pop.new("X", X)
Exemplo n.º 11
0
def comp_by_dom_and_crowding(pop, indices, data):
    if len(indices) != 2:
        raise ValueError("Only implemented for binary tournament!")

    first = indices[0]
    second = indices[1]

    rel = Dominator.get_relation(pop.F[first, :], pop.F[second, :])

    if rel == 1:
        return first
    elif rel == -1:
        return second
    else:
        if data.crowding[first] > data.crowding[second]:
            return first
        elif data.crowding[second] > data.crowding[first]:
            return second
        else:
            return indices[random.randint(0, 2)]
Exemplo n.º 12
0
def _quicksort(A, I, left, right):
    if left < right:

        index = random.randint(left, right + 1)
        swap(I, right, index)

        pivot = A[I[right]]

        i = left - 1

        for j in range(left, right):

            if A[I[j]] <= pivot:
                i += 1
                swap(I, i, j)

        index = i + 1
        swap(I, right, index)

        _quicksort(A, I, left, index - 1)
        _quicksort(A, I, index + 1, right)
Exemplo n.º 13
0
def niching(F, n_remaining, niche_count, niche_of_individuals, dist_to_niche):
    survivors = []

    # boolean array of elements that are considered for each iteration
    mask = np.full(F.shape[0], True)

    while len(survivors) < n_remaining:

        # all niches where new individuals can be assigned to
        next_niches_list = np.unique(niche_of_individuals[mask])

        # 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_niches_list[next_niche]
        next_niche = next_niche[random.randint(0, len(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, mask))[0]

        # shuffle to break random tie (equal perp. dist) or select randomly
        next_ind = random.shuffle(next_ind)

        if niche_count[next_niche] == 0:
            next_ind = next_ind[np.argmin(dist_to_niche[next_ind])]
        else:
            # already randomized through shuffling
            next_ind = next_ind[0]

        mask[next_ind] = False
        survivors.append(int(next_ind))

        niche_count[next_niche] += 1

    return survivors
Exemplo n.º 14
0
    def _do(self, pop, n_survive, **kwargs):

        # get the objective space values and objects
        F = pop.get("F")

        # the final indices of surviving individuals
        survivors = []

        # do the non-dominated sorting until splitting front
        fronts = NonDominatedSorting().do(F)

        if self.normalization == "ever":
            # find or usually update the new ideal point - from feasible solutions
            self.ideal_point = np.min(np.vstack((self.ideal_point, F)), axis=0)
            self.nadir_point = np.max(np.vstack((self.nadir_point, F)), axis=0)

        elif self.normalization == "front":
            front = fronts[0]
            if len(front) > 1:
                self.ideal_point = np.min(F[front], axis=0)
                self.nadir_point = np.max(F[front], axis=0)

        elif self.normalization == "no":
            self.ideal_point = np.zeros(self.n_obj)
            self.nadir_point = np.ones(self.n_obj)

        if self.extreme_points_as_reference_points:
            self.ref_points = np.row_stack(
                [self.ref_points,
                 get_extreme_points_c(F, self.ideal_point)])

        # calculate the distance matrix from ever solution to all reference point
        dist_to_ref_points = calc_norm_pref_distance(F, self.ref_points,
                                                     self.weights,
                                                     self.ideal_point,
                                                     self.nadir_point)

        for k, front in enumerate(fronts):

            # save rank attributes to the individuals - rank = front here
            pop[front].set("rank", np.full(len(front), k))

            # number of individuals remaining
            n_remaining = n_survive - len(survivors)

            # the ranking of each point regarding each reference point (two times argsort is necessary)
            rank_by_distance = np.argsort(np.argsort(dist_to_ref_points[front],
                                                     axis=0),
                                          axis=0)

            # the reference point where the best ranking is coming from
            ref_point_of_best_rank = np.argmin(rank_by_distance, axis=1)

            # the actual ranking which is used as crowding
            ranking = rank_by_distance[np.arange(len(front)),
                                       ref_point_of_best_rank]

            if len(front) <= n_remaining:

                # we can simply copy the crowding to ranking. not epsilon selection here
                crowding = ranking
                I = np.arange(len(front))

            else:

                # Distance from solution to every other solution and set distance to itself to infinity
                dist_to_others = calc_norm_pref_distance(
                    F[front], F[front], self.weights, self.ideal_point,
                    self.nadir_point)
                np.fill_diagonal(dist_to_others, np.inf)

                # the crowding that will be used for selection
                crowding = np.full(len(front), np.nan)

                # solutions which are not already selected - for
                not_selected = np.argsort(ranking)

                # until we have saved a crowding for each solution
                while len(not_selected) > 0:

                    # randomly select an alive individual
                    if self.survival_type == "random":
                        idx = not_selected[random.randint(
                            0, len(not_selected))]
                    elif self.survival_type == "closest":
                        idx = not_selected[0]
                    else:
                        raise Exception("Unknown survival type.")

                    # set crowding for that individual
                    crowding[idx] = ranking[idx]

                    # need to remove myself from not-selected array
                    to_remove = [idx]

                    # Group of close solutions
                    dist = dist_to_others[idx][not_selected]
                    group = not_selected[np.where(dist < self.epsilon)[0]]

                    # if there exists solution with a distance less than epsilon
                    if len(group):
                        # discourage them by giving them a high crowding
                        crowding[group] = ranking[group] + np.round(
                            len(front) / 2)

                        # remove group from not_selected array
                        to_remove.extend(group)

                    not_selected = np.array(
                        [i for i in not_selected if i not in to_remove])

                # now sort by the crowding (actually modified rank) ascending and let the best survive
                I = np.argsort(crowding)[:n_remaining]

            # set the crowding to all individuals
            pop[front].set("crowding", crowding)

            # extend the survivors by all or selected individuals
            survivors.extend(front[I])

        # inverse of crowding because nsga2 does maximize it (then tournament selection can stay the same)
        pop.set("crowding", -pop.get("crowding"))

        return pop[survivors]
Exemplo n.º 15
0
 def sample(self, problem, n_samples, **kwargs):
     return random.randint(0, 2, size=(n_samples, problem.n_var))
Exemplo n.º 16
0
    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
Exemplo n.º 17
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)
Exemplo n.º 18
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)
Exemplo n.º 19
0
 def _do(self, problem, pop, parents, **kwargs):
     # get the X of parents and count the matings
     X = pop.get("X")[parents.T]
     _, n_matings, n_var = X.shape
     print("Number of matings: %s" %n_matings)
     #print("Number of variables: %s" %n_var)
     #print("Number of offspring: %s" %self.n_offsprings)
     children = np.full((self.n_offsprings*n_matings, problem.n_var), np.inf)
     k=0
     while k < n_matings*self.n_offsprings:
         x1 = []
         x2 = []
         #not sure about this method for selecting x1 and x2... need to preserve elitism more
         #while x1==x2:
         try:
             x1 = X[0][random.randint(0,n_matings-1)].copy()
             x1 = x1.tolist()
             x2 = X[1][random.randint(0,n_matings-1)].copy()
             x2 = x2.tolist()
         except:
             x1 = X[0][0].copy()
             x1 = x1.tolist()
             x2 = X[0][0].copy()
             x2 = x2.tolist()
         #print("X1:")
         #print(x1)
         #print("X2:")
         #print(x2)
         og_x1 = x1.copy()
         og_x2 = x2.copy()
         cycles = []
         cycles_index1 = []
         cycles_index2 = []
         num_cyc = 0
         while len(x1) > 1:
             cycle = []
             cycle_index1 = []
             cycle_index2 = []
             index=0
             cycle.append(x1[index])
             index_1 = og_x1.index(x1[index])
             cycle_index1.append(index_1)
             index_2 = og_x2.index(x1[index])
             cycle_index2.append(index_2)
             x1.pop(index)
             while cycle[0] != x2[index]:
                 temp = x2[index]
                 x2.pop(index)
                 cycle.append(temp)
                 #note: using obj.index may be slow for long lists
                 index = x1.index(temp)
                 index_1 = og_x1.index(temp)
                 cycle_index1.append(index_1)
                 x1.pop(index)
                 index_2 = og_x2.index(temp)
                 cycle_index2.append(index_2)
             num_cyc = num_cyc + 1
             x2.pop(index)
             cycles_index1.append(cycle_index1)
             cycles_index2.append(cycle_index2)
             cycles.append(cycle)
         if len(x1) == 1:
             cycles.append([x2[0]])
             x1.pop
             x2.pop
             index_2=og_x2.index(x2[0])
             index_1=og_x1.index(x1[0])
             cycles_index2.append([index_2])
             cycles_index1.append([index_1])
             num_cyc = num_cyc + 1
         child1 = np.zeros(len(og_x1))
         child2 = np.zeros(len(og_x2))
         i=1
         #print("Num cyc %s" %num_cyc)
         while i<num_cyc:
             child1[cycles_index1[i-1]] = cycles[i-1]
             child2[cycles_index2[i-1]] = cycles[i-1]
             child1[cycles_index2[i]] = cycles[i]
             child2[cycles_index1[i]] = cycles[i]
             i +=2
         if np.mod(num_cyc,2)!=0:
             child1[cycles_index1[i-1]] = cycles[i-1]
             child2[cycles_index2[i-1]] = cycles[i-1]
         children[k] = child1
         try:
             children[k+1] = child2
         except:
             pass
         k += 2
         #The method to fill children[] is fine for now as long as k's limit is even
     #print("Children")
     children = children.astype(int)
     #print(children)
     return pop.new("X", children)
Exemplo n.º 20
0
    def solve(self,
              problem,
              termination,
              seed=None,
              disp=False,
              callback=None,
              save_history=False,
              pf=None,
              **kwargs):
        """

        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

        termination: 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.

        disp : bool
            If it is true than information during the algorithm execution are displayed

        callback : func
            A callback function can be passed that is executed every generation. The parameters for the function
            are the algorithm itself, the number of evaluations so far and the current population.

                def callback(algorithm):
                    pass

        save_history : bool
            If true, a current snapshot of each generation is saved.

        pf : np.array
            The Pareto-front for the given problem. If provided performance metrics are printed during execution.

        Returns
        -------
        res : dict
            A dictionary that saves all the results of the algorithm. Also, the history if save_history is true.

        """

        # set the random seed for generator
        if seed is not None:
            random.seed(seed)
        else:
            seed = random.randint(0, 10000000)
            random.seed(seed)

        # the evaluator object which is counting the evaluations
        self.evaluator = Evaluator()
        self.problem = problem
        self.termination = termination
        self.pf = pf

        self.disp = disp
        self.callback = callback
        self.save_history = save_history

        # call the algorithm to solve the problem
        pop = self._solve(problem, termination)

        # get the optimal result by filtering feasible and non-dominated
        if self.opt is None:
            opt = pop.copy()
        else:
            opt = self.opt

        opt = opt[opt.collect(lambda ind: ind.feasible)[:, 0]]

        # if at least one feasible solution was found
        if len(opt) > 0:

            if problem.n_obj > 1:
                I = NonDominatedSorting().do(opt.get("F"),
                                             only_non_dominated_front=True)
                opt = opt[I]
                X, F, CV, G = opt.get("X", "F", "CV", "G")

            else:
                opt = opt[np.argmin(opt.get("F"))]
                X, F, CV, G = opt.X, opt.F, opt.CV, opt.G
        else:
            opt = None

        res = Result(opt, opt is None, "")
        res.algorithm, res.problem, res.pf = self, problem, pf
        res.pop = pop

        if opt is not None:
            res.X, res.F, res.CV, res.G = X, F, CV, G

        res.history = self.history

        return res