禁忌搜索算法TS(学习笔记_04)

1. 特点

  • 禁忌准则:禁忌表和禁忌对象的设置,使算法避免迂回搜索

  • 藐视准则(特赦准则):对禁忌策略的放松

  • 新解为优良解的概率高:局部搜索能力强

    • 优于best so far的解

    • 非禁忌的最优解(可以接受劣质解,全局搜索能力强)

2. 基本参数

  • L :禁忌长度,指禁忌对象在不考虑特赦准则的情况下不允许被选取的最大次数

  • taboo :禁忌表,组织搜索过程中出现循环和避免陷入局部最优(数据结构:FIFO队列)

  • near_num:邻域解的个数

  • iter_max: 最大迭代次数

  • w :自适应权重系数,产生邻域解时使用

3. 基本流程

  1. 初始化参数,产生初始化解,置空禁忌表

  2. while(终止条件)

    1. 由当前解产生near_num个邻域解

    2. 选出最优的邻域解作为候选解

    3. if (藐视准则,候选解优于最优解)

      1. 更新最优解

      2. 更新新的当前解

      3. 更新禁忌表

    4. else

      1. if(候选解在禁忌表)

        1. 用当前解重新产生邻域解

      2. else 候选解不在紧急表中

        1. 找到非禁忌对象的最佳解

        2. 更新新的当前解更新禁忌表

      3. end

  3. end

4. 改进方向

  • TS对于初始解具有较强的依赖性。

    可以与遗传算法、模拟退火算法等优化算法结合,产生较好的初始解。

  • 迭代搜索过程是串行的。

    • 对TS本身的操作、参数选取进行改进,对算法初始化、参数设置等方面实施并行策略。

    • 与遗传算法、神经网络以及基于问题信息的局部搜索相结合。

  • 在集中性与多样性并重的情况下,多样性不足。

    • 对算法进行重新随机初始化。

    • 根据频率信息对一些已知对象进行惩罚。

5.  随机产生初始值的TS

%% 随机产生初始值的TS

clear;
close all;
clc;

x_max = 5;
x_min = -5;
y_max = 5;
y_min = -5;

w = 1;  % 自适应权重系数
L = randi([5,11]);  % 禁忌表长度
near_num = 5;  % 邻域解(neighborhood solution)的个数
iter_max = 200;   % 最大迭代次数
taboo = [];  % 禁忌表

% 定义存储数组
cur_x = zeros(iter_max,1);  % 当前位置数组
cur_y = zeros(iter_max,1);
cur_func = zeros(iter_max,1);

%% 1.随机产生初始解
x0 = rand * (x_max - x_min) + x_min;
y0 = rand * (y_max - y_min) + y_min;
best_x = x0;  % 记录最优解位置
best_y = y0;
cur_x(1) = x0;  % 记录当前解位置
cur_y(1) = y0;
cur_func(1) = func(cur_x(1),cur_y(1));  % 当前解
best = func(best_x,best_y);  % 最优解

i = 1;
while i < iter_max
    %% 2.由当前解产生邻域解
    w = 0.998 * w;
    for j =1:near_num
        % 产生一个邻域解
        near_x(j) = cur_x(i)+(2*rand-1)*(x_max-x_min)*w;
        near_y(j) = cur_y(i)+(2*rand-1)*(y_max-y_min)*w;
        % 边界处理(边界吸收)
        if near_x(j) < x_min
            near_x(j) = x_min;
        end
        if near_x(j) > x_max
            near_x(j) = x_max;
        end
        if near_y(j) < y_min
            near_y(j) = y_min;
        end
        if near_y(j) > y_max
            near_y(j) = y_max;
        end
        % 计算邻域解点处的函数值
        near_func(j) = func(near_x(j),near_y(j));
    end
    
    %% 3.将最优邻域解作为候选解
    %temp = find(near_func == max(near_func));  %找到最优邻域解的位置
    temp = 1;
    for k =2:near_num
        if near_func(k) < near_func(temp)
            temp = k;
        end
    end
    candidate_x(i) = near_x(temp);
    candidate_y(i) = near_y(temp);
    candidate_func(i) = near_func(temp);
    
    %% 4.判断是否满足藐视准则
    deta_cc = candidate_func(i) - cur_func(i);  %% 候选解与当前解的评价函数差
    deta_cb = candidate_func(i) - best;  % 候选解与最优解的评价函数差
    
    if deta_cc >= 0  % 候选解>=当前解,更新下一个当前解
        cur_x(i+1) = candidate_x(i);
        cur_y(i+1) = candidate_y(i);
        cur_func(i+1) = candidate_func(i);
        % 更新禁忌表
        taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
        if size(taboo,1) > L
            taboo(1,:) = [];
        end
        i = i + 1;
    else
        if deta_cb < 0  % 候选解<最优解,更新下一个当前解、最优解
            cur_x(i+1) = candidate_x(i);
            cur_y(i+1) = candidate_y(i);
            cur_func(i+1) = candidate_func(i);
            best = candidate_func(i);  % 更新最优解
            best_x = candidate_x(i);
            best_y = candidate_y(i);
            % 更新禁忌表
            taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
            if size(taboo,1) > L
                taboo(1,:) = [];
            end
            i = i + 1;
        else
            [M,N] = size(taboo);  %判断是否在禁忌表中
            r = 0;
            for m = 1:M
                if candidate_x(i) == taboo(m,1) && candidate_y(i) == taboo(m,2)
                    r = 1;
                end
            end
            
            if r == 0  % 不在禁忌表中,更新下一次当前解,反之用当前解重新产生邻域
                cur_x(i+1) = candidate_x(i);
                cur_y(i+1) = candidate_y(i);
                cur_func(i+1) = candidate_func(i);
                % 更新禁忌表
                taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
                if size(taboo,1) > L
                    taboo(1,:) = [];
                end
                i = i + 1;
            end
        end
    end
    trace(i) = best;
