This text is heavily based on the work of George Spencer-Brown Laws
of Form, but assumes that the reader is only familiar with the basics
of boolean logic, since a succint description of the laws and of the forms is
given.
Without restating the
entire book, we can understand the logic in a few basic terms : The basic unit
in this system is the mark,
, it has a dual nature,
order and structure, it is both
indicating a truth value (1), and acting as an operator (NOR). Embedding two
marks like this :
yields NOR(TRUE), which is false, and equivalent to "no
mark". The key to understand the system is to
turn any empty mark (a mark that doesn't have anything below its horizontal
line) into a true value, and all others as NOR gates on their
content (what is below a gate is contained by it). The notation is hierarchical, and theorems follow that agree with logic
as we know it in its various other forms
The basic initials of the calculus are
,
and
. (no mark), they are the basic steps we
can take toward reduction (or complexity, if taken in reverse), and theorems are
simple consequences of these equalities.
By the end of the book, GSB offers us a tentalizing peek
into his second-degrees equations, where time is a factor, and allows the
representation of logic values that are analogous to the imaginary values of
mathematics. Althought the examples are few, understanding them gives a glimpse
into properties of this logic left for the reader to ponder on, as the books ends
on these. This text is an attempt to give a few
more details about these procedures, and to try to expand a bit on the
construction of functional forms such as memories. Despite being, in my opinion,
one of the most interesting aspect of the laws of form, several details seem to be
left unresolved. It is unclear, for instance, what procedure should be adopted to compute
some of these equations, as different implementations (recursivity, temporal
synchronization of gates, parallel processing) are suceptible to produce different results. We will,
in this text, limit ourselves to small functions for which most implementations
would agree.
We will begin by a brief introduction into laws of forms, the
notation of the form, its relation to boolean logic, and its reduction via
inference.
The Boolean logic gates
| a |
b |
a o b |
| 0 |
0 |
v0 |
| 0 |
1 |
v1 |
| 1 |
0 |
v2 |
| 1 |
1 |
v3 |
Table 1: The list of possible input values and
the result of a given operator o, ie, for AND, v0=0, v1=0, v2=0,v3=1.
Given two input and one ouput, there are
16 (4 bits for v0 to v3) different ways to arrange our output depending on the input. Here is the list
of the corresponding operators, with their equivalent in the notation of Laws of
Form :
Table 2: The list of binary operators and their
form-equivalents.
Let us take for instance the form for the equality operator.
This operator should output 1 if and only if its input values are identical to
one another. If we wish to compute the truth table for the form, we can generate
four different forms, each with a different set of input values, and try to
reduce the expression using the initials of the calculus.
For instance, one of these forms will look like this (on the right are the steps
toward reduction) :
For a =
and b = .

The first simplification collapses
into nothing, the second step changes
into
, the third and fourth steps collapse again.
So for a = 1 and b = 0, we get 0.
Now that we see how this works, we can reduce the 3
remaining forms using multiple steps at once :
For a = 0, b = 0 :

= 1.
For a = 0, b = 1 :

= 0.
And for a = 1, b = 1 :

= 1
And so if we compare our results with the truth table, we see
that it agrees with our requirements (equality). Note that an equality
operator is also a NOT(XOR), which is how it is constructed here.
Here we have shown via enumeration that this form is that of the
equality operator. Some of the gates however lend themselves to literal
interpretation without enumeration. One instance is the form
,
which reads "a implies b". This form has only one mark. If we see that
if a is true, the mark for true will cancel out with the mark already present,
we realize that, literally, "if a, then b", by way of reduction : 
Logic circuitry
Second degree equations introduce the concept of time because they allow reentry into the form. One portion
of the form (not necessarily its output value) can be redirected to another
location of the form so as to allow spatial paradoxes. Such a classic form
is
, or simply
, which flickers in time,
alternating the values true and false, because
the result of a previous NOR is fed into that same NOR gate. These values are logical
equivalents of complex values in classical mathematics, they have no truth value per se
when considering the form in its entirety, however they do with respect to time.
At one time t, the system is in a definite state, even if that state changes at
time t+1. Re-entering into the form introduces computation, using the form, of a sort of infinite series
of boolean values. Infinite, here, is only limited to what ammount of effort (time) we wish to put
into the calculation. To represent these reentries, the standard notation of the
forms introduces marks under the form that indicate the rentry, these marks are
not truth values or NOR operators, they simply indicates the path a value at
this subspace of the expression takes as it is reentering the expression at
another location. With many reentries, this can become
cumbersome, and so a new notation is introduced.
To quote GSB, "Let what is under the marker be seen to be
so by lines of connection called leads, thus.
. Let the value indicated by the marker be led from the marker by a lead, which
may, in the expression, divide to be entered under other markers. Now, for
example, the expression
can
be represented thus :
"
Note that this is another way of building an equality gate. The form in our table is simpler and can be reached
from this one using inference.
We can follow the logic within the circuit by flipping truth
values at each marker, to do this we identify the input leads, where the
variables are located, and we propagate these values thru the markers, flipping
marked and unmarked state as necessary. In GSB's example, the flow will look
like this :

The blue arrows show the propagation of truth and false values
within the system. Nothing can go backward (yet). The rule is to go from the
variables to the marks, and continue on the other side of the mark, or in other
words: follow the leads.
So given we have some definite values for a and b, we can follow
the logic of the gate directly on the circuit :

