Python - 使用现有类方法的特殊方法算法

时间:2013-07-13 19:42:47

标签: python operator-overloading overloading polynomial-math s-expression

该类采用有限域多项式字符串,对其进行解析,操作(+ - * /%),然后以与输入相同的格式输出。它工作正常(到目前为止)。但是,现在我正在尝试在算术运算符上实现特殊方法,并且我无法将其简单地连接到字符串。通常,我们的想法是将输入初始化为类实例,但在这种情况下,输入上有一个正则表达式似乎使任何尝试都这样做变得复杂。我正在自学Python,所以这对我来说是一部恐怖电影,但可能只是一个经验丰富的Python程序员的玩具。

这些似乎有很多信息,但我不确定他们在这种情况下有多大帮助:

http://stackoverflow.com/questions/10842166/programmatically-create-arithmetic-special-methods-in-python-aka-factory-funct
http://rosettacode.org/wiki/S-Expressions
http://www.greenteapress.com/thinkpython/thinkCSpy/html/chap14.html
http://docs.cython.org/src/userguide/special_methods.html

以下是我正在使用的课程和示例:

import re

class gf2pim:

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):
    """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 prepBinary(self,x,y):
    """converts to base 2; bina,binb are binary values like 110100101100....."""
    x = self.parsePolyToListInput(x); y = self.parsePolyToListInput(y)
    a = self.listToInt(x); b = self.listToInt(y)
    bina = int(str(a),2); binb = int(str(b),2)
    return bina,binb  #

def add(self,a,b):
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns binary string"""
    bina,binb = self.prepBinary(a,b)
    return self.outFormat(bina^binb)

def subtract(self,x,y):
    """same as addition in GF(2)"""
    return self.add(x,y)

def quotient(self,a,b):
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns quotient formatted as polynomial"""
    a,b = self.prepBinary(a,b)
    return self.outFormat(a/b)

def remainder(self,a,b):
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns remainder formatted as polynomial"""
    a,b = self.prepBinary(a,b)
    return self.outFormat(a%b)

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]))
    if len(g) == 0: return 0 #return 0 if list empty
    return processed  #returns result in gf(2) polynomial form

def __add__(self,other):
    return gf2pim.add(self,other)

底部的最后一个示例显示了问题:

obj = gf2pim()
a = "x**14 + x**1 + x**0"; b = "x**6 + x**2 + x**1"
c = "x**2 + x**1 + x**0"; d = "x**3 + x**1 + x**0"
e = "x**3 + x**2 + x**1 + x**0"; f = "x**2"; g = "x**1 + x**0"; h = "x**3 + x**2 + x**0"
p = "x**13 + x**1 + x**0"; q = "x**12 + x**1"; j = "x**4 + x**3 + x**1 + x**0"
print "add: [%s] + [%s]  =  %s "%(a,b,obj.add(a,b))
print "add: [%s] + [%s]  =  %s "%(c,d,obj.add(c,d))
print "quotient (max(a,b)/min(a,b): [%s] / [%s]  =  %s "%(a,b,obj.quotient(a,b))
print "remainder (max(a,b) mod min(a,b)): [%s] mod [%s]  =  %s "%(a,b,obj.remainder(a,b))
print "quotient (max(a,b)/min(a,b): [%s] / [%s]  =  %s "%(c,d,obj.quotient(c,d))
print "remainder (max(a,b) mod min(a,b): [%s] mod [%s]  =  %s "%(c,d,obj.remainder(c,d))
print "quotient (max(a,b)/min(a,b): [%s] / [%s]  =  %s "%(q,q,obj.quotient(q,q))
print "remainder (max(a,b) mod min(a,b): [%s] mod [%s]  =  %s "%(q,q,obj.remainder(q,q))
print "modular_inverse: [%s] * [%s] mod [%s] = 1  [%s]"%(p,valuemi2[0],q,valuemi2[1])
sum1 = obj.add(a,b); quotient1 = obj.quotient(sum1,c)

### HERE THE PROBLEM IS CLEAR
print "[(a+b)/c] = ",quotient1
smadd1 = a+b
print "smadd1   ",smadd1

输出:

