예전에 MATLAB에서 문자연산을 이용해서 미분하는 법에 대한 이야기[관련글]를 했었습니다.

그런데 만약 사용할 변수가 어떤 변수(대체로 시간 t)에 대해 종속이면서, 여러 함수를 사용 중 이라면, 문자연산을 이용한 미적분의 적용에 애를 먹게 됩니다. 물론 애초 syms로 선언할 당시 시간에 관한 함수라고 선언하면 되지만, 그렇게 하면 일반적 수식이 아니라 텍스트형태로 나오는 결과가 해당 식이 아주 복잡할 때는 더더욱 알아보기 힘들게 됩니다. 이것을 극복하는 많은 방법이 있습니다만, 간단히 MATLAB이 제공하는 문자치환(subs) 명령어를 이용해서 극복해 보겠습니다.

그리고, 마지막에는 이를 함수(function)로 만들어 두고두고 사용할 수 있도록 한번 해보죠.




간단한 예제를 통해 프로그램의 흐름을 잡아보겠습니다.


위에 문자연산에 사용할 변수를 

syms x y a b z t

로 선언했습니다. 예제로 사용할 함수 z는

z = a*x^2 + b*y^2

으로 두겠습니다. 여기서 x, y는 모두 시간에 대한 함수입니다. 그러니 z라는 함수를 시간에 대해 미분했다면, 

dot_z = 2*a*x*dox_x + 2*b*y*dox_y

여야합니다. 

그러나 실제 MATLAB의 diff 명령을 이용해서 미분을 해보면


저런 결과가 나옵니다. 다변수함수인 경우, diff를 옵션없이 사용하면, x에 관해 미분을 수행하기 때문인데요.


저렇게 옵션을 줘도 편미분의 결과가 나타납니다. 뭐 당연히 x, y가 시간에 관한 함수라고 선언하지 않았기 때문이지요^^





그래서 x는 x(t)로 y는 y(t)로 문자를 바꾸기 위해서 위와 같이 tmp1, tmp2를 선언합니다.


그리고, subs 명령을 이용해 바꿔버리는 거지요.


subs 명령의 마지막, 옵션 '0'는 설명이 필요하겠네요.

tmp = subs(A, b, c)

라고만 명령을 주면, A라는 문자열에서 b를 c로 바꿔라는 명령인데요. 만약 A의 문자열에 b라는 글자가 없으면, 역으로 c를 찾아서 b로 바꿔버립니다. 그걸 하지 말라는 옵션이 마지막에 붙은 '0'입니다.

그리고 나서, 

diff(z, t) 

라고 명령을 주면, z를 t에 대해 미분하라가 되죠.



위 그림과 같은 결과가 나옵니다. 





그러나 일반적으로는 diff(x(t), t)라는 표현보다 우리한테는 dot_x가 익숙하고, 또, x(t)는 애초에 그냥 x라고 표현하고 싶었으니 다시 subs 명령을 사용해서



위와 같이 하면, 제가 원하는 출력이 나왔네요.

위 결과를 한글처럼 수식입력기에 넣기 전에, 한글에서 제공하는 스크립트를 사용해서 모든 *기호를 없애버리고, dot_x 은 dot{x} 이런 식으로 변환해주면, 일반 보고서를 작성하는데도 아주 도움이 됩니다.

마지막으로 이를 함수(function)화 하면


위와 같이 만들 수 있습니다. 위의 함수코드는 제가 만든것이 아니라 저의 지도교수님께서 만드신 것인데요. 저희 지도교수님은 사용자함수를 만들때 함수 이름앞에 'Z_'를 붙이는 습관을 가지고 계시지요^^. 위 함수는 제가 앞서 설명한 스텝을 흘러가기 때문에 별도로 설명드릴것은 없어보입니다. 


