【转】VS2010和Matlab混编尝试

 

1系统环境说明

操作系统:Window8 X64.

Matlab版本:Matlab2012b(Matlab 8.0).

VS版本:VS 2010.

添加系统环境变量:

 

Path变量中增加:C:\Program Files\MATLAB\R2012b\bin\win64;

重启电脑。

2 二次规划算法的Matlab实现

2.1 编程准备工作

    首先为本文建立一个单独的文件夹\QPTEST,再在该文件夹下建立子文件夹\QPMAT。然后启动Matlab并将工作目录指定到\QPMAT下。

2.2 m文件编程

    新建m文件并保存文件名为qpsubp.m,编辑内容如下,代码分析参考文献[1]程序12.1:

 

function [d,mu,lam] = qpsubp(dfk,Bk,Ae,hk,Ai,gk)
n=length(dfk);  l=length(hk);   m=length(gk);
gamma=0.05; epsilon=1.0e-6; rho=0.5;    sigma=0.2;
ep0=0.05;   mu0=0.05*zeros(l,1);    lam0=0.05*zeros(m,1);
d0=ones(n,1);   u0=[ep0;zeros(n+l+m,1)];
z0=[ep0;d0;mu0;lam0];
k=0;
z=z0;   ep=ep0; d=d0;   mu=mu0; lam=lam0;
    
while (k<=150)
    dh=dah(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk);
    if(norm(dh)<epsilon)
        break;
    end
        
    A=JacobiH(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk);
    b=beta(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk,gamma)*u0-dh;
    dz=A\b;
    
    if(l>0&&m>0)
        de=dz(1);  dd=dz(2:n+1);  du=dz(n+2:n+l+1);  dl=dz(n+l+2:n+l+m+1);
    end
    if(l==0)
        de=dz(1);  dd=dz(2:n+1);  dl=dz(n+2:n+m+1);
    end
    if(m==0)
        de=dz(1);  dd=dz(2:n+1);  du=dz(n+2:n+l+1);
    end
    
    i=0;
    while (i<=20)
        if(l>0&&m>0)
            dh1=dah(ep+rho^i*de,d+rho^i*dd,mu+rho^i*du,lam+rho^i*dl,...
                dfk,Bk,Ae,hk,Ai,gk);
        end
        if(l==0)
            dh1=dah(ep+rho^i*de,d+rho^i*dd,mu,lam+rho^i*dl,...
                dfk,Bk,Ae,hk,Ai,gk);
        end
        if(m==0)
            dh1=dah(ep+rho^i*de,d+rho^i*dd,mu+rho^i*du,lam,...
                dfk,Bk,Ae,hk,Ai,gk);
        end
        
        if(norm(dh1)<=(1-sigma*(1-gamma*ep0)*rho^i)*norm(dh))
            mk=i;   break;
        end
        i=i+1;
        if(i==20)
            mk=10;
        end
    end
    
    alpha=rho^mk;
    if(l>0&&m>0)
        ep=ep+alpha*de; d=d+alpha*dd;  mu=mu+alpha*du; lam=lam+alpha*dl;
    end
    if(l==0)
        ep=ep+alpha*de; d=d+alpha*dd;  lam=lam+alpha*dl;
    end
    if(m==0)
        ep=ep+alpha*de; d=d+alpha*dd;  mu=mu+alpha*du;
    end
    k=k+1;
end
%val = 0.5*d'*Bk*d+dfk'*d;
 
function p=phi(ep,a,b)
p=a+b-sqrt(a^2+b^2+2*ep^2);
 
function bet=beta(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk,gamma)
dh=dah(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk);
bet=gamma*norm(dh)*min(1,norm(dh));
 
function [dd1,dd2,v1]=ddv(ep,d,lam,Ai,gk)
m=length(gk);
dd1=zeros(m,m); dd2=zeros(m,m); v1=zeros(m,1);
for(i=1:m)
    fm=sqrt(lam(i)^2+(gk(i)+Ai(i,:)*d)^2+2*ep^2);
    dd1(i,i)=1-lam(i)/fm;
    dd2(i,i)=1-(gk(i)+Ai(i,:)*d)/fm;
    v1(i)=-2*ep/fm;
end
 
function A=JacobiH(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk)
n=length(dfk);  l=length(hk);   m=length(gk);
A=zeros(n+l+m+1,n+l+m+1);
[dd1,dd2,v1]=ddv(ep,d,lam,Ai,gk);
if(l>0&&m>0)
    A=[1,   zeros(1,n), zeros(1,l), zeros(1,m);
        zeros(n,1), Bk, -Ae',   -Ai';
        zeros(l,l), Ae, zeros(l,l), zeros(l,m);
        v1,dd2*Ai,  zeros(m,l),dd1];
end
if(l==0)
    A=[1,   zeros(1,n), zeros(1,m);
        zeros(n,1), Bk, -Ai';
        v1,dd2*Ai,  dd1];
end
if(m==0)
    A=[1,   zeros(1,n), zeros(1,l);
        zeros(n,1), Bk, -Ae';
        zeros(l,1), Ae, zeros(l,l)];
end
 
