12

For an applied math setting, I need to write multiple inequality constraints into a LaTeX report which are all in the form

x_{i} + x_{j} \ge 1.

I've typed up what "i" and "j" are in an excel sheet as parallel columns. I was wondering if there would be a way to loop through these values to generate the 58 equations, which would save a lot of typing (and it would also really make this scalable if we needed 500 equations, for instance)?

For example: enter image description here

6
  • 1
    See the datatool package, you will find that you want ! (ctan.org/pkg/datatool)
    – flav
    Nov 25, 2019 at 7:45
  • @flav Thank you!! Could you please give a small example on how I might implement this package?
    – user523384
    Nov 25, 2019 at 7:47
  • 9
    Other people have answered the technical question of "how to do it". I will suggest a different idea: don't do it. Instead, say $x_{i} + x_{j} \geq 1$ for all pairs $(i,j)$ in... if I saw what you wanted in a book I'd think the author was trying to pad the page length.
    – nomen
    Nov 26, 2019 at 0:29
  • 1
    @nomen Thanks for the comment. Yes indeed, it would be a good idea to avoid it, but my purpose is to provide a self-contained report for a integer programming problem, and I'd prefer if the reader need not look elsewhere to get all the details required. I've managed to fit it on one page as a reference table of sorts, But thanks for the suggestion! I will keep something like that in mind for future reports.
    – user523384
    Nov 26, 2019 at 1:34

4 Answers 4

12

Here's a possible implementation; the delimiters can be changed.

\documentclass{article}
\usepackage{amsmath,multicol}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\constraints}{omO{x}}
 {
  \IfValueTF{#1}{\begin{multicols}{#1}\centering}{\begin{center}}
  \egreg_costraints:nn { #2 } { #3 }
  \IfValueTF{#1}{\end{multicols}}{\end{center}}
 }

\seq_new:N \l__egreg_constraints_seq

\cs_new_protected:Nn \egreg_costraints:nn
 {
  \seq_set_split:Nnn \l__egreg_constraints_seq { \\ } { #1 }
  \seq_map_inline:Nn \l__egreg_constraints_seq
   {
    \__egreg_constraints_item:nn { ##1 } { #2 }
   }
 }

\cs_new_protected:Nn \__egreg_constraints_item:nn
 {
  \tl_if_blank:nF { #1 }
   {
    $#2\sb{\clist_item:nn { #1 } { 1 }} + #2\sb{\clist_item:nn { #1 } { 2 }}\ge1$ \\
   }
 }

\ExplSyntaxOff

\begin{document}

\constraints{
  1,2 \\ 3,4 \\ 5,6
}

\constraints{
  1,2 \\ 3,4 \\ 5,6
}[y]

\constraints[3]{
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
  1,2 \\ 3,4 \\ 5,6 \\
}

\end{document}

enter image description here

0
12

You can automate the job by exporting the Excel spreadsheet to a comma delimited file (for example subscripts.csv) and reading your data with the readarray package.

MWE

Assuming that the content of subscripts.csv is:

1,2
1,3
2,39
7,5
26,5

The following code:

\documentclass{article}

\usepackage{readarray}
\usepackage{forloop}

\newcommand\constraint[2]{$x_{#1} + x_{#2} \ge 1$}

\begin{document}

\readarraysepchar{,}
\readdef{subscripts.csv}{\MyMacro}
\readarray\MyMacro\MyData[-,\ncols]

\newcounter{MyCounter}
\forloop{MyCounter}{1}{\value{MyCounter} < \MyDataROWS}
{
  \constraint{\MyData[\theMyCounter,1]}{\MyData[\theMyCounter,2]}\par
}

\end{document}

renders:

output

12

Use Excel's CONCAT function.

It's probably easiest to do this in Excel, especially if it's a one-time thing. Excel has several text-manipulation functions, and I have often found it a very convenient way to generate several similar lines of text or code. CONCAT(text1,text2,...) concatenates a bunch of text and data values into one text output.

If columns A and B contain your i and j values, enter the following in cell C1:

=CONCAT("x_{", A1, "} + x{", B1, "} \ge 1.")

and hit Enter. You can then copy-paste the function all the way down column C and get the result you want. You can then select all the output cells in column C and paste into your text editor.

enter image description here

3
  • 4
    concat can also be written using "&", so that the above is equivalent to ="x_{"&A1&"}+x_{"&B1&"}\ge 1." Whether this is simpler depends on the code involved.
    – Teepeemm
    Nov 25, 2019 at 19:22
  • 1
    Effectively: Q: "How do I use a hammer to plant a screw?" A: "Use a screwdriver" Nov 27, 2019 at 3:35
  • Funny thing is I haven't used LaTeX in years, but I did know how to solve this problem.
    – workerjoe
    Nov 27, 2019 at 13:21
0

I've always found the simplest way to do loops of this sort is the /foreach construct in PGF (\usepackage{pgffor}). The simplest way to use it would be something like:

\foreach \i/\j in {1/2, 1/3, 2/39} {$x_{\i} + x_{\j} \ge 1$ \quad}

which would just put everything on one line with \quads between them.

If you want to format this, you might want to line up the greater-thans, e.g. in an align environment. Unfortunately, just doing a \foreach loop in an align breaks as it can't handle the \\ line breaks properly. Instead, we can use a \foreach loop to build up a macro, and then afterwards wrap that macro in the align environment. Below (example 2) I use \xappto from the etoolbox package to build up the \constraintlist macro in this way.

By building things up in a macro, we can get quite creative. In example 3, I'm using the pgfmath library to only add \\ to the macro after every third constraint (otherwise & is added), which gives us the constraints in three columns, all nicely aligned on the greater-than sign.

Here's the code:

\documentclass{article}

\usepackage{pgffor}     % \foreach
\usepackage{amsmath}    % align* environment
\usepackage{etoolbox}   % \xappto and \gappto
\usepackage{pgfmath}    % \pgfmathparse and \pgfmathresult

\begin{document}

Example 1:
\begin{center}
    \foreach \i/\j in {
        1/2,
        1/3,
        2/39,
        2019/2020
    }{$x_{\i} + x_{\j} \ge 1$ \\}
\end{center}

Example 2:
\def\constraintlist{}
\foreach \i/\j in {1/2, 1/3, 2/39, 2019/2020}{
    \xappto\constraintlist{x_{\i} + x_{\j} &\ge 1 \noexpand\\}
}
\begin{align*}
    \constraintlist
\end{align*}

Example 3:
\def\constraintlist{}
\foreach \i/\j [count = \index] in {1/2, 1/3, 2/39, 2019/2020, a/b, foo/bar}{
    \xappto\constraintlist{x_{\i} + x_{\j} &\ge 1}

    \pgfmathparse{mod(\index, 3)==0}
    \ifnum\pgfmathresult=1
        \gappto\constraintlist{\\}
    \else
        \gappto\constraintlist{&}
    \fi
}
\begin{align*}
    \constraintlist
\end{align*}

\end{document}

which renders: latex render

You must log in to answer this question.

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