다양한 부분 미분을 위한 매크로 만들기

다양한 부분 미분을 위한 매크로 만들기

다음 MWE를 살펴보십시오.

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand\pdiff{s o m O{1} g O{1} g O{1}}% Star, function, variable 1, how many differentiations, ...
 {\newcount\pdiffn% Count the number of differentiations
  \advance\pdiffn #4\relax%
  \IfValueT{#5}{\advance\pdiffn #6\relax}%
  \IfValueT{#7}{\advance\pdiffn #8\relax}%
  \frac%
   {\partial \ifnum\pdiffn >1\relax ^{\the\pdiffn} \fi%
    \IfValueT{#2}{#2}}%
   {\IfValueT{#7}{\mathinner{\partial #7 \ifnum#8 >1\relax ^{#8} \fi}}%
    \IfValueT{#5}{\mathinner{\partial #5 \ifnum#6 >1\relax ^{#6} \fi}}%
    \mathinner{\partial #3 \ifnum#4 >1\relax ^{#4} \fi}}}

\begin{document}

\Huge

\[ \pdiff[f(x,y,z)]{y} \]

\[ \pdiff[f(x,y,z)]{y}[3]{x}{z} \]

\[ \pdiff[f(x,y,z)]{y}[9999]{x}[3333]{z}[8888] \]

\end{document}

(별 유형 인수를 무시하고 플랫 FRAC를 작성하는 데 사용했습니다(지금은 필요하지 않음).)

이는 미분이 3개의 변수로 제한되는 경우에 잘 작동합니다. 이 매크로를 더 많은 변수로 확장할 가능성이 있습니까? 이렇게 하면 이미 8개의 인수가 있으므로 작동하지 않습니다.

"SplitList"와 "ProcessList"를 알고 있지만 여기서는 각 변수에 대한 미분 수를 추가해야 하기 때문에 더 복잡합니다.

어떤 아이디어가 있나요?

여기에 이미지 설명을 입력하세요

답변1

listofitems키 값을 사용하는 접근 방식입니다 . 구문은 예를 들어

\pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)}

MWE는 다음과 같습니다

\documentclass{article}
\usepackage{listofitems,tikz}
\newcounter{totalindex}
\newcommand\pdiff[2][1]{%
  \setsepchar{,/=}%
  \readlist\Partialvars{#1}%
  \setcounter{totalindex}{0}%
  \foreach \Varindex in {1,...,\listlen\Partialvars[]}%
    {%
      \ifnum\listlen\Partialvars[\Varindex]>1\relax%
        \addtocounter{totalindex}{\Partialvars[\Varindex,2]}%
      \else%
        \stepcounter{totalindex}%
      \fi%
    }%
    \frac{\partial\ifnum\thetotalindex>1\relax^{\thetotalindex}\fi#2}%
         {%
          \foreach\Varindex in {1,...,\listlen\Partialvars[]}%
           {%
             \partial\Partialvars[\Varindex,1]%
             \ifnum\listlen\Partialvars[\Varindex]>1\relax^{\Partialvars[\Varindex,2]}\fi%
           }%
         }%
}
\begin{document}
\[ \pdiff[y]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z]{f(x,y,z)} \]
\[ \pdiff[y=9999, x=3333, z=8888]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)} \]
\end{document}

여기에 이미지 설명을 입력하세요

위에 사용된 루프 는 인덱스를 통한 루프를 위한 쉽게 이해할 수 있는 구성이지만 패키지 에 내장된 루프 구성을 사용하면 패키지 tikz \foreach사용을 완전히 제거할 수 있습니다 . 하지만 이 경우 루프는 목록의 항목을 통해 이루어지며 를 통해 인덱스 번호에 간접적으로 액세스할 수 있습니다 .tikzlistofitems\<loop-variable>cnt

\documentclass{article}
\usepackage{listofitems}
\newcounter{totalindex}
\newcommand\pdiff[2][1]{%
  \setsepchar{,/=}%
  \readlist\Partialvars{#1}%
  \setcounter{totalindex}{0}%
  \foreachitem \Var \in \Partialvars[]%
    {%
      \ifnum\listlen\Partialvars[\Varcnt]>1\relax%
        \addtocounter{totalindex}{\Partialvars[\Varcnt,2]}%
      \else%
        \stepcounter{totalindex}%
      \fi%
    }%
    \frac{\partial\ifnum\thetotalindex>1\relax^{\thetotalindex}\fi#2}%
         {%
          \foreachitem \Var \in \Partialvars%
           {%
             \partial\Partialvars[\Varcnt,1]%
             \ifnum\listlen\Partialvars[\Varcnt]>1\relax^{\Partialvars[\Varcnt,2]}\fi%
           }%
         }%
}
\begin{document}
\[ \pdiff[y]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z]{f(x,y,z)} \]
\[ \pdiff[y=9999, x=3333, z=8888]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)} \]
\end{document}

답변2

바퀴를 재발명할 필요가 없습니다. 이미 전용 패키지가 있습니다. esdiff이 패키지는 평가 포인트를 인덱스로 관리합니다.

\documentclass{article}

\usepackage{esdiff}

\begin{document}

    \[ \diffp{f(x, y, z)}{{x^{3333}}{y^{9999}}{z^{8888}}{t^{55555}}} \]%

    \[ \diffp*{f(x, y, z)}{{x^{3333}}{y^{9999}}{z^{8888}}{t^{55555}}}{(x_0,y_0,z_0,t_0)} \]%

\end{document} 

여기에 이미지 설명을 입력하세요

답변3

변수 목록에 쉼표로 구분된 목록을 사용할 수 있습니다. 나는 다음과 같은 규칙을 사용합니다.

x/2,y/3,z

두 번'이라는 뜻이다.엑스, 세 번와이그리고 한번". x/2,y/3,z/1원하는 경우 를 사용할 수도 있습니다 .

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\pdiff}{smm}
 {
  \IfBooleanTF{#1}
   {% with \pdiff* call the inner function for inline
    \egreg_pdiff_inline:nn { #2 } { #3 } % TO DO
   }
   {% with \pdiff call the inner function for display
    \egreg_pdiff_frac:nn { #2 } { #3 }
   }
 }

% allocate some variables
\int_new:N \l__egreg_pdiff_total_int
\seq_new:N \l__egreg_pdiff_vars_seq
\seq_new:N \l__egreg_pdiff_var_seq
\tl_new:N \l__egreg_pdiff_denom_tl

\cs_new_protected:Nn \egreg_pdiff_frac:nn
 {
  % clear the variables to be given values later
  \int_zero:N \l__egreg_pdiff_total_int
  \tl_clear:N \l__egreg_pdiff_denom_tl
  % split the second argumen at commas
  \seq_set_split:Nnn \l__egreg_pdiff_vars_seq { , } { #2 }
  % map this sequence for adding to the denominator and
  % computing the number of derivatives
  \seq_map_function:NN \l__egreg_pdiff_vars_seq \__egreg_pdiff_var:n

  % now print:
  % \l__egreg_pdiff_total_int is set to the number of derivatives
  % \l__egreg_pdiff_denom_tl contains the denominator
  \frac
   {
    \partial
    \int_compare:nT { \l__egreg_pdiff_total_int > 1 }
     { \sp { \int_to_arabic:n { \l__egreg_pdiff_total_int } } }
    #1
   }
   {
    \tl_use:N \l__egreg_pdiff_denom_tl
   }
 }

\cs_new_protected:Nn \__egreg_pdiff_var:n
 {
  % split the argument at / (it should be in the form 'x' or 'x/2')
  \seq_set_split:Nnn \l__egreg_pdiff_var_seq { / } { #1 }
  % if the sequence has one term, no exponent is present
  \int_compare:nTF { \seq_count:N \l__egreg_pdiff_var_seq < 2 }
   {% simple variable: add to the denominator and increment the number
    \tl_put_right:Nn \l__egreg_pdiff_denom_tl { \partial #1 }
    \int_incr:N \l__egreg_pdiff_total_int
   }
   {% multiple: add to the denominator and increment the number
    % item 1 contains the variable, item 2 the exponent
    \tl_put_right:Nx \l__egreg_pdiff_denom_tl
     {
      \partial
      \seq_item:Nn \l__egreg_pdiff_var_seq { 1 }
      \sp { \seq_item:Nn \l__egreg_pdiff_var_seq { 2 } }
     }
    \int_add:Nn \l__egreg_pdiff_total_int { \seq_item:Nn \l__egreg_pdiff_var_seq { 2 } }
   }
 }
\ExplSyntaxOff

\begin{document}

\[
\pdiff{f(x,y)}{x}
\quad
\pdiff{f(x,y,z)}{x/20,y/32,z}
\]

\end{document}

여기에 이미지 설명을 입력하세요

답변4

업데이트마지막에 더 나은 버전을 확인하세요.

이를 달성하기 위한 패키지가 있지만 xparse여기서는 이미 담당하고 있으므로 다른 방법을 제시합니다 ;-)

expl3파생 지정자 목록을 분할하고 토큰 목록을 작성하는 방법 :

구문: \pdiff{x/3,y/4,z/17}{f(x,y,z)}세 번째 파생물을 지정합니다. x에 대해서는 네 번째, y에 대해서는 네 번째, z에 대해서는 17번째입니다.

거듭제곱 또는 the를 생략하면 /도함수 순서로 해석됩니다 1.

(실수로 발생한 음수에 대한 확인이 추가되어야 함)

함수 인수는 평가되거나 확인되지 않습니다.

파생상품의 수는 내부적으로 계산됩니다.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\cs_generate_variant:Nn \int_add:Nn {Nx}
\seq_new:N \l_pdiff_deriv_seq

\NewDocumentCommand{\pdiffs}{mm}{%
  \int_zero:N \l_tmpa_int
  \seq_set_from_clist:Nn \l_tmpa_seq {#1} % Split the comma list
  \seq_map_inline:Nn \l_tmpa_seq {% Traverse the local entries
    \seq_set_split:Nnn \l_tmpb_seq {/} {##1}% Split into variable and order
    \tl_put_right:Nn \l_tmpa_tl {\partial}% Built the nominator list
    \int_compare:nNnTF {\seq_count:N \l_tmpb_seq } = {\c_one} {% Is there only one split element?
      \seq_put_right:Nn \l_tmpb_seq {\c_one}% Yes
      \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}} % Add now 'power'
    }{%
      \int_compare:nNnTF {\seq_item:Nn \l_tmpb_seq {2}} = {\c_one } {
        % Is the derivative order one --> no power? 
        \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
      }{
        \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}^{\seq_item:Nn \l_tmpb_seq  {2}}}
      }
    }
    \int_add:Nx \l_tmpa_int {\seq_item:Nn \l_tmpb_seq {2}}
  }
  % Display the list
  \mathinner{\frac{\partial^{\int_use:N\l_tmpa_int}#2}{\tl_use:N \l_tmpa_tl}}
}
\ExplSyntaxOff


\begin{document}

\Huge

\[\pdiffs{x/5,y/3}{f(x,y,z)}\]


\[\pdiffs{x/4,y/8,z/17}{f(x,y,z)}\]


\end{document}

여기에 이미지 설명을 입력하세요

변수 확인 및 자동 확장 기능이 포함된 개선된 버전:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\cs_generate_variant:Nn \int_add:Nn {Nx}
\cs_generate_variant:Nn \int_set:Nn {Nx}

\seq_new:N \l_pdiff_var_seq



\msg_new:nnn {pdiff}{negativedifforder}{Error:~The~order~of~derivative~is~negative~for~variable~#1!} 


\NewDocumentCommand{\pdiffs}{mm}{%
  \int_zero:N \l_tmpa_int
  \tl_clear:N \l_tmpa_tl
  \seq_clear:N \l_pdiff_var_seq
  \seq_set_from_clist:Nn \l_tmpa_seq {#1}
  \seq_map_inline:Nn \l_tmpa_seq {%
    \seq_set_split:Nnn \l_tmpb_seq {/} {##1}
    \seq_put_right:Nx \l_pdiff_var_seq {\seq_item:Nn \l_tmpb_seq {1}}
    \int_compare:nNnTF {\seq_count:N \l_tmpb_seq } = {\c_one} {
      \int_set:Nn \l_tmpb_int {\c_one}
      \seq_put_right:Nn \l_tmpb_seq {\c_one}
      \tl_put_right:Nn \l_tmpa_tl {\partial}
      \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
    }{%
      \int_set:Nx \l_tmpb_int {\seq_item:Nn \l_tmpb_seq {2}}
      \int_compare:nNnTF { \l_tmpb_int } < {\c_zero} {
        \msg_fatal:nnx {pdiff}{negativedifforder}{\seq_item:Nn \l_tmpb_seq {1}}
      }{%
        \int_compare:nNnF {\l_tmpb_int } = {\c_zero} {%
          \tl_put_right:Nn \l_tmpa_tl {\partial}
          \int_compare:nNnTF{ \l_tmpb_int } = {\c_one } {
            \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
          }{%
            \tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}^{\seq_item:Nn \l_tmpb_seq  {2}}}
          }
        }
      }
    }
    \int_add:Nx \l_tmpa_int {\l_tmpb_int}
  }
  \mathinner{\frac{\partial^{\int_use:N\l_tmpa_int}#2(\seq_use:Nn \l_pdiff_var_seq {,})}{\tl_use:N \l_tmpa_tl}}
}
\ExplSyntaxOff


\begin{document}

\Huge

\[\pdiffs{x/5,y/3,z/0}{f}\]


\[\pdiffs{x/4,y/8,z/17}{f}\]


\end{document}

관련 정보