遗传算法解决低维和高维函数最优化问题

遗传算法解决低维和高维函数最优化问题,第1张

遗传算法解决低维和高维函数最优化问题
import numpy as np
from random import random


class EABi:
    def __init__(self, n_var, lb, ub, ff, wf, populations=50, iterations=2000, eps=1e-4,
                 cross_method='1', p_cross=0.1, mutation_method='1', p_mutation=0.05,
                 choose_method='1', cnt_saves=4):
        self.n = n_var
        self.fitness_function = ff
        # wrapper for MIN function
        self.wrapper_function = wf
        self.populations = populations
        self.iterations = iterations
        self.eps = eps
        self.lb = lb
        self.ub = ub
        # length of each variables(in BIN)
        self.l = np.asarray(np.ceil(np.log2((self.ub - self.lb) / eps + 1)), dtype=np.int32)
        self.end_of_var = np.concatenate((np.array([0], dtype=np.int32), np.cumsum(self.l)), axis=None)
        # length of each individual
        self.len_individual = np.sum(self.l)

        self.cross_method = cross_method
        self.p_cross = p_cross
        self.mutation_method = mutation_method
        self.p_mutation = p_mutation
        self.choose_method = choose_method

        # generate pow(2, n) for speed, shape=(len, 1)
        self.pow2 = 2 ** np.arange(np.max(self.l) + 2).reshape(-1, 1)

        self.chrom, self.fitness = self.initRace()
        self.new_chrom = None

        # frequency to save chrom
        self.save_freq = int(self.iterations / cnt_saves)

    def decode(self, individual=None):
        if individual is None:
            res = np.zeros((self.populations, self.n))
            for j in range(self.n):
                res[:, j] = self.lb[j] + (self.ub[j] - self.lb[j]) / (self.pow2[self.l[j], 0] - 1) * 
                            np.dot(self.chrom[:, self.end_of_var[j]:self.end_of_var[j + 1]],
                                   self.pow2[:self.l[j]]).reshape((-1,))
        else:
            individual = individual.reshape((-1, self.len_individual))
            res = np.zeros((individual.shape[0], self.n))
            for j in range(self.n):
                res[:, j] = self.lb[j] + (self.ub[j] - self.lb[j]) / (self.pow2[self.l[j], 0] - 1) * 
                            np.dot(individual[:, self.end_of_var[j]:self.end_of_var[j + 1]],
                                   self.pow2[:self.l[j]]).reshape((-1,))
        return res

    def initRace(self):
        chrom = np.random.rand(self.populations, self.len_individual) > 0.5
        fitness = self.getFitness(chrom)
        return chrom, fitness

    def cross(self):
        if self.cross_method == '1':
            for i in range(self.populations):
                for j in range(i + 1, self.populations):
                    if random() < self.p_cross:
                        t = np.random.randint(0, self.len_individual)
                        tmp = self.new_chrom[i, t:]
                        self.new_chrom[i, t:] = self.new_chrom[j, t:]
                        self.new_chrom[j, t:] = tmp
        else:
            pass

    def mutation(self):
        if self.cross_method == '1':
            rand = np.random.rand(*self.chrom.shape)
            is_change = rand < self.p_mutation
            self.new_chrom = self.new_chrom ^ is_change
        else:
            pass

    def choose(self, keep_cnt=2):
        self.new_chrom = np.vstack((self.new_chrom, self.chrom), )
        fitness = self.getFitness()
        tmp_id = np.argsort(-fitness)
        self.new_chrom = self.new_chrom[tmp_id, :]
        fitness = fitness[tmp_id]
        # Keep the top keep_cnt-th individual
        self.chrom[0:keep_cnt, :] = self.new_chrom[0:keep_cnt, :]
        self.fitness[0:keep_cnt] = fitness[0:keep_cnt]
        # Decide the others
        if self.choose_method == '1':
            # Lun pan du
            # CAUTION: `fitness` MUST BE POSITIVE
            # adjust `self.wrapper_function` to make it
            fitness = fitness[keep_cnt:]
            self.new_chrom = self.new_chrom[keep_cnt:, ]
            p = fitness / np.sum(fitness)
            sum_p = np.cumsum(p)
            cnt = keep_cnt
            while cnt < self.populations:
                r = random()
                j = 0
                for i in range(p.shape[0]):
                    if r <= sum_p[i]:
                        j = i
                        break
                self.chrom[cnt, :] = self.new_chrom[j, :]
                self.fitness[cnt] = fitness[j]
                cnt += 1
        else:
            pass

    def getFitness(self, x=None):
        if x is None:
            de = self.decode(self.new_chrom)
            fitness = np.array(
                [self.wrapper_function(self.fitness_function(de[i, :])) for i in range(self.new_chrom.shape[0])])
        else:
            x = x.reshape((-1, self.len_individual))
            de = self.decode(x)
            fitness = np.array([self.wrapper_function(self.fitness_function(de[i, :])) for i in range(x.shape[0])])
        return fitness

    def main(self):
        best_fit = [np.max(self.fitness)]
        mean_fit = [np.mean(self.fitness)]
        saved_idx = [0]
        saved_chrom = [self.decode()]
        for i in range(1, self.iterations):
            self.new_chrom = self.chrom.copy()
            self.cross()
            self.mutation()
            self.choose()
            best_fit.append(np.max(self.fitness))
            mean_fit.append(np.mean(self.fitness))
            # print(np.mean(self.fitness), np.max(self.fitness))
            if i % self.save_freq == 0:
                saved_idx.append(i)
                saved_chrom.append(self.decode())
        saved_idx.append(self.iterations)
        saved_chrom.append(self.decode())
        return np.array(mean_fit), np.array(best_fit), saved_idx, np.array(saved_chrom)


