Example #1
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
        best = self.opt.repeat(len(pop))
        G_X = best.get("X")

        # perform the pso equation
        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 = repair_out_of_bounds_manually(_V, -self.V_max, self.V_max)

        # update the values of each particle
        _X = X + _V
        _X = repair_out_of_bounds(self.problem, _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:
            opt = FitnessSurvival().do(self.problem,
                                       Population.create(*pop.get("pbest")), 1)
            eta = int(np.random.uniform(5, 30))
            mutant = PolynomialMutation(eta).do(self.problem, opt)
            self.evaluator.eval(self.problem, mutant, algorithm=self)
            if ImprovementReplacement().do(self.problem,
                                           opt,
                                           mutant,
                                           return_indices=True)[0]:
                k = [i for i, e in enumerate(pop.get("pbest")) if e == opt][0]
                pop[k].set("pbest", mutant)

        self.pop = pop
Example #2
0
    def _do(self, problem, X, **kwargs):

        X = X.astype(np.float)
        Y = np.full(X.shape, np.inf)

        if self.prob is None:
            self.prob = 1.0 / problem.n_var

        do_mutation = np.random.random(X.shape) < self.prob

        Y[:, :] = X

        xl = np.repeat(problem.xl[None, :], X.shape[0], axis=0)[do_mutation]
        xu = np.repeat(problem.xu[None, :], X.shape[0], axis=0)[do_mutation]

        X = X[do_mutation]

        delta1 = (X - xl) / (xu - xl)
        delta2 = (xu - X) / (xu - xl)

        mut_pow = 1.0 / (self.eta + 1.0)

        rand = np.random.random(X.shape)
        mask = rand <= 0.5
        mask_not = np.logical_not(mask)

        deltaq = np.zeros(X.shape)

        xy = 1.0 - delta1
        val = 2.0 * rand + (1.0 - 2.0 * rand) * (np.power(
            xy, (self.eta + 1.0)))
        d = np.power(val, mut_pow) - 1.0
        deltaq[mask] = d[mask]

        xy = 1.0 - delta2
        val = 2.0 * (1.0 - rand) + 2.0 * (rand - 0.5) * (np.power(
            xy, (self.eta + 1.0)))
        d = 1.0 - (np.power(val, mut_pow))
        deltaq[mask_not] = d[mask_not]

        # mutated values
        _Y = X + deltaq * (xu - xl)

        # back in bounds if necessary (floating point issues)
        _Y[_Y < xl] = xl[_Y < xl]
        _Y[_Y > xu] = xu[_Y > xu]

        # set the values for output
        Y[do_mutation] = _Y

        # in case out of bounds repair (very unlikely)
        Y = repair_out_of_bounds(problem, Y)

        return Y
Example #3
0
    def _evaluate(self, x, out, *args, **kwargs):
        out_of_bounds = np.any(repair_out_of_bounds(self, x.copy()) != x)

        f1 = x[:, 0]
        g = 1 + 9.0 / (self.n_var - 1) * np.sum((x[:, 1:]) ** 2, axis=1)
        f2 = g * (1 - np.power((f1 / g), 0.5))

        if out_of_bounds:
            f1 = np.full(x.shape[0], np.inf)
            f2 = np.full(x.shape[0], np.inf)

        out["F"] = np.column_stack([f1, f2])
Example #4
0
    def _next(self):

        # create a copy from the current values - if restart is necessary
        _X = np.copy(self.X)

        # if the gradient was not provided yet evaluate it
        if self.F is None or self.dX is None:
            # evaluate the problem and get the information of gradients
            F, dX, CV = self.problem.evaluate(
                self.X, return_values_of=["F", "dF", "CV"])

            # because we only consider one objective here
            F = F[:, [self.objective]]
            dX = dX[:, self.objective]

            # increase the evaluation count
            self.evaluator.n_eval += len(self.X)

        has_improved = self.F is None or np.any(F < self.F)
        is_gradient_valid = np.all(~np.isnan(dX))

        # if the gradient did lead to an improvement
        if has_improved:

            self.F, self.dX, self.CV = F, dX, CV

            # if the gradient is valid and has no nan values
            if is_gradient_valid:

                # make the step and check out of bounds for X
                self.apply()
                self.X = repair_out_of_bounds(self.problem, self.X)

                # set the population object for automatic print
                self.pop = Population(len(self.X)).set("X", self.X, "F",
                                                       self.F, "CV", self.CV,
                                                       "feasible",
                                                       self.CV <= 0)

            # otherwise end the termination form now on
            else:
                print("WARNING: GRADIENT ERROR", self.dX)
                self.termination.force_termination = True

        # otherwise do a restart of the algorithm
        else:
            self.X = _X
            self.restart()
            self.n_restarts += 1

        # set the gradient to none to be ready for the next iteration
        self.dX = None
Example #5
0
    def _step(self):

        # number of variables increased by one - matches equations in the paper
        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), self.problem.xl, self.problem.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 = repair_out_of_bounds(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

        # if the new point is not better than the best, but better than second worst - just take it
        if pop[0].F <= reflect.F < pop[n].F:
            pop[n + 1] = reflect

        # if even better than the best - check for expansion
        elif reflect.F < pop[0].F:

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

            # the maximum expansion until the bounds are hit
            max_beta = max_expansion_factor(centroid, (x_reflect - centroid), self.problem.xl, self.problem.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 = repair_out_of_bounds(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 expand.F < reflect.F:
                pop[n + 1] = expand
            else:
                pop[n + 1] = reflect

        # if not worst than the worst - outside contraction
        elif pop[n].F <= reflect.F < pop[n + 1].F:

            # -------------------------------------------------------------------------------------------
            # 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 contract_outside.F <= reflect.F:
                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 contract_inside.F < pop[n + 1].F:
                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)

        # finally sort the population by objective values
        pop = pop[np.argsort(pop.get("F")[:, 0])]

        return pop
Example #6
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 = repair_out_of_bounds_manually(_V, -self.V_max, self.V_max)

        # update the values of each particle
        _X = X + _V
        _X = repair_out_of_bounds(self.problem, _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
Example #7
0
    def _do(self, problem, X, **kwargs):

        X = X.astype(np.float)
        _, n_matings, n_var = X.shape

        # boundaries of the problem
        xl, xu = problem.xl, problem.xu

        #if np.any(X < xl) or np.any(X > xu):
        #    raise Exception("Simulated binary crossover requires all variables to be in bounds!")

        # crossover mask that will be used in the end
        do_crossover = np.full(X[0].shape, True)

        # per variable the probability is then 50%
        do_crossover[np.random.random((n_matings, problem.n_var)) > self.prob_per_variable] = False
        # also if values are too close no mating is done
        do_crossover[np.abs(X[0] - X[1]) <= 1.0e-14] = False

        # assign y1 the smaller and y2 the larger value
        y1 = np.min(X, axis=0)
        y2 = np.max(X, axis=0)

        # random values for each individual
        rand = np.random.random((n_matings, problem.n_var))

        def calc_betaq(beta):
            alpha = 2.0 - np.power(beta, -(self.eta + 1.0))

            mask, mask_not = (rand <= (1.0 / alpha)), (rand > (1.0 / alpha))

            betaq = np.zeros(mask.shape)
            betaq[mask] = np.power((rand * alpha), (1.0 / (self.eta + 1.0)))[mask]
            betaq[mask_not] = np.power((1.0 / (2.0 - rand * alpha)), (1.0 / (self.eta + 1.0)))[mask_not]

            return betaq

        # difference between all variables
        delta = (y2 - y1)

        # now just be sure not dividing by zero (these cases will be filtered later anyway)
        # delta[np.logical_or(delta < 1.0e-10, np.logical_not(do_crossover))] = 1.0e-10
        delta[delta < 1.0e-10] = 1.0e-10

        beta = 1.0 + (2.0 * (y1 - xl) / delta)
        betaq = calc_betaq(beta)
        c1 = 0.5 * ((y1 + y2) - betaq * delta)

        beta = 1.0 + (2.0 * (xu - y2) / delta)
        betaq = calc_betaq(beta)
        c2 = 0.5 * ((y1 + y2) + betaq * delta)

        # do randomly a swap of variables
        b = np.random.random((n_matings, problem.n_var)) <= 0.5
        val = np.copy(c1[b])
        c1[b] = c2[b]
        c2[b] = val

        # take the parents as _template
        c = np.copy(X)

        # copy the positions where the crossover was done
        c[0, do_crossover] = c1[do_crossover]
        c[1, do_crossover] = c2[do_crossover]

        c[0] = repair_out_of_bounds(problem, c[0])
        c[1] = repair_out_of_bounds(problem, c[1])

        if self.n_offsprings == 1:
            # Randomly select one offspring
            c = c[np.random.choice(2, X.shape[1]), np.arange(X.shape[1])]
            c = c.reshape((1, X.shape[1], X.shape[2]))

        return c
Example #8
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 = repair_out_of_bounds(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 = repair_out_of_bounds(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))