c++ 代码_不是吧,MATLAB代码居然能直接转成C/C++代码

各位小伙伴可在闲鱼搜索 优化算法交流地,即可搜索到官方闲鱼账号, 谨防上当受骗

前一段时间在工作中遇到这样一个实际问题,项目主体部分是用C++写的,但其中有一小部分算法是用MATLAB写的。于是乎,我第一想法是如何用C++把MATLAB中的代码实现出来。

这时,一位前辈语重心长地和我说:“可以去网上找一下MATLAB Coder。”

当时听完一脸懵逼,什么是MATLAB Coder?它有什么用?

于是在网上查阅了一些资料之后,发现MATLAB Coder实际上是MATLAB自带的一个应用程序。这个应用程序的牛X之处在于它可以直接将MATLAB代码转换成C/C++代码

ff442823a18883a1198ec4edf5a926ad.png

就在我以为使用MATLAB Coder可以轻松地转换时,但是在实际使用过程中依然遇到一些雷区,这些雷区是在网上查不到。

为了防止小伙伴继续“踩雷”,今天详细地讲解一下如何使用MATLAB Coder将MATLAB代码转换成C/C++代码?如何避免一些“雷区”?


01 | 准备工作在使用MATLAB Coder前,我们需要先对MATLAB代码进行一些处理,主要包括:

(1)删除MATLAB代码中所有的注释(这是第一个“雷区,必须要把MATLAB代码中注释全部删干净,否则无法成功转换)。

(2)删除MATLAB代码中画图和打印部分的代码,简而言之,就是把什么plot、disp之类的代码全部删除掉。如果不删除这些代码,则会导致无法成功转换,这是第二个雷区

(3)如果在MATLAB代码中想要把一个未知行(列)数的数据储存在矩阵中,常规的做法是先令这个储存的矩阵A为空。

A=[];

假设要添加的若干行数据,每次添加的数据都为B。然后可以用如下的代码将要添加的数据添加进来。

A=[A;B];

这其实是最容易忽视的一个“雷区”,C/C++不允许你MATLAB存在这么牛X的方法,因此如果MATLAB代码中存在上述类型添加数据的代码,那么是无法成功转换的。

解决方案:先求出究竟需要添加多少行数据?然后再添加数据。

假设经计算需要添加m行数据,且添加数据的列数都为n,那么可以先初始化储存的矩阵A,然后再通过计数器的方式循环添加数据。

1,n);

02 | 封装主函数

因为主函数为脚本函数,在转换之前需要先将脚本函数转换为一个常规的函数,即有明确输入和输出的函数。

以遗传算法(GA)求解旅行商问题(TSP)MATLAB代码讲解这篇推文的主函数为例,原来主函数的代码如下:

