proc nand {A B} {expr {!($A && $B)}} # The only unary operator NOT can be written in terms of nand: proc not {A} {nand $A $A} # .. and everything else can be built from them too: proc and {A B} {not [nand $A $B]} proc or {A B} {nand [not $A] [not $B]} proc nor {A B} {not [or $A $B]} proc eq {A B} {or [and $A $B] [nor $A $B]} proc ne {A B} {nor [and $A $B] [nor $A $B]} if 0 { Here's some testing tools - to see whether an implementation is correct, look at its truth table, here done as the four results for A,B combinations 0,0 0,1 1,0 1,1 - side note how easily procs can be passed in: } proc truthtable f { set res {} foreach A {0 1} { foreach B {0 1} { lappend res [$f $A $B] } } set res } # Test: catch {console show} puts "nand: [truthtable nand]" if 0 { % truthtable and 0 0 0 1 % truthtable nand 1 1 1 0 % truthtable or 0 1 1 1 % truthtable nor 1 0 0 0 % truthtable eq 1 0 0 1 To see how efficient the implementation is (in terms of NAND units used), try this, which relies on the fact that Boolean functions contain no lowercase letters apart from the operator names: } proc nandcount f { regsub -all {[^a-z]} [info body $f] " " list set nums [string map {nand 1 not 1 and 2 nor 4 or 3 eq 6} $list] expr [join $nums +] }A very different idea, having nothing to do with NAND as elementary function, but I like it because it "implements" Boolean functions very intuitively, by just giving their truth table for look-up at runtime:
proc booleanFunction {truthtable a b} { lindex $truthtable [expr {!!$a+!!$a+!!$b}]} interp alias {} and {} booleanFunction {0 0 0 1} interp alias {} or {} booleanFunction {0 1 1 1} interp alias {} nand {} booleanFunction {1 1 1 0}!! is a cute little Booleanizer (thanks KPV on Toggling a Boolean variable!)
TV: Always good to have a page on the thing that can be proven to be a basic building block of pretty much the whole universe of computers! For digital designers with some historical perspective (and sense), NANDs are pieces of electronics that have in minimal form 3 pins each, and are represented by 'iron' symbols, where the output has an extra circle, which indicates it is not an AND but a NAND (with inverted output). Inverters are more fun, because one cannot construct something inverting with gates that do not invert. Otherwise, mathematically one can construct ANY logical function from ANY logical building blocks that has two inputs and inverts and does something like an and or or function.From Texas Instruments datasheet:
Not only can NAND be used to construct all truth functions, it can also be taken as the sole logical connective in an axiomatization of the propositional calculus. [Mendelson, ISBN 0-534-06624-0], following [J.G. Nicod: A reduction in the number of primitive propositions in logic, Proc. Camb. Phil. Soc. 19 (1917), 32–41] and denoting NAND by |, give the interference rule
A, A|(B|C) ⊢ C(cf. modus ponens, which would be A, A⇒B ⊢ B in the same notation) and the axiom schema
(A|(B|C))|((D|(D|D))|((E|B)|((A|E)|(A|E))))as being sufficient for deriving any tautology.As an example of this, the easiest instance of that axiom schema is the one where all occurrencies of formula variables (A–E) are set to the same logical variable x:
(x|(x|x))|((x|(x|x))|((x|x)|((x|x)|(x|x))))The easy way to compute that is to use string map:
string map {A x B x C x D x E x} (A|(B|C))|((D|(D|D))|((E|B)|((A|E)|(A|E))))In order to derive something from that formula of all x's, it is necessary to find another instance of the axiom schema which matches it well enough for the interference rule to apply. Since that all x's formula is the shortest of all axioms, it'll have to be the A in the interference rule. The axiom used as A|(B|C) must furthermore have exactly the all x's formula as the left operand of the outermost |, which forces values for variables A, B, and C in the schema; the possible axioms are thus by
string map {A (x|(x|x)) B (x|(x|x)) C ((x|x)|((x|x)|(x|x)))} (A|(B|C))|((D|(D|D))|((E|B)|((A|E)|(A|E))))computed to be on the form
((x|(x|x))|((x|(x|x))|((x|x)|((x|x)|(x|x)))))|((D|(D|D))|((E|(x|(x|x)))|(((x|(x|x))|E)|((x|(x|x))|E))))and the part there corresponding to C of the interference rule is
(E|(x|(x|x)))|(((x|(x|x))|E)|((x|(x|x))|E))so any formula on that form is thus a theorem of this propositional calculus, and thus a tautology.As usual with compact axiomatizations of a known theory however, it takes quite some work to find a sequence of axiom combinations that produce the theorems that express the usual laws of logic…
Reference edit
- Jon Awbrey
- various links to topics related to logic
Glossary edit
- Ampheck
- refers to either one of the NAND or NNOR operators
- logical graph
- one of the systems of graphical syntax developed by Charles Sanders Peirce
- minimal negation operator
- zeroth order logic
See Also edit
- Computer Architecture
- Boolean Logic
- a course proof on how any logical function can be constructed, also from NANDs
- Laws of Form
- shows a model of Boolean arithmetics with two operators, one of them being the empty string, however...
- A little proving engine
- Parsing Polish notation