(It's assumed that the reader is familiar with random walk, Latin squares and transversals.)
Extremal LS (Latin Square) is the one that has minimally/maximally known transversals (lower/upper bounds).
Here I'm going to describe how I found L15 with TS=170369 and added it to OEIS A091323. To my knowledge, this is a best lower bound for L15 as of autumn 2025.
For random walk, we simply modify a cell (or symbol) in LS and ask MaxSAT solver to fix other cells so that LS will become valid (all LS constaints for rows/columns would be valid). Modified cell clauses are added as hard clauses (MUST be satisfied), and all other clauses are added as soft (it would be GOOD to satisfy as many clauses as possible).
In plan English, we modify a random cell/symbol and ask MaxSAT solver to find minimum cells to be flipped/modified so that LS become valid.
I'll call this procedure 'LS repair'.
As of L15, 4-11 cells must be modified to 'repair' it.
For example, here we repair L15 by modifying 4 cells after setting cell at row=3 column=11 to 3 (marked with asterisk):
set row/col to i 3 11 3 original_sq: 0 1 2 3 4 5 6 7 8 9 a b c d e 1 2 0 7 5 8 3 6 4 d b e 9 c a 2 5 4 0 8 a 1 3 b 7 e d 6 9 c 3 0 1 6 2 4 7 9 5 c 8 a d e b 4 8 5 2 b e 0 1 a 6 c 9 3 7 d 5 4 8 1 a b 2 0 e 3 d c 7 6 9 6 7 3 c 1 0 9 d 2 b 5 4 e a 8 7 3 6 9 0 2 d c 1 e 4 8 a b 5 8 b a 5 e c 4 2 d 0 9 7 1 3 6 9 6 7 d 3 1 c e 0 a 2 5 b 8 4 a e b 4 d 9 8 5 c 2 6 3 0 1 7 b a e 8 c d 5 4 9 1 7 6 2 0 3 c d 9 a 7 6 e b 3 4 1 0 8 5 2 d 9 c e 6 3 b a 7 8 0 2 5 4 1 e c d b 9 7 a 8 6 5 3 1 4 2 0 diff: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a . . . . . . . . . . 3*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mutate() all_diffs 4 transv_cnt=00916445 short=0123456789abcde120758364dbe9ca25408a13b7ed69ca01624795c83deb4852be01a6c937d5481ab20e3dc769673c109d2b54ea8736902dc1e48ab58ba5ec42d097136967d31ce0a25b843eb4d985c26a017bae8cd549176203cd9a76eb3410852d9ce63ba7802541ecdb97a86531420
Sometimes, 11 cells are to be modified.
For example, here we repair L15 by modifying 11 cells after setting cell at row=0 column=4 to 8 (marked with asterisk):
init sq: 0123456789abcde120758364dbe9ca25408a13b7ed69c301624795c8adeb4852be01a6c937d5481ab20e3dc769673c109d2a54eb8736902dc1e48ba58ba5ec42d096137967d31ce0b25a84aeb4d985c267013bae8cd549173206cd9a76eb3410852d9ce63ba7802541ecdb97a86531420 transv cnt 174941 ... original_sq: 0 1 2 3 4 5 6 7 8 9 a b c d e 1 2 0 7 5 8 3 6 4 d b e 9 c a 2 5 4 0 8 a 1 3 b 7 e d 6 9 c 3 0 1 6 2 4 7 9 5 c 8 a d e b 4 8 5 2 b e 0 1 a 6 c 9 3 7 d 5 4 8 1 a b 2 0 e 3 d c 7 6 9 6 7 3 c 1 0 9 d 2 a 5 4 e b 8 7 3 6 9 0 2 d c 1 e 4 8 b a 5 8 b a 5 e c 4 2 d 0 9 6 1 3 7 9 6 7 d 3 1 c e 0 b 2 5 a 8 4 a e b 4 d 9 8 5 c 2 6 7 0 1 3 b a e 8 c d 5 4 9 1 7 3 2 0 6 c d 9 a 7 6 e b 3 4 1 0 8 5 2 d 9 c e 6 3 b a 7 8 0 2 5 4 1 e c d b 9 7 a 8 6 5 3 1 4 2 0 diff: . . 4 . 8*. . . 2 . . . . . . . . . . . . . . . . . . . . . c . 2 . 4 . . . . . . . . . 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 . . . . . 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 . . . . . . . . . . . . . c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mutate() all_diffs 11 transv_cnt=01096177 short=0143856729abcde120758364dbe9cac5204a13b7ed698301624795c8adeb4852be01a6c937d5481ab20e3dc769673c109d8a54eb2736902dc1e48ba58ba5ec42d096137967d31ce0b25a84aeb4d985c267013bae8cd5491732062d9a76eb341085cd9ce63ba7802541ecdb97a86531420
Now the statistics.
Most LS's can be repaired with modification of 7 cells. Number of LS's 'repaired' and how many cells we had to 'fix':
1633483 mutate() all_diffs 4
2668510 mutate() all_diffs 6
3213221 mutate() all_diffs 7
2098325 mutate() all_diffs 8
707907 mutate() all_diffs 9
14225 mutate() all_diffs 10
132 mutate() all_diffs 11
Now finding extremal LS is just random walk with that 'LS repair' procedure.
Here is a part of log file, where L15 with TS=171579 was mutated by setting 7 at row=8 and column=14 and 'repairing' other cells:
init sq: 0123456789abcde120758364dbe9ca25408a13b7ed69c301624795c8adeb4852be01a6c937d5481ab20e3dc769673c109d2b54ea8736902dc1e48ab58ba5ec42d097136967d31ce0a25b84aeb4d985c263017bae8cd549176203cd9a76eb3410852d9ce63ba7802541ecdb97a86531420 transv cnt 171579 ... set row/col to i 8 14 7 original_sq: 0 1 2 3 4 5 6 7 8 9 a b c d e 1 2 0 7 5 8 3 6 4 d b e 9 c a 2 5 4 0 8 a 1 3 b 7 e d 6 9 c 3 0 1 6 2 4 7 9 5 c 8 a d e b 4 8 5 2 b e 0 1 a 6 c 9 3 7 d 5 4 8 1 a b 2 0 e 3 d c 7 6 9 6 7 3 c 1 0 9 d 2 b 5 4 e a 8 7 3 6 9 0 2 d c 1 e 4 8 a b 5 8 b a 5 e c 4 2 d 0 9 7 1 3 6 9 6 7 d 3 1 c e 0 a 2 5 b 8 4 a e b 4 d 9 8 5 c 2 6 3 0 1 7 b a e 8 c d 5 4 9 1 7 6 2 0 3 c d 9 a 7 6 e b 3 4 1 0 8 5 2 d 9 c e 6 3 b a 7 8 0 2 5 4 1 e c d b 9 7 a 8 6 5 3 1 4 2 0 diff: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 . . 7* . . . . . . . . . . . . . . . . . . . . . . . . . 7 . . . 6 . . . . . . . . . . 6 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mutate() all_diffs 6 transv_cnt=00170369 short=0123456789abcde120758364dbe9ca25408a13b7ed69c301624795c8adeb4852be01a6c937d5481ab20e3dc769673c109d2b54ea8736902dc1e48ab58ba5ec42d096137967d31ce0a25b84aeb4d985c273016bae8cd549167203cd9a76eb3410852d9ce63ba7802541ecdb97a86531420
'Mutated' LS has TS=170369.
Using such random walk, it's easy to find extremal LS up to L15, and maybe more, but my transversals counting function is getting very slow :-( I have to fix it somehow.
MaxSAT solver I used is UWrMaxSat by Marek Piotrów et al. I used it because it has IPAMIR interface (in other words, it can be loaded as .so module and be a bit faster).
I recorded a fancy video of the process.
