2017-12-11 16 views
2

아주 긴 기호식을 생성하기 위해 matlab의 기호 도구 상자를 사용합니다. 그런 다음 matlabFunction을 사용하여 함수 파일을 생성합니다. p1, p2 및 p3의 세 가지 매개 변수가 있다고 가정 해보십시오. 문자열 { 'p1', 'p2', 'p3'}이있는 셀이 있습니다. 모델의 유도에서 나는 루프에서 eval을 사용하여 기호 변수 p1, p2 및 p3을 생성하고이를 벡터 파에서 쌓습니다. 그러면 matlabFunction에서 입력으로 par를 지정합니다. 또한 셀 문자열을 .mat 파일에 저장합니다.matlab 함수의 평가 회피

이 모델을 시뮬레이트하려면 30 개의 사용 가능한 매개 변수와 해당 값 중에서 .mat 파일의 문자열 셀을 사용하여이 매개 변수 배열을 구성 할 수 있습니다.

장점 : 하나를 추가하면 다른 매개 변수를 추적 할 필요가 없습니다. 주문을 바꿀 수는 있지만 엉망진창이지만 구형 모델은 여전히 ​​작동합니다. 단점 : 함수 파일에 일을 돌리면이 오류로 연결 (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에 해당하는 입력에 항상 할당됩니다. 나는 그것을 잃고 싶지 않고 순서를 계속 추적해야하며, 모든 매개 변수로 함수를 하나씩 호출하고 싶지도 않습니다.

답변

0

사실, "여론"이 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 변수에 관한 것) I 대신 getfield 기능을 사용할 것이다 : 다른 방법은 다음과 같이 assignin 함수를 사용하는 것 또는,

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'은 [문서화 된 성능 저하]를 생성합니다 (https://www.mathworks.com/help/matlab/matlab_prog/string-evaluation.html). 왜냐하면 JIT 컴파일러는'eval' 명령에 대해 비활성화되어 있기 때문입니다. JIT 편집에서 많은 이득을 얻는 대량 인스턴스화 또는 데이터 처리에서 일반적으로 많이 사용되는 것을 감안할 때 이것은 가치있는 절충안입니다. – excaza

+0

나는 eval 함수가 가지고있는 성능 함의에 대해 알고있다. 내가 기억하는 한, 내가 만든 스크립트 하나가 이것을 사용하지는 않는다. 그러나, 나는 통제 된 환경과 아주 적은 호출의 맥락에서 그것의 spodaric 사용법이 아무도 해를 끼치 지 않을 것이라고 생각한다. 특히 Matlab을 처음 사용하고 있고 다른 솔루션을 찾아 낼 수없는 경우 (또는 가질 시간이 없다면). –

+1

감사합니다. 나는 두 번째 사건도 알아 냈으므로, 두 번째 사건은 끝났다고 생각해. 첫 번째 경우에 관해서는 성능 문제를 잘 알고 있으며 JIT 컴파일러는이 코드를 함수로 호출 할 때 오류가 발생하는 원인입니다. 나는 Matlab에 익숙하지 않고 시간도 있지만 유연하고 견고한 솔루션을 볼 수는 없습니다. 코드를 변경할 때 가장 중요한 오류 소스이므로 모델 매개 변수 목록 및 값 목록 (getparams) 이상에 매개 변수를 추가하지 않아도됩니다. – RinusHoog