class EAReal:
    def __init__(self, n_var, lb, ub, ff, wf, populations=50, iterations=2000, eps=1,
                 cross_method='1', p_cross=0.2, mutation_method='1', p_mutation=0.8,
                 choose_method='1', cnt_saves=4):
        self.n = n_var
        self.fitness_function = ff
        # wrapper for MIN function
        self.wrapper_function = wf
        self.populations = populations
        self.iterations = iterations
        self.eps = eps
        self.len_individual = self.n  # length of each individual
        self.lb = lb.reshape((1, -1))
        self.ub = ub.reshape((1, -1))

        self.cross_method = cross_method
        self.p_cross = p_cross
        self.mutation_method = mutation_method
        self.p_mutation = p_mutation

        self.choose_method = choose_method

        self.chrom, self.fitness = self.initRace()
        self.new_chrom = None

        # frequency to save chrom
        self.save_freq = int(self.iterations / cnt_saves)

    def decode(self):
        return self.chrom.copy()

    def initRace(self):
        chrom = np.random.rand(self.populations, self.n)
        chrom = chrom * (self.ub - self.lb) + self.lb
        return chrom, self.getFitness(chrom)

    def cross(self, lamb=0.7):
        if self.cross_method == '1':
            for i in range(self.populations):
                for j in range(i + 1, self.populations):
                    if random() < self.p_cross:
                        self.new_chrom[i, :] = lamb * self.chrom[i, :] + (1 - lamb) * self.chrom[j, :]
                        self.new_chrom[j, :] = lamb * self.chrom[j, :] + (1 - lamb) * self.chrom[i, :]
        else:
            pass

    def mutation(self):
        if self.cross_method == '1':
            rand = np.random.rand(*self.chrom.shape)
            is_change = rand < self.p_mutation
            rand = np.random.rand(*self.chrom.shape)
            is_neg = np.ones_like(is_change, dtype=int)
            is_neg[rand < 0.5] = -1
            self.new_chrom = self.new_chrom + is_change * is_neg * self.eps
        else:
            pass

    def choose(self, keep_cnt=2):
        assert np.all(self.new_chrom <= self.ub) and np.all(self.new_chrom >= self.lb)
        self.new_chrom = np.vstack((self.new_chrom, self.chrom), )
        fitness = self.getFitness()
        tmp_id = np.argsort(-fitness)
        self.new_chrom = self.new_chrom[tmp_id, :]
        fitness = fitness[tmp_id]
        # Keep the top keep_cnt-th individual
        self.chrom[0:keep_cnt, :] = self.new_chrom[0:keep_cnt, :]
        self.fitness[0:keep_cnt] = fitness[0:keep_cnt]
        # Decide the others
        if self.choose_method == '1':
            # Lun pan du
            # CAUTION: `fitness` MUST BE POSITIVE
            # adjust `self.wrapper_function` to make it
            fitness = fitness[keep_cnt:]
            self.new_chrom = self.new_chrom[keep_cnt:, ]
            p = fitness / np.sum(fitness)
            sum_p = np.cumsum(p)
            cnt = keep_cnt
            while cnt < self.populations:
                r = random()
                j = 0
                for i in range(p.shape[0]):
                    if r <= sum_p[i]:
                        j = i
                        break
                self.chrom[cnt, :] = self.new_chrom[j, :]
                self.fitness[cnt] = fitness[j]
                cnt += 1
        else:
            pass

    def getFitness(self, x=None):
        if x is None:
            fitness = np.array([self.wrapper_function(self.fitness_function(self.new_chrom[i, :])) for i in
                                range(self.new_chrom.shape[0])])
        else:
            x = x.reshape((-1, self.n))
            fitness = np.array([self.wrapper_function(self.fitness_function(x[i, :])) for i in range(x.shape[0])])
        return fitness

    def main(self):
        best_fit = [np.max(self.fitness)]
        mean_fit = [np.mean(self.fitness)]
        saved_idx = [0]
        saved_chrom = [self.decode()]
        for i in range(1, self.iterations):
            if i % 50 == 0:
                self.ub = np.max(self.chrom, axis=0, keepdims=True)
                self.lb = np.min(self.chrom, axis=0, keepdims=True)
            if i == 100:
                self.eps /= 2
            elif i == 500:
                self.eps /= 2
            self.new_chrom = self.chrom.copy()
            self.cross()
            self.mutation()
            self.new_chrom = np.maximum(np.minimum(self.new_chrom, self.ub), self.lb)
            self.choose()
            best_fit.append(np.max(self.fitness))
            mean_fit.append(np.mean(self.fitness))
            # print(np.mean(self.fitness), np.max(self.fitness))
            if i % self.save_freq == 0:
                saved_idx.append(i)
                saved_chrom.append(self.decode())
        saved_idx.append(self.iterations)
        saved_chrom.append(self.decode())
        return np.array(mean_fit), np.array(best_fit), saved_idx, np.array(saved_chrom)


