如何为向量矩阵运算符构建宏?

如何为向量矩阵运算符构建宏?

有人可以构建以下矢量操作的宏吗?

1) Example data: \def\a{(5,3,0)}
                 \def\b{(5,1,6)}
                 \def\A{(1,0,1\\0,2,0\\0,0,3)}
2) Vector addition: $\a+\b$ returns (10,4,6)
3) Vector subtraction: $\a-\b$ returns (0,2,-6)
4) Vector matrix multiplication: $\A*\a$ returns (5,6,0)

感谢 David 的代码,我扩展了以下内容:1) 向量加法、2) 向量减法、3) 向量乘法、4) 向量除法。我要做的是将代码扩展为 5) \car 和 \cdr 以进行列表处理。以下是第一步。

\documentclass{article}

\makeatletter

%main macros
\def\rvecadd#1#2{\edef\tmp{\noexpand\@rvecadd+#1,\relax#2,\relax}\tmp}
\def\rvecsub#1#2{\edef\tmp{\noexpand\@rvecadd-#1,\relax#2,\relax}\tmp}
\def\rvecmul#1#2{\edef\tmp{\noexpand\@rvecadd*#1,\relax#2,\relax}\tmp}
\def\rvecdiv#1#2{\edef\tmp{\noexpand\@rvecadd/#1,\relax#2,\relax}\tmp}
\def\rcar#1{\edef\tmp{\noexpand\@rcar#1,\relax}\tmp}
\def\rcdr#1{\edef\tmp{\noexpand\@rcdr#1,\relax}\tmp}

%recursive macros
\def\@rvecadd#1#2,#3\relax#4,#5\relax{%
\the\numexpr#2#1#4\relax
\ifx\@#3\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi{,\@rvecadd#1#3\relax#5\relax} }

\def\@rcar#1,#2\relax{%
#1\relax
\ifx\@#2\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi}

\def\@rcdr#1,#2\relax{%
#2\relax
\ifx\@#2\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi}


\begin{document}
%Data
\def\a{5,3,0,100,1}
\def\b{5,1,6,1000,1}
\def\A{1,0,1\\0,2,0\\0,0,3}
\def\aT{5\\3\\0}

%Test
$(\a) + (\b) = (\rvecadd\a\b)$\par
$(\a) - (\b) = (\rvecsub\a\b)$\par
$(\a) * (\b) = (\rvecmul\a\b)$\par
$(\a) / (\b) = (\rvecdiv\a\b)$

%car test:
\rcar\a

%cdr test
(\rcdr\a)

\end{document}

答案1

现在没有时间做乘法了,但是可以做简单的向量加法/减法。

\documentclass{article}

\def\a{5,3,0}
\def\b{5,1,6}
\def\A{1,0,1\\0,2,0\\0,0,3}
%2) Vector addition: $\a+\b$ returns (10,4,6)
%3) Vector subtraction: $\a-\b$ returns (0,2,-6)
%4) Vector matrix multiplication: $\A*\aT$ returns (5,6,0)

\makeatletter

\def\rvecadd#1#2{\edef\tmp{\noexpand\@rvecadd+#1,\relax#2,\relax}\tmp}
\def\rvecsub#1#2{\edef\tmp{\noexpand\@rvecadd-#1,\relax#2,\relax}\tmp}

\def\@rvecadd#1#2,#3\relax#4,#5\relax{%
\the\numexpr#2#1#4\relax
\ifx\@#3\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi{,\@rvecadd#1#3\relax#5\relax}}

\begin{document}

\def\a{5,3,0}
\def\b{5,1,6}
\def\A{1,0,1\\0,2,0\\0,0,3}
\def\aT{5\\3\\0}


$(\a) + (\b) = (\rvecadd\a\b)$


$(\a) - (\b) = (\rvecsub\a\b)$

\end{document}

答案2

我稍微改变了语法,省略了向量和矩阵中的括号。使用下面的代码,你可以做到

\setvector\a{5,3,0}
\setmatrix\A{1,0,1\\0,2,0\\0,0,3}
\begin{equation}
  \usematrix\A \cdot \usevvector\a
  = \matrixtimesvector\result\A\a  \usevvector\result
\end{equation}

要显示矩阵(垂直),请计算\A乘以乘以,并显示为垂直向量。\a\result\A\a\result

\documentclass{article}
\usepackage{expl3, xparse}
\usepackage{amsmath}
\ExplSyntaxOn
\seq_new:N \l__mypkg_a_seq
\seq_new:N \l__mypkg_b_seq
\seq_new:N \l__mypkg_result_seq
\int_new:N \l__mypkg_entries_int

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declaring vectors and matrices
%
\cs_new_protected:Npn \mypkg_set_vector:Nnn #1#2#3
  {
    \seq_set_split:Nnn #1 {#2} {#3} % Split into entries.
    \seq_set_map:NNn #1#1 { \fp_to_tl:n {##1} } % Evaluate each entry.
  }
