SAT-based Circuit Local Improvement
SSAT-based Circuit Local Improvement
Alexander S. Kulikov ! ˇ Steklov Mathematical Institute at St. Petersburg, Russian Academy of SciencesSt. Petersburg State University
Nikita Slezkin ! St. Petersburg State University
Abstract
Finding exact circuit size is a notorious optimization problem in practice. Whereas modern computersand algorithmic techniques allow to find a circuit of size seven in blink of an eye, it may take morethan a week to search for a circuit of size thirteen. One of the reasons of this behavior is that thesearch space is enormous: the number of circuits of size s is s Θ( s ) , the number of Boolean functionson n variables is 2 n .In this paper, we explore the following natural heuristic idea for decreasing the size of a givencircuit: go through all its subcircuits of moderate size and check whether any of them can beimproved by reducing to SAT. This may be viewed as a local search approach: we search for a smallercircuit in a ball around a given circuit. We report the results of experiments with various symmetricfunctions. Theory of computation → Circuit complexity
Keywords and phrases circuits, algorithms, complexity theory, SAT, SAT-solvers, heuristics
Supplementary Material
Source code: repository : GitHub
Funding
Alexander S. Kulikov : Supported by Russian Science Foundation (18-71-10042).
A Boolean straight line program of size r for input variables ( x , . . . , x n ) is a sequenceof r instructions where each instruction g ← h ◦ k applies a binary Boolean operation ◦ totwo operands h, k each of which is either an input bit or the result of a previous instruction.If m instructions are designated as outputs, the straight line program computes a function { , } n → { , } m in a natural way. We denote the set of all such functions by B n,m andwe let B n = B n, . For a Boolean function f : { , } n → { , } m , by size( f ) we denote theminimum size of a straight line program computing f . A Boolean circuit shows a flow graphof a program.Figure 1 gives an example for the SUM n : { , } n → { , } l function that computes thebinary representation of the sum of n bits:SUM n ( x , . . . , x n ) = ( w , w , . . . , w l − ) : n X i =1 x i = l − X i =0 i w i , where l = ⌈ log ( n + 1) ⌉ . This function transforms n bits of weight 0 into l bits of weights (0 , , . . . , l − Python programming language. This makes particularly easyto verify their correctness. For example, the program for SUM can be verified with justthree lines of code: from itertools import product for x1, x2, x3 in product(range(2), repeat=3): a r X i v : . [ c s . A I] F e b SAT-based Circuit Local Improvement def sum2(x1, x2):w0 = x1 ^ x2w1 = x1 * x2 return w0, w1 x x ∧ w ⊕ w def sum3(x1, x2, x3):a = x1 ^ x2b = x2 ^ x3c = a | bw0 = a ^ x3w1 = c ^ w0 return w0, w1 x x x ⊕ a ⊕ b ∨ c ⊕ w ⊕ w Figure 1
Optimal size straight line programs and circuits for SUM and SUM . These twocircuits are known as half adder and full adder . w0, w1 = sum3(x1, x2, x3) assert x1 + x2 + x3 == w0 + 2 * w1 Determining size( f ) requires proving lower bounds: to show that size( f ) > α , one needsto prove that every circuit of size at most α does not compute f . Known lower bounds arefar from being satisfactory: the strongest known lower bound for a function family in NPis (3 + 1 / n − o ( n ) [7]. Here, by a function family we mean an infinite sequence of functions { f n } ∞ n =1 where f n ∈ B n .Even proving lower bounds for specific functions (rather than function families) is difficult.Brute force approaches become impractical quickly: | B n | = 2 n , hence already for n = 6,one cannot just enumerate all functions from B n ; also, the number of circuits of size s is s Θ( s ) , hence checking all circuits of size s takes reasonable time for small values of s only.Knuth [9] found the exact circuit size of all functions from B and B .Finding the exact value of size( f ) for f ∈ B is already a difficult computational task formodern computers and techniques. One approach is to translate a statement “there existsa circuit of size s computing f ” to a Boolean formula and to pass it to a SAT-solver. Then,if the formula is satisfiable, one decodes a circuit from its satisfying assignment; otherwise,one gets a (computer generated) proof of a lower bound size( f ) > s . This circuit synthesisapproach was proposed by Kojevnikov et al. [11] and, since then, has been used in variouscircuit synthesis programs ( abc [1], mockturtle [18], sat-chains [8]).The state-of-the-art SAT-solvers are surprisingly efficient and allow to handle variouspractically important problems (with millions of variables) and even help to resolve openproblems [3]. Still, already for small values of n and s the problem of finding a circuitof size s for a function from B n is difficult for SAT-solvers. We demonstrate the limits of thisapproach on counting functions:MOD m,rn = [ x + · · · + x n ≡ r mod m ](here, [ · ] is the Iverson bracket: [ S ] is equal to 1 if S is true and is equal to 0 otherwise).Using SAT-solvers, Knuth [10, solution to exercise 480] found size(MOD ,rn ) for all 3 ≤ n ≤ ≤ r ≤
2. Based on the found numbers, he made the following conjecture:size(MOD ,rn ) = 3 n − − [( n + r ) ≡ r mod 3] for all n ≥ r . (1)He was also able to find the circuit size for the n = 6 , r = 0 case and wrote: “The case n = 6and r ̸ = 0, which lies tantalizingly close to the limits of today’s solvers, is still unknown.” . S. Kulikov and N. Slezkin 3 To summarize, our current abilities for checking whether there exists a Boolean circuitof size s are roughly the following:for s ≤
6, this can be done in a few seconds;for 7 ≤ s ≤
12, this can (sometimes) be done in a few days;for s ≥
13, this is out of reach.In this paper, we explore the limits of the following natural idea: given a circuit, tryto improve its size by improving (using SAT-solvers, for example) the size of its subcircuitof size seven. This is a kind of a local search approach: we have no possibility to go throughthe whole space of all circuits, but we can at least search in a neighborhood of a given circuit.This allows us to work with circuits consisting of many gates.As the results of experiments, we show several circuits for which the approach describedabove leads to improved upper bounds. In particular, we support Knuth’s conjecture (1)by proving the matching upper bound. Also, we present improvements for size(SUM n ) forvarious small n . Finally, we provide examples of circuits that are optimal locally, but notglobally: our program is not able to find a (known) smaller circuit since it is “too different”from the original circuit. The program is implemented in
Python . We give a high-level overview of its main featuresbelow. All the code shown below can be found in the file tutorial.py at [4]. One may run itafter installing a few
Python modules. Alternatively, one may run the Jupyter notebook tutorial.ipynb in the cloud without installing anything. To do this, press the badge “Colab”at [4].
This is done through the
Circuit class. One can load and save circuits as well as printand draw them. A nicely looking layout of a circuit is produced by the pygraphviz module[16]. The program also contains some built-in circuits that can be used as building blocks.The following sample code constructs a circuit for SUM out of two full adders and onehalf adder. This construction is shown in Figure 2(a). Then, the circuit is verified via the check_sum_circuit method. Finally, the circuit is drawn. As a result, one gets a picturesimilar to the one in Figure 2(b). circuit = Circuit(input_labels=['x1', 'x2', 'x3', 'x4', 'x5'])x1, x2, x3, x4, x5 = circuit.input_labelsa0, a1 = add_sum3(circuit, [x1, x2, x3])b0, b1 = add_sum3(circuit, [a0, x4, x5])w1, w2 = add_sum2(circuit, [a1, b1])circuit.outputs = [b0, w1, w2]check_sum_circuit(circuit)circuit.draw('sum5') The class
CircuitFinder allows to check whether there exists a circuit of the required sizefor a given Boolean function. For example, one may discover the full adder as follows. (The
SAT-based Circuit Local Improvement x x x x x SUM SUM w w w x x x x x ⊕ g ⊕ g ∨ g ⊕ g ⊕ g ⊕ g ⊕ g ∨ g ⊕ w ⊕ g ⊕ w ∧ w x x x x x ⊕ g ⊕ g ∨ g ⊕ g ⊕ g ⊕ g ⊕ g > g ⊕ w ⊕ w > w (a) (b) (c) Figure 2 (a) A schematic circuit for SUM composed out of two full adders and one half adder.(b) The corresponding circuit of size 12. (c) An improved circuit of size 11. function sum_n returns the list of ⌈ log ( n + 1) ⌉ bits of the binary representation of the sumof n bits.) def sum_n(x): return [(sum(x) >> i) & 1 for i in range(ceil(log2(len(x) + 1)))]circuit_finder = CircuitFinder(dimension=3, number_of_gates=5,function=sum_n)circuit = circuit_finder.solve_cnf_formula()circuit.draw('sum3') This is done by encoding the task as a CNF formula and invoking the PicoSAT solver [2](via the pycosat module [15]). The reduction to SAT is described in [11].As mentioned in the introduction, the limits of applicability of this approach (for findinga circuit of size s ) are roughly the following: for s ≤
6, it usually works in less than a minute;for 7 ≤ s ≤
12, it may already take up to several hours or days; for s ≥
13, it becomes almostimpractical. The running time may vary a lot for inputs of the same length. In particular, itusually takes much longer to prove that the required circuit does not exist (by proving thatthe corresponding formula is unsatisfiable).The program allows to predefine some of the gates and wires of a circuit. We demonstratethis functionality later in the text.
The method improve_circuit goes through all subcircuits of a given size of a given circuitand checks whether any of them can be replaced by a smaller subcircuit (computing the . S. Kulikov and N. Slezkin 5 same function) via find_circuit . For example, applying this method to the circuit fromFigure 2(b) gives the circuit from Figure 2(c) in nine seconds. circuit = Circuit(input_labels=[f'x { i } ' for i in range(1, 6)], gates={})circuit.outputs = add_sum5_suboptimal(circuit, circuit.input_labels)improved_circuit = improve_circuit(circuit, subcircuit_size=5,connected= True )print(improved_circuit)improved_circuit.draw('sum5')
This circuit can be also found via find_circuit directly, but it takes about seven hours.
In this section, we report the results of experiments with various symmetric functions.A function f ( x , . . . , x n ) is called symmetric if its value depends on P ni =1 x i only. They areamong the most basic Boolean functions:to specify an arbitrary Boolean function from B n , one needs to write down its truth tableof length 2 n ; symmetric functions allow for more compact representation: it is enough tospecify n + 1 bits (for each of n + 1 values of P ni =1 x i );circuit complexity of almost all functions of n variables is exponential (Θ(2 n /n )), whereasany symmetric function can be computed by a linear size circuit ( O ( n )).Despite simplicity of symmetric functions, we still do not know how optimal circuits looklike for most of them. Below, we present new circuits for some of these functions. The SUM function is a fundamental symmetric function: for any symmetric f ∈ B n , size( f ) ≤ size(SUM n ) + o ( n ). The reason for this is that any function from B n can be computedby a circuit of size O (2 n /n ) by the results of Muller [14] and Lupanov [13]. This allowsto compute any symmetric f ( x , . . . , x n ) ∈ B n as follows: first, compute SUM n ( x , . . . , x n )using size(SUM n ) gates; then, compute the resulting bit using at most O (2 log n / log n ) = o ( n )gates. For the same reason, any lower bound size( f ) ≤ α for a symmetric function f ∈ B n implies a lower bound size(SUM n ) ≤ α − o ( n ). Currently, we know the following bounds forSUM n :2 . n − O (1) ≤ size(SUM n ) ≤ . n + o ( n ) . The lower bound is due to Stockmeyer [19], the upper bound is due to Demenkov et al. [5].A circuit for SUM n can be constructed from circuits for SUM k for some small k . Forexample, using full and half adders as building blocks, one can compute SUM n (for any n )by a circuit of size 5 n as follows. Start from n bits ( x , . . . , x n ) of weight 0. While there arethree bits of the same weight k , replace them by two bits of weights k and k + 1 using a fulladder. This way, one gets at most two bits of each weight 0 , , . . . , l − l = ⌈ log ( n + 1) ⌉ )in at most 5( n − l ) gates (as each full adder reduces the number of bits). To leave exactlyone bit of each weight, it suffices to use at most l half or full adders ( o ( n ) gates). Let usdenote the size of the resulting circuit by s ( n ). The second row of Table 1 shows the valuesof s ( n ) for some n ≤
15 (see (28) in [9]).
SAT-based Circuit Local Improvement n s ( n ) 2 5 9 12 17 20 26 29 34 55size(SUM n ) 2 5 9 11 ≤ ≤ ≤ ≤ ≤ ≤ Table 1
The first line shows the value of n . The second line gives the size s ( n ) of a circuit forSUM n composed out of half and full adders. The third row shows known bounds for size(SUM n ). SUM SUM x x x x x a b b (a) MDFA x x x x x ⊕ ⊕ a a ⊕ b b (b) x x x x x ⊕ ⊕∨ ⊕⊕ a ⊕ ⊕ > ⊕ b ⊕ a ⊕ b > (c) Figure 3 (a) Two consecutive SUM blocks. (b) The MDFA block. (c) The highlighted part ofthe optimal circuit for SUM computes MDFA. In a similar fashion, one can get an upper bound (see Theorem 1 in [12])size(SUM n ) ≤ size(SUM k ) k − ⌈ log ( k + 1) ⌉ · n + o ( n ) . (2)This motivates the search for efficient circuits for SUM k for small values of k . The bottomrow of Table 1 gives upper bounds that we were able to find using the program (the upperbounds for n ≤ s ( n )is not optimal is n = 5. The best upper bound for SUM n given by (2) is 4 . n + o ( n ) for n = 7. The upper bound for n = 15 is 53 n/
11 + o ( n ) which is worse than the previous upperbound. But if it turned out that size(SUM ) ≤
52, it would give a better upper bound.The found circuits for SUM n for n ≤
15 does not allow to improve the strongest knownupper bound size(SUM n ) ≤ . n + o ( n ) due to Demenkov et al. [5]. Below, we present severalinteresting observations on the found circuits. The optimal circuit of size 11 for SUM shown in Figure 2(c) can be used to get an upperbound 4 . n + o ( n ) for size(SUM n ) (though not through (2) directly). To do this, considertwo consecutive SUM circuits shown in Figure 3(a). Its specification is: x + · · · + x = b + 2( a + b ), its size is equal to 10. One can construct a similar block, called MDFA (for . S. Kulikov and N. Slezkin 7 x x x ⊕ ⊕ w ⊕ ∨ ⊕ w x x x x ⊕ ⊕ ⊕ w ⊕ > ∨ ⊕ ⊕ w >w x x x x x ⊕ ⊕ ⊕ ⊕ w ⊕ ⊕∨ > ⊕ ⊕ w > w Figure 4
Optimal circuits computing SUM n for n = 3 , , x , has out-degree one. modified double full adder), of size 8, whose specification isMDFA( x ⊕ x , x , x , x , x ⊕ x ) = ( b , a , a ⊕ b ) , see Figure 3(b). The fact that MDFA uses the encoding ( p, p ⊕ q ) for pairs of bits ( p, q ),allows to use it recursively to compute SUM n : first, compute x ⊕ x , x ⊕ x , . . . , x n − ⊕ x n ( n/ n/ n gates). The MDFA block was constructedby Demenkov et al. [5] in a semiautomatic manner. And it turns out that MDFA is justa subcircuit of the optimal circuit for SUM ! See Figure 3(c). For many upper bounds from the bottom row of Table 1, we found circuits with the followinginteresting structure: the first thing the circuit computes is x ⊕ x ⊕ · · · ⊕ x n ; moreoverthe variables x , . . . , x n are used for this only. This is best illustrated by an example — seeFigure 4.These circuits can be found using the following code. It demonstrates two new usefulfeatures: fixing gates and forbidding wires between some pairs of gates. def sum_n(x): return [(sum(x) >> i) & 1 for i in range(ceil(log2(len(x) + 1)))] for n, size in ((3, 5), (4, 9), (5, 11)):circuit_finder = CircuitFinder(dimension=n, number_of_gates=size,function=sum_n)circuit_finder.fix_gate(n, 0, 1, '0110') for k in range(n - 2):circuit_finder.fix_gate(n + k + 1, k + 2, n + k, '0110') for i in range(1, n): for j in range(n, n + size): if i + n - 1 != j:circuit_finder.forbid_wire(i, j) SAT-based Circuit Local Improvement circuit = circuit_finder.solve_cnf_formula(verbose=0)circuit.draw(f'sum { n } ') The optimal circuit for SUM can be used to construct an optimal circuit of size 2 . n + O (1)for MOD n due to Stockmeyer [19]. To do this, note that there is a subcircuit (of thecircuit at Figure 2(c)) of size 9 that computes the two least significant bits ( w , w ) of x + · · · + x (one removes the gates g , w ). To compute x + · · · + x n mod 4, one firstapplies n such blocks and then computes the parity of the resulting bits of weight 1. Thetotal size is 9 · n + n = 2 . n . Thus, the circuit that Stockmeyer constructed in 1977 by hand,nowadays can be found automatically in a few seconds. In [11], Kojevnikov et al. presented circuits of size 3 n + O (1) for MOD ,rn (for any r ). Later,Knuth [10, solution to exercise 480] analyzed their construction and proved an upper bound3 n −
4. Also, by finding the exact values for size(MOD ,rn ) for all 3 ≤ n ≤ ≤ r ≤ n . ▶ Theorem 1.
For all n ≥ and all r ∈ { , , } , size(MOD ,rn ) ≤ n − − [( n + r ) ≡ r mod 3] . To prove Knuth’s conjecture, one also needs to prove a lower bound on size(MOD ,rn ). Thecurrently strongest known lower bound for size(MOD ,rn ) is 2 . n − O (1) due to Stockmeyer [19](and no stronger lower bound is known for any other symmetric function). Proof.
As in [11], we construct the required circuit out of constant size blocks. Schematically,the circuit looks as follows. x x k x k +1 x k +2 x k +3 x n − l +1 x n · · · · · ·· · · IN k MID MID OUT rl Here, the n input bits are passed from above. What is passed from block to block (from leftto right) is the pair of bits ( r , r ) encoding the current remainder r modulo 3 as follows: if r = 0, then ( r , r ) = (0 , r = 1, then ( r , r ) = (0 , r = 2, then r = 1. The firstblock IN k takes the first k input bits and computes the remainder of their sum modulo 3. It isfollowed by a number of MID blocks each of which takes the current remainder and three newinput bits and computes the new remainder. Finally, the block OUT rl takes the remainderand the last l input bits and outputs MOD ,rn . The integers k, l take values in { , , } and { , , } , respectively. Their exact values depend on r and n mod 3 as described below.The theorem follows from the following upper bounds on the circuit size of the justintroduced functions: size(IN ) ≤
2, size(IN ) ≤
5, size(IN ) ≤
7, size(MID ) ≤ ) ≤
5, size(OUT ) ≤
2, size(OUT ) ≤
8. The corresponding circuits are presented . S. Kulikov and N. Slezkin 9 n = 3 t n = 3 t + 1 n = 3 t + 2 r = 0 (4 , t − , , n − , t − , , n − , t − , , n − r = 1 (2 , t − , , n − , t − , , n − , t − , , n − r = 2 (3 , t − , , n − , t − , , n − , t − , , n − Table 2
Choosing parameters k, m, l depending on n mod 3 and r . The circuit is composed outof blocks as follows: IN k + m × MID + OUT lr . For each pair ( n mod 3 , r ) we show three things:the triple ( m, k, l ); the sizes of two blocks: size(IN k ) and size(OUT lr ); the size of the resultingcircuit computed as s = size(IN k ) + 9 m + size(OUT lr ). For example, the top left cell is read asfollows: when r = 0 and n = 3 t , we set k = 4 , m = t − , l = 2; the resulting circuit is thenIN +( t − × MID + OUT ; since size(IN ) = 7 and size(OUT ) = 5, the size of the circuit is7 + 9( t −
2) + 5 = 9 t − n − in the Appendix by a straightforward Python code that verifies their correctness. (Thepresented code proves the mentioned upper bounds by providing explicit circuits. We havealso verified that no smaller circuits exist meaning that the inequalities above are in factequalities.)Table 2 shows how to combine the blocks to get a circuit computing MOD ,rn of therequired size. (Technically, it requires n to be at least 4. For n = 3, the correspondingcircuits are easy to construct.) ◀ Here, we present an example of a reasonably small circuit that our program fails to improvethough a better circuit is known. The reason is that these two circuits are quite different.The function we are going to consider is the threshold-2 function:THR n ( x , . . . , x n ) = [ x + · · · + x n ≥ . Figures 5 and 6 show circuits of size 31 and 29 for THR . They are quite different and ourprogram is not able to find out that the circuit of size 31 is suboptimal. One can constructthe two circuits in the program as follows. c = Circuit(input_labels=[f'x { i } ' for i in range(1, 13)], gates={})c.outputs = add_naive_thr2_circuit(c, c.input_labels)c.draw('thr2naive')c = Circuit(input_labels=[f'x { i } ' for i in range(1, 13)], gates={})c.outputs = add_efficient_thr2_circuit(c, c.input_labels, 3, 4)c.draw('thr2efficient') In the paper, we focus mainly on proving asymptotic upper bounds for function families(that is, that work for every input size). A natural further step is to apply the programto specific circuits that are used in practice. x x x x x x x x x x x x ∨ ∨ ∨ ∨ ∨ ∨ ∨ ∨ ∨ ∨∧ ∧ ∧ ∧ ∧ ∧ ∧ ∧ ∧ ∧∨ ∨ ∨ ∨ ∨ ∨ ∨ ∨ ∨ ∧∨ output x x x x x x · · · s o r t s o r t s o r t s o r t ∧∨ Figure 5
A circuit of size 31 for THR : (a) block structure and (b) gate structure. TheSORT( u, v ) block sorts two input bits as follows: SORT( u, v ) = (min { u, v } , max { u, v } ) = ( u ∧ v, u ∨ v ).The circuit performs one and a half iterations of the bubble sort algorithm: one first finds themaximum bit among n input bits; then, it remains to compute the disjunction of the remaining n − n − x x x x ∨ x x ∨ ∨ x x ∨∨ c ∨ ∨ c x ∨ ∨ x x ∨∧ ∨ ∨ ∨ c x ∨ r ∨ ∨ r ∧ ∨ ∨ r ∨ c ∨ ∧∨ ∧ ∧∨ ∨∨ output x x x x x x x x x x x x ∨ r ∨ r ∨ r ∨ c ∨ c ∨ c ∨ c THR T H R ∨ Figure 6
A circuit of size 29 for THR : (a) block structure and (b) gate structure. It implementsa clever trick by Dunne [6]. Organize 12 input bits into a 3 × r , r , r of the rows and disjunctions c , c , c , c of the columns. Then, there are at least two 1’s among x , . . . , x if and only if there are at least two 1’s among either r , r , r or c , c , c , c . This allowsto proceed recursively. In general, it leads to a circuit of size 2 n + o ( n ). (Sergeev [17] showed recentlythat the monotone circuit size of THR n is 2 n + Θ( √ n ).) It would also be interesting to extend the program so that it is able to discover the circuitfrom Figure 6.
References https://github.com/berkeley-abc/abc . Armin Biere. PicoSAT essentials.
J. Satisf. Boolean Model. Comput. , 4(2-4):75–97, 2008. URL: https://doi.org/10.3233/sat190039 , doi:10.3233/sat190039 . Joshua Brakensiek, Marijn Heule, John Mackey, and David Narváez. The resolution of Keller’sconjecture. In Nicolas Peltier and Viorica Sofronie-Stokkermans, editors,
Automated Reasoning- 10th International Joint Conference, IJCAR 2020, Paris, France, July 1-4, 2020, Proceedings,Part I , volume 12166 of
Lecture Notes in Computer Science , pages 48–65. Springer, 2020. URL: https://doi.org/10.1007/978-3-030-51074-9_4 , doi:10.1007/978-3-030-51074-9\_4 . https://github.com/alexanderskulikov/circuit_improvement . . S. Kulikov and N. Slezkin 11 Evgeny Demenkov, Arist Kojevnikov, Alexander S. Kulikov, and Grigory Yaroslavtsev. Newupper bounds on the boolean circuit complexity of symmetric functions.
Inf. Process. Lett. ,110(7):264–267, 2010. URL: https://doi.org/10.1016/j.ipl.2010.01.007 , doi:10.1016/j.ipl.2010.01.007 . Paul E. Dunne.
Techniques for the analysis of monotone Boolean networks . PhD thesis,University of Warwick, 1984. Magnus Gausdal Find, Alexander Golovnev, Edward A. Hirsch, and Alexander S. Kulikov. Abetter-than-3n lower bound for the circuit complexity of an explicit function. In Irit Dinur,editor,
IEEE 57th Annual Symposium on Foundations of Computer Science, FOCS 2016, 9-11October 2016, Hyatt Regency, New Brunswick, New Jersey, USA , pages 89–98. IEEE ComputerSociety, 2016. URL: https://doi.org/10.1109/FOCS.2016.19 , doi:10.1109/FOCS.2016.19 . . Donald E. Knuth.
The Art of Computer Programming, Volume 4, Fascicle 0: Introduction toCombinatorial Algorithms and Boolean Functions (Art of Computer Programming) . Addison-Wesley Professional, 1 edition, 2008. Donald E. Knuth.
The Art of Computer Programming, Volume 4, Fascicle 6: Satisfiability .Addison-Wesley Professional, 1st edition, 2015. Arist Kojevnikov, Alexander S. Kulikov, and Grigory Yaroslavtsev. Finding efficient circuitsusing SAT-solvers. In Oliver Kullmann, editor,
Theory and Applications of SatisfiabilityTesting - SAT 2009, 12th International Conference, SAT 2009, Swansea, UK, June 30 -July 3, 2009. Proceedings , volume 5584 of
Lecture Notes in Computer Science , pages 32–44. Springer, 2009. URL: https://doi.org/10.1007/978-3-642-02777-2_5 , doi:10.1007/978-3-642-02777-2_5 . Alexander S. Kulikov. Improving circuit size upper bounds using sat-solvers. In Jan Madsenand Ayse K. Coskun, editors, , pages 305–308. IEEE, 2018.URL: https://doi.org/10.23919/DATE.2018.8342026 , doi:10.23919/DATE.2018.8342026 . Oleg Lupanov. A method of circuit synthesis.
Izvestiya VUZov, Radiofizika , 1:120–140, 1959. David E. Muller. Complexity in electronic switching circuits.
IRE Transactions on ElectronicComputers , EC-5:15–19, 1956. https://pypi.org/project/pycosat/ . https://pygraphviz.github.io/ . Igor Sergeev. On monotone circuit complexity of threshold boolean functions.
DiskretnayaMatematika , 32:81–109, 2020. doi:10.4213/dm1547 . Mathias Soeken, Heinz Riener, Winston Haaswijk, Eleonora Testa, Bruno Schmitt, GiuliaMeuli, Fereshte Mozafari, and Giovanni De Micheli. The EPFL logic synthesis libraries,November 2019. arXiv:1805.05121v2. Larry J. Stockmeyer. On the combinational complexity of certain symmetric boolean functions.
Mathematical Systems Theory , 10:323–336, 1977. doi:10.1007/BF01683282 . A Blocks for the Modulo 3 Function
The following code justifies the existence of circuits needed in the proof of Theorem 1. from itertools import productenc = {(0, 0): 0, (0, 1): 1, (1, 0): 2, (1, 1): 2} for x1, x2 in product(range(2), repeat=2):g1 = x1 ^ x2 g2 = x1 & x2 assert (x1 + x2) % 3 == enc[g2, g1] for x1, x2, x3 in product(range(2), repeat=3):g1 = x1 == x2g2 = 1 - (x1 | x2)g3 = g2 == x3g4 = g1 == g3g5 = g2 < g4 assert (x1 + x2 + x3) % 3 == enc[g5, g3] for x1, x2, x3, x4 in product(range(2), repeat=4):g1 = x1 == x2g2 = g1 ^ x3g3 = g2 ^ x2g4 = g1 & g3g5 = g4 == x4g6 = g2 == g5g7 = g4 < g6 assert (x1 + x2 + x3 + x4) % 3 == enc[g7, g5] for x1, x2, x3, z0, z1 in product(range(2), repeat=5):g1 = x1 == z1g2 = g1 | z0g3 = g2 ^ x2g4 = g3 ^ z0g5 = g4 ^ x1g6 = g2 & g5g7 = g6 == x3g8 = g3 == g7g9 = g6 < g8 assert (enc[z0, z1] + x1 + x2 + x3) % 3 == enc[g9, g7] for x1, z0, z1 in product(range(2), repeat=3):g1 = x1 ^ z1g2 = z0 < g1 assert ((enc[z0, z1] + x1) % 3 == 1) == g2 for x1, x2, z0, z1 in product(range(2), repeat=4):g1 = z0 == x2g2 = x1 ^ z1g3 = g1 == x1g4 = z0 < g2 . S. Kulikov and N. Slezkin 13 g5 = 1 - (g3 | g4) assert ((enc[z0, z1] + x1 + x2) % 3 == 0) == g5 for x1, x2, x3, z0, z1 in product(range(2), repeat=5):g1 = x1 == z1g2 = g1 | z0g3 = g2 ^ x2g4 = g3 ^ z0g5 = g4 ^ x1g6 = g2 & g5g7 = g3 == x3g8 = 1 - (g6 | g7) assert ((enc[z0, z1] + x1 + x2 + x3) % 3 == 2) == g8 for x1, x2, x3 in product(range(2), repeat=3):g1 = x2 == x3g2 = x1 ^ x2g3 = g1 > g2 assert ((x1 + x2 + x3) % 3 == 0) == g3 for x1, x2, x3 in product(range(2), repeat=3):g1 = x2 ^ x3g2 = x3 | g1g3 = x1 < g2g4 = g1 ^ g3 assert ((x1 + x2 + x3) % 3 == 2) == g4 for x1, x2, x3, x4 in product(range(2), repeat=4):g1 = x1 ^ x2g2 = x3 ^ x4g3 = x1 ^ x3g4 = g2 | g3g5 = g1 < g4g6 = g2 ^ g5 assertassert