Generating new expression from an existing expression in Z3 - python

Given an expression f , I want to replace all variables v in f with something like v_d (d is a number). Currently I have to go through the following steps to achieve this
Obtain all the variables in f
For each variable v in f, determine its sort, then generate the appropriate v_d var.
do the substitution
Since I am still trying to learn Z3 python so probably there is a much better way to do the above?
Thanks.
My full code is listed below:
def get_vars(f,rs=[]):
"""obtain variables from f"""
if is_const(f):
try:
f.as_string() #to differentiate btw Int('x') and IntVal('3')
return rs
except AttributeError:
return vset(rs + [f],str)
else:
for f_ in f.children():
rs = get_vars(f_,rs)
return vset(rs,str)
def gen_vars(vs,i):
"""
Generates a new set of variables
E.g. v => v_i , v_next => v_(i+1)
"""
assert i>=0
def mk_name(i,v):
next_kw = '_next'
if str(v).endswith(next_kw):
astr = str(v)[:-len(next_kw)] + '_' + str(i+1)
else:
astr = str(v) + '_' + str(i)
return astr
def mk_var(name,vsort):
if vsort.kind() == Z3_INT_SORT:
v = Int(name)
elif vsort.kind() == Z3_REAL_SORT:
v = Real(name)
elif vsort.kind() == Z3_BOOL_SORT:
v = Bool(name)
elif vsort.kind() == Z3_DATATYPE_SORT:
v = Const(name,vsort)
else:
assert False, 'Cannot handle this sort yet (id: %d)'%vsort.kind()
return v
#so that the longest one is replaced first
vs = sorted(vs,key=str,reverse=True)
names = [mk_name(i,v) for v in vs]
vs_ = [mk_var(ns,v.sort()) for ns,v in zip(names,vs)]
vss = zip(vs,vs_)
return vss
def substitute_f(f,i,vs=None):
"""
Replaces all variables v in f with v_(i*_)
vs: variables in f (could be automatically obtained from f)
"""
assert is_expr(f)
assert isinstance(vs,list) or vs is None
if vs is None:
vs = get_vars(f)
vss = gen_vars(vs,i)
f_ = f
for pvs in vss:
f_ = substitute(f_,pvs)
return f_

Related

Need an OOP method for share variable between function?

I have a class and some functions. In the 'check_reflexive()' function, there is a variable called reflexive_list. I want to use this variable also in the 'antisymmetric' function.
I checked some examples about class but didn't find a specific example to solve this problem.
I'll be waiting for your advice. Hope you have a nice day
class MyClass():
def __init__(self):
def checkif_pair(k):
for a in k:
if a%2 == 0:
None
else:
return False
return True
def check_reflexive(k):
j = 0
z = 0
reflexive_list = []
while j < len(k):
i = 0
while i < len(k):
if k[i] == k[j]:
tup = k[j],k[i]
reflexive_list.append(tup)
i += 1
else:
None
j = j + 1
else:
None
print(reflexive_list)
if len(reflexive_list) == len(self.list1):
return True
else:
return False
def antisymmetric(k):
antisymettric_list = []
for b in k:
swap1 = b[0]
swap2 = b[1]
newtuple = (swap2, swap1)
antisymettric_list.append(newtuple)
for ü in reflexive_list:
if ü in antisymettric_list:
antisymettric_list.remove(ü)
else:
None
print(antisymettric_list)
for q in antisymettric_list:
if q in k:
print("The system is not Anti-Symmetric.")
break
print("The system is Anti-Symmetric.")
def transitive(k):
result = {}
for first, second in k:
result.setdefault(first, []).append(second)
print(result)
for a, b in k:
for x in result[b]:
if x in result[a]:
None
else:
print("There is no {} in the {}".format(x, result[a]))
return False
return True
You can just use reflexive_list as an instance variable. Just add a constructor where the variable is defined:
class MyClass():
def __init__(self):
self.reflexive_list = []
And everytime you want to use it inside the function, you use self.reflexive_list