def f(x):
    return np.dot(x, x)


def test_real():
    n_var = 3
    ea = EAReal(n_var, np.ones(n_var) * (-10), np.ones(n_var) * 10, f)
    ea.main()
    # print('-------------------------------')
    # ea = EAReal(n_var, ea.lb, ea.ub, f)
    # ea.main()
    # print('-------------------------------')
    # ea = EAReal(n_var, ea.lb, ea.ub, f)
    # ea.main()
    print(ea.chrom)


def test_bin():
    n_var = 3
    ea = EABi(n_var, np.ones(n_var) * (-10), np.ones(n_var) * 10, f)
    ea.main()
    print(ea.decode())


if __name__ == '__main__':
    test_real()

from ea import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


def Ball(x):
    # min x^2 + y^2
    # [-5.12, 5.12]
    return x[0] * x[0] + x[1] * x[1]


def DeJong(x):
    # min 100(y - x^2)^2 + (x - 1)^2
    # [-2.048, 2.048]
    return 100 * (x[1] - x[0] ** 2) ** 2 + (x[0] - 1) * (x[0] - 1)


def HimmelBaut(x):
    # min
    # [-6, 6]
    x, y = x[0], x[1]
    return (x * x + y - 11) * (x * x + y - 11) + (x + y * y - 7) * (x + y * y - 7)


