Exemple #1
0
    def _exploration_move(self, center, opt=None):
        if opt is None:
            opt = center

        def step(x, delta, k):

            # copy and add delta to the new point
            X = np.copy(x)

            # normalize the delta by the bounds if they are provided by the problem
            eps = delta[k]

            # if the problem has bounds normalize the delta
            if self.problem.has_bounds():
                xl, xu = self.problem.bounds()
                eps *= (xu[k] - xl[k])

            # now add to the current solution
            X[k] = X[k] + eps

            # repair if out of bounds if necessary
            X = set_to_bounds_if_outside_by_problem(self.problem, X)

            # return the new solution as individual
            mutant = pop_from_array_or_individual(X)[0]

            return mutant

        for k in range(self.problem.n_var):

            # create the the individual and evaluate it
            mutant = step(center.X, self.explr_delta, k)
            self.evaluator.eval(self.problem, mutant, algorithm=self)
            self.pop = Population.merge(self.pop, mutant)

            if is_better(mutant, opt):
                center, opt = mutant, mutant

            else:

                # inverse the sign of the delta
                self.explr_delta[k] = -self.explr_delta[k]

                # now try the other sign if there was no improvement
                mutant = step(center.X, self.explr_delta, k)
                self.evaluator.eval(self.problem, mutant, algorithm=self)
                self.pop = Population.merge(self.pop, mutant)

                if is_better(mutant, opt):
                    center, opt = mutant, mutant

        return opt
Exemple #2
0
    def _next(self):

        # in the beginning of each iteration first do an exploration move
        self._previous = self.opt[0]
        self._current = self._exploration_move(self._previous)

        # one iteration is the combination of this two moves repeatedly until delta needs to be reduced
        while self._previous != self._current:

            # use the pattern move to get a new trial vector
            trial = self._pattern_move(self._previous, self._current)

            # perform an exploration move around the trial vector - the best known solution is always stored in _current
            explr = self._exploration_move(trial, opt=self._current)

            # we can break if we did not improve
            if not is_better(explr, self._current, eps=1e-6):
                break

            # else also check if we are terminating - otherwise this loop might run far too long
            self._set_optimum()
            if not self.termination.do_continue(self):
                break

            self._previous, self._current = self._current, explr

        self.explr_delta *= self.explr_rho
Exemple #3
0
    def _step(self):
        pop = self.pop
        X, F, V = pop.get("X", "F", "V")

        # get the personal best of each particle
        pbest = Population.create(*pop.get("pbest"))
        P_X, P_F = pbest.get("X", "F")

        # get the GLOBAL best solution - other variants such as local best can be implemented here too
        best = self.opt.repeat(len(pop))
        G_X = best.get("X")

        # get the inertia weight of the individual
        inerta = self.w * V

        # calculate random values for the updates
        r1 = np.random.random((len(pop), self.problem.n_var))
        r2 = np.random.random((len(pop), self.problem.n_var))

        cognitive = self.c1 * r1 * (P_X - X)
        social = self.c2 * r2 * (G_X - X)

        # calculate the velocity vector
        _V = inerta + cognitive + social
        _V = set_to_bounds_if_outside(_V, - self.V_max, self.V_max)

        # update the values of each particle
        _X = X + _V
        _X = InversePenaltyOutOfBoundsRepair().do(self.problem, _X, P=X)

        # evaluate the offspring population
        off = Population(len(pop)).set("X", _X, "V", _V, "pbest", pbest)
        self.evaluator.eval(self.problem, off, algorithm=self)

        # check whether a solution has improved or not - also consider constraints here
        has_improved = ImprovementReplacement().do(self.problem, pbest, off, return_indices=True)

        # replace the personal best of each particle if it has improved
        off[has_improved].set("pbest", off[has_improved])
        off.set("best", best)
        pop = off

        # try to improve the current best with a pertubation
        if self.pertube_best:
            pbest = Population.create(*pop.get("pbest"))
            k = FitnessSurvival().do(self.problem, pbest, 1, return_indices=True)[0]
            eta = int(np.random.uniform(5, 30))
            mutant = PolynomialMutation(eta).do(self.problem, pbest[[k]])[0]
            self.evaluator.eval(self.problem, mutant, algorithm=self)

            # if the mutant is in fact better - replace the personal best
            if is_better(mutant, pop[k]):
                pop[k].set("pbest", mutant)

        self.pop = pop
