Boolean Chains

Table of Contents

Home

1. Boolean Chains

1.1. Introduction

In section 7.1.2 The Art of Computer Programming Volume 4A Knuth describes and analyzes boolean chains, which are defined for functions of \(n\) variables \(x_1, x_2, ... x_n\) as a sequence of operations \(x_i = x_{j(i)} \circ_i x_{k(i)}\) for \(n+1 \leq i \leq n + r\), with \(1 \leq j(i) < i, 1 \leq k(i)\) and \(\circ_i\) being any binary operation. He shows that it is sufficient to consider the binary operations \(\land\), \(\lor\), \(\oplus\), \(<\) (bitwise), \(>\) (bitwise).

In Synthesizing a good chain he discusses finding short boolean chains for given target functions, using the example of a 7-segment display for hexadecimal digits; each segment is controlled by a boolean functions of the four inputs of a 4-bit hexadecimal digit.

1.2. Starting point

In order to find a reasonably short boolean chain Knuth describes Algorithm L and Algorithm U, an extension of Algorithm L, which tracks a footprint for each possible function. The footprint is a set of “first operations” that can be achieved with \(n\) input variables and that are part of the shortest chains generating a target function. This footprint can used as a heuristic to greedily pick the next operation. The resulting chain including the new operation can be used as an input for Algorithm U again, resulting in the next operation to pick, etc., until the chain contains all target functions.

This approach generates a boolean chain of length 22 for the 7-segment decimal digit display. Knuth also mentions that David Stevenson found a 21-step chain by picking \(x_{10}\) non-greedily.

I was interested in trying to find an even shorter chain for the display.

3. Results

3.1. Full search

  optimal unique unique chains chains generated computation progress capacity version
  length function sets     time      
10 digits 11 3 40 1,914,846 0.016 secs 100% MacBook Air 15" (M2, 2023) c1bef22e
11 digits 12 91 1,079 96,137,844 0.33 secs 100% MacBook Air 15" (M2, 2023) c1bef22e
12 digits 14 6 75 93,976,359,707 3.87 mins 100% MacBook Air 15" (M2, 2023) c1bef22e
13 digits 15 1 4 7,100,011,078,016 3.78 hours 100% MacBook Air 15" (M2, 2023) c1bef22e
14 digits 16 35 71 1,172,393,232,657,510 156 days 100% AWS ECS, 1 vCPU/job 4ab3460f
15 digits 17 1 1 30,968,277,080,052,517 3.93 years   AWS ECS, 1 vCPU/job 4ab3460f
        37,444,981,252,103,000 5.86 years 100% BOINC Central, various ba16ebb4
16 digits 18 0 0 2,567,815,524,926,566,380 450 years 100% BOINC Central, various ba16ebb4

Note: the runs of 14 digits and the first 10% of the 15 digits on AWS ECS use the version that didn’t yet stop the branch after finding a target function; that version generated about 70-80% more chains than the newer version.

Thanks to BOINC Central for providing computing capacity for this search!

More info on verification and confidence

For the 16 digit run I ran many batches via BOINC Central, each batch consisted of 1000 jobs, each job consisted of 10 chunks. After many years of processing I encountered some obviously corrupted results, which appear to have been caused by bit flips in memory, likely due to hardware failure or cosmic rays. I ignored files from those hosts, but it worried me that this could have happened with other jobs, without changing the result in a way that I would detect the corruption.

For that reason I re-ran a random sample of 3,556,138 chunks a second time to verify the results. That's ~26% of all the 13,695,883 chunks of the search space. I also made sure that I included at least one random chunk from every job. I found 19 chunks that differed from the first run. For those I verified the result with a third run, discarded all the results of the job the problematic cases were part of, and re-ran them.

Given those results I estimate a corruption chance of about 1 in 187,000 chunks. A missed solution would have to lie in one of the 70-100 corrupt chunks of 13.696 million total chunks. It would also have to be missed by the random verification sample of 3.556 million chunks, which verified at least one chunk of every 10-chunk jobs. The probability of this should be about 1 in 250,000. Therefore I'm confident, that there is no boolean chain of length 18 for this problem. The one of length 19 is optimal.

Note: The runtime in the table only includes the first valid run of every chunk. The verification took another ~131 years in total.

3.2. Hungry search

With bite sizes 15, 14, 13, 12, 11, 10, 2, 2, 2, 2, 2, 2, 1, …

  length chains found unique chains generated computation time capacity version
      function sets        
10 digits 12 1,155 483 220,311 4.58 secs MacBook Air 15" (M2, 2023) bdaa899d
11 digits 12 182 47 264,537 11.17 secs MacBook Air 15" (M2, 2023) bdaa899d
12 digits 14 4 3 4,072,870 13.72 mins MacBook Air 15" (M2, 2023) bdaa899d

