1

Cette classe prend une chaîne polynomiale à corps fini, l'analyse, opère (+ - * /%), puis affiche le même format que l'entrée. Cela fonctionne bien (jusqu'à présent). Cependant, maintenant j'essaye d'implémenter des méthodes spéciales sur les opérateurs arithmétiques, et je ne peux pas passer le point de simplement concaténer les chaînes. Généralement, l'idée est d'initialiser l'entrée dans une instance de classe, mais dans ce cas, il y a une regex en entrée qui semble compliquer toute tentative de faire cela. Je m'enseigne Python donc c'est un film d'horreur pour moi, mais probablement juste un jouet pour tout programmeur Python chevronné.Python - arithmétique de méthodes spéciales utilisant des méthodes de classe existantes

Ceux-ci semblent avoir beaucoup d'informations, mais je ne sais pas combien ils sont utiles dans cette situation:

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 

Voici la classe et les exemples que je suis en utilisant:

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) 

le dernier exemple en bas montre le problème:

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 

Et la sortie:

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

Comme vous pouvez le voir par smadd1 je dois ajouter ces 2 en utilisant + et pas seulement concaténer. De plus, j'aimerais savoir si je dois utiliser un arbre d'expression S dans cette situation.

EDIT:

Multiply() qui fonctionnait mais pas maintenant:

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))) 

sa forme originale était:

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)) 

Mépris cette question avec multiply(), Je l'ai corrigé. La ligne qui a été modifiée était:

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

et la ligne avant celle-ci a été retirée.

Répondre

1

Il semble que vous confondiez deux concepts: les chaînes qui représentent des polynômes à corps finis et les objets de la classe gf2pim, qui représentent également des polynômes à corps finis. Vous devez instancier un objet gf2pim pour chaque polynôme que vous souhaitez manipuler, et les opérations sur les objets gf2pim doivent renvoyer d'autres objets gf2pim. Actuellement, vous essayez d'utiliser l'opérateur + sur 2 chaînes, ce qui explique pourquoi votre méthode __add__ n'est pas appelée. Il y a aussi plusieurs autres problèmes avec votre définition de la classe gf2pim. J'ai refactorisé votre code un peu plus bas, même si ce n'est toujours pas parfait. J'ai également omis les méthodes de division, mais je pense que ce que j'ai fait devrait vous mettre sur la bonne voie. Voir la section 3.4.8 de ce link pour plus de noms de méthodes spéciales pour la surcharge de l'opérateur.

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   
+0

oui merci, exactement ce dont j'avais besoin. Je ne sais pas pourquoi vous avez utilisé la méthode __str __ (self). est-ce seulement pour le __init __() et pourquoi? aussi pourquoi avez-vous déplacé parsePolyToListInput() en dehors de prepBinary() pour initialiser sur son propre dans la méthode __init __()? – stackuser

+0

La méthode '__str__' est appelée lorsque vous utilisez' print'. Essayez de le supprimer et vous verrez que l'impression d'objets de votre classe donne un résultat moins utile.Je n'ai pas entièrement compris votre code car je refactoring, donc mon choix déplace parsePolyToListInput() de prepBinary() était quelque peu arbitraire. Je comprends mieux maintenant et j'ai quelques minutes gratuites, je vais donc refactoriser et éditer mon post. – jcrudy

Questions connexes