import itertools
import operator
class Logic():
"""class of generic logic operators"""
@staticmethod
def lsd(rdx, n):
"""yield up base rdx digits of n in least significant order"""
while n > 0:
q, r = divmod(n, rdx)
n = q
yield r
@staticmethod
def rdxn(rdx, seq):
"""reduce a sequence of numbers by powers of rdx"""
return reduce(operator.add,
map(operator.mul,
seq, (pow(rdx, i) for i in range(len(seq)))))
@staticmethod
def pute(rdx, opr, arg):
"""a logical primitive which returns 0 or 1."""
if arg < 0:
return 0
o = tuple(lsd(rdx, opr))
try:
return o[arg]
except IndexError:
return 0
@staticmethod
def make_puter(rdx, opr):
"""return a function based on pute."""
o = tuple(Logic.lsd(rdx, opr))
def puter(arg):
if arg < 0:
return 0
try:
return o[arg]
except IndexError:
return 0
return puter
@staticmethod
def make_inputs(rdx, *args):
"""yield a stripe of rdxn digits from args."""
largs = [Logic.lsd(rdx, a) for a in args]
for i in itertools.izip_longest(*largs, fillvalue=0):
yield Logic.rdxn(rdx, i)
@staticmethod
def compute(rdx, opr, *args):
"""return a number computed from opr of rdx."""
puter = Logic.make_puter(rdx, opr)
inputs = Logic.make_inputs(rdx, *args)
outputs = [puter(i) for i in inputs]
return Logic.rdxn(rdx, outputs)
@staticmethod
def make_computer(rdx, opr):
"""return a computer of opr, rdx."""
def computer(*args):
puter = Logic.make_puter(rdx, opr)
inputs = Logic.make_inputs(rdx, *args)
outputs = [puter(i) for i in inputs]
return Logic.rdxn(rdx, outputs)
return computer
def __init__(self, rdx, opr):
self._computer = Logic.make_computer(rdx, opr)
def __call__(self, *args):
return self._computer(*args)
This seemed to be working for the limited tests I did on it, while I
was doing them. The following checked out last time I tried:
>>> and_ = Logic(2, 8)
>>> or_ = Logic(2, 14)
>>> xor = Logic(2, 6)
I have no idea how to validate the results of the trinary and beyond
logics.
Thanks for reading and trying this out. Corrections? Criticism?
Comments?
--
William Clifford
> I was staring at a logic table the other day, and I asked myself, "what
> if one wanted to play with exotic logics; how might one do it?"
First question: what's an exotic logics?
Do you mean things like three-value logic, fuzzy logic, probabilistic
reasoning, etc?
Or do you mean logical operators others than and, or, xor, nand, nor, etc?
Or both? Something else?
> I did
> some searching but not being too sure of what to look for and carried
> away with my own enthusiasm for the idea, I didn't find much. What I've
> come up with is, no doubt, inefficient, naive, poor python style, and
> probably wrong in fundamental ways too subtle for me, but here it is:
>
> import itertools
> import operator
>
> class Logic():
> """class of generic logic operators"""
[...]
If (nearly) all your methods are static methods, chances are a class is
the wrong solution. Why not just define the static methods as top-level
functions?
> This seemed to be working for the limited tests I did on it, while I was
> doing them. The following checked out last time I tried:
>
>>>> and_ = Logic(2, 8)
>>>> or_ = Logic(2, 14)
>>>> xor = Logic(2, 6)
>
> I have no idea how to validate the results of the trinary and beyond
> logics.
The same way you would validate and_, or_ and xor: to validate something,
you need to know what the correct answer is, then compare the answer you
get with the answer you should get. For a binary operator and binary
operands, you can exhaustively check every valid input:
flag1 op flag2
there are four combinations of input flags:
0 op 0
0 op 1
1 op 0
1 op 1
For three-valued logic, there are 9 combinations. For four-valued, 16. So
exhaustively testing all the possible inputs is quite simple.
As far as getting the correct answers, you have to decide which three-
valued logic(s) you want to use, then go look them up. Or just make them
up yourself!
E.g. given trinary flags 0, 1, 2, (say), you might want the operators to
give the same results with 0, 1 as they would if you were applying it to
binary flags 0, 1. E.g.:
# binary operands
0 and 0 => 0
0 and 1 => 0
1 and 0 => 0
1 and 1 => 1
# trinary operands
0 and 0 => 0
0 and 1 => 0
0 and 2 => ? # probably 0
1 and 0 => 0
1 and 1 => 1
1 and 2 => ? # could be 0, or maybe 1
2 and 0 => ? # probably 0
2 and 1 => ? # 0 or 1
2 and 2 => ? # probably 2
Different choices lead to different versions of ternary logic.
> Thanks for reading and trying this out. Corrections? Criticism?
> Comments?
You're implementation seems rather confusing. I think that's partly
because you use lots of abbreviated jargon terms that mean little or
nothing to me: rdx, opr (operator?), lsd, pute.
--
Steven
> I was staring at a logic table the other day, and I asked myself, "what
> if one wanted to play with exotic logics; how might one do it?"
This might be useful for you, and if not useful, at least it might blow
your mind like it did mine.
(This is not original to me -- I didn't create it. However, I can't find
the original source.)
Imagine for a moment that there are no boolean values.
There are no numbers. They were never invented.
There are no classes.
There are no objects.
There are only functions.
Could you define functions that act like boolean values? And could you
define other functions to operate on them?
def true(x, y):
return x
def false(x, y):
return y
def print_bool(b):
print b("true", "false")
print_bool(true)
print_bool(false)
def Not(b):
def not_b(x, y):
return b(y, x)
return not_b
print_bool(Not(true))
print_bool(Not(false))
print_bool(Not(Not(true)))
def And(a, b):
return a(b, a)
def Or(a, b):
return a(a, b)
print_bool(And(true, true))
print_bool(And(true, false))
print_bool(Or(false, true))
print_bool(Or(false, false))
--
Steven
String isn't considered object?
Also, b/true()/false() is a function object, isn't it? Unless function
is first-class, you can't pass them around like that, since you need a
function pointer (a.k.a number); but if function is first-class then
there it is an object.
I think high and low /voltages/, though continuous and approximate,
might satisfy this.
There are no such things as electrons, only variations in density of
the luminiferous ether.
You (OP) may be interested in the definitions of the fuzzy operators:
and( x, y ) := min( x, y )
or( x, y ) := max( x, y )
not( x ) := 1 (one)- x
nand( x, y ) := not( and( x, y ) ) = 1- min( x, y )
Defining 'xor' as '( x or y ) and ( not( x and y ) )', we have:
xor( x, y ) := min( max( x, y ), 1- min( x, y ) )
However, defining 'xor' as '( x and not y ) or ( y and not x )', we
don't have:
xor( x, y ) := max( min( x, 1- y ), min( y, 1-x ) )
Good question.
What Steven was doing was implementing some of the more basic stuff
from Lambda calculus in python. If you're implementing a different
system in an existing language, you'll need to use _some_ facilities
of the original language to interface with the outside world. Anyway,
here's a sample interactive session I just tried:
>>> def a(stuff):
... print stuff
...
>>> def b(stuff):
... stuff("abc")
...
>>> b(a)
abc
functions are first-class citizens in python.
Corollary:
xor1( x, y ) === xor2( x, y ).
Non-exhaustive demonstration, excerpt:
>>> def xor1( x, y ):
... return min( max( x, y ), 1- min( x, y ) )
...
>>> def xor2( x, y ):
... return max( min( x, 1- y ), min( y, 1- x ) )
...
>>> for i in range( 0, 11, 2 ):
... for j in range( 0, 11, 2 ):
... print i, j, xor2( x, y )*10, ' ',
... print
0 0 0.0 0 2 2.0 0 4 4.0 0 6 6.0 0 8 8.0
2 0 2.0 2 2 2.0 2 4 4.0 2 6 6.0 2 8 8.0
4 0 4.0 4 2 4.0 4 4 4.0 4 6 6.0 4 8 6.0
6 0 6.0 6 2 6.0 6 4 6.0 6 6 4.0 6 8 4.0
8 0 8.0 8 2 8.0 8 4 6.0 8 6 4.0 8 8 2.0
10 0 10.0 10 2 8.0 10 4 6.0 10 6 4.0 10 8 2.0
They appear to be equal.
I forgot to mention, fuzzy values take on values from the continuous
open or closed range 0 to 1.
I've got a Tesla coil if you'd like to meet some electrons personally.
Sir! Entropy levels are approaching dangerously low levels. We don't
even have enough entropy to fi
The Wall Street Journal ran an article about Asian pleasure markets;
they provide a-- quote-- "perfectly reasonable professional option".
For shame, Lieutenant. Always cite your source.
http://online.wsj.com/article/SB124416693109987685.html
Last paragraph, second to last sentence. It was a book review of _The
East, the West, and Sex_ by Richard Bernstein .
The short answer is 'yes'.
Obviously, I don't know much about this stuff. I was looking a table
of different
operators and their truth values and saw that these were just
different ways of
reading and comparing numbers. I wrote this code to explore this idea
in a
general sense and see where it leads and learn something about
computers.
> [...]
>
> If (nearly) all your methods are static methods, chances are a class is
> the wrong solution. Why not just define the static methods as top-level
> functions?
That is exactly how they started. I wrapped them up in an class
because I
thought I might want to create a bunch of them for testing and
experimentation. I'm curious to see how combinations of functions give
the
same (or different) results. I've read one can do all of the 16
binary
operations with clever uses of NAND or NOR.
[SNIP]
> You're implementation seems rather confusing. I think that's partly
> because you use lots of abbreviated jargon terms that mean little or
> nothing to me: rdx, opr (operator?), lsd, pute.
Sorry about the confusion. It's because I'm confused. I should check
out a book on the subject. Thanks for your help.
--
William Clifford
> same (or different) results. I've read one can do all of the 16
> binary
> operations with clever uses of NAND or NOR.
The book Laws of Form, by Spencer-Brown' is based on that observation,
with nand/nor expanded to n-ary 'bag' functions (like sum() is).
I recommend it, especially if you can find it in a library.
tjr
I've just reread my sentence, and even I wouldn't have understood (or
would misunderstood) what I was talking about if it was worded like that.
What I meant was: if you can pass a function as an argument to another
function, that means either: 1) you must use function pointer (numbers)
or 2) function is a first-class object. Both violates the restriction
(no number and no object respectively).
Even after abandoning the semantics of functions in python, going to
function as in purely mathematical sense, I still am not convinced
(warning: I don't know lambda calculus, although I program in heavily
functional style).
PS: the string comment was meant to be a joke...
> pdpi wrote:
> > On Jun 17, 5:37 pm, Lie Ryan <lie.1...@gmail.com> wrote:
> >> Steven D'Aprano wrote:
> >>> On Tue, 16 Jun 2009 22:46:14 -0700, William Clifford wrote:
> >>>> I was staring at a logic table the other day, and I asked myself, "what
> >>>> if one wanted to play with exotic logics; how might one do it?"
> >>> This might be useful for you, and if not useful, at least it might blow
> >>> your mind like it did mine.
> >>> (This is not original to me -- I didn't create it. However, I can't find
> >>> the original source.)
> >>> Imagine for a moment that there are no boolean values.
> >>> There are no numbers. They were never invented.
> >>> There are no classes.
> >>> There are no objects.
> >>> There are only functions.
> >>> Could you define functions that act like boolean values? And could you
> >>> define other functions to operate on them?
> >>> [basic lambda calculus definitions]
[...]
> What I meant was: if you can pass a function as an argument to another
> function, that means either: 1) you must use function pointer (numbers)
> or 2) function is a first-class object. Both violates the restriction
> (no number and no object respectively).
>
> Even after abandoning the semantics of functions in python, going to
> function as in purely mathematical sense, I still am not convinced
> (warning: I don't know lambda calculus, although I program in heavily
> functional style).
You are confusing semantics with implementation. At some point, of course one
would need to use real object (at the lowest level, the computer I'm typing this
in is a physical object). But the interesting part is that you can define the
whole logic system using nothing but functions. You may need to implement it
using objects, or maybe you could devise a machine that will behave like that
using only sticks on the floor, but that doesn't matter. From the user's
perspective, there would be only functions: no strings, no objects, no numbers.
That reminds me of my last class (disclaimer: I teach discrete math). I told my
students "well, let's assume that numbers exist", and I wasn't making fun of
them... I found that topic easier to understand (computability, primitive
recursion) if one ignores the numbers, even if one obviously has to write them
somewhere at some point.
--
Luis Zarrabeitia
Facultad de Matem�tica y Computaci�n, UH
http://profesores.matcom.uh.cu/~kyrie
--
Participe en Universidad 2010, del 8 al 12 de febrero de 2010
La Habana, Cuba
http://www.universidad2010.cu
>> Imagine for a moment that there are no boolean values. There are no
>> numbers. They were never invented. There are no classes.
>> There are no objects.
>> There are only functions.
>>
>> Could you define functions that act like boolean values? And could you
>> define other functions to operate on them?
...
> String isn't considered object?
<handwave/>
Given that the strings only exist inside one function specifically for
printing, I think we can ignore that. If you prefer, print_bool() could
look at the function names, that would work just as well. One way or the
other, we have to get human-readable names into the system *somehow*.
> Also, b/true()/false() is a function object, isn't it? Unless function
> is first-class, you can't pass them around like that, since you need a
> function pointer (a.k.a number); but if function is first-class then
> there it is an object.
That's an implementation detail. So long as you can pass around
functions, and return them, then it doesn't matter whether they are
implemented as objects or not.
--
Steven
That is correct. In fact semiconductor logic is done using these two
principle gates. See http://en.wikipedia.org/wiki/NAND_logic . Quite
interesting really.
As your reference correctly points out, "However, contrary to popular
belief, modern integrated circuits
<http://en.wikipedia.org/wiki/Integrated_circuit> are not constructed
exclusively from a single type of gate"