避免在MATLAB函数中使用eval

3
我使用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”先前似乎被用作函数或命令,与其在此处用作变量名冲突。 此错误的可能原因是您忘记初始化变量,或者您已经使用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个回答

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

2
我真的不太理解这个引号。虽然你可能通常不同意每个人,但是eval会导致文档化的性能下降,因为JIT编译器对于eval命令被禁用了。考虑到它们在大量实例化或数据处理中的广泛使用,这几乎从来没有一个值得做出的权衡。 - sco1
我知道eval函数的性能影响,据我所记,我制作的脚本从未使用过它。然而,我认为在受控环境和极少调用的情况下,偶尔使用它不会对任何人造成伤害。特别是如果你是Matlab的新手,无法(或没有时间)找到替代解决方案。 - Tommaso Belluzzo
1
谢谢你们两个。我也解决了第二种情况,所以可以把它关闭了。至于第一种情况,我很清楚性能问题和JIT编译器正是导致当我将此代码作为函数调用时才出现的错误。我不是Matlab的新手,也有时间,但找不到一个既灵活又健壮的解决方案。我不想在模型参数列表和值列表(getparams)中添加超过一个参数,因为我在更改代码时是最大的错误源。 - R. H.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接