We start our investigation of computer hardware with Boolean functions. For this part of the course we will use the hardware convention for Boolean values, 0 = false and 1 = true (instead of the Racket convention of #f and #t). A Boolean function maps n-tuples of Boolean values to Boolean values, where n is a non-negative integer. (An n-tuple of values is an ordered sequence of n values, generally represented with parentheses and commas: (13,7,44) is a 3-tuple (or triple) of values, with first element 13, second element 7, and third element 44.)
Note that the domain of a Boolean function is finite, so we can write down a table containing every possible input and the corresponding value of the function for that input. Four examples of Boolean functions when n = 1.
input | value input | value input | value input | value ------------- ------------- ------------- ------------- 0 | 0 0 | 1 0 | 0 0 | 1 1 | 1 1 | 0 1 | 0 1 | 1The first function shown above is the identity: it takes input x and returns value x, for x = 0,1. The second function is negation, or NOT -- if the input is 0 (false), the value is 1 (true); if the input is 1 (true), the output is 0 (false). The last two functions "ignore" their inputs: the third one is the constant function 0, and the fourth one is the constant function 1. These are the only possible Boolean functions when n = 1. To see this, note that the table for any such function has 2 lines, one for input 0 and one for input 1.
input | value ------------- 0 | ? 1 | ?Each of the two question marks can (independently) be replaced by 0 or 1 to get a Boolean function. Two choices for the first question mark times two choices for the second question mark gives four choices overall for Boolean functions when n = 1. Some examples of Boolean functions when n = 2.
input | value input | value input | value input | value ------------- ------------- ------------- ------------- 0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 1 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 1 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 1 | 1 1 1 | 1 1 1 | 0 1 1 | 1(Note that I have written "0 1" instead of the 2-tuple (0,1).) The first function above is AND -- it is only 1 (true) when *both* of its inputs are 1 (true), and 0 (false) otherwise. The second function above is (inclusive) OR -- it is only 0 (false) when *both* of its inputs are 0, and 1 (true) otherwise. The third function is something called Exclusive OR, whose abbreviation is XOR -- it is 1 (true) if and only if exactly *one* of its arguments is 1 (true). Note that it differs from (inclusive) OR on the last line, when both arguments are 1 (true). In this case, inclusive OR is 1 but Exclusive OR is 0. We will use OR to mean (inclusive) OR, and use XOR when we mean Exclusive OR. The fourth function is one that logicians like; it is IMPLICATION, where the intuitive meaning is "if the first argument is true then the second argument is true." After long debate mathematical logicians agreed on this Boolean function as a good meaning for implication, though the first two lines of the table are a bit counterintuitive. This table represents the meaning intended by a mathematician who says "If p then q."
Another useful Boolean function of two arguments is equivalence, given by the following table.
input | value ------------- 0 0 | 1 0 1 | 0 1 0 | 0 1 1 | 1This function is 1 if and only if its two arguments are equal (both 0 or both 1.)
How many total Boolean functions for n = 2? There are clearly four lines in the table, and on each line we can make a choice of 0 or 1 for the value of the Boolean function, so there are 2x2x2x2 = 24 = 16 possible Boolean functions when n = 2. We've shown 5 of them above; there are 11 others, including the constant function 0 and the constant function 1, whose tables are:
input | value input | value ------------- ------------- 0 0 | 0 0 0 | 1 0 1 | 0 0 1 | 1 1 0 | 0 1 0 | 1 1 1 | 0 1 1 | 1Note that these (technically) are different functions from the constant functions 0 and 1 for n = 1, because their domains are different (one has 4 elements, the other has 2 elements.)
An example of a Boolean function for n = 3.
input | value --------------- 0 0 0 | 0 0 0 1 | 0 0 1 0 | 0 0 1 1 | 1 1 0 0 | 0 1 0 1 | 1 1 1 0 | 1 1 1 1 | 1Note that this function is 1 if and only if at least two of its arguments are 1. Thus, it computes a "majority vote" of its inputs. How many Boolean functions are there for n = 3? Clearly, there are 2x2x2 = 23 = 8 lines in the table, and for each of these 8 lines we may independently choose a 0 or a 1 to enter for the value. Thus, there are 2x2x2x2x2x2x2x2 = 28 = 256 Boolean functions when n = 3.
For a general non-negative integer n, how many Boolean functions are there? There are n arguments, each of which can be 0 or 1, so there are 2n lines in the table for such a function. On each of those lines, we may (independently) enter a 0 or a 1 as the value, for a total of (2)(2n) possible Boolean functions of n arguments. Check for n = 3: we get 2n = 23 = 8 lines, and 2(2n) = 28 = 256 functions. Here is a table of some values of this function
n | 2(2n) ---------------- 0 | 2 1 | 4 2 | 16 3 | 256 4 | 65,536 (= 2(16))Note that each line is the square of its predecessor, so that this sequence can be described by the recurrence:
A0 = 2 A(n+1) = (An)2 for n >= 0You may want to convince yourself of that algebraically. Note that by convention exponentiation associates to the right, and in general (ab)c is not equal to (a)(bc).
Boolean expressions. We first introduce the syntax of a notation for representing Boolean functions. The definition we give is inductive (or recursive). We assume a countable supply of variable symbols, for example, x, y, z, x1, y1, z1, x2, y2, z2, ... . The definition:
(Base cases) 0 is a Boolean expression 1 is a Boolean expression x is a Boolean expression, for any variable x (Inductive cases) If E1 and E2 are Boolean expressions, then so are: (E1)' (E1 * E2) (E1 + E2)(Note that in the above I've used the asterisk (*) instead of the centered dot that I've used on the blackboard.) As is customary with these inductive definitions, we agree that the only Boolean expressions are those that can be obtained in a finite number of steps using the rules above. As examples of Boolean expressions, we have:
0 is a Boolean expression (base case) 1 is a Boolean expression (base case) x is a Boolean expression (base case) y is a Boolean expression (base case) (0)' is a Boolean expression (from 0 and inductive case) (x * 1) is a Boolean expression (from x and 1 and inductive case) ((0)' + (x * 1)) is a Boolean expression (from (0)' and (x * 1) ...There are a variety of other notations for the operations ', *, +, but these will be our conventions in the part of the course.
The syntactic definition just given requires a lot of parentheses, which are not so congenial for humans. We will use an order of operations convention for these operations: parentheses, ', *, +. This agrees with the PEMDAS (or BEDMAS or BODMAS) mnemonic, if we note that ' looks like exponentiation, * looks like multiplication, and + looks like addition. Hence we can interpret the expression (x' + y)' as (fully parenthesized): (((x)' + y))'.
The meaning (semantics) of Boolean expressions. We have a syntax, recursively defined, but we'd like to know what these expressions mean or denote. We start from the truth tables that many of you have previously encountered. To construct a truth table for the expression (x' + y)' we proceed as follows. There are two variables, x and y, so we have two columns labeled by x and y. We have a line in the table for each possible way to assign 0 or 1 to the variables x and y, thus:
x y | --------------- 0 0 | 0 1 | 1 0 | 1 1 |Now we look at the most deeply-nested subexpressions of our expression (the ones we'd have to construct first using our inductive definition of the syntax.) In this case, we need x' So we label a column of the table with x' and proceed to fill in values for it by applying NOT to the value of x on that line:
x y | x' --------------- 0 0 | 1 0 1 | 1 1 0 | 0 1 1 | 0Now we take the next expression: (x' + y), and label a column with this expression, and enter values for it on each line by combining the value of x' for that line with the value of y for that line:
x y | x' (x' + y) ---------------------- 0 0 | 1 1 0 1 | 1 1 1 0 | 0 0 1 1 | 0 1Note that this shows that the value of (x' + y) is 0 if and only if x = 1 and y = 0. Finally, to get the value of the top-level expression (x' + y)', we label another column of the table with this expression and enter values for it on each line by applying NOT to the value of (x' + y) on that line:
x y | x' (x' + y) (x' + y)' --------------------------------- 0 0 | 1 1 0 0 1 | 1 1 0 1 0 | 0 0 1 1 1 | 0 1 0Note that the value of (x' + y)' is 1 if and only if x = 1 and y = 0. Also, this expression is not symmetric in x and y. If our expression had involved the * symbol, then we would have used the AND function to combine the values of the two expressions on each line.
To relate this truth-table procedure to a slightly different formal treatment, we can view a Boolean expression as representing a map from *environments* to Boolean values. What is an environment? It is a map from variables to Boolean values, assigning a 0 or 1 to each variable. (In fact, we only need values for the variables that appear in the expression.) If we are only concerned with the values of the variables x and y, then there are four possibilities for environments: x = 0 and y = 0, or x = 0 and y = 1, or x = 1 and y = 0, or x = 1 and y = 1. Note that these correspond to the values in the columns labeled x and y in the four lines of the truth table above. What is shown in the other three columns, respectively, are the values taken by the expressions x', (x' + y) and (x' + y)' in those four environments. We'll see a recursive view of the process of determining the value of a Boolean expression in an environment in the next lecture.
Inductive/recursive definition of the value of a Boolean expression in an environment. Recall that an environment is an assignment of Boolean values (0 or 1) to the variables. For example, for the expression (x' + y)' we might consider the environment x = 0 and y = 1. In the previous lecture we saw a construction of the truth table for the expression (x' + y)' as follows.
x y | x' (x' + y) (x' + y)' --------------------------------- 0 0 | 1 1 0 0 1 | 1 1 0 1 0 | 0 0 1 1 1 | 0 1 0The environment x = 0 and y = 1 corresponds to the second line of this truth table, where x and y have these values. The other columns of the second line show the values taken on by the expressions x', (x' + y), and (x' + y)' in this environment. A recursive definition of the value of a Boolean expression in an environment follows the form of the recursive definition of the syntax of a Boolean expression, as follows.
If E is a Boolean expression and env is an environment, then the value of E in env is defined as follows: Base cases If E = 0, then the value of E is 0 in any environment If E = 1, then the value of E is 1 in any environment If E = x (a variable), then the value of E is the value that env assigns to x Recursive cases If E = (E1)', then the value of E in env is the NOT of the value of E1 in env If E = (E1 * E2), then the value of E in env is the AND of the value of E1 in env and the value of E2 in env If E = (E1 + E2), then the value of E in env is the OR of the value of E1 in env and the value of E2 in envWe can apply this definition to the expression E = (x' + y)' and the environment x = 0 and y = 1, and we get a tree of recursive applications of the definition as follows.
value of (x' + y)' (=> 0) / | NOT value of (x' + y) (=> 1) / | \ OR value of x' value of y (=> 1) (=> 1) / | NOT value of x ( => 0)Note that the leaves are the base cases x and y, whose values are determined by the environment (x = 0 and y = 1), and as the values are returned back up the tree, the values for the sub-expressions x' and (x' + y) are also found, corresponding to the "auxiliary" columns in the truth table. You'll be asked to implement this definition as a recursive procedure in the next homework.
How expressive are Boolean expressions? What class of Boolean functions can be expressed by Boolean expression? The answer is: EVERY Boolean function can be expressed by a Boolean expression. We'll show this by means of the "sum of products" algorithm that can take an arbitrary truth table and produce a Boolean expression for that truth table.
The sum-of-products algorithm. We start with a truth table for an arbitrary Boolean function, for example the following one, where we've given the 3 arguments the names x, y and z. (This is not so arbitrary -- we saw that it is the "majority vote" function, but the same procedure works on an arbitrary function.)
x y z | f(x,y,z) ----------------- 0 0 0 | 0 0 0 1 | 0 0 1 0 | 0 0 1 1 | 1 1 0 0 | 0 1 0 1 | 1 1 1 0 | 1 1 1 1 | 1Can we write down a Boolean expression with this truth table? The answer is yes, and one method is the sum-of-products algorithm. If we look at the first 1 in the table above, we see that it corresponds to the environment where x = 0, y = 1, and z = 1. The expression (x' * y * z) has the property that it is 1 in this environment, and 0 in all the other environments in the table. That is, it has the truth table:
x y z | (x' * y * z) --------------------------- 0 0 0 | 0 0 0 1 | 0 0 1 0 | 0 0 1 1 | 1 1 0 0 | 0 1 0 1 | 0 1 1 0 | 0 1 1 1 | 0Note, for example that when x = 1, y = 0, and z = 1, x' = 0, so the AND of x', y, and z is 0. For each of the other 1's in the truth table of f we can find an expression that is 1 on that line of the truth table and 0 elsewhere. For example, for the environment x = 1, y = 0, z = 1, we get such an expression by conjoining x, y', and z. (Note that we take the variable if its value is 1, and the NOT of the variable if its value is 0.)
x y z | (x * y' * z) --------------------------- 0 0 0 | 0 0 0 1 | 0 0 1 0 | 0 0 1 1 | 0 1 0 0 | 0 1 0 1 | 1 1 1 0 | 0 1 1 1 | 0Similarly, for the other two 1's in the table, we get the expressions (x * y * z') and (x * y * z). Putting all four of these expressions in a truth table, together with the expression gotten by OR'ing all of them together, we get:
x y z | (x'*y*z) (x*y'*z) (x*y*z') (x*y*z) (x'*y*z)+(x*y'*z)+(x*y*z')+(x*y*z) ------------------------------------------------------------------------------------------ 0 0 0 | 0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 1 0 | 0 0 0 0 0 0 1 1 | 1 0 0 0 1 1 0 0 | 0 0 0 0 0 1 0 1 | 0 1 0 0 1 1 1 0 | 0 0 1 0 1 1 1 1 | 0 0 0 1 1Note that the final expression, (x'*y*z) + (x*y'*z) + (x*y*z') + (x*y*z), has the truth table of f as specified above.
The sum of products algorithm takes any truth table for a Boolean function and returns a Boolean expression with that truth table. We may re-state the algorithm in general terms as follows.
The Sum of Products Algorithm ------------------------------ Input: a truth table Output: a Boolean expression with that truth table If all of the rows of the truth table have value 0, output the Boolean expression: 0. Otherwise, for each row with the value 1, construct a term (product) by and'ing together all the variables that are 1 in that row and the negations of all the variables that are 0 in that row. Output the Boolean expression gotten by or'ing together all the terms (products) constructed for rows with value 1.The term "sum of products" refers to the fact that the main connectors are ORs ("sums") and the minor connectors are ANDs ("products"). (There is a dual "product-of-sums" algorithm -- it might be interesting to derive it.)
Thus, all Boolean functions may be expressed by Boolean expressions. This also shows that the operations of NOT, AND, and OR are a "complete basis" for the Boolean functions -- every Boolean function can be represented by an expression using only NOT, AND, and OR.
The sum of products algorithm in general does not return the "most concise" possible expression for a given truth table. Consider the truth table for the expression (x*y + x*z + y*z), as follows.
x y z | (x*y + x*z + y*z) ------------------------------ 0 0 0 | 0 0 0 1 | 0 0 1 0 | 0 0 1 1 | 1 1 0 0 | 0 1 0 1 | 1 1 1 0 | 1 1 1 1 | 1This expression also has the desired truth table for f(x,y,z), and is much more concise than the expression that the sum of products algorithm found.
In general, we may define a notion of (semantic) equivalence of two Boolean expressions as follows.
Two Boolean expressions E1 and E2 are equivalent if for every environment env that assigns values to all of the variables that occur in either E1 or E2, the value of E1 in env is equal to the value of E2 in env.Note that we need to consider environments that give values to all of the variables that occur in either expression. (The notation for the equivalence of two Boolean expressions is an "equal sign" with 3 horizontal bars, which we'll somewhat inaccurately render as "=" in these notes or ≡) Thus, we've seen the equivalence of the following two Boolean expressions.
(x*y*z' + x*y'*z + x'*y*z + x*y*z) = (x*y + x*z + y*z)Question: is there an algorithm that inputs a Boolean expression E1 and outputs a "most concise" Boolean expression E2 equivalent to E1? (We can define the size of a Boolean expression as the number of occurrences of symbols needed to write it down; then a "most concise" expression is one that has the smallest possible size.)
See the notes Sum-of-products algorithm for the truth table for the alarm signal (a) as a function of sensors for key in ignition (k), door closed (d) and seat belt fastened (b), and two Boolean expressions for a in terms of k, d, and b, one derived informally and one derived using the sum-of-products algorithm.
Three useful Boolean functions of 2 variables are XOR, implication (->), and equivalence (<->), whose truth tables are as follows.
x y | (x XOR y) x y | (x -> y) x y | (x <-> y) ------------------ ----------------- ------------------ 0 0 | 0 0 0 | 1 0 0 | 1 0 1 | 1 0 1 | 1 0 1 | 0 1 0 | 1 1 0 | 0 1 0 | 0 1 1 | 0 1 1 | 1 1 1 | 1Each of these can be expressed in terms of AND, OR and NOT, using the sum of products algorithm as follows.
(x XOR y) = x'*y + x*y' (x -> y) = x'*y' + x'*y + x*y (x <-> y) = x'*y' + x*yNote that equivalence is true when x and y are equal, and XOR is true when x and y are unequal, so that each is the negation of the other. Another expression for (x -> y) is (x' + y), as verified by the following truth table.
x y | (x' + y) ----------------- 0 0 | 1 0 1 | 1 1 0 | 0 1 1 | 1
A set of axioms for the equivalence of Boolean expressions is available here: Boolean axioms. Each axiom expresses an equivalence between two Boolean expressions. For example, axiom (A10) is the following.
a + (b * c) ≡ (a + b) * (a + c)This is the property that in Boolean algebra, OR distributes over AND. To verify the equivalence of the two sides, we consider the following truth table.
a b c | a + (b * c) (a + b) * (a + c) -------------------------------------------- 0 0 0 | 0 0 0 0 1 | 0 0 0 1 0 | 0 0 0 1 1 | 1 1 1 0 0 | 1 1 1 0 1 | 1 1 1 1 0 | 1 1 1 1 1 | 1 1Because the columns giving the values of the two expressions are equal, the expressions are equivalent.
These axioms have the property that consistently substituting an expression for each of the variables on both sides of the axiom gives another equivalent pair of expressions. So, if we take axiom (A7), which is
a * (a + b) ≡ aand substitute (x' + y) for a and z' for b on both sides, we get the equivalence
(x' + y) * ((x' + y) + z') ≡ (x' + y)Moreover, if we have an equivalence E1 ≡ E2 and another expression E3 that contains one or more sub-expressions equal to E1, then we can replace one or more of the sub-expressions E1 in E3 by E2 and get a new expression equivalent to E3. Thus, from axiom (A13) we have the equivalence
1 * a ≡ aand as a substitution instance of (A16) we have
x + x' ≡ 1and we may substitute (x + x') for 1 in the previous equivalence to get
(x + x') * a ≡ a
These axioms and rules of inference give a system that is "sound" (every equivalence derivable using the rules is in fact true) and "complete" (every true equivalence between Boolean expressions is in fact derivable.) The axioms are in fact redundant; as an example, we'll derive (A8) from the other axioms using the rules of inference. The axiom (A8) is one of the "absorption laws", namely,
a + (a * b) ≡ aOne way to derive it is to start with a + (a * b) and use (A10) to get
a + (a * b) ≡ (a + a) * (a + b)Using (A2), (a + a) ≡ a, so we have
a + (a * b) ≡ a * (a + b)Then using (A7) (the other "absorption law"), a * (a + b) ≡ a, so
a + (a * b) ≡ a
Here are three very useful equivalences that are not among the axioms.
(a + b)' ≡ a' * b' (a * b)' ≡ a' + b' (a')' ≡ aThe first two are called DeMorgan's laws, after the logician Augustus DeMorgan (who tutored Ada Lovelace in mathematics, after whom the Ada programming language was named.) The third is the law of double negation. These equivalences are easily verified using truth tables, but are somewhat challenging to derive using the given axioms and inference rules.
Note that the axioms on the list come in "dual" pairs. That is, if we replace + by *, replace * by +, replace 0 by 1 and replace 1 by 0, we will find a "dual" for every axiom on the list. For example, the dual of (A11), a * 0 ≡ 0 is (A14), a + 1 ≡ 1. This means that if we take any equivalence E1 ≡ E2 and apply the dual operation to the two sides to get D1 and D2, then the equivalence D1 ≡ D2 is also true.
We considered the question: is there an algorithm that takes as input a Boolean expression E1 and outputs a Boolean expression E2 equivalent to E1 such that E2 has the smallest "size" among all Boolean expressions equivalent to E1? (Where we define "size" as the number of symbols to write down the expression, for example.)