如何加速MATLAB集成?

时间:2014-08-14 17:57:53

标签: performance matlab integral

我有以下代码:

function [] = Solver( t )

    %pre-declaration
    foo=[1,1,1];
    fooCell = num2cell(foo);
    [q, val(q), star]=fooCell{:};

    %functions used in prosomoiwsh
    syms q val(q) star;
    qd1=symfun(90*pi/180+30*pi/180*cos(q),q);
    qd2=symfun(90*pi/180+30*pi/180*sin(q),q);
    p1=symfun(79*pi/180*exp(-1.25*q)+pi/180,q);
    p2=symfun(79*pi/180*exp(-1.25*q)+pi/180,q);
    e1=symfun(val-qd1,q);
    e2=symfun(val-qd2,q);
    T1=symfun(log(-(1+star)/star),star);
    T2=symfun(log(star/(1-star)),star);

    %anonymous function handles
    lambda=[0.75;10.494441313222076];
    calcEVR_handles={@(t,x)[double(subs(diff(subs(T1,star,e1/p1),q)+subs(lambda(1)*T1,star,e1/p1),{diff(val,q);val;q},{x(2);x(1);t})),double(subs(diff(subs(T1,star,e1/p1),q)+subs(lambda(1)*T1,star,e1/p1),{diff(val,q);val;q},{0;x(1);t})),double(subs(double(subs(subs(diff(T1,star),star,e1/p1),{val;q},{x(1);t}))/p1,q,t))];@(t,x)[double(subs(diff(subs(T2,star,e2/p2),q)+subs(lambda(2)*T2,star,e2/p2),{diff(val,q);val;q},{x(4);x(3);t})),double(subs(diff(subs(T2,star,e2/p2),q)+subs(lambda(2)*T2,star,e2/p2),{diff(val,q);val;q},{0;x(3);t})),double(subs(double(subs(subs(diff(T2,star),star,e2/p2),{val;q},{x(3);t}))/p2,q,t))]};

    options = odeset('AbsTol',1e-1,'RelTol',1e-1);
    [T,x_r] = ode23(@prosomoiwsh,[0 t],[80*pi/180;0;130*pi/180;0;2.4943180186983711;11.216948999754299],options);

    save newresult T x_r

    function dx_th = prosomoiwsh(t,x_th)
        %declarations
        k=0.80773938740480955;
        nf=6.2860930902603602;
        hGa=0.16727117784664769;
        hGb=0.010886618389781832;
        dD=0.14062935253218495;
        s=0.64963817519705203;
        IwF={[4.5453398382686956 5.2541234145178066 -6.5853972592002235 7.695225990702979];[-4.4358339284697337 -8.1138542053372298 -8.2698210582548395 3.9739729629084071]};
        IwG={[5.7098975358444752 4.2470526600975802 -0.83412489434697168 0.53829395964565041] [1.8689492167233894 -0.0015017513794517434 8.8666804106266461 -1.0775021663921467];[6.9513235639494155 -0.8133752392893685 7.4032432556804162 3.1496138243338709] [5.8037182454981568 2.0933267947187457 4.852362963697928 -0.10745559204132382]};
        IbF={-1.2165533594615545;7.9215291787744917};
        IbG={2.8425752327892844 2.5931576770598168;9.4789237295474873 7.9378928037841252};
        p=2;
        m=2;
        signG=1;
        n_vals=[2;2];
        nFixedStates=4;
        gamma_nn=[0.31559428834175318;9.2037894041383641];
        th_star_guess=[2.4943180186983711;11.216948999754299];

        %solution
        x  = x_th(1:nFixedStates);
        th = x_th(nFixedStates+1:nFixedStates+p);

        f  = zeros(m,1);
        G  = zeros(m,m);
        ZF = zeros(p,m);
        ZG = zeros(p,m,m);

        for i=1:m
            [f(i), ZF(:,i)] = calculate_neural_output(x, IwF{i}, IbF{i}, th);
            for j=1:m
                [G(i,j), ZG(:,i,j)] = calculate_neural_output(x, IwG{i,j}, IbG{i,j}, th);
            end
        end

        detG = det(G);
        if m == 1
            adjG = 1;
        else
            adjG = detG*G^-1;
        end

        E = zeros(m,1);
        V = zeros(m,1);
        R = zeros(m,m);

        for i=1:m
            EVR=calcEVR_handles{i}(t,x);
            E(i)=EVR(1);
            V(i)=EVR(2);
            R(i,i)=EVR(3);
        end


        Rinv     = R^-1;
        prod_R_E = R*E;
        ub = f + Rinv * (V + k*E) + nf*prod_R_E;
        ua = - detG / (detG^2+dD) * (adjG * ub) ;
        u  = ua - signG * (hGa*(ua'*ua) + hGb*(ub'*ub)) * prod_R_E;

        dx_th = zeros(nFixedStates+p, 1); %preallocation

        %System in form (1) of the IEEE paper
        [vec_sys_f, vec_sys_G] = sys_f_G(x);
        dx_nm  = vec_sys_f + vec_sys_G*u;

        %Calculation of dx
        index_start = 1;
        index_end   = -1;
        for i=1:m
            index_end   = index_end + n_vals(i);
            for j=index_start:index_end
                dx_th(j) = x(j+1);
            end
            dx_th(index_end+1) = dx_nm(i);
            index_start = index_end + 2;
        end

        %Calculation of dth

        AFvalueT = zeros(p,m);
        for i=1:m
            AFvalueT(:,i) = 0;
            for j=1:m
                AFvalueT(:,i) = AFvalueT(:,i)+ZG(:,i,j)*ua(j);
            end
        end

        dx_th(nFixedStates+1:nFixedStates+p) = diag(gamma_nn)*( (ZF+AFvalueT)*prod_R_E -s*(th-th_star_guess) );
        display(t)
    end

    function [y, Z] = calculate_neural_output(input, Iw, Ib, state)
        Z = [tanh(Iw*input+Ib);1];
        y = state' * Z;
    end

    function [ f,g ] = sys_f_G( x )
        Iz1=0.96;
        Iz2=0.81;
        m1=3.2;
        m2=2.0;
        l1=0.5;
        l2=0.4;
        g=9.81;
        q1=x(1);
        q2=x(3);
        q1dot=x(2);
        q2dot=x(4);
        M=[Iz1+Iz2+m1*l1^2/4+m2*(l1^2+l2^2/4+l1*l2*cos(q2)),Iz2+m2*(l2^2/4+l1*l2*cos(q2)/2);Iz2+m2*(l2^2/4+l1*l2*cos(q2)/2),Iz2+m2*l2^2/4];
        c=0.5*m2*l1*l2*sin(q2);
        C=[-c*q2dot,-c*(q1dot+q2dot);c*q1dot,0];
        G=[0.5*m1*g*l1*cos(q1)+m2*g*(l1*cos(q1)+0.5*l2*cos(q1+q2));0.5*m2*g*l2*cos(q1+q2)];
        f=-M\(C*[q1dot;q2dot]+G);
        g=inv(M);
    end


