0

У меня есть класс, который принимал списки 1 и 0 и выполнял GF (2) арифметические операции с конечным полем. Он работал до тех пор, пока я не попытался заставить его принимать данные в полиномиальном формате. Что касается того, как конечная арифметика будет выполнена после исправления проблемы с регулярным выражением, я думал о перегрузке операторов.Python - использование регулярного выражения для экземпляра класса

Фактический код в parsePolyToListInput(input) работает вне класса. Проблема, похоже, связана с регулярным выражением, и ошибки, которые он принимает только в строке (это имеет смысл), но, похоже, не инициализируется с помощью self.expr в качестве параметра (это проблема). Метод @static непосредственно перед инициализацией был попыткой спасти несвязанную ошибку, так как он прошел многочлен, но это, по-видимому, совершенно неверно. Чтобы сэкономить ваше время, если вы решите посмотреть на какую-либо из арифметических операций, модульный обратный не работает (похоже, из-за проблемы форматирования после каждой итерации этого цикла while для деления в функции и типа возвращаемого типа) :

import re 

class gf2poly: 
    #binary arithemtic on polynomials 
    #@staticmethod 
    def __init__(self,expr): 
     self.expr = expr 
     #self.expr = [int(i) for i in expr] 
     self.expr = gf2poly.parsePolyToListInput(self.expr) 
    def convert(self): #to clarify the input if necessary 
     convertToString = str(self.expr) 
     print "expression is %s"%(convertToString) 
    def id(self): #returns modulus 2 (1,0,0,1,1,....) for input lists 
     return [int(self.expr[i])%2 for i in range(len(self.expr))] 
    def listToInt(self): #converts list to integer for later use 
     result = gf2poly.id(self) 
     return int(''.join(map(str,result))) 
    def prepBinary(a,b): #converts to base 2 and orders min and max for use 
     a = gf2poly.listToInt(a); b = gf2poly.listToInt(b) 
     bina = int(str(a),2); binb = int(str(b),2) 
     a = min(bina,binb); b = max(bina,binb); 
     return a,b 
    @staticmethod 
    def outFormat(raw): 
     raw = str(raw[::-1]); g = [] #reverse binary string for enumeration 
     [g.append(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 parsePolyToListInput(poly): 
     c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)] #re.finditer returns an iterator 
     #m = max(c) 
     return [1 if x in c else 0 for x in xrange(max(c), -1, -1)] 
     #return d 
    def add(self,other): #accepts 2 lists as parameters 
     a = gf2poly.listToInt(self); b = gf2poly.listToInt(other) 
     bina = int(str(a),2); binb = int(str(b),2) 
     m = bina^binb; z = "{0:b}".format(m) 
     return z #returns binary string 
    def subtract(self,other): #basically same as add() but built differently 
     result = [self.expr[i]^other.expr[i] for i in range(len(max(self.expr,other.expr)))] 
     return int(''.join(map(str,result))) 
    def multiply(a,b): #a,b are lists like (1,0,1,0,0,1,....) 
     a,b = gf2poly.prepBinary(a,b) 
     g = []; bitsa = "{0:b}".format(a) 
     [g.append((b<<i)*int(bit)) for i,bit in enumerate(bitsa)] 
     m = reduce(lambda x,y: x^y,g); z = "{0:b}".format(m) 
     return z #returns product of 2 polynomials in gf2 
    def divide(a,b): #a,b are lists like (1,0,1,0,0,1,....) 
     a,b = gf2poly.prepBinary(a,b) 
     bitsa = "{0:b}".format(a); bitsb = "{0:b}".format(b) 
     difflen = len(str(bitsb)) - len(str(bitsa)) 
     c = a<<difflen; q=0 
     while difflen >= 0 and b != 0: #a is divisor, b is dividend, b/a 
      q+=1<<difflen; b = b^c # b/a because of sorting in prep 
      lendif = abs(len(str(bin(b))) - len(str(bin(c)))) 
      c = c>>lendif; difflen -= lendif 
     r = "{0:b}".format(b); q = "{0:b}".format(q) 
     return r,q #returns r remainder and q quotient in gf2 division 
    def remainder(a,b): #separate function for clarity when calling 
     r = gf2poly.divide(a,b)[0]; r = int(str(r),2) 
     return "{0:b}".format(r) 
    def quotient(a,b): #separate function for clarity when calling 
     q = gf2poly.divide(a,b)[1]; q = int(str(q),2) 
     return "{0:b}".format(q) 
    def extendedEuclideanGF2(a,b): # extended euclidean. a,b are GF(2) polynomials in list form 
     inita,initb=a,b; x,prevx=0,1; y,prevy = 1,0 
     while sum(b) != 0: 
      q = gf2poly.quotient(a,b); 
      q = list(q); q = [int(x) for x in q] 
      #q = list(q); 
      #q = tuple([int(i) for i in q]) 
      q = gf2poly(q) 
      a,b = b,gf2poly.remainder(a,b); 
      #a = map(list, a); 
      #b = [list(x) for x in a]; 
      #a = [int(x) for x in a]; b = [int(x) for x in b]; 
      b = list(b); b = [int(x) for x in b] 
      #b = list(b); 
      #b = tuple([int(i) for i in b]) 
      b = gf2poly(b) 
      #x,prevx = (prevx-q*x, x); 
      #y,prevy=(prevy-q*y, y) 
      print "types ",type(q),type(a),type(b) 
      #q=a//b; a,b = b,a%b; x,prevx = (prevx-q*x, x); y,prevy=(prevy-q*y, y) 
     #print("%d * %d + %d * %d = %d" % (inita,prevx,initb,prevy,a)) 
     return a,prevx,prevy # returns gcd of (a,b), and factors s and t 
    def modular_inverse(a,mod): # where a,mod are GF(2) polynomials in list form 
     gcd,s,t = gf2poly.extendedEuclideanGF2(a,mod); mi = gf2poly.remainder(s,mod) 
     #gcd,s,t = ext_euc_alg_i(a,mod); mi = s%mod 
     if gcd !=1: return False 
     #print ("%d * %d mod %d = 1"%(a,mi,mod)) 
     return mi # returns modular inverse of a,mod 