Remove unused variables in Python source code

The Question
Is there a straightforward algorithm for figuring out if a variable is "used" within a given scope?
In a Python AST, I want to remove all assignments to variables that are not otherwise used anywhere, within a given scope.
Details
Motivating example
In the following code, it is obvious to me (a human), that _hy_anon_var_1 is unused, and therefore the _hy_anon_var_1 = None statements can be removed without changing the result:
# Before
def hailstone_sequence(n: int) -> Iterable[int]:
while n != 1:
if 0 == n % 2:
n //= 2
_hy_anon_var_1 = None
else:
n = 3 * n + 1
_hy_anon_var_1 = None
yield n
# After
def hailstone_sequence(n: int) -> Iterable[int]:
while n != 1:
if 0 == n % 2:
n //= 2
else:
n = 3 * n + 1
yield n
Bonus version
Extend this to []-lookups with string literals as keys.
In this example, I would expect _hyx_letXUffffX25['x'] to be eliminated as unused, because _hyx_letXUffffX25 is local to h, so _hyx_letXUffffX25['x'] is essentially the same thing as a local variable. I would then expect _hyx_letXUffffX25 itself to be eliminated once there are no more references to it.
# Before
def h():
_hyx_letXUffffX25 = {}
_hyx_letXUffffX25['x'] = 5
return 3
# After
def h():
return 3
From what I can tell, this is somewhat of an edge case, and I think the basic algorithmic problem is the same.
Definition of "used"
Assume that no dynamic name lookups are used in the code.
A name is used if any of these are true in a given scope:
It is referenced anywhere in an expression. Examples include: an expression in a return statement, an expression on the right-hand side of an assignment statement, a default argument in a function definition, being referenced inside a local function definition, etc.
It is referenced on the left-hand side of an "augmented assignment" statement, i.e. it is an augtarget therein. This might represent "useless work" in a lot of programs, but for the purpose of this task that's OK and distinct from being an entirely unused name.
It is nonlocal or global. These might be useless nonlocals or globals, but because they reach beyond the given scope, it is OK for my purposes to assume that they are "used".
Please let me know in the comments if this seems incorrect, or if you think I am missing something.
Examples of "used" and "unused"
Example 1: unused
Variable i in f is unused:
def f():
i = 0
return 5
Example 2: unused
Variable x in f is unused:
def f():
def g(x):
return x/5
x = 10
return g(100)
The name x does appear in g, but the variable x in g is local to g. It shadows the variable x created in f, but the two x names are not the same variable.
Variation
If g has no parameter x, then x is in fact used:
def f():
x = 10
def g():
return x/5
return g(100)
Example 3: used
Variable i in f is used:
def f():
i = 0
return i
Example 4: used
Variable accum in silly_map and silly_sum is used in both examples:
def silly_map(func, data):
data = iter(data)
accum = []
def _impl():
try:
value = next(data)
except StopIteration:
return accum
else:
accum.append(value)
return _impl()
return _impl()
def silly_any(func, data):
data = iter(data)
accum = False
def _impl():
nonlocal accum, data
try:
value = next(data)
except StopIteration:
return accum
else:
if value:
data = []
accum = True
else:
return _impl()
return _impl()
The solution below works in two parts. First, the syntax tree of the source is traversed and all unused target assignment statements are discovered. Second, the tree is traversed again via a custom ast.NodeTransformer class, which removes these offending assignment statements. The process is repeated until all unused assignment statements are removed. Once this is finished, the final source is written out.
The ast traverser class:
import ast, itertools, collections as cl
class AssgnCheck:
def __init__(self, scopes = None):
self.scopes = scopes or cl.defaultdict(list)
#classmethod
def eq_ast(cls, a1, a2):
#check that two `ast`s are the same
if type(a1) != type(a2):
return False
if isinstance(a1, list):
return all(cls.eq_ast(*i) for i in itertools.zip_longest(a1, a2))
if not isinstance(a1, ast.AST):
return a1 == a2
return all(cls.eq_ast(getattr(a1, i, None), getattr(a2, i, None))
for i in set(a1._fields)|set(a2._fields) if i != 'ctx')
def check_exist(self, t_ast, s_path):
#traverse the scope stack and remove scope assignments that are discovered in the `ast`
s_scopes = []
for _ast in t_ast:
for sid in s_path[::-1]:
s_scopes.extend(found:=[b for _, b in self.scopes[sid] if AssgnCheck.eq_ast(_ast, b) and \
all(not AssgnCheck.eq_ast(j, b) for j in s_scopes)])
self.scopes[sid] = [(a, b) for a, b in self.scopes[sid] if b not in found]
def traverse(self, _ast, s_path = [1]):
#walk the ast object itself
_t_ast = None
if isinstance(_ast, ast.Assign): #if assignment statement, add ast object to current scope
self.traverse(_ast.targets[0], s_path)
self.scopes[s_path[-1]].append((True, _ast.targets[0]))
_ast = _ast.value
if isinstance(_ast, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
s_path = [*s_path, (nid:=(1 if not self.scopes else max(self.scopes)+1))]
if isinstance(_ast, (ast.FunctionDef, ast.AsyncFunctionDef)):
self.scopes[nid].extend([(False, ast.Name(i.arg)) for i in _ast.args.args])
_t_ast = [*_ast.args.defaults, *_ast.body]
self.check_exist(_t_ast if _t_ast is not None else [_ast], s_path) #determine if any assignment statement targets have previously defined names
if _t_ast is None:
for _b in _ast._fields:
if isinstance((b:=getattr(_ast, _b)), list):
for i in b:
self.traverse(i, s_path)
elif isinstance(b, ast.AST):
self.traverse(b, s_path)
else:
for _ast in _t_ast:
self.traverse(_ast, s_path)
Putting it all together:
class Visit(ast.NodeTransformer):
def __init__(self, asgn):
super().__init__()
self.asgn = asgn
def visit_Assign(self, node):
#remove assignment nodes marked as unused
if any(node.targets[0] == i for i in self.asgn):
return None
return node
def remove_assgn(f_name):
tree = ast.parse(open(f_name).read())
while True:
r = AssgnCheck()
r.traverse(tree)
if not (k:=[j for b in r.scopes.values() for k, j in b if k]):
break
v = Visit(k)
tree = v.visit(tree)
return ast.unparse(tree)
print(remove_assgn('test_name_assign.py'))
Output Samples
Contents of test_name_assign.py:
def hailstone_sequence(n: int) -> Iterable[int]:
while n != 1:
if 0 == n % 2:
n //= 2
_hy_anon_var_1 = None
else:
n = 3 * n + 1
_hy_anon_var_1 = None
yield n
Output:
def hailstone_sequence(n: int) -> Iterable[int]:
while n != 1:
if 0 == n % 2:
n //= 2
else:
n = 3 * n + 1
yield n
Contents of test_name_assign.py:
def h():
_hyx_letXUffffX25 = {}
_hyx_letXUffffX25['x'] = 5
return 3
Output:
def h():
return 3
Contents of test_name_assign.py:
def f():
i = 0
return 5
Output:
def f():
return 5
Contents of test_name_assign.py:
def f():
x = 10
def g():
return x/5
return g(100)
Ouptut:
def f():
x = 10
def g():
return x / 5
return g(100)

Why does passing a dictionary as a parameter take more time?

I tried to a leetcode problem. I find one of the following code throws a time limit exceeded error. I created the following testing code. I found the first one pass dictionary as a parameter takes more time the the other one. 0.94s vs 0.84s.
Can anyone explain this ?
class Solution(object):
def longestPalindromeSubseq(self, x):
"""
:type s: str
:rtype: int
"""
#dic = {}
def helper(s, dic):
if len(s) == 0:
return 0
if len(s) == 1:
return 1
if s in dic:
return dic[s]
if s[0] == s[-1]:
res = helper(s[1:-1], dic)+2
else:
l1 = helper(s[:-1], dic)
l2 = helper(s[1:], dic)
res = max(l1,l2)
dic[s] = res
#print (id(dic), dic)
return res
d = {}
ans = helper(x, d)
#print (id(d), d)
return ans
class Solution1(object):
def longestPalindromeSubseq(self, x):
"""
:type s: str
:rtype: int
"""
dic = {}
def helper(s):
if len(s) == 0:
return 0
if len(s) == 1:
return 1
if s in dic:
return dic[s]
if s[0] == s[-1]:
res = helper(s[1:-1])+2
else:
l1 = helper(s[:-1])
l2 = helper(s[1:])
res = max(l1,l2)
dic[s] = res
#print (id(dic), dic)
return res
ans = helper(x)
#print (id(dic), dic)
return ans
import time
if __name__ == "__main__":
x = "gphyvqruxjmwhonjjrgumxjhfyupajxbjgthzdvrdqmdouuukeaxhjumkmmhdglqrrohydrmbvtuwstgkobyzjjtdtjroqpyusfsbjlusekghtfbdctvgmqzeybnwzlhdnhwzptgkzmujfldoiejmvxnorvbiubfflygrkedyirienybosqzrkbpcfidvkkafftgzwrcitqizelhfsruwmtrgaocjcyxdkovtdennrkmxwpdsxpxuarhgusizmwakrmhdwcgvfljhzcskclgrvvbrkesojyhofwqiwhiupujmkcvlywjtmbncurxxmpdskupyvvweuhbsnanzfioirecfxvmgcpwrpmbhmkdtckhvbxnsbcifhqwjjczfokovpqyjmbywtpaqcfjowxnmtirdsfeujyogbzjnjcmqyzciwjqxxgrxblvqbutqittroqadqlsdzihngpfpjovbkpeveidjpfjktavvwurqrgqdomiibfgqxwybcyovysydxyyymmiuwovnevzsjisdwgkcbsookbarezbhnwyqthcvzyodbcwjptvigcphawzxouixhbpezzirbhvomqhxkfdbokblqmrhhioyqubpyqhjrnwhjxsrodtblqxkhezubprqftrqcyrzwywqrgockioqdmzuqjkpmsyohtlcnesbgzqhkalwixfcgyeqdzhnnlzawrdgskurcxfbekbspupbduxqxjeczpmdvssikbivjhinaopbabrmvscthvoqqbkgekcgyrelxkwoawpbrcbszelnxlyikbulgmlwyffurimlfxurjsbzgddxbgqpcdsuutfiivjbyqzhprdqhahpgenjkbiukurvdwapuewrbehczrtswubthodv"
print (x)
t0 = time.time()
sol = Solution()
print (sol.longestPalindromeSubseq(x))
t1 = time.time()
print(t1- t0)
sol1 = Solution1()
print (sol1.longestPalindromeSubseq(x))
t2 = time.time()
print(t2-t1)
Python uses something that is called call by sharing. The function gets only the alias on the parameter. With that in mind, it does't matter what you pass to the function.
But the script may take different time to execute. It is not constant. Using recursion makes it even harder to predict

I'd like to create a array of record (Pascal) in Python. But how?

Here my code:
class typeE:
def __init__(self):
self.u = 0
self.v = 0
self.w = 0
def readData():
global n
global m
global e
e = [typeE]
c = -2
f = open(fi, 'r')
for line in f:
print e[0]
c += 1
ln = [int(i) for i in line.split()]
if c == -1:
n = ln[0]
m = ln[1]
else:
e[c].u = ln[0]
e[c].v = ln[1]
e[c].w = ln[2]
f.close()
Do you have any idea how to make a record like this in Python?
type
typeE = record
u, v, w: longint;
end;
Python is not Pascal. You don't create an "array of records" but a "list of objects" (which can be instances custom class, but in your case could as well be plain dicts).
Also, globals are a bad idea whatever the language, it's always better to use true functions (functions that return a result depending on their input, instead of mutating or rebinding global variables).
The pythonic version of your code (error handling set aside) would look something like this:
class TypeE(object):
def __init__(self, u=0, v=0, w=0):
self.u = u
self.v = v
self.w = w
def __repr__(self):
return "<TypeE({u}, {v}, {w})>".format(**self.__dict__)
def to_int(line):
return [int(i) for i in line.strip().split()]
def read_data(src):
records = []
with open(src, 'r') as f:
headers = to_int(f.next())[:2]
for line in f:
records.append(TypeE(*ln[:3]))
return headers, records
def main():
(m,n), e = read_data("/path/to/your/file")
# now do something with m, n and e
print m, n, e
if __name__ == "__main__":
main()

Python -- polynomials in finite fields. Why does only __add__() work with super() in this case?

I'm trying to use the parent class's __div__() in order to maintain the same type so that many operations can be called at once as in the last example mix1 = bf2/bf4*bf1%bf5 in main() below where multiple arithmetic operations are strung together. For some reason, I can use super() in __add__() but not in __div__(). The error is "IndexError: list index out of range" and I've been going over and over this without any progress. Note that this is all related to polynomial arithmetic within a finite field.
I'm including the parsePolyVariable() and it's dependents (sorry if it looks like there's a bit of code but I assure you it's all for a good cause and builds character), since that's where the list error seems to be stemming from but I can't for the life of me figure out where everything is going very wrong. I'm teaching myself Python, so I'm sure there are some other beginners out there who will see where I'm missing the obvious.
I've been looking over these but they don't seem to be related to this situation:
http://docs.python.org/2/library/functions.html#super
Python super(Class, self).method vs super(Parent, self).method
How can I use Python's super() to update a parent value?
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)
#if self.parsePolyVariable(string) == "0": self.key,self.lst = "0",[0]
#else:
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
if sum(c) == 0: return "0",[0]
letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]
degree = 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
lst = [1 if x in c else (1 if x==0 else (1 if x=='x' else 0)) for x in xrange(degree, -1, -1)]
return key,lst
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 __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.
self,other are gf2infix instances; returns GF(2) polynomial in string format
"""
if self.polyVariableCheck(other) == False:
return "error: variables of %s and %s do not match"%(self.string,other.string)
return GF2Polynomial(self.outFormat(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 __mul__(self,other):
"""
__mul__ is the special method for overriding the * operator
returns product of 2 polynomials in gf2; self,other are values 10110011...
"""
if self.polyVariableCheck(other) == False:
return "error: variables of %s and %s do not match"%(self.string,other.string)
bitsa = reversed("{0:b}".format(self.bin))
g = [(other.bin<<i)*int(bit) for i,bit in enumerate(bitsa)]
return GF2Polynomial(self.outFormat(reduce(lambda x,y: x^y,g)))
def __div__(self,other):
"""
__div__ is the special method for overriding the / operator
returns quotient 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 1
return GF2Polynomial(self.outFormat(self.bin/other.bin))
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
class BinaryField(GF2Polynomial):
def __init__(self, poly, mod):
if mod == "0": self.string = "Error: modulus division by 0"
elif mod == "0": self.string = "%s is 0 so resulting mod is 0"%(poly)
fieldPoly = GF2Polynomial(poly) % mod
if fieldPoly == 0: self.string = "%s and %s are the same so resulting mod is 0"%(poly,mod)
else: super(BinaryField, self).__init__(fieldPoly.string)
#self.degree = len(str(fieldPoly))
def polyFieldCheck(self,other):
return self.degree() == other.degree()
def __add__(self, other):
"""
inherited from GF2Polynomial
"""
return super(BinaryField, self).__add__(other) % min(other,self)
def __sub__(self,other):
"""
inherited from GF2Polynomial
"""
return self.__add__(other)
def __mul__(self, other):
"""
special method of BinaryField, needed for format adjustments between classes
"""
#print "self = %s,%s other = %s,%s "%(self.degree(),type(self.degree()),other.degree(),type(other.degree()))
if self.polyVariableCheck(other) == False:
return "error: variables of %s and %s do not match"%(self.string,other.string)
if self.polyFieldCheck(other) == False:
return "error: fields of %s and %s do not match"%(self.string,other.string)
else: print "Operation will proceed: fields of %s and %s match"%(self.string,other.string)
bitsa = reversed("{0:b}".format(self.bin))
g = [(other.bin<<i)*int(bit) for i,bit in enumerate(bitsa)]
result = reduce(lambda x,y: x^y,g)%min(self.bin,other.bin)
return GF2Polynomial(self.outFormat(result))
def __div__(self, other):
"""
special method of BinaryField, needed for format adjustments between classes
"""
if self.polyVariableCheck(other) == False:
return "error: variables of %s and %s do not match"%(self.string,other.string)
if self.polyFieldCheck(other) == False:
return "error: fields of %s and %s do not match"%(self.string,other.string)
else: print "Operation will proceed: fields of %s and %s match"%(self.string,other.string)
if self.bin == other.bin: return 1
result = self.bin/other.bin
#return self.outFormat(result)
return super(BinaryField, self).__div__(other) #% min(other,self)
def degree(self):
return len(self.lst)-1
And here's the main():
if __name__ == '__main__':
## "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 = "x**8 + x**3 + 1"
d = GF2Polynomial(poly4); e = GF2Polynomial(poly5); f = GF2Polynomial(poly6)
poly7 = "x**9 + x**5 + 1"; poly8 = "x**11 + x**7 + x**4 + 1"; poly9 = "x**5 + x**4 + x**2 + x"
g = GF2Polynomial(poly7); h = GF2Polynomial(poly8); i = GF2Polynomial(poly9)
## g = GF2Polynomial("x**5 + x**4 + x**3 + 1"); h = GF2Polynomial("x**5 + x"); print "(g*h)%b = ",(g*h)%b
## dd = GF2Polynomial("x**0"); print "dd -- ",dd
## ee = GF2Polynomial("0"); print "ee -- ",ee
bf1 = BinaryField(poly1,b); print bf1; print "degree bf1 = ",bf1.degree()
bf2 = BinaryField(poly4,e); print "bf2 ",bf2; bf3 = BinaryField(poly4,d); print "bf3 ",bf3,type(bf3)
bf4 = BinaryField(poly4,h); bf5 = BinaryField(poly9,e); bf6 = BinaryField(poly8,i)
add1 = bf1+bf2
print "add1 ",add1
div1 = bf1/bf2
print "div1 ",div1,type(div1)
mix1 = bf2*bf1%bf5
print "mix1 ",mix1,type(mix1)
EDIT:
The full traceback --
Message File Name Line Position
Traceback
<module> C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py 233
__div__ C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py 197
__div__ C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py 100
__init__ C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py 20
parsePolyVariable C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py 48
IndexError: list index out of range
For reference line 48 is degree = max(c); varmatch = True; key = letter[0].
Personal notes and information were removed, adjusting the line numbers.
Your return GF2Polynomial(self.outFormat(self.bin/other.bin)) line results in the string 1, which is then passed to the GF2Polynomial.parsePolyVariable() method.
This value has no letters, so the line:
letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]
returns an empty list. The next line:
degree = max(c); varmatch = True; key = letter[0]
then fails because key = letter[0] gives a IndexError exception.
Your code is hard to read because you use one-letter variables and put multiple statements on one line, so it is hard to make out what your expectations are in that function.
The exception has otherwise nothing to do with super(). There is a simple bug in your own code somewhere.

Categories

Resources