With bite sizes 15, 15, 13, 13, 10, 10, 8, 8, 6, 6, 3, 3, 1, …

  length chains found unique chains generated computation time capacity version
      function sets        
16 digits 18 0 0 956,492,610 303 days AWS ECS, 1 vCPU/job 60b931e0

With bite sizes 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 2, 1, …

  length chains found unique chains generated computation time capacity version
      function sets        
15 digits 17 0 0 8,197,343 7 days AWS ECS, 1 vCPU/job a78bc24a
15 digits 18 493 48 11,202,690 23 hours AWS ECS, 1 vCPU/job 3a616650
16 digits 18 0 0 20,297,976 7 days AWS ECS, 1 vCPU/job 60af8743
16 digits 19 34 11 30,890,984 121 days AWS ECS, 1 vCPU/job 34a00bda

Note: the 15 digits search for length 18 is noticeably faster than the one for length 17, this is because the one for length 18 already employed the optimization of avoiding Algorithm U if the next step must be a target function. The same is true for the 16 digits search of length 18, its version was more efficient than the one for length 19.

With bite sizes 31, 31, 31, 11, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 2, 1.

  length chains found unique chains generated computation time progress capacity version
      function sets          
16 digits 18 0 0 39,660,805,920 20.54 years 100.0% BOINC Central, various ba16ebb4

No chains were found for those bite sizes. I think that’s a strong indicator that there are no solutions of length 18, because the first 4 bite sizes were pretty big and would’ve found all the optimal solutions for lower number of digits. Nonetheless this is no proof, I’m still trying to do an exhaustive search for 16 digits, see above.

3.3. Branching

I tracked some statistics on the number of new instructions encountered at different lengths and the number of chains generated. For the decimal display for 13 digits, searching to a maximal length of \(m=19\) the program looked at 15,586,512,093,540 chains, The exact number depends on the order in which instructions are generated, and the following table provides some statistics on the number of newly added instructions at every length.

The main takeaway is that the branching factor doesn’t grow much as the chains get longer, because so many instructions result in the same functions and we ignore different orders of the same set of functions. The table is slightly misleading, however, as the number of actual branches will be roughly the sum of these newly added instructions up to that length, e.g. at length 8 on average \(30+8+10+11+12 = 71\).

That the numbers go down again after length 12 is due to the algorithm stopping at a max length of 19 and bailing out once a chain has no hope of generating all 7 target functions by length 10 anymore (12 = 19 - 7 target functions). So fewer and fewer branches make it to those higher lengths.

c chains sum new instructions avg min max
4 1 30 30 30 30
5 30 252 8 2 10
6 687 6881 10 3 15
7 15349 170840 11 2 20
8 362425 4448336 12 1 25
9 9341932 127672810 13 1 30
10 266485149 4055025721 15 0 33
11 8442288161 141892395181 16 0 38
12 296360074644 5451011054514 18 0 43
13 67539256837 1281813235039 18 0 46
14 29625227652 564173170164 19 0 51
15 1038462604 23435424999 22 0 53
16 27930118 762860238 27 2 54
17 255268 7328660 28 5 51
18 1282 39984 31 16 45

4. Best chains

4.1. Seven-segment display for 10 digits

\begin{aligned} x_5 &= x_1 \lor x_2 & \quad x_9 &= x_5 < x_8 = \overline{f} & \quad x_{13} &= x_3 < x_{10} = \overline{a} & \\ x_6 &= x_3 \oplus x_5 & \quad x_{10} &= x_6 \oplus x_8 = \overline{d} & \quad x_{14} &= x_4 \lor x_{10} = \overline{e} & \\ x_7 &= x_2 < x_6 & \quad x_{11} &= x_4 < x_9 = \overline{c} & \quad x_{15} &= x_6 \lor x_{12} = g & \\ x_8 &= x_4 \lor x_7 & \quad x_{12} &= x_2 > x_{10} = \overline{b} & \\ \end{aligned}

10-digits-segments.svg

All 40 unique optimal chains of length 11: chains-10-15.txt

4.2. Seven-segment display for 11 digits

\begin{aligned} x_5 &= x_1 \lor x_2 & \quad x_9 &= x_3 \oplus x_7 & \quad x_{13} &= x_9 \oplus x_{10} = \overline{d} & \\ x_6 &= x_1 \oplus x_3 & \quad x_{10} &= x_5 < x_8 = \overline{f} & \quad x_{14} &= x_3 < x_{13} = \overline{a} & \\ x_7 &= x_2 > x_4 & \quad x_{11} &= x_2 > x_9 = \overline{b} & \quad x_{15} &= x_8 \oplus x_{13} = g & \\ x_8 &= x_4 \lor x_6 & \quad x_{12} &= x_4 < x_{10} = \overline{c} & \quad x_{16} &= x_4 \lor x_{14} = \overline{e} & \\ \end{aligned}