function dh=dah(ep,d,mu,lam,dfk,Bk,Ae,hk,Ai,gk)
n=length(dfk);  l=length(hk);   m=length(gk);
dh=zeros(n+l+m+1,1);
dh(1)=ep;
if(l>0&&m>0)
    dh(2:n+1)=Bk*d-Ae'*mu-Ai'*lam+dfk;
    dh(n+2:n+l+1)=hk+Ae*d;
    for(i=1:m)
        dh(n+l+1+i)=phi(ep,lam(i),gk(i)+Ai(i,:)*d);
    end
end
if(l==0)
    dh(2:n+1)=Bk*d-Ai'*lam+dfk;
    for(i=1:m)
        dh(n+1+i)=phi(ep,lam(i),gk(i)+Ai(i,:)*d);
    end
end
if(m==0)
    dh(2:n+1)=Bk*d-Ae'*mu+dfk;
    dh(n+2:n+l+1)=hk+Ae*d;
end
dh=dh(:);

 

2.3 m文件测试

    使用2.2中的程序求解如下二次规划问题:

 

该问题的极小值点为。在Matlab命令窗口中输入如下命令:

    dfk=[-6 -2 -12]’;
    Bk=[2 1 0;1 4 0;0 0 0];
    Ae=[1 1 1];
    hk=[-2]’;
    Ai=[1 -2 0;1 0 0;0 1 0;0 0 1];
    gk=[3 0 0 0]’;
    [d,mu,lam]=qpsubp(dfk,Bk,Ae,hk,Ai,gk)

 

输出结果如下:

d =
           -0.0000
           -0.0000
            2.0000
mu =
          -12.0000
lam =
           -0.0000
          6.0000
           10.0000
           -0.0000    

 

 

2.4 m文件编译

    在Matlab命令行中输入编译命令:mcc -B cpplib:qpsubp qpsubp.m。第一次运行该命令是,Matlab会在本机上搜索可用的编译器,并列于命令窗口内,如下图所示:

 

选择输入1回车,等待编译结果,编译时间较长,编译后的输出提示如下图所示:

 

编译完成后,在\QPMAT文件夹下生成如下文件:

 

其中对于VS调用dll有用的文件包括qpsubp.h、qpsubp.lib与qpsubp.dll。

 

3 VS2010下测试dll

3.1 VS工程设置

启动VS2010,新建项目,项目目录选择\QPTEST,项目名称填QPVS,项目类型为win32下的控制台程序,如下图所示:

将文件\QPMAT文件夹下的qpsubp.h、qpsubp.lib与qpsubp.dll文件拷贝到文件夹\QPVS\QPVS下。由于操作系统和Matlab为64位,所以在VS下只能编译成64位程序才能正常链接到Matlab中的函数,需要在VS中新建一个64位的编译平台,步骤如下:

(1)   进入“配置管理器”

通过项目属性进入。

 

或者直接从工具栏平台的下拉箭头下进入:

 

(2)增加x64平台

 

确定,得到如下结果。

 

为工程添加Matlab的头文件和库文件路径,步骤如下:

项目属性——》VC++目录,如图:

 

包含目录增加:C:\Program Files\MATLAB\R2012b\extern\include

库目录增加:C:\Program Files\MATLAB\R2012b\extern\lib\win64\microsoft

3.2代码编辑

    编辑文件SQVS.cpp。编辑内容如下:

(1)添加头文件与作用域声明

#include <iostream>
#include "qpsubp.h"

using namespace std;

iostream为C++输入输出流类的头文件,与using namespace std配合后可调用cin、cout,qpsubp.h是调用二次规划dll的头文件。

(2)   链接库文件

#pragma comment(lib,"qpsubp.lib")

#pragma comment(lib,"mclmcrrt.lib")

Qpsubp.lib为调用二次规划dll的库文件,mclmcrrt.lib是调用Matlab相关函数的库文件。

(3)   初始化库文件

if( !qpsubpInitializeWithHandlers(NULL,0) )

    {

        std::cout << "Could not initialize the application!" <<

            std::endl;

        return -1;

    }

 

    if(!qpsubpInitialize())

    {

        std::cout << "Could not initialize the application!" <<

            std::endl;

        return -1;

    }

    else

    {

        cout<<"Application is initialized successfully!"<<endl;

}

