优化算法matlab实现(二(补))框架增强:matlab动态图绘制

1.修改框架的目的

之前有不少问如下动态图是怎么绘制的?



这个是使用java编写的代码实现的,方式较为复杂,把每一代的位置画在一张图中,然后按顺序合成gif动态图。用java实现这种方式非常复杂,需要自己去实现绘制代码,然后保存成图片再合成。单绘制图像的代码就有几百行,而且有不少未解决的bug,比如一些位置的点只能用黑色或者白色才会在动态图中显示。
  将代码用matlab实现之后,发现使用matlab绘制动态图要比java容易一万倍,其效果如图。


所以在这里对优化算法框架进行一个小小的更新,让每个算法都能绘制群体位置动态图。

2.算法框架的修改

使用matlab绘制动态图的原理和使用java绘制的原理一样:即将每一代的所有个体的位置保存下来,然后每一代绘制成一张图,最后按顺序合成动态图。
  这里我们需要修改的部分由两点:
  1.保存所有个体的位置;
  2.绘制群体的位置。
  图像的显示以及动态图gif的生成,matlab已经帮我们完成,不需要单独去编码实现。
  需要修改的代码文件列表:
  优化算法matlab实现(二)框架编写中的框架。

文件名 描述
..\optimization algorithm\frame\Unit.m 个体
..\optimization algorithm\frame\Algorithm_Impl.m 算法主体

只需要修改这两个文件即可,不需要修改其他文件。
文件..\optimization algorithm\frame\Unit.m中需要添加个体的历史位置及保存历史位置的方法,其实现如下:

% 个体基类
classdef Unit< handle
    properties
        % 个体的位置
        position;
        % 个体的适应度值
        value;
        % 记录所有的位置,画图用
        position_history_list;
    end
    
    methods
        function self = Unit()
        end
        
        % 将当前位置保存到position_history_list中
        function save(self)
            self.position_history_list=[self.position_history_list;self.position];
        end
    end
    
end

文件..\optimization algorithm\frame\ Algorithm_Impl.m中每一代都需要调用上面的save方法来保存图像,其实现如下:

% 记录最优值
for i = 1:self.size
    if(self.unit_list(i).value>self.value_best)
        self.value_best = self.unit_list(i).value;
        self.position_best = self.unit_list(i).position;
    end
    % 保存每一代的位置
    self.unit_list(i).save();
end

文件..\optimization algorithm\frame\ Algorithm_Impl.m中需要绘制群体位置的方法,其实现如下:

% 绘制动态图,2维图像:step为步长(几代绘制一张图像),is_save用来判断是否保存gif动态图
function draw2_gif(self,step,is_save,name)
    if self.dim < 2
        disp('维度太低,无法绘制图像');
        return
    end
    if step < 1
        step = 1;
    end
    f1 = figure;
    % 遍历每一代
    for i = 1:self.iter_max
        % 如果不满足步长,则跳过
        if mod(i,step) > 0 && i>1
            % 必须要绘制第一代,否则matlab会报错,原因未知
            continue
        end
        % 遍历每一个个体
        for s = 1:self.size
            cur_position = self.unit_list(s).position_history_list(i,:);
            scatter(cur_position(1),cur_position(2),10,'b','filled');
            hold on;
        end

        % 将文字绘制在左上角
        text(self.range_min_list(1),self.range_max_list(2),num2str(i),'FontSize',20);

        % 绘制显示区域
        range_size_x = self.range_max_list(1)-self.range_min_list(1);
        range_size_y = self.range_max_list(2)-self.range_min_list(2);
        axis([self.range_min_list(1)-0.2*range_size_x,self.range_max_list(1)+0.2*range_size_x, self.range_min_list(2)-0.2*range_size_y, self.range_max_list(2)+0.2*range_size_y]);

        axis equal;

        % 固定横纵坐标轴
        set(gca,'XLim',[self.range_min_list(1)-0.1*range_size_x self.range_max_list(1)+0.1*range_size_x]);
        set(gca,'YLim',[self.range_min_list(2)-0.1*range_size_y self.range_max_list(2)+0.1*range_size_y]);
        % 每0.1绘制一次
        pause = 0.1;
        % 需要保存git则设置is_save = true
        if is_save
            %下面是保存为GIF的程序
            frame=getframe(gcf);
            % 返回单帧颜色图像
            imind=frame2im(frame);
            % 颜色转换
            [imind,cm] = rgb2ind(imind,256);
            filename = [name,'_2d.gif'];
            if i==1
                 imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-2);
            else
                 imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
            end
        end
        % 绘制完就清除,绘制下一代
        clf;
    end
    % 绘制完成关闭窗口
    close(f1);    