11-digits-segments.svg

All 1,079 unique optimal chains of length 12: chains-11-16.txt

4.3. Seven-segment display for 12 digits

\begin{aligned} x_5 &= x_1 \oplus x_3 & \quad x_{10} &= x_3 \oplus x_9 & \quad x_{15} &= x_7 \lor x_{13} = g & \\ x_6 &= x_3 \oplus x_4 & \quad x_{11} &= x_5 < x_{10} = \overline{a} & \quad x_{16} &= x_9 < x_{13} = \overline{b} & \\ x_7 &= x_2 < x_5 & \quad x_{12} &= x_6 \lor x_{11} & \quad x_{17} &= x_{10} > x_{13} = \overline{f} & \\ x_8 &= x_6 > x_7 & \quad x_{13} &= x_8 \oplus x_{11} & \quad x_{18} &= x_4 < x_{17} = \overline{c} & \\ x_9 &= x_2 \oplus x_8 = \overline{d} & \quad x_{14} &= x_3 \oplus x_{12} = \overline{e} & \\ \end{aligned}

12-digits-segments.svg

All 75 unique optimal chains of length 14: chains-12-18.txt

4.4. Seven-segment display for 13 digits

\begin{aligned} x_5 &= x_2 \oplus x_3 & \quad x_{10} &= x_5 \lor x_9 = g & \quad x_{15} &= x_6 \land x_{14} = \overline{a} & \\ x_6 &= x_2 \oplus x_4 & \quad x_{11} &= x_7 > x_9 = \overline{f} & \quad x_{16} &= x_9 \land x_{15} & \\ x_7 &= x_5 \lor x_6 & \quad x_{12} &= x_4 < x_{11} = \overline{c} & \quad x_{17} &= x_4 \oplus x_{16} = \overline{e} & \\ x_8 &= x_2 \land x_7 & \quad x_{13} &= x_8 \lor x_{11} & \quad x_{18} &= x_8 \oplus x_{16} = \overline{b} & \\ x_9 &= x_1 \oplus x_8 & \quad x_{14} &= x_3 \oplus x_{13} & \quad x_{19} &= x_{14} > x_{18} = \overline{d} & \\ \end{aligned}

13-digits-segments.svg

All 4 unique optimal chains of length 15: chains-13-19.txt

4.5. Seven-segment display for 14 digits

\begin{aligned} x_5 &= x_1 \oplus x_2 & \quad x_{11} &= x_5 < x_9 = \overline{f} & \quad x_{17} &= x_{13} < x_{14} = \overline{d} & \\ x_6 &= x_1 \oplus x_4 & \quad x_{12} &= x_8 \oplus x_9 = \overline{a} & \quad x_{18} &= x_5 < x_{15} = \overline{c} & \\ x_7 &= x_3 \oplus x_4 & \quad x_{13} &= x_2 \oplus x_{10} & \quad x_{19} &= x_{13} \land x_{15} = \overline{b} & \\ x_8 &= x_3 \lor x_5 & \quad x_{14} &= x_6 \lor x_{12} & \quad x_{20} &= x_{13} \lor x_{15} = g & \\ x_9 &= x_6 \lor x_7 & \quad x_{15} &= x_7 \oplus x_{12} & \\ x_{10} &= x_7 < x_8 & \quad x_{16} &= x_1 \oplus x_{14} = \overline{e} & \\ \end{aligned}

This chain almost solves the 15 or even 16 digit case, with the top-left segment missing from the E and the top segment of the F slipped to the top-right. So close!

14-digits-segments.svg

All 71 unique optimal chains of length 16: chains-14-20.txt

4.6. Seven-segment display for 15 digits

\begin{aligned} x_5 &= x_2 \land x_3 & \quad x_{12} &= x_7 < x_{10} = \overline{d} & \quad x_{19} &= x_8 \lor x_{16} & \\ x_6 &= x_1 \lor x_5 & \quad x_{13} &= x_2 \oplus x_{11} & \quad x_{20} &= x_6 \oplus x_{19} = \overline{e} & \\ x_7 &= x_3 \oplus x_6 & \quad x_{14} &= x_{11} \oplus x_{12} = g & \quad x_{21} &= x_{10} < x_{19} = \overline{b} & \\ x_8 &= x_4 \oplus x_6 & \quad x_{15} &= x_1 \oplus x_{13} & \\ x_9 &= x_4 \lor x_7 & \quad x_{16} &= x_7 \oplus x_{13} = \overline{a} & \\ x_{10} &= x_2 \oplus x_8 & \quad x_{17} &= x_9 \land x_{15} = \overline{f} & \\ x_{11} &= x_5 \lor x_9 & \quad x_{18} &= x_{10} < x_{15} = \overline{c} & \\ \end{aligned}