end

figure
disp('最小值在点:');
best_x
best_y
disp( '最小值为:');
best

plot(trace)
hold on;
legend_str = {'随机初始解TS','BSAPSO产生初始解TS'};
xlabel('迭代次数')
ylabel('适应度值')
title('适应度进化曲线')


function results = func(x,y)
    results = 5 * cos(x * y)+ x * y + y * y * y;
end

6. BSAPSO产生初始值的TS

%% BSAPSO算法产生初始值的TS

x_max = 5;
x_min = -5;
y_max = 5;
y_min = -5;
w = 1;  % 自适应权重系数
L = randi([5,11]);  % 禁忌表长度
near_num = 5;  % 邻域解(neighborhood solution)的个数
iter_max = 200;   % 最大迭代次数
taboo = [];  % 禁忌表

% 定义存储数组
cur_x = zeros(iter_max,1);  % 当前位置数组
cur_y = zeros(iter_max,1);
cur_func = zeros(iter_max,1);

% BSAPSO 参数
m = 30;  %粒子数量
d = 2;  %粒子维度
ac1 = 2.0;  % 自身认知函数初始值
ac2 = 0.5;
sa_k = 0.98;  %衰减因子
iwe = 3;  % 惯性权重调整步数
w_max = 0.8;
w_min = 0.4;
v_max = 1;
v_min = -1;
t_star = 100;
t_end = 0.01;

%% 1.BSAPSO产生初始解
%%% 1、初始化
x = rand(m,1) * (x_max - x_min) + x_min;
y = rand(m,1) * (y_max - y_min) + y_min;
v_x = rand(m,1) * (v_max - v_min) + v_min;
v_y = rand(m,1) * (v_max - v_min) + v_min;
%%% 初始化个体最优位置,最优值
p_x = x;  %每个粒子的个体最优解的位置
p_y = y;
pbest = ones(m,1);
for i =1:m
    pbest(i) = func(x(i),y(i));
end
%%% 初始化全局最优位置,最优值
gbest = inf;
for i=1:m
    if(pbest(i) < gbest)
        g_x = p_x(i);
        g_y = p_y(i);
        gbest = pbest(i);
    end
end
t_cur = t_star;
c1 = 1.5;
c2 = 1.5;
for i = 1:iter_max
    for j = 1:m
        %%% 2、计算每个粒子的个体最优值
        if i * 2 < iter_max   % 迭代前期采取标准的学习因子更新速度
            if (func(x(j),y(j)) < pbest(j))
                p_x(j) = x(j);  %更新个体最优解位置
                p_y(j) = y(j);
                pbest(j) = func(x(j),y(j));  %更新个体最优解
            end
        else
            deta_p = func(x(j),y(j)) - pbest(j);
            if (deta_p < 0)
                p_x(j) = x(j);  %更新个体最优解位置
                p_y(j) = y(j);
                pbest(j) = func(x(j),y(j));  %更新个体最优解
            else  %(Metropolis算法)
                p1 = exp(-1 * deta_p / t_cur);
                r = 0;
                for ii = 1:10
                    r = max(r,rand);
                end
                if p1 > r  % 接受较差的值
                    p_x(j) = x(j);  %更新个体最优解位置
                    p_y(j) = y(j);
                    pbest(j) = func(x(j),y(j));  %更新个体最优解
                    c1 = ac1 * exp(-t_cur/t_star)*rand;
                    %c2 = ac2 * (1+exp(-t_cur/t_star))*rand;
                end
            end
        end
        %%% 3、计算整个群体的全局最优值
        if (pbest(j) < gbest)
            gbest0 = gbest;
            g_x = p_x(j);
            g_y = p_y(j);
            gbest = pbest(j);
        end
        %%% 4、对粒子的速度、位置进行进化
        %w = w_max + (w_max - w_min) *(i-1)/(iwe-1);
        w = w_max - (w_max - w_min) * i / iter_max;
        v_x(j) = w*v_x(j)+c1 * rand*(p_x(j)-x(j))+c2 * rand*(g_x-x(j));
        v_y(j) = w*v_y(j)+c1 * rand*(p_y(j)-y(j))+c2 * rand*(g_y-y(j));
        x(j) = x(j) + v_x(j);
        y(j) = y(j) + v_y(j);
        %%% 5、进行边界处理
        if (v_x(j) > v_max | v_x(j) < v_min)
            v_x(j) = rand * (v_max - v_min) + v_min;
        end
        if (v_y(j) > v_max | v_y(j) < v_min)
            v_y(j) = rand * (v_max - v_min) + v_min;
        end
        if (x(j) > x_max | x(j) < x_min)
            x(j) = rand * (x_max - x_min) + x_min;
        end
        if (y(j) > y_max | y(j) < y_min)
            y(j) = rand * (y_max - y_min) + y_min;
        end
    end
    t_cur = sa_k * t_cur;
