2

For an assignment in my design theory class I am trying to construct idempotent latin squares and mutually orthogonal latin squares as stated in the question. I understand the process and can do this for small orders very easily, but for this particular problem I feel like it would be much quicker to write a program to generate these tables. I don't think any knowledge of design theory is necessary, but I certainly would appreciate someone helping me with the code to generate these tables.

Here is how the process works. I am given a pairwise balanced design of order 21 with blocks of size 5. For example, one block is {1,2,3,4,21}. I then use each block to create 3 idempotent latin squares of order 5. In each latin square

x<y<z<u<v

so for our particular block x=1,y=2,z=4,u=4,v=21. Here is the construction for the first idempotent latin square. (I'm confident that if I can get this coded I can modify it for the other 2). The outer row and column essentially create a multiplication table (think Cayley table from group theory) under the operation.

\documentclass[12pt]{article}
\usepackage{fullpage}

\begin{document}

\begin{tabular}{c|ccccc}
\(\circ_1\)&\(x\)&\(y\)&\(z\)&\(u\)&\(v\)\\
\hline
\(x\)&\(x\)&\(u\)&\(y\)&\(v\)&\(z\)\\
\(y\)&\(u\)&\(y\)&\(v\)&\(z\)&\(x\)\\
\(z\)&\(y\)&\(v\)&\(z\)&\(x\)&\(u\)\\
\(u\)&\(v\)&\(z\)&\(x\)&\(u\)&\(y\)\\
\(v\)&\(z\)&\(x\)&\(u\)&\(y\)&\(v\)
\end{tabular}

\end{document}

Using the idempotent latin squares for all 21 blocks, I can then create a latin square of order 21 where the (i,j) entry is found by locating the product in the previous latin squares. For example, in the construction given, y=2,z=3, and yz=21, so the (2,3) entry is 21.

Looking around, I found this topic Insert loop inside table? which mentions "This is a LaTeX solution, with a \forloop from forloop package. It builds a tabular array with a command \maketablerows{number_of_rows}{rowcontent}, where rowcontent is suspected to hold the values for the cells in a row, either direct or via a command." However, I have looked at the manual and I don't really see how to get {rowcontent} to generate what I want.

I know I could crank out a program to do this in C++ and make it export the tex table (aka the 21X21 latin square code, jeez!), but I was hoping someone could help guide me in how to do this in latex. I can figure out the programming logic, I just don't know the syntax to use.

TLDR: How do I use loops in latex to generate tables using specified formulas?

EDIT: Too long for a comment.

I believe I have found formulas for the other 2 and indeed one of them was 2(2x+y) mod 5, but the other I found was 2x-y mod 5. I am trying to convert these to formulas like you did for 3(x+y), which got me tinkering with your given formula of 3*(#2+#3)-5*((3*(#2+#3)+3)/5 -1)+1.

If I am understanding this correctly,

\expandafter\edef\csname Latin-\aBlock{#2+1}-\aBlock{#3+1}\endcsname {\aBlock{3*(#2+#3)-5*((3*(#2+#3)+3)/5 -1)+1}}% % this is crazy formula which simply does 3(a+b) modulo 5 % but recall it is a+1 and b+1 which serve as arguments to % the array \aBlock

is saying if I take the numbers 3,4 in the block 0,1,2,3,4, then the number 3*(3+4)-5((3*(3+4)+3)/5-1)+1=3 should appear in the ((3+1,4+1))=(4,5) entry? I must be misunderstanding the part where you are adding 1 to #2 and #3 as I've tried adding 1 then performing the operation, along with putting the calculated vaule into the (#2+1,#3+1) cell and still am not getting the values that are in the table.

  • 1
    For 2(2x+y) this would be \aBlock{2*(2*#2+#3)-5*((2*(2*#2+#3)+3)/5 -1)+1} and for 2x-y it would be \aBlock{(2*#2-#3)-5*((2*#2-#3+3)/5 -1)+1}. The crazyness is in part caused by \numexpr division which rounds rather than truncating. – user4686 Nov 14 '17 at 22:27
  • I appreciate the help, but could you explain why these are the formulas that work? As I mention in the last comment, I tried following your formula using your given table and was getting different entries. – JohnC Nov 14 '17 at 22:34
  • 1
    Perhaps you the division / does not behave like you expect. In numexpr for example 3/5 gives 1 and 2/5 gives 0. It rounds up. Thus (a+3)/5-1 is magic formula to get euclidean quotient of a by 5. Hence the modulo will be a - 5*((a+3)/5-1). So the formulas above implement 2(2x+y) and 2x-y but there is the additional twist that macro \aBlock wants its argument to be over the range 1, 2, 3, 4, 5. The #2 and #3 are already looping from 0 to 4, hence the code contains \aBlock{#2+1} to recover the block elements, etc.., – user4686 Nov 14 '17 at 22:39
  • 1
    and there is a final +1 in the formula above to go from mod 5 to 1, 2, 3, 4, 5. A propos magic formula (a+3)/5-1one has to be careful that a has to be non-negative. So the (2*#2-#3)-5*((2*#2-#3+3)/5 -1)+1 is wrong, one must use (2*#2+4*#3)-5*((2*#2+4*#3+3)/5 -1)+1. Python language has periodic modulo but this fails in other languages and in particular with eTeX's \numexpr division and one has to pay attention to sign of argument. – user4686 Nov 14 '17 at 22:39
  • 1
    just to point out the 2x-y mod 5 is same as 2x+4y = 2(x+2y) mod 5, which was indeed among listed possibilities :)... and as explained in previous comments for matter of modulo computations with numexpr, one must avoid negative numbers which add their own twists, so 2(x+2y) is to be preferred anyhow... – user4686 Nov 15 '17 at 8:31
3

Table of contents

  • general method

  • proof of concept from Fano plane to obtain 7 by 7 case

  • the projective plane over F4 has 16+4+1 = 21 points and lines. Thanks to an explicit enumeration found here I could apply the previously described method. I used the Latin square 5x5 of OP, which is simply 3(x+y) mod 5. Each pair of points lie on a unique one of the 21 projective lines. Each projective line has 5 points and we can thus use 5x5 Latin squares there. Using always the same we construct a 21x21 Latin square. Because the enumeration at https://www.uwyo.edu/moorhouse/pub/planes/pg24.txt of the points is from 0 to 20, I kept that in final result, hence rows and columns are indexed from 0 to 20, not 1 to 21, but this is detail which can be changed.


Here is how one could go about it: you have 21 blocks B each of size 5x5.

For each such block B, you use \@namedef{Latin-i-j}{the value at row i and column j for the 5x5 Latin square with letters from B}. Your small Latin squares are idempotent so one the diagonal at i, i we simply have i. Each small Latin block defines 20 values off-diagonal.

So you need a loop over the 21 blocks B for each to define 20+5 macros (diagonal ones will be defined again by other blocks, but that's ok). Once done your big Latin square which contains 21 times 20 = 420 off-diagional elements plus 21 diagonal elements for a total of 441 = 21x21 pairs is prepared. The diagonal is known because your small Latin squares are idempotent.

You can then typeset it using a construct like this:

\documentclass{article}
\usepackage{array}
\usepackage{xinttools}
% YOU NEED HERE TO DO A LOOP OVER THE BLOCKS TO DEFINE SUITABLY
% (POSSIBLY EVEN BY SOME \numexpr FORMULA) THE 21 x 21 MACROS
% \makeatletter
% % some loop here over the block to define for each suitable
% % \@namedef{Latin-i-j}
% \makeatother
\edef\TwentyOneNumbers{\xintSeq{1}{21}}
\begin{document}
\makeatletter
\begin{tabular}{*{22}{c|}}
  % first row
\xintFor* #1 in \TwentyOneNumbers\do{&#1}\\
\hline
\xintFor* #1 in \TwentyOneNumbers\do{% this will be row number #1
  #1
  \xintFor* #2 in \TwentyOneNumbers\do{% this indices the columns
     &\@nameuse{Latin-#1-#2}}
  \\\hline}
\end{tabular}
\makeatother
\end{document}

The mwe above is lacking all the needed \@namedef because you did not explain what the blocks were (the 5x5 Latin square you gave is at first sight simply addition in Z/5Z up to renaming of indices). So currently we only get this:

enter image description here

the above table spills over right margin, but I didn't fix the page layout (which is very narrow in LaTeX default, better use package geometry). Also the columns are of varying widths which should be fixed. Finally, I took over inclusion of first row and first column from your 5x5 example, perhaps as Latin square these decorations should be removed to really ahve a 21x21 not 22x22 grid.


As proof of concept here is a construction a 7x7 Latin square base on the geometry of the Fano plane. The lines give our 7 blocks of each 3 elements.

For 3x3 idempotent Latin squares I chose addition modulo 3 (more precisely -x-y mod 3 to get idempotence). The formula can be implemented by a \numexpr expression. The \numexpr is tacit, because I use \xintAssignArray from xinttools, which defines a macro whose argument is automatically evaluated via \numexpr. This argument starts at 1 (the value 0 gives the number of elements of the array, here 3 in this application as blocks are of size 3).

Each pair of distinct elements from 1 to 7 is contained in a unique Block. Applying the recipe we construct a 7 by 7 Latin square.

In the general description I mentioned \@namedef but here I needed to expand argument, sadly LaTeX is extremely limited in terms of "programming", so I had to go to deeper lying TeX primitives for this bit.

In your specific case you seem to be aiming at 3 distinct 21x21 squares, so you need to adapt or repeat the procedure here by looping again over blocks.

\documentclass{article}
\usepackage{array}
\usepackage{xinttools}

% Take a pairwise design from Fano Plane

% I picked up the blocks at https://fr.wikipedia.org/wiki/Plan_de_Fano
% but I needed to shift by 1 the enumeration to manipulate 1, 2, ..., 7

% For each block, having 3 elements, I will construct an idempotent Latin
% square from addition modulo 3.

\xintFor #1 in {{1, 2, 4}, {2, 3, 5}, {3, 4, 6}, {4, 5, 7}, {5, 6, 1},
   {6, 7, 2}, {7, 1, 3}}\do{%
  \xintAssignArray\xintCSVtoList{#1}\to\aBlock
  % arrays defined by \xintAssignArray are indexed starting at 1
  \xintFor #2 in {0, 1, 2}\do{%
   \xintFor #3 in {0, 1, 2}\do{%
   % unfortunately LaTeX has very few programming tools,
   % there is \@namedef but not even a \@nameedef
    \expandafter\edef\csname Latin-\aBlock{#2+1}-\aBlock{#3+1}\endcsname
    {\aBlock{2*(#2+#3)-3*((2*(#2+#3)+2)/3 -1)+1}}%
    % this is crazy formula which simply does -(a+b) modulo 3
    % which is same as 2(a+b) (we prefer non negative numbers with \numexpr)
    % but a = i-1, b = j-1, and modulo is complicated with \numexpr
    % (\numexpr is used by \aBlock to parse its argument)
    % (this is property of "arrays" defined by \xintAssignArray)
   }%
  }%
}

% done, all our macros defined

\edef\SevenNumbers{\xintSeq{1}{7}}
\begin{document}
\makeatletter
\begin{tabular}{*{8}{c|}}
  % first row
\xintFor* #1 in \SevenNumbers\do{&#1}\\
\hline
\xintFor* #1 in \SevenNumbers\do{% this will be row number #1
  #1
  \xintFor* #2 in \SevenNumbers\do{% this indices the columns
     &\@nameuse{Latin-#1-#2}}
  \\\hline}
\end{tabular}
\makeatother
\end{document}

enter image description here


Now the real thing, using the 21-plane.

\documentclass{article}
\usepackage{geometry}
\usepackage{array}
\usepackage{xinttools}

% The projective plane over the field of 4 elements has 
% 16+4+1 = 21 points.

% It also has 21 lines. Each pair of distinct points 
% is contained in a unique line.

% A projective line has 4+1 = 5 elements and we can
% construct an idempotent Latin square using the field
% with five elements and the rule 3(x+y) modulo 5
% as 6x is same as x modulo 5. This is indeed exactly the
% rule in the OP's example of Latin square.

% Thus we will get a 21x21 Latin square from that, simply
% by enumerating the 21 projective lines in the projective
% plane over F_4.

% We need a list of those lines, with the points of the plane
% are suitably enumerated. Thankfully, we found one at
% https://www.uwyo.edu/moorhouse/pub/planes/pg24.txt

% 0 1 2 3 4
% 0 5 6 7 8
% 0 9 14 15 16
% 0 10 12 17 19
% 0 11 13 18 20
% 1 5 9 10 11
% 1 6 14 17 18
% 1 8 13 16 19
% 1 7 12 15 20
% 2 5 14 19 20
% 4 5 13 15 17
% 3 5 12 16 18
% 2 6 9 12 13
% 2 7 11 16 17
% 2 8 10 15 18
% 3 6 11 15 19
% 4 6 10 16 20
% 4 7 9 18 19
% 3 8 9 17 20
% 4 8 11 12 14
% 3 7 10 13 14

% Our points are enumerated from 0 to 20.
% I manipulated it using search/replace in an Emacs buffer into
% nice format for input to \xintFor and \xintAssignArray

\xintFor #1 in {%
{0}{1}{2}{3}{4},
{0}{5}{6}{7}{8},
{0}{9}{14}{15}{16},
{0}{10}{12}{17}{19},
{0}{11}{13}{18}{20},
{1}{5}{9}{10}{11},
{1}{6}{14}{17}{18},
{1}{8}{13}{16}{19},
{1}{7}{12}{15}{20},
{2}{5}{14}{19}{20},
{4}{5}{13}{15}{17},
{3}{5}{12}{16}{18},
{2}{6}{9}{12}{13},
{2}{7}{11}{16}{17},
{2}{8}{10}{15}{18},
{3}{6}{11}{15}{19},
{4}{6}{10}{16}{20},
{4}{7}{9}{18}{19},
{3}{8}{9}{17}{20},
{4}{8}{11}{12}{14},
{3}{7}{10}{13}{14}}\do{%
  \xintAssignArray#1\to\aBlock
  % arrays defined by \xintAssignArray are indexed starting at 1
  \xintFor #2 in {0, 1, 2, 3, 4}\do{%
   \xintFor #3 in {0, 1, 2, 3, 4}\do{%
    \expandafter\edef\csname Latin-\aBlock{#2+1}-\aBlock{#3+1}\endcsname
    {\aBlock{3*(#2+#3)-5*((3*(#2+#3)+3)/5 -1)+1}}%
    % this is crazy formula which simply does 3(a+b) modulo 5
    % but recall it is a+1 and b+1 which serve as arguments to
    % the array \aBlock
   }%
  }%
}

% done, all our macros defined

\edef\TwentyOneNumbersStartingAtZero{\xintSeq{0}{20}}
\begin{document}
\makeatletter
\begin{tabular}{*{22}{c|}}
  % first row
\xintFor* #1 in \TwentyOneNumbersStartingAtZero\do{&#1}\\
\hline
\xintFor* #1 in \TwentyOneNumbersStartingAtZero\do{% this will be row number #1
  #1
  \xintFor* #2 in \TwentyOneNumbersStartingAtZero\do{% this indices the columns
     &\@nameuse{Latin-#1-#2}}
  \\\hline}
\end{tabular}
\makeatother
\end{document}

enter image description here

  • 1
    In the code above the (complicated) formula \aBlock{3*(#2+#3)-5*((3*(#2+#3)+3)/5 -1)+1} is simply because small Latin square corresponded to 3(x+y) modulo 5. Any 5x5 Latin square can be encoded by \smallLatinUV macros where U and V range over 0, 1, .., 4. Then simply use \aBlock{\@nameuse{smallLatin#2#3}+1}. The +1 is because the smallLatin is encoded with indices from 0 to 4, but the \aBlock array counts starting at 1. Here as #2 and #3 are simple digits, #2#3 is unambiguous and needs no separator. – user4686 Nov 9 '17 at 16:49
  • 1
    the projective line through "point2" and "point5" is listed as 2 5 14 19 20. Map them in this order to 0 1 2 3 4. Thus 2 becomes 0 and 5 becomes 1, and 3(x+y) mod 5 gives 3 mod 5 which is mapped to "point19". Take 6 and 9, we find the line 2 6 9 12 13, hence 6 is mapped to x=1 and 9 to y=2 and 3(x+y) is 9 mod 5 i.e. 4 which is reverse-mapped to 13. – user4686 Nov 14 '17 at 18:42
  • 2
    I did not look at your table but at the rendering in @Andrew's answer... I mentally replaced 21 by 5 and noticed each horizontal was going by +3 increments with some modulo... I also noticed the anti-diagonals hold constant value so was looking for a formula in x+y. – user4686 Nov 14 '17 at 18:55
  • 1
    If you add the two other 5x5 tables to your post I can enhance my answer with the formula for them. However as I said in my other comments, it is also perfectly fine to do by hand the 25 macro definitions and use these macros in place of a formula in numexpr. I can do that rather, to not spoil your discovery of a possible arithmetic formula for the two other 5x5 tables... – user4686 Nov 14 '17 at 18:59
  • 2
    besides 3(x+y) mod 5, the formulas 2(2x+y) mod 5 and -(3x+y) mod 5 generate idempotent Latin squares and the three are mutually orthogonal (because 3 and 2 are invertible modulo 5, and the various 2x2 matrices checking for linear dependency have determinants non zero mod 5. This means a couple (u,v) can be obtained only once by u=3(x+y), v=2(2x+y) which is orthogonality. Idempotence is reason for 2 in 2(2x+y), because 6x is same as x. There is also 2(x+2y) and -(x+3y). Perhaps your matrices are of this type. – user4686 Nov 14 '17 at 19:55
3

For the example that you have given there is no need for a \forloop. Rather, you can just use a simple macro like:

\newcommand\LatinSquare[5]{
  \[
    \begin{array}{c|ccccc}
      \circ_1&#1&#2&#3&#4&#5\\
      \hline
      #1&#1&#4&#2&#5&#3\\
      #2&#4&#2&#5&#3&#1\\
      #3&#2&#5&#3&#1&#4\\
      #4&#5&#3&#1&#4&#2\\
      #5&#3&#1&#4&#2&#5
    \end{array}
  \]
}

that you would use as

 \LatinSquare{1}{2}{3}{4}{21}

As expected, this produces:

enter image description here

I suspect that this is not really what you want, however, so perhaps you need to add more detail to your question!

Here's the full code:

\documentclass[12pt]{article}
\usepackage{fullpage}

\newcommand\LatinSquare[5]{
  \[
    \begin{array}{c|ccccc}
      \circ_1&#1&#2&#3&#4&#5\\
      \hline
      #1&#1&#4&#2&#5&#3\\
      #2&#4&#2&#5&#3&#1\\
      #3&#2&#5&#3&#1&#4\\
      #4&#5&#3&#1&#4&#2\\
      #5&#3&#1&#4&#2&#5
    \end{array}
  \]
}

\begin{document}

    \LatinSquare{1}{2}{3}{4}{21}

\end{document}
  • Thanks for the answer! That was way easier than I was thinking it would be (tex can be pretty amazing sometimes). That certainly takes care of the 63 latin squares of order 5. The larger question (3rd paragraph from the bottom) is how to get latex to read these smaller latin squares to create a larger latin square. What I imagine needs to happen is to have latex store these order 5 latin squares in memory, and then use the same macro as above to create an order 21 latin square. However, the multiplication isn't a generic formula, but is given by the operations in the smaller latin squares. – JohnC Nov 9 '17 at 6:13
  • @JohnC I’m sure it’s possible. I suggest asking another question where you give the details of the required operations. – Andrew Nov 9 '17 at 7:47

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.