def SixHumpCamelBack(x):
    # min
    # [-5, 5]
    # C = 3
    x, y = x[0], x[1]
    return 4 * x * x - 2.1 * x ** 4 + 1 / 3 * x ** 6 + x * y - 4 * y * y + 4 * y ** 4


def Shubert(x):
    # min
    # [-10, 10]
    # C = 190
    x, y = x[0], x[1]
    return (sum([i * np.cos((i + 1) * x + i) for i in range(1, 6)])) * (
        sum([i * np.cos((i + 1) * y + i) for i in range(1, 6)]))


def draw(fun, lb, ub, idx, chrom, title, fig):
    for i in range(5):
        if 'Real' in title:
            ax = fig.add_subplot(6, 5, i + 16)
        else:
            ax = fig.add_subplot(6, 5, i + 21)
        eps = (ub - lb) / 50
        x = np.arange(lb - eps * 5, ub + eps * 5, eps)
        y = np.arange(lb - eps * 5, ub + eps * 5, eps)
        xx, yy = np.meshgrid(x, y)
        zz = fun(np.array([xx, yy]))
        ax.contourf(xx, yy, zz, cmap='rainbow', levels=100)
        x = chrom[i, :, 0]
        y = chrom[i, :, 1]
        ax.scatter(x, y, s=2, marker='x', c='black')
        ax.set_title(title + ' in ' + str(idx[i]), fontsize=8)
        ax.tick_params(labelsize=6)


def wrapper(x):
    return 1 / (1 + x)


