Books · Solving Puzzles through Mathematical Programming
Chapter 46
The Four Strongest
In the National Museum of Mongolia sits a wooden puzzle of four carved animals, the dragon, the tiger, the lion, and the garuda, the four mythological guardians known as the Four Strongest. Each carving must be laid flat in a shallow box, and the box is only just large enough: the four fit along it in one arrangement and refuse to fit in almost every other. A player may slide a carving in either of two ways, call them up and down, a half turn apart, and may place the four in any order along the box. The question is the order and the turns that pack them into the least length.
With four animals and two turns each, the arrangements number , and since reversing a row and turning every animal over gives the mirror image of the same packing, the distinct arrangements number . The puzzle’s own author settled it the hard way, by laying out all and measuring each. An integer program does better, and the saving is not in the search but in the measuring.
A length built from pairs
The length of a row is awkward to measure: there are rows. But the length of a row of touching shapes is almost decided by its neighbours. When two carvings sit side by side they nest, the bumps of one settling into the hollows of the other, and how far they nest depends only on the two of them and their turns, not on what else is in the box. So write for the length of a single carving in orientation , and for the length of the touching pair then . A row of three, , is the first pair laid against the second, and the two overlap exactly along the middle carving , which the inclusion-exclusion principle says to add once and subtract once: The pattern continues. The length of the whole row is the sum of the adjacent-pair lengths, with each interior carving’s own length subtracted back out: This is exact when the carvings nest along a line, and a close approximation for real two-dimensional shapes, which is the setting the puzzle’s author worked in.
The point of the formula is the measuring it saves. Every row’s length is now known once the single lengths and the pair lengths are known, and those are few: the singles number , and the ordered pairs of two different carvings, each in either turn, number . Fifty-six measurements in place of , and the gap widens fast: the arrangements grow faster than any polynomial in the number of carvings, while the measurements grow only as its square.
The model
With the lengths in hand the puzzle is an assignment. Number the positions along the box to .
Variables
For each carving , turn , and position , a binary variable takes the value exactly when carving lies at position in turn .
Constraints and objective
Each position holds exactly one carving in one turn, and each carving is placed exactly once: The length is a sum over adjacent positions, and a product records when carving in turn sits just left of carving in turn . A product of two binaries is linearised in the standard way by a fresh binary pinned to their conjunction, so that exactly when both placements are made. The objective sums the pair lengths over adjacent positions and subtracts the interior single lengths, the inclusion-exclusion total, and is minimised:
A solver
The instance below is a self-contained stand-in for the museum’s carvings, whose true measurements are not public. Each carving in each turn is given a left reach and a right reach; its own length is their sum, and two neighbours nest by the smaller of the touching reaches, so .
from ortools.sat.python import cp_model
TOYS = ["D", "T", "L", "G"] # Dragon, Tiger, Lion, Garuda
ORI = ["up", "dn"]
REACH = { # (left reach, right reach)
("D", "up"): (3, 4), ("D", "dn"): (5, 5),
("T", "up"): (4, 5), ("T", "dn"): (2, 5),
("L", "up"): (2, 5), ("L", "dn"): (5, 1),
("G", "up"): (4, 2), ("G", "dn"): (5, 1),
}
B = {k: h + t for k, (h, t) in REACH.items()} # own length
def OV(a, c): return min(REACH[a][1], REACH[c][0])
def D(a, c): return B[a] + B[c] - OV(a, c) # pair length
def shortest_row():
I, J, K = TOYS, ORI, range(len(TOYS))
m = cp_model.CpModel()
x = {(i, j, k): m.NewBoolVar("")
for i in I for j in J for k in K}
for k in K: # one (toy, turn) per spot
m.Add(sum(x[i, j, k] for i in I for j in J) == 1)
for i in I: # each toy placed once
m.Add(sum(x[i, j, k] for j in J for k in K) == 1)
pairs = [(i, j, p, q) for i in I for j in J
for p in I for q in J if p != i]
cost = []
for k in list(K)[:-1]: # add adjacent-pair lengths
for (i, j, p, q) in pairs:
y = m.NewBoolVar("")
m.Add(y <= x[i, j, k])
m.Add(y <= x[p, q, k + 1])
m.Add(y >= x[i, j, k] + x[p, q, k + 1] - 1)
cost.append(D((i, j), (p, q)) * y)
for k in K: # subtract interior singles
if 0 < k < len(TOYS) - 1:
for i in I:
for j in J:
cost.append(-B[(i, j)] * x[i, j, k])
m.Minimize(sum(cost))
s = cp_model.CpSolver()
s.Solve(m)
row = [None] * len(TOYS)
for (i, j, k), v in x.items():
if s.Value(v):
row[k] = (i, j)
return int(s.ObjectiveValue()), row
On this instance the shortest row has length , the dragon and tiger upright leading the lion and garuda turned over: , , , . It is the only shortest row up to the mirror symmetry, as a sweep of all arrangements confirms, and the integer program finds it directly without enumerating them.
The museum puzzle itself, with the carvings’ real proportions recovered from photographs, packs shortest as tiger, dragon, lion, garuda in turns up, up, up, down, a published length of about centimetres; the hand-found arrangement the puzzle is usually solved by, dragon, lion, tiger, garuda turned down, up, down, up, measures about under the same data. Those numbers rest on measurements taken off photographs of carvings in a glass case, so the chapter does not reproduce them; what carries across exactly is the shape of the argument, a length read off pairs and a placement read off an assignment.
Sources. The Four Strongest is a puzzle in the collection of the National Museum of Mongolia, described and solved by exhaustive hand arrangement by Uuganbaatar Ninjbat, “The Four Strongest” at the National Museum of Mongolia, The Mathematical Intelligencer volume , number (), pages –, who counts the candidate arrangements; the puzzle also appears as the “Four Dignities.” The integer-programming treatment, the inclusion-exclusion length and the -measurement count, the assignment model with linearised adjacencies, and the and centimetre figures are due to Bismark Singh, Puzzle—A Mathematical Programming Approach for Mongolia’s “The Four Strongest” Puzzle, INFORMS Transactions on Education volume , number (), pages –, who works from photograph-derived measurements and a rectangular approximation of the museum’s hexagonal box. The standard linearisation of a product of binaries by a single conjunction variable is the McCormick envelope, after Garth P. McCormick, Computability of Global Solutions to Factorable Nonconvex Programs, Mathematical Programming volume (), pages –. The illustrative instance and its unique shortest row are produced and cross-checked by the model above against a full sweep of the arrangements.