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

  • 1
    See the datatool package, you will find that you want ! (ctan.org/pkg/datatool) – flav Nov 25 '19 at 7:45
  • @flav Thank you!! Could you please give a small example on how I might implement this package? – user523384 Nov 25 '19 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 '19 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 '19 at 1:34
13

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

|improve this answer|||||
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

|improve this answer|||||
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

|improve this answer|||||
  • 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 '19 at 19:22
  • 1
    Effectively: Q: "How do I use a hammer to plant a screw?" A: "Use a screwdriver" – William 'Ike' Eisenhauer Nov 27 '19 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 '19 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

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.