0

This is a class which will take in as input and then output a polynomial in string form (both ways same format). Some arithmetic is performed in the various methods. I've been trying to inherit this class into another class that will then use the __mod__() special method of the first class (or make it's own special method if necessary but I don't see how you can't just use the original method) to perform the mod on intake. Seems like this goes into __init__() but I've tried 5 different versions of this, even going so far as to change the parent class, and I'm getting nowhere. I'm teaching myself Python so I'm sure that even a junior Python dev can see where I'm going totally wrong.

import re

class GF2Polynomial(object): #classes should generally inherit from object

    def __init__(self, string):
        '''__init__ is a standard special method used to initialize objects.
        Here __init__ will initialize a gf2infix object based on a string.'''
        self.string = string  #basically the initial string (polynomial)
        self.key,self.lst = self.parsePolyVariable(string) # key determines polynomial compatibility
        self.bin = self.prepBinary(string)  #main value used in operations

    def id(self,lst):
        """returns modulus 2 (1,0,0,1,1,....) for input lists"""
        return [int(lst[i])%2 for i in range(len(lst))]

    def listToInt(self,lst):
        """converts list to integer for later use"""
        result = self.id(lst)
        return int(''.join(map(str,result)))

    def parsePolyToListInput(self,poly):
        """
        replaced by parsePolyVariable. still functional but not needed.
        performs regex on raw string and converts to list
        """
        c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)]
        return [1 if x in c else 0  for x in xrange(max(c), -1, -1)]

    def parsePolyVariable(self,poly):
        """
        performs regex on raw string, converts to list.
        also determines key (main variable used) in each polynomial on intake
        """
        c = [int(m.group(0)) for m in re.finditer(r'\d+', poly)] #re.finditer returns an iterator
        letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]
        m = max(c); varmatch = True; key = letter[0]
        for i in range(len(letter)):
            if letter[i] != key: varmatch = False
            else: varmatch = True
        if varmatch == False: return "error: not all variables in %s are the same"%a
        d = [1 if x in c else (1 if x==0 else (1 if x=='x' else 0))  for x in xrange(m, -1, -1)]
        return key,d

    def polyVariableCheck(self,other):
        return self.key == other.key

    def prepBinary(self,poly):
        """converts to base 2; bina,binb are binary values like 110100101100....."""
        x = self.lst; a = self.listToInt(x)
        return int(str(a),2)

    def __mod__(self,other):
        """
        __mod__ is the special method for overriding the % operator
        returns remainder formatted as polynomial
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        if self.bin == other.bin: return 0
        return GF2Polynomial(self.outFormat(self.bin%other.bin))

    def __str__(self):
        return self.string

    def outFormat(self,raw):
        """process resulting values into polynomial format"""
        raw = "{0:b}".format(raw); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration
        g = [i for i,c in enumerate(raw) if c == '1']
        processed = "x**"+" + x**".join(map(str, g[::-1]))
        proc1 = processed.replace("x**1","x"); proc2 = proc1.replace("x**0","1")
        if len(g) == 0: return 0 #return 0 if list empty
        return proc2  #returns result in gf(2) polynomial form

The desired result is to be able to call it on a new (child) class with the parent type and while changing the parent class as little as possible (if even at all). Note that class "BinaryField" is the intended child class:

p=GF2Polynomial("x**2+x**1+x**0")
a=BinaryField("x**1+x**0", p)
b=BinaryField("x**1", p)

On intake, the given polynomial should be modulus divided by the 2nd element (here it's 'p'). This is necessary for finite field math.

EDIT: when running it with --

## "x**1 + x**0" polynomial string style input
poly1 = "x**14 + x**1 + x**0"; poly2 = "x**6 + x**2 + x**1"; poly3 = "y**6 + y**2 + y**1"
a = GF2Polynomial(poly1); b = GF2Polynomial(poly2); c = GF2Polynomial(poly3)
## "x+1" polynomial string style input
poly4 = "x**14 + x + 1"; poly5 = "x**6 + x**2 + x"; poly6 = "y**6 + y**2 + 1"
d = GF2Polynomial(poly4); e = GF2Polynomial(poly5); f = GF2Polynomial(poly6)
bf1 = BinaryField(poly1,b); print bf1
bf2 = BinaryField(poly4,e); print bf2

Both of these styles are possible because of the way I coded it, but they should both return the same answer. However the result on that code is:

>>> 
x**5 + x**4 + x**3 + 1
x**5 + x

Also, when using BinaryField(poly4,d), which is just the same string with it's GF2Polynomial() initialization, this errors as: AttributeError: 'int' object has no attribute 'string'

stackuser
  • 869
  • 16
  • 34

1 Answers1

1

Does this solves your problem?

class BinaryField(GF2Polynomial):
    def __init__(self, string, mod):
        modded = GF2Polynomial(string) % mod
        super(BinaryField, self).__init__(modded.string)


>>> p = GF2Polynomial("x**2+x**1+x**0")
>>> a = BinaryField("x**1+x**0", p)
>>> print a
x + 1

You can also make the BinaryField class to be just a factory method:

def BinaryField(string, mod):
    return GF2Polynomial(string) % mod
Viktor Kerkez
  • 45,070
  • 12
  • 104
  • 85
  • i ran that class with `a = GF2Polynomial(poly1); aa = BinaryField(poly1,a); print aa` and it gives the error: ` AttributeError: 'int' object has no attribute 'string' ` on the last line of \__init__() – stackuser Aug 09 '13 at 23:53
  • Fixed it, had and extra self. – Viktor Kerkez Aug 10 '13 at 00:01
  • edited the question to add the issue with that. the different style inputs are giving entirely different answers. check the edit. but +1 because that's helpful so far. – stackuser Aug 10 '13 at 00:29
  • Ok so the first problem I see is that the `__mod__` function returns two different data types. It returns an `int` in some cases and a `GF2Polynomial` in other cases. To make it work in all cases you should change it to always return a `GF2Polynomial`. `GF2Polynomial('0')` also doesn't work. You should modify the class to always return a `GF2Polynomial` for every operation, that will ensure that you have a complete encapsulation which will enable the subclassing to work as you desired. – Viktor Kerkez Aug 10 '13 at 00:48
  • i see what you're saying. the "x**1 + x**0" format seems to be taking all the part of that string parameter and there could be something in `parsePolyVariable()` about the "x+1" format. not sure how to fix the conditional about "0" input ("1" and "x" also crash it). i'm wondering if there's some way to format the 0 or 1 or x as GF2Polynomial() output. anyhow, your code solved my original question, and taught me a few things i definitely need to learn more about, thanks a lot. – stackuser Aug 10 '13 at 01:10