end

其目标是使用某种控制律来模拟2自由度机械臂的控制。运行模拟后得到的结果是正确的(我有一个我应该期望的输出图),但是需要很长时间才能完成!

我有什么办法可以加快这个过程吗?

1 个答案:

答案 0 :(得分:1)

为了提高Matlab中任何集成的计算速度,您可以使用以下几个选项:

  1. 降低所需的准确度(您已经完成的)
  2. 使用适合的集成商。正如@sanchises所提到的,有时ode23可能比Matlab中的另一个ode求解器更长(例如,如果你的等式很僵硬)。您可以尝试从文档中确定哪个解算器最适合...或者只是尝试一下!
  3. 最好的解决方案,但到目前为止最耗时的是使用编译语言,如C或Fortran。如果集成只是Matlab程序的一部分,则可以使用Mex files,并仅将集成转换为编译语言。您还可以使用编译语言创建动态库,并使用loadlibrary在Matlab中加载它们。我使用loadlibrary和Fortran编写的集成例程来集成轨道和轨迹,我使用Fortran与Matlab进行了100多次加速!当然,从技术上讲,集成不再是Matlab ......但是库或Mex文件技巧只允许您将程序的集成部分转换为其他语言!有许多开源集成商可供选择,例如Fortran中的ODEPACKRKSUITE。然后,您只需要使用正确的语言创建包装器和动力学功能。
  4. 简而言之,如果你要使用这种集成,我会建议使用编译语言。如果没有,你应该用Matlab做,并耐心等待!