$title The Orthogonal Latin-Square Problem (LATIN,SEQ=159)
$onText
A latin square is an arrangement of objects such that no object
is repeated in a row or column. Two latin squares are orthogonal
if all entries are different. For example,
one two
1 3 2 2 1 3
3 2 1 1 3 2
2 1 3 3 2 1
The case of n = 10 has historical interest and was only settled in 1952.
The original formulation is not correct. A new formulation
is presented which generates a correct solution. Also note that the
solution time is very sensitive to formulation details and depends on
the kind of algorithm used.
The size of the square can easily by changed by editing the lines
containing the definitions of the rows, columns and values in the.
set definition below. This kind of assignment problem can be very
difficult to solve for general purpose MIP codes.
Dantzig, G B, Chapter 26.3. In Linear Programming and Extensions.
Princeton University Press, Princeton, New Jersey, 1963.
Keywords: mixed integer linaer programming, latin square, mathematics
$offText
$eolCom //
$if not set SIZE $set SIZE 4 // set --SIZE=n on GAMS command line to new size n
Set
k 'rows' / row1*row%SIZE% /
l 'columns' / col1*col%SIZE% /
v 'values' / val1*val%SIZE% /;
Alias (i,j,v);
$onText ORIGINAL FORMULATION
Note that the squares use k,l for row and column indexes. The first
index position (i) is for the values of square one and the second
index position (j) is for square two. For example, the cell 2,3
in the latin square shown above would be defined by the value of
one for the following index values:
x.fx('val1','val2','row2',col3') = 1;
The original formulation is not correct. For example, you can pick
any cell (k,l) and pick and make the cell values equal and the
model will find a feasible solution. For example, you could set:
x.fx('val1','val1','row1','col1') = 1;
and get a feasible solution. Both the original and a new formulation
are given.
$offText
Variable
x(i,j,k,l) 'pairs (i,j) allocated to cell(k,l)'
z 'some objective';
Binary Variable x;
Equation
c1(i,j) 'for each cell pick only one item pair'
c2(k,l) 'an item pair can show up only once'
c3(i,l) 'items have to be unique in each column for square one'
c4(j,l) 'items have to be unique in each column for square two'
c5(i,k) 'items have to be unique in each row for square one'
c6(j,k) 'items have to be unique in each row for square two'
obj 'some objective function';
c1(i,j).. sum((k,l), x(i,j,k,l)) =e= 1;
c2(k,l).. sum((i,j), x(i,j,k,l)) =e= 1;
c3(i,l).. sum((j,k), x(i,j,k,l)) =e= 1;
c4(j,l).. sum((i,k), x(i,j,k,l)) =e= 1;
c5(i,k).. sum((j,l), x(i,j,k,l)) =e= 1;
c6(j,k).. sum((i,l), x(i,j,k,l)) =e= 1;
obj.. z =e= sum((i,j,k,l), x(i,j,k,l));
Model latin / all /;
Parameter report(*,k,l);
option report:0:1:1;
$onText skip over old model
* force an incorrect solution
x.fx('val1','val1','row1','col1') = 1;
solve latin minimizing z using mip;
loop((i,j,k,l)$x.l(i,j,k,l),
report('one',k,l) = ord(i);
report('two',k,l) = ord(j);
);
display report;
$offText
* New Formulation
Set s 'square' / one, two /;
Variable
y(s,v,k,l) 'square s has value v in cell(k,l)'
dev(v,k,l) 'deviation from correct formulation'
w 'some objective';
Binary Variable y;
Equation
n2(s,k,l) 'exactly one value for each cell'
n3(s,v,l) 'columns entries have to be unique'
n5(s,v,k) 'row entries have to be unique'
n6(v,k,l) 'entries in squares have to be different'
nobj 'definition of objective - anything';
n2(s,k,l).. sum(v, y(s,v,k,l)) =e= 1;
n3(s,v,l).. sum(k, y(s,v,k,l)) =e= 1;
n5(s,v,k).. sum(l, y(s,v,k,l)) =e= 1;
n6(v,k,l).. sum(s, y(s,v,k,l)) =l= 1;
nobj.. w =e= sum((s,v,k,l), y(s,v,k,l));
Model newlatin / nobj, n2, n3, n5, n6 /;
* position the solution
y.fx('one','val1','row1','col1') = 1;
solve newlatin min w using mip;
loop((s,v,k,l)$y.l(s,v,k,l),
report(s,k,l) = ord(v);
report(s,k,l) = ord(v);
);
display report;