end
        

上面绘制的是2维动态图,我们可以将其类推至3维,来绘制3维动态图。当然图像最多只能绘制到3维,毕竟我们生活在3维空间,只能直观看到3维。

% 绘制动态图,3维图像:step为步长(几代绘制一张图像),is_save用来判断是否保存gif动态图
function draw3_gif(self,step,is_save,name)
    if self.dim < 3
        disp('维度太低,无法绘制三维图像');
        return
    end
    if step < 1
        step = 1;
    end
    f1 = figure;
    % 遍历每一代
    for i = 1:self.iter_max
        % 如果不满足步长,则跳过
        if mod(i,step) > 0 && i>1
            % 必须要绘制第一代,否则matlab会报错,原因未知
            continue
        end
        % 遍历每一个个体
        for s = 1:self.size
            cur_position = self.unit_list(s).position_history_list(i,:);
            scatter3(cur_position(1),cur_position(2),cur_position(3),10,'b','filled');
            hold on;
        end

        % 将文字绘制在左上角
        text(self.range_min_list(1),self.range_max_list(2),self.range_max_list(3),num2str(i),'FontSize',20);

        % 绘制显示区域
        range_size_x = self.range_max_list(1)-self.range_min_list(1);
        range_size_y = self.range_max_list(2)-self.range_min_list(2);
        range_size_z = self.range_max_list(3)-self.range_min_list(3);
        axis([self.range_min_list(1)-0.2*range_size_x,self.range_max_list(1)+0.2*range_size_x, self.range_min_list(2)-0.2*range_size_y, self.range_max_list(2)+0.2*range_size_y,self.range_min_list(3)-0.2*range_size_z, self.range_max_list(3)+0.2*range_size_z]);

        axis equal;

        % 固定横纵坐标轴
        set(gca,'XLim',[self.range_min_list(1)-0.1*range_size_x self.range_max_list(1)+0.1*range_size_x]);
        set(gca,'YLim',[self.range_min_list(2)-0.1*range_size_y self.range_max_list(2)+0.1*range_size_y]);
        set(gca,'ZLim',[self.range_min_list(3)-0.1*range_size_z self.range_max_list(3)+0.1*range_size_z])
        % 每0.1绘制一次
        pause = 0.1;
        % 需要保存git则设置is_save = true
        if is_save
            %下面是保存为GIF的程序
            frame=getframe(gcf);
            % 返回单帧颜色图像
            imind=frame2im(frame);
            % 颜色转换
            [imind,cm] = rgb2ind(imind,256);
            filename = [name,'_3d.gif'];
            if i==1
                 imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-2);
            else
                 imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
            end
        end
        % 绘制完就清除,绘制下一代
        clf;
    end
    % 绘制完成关闭窗口
    close(f1);    
end

3维图像效果如图:

3.完整框架代码

总目录:..\optimization algorithm
框架目录:..\optimization algorithm/frame
框架文件:

文件名 描述
..\optimization algorithm\frame\Unit.m 个体
..\optimization algorithm\frame\Algorithm_Impl.m 算法主体

文件内容:
Unit.m