15-digits-segments.svg

1 unique optimal set of functions of length 17: chains-15-21.txt

428 unique chains of length 18 that the hungry search found: chains-15-22.txt.

4.7. Seven-segment display for 16 digits

A chain of length 19 found by the hungry search:

\begin{aligned} x_5 &= x_3 < x_4 & \quad x_{12} &= x_1 \lor x_{11} & \quad x_{19} &= x_8 > x_{18} = \overline{a} & \\ x_6 &= x_3 \oplus x_4 & \quad x_{13} &= x_7 \lor x_{12} = g & \quad x_{20} &= x_4 \oplus x_{14} & \\ x_7 &= x_2 \oplus x_3 & \quad x_{14} &= x_7 > x_{11} & \quad x_{21} &= x_{16} < x_{20} = \overline{e} & \\ x_8 &= x_5 \lor x_7 & \quad x_{15} &= x_2 \oplus x_{14} & \quad x_{22} &= x_{19} \oplus x_{20} & \\ x_9 &= x_1 \oplus x_2 & \quad x_{16} &= x_9 < x_{15} = \overline{c} & \quad x_{23} &= x_8 \oplus x_{22} = \overline{d} & \\ x_{10} &= x_8 > x_9 = \overline{f} & \quad x_{17} &= x_{12} \land x_{15} = \overline{b} & \\ x_{11} &= x_6 \oplus x_{10} & \quad x_{18} &= x_{11} \oplus x_{16} & \\ \end{aligned}

11 unique chains of length 19 that the hungry search found: chains-16-23.txt, not exhaustive. The exhaustive search for a chain of length 18 proves these chain lengths are optimal.

16-digits-segments.svg

4.8. Exercise 7.1.2-54

Total chains generated: 934,236,665,700

Number of unique optimal sets of functions: 1270

The minimal length is 13, one step shorter than the solution known in the book.

Here is the first one found:

\begin{aligned} x_5 &= x_1 \land x_2 & \quad x_{10} &= x_4 > x_7 & \quad x_{15} &= x_7 \land x_{11} = f_1 & \\ x_6 &= x_1 \oplus x_3 & \quad x_{11} &= x_6 \oplus x_8 & \quad x_{16} &= x_9 > x_{13} = f_3 & \\ x_7 &= x_2 \oplus x_3 & \quad x_{12} &= x_5 \land x_9 = f_5 & \quad x_{17} &= x_4 \land x_{15} = f_6 & \\ x_8 &= x_4 \lor x_5 & \quad x_{13} &= x_1 \land x_{10} = f_4 & \\ x_9 &= x_4 \land x_6 & \quad x_{14} &= x_6 < x_{10} = f_2 & \\ \end{aligned}

4.9. Exercise 7.1.2-59

Hungry search found chains of length 15, two steps shorter than the one in the book, but no guarantees that it is minimal.

Here is the first one found:

\begin{aligned} x_5 &= x_2 \oplus x_4 & \quad x_{10} &= x_6 < x_9 & \quad x_{15} &= x_1 > x_{14} & \\ x_6 &= x_2 \oplus x_3 & \quad x_{11} &= x_7 \oplus x_{10} = f_3 & \quad x_{16} &= x_6 > x_{15} & \\ x_7 &= x_1 \oplus x_5 & \quad x_{12} &= x_3 \land x_7 & \quad x_{17} &= x_{12} \lor x_{16} = f_4 & \\ x_8 &= x_4 < x_7 & \quad x_{13} &= x_5 \lor x_{12} & \quad x_{18} &= x_{12} \oplus x_{16} & \\ x_9 &= x_3 \oplus x_8 & \quad x_{14} &= x_9 \oplus x_{13} = f_2 & \quad x_{19} &= x_9 \oplus x_{18} = f_1 & \\ \end{aligned}

5. Conclusion

The minimal length of Boolean chains for the 7-segment display of hexadecimal digits is 19, as found by the Hungry Search in approximately 121 computing days. An exhaustive search subsequently confirmed that no chains of length 18 exist; this computation required roughly 450 computing years.

6. Source code

The code can be found on GitHub: https://github.com/or/boolean-chains

Date: 2025-03-01 Sat 00:00

Author: Oliver Runge

Created: 2026-03-09 Mon 20:29