代码之家  ›  专栏  ›  技术社区  ›  R. H.

matlab函数中避免求值

  •  3
  • R. H.  · 技术社区  · 7 年前

    我使用matlab中的符号工具箱来生成一些很长的符号表达式。然后,我使用matlabFunction生成一个函数文件。 假设有三个参数:p1、p2和p3。 我有一个带有字符串{'p1',p2',p3}的单元格。 在模型的推导过程中,我在循环中使用eval从中生成符号变量p1、p2和p3,并将它们堆叠在向量par中。 然后在matlabFunction中,我指定par作为输入。 此外,我将单元格字符串保存在中。mat文件。

    然后,当我想要模拟这个模型时,我可以使用中的字符串单元格构造这个参数数组。mat文件,共有30个可用参数及其值。

    优点:如果向中添加一个参数,则无需跟踪不同的参数。我可以改变顺序,胡乱摆弄,但旧型号仍然可以使用。 缺点: 将内容转换为函数文件会导致此错误(psi是参数之一):

    错误:文件:f\u derivate\u model。m行:96列:5 “psi”之前似乎用作函数或 命令,与此处将其用作 变量 此错误的一个可能原因是您忘记了 初始化变量,或已初始化 隐式使用load或eval。

    显然,正在进行一些不明显的可怕检查,因为变量将在eval语句中初始化。

    问题:我如何避免eval,但保持参数列表与模型无关。

    推导长方程的代码:

    % Model parameters
    mdl.parameters = {'mp','mb','lp','lb','g','d','mP','mM','k','kt'};    
    
    par = [];
    
    for i=1:length(mdl.parameters)
        eval(strcat(mdl.parameters{i}, '=sym(''', mdl.parameters{i}, "');"));
        eval(sprintf(['par = [par;' mdl.parameters{i} '];']));
        end
    
    %% Calculate stuff
    
    matlabFunction(MM,'file',[modelName '_mass'],'vars',{par},'outputs',{'M'});
    

    使用生成的文件的代码:

        getparams
        load('m3d_1')
    
        par = [];
        for i=1:length(mdl.parameters)
            eval(sprintf(['par = [par;params.' mdl.parameters{i} '];']));
        end
    

    看看如何,只要我为例如params指定了正确的值。mp,它总是被分配给par向量中符号变量mp对应的输入。我不想失去它,不想跟踪顺序等等,也不想用所有参数逐个调用我的函数。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Tommaso Belluzzo    7 年前

    事实上,我认为你的方法没有错,即使“公众舆论”确认最好避免使用 eval 作用另一种方法是使用 assignin 功能如下:

    % use 'caller' instead of 'base' if this code runs within a function
    
    for i = 1:numel(mdl.parameters)
        var_name = mdl.parameters{i};
        assignin('base',var_name,sym(var_name));
    end
    

    在第二种情况下(关于 par 变量)我将使用 getfield 功能:

    par_len = numel(mdl.parameters);
    par = cell(par_len,1);
    
    for i = 1:par_len
        par{i} = getfield(params,mdl.parameters{i});
    end
    

    或者,这种方法:

    par_len = numel(mdl.parameters);
    par = cell(par_len,1);
    
    for i = 1:par_len
        par{i} = params.(mdl.parameters{i});
    end