0

1과 0의 목록을 가져 와서 GF (2) 유한 필드 산술 연산을 수행하는 클래스가 있습니다. 그것은 다항식 형식으로 입력을 만들려고 할 때까지 일하는 것이 었습니다. 정규식 문제를 해결 한 후에 유한 산술 연산을 수행하는 방법에 관해서는 연산자에 과부하가 발생할 것으로 생각했습니다.Python - 클래스 인스턴스에서 정규식 사용

parsePolyToListInput(input)의 실제 코드는 수업 외에서 작동합니다. 문제는 정규식에있는 것 같아요.이 문자열은 문자열에서만 가져올 것이고 (이것은 의미가 있습니다) 매개 변수로 self.expr을 사용하여 초기화하지 않는 것 같습니다 (이것이 문제입니다). 초기화 직전의 @staticmethod는 다항식이 전달 될 때 언 바운드 오류를 복구하기위한 시도 였지만 분명히 완전히 잘못되었습니다. 어떤 산술 연산을 살펴보기로 결정했다면 모듈러 역함은 작동하지 않습니다 (함수의 나눗셈과 리턴 타입이 반복되는 동안 반복되는 형식화 문제로 인한 것 같습니다) :

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)에서 작업을 수행하고 다항식 형식으로 출력 할 수 있도록 썼습니다. 다음 버전은 다항식 입력을 받아 들일 수 있어야하고 계획대로 작동하지 않는 중요한 '모듈 역 (modular inverse)'기능을 수행해야합니다 (실제로는 전혀 작동하지 않습니다).

2) 나는 파이썬을 가르치고있다. (사실 나는 전반적으로 프로그래밍을 가르치고있다.) 그래서 나는 초보자 습관을 가능한 한 빨리 깨기 위해 프로 파이썬 프로그래머의 건설적인 비판을 환영한다.

편집 :

어쩌면 내가 무엇을 작동하고 무엇을 명확히 도움이 될 것으로 테스트했던 코드를 좀 더하지 않는 : 문제의

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

일부는 당신이하지 않은 것입니다 parsePolyToListInput에 대한 인수로 self을 선언했습니다. 메소드를 호출 할 때 호출하는 인스턴스는 암시 적으로 첫 번째 인수로 바인드됩니다. 첫 번째 인수 인 self의 이름을 지정하는 것은 엄격한 요구 사항이 아닌 규칙이며, 인스턴스는 poly에 바인딩되어 있습니다. 그런 다음 정규식을 실행하려고합니다.

클래스의 개별 인스턴스의 동작과 클래스 수준 또는 모듈 수준 동작에 대한 디자인에 약간의 혼란이있는 것처럼 보입니다. 파이썬에서는 클래스의 인스턴스를 매개 변수로 사용하지 않고 무언가를 모듈 수준의 함수로 정의하는 대신 어색하게 처리하지 않는 것이 좋습니다. parsePolyToListInput은 그러한 함수 중 하나 일 수 있습니다.

add 구현에는 마찬가지로 "매개 변수로 2 개의 목록을 허용합니다"라는 주석이 있습니다. 사실, 첫 번째 인수로 gf2poly 인스턴스를 가져올 것입니다. 이는 연산자 오버로딩을 계획하고 있다면 아마도 맞을 것이지만 두 번째 인수도 gf2poly 인스턴스 여야 함을 의미합니다.

편집 : 예, 귀하의 예제 코드는 클래스 동작과 인스턴스 동작 사이의 차이를 보여줍니다.어느 당신의 다중 호출은 다음과 같이 보일 것입니다 :

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 
관련 문제