end
x0 = g_x;
y0 = g_y;

best_x = x0;  % 记录最优解位置
best_y = y0;
cur_x(1) = x0;  % 记录当前解位置
cur_y(1) = y0;
cur_func(1) = func(cur_x(1),cur_y(1));  % 当前解
best = func(best_x,best_y);  % 最优解

i = 1;
while i < iter_max
    %% 2.由当前解产生邻域解
    w = w * 0.998;
    for j =1:near_num
        % 产生一个邻域解
        near_x(j) = cur_x(i)+(2*rand-1)*(x_max-x_min)*w;
        near_y(j) = cur_y(i)+(2*rand-1)*(y_max-y_min)*w;
        % 边界处理(边界吸收)
        if near_x(j) < x_min
            near_x(j) = x_min;
        end
        if near_x(j) > x_max
            near_x(j) = x_max;
        end
        if near_y(j) < y_min
            near_y(j) = y_min;
        end
        if near_y(j) > y_max
            near_y(j) = y_max;
        end
        % 计算邻域解点处的函数值
        near_func(j) = func(near_x(j),near_y(j));
    end
    
    %% 3.将最优邻域解作为候选解
    %temp = find(near_func == max(near_func));  %找到最优邻域解的位置
    temp = 1;
    for k =2:near_num
        if near_func(k) < near_func(temp)
            temp = k;
        end
    end
    candidate_x(i) = near_x(temp);
    candidate_y(i) = near_y(temp);
    candidate_func(i) = near_func(temp);
    
    %% 4.判断是否满足藐视准则
    deta_cc = candidate_func(i) - cur_func(i);  %% 候选解与当前解的评价函数差
    deta_cb = candidate_func(i) - best;  % 候选解与最优解的评价函数差
    
    if deta_cc >= 0  % 候选解>=当前解,更新下一个当前解
        cur_x(i+1) = candidate_x(i);
        cur_y(i+1) = candidate_y(i);
        cur_func(i+1) = candidate_func(i);
        % 更新禁忌表
        taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
        if size(taboo,1) > L
            taboo(1,:) = [];
        end
        i = i + 1;
    else
        if deta_cb < 0  % 候选解<最优解,更新下一个当前解、最优解
            cur_x(i+1) = candidate_x(i);
            cur_y(i+1) = candidate_y(i);
            cur_func(i+1) = candidate_func(i);
            best = candidate_func(i);  % 更新最优解
            best_x = candidate_x(i);
            best_y = candidate_y(i);
            % 更新禁忌表
            taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
            if size(taboo,1) > L
                taboo(1,:) = [];
            end
            i = i + 1;
        else
            [M,N] = size(taboo);  %判断是否在禁忌表中
            r = 0;
            for m = 1:M
                if candidate_x(i) == taboo(m,1) && candidate_y(i) == taboo(m,2)
                    r = 1;
                end
            end
            
            if r == 0  % 不在禁忌表中,更新下一次当前解,反之用当前解重新产生邻域
                cur_x(i+1) = candidate_x(i);
                cur_y(i+1) = candidate_y(i);
                cur_func(i+1) = candidate_func(i);
                % 更新禁忌表
                taboo = [taboo;[cur_x(i+1),cur_y(i+1)]];
                if size(taboo,1) > L
                    taboo(1,:) = [];
                end
                i = i + 1;
            end
        end
    end
    trace(i) = best;
end

disp('最小值在点:');
best_x
best_y
disp( '最小值为:');
best
plot(trace)
legend(legend_str)
xlabel('迭代次数')
ylabel('适应度值')
title('适应度进化曲线')


function results = func(x,y)
    results = 5 * cos(x * y)+ x * y + y * y * y;
end

 7. 对比

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值