Here is now our table representing each operator in the form of
a logic circuit :
Table 3: The list of binary operators and their
form-equivalents in standard and schematics notations.
Note that both TRUE and FALSE operators have no connectivity
with the variables, but have a lose input on one end and the output on the other
(they are obviously reversible spatially). That they are not connected with variables is a
consequence of our listing the simplified forms
of the logic circuits. If we had wished so, we could have used the values of both
a and b in a gate that outputs only 0 or only 1. For instance,
,
or
always yields 1, and obviously,
always yields 0. Thus we can construct a two variables gate that always yields 1:
or always yields 0 :
, but these are arbitrarily complex gates as many more equivalent but formally
distinct structures exist. Much in the same way, we can construct a gate that
always return b by using the form
,
and substituting a for the form of the TRUE operator we previously constructed;
thus we obtain
, which always
returns b.
Special attention needs to be given to the XOR and == gates, as,
for simplification of the circuit, two pairs of variables are used, and the output value is
available at the center of the circuit instead of as a lose end.
Second degree functions and remembering
We can now represent our function
thus :
. The value at the
output of the only marker in the system will flicker in time. Assuming we were
to start with f being in an unmarked state (some arbitrary value needs to be
chosen, and unmarked seems more appropriate than marked), then at t0, the
available output would be 1, marked (NOR(0)), and at time t1, the value would
turn into 0, unmarked (NOR(1)), and this would continue to oscillate until we no longer wish
to perform the computation. We will call that value i : 
These considerations allow for a special kind of forms, the
above form is an oscilator, one way to look at it is to say that it counts.
Other recursive forms are able to remember.
The most primitive of such forms is
, which, in circuitry, is translated thus :
.
To see how this form remembers, we need to look a bit deeper into
its structure.
There are only 4 cases, either both a and b are true or false,
or either a or b is true and the other is false, so we have the following
possible forms :

For each step, we write before the gate the value of its inputs,
and after it, the value of its output, just like we did earlier with simple linear
forms. This time, however,
the function is re-entrant, our gates will be activated more than once; for each
new activation of the gate, we insert a carriage return. The first value is from
the topmost lead, the second from the lead directly under it. The outlined
values in the schematics above are the values of i.
We can make a few observations :
- b=0 is a condition for charging the content of i (outlined in the circuits above),
the other condition is a=1.
- when b = 1, i=0, whatever the value of a. Thus,
b=1 discharges the content of i.
- When i is charged it is propagated circularly through two NOR gates
and fed back to itself so as to maintain the charge,
but only so long as b = 0, because b = 0 is a condition for keeping i
charged.
- a = 0 AND b = 0 will preserve the content of i indefinately, or
so long as the computation is maintained.
Thus, we have a one bit memory cell, with a reset switch :
, its output value is the answer to the question "have you been set yet
?", and it forgets the answer each time it is reset.
Remembering Undefined States
This is all and well if you know what the value you wish to
remember is: you could encode TRUE as set=1, reset=0, and FALSE as set=0,
reset=1, so that the output value of the memory after it has been set is the
value you wanted to encode. But if what you wish to remember is a variable whose truth value is
either not known or variable, this is not sufficient.
What we wish now is to
make a form that remembers what the state of one of its input variable was at
some point in the past.
We can do this by creating a secondary form which will control
the basic memory unit in such a way that two input values will be fed : the
value we wish to remember, which we will call 'a', and a variable (called 'set')
which, when it is 1, tells the memory unit
to remember the value of a. From this secondary form, two output values will be generated, one will
feed the set variable of our previous memory form, and the other will control
its reset
variable.
The truth table we want is this :
| set |
a |
o1 |
o2 |
| 0 |
0 |
0 |
0 |
| 0 |
1 |
0 |
0 |
| 1 |
0 |
* |
1 |
| 1 |
1 |
1 |
0 |
Which, in english, means the following :
- if set=0, we want a passive action on the
memory, so we want o1=o2=0
- if set=1, there are two solutions :
- if a=0, we want
o2=1 (memory unit reset), but the value of o1 is inconsequent because of the
structure of our memory cell (see above).
- if a=1, we want o2=0 (no memory
unit reset) and o1=1 (memory unit set).
We can accomplish this with the following form :

or, in schematics (note the contraction of both NOR(set) into
one by dividing the leads) :

We can verify that our "control unit" performs as desired by
checking its truth values as they propagates in the circuit :

We can now link both units, so that if set=1, the value of a is
recorded in the memory cell and is available at its output. If set=0, the memory retains the last value of a when
set was equal to 1 for the last time :

Which we can rewrite in standard notation thus:
memory[a, set] = 
--
10/10/2002 - Updated 13/10 - Click reload for last version
Bonus
Here is a small tool which will let
you enter two-variables forms and reduce them into one of the sixteen boolean
operators. It does not support reentry (obviously, or it would not always reduce
to one of the sixteen boolean operators, heh). The syntax to use it is simple
(if cumbursome) : parenthesis denote the mark : ( ) , a and b denote the two
input variables of the form.
A few examples :
= ( )
= (( ))
= ( ) ( )
=
(((ab)a)((ab)b))
q = quit :-)
The program will output the four sequences of reductions, one
step at a time, and you will see things like (1), which really is the same as ((
)), in fact, you can even put 1 in your expression in place of an empty mark.
--
Reentry and ascii
On ways to represent reentry using limited printing capabilities
(for emails, or console programs for instance), the simplest way seems to be the
usage of placeholder names for leads inside the equation. Writing the form
graphically, we can represent the source in bold, and the destination(s) in
normal font. When writing in ascii, we can enclose the source in quotes.
memory[a, set] =
=
. =
((((a)(set))x)(((a)(set))(set)))"x"
B
A C K