\NewDocumentCommand { \setvector } { m O{,} m }
  {
    \mypkg_set_vector:Nnn \l__mypkg_result_seq {#2} {#3}
    \cs_set_eq:NN #1 \l__mypkg_result_seq
  }
\NewDocumentCommand { \setmatrix } { m O{\\} O{,} m }
  {
    \seq_clear:N \l__mypkg_result_seq
    \int_set_eq:NN \l__mypkg_entries_int \c_minus_one
    \seq_set_split:Nnn \l__mypkg_a_seq {#2} {#4} % Split into lines.
    \seq_map_inline:Nn \l__mypkg_a_seq
      {
        % Split each line |##1| into entries.  For the first line,
        % |\l__mypkg_entries_int| is -1 still; we set it to the
        % number of entries in the first line.  Then check that the line
        % has the right number of entries: if so, put it in the result
        % as a comma-delimited list, otherwise complain loudly and
        % ignore the line.
        %
        \mypkg_set_vector:Nnn \l__mypkg_b_seq {#3} {##1}
        \int_compare:nT { \l__mypkg_entries_int = \c_minus_one }
          {
            \int_set:Nn \l__mypkg_entries_int
              { \seq_count:N \l__mypkg_b_seq }
          }
        \int_compare:nTF
          { \seq_count:N \l__mypkg_b_seq = \l__mypkg_entries_int }
          {
            \seq_put_right:Nx \l__mypkg_result_seq
              { \seq_use:Nnnn \l__mypkg_b_seq { & } { & } { & } }
          }
          {
            \msg_error:nnxxx { mypkg } { mismatched-lines }
              { \token_to_str:N #1 }
              { \int_use:N \l__mypkg_entries_int }
              { \seq_count:N \l__mypkg_b_seq }
          }
      }
    \cs_set_eq:NN #1 \l__mypkg_result_seq
  }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Adding two vectors
%
\tl_new:N \l__mypkg_operation_tl
\NewDocumentCommand { \addvectors } { m m m }
  {
    \tl_set:Nn \l__mypkg_operation_tl { + }
    \mypkg_add_vectors:NN #2#3
    \cs_set_eq:NN #1 \l__mypkg_result_seq
  }
\NewDocumentCommand { \subvectors } { m m m }
  {
    \tl_set:Nn \l__mypkg_operation_tl { - }
    \mypkg_add_vectors:NN #2#3
    \cs_set_eq:NN #1 \l__mypkg_result_seq
  }
\cs_new_protected:Npn \mypkg_add_vectors:NN #1#2
  {
    \int_compare:nNnTF { \seq_count:N #1 } = { \seq_count:N #2 }
      {
        \seq_clear:N \l__mypkg_result_seq
        \seq_mapthread_function:NNN #1#2 \mypkg_add_vectors:nn
      }
      {
        \msg_error:nnxxxx { mypkg } { mismatched-vectors }
          { \token_to_str:N #1 } { \seq_count:N #1 }
          { \token_to_str:N #2 } { \seq_count:N #2 }
      }
  }
\cs_new_protected:Npn \mypkg_add_vectors:nn #1#2
  {
    \seq_put_right:Nx \l__mypkg_result_seq
      { \fp_to_tl:n { #1 \l__mypkg_operation_tl #2 } }
  }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Scalar product of two vectors
%
\NewDocumentCommand { \scalarproduct } { mmm }
  {
    \tl_set:Nx #1 { \mypkg_scalar_product:NN #2 #3 }
  }
\cs_new:Npn \mypkg_scalar_product:NN #1#2
  {
    \fp_to_tl:n
      { \seq_mapthread_function:NNN #1 #2 \mypkg_scalar_product_aux:nn }
  }
\cs_new:Npn \mypkg_scalar_product_aux:nn #1#2 { + #1 * #2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Multiplying matrix times vector
%
\NewDocumentCommand { \matrixtimesvector } { mmm }
  {
    \seq_clear:N \l__mypkg_result_seq
    \seq_map_inline:Nn #2
      {
        \seq_set_split:Nnn \l__mypkg_a_seq { & } {##1}
        \seq_put_right:Nx \l__mypkg_result_seq
          { \mypkg_scalar_product:NN \l__mypkg_a_seq #3 }
      }
    \cs_set_eq:NN #1 \l__mypkg_result_seq
  }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Displaying vectors and matrices
%
\NewDocumentCommand { \usehvector } { m }
  {
    \mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
    \ensuremath
      {
        \begin{pmatrix}
          \seq_use:Nnnn #1 { , } { , } { , }
        \end{pmatrix}
      }
  }
\NewDocumentCommand { \usevvector } { m }
  {
    \mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
    \ensuremath
      {
        \begin{pmatrix}
          \seq_use:Nnnn #1 { \\ } { \\ } { \\ }
        \end{pmatrix}
      }
  }
\NewDocumentCommand { \usematrix } { m }
  {
    \mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
    \ensuremath
      {
        \begin{pmatrix}
          \seq_use:Nnnn #1 { \\ } { \\ } { \\ }
        \end{pmatrix}
      }
  }

\msg_new:nnn { mypkg } { mismatched-lines }
  { The~lines~of~#1~should~have~#2~entries,~but~this~one~has~#3. }
\msg_new:nnn { mypkg } { mismatched-vectors }
  { The~vector~#1~has~#2~entries,~but~the~vector~#3~has~#4~entries. }
\msg_new:nnn { mypkg } { text-mode }
  { The~\iow_char:N\\use...~commands~should~only~be~used~in~math~mode. }

\ExplSyntaxOff
\begin{document}
\setvector\a{5,3,0}
\setvector\b{5,1,6}
\setmatrix\A{1,0,1\\0,2,0\\0,0,3}

Vector addition: $\usehvector\a+\usehvector\b$ returns
$\addvectors\result\a\b \usehvector\result$.  Subtraction:
\begin{equation}
  \usevvector\a - \usevvector\b
  = \subvectors\result\a\b \usevvector\result .
\end{equation}

Scalar product:
\begin{equation}
  \usehvector\a \cdot \usevvector\b
  = \scalarproduct\result\a\b \result
\end{equation}
Matrix-vector product
\begin{equation}
  \usematrix\A \cdot \usevvector\a
  = \matrixtimesvector\result\A\a  \usevvector\result
\end{equation}

% 2) Vector addition: $\a+\b$ returns (10,4,6)
% 3) Vector subtraction: $\a-\b$ returns (0,2,-6)
% 4) Vector matrix multiplication: $\A*\a$ returns (5,6,0)
\end{document}

相关内容