Я обычно проверить его с этим входом:

a = x**14 + x**1 + x**0 
p1 = gf2poly(a) 
b = x**6 + x**2 + x**1 
p2 = gf2poly(b) 

Первое, что вы могли бы заметить, мой код является то, что это не очень хорошо. Есть две причины:

1) Я написал его так, чтобы 1-я версия могла работать в конечном поле GF (2) и выводиться в полиномиальном формате. Затем следующие версии должны были иметь возможность принимать полиномиальные входы, а также выполнять критически важную функцию «модульной инверсии», которая не работает так, как планировалось (это означает, что она фактически не работает вообще).

2) Я учу себя Python (я на самом деле преподаю программирование в целом), поэтому любая конструктивная критика от программистов на Python приветствуется, поскольку я стараюсь как можно быстрее разбить привычки начинающих.

EDIT:

Может быть, некоторые больше кода я тестирование с поможет прояснить, что работает, а что нет:

t1 = [1,1,1]; t2 = [1,0,1]; t3 = [1,1]; t4 = [1, 0, 1, 1, 1, 1, 1] 
t5 = [1,1,1,1]; t6 = [1,1,0,1]; t7 = [1,0,1,1,0] 
f1 = gf2poly(t1); f2 = gf2poly(t2); f3 = gf2poly(t3); f4 = gf2poly(t4) 
f5 = gf2poly(t5);f6 = gf2poly(t6);f7 = gf2poly(t7) 
##print "subtract: ",a.subtract(b) 
##print "add: ",a.add(b) 
##print "multiply: ",gf2poly.multiply(f1,f3) 
##print "multiply: ",gf2poly.multiply(f1,f2) 
##print "multiply: ",gf2poly.multiply(f3,f4) 
##print "degree a: ",a.degree() 
##print "degree c: ",c.degree() 
##print "divide: ",gf2poly.divide(f1,b) 
##print "divide: ",gf2poly.divide(f4,a) 
##print "divide: ",gf2poly.divide(f4,f2) 
##print "divide: ",gf2poly.divide(f2,a) 
##print "***********************************" 
##print "quotient: ",gf2poly.quotient(f2,f5) 
##print "remainder: ",gf2poly.remainder(f2,f5) 
##testq = gf2poly.quotient(f4,f2) 
##testr = gf2poly.remainder(f4,f2) 
##print "quotient: ",testq,type(testq) 
##print "remainder: ",testr,type(testr) 
##print "***********************************" 
##print "outFormat testp: ",gf2poly.outFormat(testq) 
##print "outFormat testr: ",gf2poly.outFormat(testr) 
##print "***********************************" 
#print "gf2poly.modular_inverse(): ",gf2poly.modular_inverse(f2,f3) 
print "p1 ",p1 #,type(f2),type(f3) 
#print "parsePolyToListInput ",gf2poly.parsePolyToListInput(a) 

ответ

0

Часть вашей проблемы в том, что вы не имеете объявлен self в качестве аргумента для parsePolyToListInput. Когда вы вызываете метод, экземпляр, который вы вызываете его, неявно связан как первый аргумент. Именование первого аргумента self - это соглашение, а не строгое требование - экземпляр привязан к poly, который затем пытается запустить regexp.

Мне кажется, что в вашем дизайне есть некоторая путаница в том, что такое поведение отдельных экземпляров класса, а также поведение класса или уровня модуля. В Python вполне приемлемо оставить что-то, что не принимает экземпляр класса как параметр, определенный как функция уровня модуля, а не неудобно обучать его. parsePolyToListInput может быть такой такой функцией.

Реализация add, аналогично, имеет комментарий, в котором говорится, что «принимает 2 списка в качестве параметров». Фактически, в качестве первого аргумента он получит экземпляр gf2poly - это, вероятно, правильно, если вы планируете выполнять перегрузку оператора, но это означает, что вторым аргументом также должен быть экземпляр gf2poly.

EDIT: Да, код вашего примера показывает разбивку поведения класса и поведения экземпляра.Либо ваш многозарядный вызов должен выглядеть следующим образом:

print "multiply: ",f1.multiply(f3) 

Или умножать не должен быть методом вообще:

gfpoly.py: 
def multiply(f1, f2): 
    a,b = prepBinary(a,b) 
    g = []; bitsa = "{0:b}".format(a) 
    [g.append((b<<i)*int(bit)) for i,bit in enumerate(bitsa)] 
    m = reduce(lambda x,y: x^y,g); z = "{0:b}".format(m) 
    return z #returns product of 2 polynomials in gf2 

Этих последний подход, например, как стандартная библиотека math делает вещи ,

Преимущество определения метода умножения является то, что вы могли бы назвать его соответствующим образом (http://docs.python.org/2/reference/datamodel.html#special-method-names) и использовать его с * оператором:

print "multiply: ",f1 *f3 
Смежные вопросы