(4)定义输入输出变量并城市化(根据m文件测试所用例子)

    

  mwArray mwdfk(3,1,mxDOUBLE_CLASS);

    mwArray mwBk(3,3,mxDOUBLE_CLASS);

    mwArray mwAe(1,3,mxDOUBLE_CLASS);

    mwArray mwhk(1,1,mxDOUBLE_CLASS);

    mwArray mwAi(4,3,mxDOUBLE_CLASS);

    mwArray mwgk(4,1,mxDOUBLE_CLASS);

 

    mwArray mwd;

    mwArray mwmu;

    mwArray mwlam;

 

    mwdfk(1,1)=-6;

    mwdfk(2,1)=-2;

    mwdfk(3,1)=-12;

 

    mwBk(1,1)=2;

    mwBk(1,2)=1;

    mwBk(1,3)=0;

    mwBk(2,1)=1;

    mwBk(2,2)=4;

    mwBk(2,3)=0;

    mwBk(3,1)=0;

    mwBk(3,2)=0;

    mwBk(3,3)=0;

 

    mwAe(1,1)=1;

    mwAe(1,2)=1;

    mwAe(1,3)=1;

 

    mwhk(1,1)=-2;

 

    mwAi(1,1)=1;

    mwAi(1,2)=-2;

    mwAi(1,3)=0;

    mwAi(2,1)=1;

    mwAi(2,2)=0;

    mwAi(2,3)=0;

    mwAi(3,1)=0;

    mwAi(3,2)=1;

    mwAi(3,3)=0;

    mwAi(4,1)=0;

    mwAi(4,2)=0;

    mwAi(4,3)=1;

 

    mwgk(1,1)=3;

    mwgk(2,1)=0;

    mwgk(3,1)=0;

    mwgk(4,1)=0;

(5)地用二次规划函数

qpsubp(3,mwd,mwmu,mwlam,mwdfk,mwBk,mwAe,mwhk,mwAi,mwgk);

(6)输出计算结果

    cout<<"d = ["<<mwd(1,1)<<","<<mwd(2,1)<<","<<mwd(3,1)<<"]"<<endl;

    cout<<"mu = ["<<mwmu(1,1)<<"]"<<endl;

    cout<<"lam = ["<<mwlam(1,1)<<","<<mwlam(2,1)<<","<<mwlam(3,1)<<","<<mwlam(4,1)<<"]"<<endl;

(7)屏幕停留、终止动态链接库与退出程序

    cout <<"Press any key to exit!" <<endl;

    cin.get();

 

    qpsubpTerminate();

3.3完整代码

 

#include "stdafx.h"

#include <iostream>

#include "qpsubp.h"

 

using namespace std;

 

#pragma comment(lib,"qpsubp.lib")

#pragma comment(lib,"mclmcrrt.lib")

 

int _tmain(int argc, _TCHAR* argv[])

{

    if( !qpsubpInitializeWithHandlers(NULL,0) )

    {

        std::cout << "Could not initialize the application!" <<

            std::endl;

        return -1;

    }

 

    if(!qpsubpInitialize())

    {

        std::cout << "Could not initialize the application!" <<

            std::endl;

        return -1;

    }

    else

    {

        cout<<"Application is initialized successfully!"<<endl;

    }

 

    mwArray mwdfk(3,1,mxDOUBLE_CLASS);

    mwArray mwBk(3,3,mxDOUBLE_CLASS);

    mwArray mwAe(1,3,mxDOUBLE_CLASS);

    mwArray mwhk(1,1,mxDOUBLE_CLASS);

    mwArray mwAi(4,3,mxDOUBLE_CLASS);

    mwArray mwgk(4,1,mxDOUBLE_CLASS);

 

    mwArray mwd;

    mwArray mwmu;

    mwArray mwlam;

 

    mwdfk(1,1)=-6;

    mwdfk(2,1)=-2;

    mwdfk(3,1)=-12;

 

    mwBk(1,1)=2;

    mwBk(1,2)=1;

    mwBk(1,3)=0;

    mwBk(2,1)=1;

    mwBk(2,2)=4;

    mwBk(2,3)=0;

    mwBk(3,1)=0;

    mwBk(3,2)=0;

    mwBk(3,3)=0;

 

    mwAe(1,1)=1;

    mwAe(1,2)=1;

    mwAe(1,3)=1;

 

    mwhk(1,1)=-2;

 

    mwAi(1,1)=1;

    mwAi(1,2)=-2;

    mwAi(1,3)=0;

    mwAi(2,1)=1;

    mwAi(2,2)=0;

    mwAi(2,3)=0;

    mwAi(3,1)=0;

    mwAi(3,2)=1;

    mwAi(3,3)=0;

    mwAi(4,1)=0;

    mwAi(4,2)=0;

    mwAi(4,3)=1;

 

    mwgk(1,1)=3;

    mwgk(2,1)=0;

    mwgk(3,1)=0;

    mwgk(4,1)=0;

 

    qpsubp(3,mwd,mwmu,mwlam,mwdfk,mwBk,mwAe,mwhk,mwAi,mwgk);

 

    cout<<"d = ["<<mwd(1,1)<<","<<mwd(2,1)<<","<<mwd(3,1)<<"]"<<endl;

    cout<<"mu = ["<<mwmu(1,1)<<"]"<<endl;

    cout<<"lam = ["<<mwlam(1,1)<<","<<mwlam(2,1)<<","<<mwlam(3,1)<<","<<mwlam(4,1)<<"]"<<endl;

 

    cout <<"Press any key to exit!" <<endl;

    cin.get();

 

    qpsubpTerminate();

 

    return 0;

}

 

 

3.4运行结果

 

4参考文献

[1]马昌凤.最优化方法及其Matlab程序设计.北京:科学出版社,2010.

[2]刘维.精通Matlab与C/C++混合程序设计.北京:北京航空航天大学出版社,2007.

posted @ 2014-11-17 10:56  综合农场  阅读(398)  评论(0)    收藏  举报