# Enumerating monotone Boolean functions

The 9th Dedekind number was recently computed. What is a Dedekind number and why was it a big deal to compute just the 9th one of them?

We need to define a couple terms before we can define Dedekind numbers.

A Boolean function is a function whose inputs are 0’s and 1’s and whose output is 0 or 1.

A function f is monotone if increasing the input cannot decrease the output:

xyf(x) ≤ f(y).

Obviously a monotone Boolean function is a Boolean function that is monotone, but monotone with respect to what order? How are we to define when xy when x and y are sequences of bits?

There are numerous ways one might order the inputs, but the conventional order  in this context is to say x ≤ y if every bit in x is less than or equal to the corresponding bit in y. So if the ith bit of x is a 1, then the ith bit of y must be a 1.

A Boolean function is monotone if and only if flipping an input bit from 0 to 1 cannot change the output from 1 to 0.

## Enumerating monotone Boolean functions

The nth Dedekind number M(n) is the number of monotone Boolean functions of n variables. We’ll enumerate a few of these. Let a, b, c and d be Boolean variables and denote AND by ∧ and OR by ∨. As usual, we assume ∧ is higher precedence than ∨ so that, for example,

xyz

means

x ∨ (yz).

## One variable

There are three monotone functions of one variable a: always return 0, always return a, and always return 1.

• 0
• a
• 1

The only Boolean function of one variable that isn’t monotone is the function that flips a, i.e. f(a) = ¬a.

## Two variables

There are six monotone Boolean functions with two variables:

• 0
• a
• b
• a ∧ b
• a ∨ b
• 1

and so M(2) = 6.

We can verify that the six functions above are monotone with the following Python code.

```    from itertools import product

f = [None]*6
f = lambda a, b: 0
f = lambda a, b: a
f = lambda a, b: b
f = lambda a, b: a | b
f = lambda a, b: a & b
f = lambda a, b: 1

for i in range(6):
for (a, b) in product((0,1), repeat=2):
for (x, y) in product((0,1), repeat=2):
if a <= x and b <= y:
assert(f[i](a, b) <= f[i](x, y))
```

## Three variables

There are 20 monotone Boolean functions of three variables:

• 0
• a
• b
• c
• a ∧ b
• bc
• ac
• ab
• bc
• ac
• abc
• bca
• acb
• abbc
• acbc
• abac
• abbcac
• abc
• abc

and so M(3) = 20.

As before, we can verify that the functions above are monotone with a script.

```    g = [None]*20
g[ 0] = lambda a, b, c: 0
g[ 1] = lambda a, b, c: a
g[ 2] = lambda a, b, c: b
g[ 3] = lambda a, b, c: c
g[ 4] = lambda a, b, c: a & b
g[ 5] = lambda a, b, c: b & c
g[ 6] = lambda a, b, c: a & c
g[ 7] = lambda a, b, c: a | b
g[ 8] = lambda a, b, c: b | c
g[ 9] = lambda a, b, c: a | c
g = lambda a, b, c: a & b | c
g = lambda a, b, c: b & c | a
g = lambda a, b, c: a & c | b
g = lambda a, b, c: a & b | b & c
g = lambda a, b, c: a & c | b & c
g = lambda a, b, c: a & b | a & c
g = lambda a, b, c: a & b | b & c | a & c
g = lambda a, b, c: a & b & c
g = lambda a, b, c: a | b | c
g = lambda a, b, c: 1

for i in range(20):
for (a, b, c) in product((0,1), repeat=3):
for (x, y, z) in product((0,1), repeat=3):
if a <= x and b <= y and c <= z:
assert(g[i](a, b, c) <= g[i](x, y, z))
```

## More variables

The concrete approach to enumerating monotone Boolean functions does not scale. There are 168 monotone functions of four variables, 7581 of five variables, and 7,828,354 functions of six variables. The Dedekind numbers M(n) grow very quickly. The next post will quantify just how quickly.

 This “order” is technically a partial order. If x = (0, 1) and y = (1, 0) then x and y are not comparable; neither is less than or equal to the other.

## One thought on “Enumerating monotone Boolean functions”

1. David Liguori

It would be helpful if you enumerated the Boolean functions for 2 and 3 arguments that are *not* monotone.