%
%      @作者:随心390
%      @微信公众号:优化算法交流地
%
tic
clear
clc
%% 输入数据
x=[38.24,39.57,40.56,36.26,33.48,37.56,38.42,37.52,41.23,41.17,36.08,38.47,38.15,37.51,35.49,39.36,38.09,36.09,40.44,40.33,40.37,37.57];
y=[20.42,26.15,25.32,23.12,10.54,12.19,13.11,20.44,9.100,13.05,-5.210,15.13,15.35,15.17,14.32,19.56,24.36,23,13.57,14.15,14.23,22.56];
vertexs=[x;y]';
n=length(x);                    %城市数目
h=pdist(vertexs);
dist=squareform(h);             %距离矩阵
%% 遗传算法参数设置
NIND=50;                        %种群大小
MAXGEN=1000;                    %迭代次数
Pc=0.8;                         %交叉概率
Pm=0.2;                         %变异概率
pSwap=0.2;                      %选择交换结构的概率
pReversion=0.5;                 %选择逆转结构的概率
pInsertion=1-pSwap-pReversion;  %选择插入结构的概率
N=n;                            %染色体长度=城市数目
%% 种群初始化
Chrom=InitPop(NIND,N);
%% 优化
gen=1;                          %计数器
bestChrom=Chrom(1,:);           %初始全局最优个体
bestL=RouteLength(bestChrom,dist);%初始全局最优个体的总距离
BestChrom=zeros(MAXGEN,N);      %记录每次迭代过程中全局最优个体
BestL=zeros(MAXGEN,1);          %记录每次迭代过程中全局最优个体的总距离
while gen<=MAXGEN
    %二元锦标赛选择
    SelCh=BinaryTourment_Select(Chrom,dist);
    %OX交叉
    SelCh=Recombin(SelCh,Pc);
    %变异
    SelCh=Mutate(SelCh,Pm,pSwap,pReversion,pInsertion);
    %将Chrom更新为SelCh
    Chrom=SelCh;
    %计算当前代所有个体总距离
    Obj=ObjFunction(Chrom,dist);
    %找出当前代中最优个体
    [minObj,minIndex]=min(Obj);
    %将当前代中最优个体与全局最优个体进行比较,如果当前代最优个体更好,则将全局最优个体进行替换
    if minObj<=bestL
        bestChrom=Chrom(minIndex,:);
        bestL=minObj;
    end
    %记录每一代全局最优个体,及其总距离
    BestChrom(gen,:)=bestChrom;
    BestL(gen,:)=bestL;
    %显示外层循环每次迭代的信全局最优路线的总距离
    disp(['第' num2str(gen) '次迭代:全局最优路线总距离 = ' num2str(bestL)]);
    %画出每次迭代的全局最优路线图
    figure(1);
    PlotRoute(bestChrom,x,y)
    pause(0.01);
    %计数器加1
    gen=gen+1;
end
%% 打印每次迭代的全局最优个体的总距离变化趋势图
figure;
plot(BestL,'LineWidth',1);
title('优化过程')
xlabel('迭代次数');
ylabel('总距离');
toc

封装之后的主函数如下:

%% 封装后的主函数
%输入x,y:城市的x,y坐标
%输入NIND:种群大小
%输入MAXGEN:迭代次数
%输入Pc:交叉概率
%输入Pm:变异概率
%输入pSwap:选择交换结构的概率
%输入pReversion:选择逆转结构的概率
%输入pInsertion:选择插入结构的概率
%输出bestChrom:全局最优个体
function bestChrom=GA_TSP(x,y,NIND,MAXGEN,Pc,Pm,pSwap,pReversion,pInsertion)
%% 输入数据vertexs=[x;y]';n=length(x);                    %城市数目h=pdist(vertexs);dist=squareform(h);             %距离矩阵N=n;                            %染色体长度=城市数目
%% 种群初始化Chrom=InitPop(NIND,N);
%% 优化gen=1;                          %计数器bestChrom=Chrom(1,:);           %初始全局最优个体bestL=RouteLength(bestChrom,dist);%初始全局最优个体的总距离BestChrom=zeros(MAXGEN,N);      %记录每次迭代过程中全局最优个体BestL=zeros(MAXGEN,1);          %记录每次迭代过程中全局最优个体的总距离while gen<=MAXGEN
    %二元锦标赛选择SelCh=BinaryTourment_Select(Chrom,dist);
    %OX交叉SelCh=Recombin(SelCh,Pc);
    %变异SelCh=Mutate(SelCh,Pm,pSwap,pReversion,pInsertion);
    %将Chrom更新为SelChChrom=SelCh;
    %计算当前代所有个体总距离Obj=ObjFunction(Chrom,dist);
    %找出当前代中最优个体
    [minObj,minIndex]=min(Obj);
    %将当前代中最优个体与全局最优个体进行比较,如果当前代最优个体更好,则将全局最优个体进行替换if minObj<=bestLbestChrom=Chrom(minIndex,:);bestL=minObj;end
    %记录每一代全局最优个体,及其总距离BestChrom(gen,:)=bestChrom;BestL(gen,:)=bestL;
    %显示外层循环每次迭代的信全局最优路线的总距离disp(['第' num2str(gen) '次迭代:全局最优路线总距离 = ' num2str(bestL)]);
    %画出每次迭代的全局最优路线图figure(1);PlotRoute(bestChrom,x,y)pause(0.01);
    %计数器加1gen=gen+1;end
