I want to write a macro for optimisation problems and my current approach is to write a macro, that takes the target function and a list of constraints. The entries are separated by comma, and each entry is of the type "(in)equality / range", e.g.

x_i \geq 0 / i=1,...,n

I got the idea from Defining a command with arbitrary number of parameters. However, this does not allow new lines inside an align.

My friend found out to use \pgfplotsforeachungrouped, but now I cannot write & inside the loop. The following code compiles, but does not look nice.

edit: now has entries of type \x/\y.

    \pgfplotsforeachungrouped \x/\y in {a/3, b/5, foo/0}{
      \x_i : \x = \x \quad i=\y \\

enter image description here

But if I replace the body of the loop by \x_i : \x &= \x \quad i=\y \\ (just adding the &), I get multiple errors `! Undefined control sequence.

Furthermore, using entry a/{0,\ldots,5} does not work as expected. It only takes the 0.

Also I might wish to put the range of my variable inside \tag, or similar. Tying this, I get another Undefined control sequence for `\y¸.

  • So how can I align these lines inside the loop? solved in answer of Steven B. Segletes
  • How can I have more complex values in the entries?
  • How can I place the second part of an entry inside \tag*{}?

Maybe-helpful-link: I don't understand Foreach loop in tabular, missing endgroup inserted, so I can't tell, whether the idea helps, but it seems to go in the direction.

  • This is a well-known problem with active characters: See tex.stackexchange.com/questions/227084/… – percusse Jul 9 '18 at 14:58
  • Would you please make a more sensible example based on what you actually want to achieve (the inequalities, I guess)? The example you give is a typical XY-problem. – egreg Jul 9 '18 at 15:15
  • @egreg Sorry, I was too focused on the alignment. I have adjusted my example and extended my question. – Hennich Jul 9 '18 at 15:37

Here's a fairly general macro that takes four mandatory arguments and one optional as described in the code.

The idea is to define a scheme for the input, in the examples it is #1/#2, but it can be whatever with any number of arguments (up to nine, of course); we also define the template for each row, using #1 and so on for the actual arguments to be substituted; finally, the input. The optional argument is for accommodating alignat or alignedat that need to know the number of column pairs to be typeset.

An internal function is defined to deliver the required template; then it is a matter of splitting the input at commas and feed each item to the template function.



 { % #1 = environment
   % #2 = optional for alignat
   % #3 = scheme for the variables
   % #4 = scheme for the rows
   % #5 = items
   \cs_set_protected:Npn \__hennich_row:w #3 \q_stop { #4 }
   \seq_set_split:Nnn \l__hennich_input_seq { , } { #5 }
     { \__hennich_row:n { ##1 } }
   \seq_use:Nn \l__hennich_output_seq { \\ }

\seq_new:N \l__hennich_input_seq
\seq_new:N \l__hennich_output_seq
\cs_new_protected:Nn \__hennich_row:n { \__hennich_row:w #1 \q_stop }



  {#1_{i} : #1 &= #1 & i&=#2}
  {a/3, b/5, foo/0}

  {#1_{i} : #1 &= #1 &\qquad i&=#2}
  {a/3, b/5, foo/0}


enter image description here


Here I build a token list, and then pass it to align*. The use of \xaddtotoks allows the first token in the list (here \x) to be expanded once in the building of the token list.

  \xaddtotoks\alignbuild{\x : }%
  \xaddtotoks\alignbuild{\x &= }%

enter image description here

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