2

I want to implement function as tags. For now, this code is working:

In equations_folder/equations.tex

\EQUATION{miqp-obj}
\begin{equation}
  \label{eq:miqp-obj}
  \min_{\mathbf{x}}C = \frac{1}{2} \mathbf{x}^{T}Q\mathbf{x}+\mathbf{c}^{T}\mathbf{x} 
\end{equation}
\ENDEQUATION
 
\bigskip % use this to make a space between equations

\EQUATION{miqp-cons}
\begin{equation}
  \label{eq:miqp-cons}
  A\mathbf{x} \preceq \mathbf{b},
\end{equation}
\ENDEQUATION

Using a format.cls

\newcommand{\inputeq}[2]{% #1 = file, #2 = eq name
    \long\def\EQUATION ##1#2 {}%
    \input{#1}
}
\let\ENDEQUATION\endinput

And from my main.tex

    \inputeq{equations/equations}{{miqp-obj}}
    \inputeq{equations/equations}{{miqp-cons}}

Problem is, the miqp-obj is printed. I can fix it by edit the above code into: \inputeq{equations/equations}{miqp-obj} and \EQUATION miqp-obj, but the tag will lose the bracket. Can anyone help me modify the .cls code?

I've read this but does not satisfy my need.

__

Bonus: Originally, I want to implement bibtex-like function when we can cite our equation from a single centralized file. If you can help me with this, but not answering the main question, feel free to answer it that way. This is because I want to make a standard equation naming for my research group, and everyone should only cite this file or contribute to it first.

__

Edit: above code sadly only work if I cite only one equations. Solution to multi citing is using:

\EQUATION miqp-obj
\begin{equation}
  \label{eq:miqp-obj}
  \min_{\mathbf{x}}C = \frac{1}{2} \mathbf{x}^{T}Q\mathbf{x}+\mathbf{c}^{T}\mathbf{x} 
\end{equation}
\ENDEQUATION

Problem is, \EQUATION become a command with arbitrary many input.

5
  • 1
    I'm not sure that reading over and over again the same file each time you want to import an equation is the best thing to do. If the equations are not too many, you could read once the file and keep it in memory. Otherwise, interfacing with some database tool might be more efficient.
    – egreg
    Jun 20, 2021 at 12:34
  • @egreg Could you give an example of storing the data in the memory and print it as a means of citing equations? This is because I want to make a standard equation naming for my research group. Jun 20, 2021 at 14:11
  • Seems the text-file equations.tex is just a database of named equations where names are provided via "tags" of pattern \EQUATION{<name of equation>}. Why does that database contain things like \bigskip outside "named" areas? How to handle the case of the same tag being used twice, e.g. \EQUATION{foobar}..\ENDEQUATION occurring twice/several times within equations.tex, i.e., the tag not really being a primary key of the database? Jun 21, 2021 at 16:05
  • 1
    @MuhammadYasirroni Probably the package datatool is of interest. It can handle, e.g., comma-separated-value-files. Probably maintaining a database of snipets of .tex-code via a professional database management-system (MariaDB/MySQL/Access(brrr...)) and exporting to .csv-file, which in turn from within TeX can be handled via datatool, is an option? In the past I did some php-scripting for interacting with a database-server and creating .tex-files on the fly... Jun 21, 2021 at 21:39
  • Thanks, datatool seems interesting to be looked. Jun 28, 2021 at 4:36

2 Answers 2

2

Seems you have a ⟨.tex-file⟩ with a sequence of \EQUATION{⟨tag⟩}...\ENDEQUATION-thingies and you wish a command \inputeq{⟨.tex-file⟩}{⟨tag⟩} to deliver that one \EQUATION...\ENDEQUATION-thingie where ⟨tag⟩ is matching.

In other words:

  • Constellations of ⟨.tex-file⟩s form a database of equations.
  • \EQUATION{⟨tag⟩}...\ENDEQUATION-thingies form entries of that database.
  • ⟨tag⟩ is a primary-key/a unique identifier for an entry of that database.

As long as you are okay with obeying the conventions that

  • with \EQUATION...\ENDEQUATION-thingies the same ⟨tag⟩ is used only once/is not used repeatedly across all ⟨.tex-file⟩s used by \inputeq-commands within the whole document,
  • a ⟨.tex-file⟩ contains only material nested between \EQUATION{⟨tag⟩}...\ENDEQUATION

, a "poorman's approach" could be defining \EQUATION in terms of an undelimited argument trailed by an \ENDEQUATION-delimited argument.

In the following example I did some trickery for removing leading space-tokens from the \ENDEQUATION-delimited argument and for preventing the removal of curly braces that might surround the entire \ENDEQUATION-delimited argument.

The following example provides a command

\inputeq{⟨.tex-file⟩}{⟨tag⟩}

The "unstarred" variant of that command is intended to introduce an equation with equation-number and cross-referencing-label so that cross-referencing via \ref{...}/\pageref{...}/etc while using the hyperref-package yields a hyperlink to the corresponding place in the document.

The "starred" variant, i.e., \inputeq*{⟨.tex-file⟩}{⟨tag⟩} does not produce a cross-referencing label and is intended for repeating/quoting an equation introduced via the "unstarred" variant.

The "starred" variant can only be used if the "unstarred" variant is used with the same ⟨.tex-file⟩-argument and the same ⟨tag⟩-argument in the same document, too. Otherwise you get undefined-reference-errors.

% Compile with LaTeX.
%
% Just to make sure you have an external .tex-file   equations.tex   which
% can be used as   <.tex-file>  when applying 
%   \inputeq{<.tex-file>}{<tag>}%
% let's create a file   equations.tex   in the current directory via the
% filecontents*-environment:

\begin{filecontents*}{equations.tex}
\EQUATION{miqp-obj}
  \min_{\mathbf{x}}C = \frac{1}{2} \mathbf{x}^{T}Q\mathbf{x}+\mathbf{c}^{T}\mathbf{x} 
\ENDEQUATION
% 
% !!!! Nothing processable by TeX outside \EQUATION..\ENDEQUATION  !!!!!
%
\EQUATION{miqp-cons}
  A\mathbf{x} \preceq \mathbf{b},
\ENDEQUATION
\end{filecontents*}

% Between \makeatletter..\makeatother let's define "mechanisms"
%  - \EQUATION{<tag>}...\ENDEQUATION
%  - \inputeq{<.tex-file>}{<tag>}
%
\makeatletter
\RequirePackage{refcount}%
%%=============================================================================
%% PARAPHERNALIA:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%% \UD@stopromannumeral, \UD@CheckWhetherNull,
%% \UD@CheckWhetherLeadingExplicitSpace,
%% \UD@Stringify, \UD@checkstringsubsetof,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@removespace{\UD@Exchange{ }{\def\UD@removespace}{}}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% \UD@CheckWhetherLeadingExplicitSpace{<Argument which is to be checked>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does have a
%%                                       leading explicit space-token>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does not have a
%%                                       a leading explicit space-token>}%
\newcommand\UD@CheckWhetherLeadingExplicitSpace[1]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral\expandafter\UD@secondoftwo
      \string{\UD@CheckWhetherLeadingExplicitSpaceB.#1 }{}%
    }{}%
  }%
}%
\@ifdefinable\UD@CheckWhetherLeadingExplicitSpaceB{%
  \long\def\UD@CheckWhetherLeadingExplicitSpaceB#1 {%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
    {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
    {\expandafter\expandafter\expandafter\UD@stopromannumeral
     \expandafter\expandafter\expandafter}%
     \expandafter\UD@secondoftwo\expandafter{\string}%
  }%
}%
%%-----------------------------------------------------------------------------
%% Remove all leading spaces:
\newcommand\UD@RemoveAllLeadingSpaces[1]{%
  \romannumeral\UD@RemoveAllLeadingSpacesLoop{#1}%
}%
\newcommand\UD@RemoveAllLeadingSpacesLoop[1]{%
  \UD@CheckWhetherLeadingExplicitSpace{#1}{%
    \expandafter\UD@RemoveAllLeadingSpacesLoop\expandafter{\UD@removespace#1}%
  }{\UD@stopromannumeral#1}%
}%
%%=============================================================================
%% \inputeq{<.tex-file>}{<tag>}
%%.............................................................................
\newcommand*\TAGPHRASE{}%
\newcommand*\CrossRefFork{}%
\newcommand\inputeq{%
  \@ifstar{\global\let\CrossRefFork\UD@secondoftwo\Innerinputeq}%
          {\global\let\CrossRefFork\UD@firstoftwo\Innerinputeq}%
}%
\newcommand\Innerinputeq[2]{%
  \xdef\TAGPHRASE{\unexpanded{#2}}%
  \input{#1}%
}%
%%=============================================================================
%% \EQUATION{<TAG>}...\ENDEQUATION
%%.............................................................................
\newcounter{equationduplicates}%
\def\theHequationduplicates{someduplicate.\number\value{equationduplicates}}%
\newcommand*\EQUATION[1]{%
  \InnerEQUATION{#1} %Prepend a space to ensure surrounding brases aren't stripped off.
}%
\@ifdefinable\InnerEQUATION{%
  \long\def\InnerEQUATION#1#2\ENDEQUATION{%
     \begingroup
     \edef\tempa{\unexpanded{#1}}%
     \expandafter\endgroup
     \ifx\tempa\TAGPHRASE\expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi{}{%
       \begingroup
       \CrossRefFork{}{%
          \def\theequation{\getrefnumber{eq:#1}}%
          \refstepcounter{equationduplicates}%
          \let\theHequation\theHequationduplicates
       }%
       \begin{equation}\CrossRefFork{\label{eq:#1}}{}%
       \UD@RemoveAllLeadingSpacesLoop{#2}%
       \end{equation}%
       \CrossRefFork{}{\global\advance\c@equation by -1\relax}%
       \endgroup
     }%
  }%
}%
\makeatother

% Now let's create a nice document:

\documentclass{article}

\AtBeginDocument{%
  % Let's number equations within sections
  \def\theequation{\thesection.\arabic{equation}}%
  \csname @addtoreset\endcsname{equation}{section}%
}%

\usepackage{hyperref}

\begin{document}

\section{Referencing:}

\noindent Reference to equation \verb|miqp-obj|: \ref{eq:miqp-obj}

\noindent Reference to equation \verb|miqp-cons|: \ref{eq:miqp-cons}

\noindent\hrule\hfill

\section{Repeating:}

These are just repetitions not hyperlinked by cross-referencing-commands:

\inputeq*{equations.tex}{miqp-cons}

\inputeq*{equations.tex}{miqp-obj}

\noindent\hrule\hfill

\section{Originals:}

These are the "originals"/the targets for hyperlinks created by cross-referencing-commands:

\inputeq{equations.tex}{miqp-obj}

\inputeq{equations.tex}{miqp-cons}

\noindent\hrule\hfill

\section{Repeating again:}

These are just repetitions not hyperlinked by cross-referencing-commands:

\inputeq*{equations.tex}{miqp-obj}

\inputeq*{equations.tex}{miqp-cons}

\section{Another section}
\begin{equation}
x^2+y^2=z^2
\end{equation}

\end{document}

The example above creates a text-file equations.tex with the following content:

\EQUATION{miqp-obj}
  \min_{\mathbf{x}}C = \frac{1}{2} \mathbf{x}^{T}Q\mathbf{x}+\mathbf{c}^{T}\mathbf{x} 
\ENDEQUATION
% 
% !!!! Nothing processable by TeX outside \EQUATION..\ENDEQUATION  !!!!!
%
\EQUATION{miqp-cons}
  A\mathbf{x} \preceq \mathbf{b},
\ENDEQUATION

In the example above that file is used as ⟨.tex-file⟩ with \inputeq{⟨.tex-file⟩}{⟨tag⟩}-commands.

The resulting .pdf-file looks like this:

enter image description here

Some of the pitfalls:

  • ⟨.tex-files⟩ containing database-entries for "named equations" must obey the convention that all material processable by TeX is nested between \EQUATION{⟨tag⟩}...\ENDEQUATION.
  • As the ⟨tag⟩ also is used for creating the cross-referencing-label no two \EQUATIONs (across different equation.tex-files!!!) may use the same ⟨tag⟩.
    In other words: ⟨tag⟩ is to be a primary-key of the database that is formed by all ⟨.tex-files⟩ used via \inputeq within your document.
  • If many people are involved in maintaining the .tex-files containing equation-databases, some of these people probably not being all too familiar with TeX, ensuring the above "by hand and eyes" might be a problem.
    Therefore I strongly recommend maintaining databases via professional database-management-systems, e.g., MariaDB or MySQL, instead of using "manually"-maintained .tex-files for this purpose.
  • Things between \EQUATION{⟨tag⟩}...\ENDEQUATION are processed as macro-arguments. Therefore between \EQUATION{⟨tag⟩}...\ENDEQUATION you can't use commands/environments like \verb or verbatim where it is relied on temporarily changing the catcode-régime and having things read and tokenized from .tex-input-file under that changed catcode-régime.
  • Nesting \EQUATION{⟨tag⟩}...\ENDEQUATION might not turn out as intended.
  • I doubt that this list of pitfalls is complete. ;-)
2

You can load the file and populate a property list:

\begin{filecontents*}{\jobname-equations}
\EQUATION{miqp-obj}{
  \min_{\mathbf{x}}C = \frac{1}{2} \mathbf{x}^{T}Q\mathbf{x}+\mathbf{c}^{T}\mathbf{x} 
}
 
\EQUATION{miqp-cons}{
  A\mathbf{x} \preceq \mathbf{b},
}
\end{filecontents*}

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\prop_new:N \g_yassirroni_equations_prop

\NewDocumentCommand{\EQUATION}{mm}
 {
  \prop_gput:Nnn \g_yassirroni_equations_prop { #1 }
   {
    \begin{equation}\label{eq:#1}#2\end{equation}
   }
 }

\NewDocumentCommand{\useequation}{m}
 {
  \prop_item:Nn \g_yassirroni_equations_prop { #1 }
 }

\ExplSyntaxOff

\input{\jobname-equations} % use your own file name

\begin{document}

Here we set the first equation
\useequation{miqp-obj}
and now also the second one
\useequation{miqp-cons}
Let's see whether references work: \eqref{eq:miqp-obj} and \eqref{eq:miqp-cons}.

\end{document}

Here I use filecontents* just to make the example self-contained.

enter image description here

However, I'm doubtful that this would ease the workflow.

5
  • I fear that the wish to use the same equation several times within the same document might arise sooner or later. :-> \label being carried out several times with the same argument might lead to problems. (My own approach to that issue is an awful hack and I suppose there exist packages that might break things...) Jun 21, 2021 at 20:10
  • @UlrichDiez As I said, I'm doubtful that this would ease the workflow.
    – egreg
    Jun 21, 2021 at 20:40
  • I fully agree. Nonetheless probably wrapping things between \begin{equation}\label{...}...\end{equation} could be done by "usage-commands" (\useequation) rather than by the \EQUATION-command. That way different usage-commands could be defined. One placing cross-referencing-label. Another one not placing cross-referencing-label but ensuring the number coming from the cross-referencing-label to be re-used... Jun 21, 2021 at 20:47
  • @UlrichDiez I thought about that, but it would not solve the problem of using the equation in align, for example.
    – egreg
    Jun 21, 2021 at 20:49
  • And there is also the aspect of our fellow questioner mentioning a "research group". Maintaining whatsoever databases as .tex-file requires maintainers to obey many conventions "by eyes and hands". If many people are involved, some not all too familiar with TeX, this tends to become error-prone. Therefore I, too, think a workflow involving a professional database-management-system for maintaining a database of snippets of .tex-code might be better Jun 21, 2021 at 20:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .