2017-12-11 20 views
2

非常に長い記号式を生成するために、matlabのシンボリックツールボックスを使用します。次に、関数ファイルを生成するためにmatlabFunctionを使用します。 p1、p2、p3の3つのパラメータがあるとします。 文字列{'p1'、 'p2'、 'p3'}を持つセルがあります。 モデルの派生において、私はループ内でevalを使って記号変数p1、p2、p3を生成し、それらをベクトルparに積み重ねます。 その後、matlabFunctionに入力としてparを指定します。 また、セル文字列を.matファイルに保存します。matlab関数の評価を避ける

このモデルをシミュレートしたいときは、使用可能な30のパラメータとその値のうち、.matファイルの文字列セルを使用してこのパラメータ配列を作成できます。

利点:1つを追加する場合、異なるパラメータを追跡する必要はありません。私は秩序を変えることができますが、古いモデルはまだ機能します。 欠点: このエラーにつながる機能ファイルに物事を回す(PSIは、パラメータの一つである):

エラー:ファイル:f_derive_model.mライン:96カラム:5 「PSI」は、以前に使用しているように見えました関数または コマンドでは、 変数の名前としてここでの使用と競合します。 このエラーの原因としては、 の変数の初期化を忘れたか、 を暗黙的に使用してloadまたはevalを初期化したことが考えられます。

変数がevalステートメントで初期化されるため、いくつかのunnescescaryチェックが行われているようです。

質問:私は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つずつ呼び出す必要もありません。

答えて

0

実際には、「世論」がeval機能の使用を避ける方が良いと断言しても、私はあなたのアプローチに間違いを見ません。

I代わり getfield関数を使用する第二ケース( par変数に関するもの)において
% 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_len = numel(mdl.parameters); 
par = cell(par_len,1); 

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

、あるいは、これを次のように代替はassignin関数を使用することになりますアプローチ:

par_len = numel(mdl.parameters); 
par = cell(par_len,1); 

for i = 1:par_len 
    par{i} = params.(mdl.parameters{i}); 
end 
+2

私は恐怖の引用符を理解していません。一般的なルールとして誰もが反対するかもしれませんが、 'eval'は[文書化されたパフォーマンスの低下](https://www.mathworks.com/help/matlab/matlab_prog/string-evaluation)を作成します。html)。これは、JITコンパイラが 'eval'コマンドに対して無効になっているためです。バルク・インスタンシエーションやデータ処理の一般的な多用性を考えると、JITコンパイルから大きく利益を得ていますが、これは決して価値のあるトレードオフにはなりません。 – excaza

+0

私はeval関数が持っているパフォーマンスの含意についてはわかっています。私が覚えている限り、これまでに作ったスクリプトはひとつもありません。しかし、私は、制御された環境と非常に少ないコールの文脈の中で、それをspodaric使用することは、誰にも害を及ぼさないと思う。特に、Matlabを初めてお使いで、代替ソリューションを見つけることができない(または時間がない)場合は特にそうです。 –

+1

ありがとうございます。私は第2のケースも同様に考え出したので、そのケースを閉じてください。最初のケースでは、パフォーマンスの問題をよく認識しています.JITコンパイラは、このコードを関数として呼び出すときにエラーが発生する原因となります。私はMatlabには新しくなく、時間もありますが、柔軟性と堅牢性を備えたソリューションは見当たりません。私は、コードを変更する際に最も重大なエラーソースであるため、モデルパラメータリストと値リスト(getparams)以上のパラメータを追加する必要はありません。 – RinusHoog

関連する問題