% 个体基类
classdef Unit< handle
    properties
        % 个体的位置
        position;
        % 个体的适应度值
        value;
        % 记录所有的位置,画图用
        position_history_list;
    end
    
    methods
        function self = Unit()
        end
        
        % 将当前位置保存到position_history_list中
        function save(self)
            self.position_history_list=[self.position_history_list;self.position];
        end
    end
    
end

Algorithm_Impl.m

% 优化算法基类
classdef Algorithm_Impl < handle
    properties

        %当前最优位置
        position_best;
        %当前最优适应度
        value_best;
        %历史最优适应度
        value_best_history;
        %历史最优位置
        position_best_history;
        %是否为求最大值,默认为是
        is_cal_max;
        %适应度函数,需要单独传入
        fitfunction;
        % 调用适应度函数次数
        cal_fit_num = 0;
    end
    properties(Access = protected)
        %维度
        dim;
        %种群中个体的数量
        size;
        %最大迭代次数
        iter_max;
        %解空间下界
        range_min_list;
        %解空间上界
        range_max_list;
        %种群列表
        unit_list;
    end
    
    methods
         % 运行,调用入口
        function run(self)
            tic
            self.init()
            self.iteration()
            toc
            disp(['运行时间: ',num2str(toc)]);

        end
        
        % 绘制动态图,2维图像
        function draw2_gif(self,step,is_save,name)
            if self.dim < 2
                disp('维度太低,无法绘制图像');
                return
            end
            if step < 1
                step = 1;
            end
            f1 = figure;
            % 遍历每一代
            for i = 1:self.iter_max
                % 如果不满足步长,则跳过
                if mod(i,step) > 0 && i>1
                    % 必须要绘制第一代,否则matlab会报错,原因未知
                    continue
                end
                % 遍历每一个个体
                for s = 1:self.size
                    cur_position = self.unit_list(s).position_history_list(i,:);
                    scatter(cur_position(1),cur_position(2),10,'b','filled');
                    hold on;
                end

                % 将文字绘制在左上角
                text(self.range_min_list(1),self.range_max_list(2),num2str(i),'FontSize',20);

                % 绘制显示区域
                range_size_x = self.range_max_list(1)-self.range_min_list(1);
                range_size_y = self.range_max_list(2)-self.range_min_list(2);
                axis([self.range_min_list(1)-0.2*range_size_x,self.range_max_list(1)+0.2*range_size_x, self.range_min_list(2)-0.2*range_size_y, self.range_max_list(2)+0.2*range_size_y]);

                axis equal;

                % 固定横纵坐标轴
                set(gca,'XLim',[self.range_min_list(1)-0.1*range_size_x self.range_max_list(1)+0.1*range_size_x]);
                set(gca,'YLim',[self.range_min_list(2)-0.1*range_size_y self.range_max_list(2)+0.1*range_size_y]);
                % 每0.1绘制一次
                pause = 0.1;
                % 需要保存git则设置is_save = true
                if is_save
                    %下面是保存为GIF的程序
                    frame=getframe(gcf);
                    % 返回单帧颜色图像
                    imind=frame2im(frame);
                    % 颜色转换
                    [imind,cm] = rgb2ind(imind,256);
                    filename = [name,'_2d.gif'];
                    if i==1
                         imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-2);
                    else
                         imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
                    end
                end
                % 绘制完就清除,绘制下一代
                clf;
            end
            % 绘制完成关闭窗口
            close(f1);    
        end
        
        % 绘制动态图,3维图像
        function draw3_gif(self,step,is_save,name)
            if self.dim < 3
                disp('维度太低,无法绘制三维图像');
                return
            end
            if step < 1
                step = 1;
            end
            f1 = figure;
            % 遍历每一代
            for i = 1:self.iter_max
                % 如果不满足步长,则跳过
                if mod(i,step) > 0 && i>1
                    % 必须要绘制第一代,否则matlab会报错,原因未知
                    continue
                end
                % 遍历每一个个体
                for s = 1:self.size
                    cur_position = self.unit_list(s).position_history_list(i,:);
                    scatter3(cur_position(1),cur_position(2),cur_position(3),10,'b','filled');
                    hold on;
                end

                % 将文字绘制在左上角
                text(self.range_min_list(1),self.range_max_list(2),self.range_max_list(3),num2str(i),'FontSize',20);

                % 绘制显示区域
                range_size_x = self.range_max_list(1)-self.range_min_list(1);
                range_size_y = self.range_max_list(2)-self.range_min_list(2);
                range_size_z = self.range_max_list(3)-self.range_min_list(3);
                axis([self.range_min_list(1)-0.2*range_size_x,self.range_max_list(1)+0.2*range_size_x, self.range_min_list(2)-0.2*range_size_y, self.range_max_list(2)+0.2*range_size_y,self.range_min_list(3)-0.2*range_size_z, self.range_max_list(3)+0.2*range_size_z]);

                axis equal;

                % 固定横纵坐标轴
                set(gca,'XLim',[self.range_min_list(1)-0.1*range_size_x self.range_max_list(1)+0.1*range_size_x]);
                set(gca,'YLim',[self.range_min_list(2)-0.1*range_size_y self.range_max_list(2)+0.1*range_size_y]);
                set(gca,'ZLim',[self.range_min_list(3)-0.1*range_size_z self.range_max_list(3)+0.1*range_size_z])
                % 每0.1绘制一次
                pause = 0.1;
                % 需要保存git则设置is_save = true
                if is_save
                    %下面是保存为GIF的程序
                    frame=getframe(gcf);
                    % 返回单帧颜色图像
                    imind=frame2im(frame);
                    % 颜色转换
                    [imind,cm] = rgb2ind(imind,256);
                    filename = [name,'_3d.gif'];
                    if i==1
                         imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-2);
                    else
                         imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
                    end
                end
                % 绘制完就清除,绘制下一代
                clf;
            end
            % 绘制完成关闭窗口
            close(f1);    
        end
    end
    
    methods (Access = protected)
        % 构造函数
        function self = Algorithm_Impl(dim,size,iter_max,range_min_list,range_max_list)
            self.dim =dim;
            self.size = size;
            self.iter_max = iter_max;
            self.range_min_list = range_min_list;
            self.range_max_list = range_max_list;
            %默认为求最大值
            self.is_cal_max = true;
        end
        
        % 初始化
        function init(self)
            self.position_best=zeros(1,self.dim);
            self.value_best_history=[];
            self.position_best_history=[];
            %设置初始最优值,由于是求最大值,所以设置了最大浮点数的负值
            self.value_best = -realmax('double');
        end
        
        % 开始迭代
        function iteration(self)
            for iter = 1:self.iter_max
                self.update(iter)
            end
        end
        
        % 处理一次迭代
        function update(self,iter)
            % 记录最优值
            for i = 1:self.size
                if(self.unit_list(i).value>self.value_best)
                    self.value_best = self.unit_list(i).value;
                    self.position_best = self.unit_list(i).position;
                end
                % 保存每一代的位置
                self.unit_list(i).save();
            end
            disp(['第' num2str(iter) '代']);
            if(self.is_cal_max)
                self.value_best_history(end+1) = self.value_best;
                disp(['最优值=' num2str(self.value_best)]);
            else
                self.value_best_history(end+1) = -self.value_best;
                disp(['最优值=' num2str(-self.value_best)]);
            end
            self.position_best_history = [self.position_best_history;self.position_best];
            disp(['最优解=' num2str(self.position_best)]);
        end
        
        function value = cal_fitfunction(self,position)
            if(isempty(self.fitfunction))
                value = 0;
            else
                % 如果适应度函数不为空则返回适应度值
                if(self.is_cal_max)
                    value = self.fitfunction(position);
                else
                    value = -self.fitfunction(position);
                end
            end
            self.cal_fit_num = self.cal_fit_num+1;
        end
        
        % 越界检查,超出边界则停留在边界上
        function s=get_out_bound_value(self,position,min_list,max_list)
          if(~exist('min_list','var'))
              min_list = self.range_min_list;
          end
          if(~exist('max_list','var'))
              max_list = self.range_max_list;
          end
          % Apply the lower bound vector
          position_tmp=position;
          I=position_tmp<min_list;
          position_tmp(I)=min_list(I);

          % Apply the upper bound vector
          J=position_tmp>max_list;
          position_tmp(J)=max_list(J);
          % Update this new move
          s=position_tmp;
        end
        
        % 越界检查,超出边界则在解空间内随机初始化
        function s=get_out_bound_value_rand(self,position,min_list,max_list)
          if(~exist('min_list','var'))
              min_list = self.range_min_list;
          end
          if(~exist('max_list','var'))
              max_list = self.range_max_list;
          end
          position_rand = unifrnd(self.range_min_list,self.range_max_list);
          % Apply the lower bound vector
          position_tmp=position;
          I=position_tmp<min_list;
          position_tmp(I)=position_rand(I);

          % Apply the upper bound vector
          J=position_tmp>max_list;
          position_tmp(J)=position_rand(J);
          % Update this new move
          s=position_tmp;
        end
        
        
    end

    events
    end