%% 打印每次迭代的全局最优个体的总距离变化趋势图figure;plot(BestL,'LineWidth',1);title('优化过程')xlabel('迭代次数');ylabel('总距离');end

03 | 新建一个脚本函数

在封装完主函数后,删除掉原来的脚本函数GA_TSP。再新建一个脚本函数TEST,在这个脚本函数中给出封装后的主函数的输入数据,具体代码如下:

clear
clc
x=[38.24,39.57,40.56,36.26,33.48,37.56,38.42,37.52,41.23,41.17,36.08,38.47,38.15,37.51,35.49,39.36,38.09,36.09,40.44,40.33,40.37,37.57];
y=[20.42,26.15,25.32,23.12,10.54,12.19,13.11,20.44,9.100,13.05,-5.210,15.13,15.35,15.17,14.32,19.56,24.36,23,13.57,14.15,14.23,22.56];
NIND=50;                      
MAXGEN=1000;                    
Pc=0.8;                   
Pm=0.2;                       
pSwap=0.2;                    
pReversion=0.5;               
pInsertion=1-pSwap-pReversion;  
bestChrom=GA_TSP(x,y,NIND,MAXGEN,Pc,Pm,pSwap,pReversion,pInsertion);

04 | 开始转换

这里我们已经将注释、画图和打印部分的代码全部删除完毕。

STEP1:点击MATLAB Coder

6e4ec8c4443e69d3d69fd61c8c2ce2d3.png

STEP2:添加封装后的GA_TSP函数。

c7a0d0366f41d4ee38cb43ee35687278.png24990f52c0549d71be00e9a7867866fd.png74d1719fbae240d41234a803b8157d01.png

STEP3:根据提示修改代码

3e252ad0f0743e144aeea483e01820d1.png

这里我们将OX函数进行修改,修改后的OX函数代码如下:

function [a,b]=OX(a,b)L=length(a);while 1r=randi([1,L],1,2);r1=r(1);r2=r(2);if r1~=r2s=min([r1,r2]);e=max([r1,r2]);a0=zeros(1,L+e-s+1);b0=zeros(1,L+e-s+1);a0(1:e-s+1)=b(s:e);a0(e-s+2:L+e-s+1)=a;b0(1:e-s+1)=a(s:e);b0(e-s+2:L+e-s+1)=b;for i=1:length(a0)aindex=find(a0==a0(i));bindex=find(b0==b0(i));if length(aindex)>1a0(aindex(2))=[];endif length(bindex)>1b0(bindex(2))=[];endif i==length(a)breakendenda=a0;b=b0;breakendend

STEP4:重复前3步操作,在STEP2点击NEXT后,直接来到定义输入变量类型这一步。

34dc837811c940e70af2e72003774b19.png7fbbb9ba864c55ee05b44a327dbb1438.png

5be90a9dfdc77ee252036c7f0614a096.pngf172bd351481ae32b7461be25470ced5.png

STEP5:检验运行环境

975126475292a4294a5cbf32f2fd290f.png1cc6eaf9613935695f512b3beaa34846.png

发现又报错了,按照要求修改OX函数,这次报错的原因是OX函数代码中的第10行和第11行,这两行代码是常见的第三个“雷区”,修改后的OX函数如下:

function [a0,b0]=OX(a,b)L=length(a);while 1r=randi([1,L],1,2);r1=r(1);r2=r(2);if r1~=r2s=min([r1,r2]);e=max([r1,r2]);a0=zeros(1,L+e-s+1);b0=zeros(1,L+e-s+1);a0(1:e-s+1)=b(s:e);a0(e-s+2:L+e-s+1)=a;b0(1:e-s+1)=a(s:e);b0(e-s+2:L+e-s+1)=b;for i=1:length(a0)aindex=find(a0==a0(i));bindex=find(b0==b0(i));if length(aindex)>1a0(aindex(2))=[];endif length(bindex)>1b0(bindex(2))=[];endif i==length(a)breakendendbreakendend

