在matlab函数中避免求值

在matlab函数中避免求值,matlab,function,eval,Matlab,Function,Eval,我使用matlab中的符号工具箱来生成一些很长的符号表达式。然后我使用matlabFunction生成一个函数文件。 假设有三个参数:p1、p2和p3。 我有一个带有字符串{'p1','p2','p3'的单元格。 在模型的推导中,我用循环中的EVE生成符号变量P1、P2和P3,并将它们堆叠在向量PAR中。 然后,在Matlab函数中,我指定PAR作为输入。 此外,我将单元格字符串保存在.mat文件中 然后,当我想要模拟这个模型时,我可以使用.mat文件中的字符串单元格,从30个可用参数及其值中构

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

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

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

错误:文件:f_派生_模型.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

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

事实上,我认为你的方法没有错,即使“公众舆论”肯定最好避免使用
eval
函数。另一种方法是使用以下功能:

% 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
变量的情况),我将使用以下函数:

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
会创建,因为JIT编译器对
eval
命令禁用。考虑到它们在大容量实例化或数据处理中的大量使用(这从JIT编译中获益匪浅),这绝不是一个值得权衡的问题。我知道eval函数的性能含义,而且据我所知,我所生成的脚本中没有一个使用它。然而,我认为,在受控环境和很少调用的情况下,随意使用它不会伤害任何人。特别是如果您是Matlab新手,无法(或没有时间)找到替代解决方案。谢谢你们。我也想出了第二个例子,所以考虑一下关闭。对于第一种情况,我很清楚性能问题,而JIT编译器恰恰是导致我仅在将此代码作为函数调用时才会出现错误的原因。我对Matlab既不是新手,也没有时间,但看不到一个同样灵活和健壮的解决方案。我不想在模型参数列表和值列表(getparams)之外添加参数,因为我是更改代码时最重要的错误源。