http://pinkwink.kr/trackback/322 관련글 쓰기
  • 재오리 2010/06/07 14:24

    함수 사용방법을 잘 모르겠는데요
    Z_diff_t(f,varargin) 에서 f에 원하는 함수를 쓰고 varargin자리에는 x, y 뭐이런식으로 사용하면 되는 건가요?

    • PinkWink 2010/06/07 16:29

      위 본문에서 사용한 걸로 한다면, 본문에서 함수 z를 선언했으니

      dot_z = Z_diff_t(z, x, y)

      라고 하시면 됩니다.

  • 훈쿤 2011/02/17 02:28

    1.
    simulink에서 현재값과 피드백된 상태값을 (현재값-상태값)/샘플링타임을 하고 싶습니다. 어떻게 구성해야할까요?

    2.matlab fcn블럭에서 m-fle로 작성시 현재 시뮬링크 샘플링타임값을 쓸수있는 방법은 없는지 궁금합니다.

    • PinkWink 2011/02/17 10:36

      시뮬링크에서는 환경설정에서 fixed time으로 설정하시고, 그냥 미분기를 사용하셔도 충분합니다. 혹은 ZOH를 사용하시면 될겁니다. 그리고, CLOCK블럭을 가져다 놓으셔서 시뮬레이션 시간을 받을 수 있습니다.

    • 훈쿤 2011/02/17 13:51

      미분기를 사용한다면 (현재값-이전값)/ts 가 되지 않을까요? 저는 이전값대신 상태값을 임의로 넣으려고합니다.

    • PinkWink 2011/02/17 14:21

      그러고 보니 질문하신 내용이 (현재값-상태값)/샘플링타임 였군요. 상태값이 현재값 아닌가요?? 현재의 상태값.. 이전 상태값.. 뭐 이럴 수도 있긴하지만... 잘 모르겠습니다.

    • 훈쿤 2011/02/17 16:24

      아 정확한 설명이 부족했습니다.
      현재값 = 현재 입력할 reference 속도
      상태값 = 피드백되어 돌아오는 측정속도입니다..

      즉, (입력 속도 - 측정된 속도)/ts 해서 각속도로 만들고싶은겁니다

    • PinkWink 2011/02/18 10:08

      언뜻 떠오르는 가장 빠르고 간단한 방법은 샘플링타임을 설정에서 고정(fix)하고 예를 들어 0.01의 값을 주었다면 직접... ref에서 현재값을 빼고 0.01로 나누면 되겠는데요^^

  • 훈쿤 2011/02/18 15:33

    제가 생각한 방법과 같군요^^ 제가 너무 어렵게 돌려서 생각한건 아닌가라고 후회하고 잇습니다 ㅎ
    pinkwink님이 말씀하신것처럼 matlab fcn을 이용해서 (ref-피드백값)/ts로 처리하고 x(n)-x(n-1) / ts 는 diff함수를 이용해서 diff(x)/ts로 처리하려고 합니다.

  • 블랙뷰티 2011/03/04 22:31

    포스팅 글 잘 읽었습니다. 혹시 질문한개만 드려도 될까요?
    저렇게 심볼릭해서 미분한 식에 특정값을 넣어서 함수값을 계산하도록 하는게 가능할지 궁금합니다. 예를 들어 위에서 미분하고 얻어진 dot_z라는 식에
    x, dot_x, y, dot_y라는 값을 지정해주어서 값으로 출력이 가능한지 궁금합니다.

    • PinkWink 2011/03/07 08:45

      가능합니다. 원하는 변수를 숫자로 치환하면 됩니다. subs같은 명령으로 말이죠

  • 김형준 2011/11/29 16:39

    포스팅 너무나 도움이 되었습니다.
    하지만 한가지 질문이 있습니다.
    x를 변수로 하는 f라는 시간함수를
    d/dt(df/dx)-df/dx
    와 같이 먼저 x에 대해 편미분하고 다음 시간에 대해 미분하는 것도 가능할까요?
    제가 적용해 볼려하니 에러가 생기네요

    • PinkWink 2011/11/29 19:25

      편미분하고, 시간에 대해 미분한다면

      d (round f / round x) / d t

      를 말씀하신건가요? 상관없을 것 같은데요. 단 시간에 대해 미분을 할때, x를 시간에 관함 함수라고 알려주어야겠지요.

  • 김형준 2011/11/30 16:30

    블로그 내용대로 x를 시간에 대한 함수라고 알려주었습니다.
    x를 x(t)로 바꾼후 시간에 대한 미분은 잘되는데...바뀐x(t)를 x에 대하여 편미분 하려 하면 에러가 뜨네요

    예를 들어
    f=ax(t) 로 시간에 관한 함수로 알려준후
    diff(f,t) 명령어르 하면 t에 관하여 올바른 미분값이 나오지만
    f=ax(t) 상태에서
    diff(f,x) 등 x에 대한 미분을 하려면 에러가 납니다.

    • PinkWink 2011/11/30 16:41

      그 후에는 약간의 노력이 필요합니다.
      일단 처음 질문이 편미분후에 미분한다고 하셨으니
      편미분을 수행한 후에
      남음 x들을 x(t)로 치환하는 작업이 필요합니다.
      그리고, 다시 t에 대해 미분하시면 됩니다.
      그 역도 비슷한 과정이구요.

  • 김형준 2011/11/30 16:41

    아...그리고tmp1=[char(x) '(t)']의 의미가 알고 싶습니다.
    tmp1이라는 행렬이 어떤 이유로 x(t)가 되는지 궁금합니다.

    여러 가지로 죄송합니다.
    아직 matlb초보인데 이것저것 너무 궁금하고 재미 있어서요

    • PinkWink 2011/11/30 16:42

      위에서 말씀드린 치환하는 작업입니다.
      시간에 대한 변수라고 알려주기 위해
      x를 x(t)로 만드는 작업이지요.

  • 김형준 2011/11/30 17:08

    답변 감사드립니다.
    역시 편미분 수행후 치환하고 t에 대하여 미분하는 방법밖에 없군요....
    한번에 하는방법이 있는지 궁금했습니다.

    tmp1이라는 문자열이 쉽게 말해
    char(x) 선언으로 x문자열과 (t)f라는 동시에 존재하는 문자열이 되는건가요?

    단순히 syms x(t) 와 어떤점이 다른지 구조적으로 궁금하네요

    • PinkWink 2011/12/01 19:46

      x라는 문자를 x(t)로 바꾸기 위해, x뒤에 (t)를 붙이라고 사용한 것입니다.

  • 류야 2012/10/31 11:55

    이게 symbolic 의 영향인지 모르겠지만 질문 드립니다.

    symbolic 을 사용하여 실수로 바꾸기 위해서, subs 혹은 double 명령어를 사용하였는데,

    (symbolic 연산의 영향인지는 정확히 모르겠으나, )

    계산 결과가 0 이 나와야 할 것들이 예를 들어 0 -2.11e-08i 의 결과 등 복소수로 나와버리는 경우가 있습니다.

    이게 0 이 되어야 하는데, 0에 가까운 복소수로 나와서 수식에 에러를 유발하는데 (real 을 써야 하는데 복소수가 들어와서 에러 발생)

    이러한 문제점을 수정하는 방법이 없을런지요??

    real 명령어로 강제적으로 실수로 바꿀수도 있겠지만, 이런 문제 (혹은 오차(?), 오류(?))를 발생하지 않도록 방지하는 방법이 있는지 궁금합니다.

    • PinkWink 2012/11/05 09:32

      강제로 실수로 두어도 된다면 상관은 없겠지만,
      확실히 로직상의 오류일 수도 있습니다.
      코드상에서는 아무 문제가 없어도,
      희한하게 저도 무슨 문제인진 몰라도 복소수의 표현으로 나타날때가 있었습니다.
      그런 경우, 표현법을 조금씩 바꾸어보면
      그런 경우가 없어졌었습니다.

  • sst 2012/12/26 17:41

    적분을 위와 같은 방법으로 한 경우 수행이 되지 안되더군요.
    가능한 방법이 있나요?

    • PinkWink 2012/12/26 17:55

      저런.. 너무나도 어려운 질문입니다.
      제가 답변할 수 있는 어떠한 정보도 없군요...

  • sst 2012/12/26 17:53

    syms x u da y;
    y = da/(x^2-u^2);
    tmp= [char(da) '(u)']; % da -> da(u)
    y = subs(y,da,tmp,0); % y -> y(u)
    int_y = int(y,u)

    아래와 같이 얻어집니다.
    Warning: Explicit integral could not be found.

    • PinkWink 2012/12/26 17:58

      아 윗 글에 대해 추가 질문이군요...
      음... 간단히 이야기해서 적분이 되지 않는다는 의미입니다.
      적분이 정의되지 않거나 혹은 적분에서 어떠한 조건들이 필요한 경우라고 보셔야할 듯 합니다.
      (코드를 보지는 않았습니다. 그냥 에러만 보고 말씀드리는 겁니다.)

  • 정병진 2014/05/20 01:47

    안녕하십니까! 구글링을 열심히 해보았지만 모르겠어서 질문드립니다...ㅠㅠ
    예를들어
    syms x t
    tmp1 = [char(x) '(t)']
    x= tmp1
    diff(x,t) 하면 결과값이 ans= diff(x(t) ,t) 라고 나옵니다. 그리고 x대신에 theta와 다른변수들을 집어넣어도
    ans = diff( ~~(t), t) 라고 나오는데 변수를 psi라고 잡으면
    ans = diff(1, t) 라고 나오는데 왜그런걸까요??... 별거 아니지만 궁금해서 질문드립니다...
    또한가지는 cos(x(t))를 사용해서 미분을 해보고싶은데 어떻게해야하는지 아무리 찾아봐도 모르겠습니다 ㅠㅠㅠ

    • PinkWink 2014/05/20 13:01

      네 그건 괄호 없이 변수로 사용하는건 문법상 문제가 안되는데
      문자연산을 위해 괄호를 사용하는 경우 즉
      psi(t)로 되는 경우는 좀 문제가 됩니다.
      그건 psi()라는 함수가 이미 있기 때문입니다.
      MATLAB command 창에서 doc psi 라고 입력해보시면 됩니다.
      그리고 cos(x(t))의 미분은

      syms x(t)
      diff(cos(x(t)), t)

      라고 하시면

      -sin(x(t))*diff(x(t), t)

      라고 응답이 나옵니다. 바로 사용할때는 (t)를 붙여서 syms를 선언하세요.^^

1 ... 17 18 19 20 21 22 23 24 25 ... 59