def main():
    fun = Ball
    n_var = 2
    lb = np.ones(n_var) * (-5.12)
    ub = np.ones(n_var) * (5.12)

    ea = EAReal(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
    real_mean, real_best, real_id, real_chrom = ea.main()
    real_res = 'EAReal: ' + str(ea.decode()[0]) + ' ' + str(real_best[-1])
    print(real_res)

    ea = EABi(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
    bi_mean, bi_best, bi_id, bi_chrom = ea.main()
    bi_res = 'EABi: ' + str(ea.decode()[0]) + ' ' + str(bi_best[-1])
    print(bi_res)

    fig = plt.figure(1, figsize=(10, 12))

    ax = fig.add_subplot(2, 1, 1, projection='3d')
    eps = (ub[0] - lb[0]) / 100
    x = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
    y = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
    xx, yy = np.meshgrid(x, y)
    zz = fun(np.array([xx, yy]))
    ax.plot_surface(xx, yy, zz, cmap='rainbow')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('g(x, y)')
    ax.set_title('3D plot')

    draw(fun, lb[0], ub[0], real_id, real_chrom, 'EAReal', fig)
    draw(fun, lb[0], ub[0], bi_id, bi_chrom, 'EABi', fig)
    ax1 = fig.add_subplot(616)
    idx = np.arange(0, 2000, 10, dtype=int)
    plt1 = ax1.plot(idx, real_mean[idx], 'r', label='EAReal-mean')
    plt2 = ax1.plot(idx, bi_mean[idx], 'g', label='EABi-mean')
    ax2 = ax1.twinx()
    plt3 = ax2.plot(real_best, '--', color='orange', label='EAReal-best')
    plt4 = ax2.plot(bi_best, '--', color='b', label='EABi-best')
    line = plt1 + plt3 + plt2 + plt4
    ax1.set_xlabel('iterations')
    ax1.set_ylabel('mean fitness')
    ax2.set_ylabel('best fitness')
    plt.legend(line, [l.get_label() for l in line], fontsize=7)
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
                        wspace=0.5, hspace=0.4)
    plt.text(0, -1, real_res + 'n' + bi_res, size=12, transform=ax1.transAxes)
    plt.savefig('2' + str(fun.__name__) + '.pdf', bbox_inches='tight')


if __name__ == '__main__':
    main()


from ea import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


def Ball(x):
    # min x^2 + y^2
    # [-100, 100]
    return np.sum(x * x, axis=0)


def Step(x):
    # min
    # [-10, 10]
    return np.sum(np.floor(x + 0.5) ** 2, axis=0)


def Rastrigin(x):
    # min
    # [-5.12, 5.12]
    A = 10
    return np.sum(A + x * x - A * np.cos(2 * np.pi * x), axis=0)


def RosenBrock(x):
    # min
    # [-2.048, 2.048]
    x0 = x[:-1]
    x1 = x[1:]
    return np.sum((1 - x0) ** 2 + 100 * (x1 - x0 ** 2) ** 2, axis=0)


def Ackley(x):
    # min
    # [-32, 32]
    s1 = np.sum(x * x, axis=0)
    s2 = np.sum(np.cos(2 * np.pi * x), axis=0)
    n = x.shape[0]
    return -20 * np.exp(-0.2 * np.sqrt(s1 / n)) - np.exp(s2 / n) + 20 + np.e


def draw(fun, lb, ub, idx, chrom, title, fig):
    for i in range(5):
        if 'Real' in title:
            ax = fig.add_subplot(6, 5, i + 16)
        else:
            ax = fig.add_subplot(6, 5, i + 21)
        eps = (ub - lb) / 100
        x = np.arange(lb - eps * 10, ub + eps * 10, eps)
        y = np.arange(lb - eps * 10, ub + eps * 10, eps)
        xx, yy = np.meshgrid(x, y)
        zz = fun(np.array([xx, yy]))
        ax.contourf(xx, yy, zz, cmap='rainbow', levels=100)
        x = chrom[i, :, 0]
        y = chrom[i, :, 1]
        ax.scatter(x, y, s=2, marker='x', c='black')
        ax.set_title(title + ' in ' + str(idx[i]), fontsize=8)
        ax.tick_params(labelsize=6)


def wrapper(x):
    return 1 / (1 + x)


def main():
    fun = Ball
    n_var = 10
    lb = np.ones(n_var) * (-100)
    ub = np.ones(n_var) * (100)

    ea = EAReal(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
    real_mean, real_best, real_id, real_chrom = ea.main()
    real_res = 'EAReal: ' + str(ea.decode()[0]) + ' ' + str(real_best[-1])
    print(real_res)

    ea = EABi(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
    bi_mean, bi_best, bi_id, bi_chrom = ea.main()
    bi_res = 'EABi: ' + str(ea.decode()[0]) + ' ' + str(bi_best[-1])
    print(bi_res)

    fig = plt.figure(1, figsize=(10, 12))

    ax = fig.add_subplot(2, 1, 1, projection='3d')
    eps = (ub[0] - lb[0]) / 200
    x = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
    y = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
    xx, yy = np.meshgrid(x, y)
    zz = fun(np.array([xx, yy]))
    ax.plot_surface(xx, yy, zz, cmap='rainbow')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('g(x, y)')
    ax.set_title('3D plot')

    draw(fun, lb[0], ub[0], real_id, real_chrom, 'EAReal', fig)
    draw(fun, lb[0], ub[0], bi_id, bi_chrom, 'EABi', fig)
    ax1 = fig.add_subplot(616)
    idx = np.arange(0, 2000, 10, dtype=int)
    plt1 = ax1.plot(idx, real_mean[idx], 'r', label='EAReal-mean')
    plt2 = ax1.plot(idx, bi_mean[idx], 'g', label='EABi-mean')
    ax2 = ax1.twinx()
    plt3 = ax2.plot(real_best, '--', color='orange', label='EAReal-best')
    plt4 = ax2.plot(bi_best, '--', color='b', label='EABi-best')
    line = plt1 + plt3 + plt2 + plt4
    ax1.set_xlabel('iterations')
    ax1.set_ylabel('mean fitness')
    ax2.set_ylabel('best fitness')
    plt.legend(line, [l.get_label() for l in line], fontsize=7)
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
                        wspace=0.5, hspace=0.4)
    plt.text(0, -1, real_res + 'n' + bi_res, size=12, transform=ax1.transAxes)
    plt.savefig('n' + str(fun.__name__) + '.pdf', bbox_inches='tight')


if __name__ == '__main__':
    main()


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5657719.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存