【问题标题】:Avoiding eval in matlab function在 matlab 函数中避免 eval
【发布时间】:2017-12-11 13:45:41
【问题描述】:

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

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

优点:如果我添加一个到 .我可以更改顺序,乱七八糟,但旧型号仍然可以使用。 坏处: 把东西变成函数文件会导致这个错误(psi是参数之一):

错误:文件:f_derive_model.m 行:96 列:5 “psi”以前似乎被用作函数或 命令,与其在此处用作 a 的名称相冲突 多变的。 此错误的一个可能原因是您忘记了 初始化变量,或者你已经初始化它 隐式使用 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 对应的输入。我不想丢失它并且必须跟踪订单等等,我也不想用所有参数一一调用我的函数。

【问题讨论】:

    标签: matlab function eval


    【解决方案1】:

    实际上,即使“公众舆论”肯定最好避免使用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
    

    【讨论】:

    • 我不太了解吓人的引语。虽然您可能不同意每个人的一般规则,但 eval 创建 documented performance degradation 因为 JIT 编译器对 eval 命令禁用。鉴于它们在批量实例化或数据处理中的广泛使用,从 JIT 编译中受益匪浅,这几乎不是一个值得做出的权衡。
    • 我知道 eval 函数对性能的影响,而且据我所知,我所编写的脚本中没有一个使用它。但是,我认为在受控环境和很少通话的情况下偶尔使用它不会伤害任何人。特别是如果您是 Matlab 新手并且无法(或没有时间)找出替代解决方案。
    • 谢谢你们。我也想出了第二种情况,所以认为那个已经关闭了。至于第一种情况,我很清楚性能问题,而 JIT 编译器正是导致我仅在将此代码作为函数调用时才得到的错误的原因。我对 Matlab 既不陌生,也有时间,但看不到同样灵活和健壮的解决方案。我不想在模型参数列表和值列表 (getparams) 之外添加参数,因为我是更改代码时最重要的错误源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    相关资源
    最近更新 更多