Exotic Logics

William Clifford mr.william.clifford at gmail.com
Wed Jun 17 07:46:14 CEST 2009


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?"
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"""

    @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



More information about the Python-list mailing list