end

4.测试代码

使用之前的差分进化算法测试一下动态图的绘制(需要实现优化算法matlab实现(七)差分进化算法matlab实现中的相关代码)。

注意调用方法是需要自行决定步长,即draw2_gif()和draw3_gif中的step参数。步长越小绘制的图片越多,执行的越慢。

测试F1

文件名:..\optimization algorithm\algorithm_differential_evolution\Test.m

%% 清理之前的数据
% 清除所有数据
clear all;
% 清除窗口输出
clc;

%% 添加目录
% 将上级目录中的frame文件夹加入路径
addpath('../frame')


%% 选择测试函数
Function_name='F1';
%[最小值,最大值,维度,测试函数]
[lb,ub,dim,fobj]=Get_Functions_details(Function_name);

%% 算法实例
% 种群数量
size = 50;
% 最大迭代次数
iter_max = 1000;
% 取值范围上界
range_max_list = ones(1,dim)*ub;
% 取值范围下界
range_min_list = ones(1,dim)*lb;

% 实例化差分进化算法类
base = DE_Base(dim,size,iter_max,range_min_list,range_max_list);
base.is_cal_max = false;
% 确定适应度函数
base.fitfunction = fobj;
% 运行
base.run();
disp(base.cal_fit_num);

%% 绘制2维图像,每10代绘制一次,且保存gif图像到本地
%base.draw2_gif(10,true,base.name);

% 绘制3维图像,每10代绘制一次,且保存gif图像到本地
base.draw3_gif(10,true,base.name);

%% 绘制图像
figure('Position',[500 500 660 290])
%Draw search space
subplot(1,2,1);
func_plot(Function_name);
title('Parameter space')
xlabel('x_1');
ylabel('x_2');
zlabel([Function_name,'( x_1 , x_2 )'])
%Draw objective space
subplot(1,2,2);
% 绘制曲线,由于算法是求最大值,适应度函数为求最小值,故乘了-1,此时去掉-1
semilogy((base.value_best_history),'Color','r')
title('Objective space')
xlabel('Iteration');
ylabel('Best score obtained so far');
% 将坐标轴调整为紧凑型
axis tight
% 添加网格
grid on
% 四边都显示刻度
box off
legend(base.name)
display(['The best solution obtained by ',base.name ,' is ', num2str(base.value_best)]);
display(['The best optimal value of the objective funciton found by ',base.name ,' is ', num2str(base.position_best)]);
步长为10,2d图
步长为10,3d图
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容