Design of Logic Environments

The "nand" logic operation is considered functionally complete, which means that using only nands it is possible to build any othr logic operation. For this reason, we have chosen to give Avida organisms "nand" as one of their instructions, and we can thereafter approximate the difficulty of all of the other tasks by the number of nands it takes to complete them.

The nand operation functions as follows:

Input A  Input B  A nand B 
0 0 1
0 1 1
1 0 1
1 1 0

All 2-input logic operations can be described in the same fashion. There are always 4 pairs of possible inputs, and the function is described by the four bits in the right-hand column. This means that there are, theoretically 16 possible 2-input logic functions, but some of these are trivial.

Four of the logic operations require no nands at all. They are ALL-ZEROs, ALL-ONEs, ECHO-A, and ECHO-B. In Avida we combine ECHO-A and ECHO-B into a single task (ECHO) and we ignore ALL-ZEROs and ALL-ONEs since they are trivial (a bit string with all zeros is just "0" and a bit string with all ones evaluates to "-1").

Given one NAND, we can determine whats possible by NANDing all pairs of our no-nands values together and see what we get. We have our two inputs (A and B) and out ALL-ZEROs and ALL-ONEs to work with.

NAND COMBOS Input A Input B Zeros Ones
Input A NOT-A A-NAND-B ALL-ONES NOT-A
Input B B-NAND-A NOT-B ALL-ONES NOT-B
Zeros ALL-ONES ALL-ONES ALL-ONES ALL-ONES
Ones NOT-A NOT-B ALL-ONES ALL-ZEROS


Glancing through this, it looks like we get four new functions: NOT-A, NOT-B, A-NAND-B, and B-NAND-A. We also see that ALL-ZEROS and ALL-ONES get us nothing new that we can't get from the other options, so we're going to ignore them from here on out.

Looking closer at the new functions, we realize the A-NAND-B is identical to B-NAND-A (they both produce 1,1,1,0 in the last column), so we lump them together into a single NAND function. With this, we discover that with a single nand we have uncovered three more 2-input logic functions, for a total of seven so far.

They are:

2-Input Logic using zero or one nands.
Input A  Input B  ALL-ZEROS  ALL-ONES  ECHO-A  ECHO-B  NOT-A  NOT-B  NAND 
0 0 0 1 0 0 1 1 1
0 1 0 1 0 1 1 0 1
1 0 0 1 1 0 0 1 1
1 1 0 1 1 1 0 0 0


We will also lump the NOT-A and NOT-B together and create the single task NOT, which will identify either of them in Avida. Of course, for the purpose of determining what other tasks can be built off of these, we will consider both separately.

To continue this process, we take our current state (and nand everything together again.) Anything new we get here will be function that cannot be performed using fewer than two nands.

NAND COMBOS Input A Input B NOT-A NOT-B A-NAND-B
Input A NOT-A A-NAND-B ALL-ONES B-OR-NOT-A B-OR-NOT-A
Input B B-NAND-A NOT-B A-OR-NOT-B ALL-ONES A-OR-NOT-B
NOT-A ALL-ONES A-OR-NOT-B ECHO-A A-OR-B ECHO-A
NOT-B B-OR-NOT-A ALL-ONES A-OR-B ECHO-B ECHO-B
A-NAND-B B-OR-NOT-A A-OR-NOT-B ECHO-A ECHO-B A-AND-B


Here it looks like we've found four new functions: A-OR-NOT-B, B-OR-NOT-A, A-OR-B and A-AND-B. But how many nands do they each require? Clearly the first two are a 1-nand function nanded with a 0-nand function, thus they require 2 nands each. The A-OR-B is clear-cut in the other direction. To get this function you must nand NOT-A to NOT-B. Each of these already cost 1 nand to build. Add to that the additional nand of combining them and you realize the A-OR-B costs 3-nands.

The same logic can almost be used for A-AND-B until we realize that both inputs are the same function. As such, we would only need one nand to construct it, and one more to nand it to itself, for a total of two nands.

When converting these to tasks in Avida, we note the symmertry between A-OR-NOT-B and B-OR-NOT-A and create a single "or not" task called ORN.

We have now found 11 of the 16 possible operations. The last 5 will arise by repeating this process. For each of them we keep track of the fewest nands we can build it with.

The final five are: A-AND-NOT-B and B-AND-NOT-A (combined into ANDN) costing 3 nands, A-NOR-B , A-XOR-B, and A-EQU-B.

2-Input Logic Operations
No-NAND Operations One-NAND operations Two-NAND operations Three-NAND operations Four-NAND operations Five NAND op.
Input A  Input B  ALL-ZERO  ALL-ONE  NOT-A  NOT-B  NAND  A-OR-NOT-B  B-OR-NOT-A AND A-AND-NOT-B B-AND-NOT-A OR NOR XOR EQU
0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 1
0 1 0 1 1 0 1 0 1 0 0 1 1 0 1 0
1 0 0 1 0 1 1 1 0 0 1 0 1 0 1 0
1 1 0 1 0 0 0 1 1 1 0 0 1 0 0 1


This entire process can easily scale up to three-input or higher logic functions, but by that point you'd probably want to automate the process. When you move to three inputs, you have 8 combinations of inputs (2^3). Each of these combinations comes out to a zero or one for any specific logic function. This means that there are 2^8 = 256 unique logic functions. When we remove symmetries (given that inputs can come in in any order), we only get 68 new logic operations out of this.