>>> 
add: [x**14 + x**1 + x**0] + [x**6 + x**2 + x**1]  =  x**14 + x**6 + x**2 + x**0 
add: [x**2 + x**1 + x**0] + [x**3 + x**1 + x**0]  =  x**3 + x**2 
quotient (max(a,b)/min(a,b): [x**14 + x**1 + x**0] / [x**6 + x**2 + x**1]  =  x**7 + x**6 + x**5 + x**3 + x**1 
remainder (max(a,b) mod min(a,b)): [x**14 + x**1 + x**0] mod [x**6 + x**2 + x**1]  =  x**2 + x**1 + x**0 
quotient (max(a,b)/min(a,b): [x**2 + x**1 + x**0] / [x**3 + x**1 + x**0]  =  0 
remainder (max(a,b) mod min(a,b): [x**2 + x**1 + x**0] mod [x**3 + x**1 + x**0]  =  x**2 + x**1 + x**0 
quotient (max(a,b)/min(a,b): [x**12 + x**1] / [x**12 + x**1]  =  x**0 
remainder (max(a,b) mod min(a,b): [x**12 + x**1] mod [x**12 + x**1]  =  0 
[(a+b)/c]*d =  x**14 + x**12 + x**9 + x**1
smadd1    x**14 + x**1 + x**0x**6 + x**2 + x**1
>>> 

正如您在smadd1看到的那样,我需要使用+添加这两个而不仅仅是连接。此外,我想知道在这种情况下是否需要使用S表达式树。

编辑:

Multiply()正在运行但现在不是:

def __mul__(self,other):
    """
    __multiply__ is the special method for overriding the - operator
    returns product of 2 polynomials in gf2; self,other are values 10110011...
    """
    self = int(str(self),2)
    bitsa = reversed("{0:b}".format(self))
    g = [(other<<i)*int(bit) for i,bit in enumerate(bitsa)]
    return gf2infix(self.outFormat(reduce(lambda x,y: x^y,g)))

它的原始形式是:

def multiply(self,a,b):
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0... ; returns product of 2 polynomials in gf2"""
    a = self.prepBinary(a); b = self.prepBinary(b)
    bitsa = reversed("{0:b}".format(a))
    g = [(b<<i)*int(bit) for i,bit in enumerate(bitsa)]
    return self.outFormat(reduce(lambda x,y: x^y,g))

忽略multiply()的问题,我修复了它。更改的行是:

bitsa = reversed("{0:b}".format(self.bin))

之前的那条线被取出了。

1 个答案:

答案 0 :(得分:1)

看起来你混淆了两个概念:代表有限域多项式的字符串和类gf2pim的对象,它们也代表有限域多项式。您应该为要操作的每个多项式实例化一个gf2pim对象,并且对gf2pim对象的操作应该返回其他gf2pim对象。目前,您尝试在2个字符串上使用+运算符,这就是为什么不调用__add__方法的原因。您定义gf2pim类还有其他一些问题。我已经在下面重构了你的代码,虽然它仍然不完美。我也省略了分工方法,但我认为我所做的应该让你走上正轨。有关运算符重载的更多特殊方法名称,请参见本link的第3.4.8节。

import re
class gf2pim(object):#Your classes should generally inherit from object


    def __init__(self, binary):
        '''__init__ is a standard special method used to initialize objects.  Here __init__
        will initialize a gf2pim object based on a binary representation.'''
        self.bin = binary

    @classmethod
    def from_string(cls, string):
        return cls(cls._string_to_binary(string))

    def to_string(self):
        raw = "{0:b}".format(self.bin); 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]))
        if len(g) == 0: return 0 #return 0 if list empty
        return processed  #returns result in gf(2) polynomial form

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

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

    @classmethod
    def _string_to_list(cls, string):
        """performs regex on raw string and converts to list"""
        c = [int(i.group(0)) for i in re.finditer(r'\d+', string)]
        return [1 if x in c else 0  for x in xrange(max(c), -1, -1)]

    @classmethod
    def _string_to_binary(cls, string):
        """converts to base 2; bina,binb are binary values like 110100101100....."""
        x = cls._string_to_list(string)
        a = cls._list_to_int(x)
        bina = int(str(a),2)
        return bina  #

    def __add__(self,other):
        """
        __add__ is another special method, and is used to override the + operator.  This will only 
        work for instances of gf2pim and its subclasses.

        a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns binary string"""
        return gf2pim(self.bin^other.bin)

    def __sub__(self,other):
        """
        __sub__ is the special method for overriding the - operator

        same as addition in GF(2)"""
        return self.add(other)

    def __str__(self):
        return self.to_string()

if __name__ == '__main__':
    a = gf2pim.from_string("x**14 + x**1 + x**0")
    b = gf2pim.from_string("x**6 + x**2 + x**1")
    smadd1 = a+b
    print "smadd1   ",smadd1