继续重复前几步到STEP5,又发现了新的报错。

07bc8b62e63a01bec00d217bd4b5d962.png

报错信息是C中if语句中的条件不能像MATLAB这么写,于是对Mutate函数做出一些修改,修改后的函数如下:

function SelCh=Mutate(SelCh,Pm,pSwap,pReversion,pInsertion)NSel=size(SelCh,1);for i=1:NSelif Pm>=randindex=Roulette(pSwap,pReversion,pInsertion);route1=SelCh(i,:);flag=zeros(1,3);flag(1)= index==1;flag(2)= index==2;flag(3)= index==3;if flag(1)route2=Swap(route1);elseif flag(2)route2=Reversion(route1);elseroute2=Insertion(route1);endSelCh(i,:)=route2;endend

再一次重复前几步到STEP5,这一次终于成功了。

1642ded1b7adc3b03d31a6a3e4f34b64.png

STEP6:点击Gnerate生成C代码,在MATLAB代码文件夹下多了2个文件和1个文件夹,转换出的C代码在codegen文件夹->lib文件夹->GA_TSP文件夹下。

2ffde11e9877278885d9cad48b501aef.png6061c1b164d075f65285dca8e6a188da.pnge6cda9c4a557e60802f60461d2d74c46.png

至此,使用MATLAB Coder应用程序成功将遗传算法(GA)求解旅行商问题(TSP)MATLAB代码讲解这篇推文的MATLAB代码转换为C代码。

各位小伙伴可参与免费送付费代码,第二波这篇推文的活动,免费领取付费代码。

点击下方小程序写留言

写留言

a385caa67b73bd545e631f496a3e7102.png a385caa67b73bd545e631f496a3e7102.png

往期精选

  • 号内搜索

  • 头脑风暴优化(BSO)算法求解旅行商问题(TSP)(附MATLAB代码)

  • 一种新颖的交叉算子——头脑风暴优化(BSO)算法求解旅行商问题(TSP)预备知识

  • 头脑风暴优化(BSO)算法(附MATLAB代码)

  • 如何自学智能优化算法?

  • 遗传模拟退火算法求解旅行商(TSP)问题MATLAB代码讲解

  • 遗传模拟退火算法求解旅行商(TSP)问题

  • 车辆路径问题(VRP)合集

  • 旅行商问题(TSP)合辑

  • MATLAB导入txt文件技巧大全

  • 遗传算法(GA)求解旅行商问题(TSP)MATLAB代码讲解

  • 遗传算法求解0-1背包问题(附matlab源代码)
  • 模拟退火(SA)算法求解旅行商 (TSP)问题MATLAB代码讲解
  • 多目标优化 | 基于NSGA-II的多目标0-1背包问题求解(附matlab代码)
  • 多目标优化 | NSGA-II进阶教程(全网首个三目标优化教程)
  • 机器学习 | 基于遗传算法的BP神经网络优化算法(附MATLAB代码)
  • 遗传算法求解车间调度问题(附MATLAB代码)
  • 多目标优化 | NSGA-II
  • word转换为pdf后图片失真的解决办法(全网首发)
  • 机器学习 | 简单实现Bp神经网络
  • 二维装箱问题之BL法修正版(附MATLAB代码)
  • 快速入门文献管理软件-EndNote X9
  • 最小二乘法(附MATLAB代码)
  • NSGA-II多目标优化算法讲解(附MATLAB代码)
  • 基于人工势场法的机器人二维路径规划(附MATLAB代码)
  • 基于粒子群算法的多目标搜索算法讲解(附MATLAB代码)
  • 蚁群算法通俗讲解(附MATLAB代码)
  • 混合粒子群算法通俗讲解(附MATLAB代码)

知乎 | bilibili:随心390

4ea7cb8b33a84e3c0e1fa08e05e10703.png 5f8d73a0958f34d1629d33857cec9e77.png 长按识别二维码关注我们 觉得内容还不错的话,给我点个“在看”呗 126a98b859b2daa308af5cca1348160e.gif 61390164ceb62f386d0995aab0c50c1b.gif
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值