我在matlab中使用符号工具箱来生成一些非常长的符号表达式。然后我使用matlabFunction生成一个函数文件。 假设有三个参数:p1,p2和p3。 我有一个带字符串的单元格{' p1',' p2',' p3'}。 在模型的推导中,我在循环中使用eval生成符号变量p1,p2和p3,并将它们堆叠在矢量参数中。 然后在matlabFunction中,我指定par作为输入。 此外,我将单元格字符串保存在.mat文件中。
然后,当我想模拟这个模型时,我可以使用.mat文件中的30个可用参数及其值中的字符串单元构造此参数数组。
优点:如果我添加一个参数,则无需跟踪不同的参数。我可以改变顺序,乱七八糟,但旧款仍然有用。 坏处: 将事物转换为函数文件会导致此错误(psi是参数之一):
错误:文件:f_derive_model.m行:96列:5 " PSI"以前似乎被用作功能或 命令,与此处的使用冲突,作为a的名称 变量。 这个错误的一个可能原因是你忘记了 初始化变量,或者您已初始化它 隐式使用load或eval。
显然正在进行一些不必要的检查,因为该变量将在eval语句中初始化。
问题:如何避免使用eval,但保持参数列表不依赖于模型。
导出长方程的代码:
^ // Start of the string
(?=.*[a-zA-Z]) // Does it have a character?
[a-zA-Z\d]* // The rest should be alphanumeric
$ // End of the string
使用生成的文件的代码:
% 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'});
看看,只要我指定正确的值,例如params.mp,它总是被分配给对应于par向量中的符号变量mp的输入。我不想丢失它并且必须跟踪顺序等等,我也不想逐个调用我的函数所有参数。
答案 0 :(得分: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