Exemple #4
0
    def _next(self):

        # number of variables increased by one - matches equations in the paper
        xl, xu = self.problem.bounds()
        pop, n = self.pop, self.problem.n_var - 1

        # calculate the centroid
        centroid = pop[:n + 1].get("X").mean(axis=0)

        # -------------------------------------------------------------------------------------------
        # REFLECT
        # -------------------------------------------------------------------------------------------

        # check the maximum alpha until the bounds are hit
        max_alpha = max_expansion_factor(centroid, (centroid - pop[n + 1].X),
                                         xl, xu)

        # reflect the point, consider factor if bounds are there, make sure in bounds (floating point) evaluate
        x_reflect = centroid + min(self.alpha,
                                   max_alpha) * (centroid - pop[n + 1].X)
        x_reflect = set_to_bounds_if_outside_by_problem(
            self.problem, x_reflect)
        reflect = self.evaluator.eval(self.problem,
                                      Individual(X=x_reflect),
                                      algorithm=self)

        # whether a shrink is necessary or not - decided during this step
        shrink = False

        better_than_current_best = is_better(reflect, pop[0])
        better_than_second_worst = is_better(reflect, pop[n])
        better_than_worst = is_better(reflect, pop[n + 1])

        # if better than the current best - check for expansion
        if better_than_current_best:

            # -------------------------------------------------------------------------------------------
            # EXPAND
            # -------------------------------------------------------------------------------------------

            # the maximum expansion until the bounds are hit
            max_beta = max_expansion_factor(centroid, (x_reflect - centroid),
                                            xl, xu)

            # expand using the factor, consider bounds, make sure in case of floating point issues
            x_expand = centroid + min(self.beta,
                                      max_beta) * (x_reflect - centroid)
            x_expand = set_to_bounds_if_outside_by_problem(
                self.problem, x_expand)

            # if the expansion is almost equal to reflection (if boundaries were hit) - no evaluation
            if np.allclose(x_expand, x_reflect, atol=1e-16):
                expand = reflect
            else:
                expand = self.evaluator.eval(self.problem,
                                             Individual(X=x_expand),
                                             algorithm=self)

            # if the expansion further improved take it - otherwise use expansion
            if is_better(expand, reflect):
                pop[n + 1] = expand
            else:
                pop[n + 1] = reflect

        # if the new point is not better than the best, but better than second worst - just keep it
        elif not better_than_current_best and better_than_second_worst:
            pop[n + 1] = reflect

        # if not worse than the worst - outside contraction
        elif not better_than_second_worst and better_than_worst:

            # -------------------------------------------------------------------------------------------
            # Outside Contraction
            # -------------------------------------------------------------------------------------------

            x_contract_outside = centroid + self.gamma * (x_reflect - centroid)
            contract_outside = self.evaluator.eval(
                self.problem, Individual(X=x_contract_outside), algorithm=self)

            if is_better(contract_outside, reflect):
                pop[n + 1] = contract_outside
            else:
                shrink = True

        # if the reflection was worse than the worst - inside contraction
        else:

            # -------------------------------------------------------------------------------------------
            # Inside Contraction
            # -------------------------------------------------------------------------------------------

            x_contract_inside = centroid - self.gamma * (x_reflect - centroid)
            contract_inside = self.evaluator.eval(
                self.problem, Individual(X=x_contract_inside), algorithm=self)

            if is_better(contract_inside, pop[n + 1]):
                pop[n + 1] = contract_inside
            else:
                shrink = True

        # -------------------------------------------------------------------------------------------
        # Shrink (only if necessary)
        # -------------------------------------------------------------------------------------------

        if shrink:
            for i in range(1, len(pop)):
                pop[i].X = pop[0].X + self.delta * (pop[i].X - pop[0].X)
            pop[1:] = self.evaluator.eval(self.problem,
                                          pop[1:],
                                          algorithm=self)

        self.pop = FitnessSurvival().do(self.problem, pop, len(pop))