autopep8 on all files but operator.py

This commit is contained in:
Benjamin Bertrand 2016-02-13 07:04:08 +03:00
parent e43544006e
commit 47d43849d0
15 changed files with 536 additions and 366 deletions

View File

@ -5,13 +5,15 @@ from .explicable import Explicable
from .expression import Expression from .expression import Expression
from .operator import op from .operator import op
from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand
from .render import txt,tex from .render import txt, tex
from itertools import chain from itertools import chain
from functools import wraps from functools import wraps
def power_cache(fun): def power_cache(fun):
"""Decorator which cache calculated powers of polynoms """ """Decorator which cache calculated powers of polynoms """
cache = {} cache = {}
@wraps(fun) @wraps(fun)
def cached_fun(self, power): def cached_fun(self, power):
#print("cache -> ", cache) #print("cache -> ", cache)
@ -23,11 +25,12 @@ def power_cache(fun):
return poly_powered return poly_powered
return cached_fun return cached_fun
class AbstractPolynom(Explicable): class AbstractPolynom(Explicable):
"""The mathematic definition of a polynom. It will be the parent class of Polynom (classical polynoms) and later of SquareRoot polynoms""" """The mathematic definition of a polynom. It will be the parent class of Polynom (classical polynoms) and later of SquareRoot polynoms"""
def __init__(self, coefs = [1], letter = "x", name = "P"): def __init__(self, coefs=[1], letter="x", name="P"):
"""Initiate the polynom """Initiate the polynom
:param coef: coefficients of the polynom (ascending degree sorted) :param coef: coefficients of the polynom (ascending degree sorted)
@ -86,7 +89,7 @@ class AbstractPolynom(Explicable):
""" """
self._coef = [] self._coef = []
for coef in l_coef: for coef in l_coef:
if type(coef) == list and len(coef)==1: if isinstance(coef, list) and len(coef) == 1:
self._coef.append(coef[0]) self._coef.append(coef[0])
else: else:
self._coef.append(coef) self._coef.append(coef)
@ -114,7 +117,7 @@ class AbstractPolynom(Explicable):
>>> AbstractPolynom([1]).is_monom() >>> AbstractPolynom([1]).is_monom()
1 1
""" """
if len([i for i in self._coef if i != 0])==1: if len([i for i in self._coef if i != 0]) == 1:
return 1 return 1
else: else:
return 0 return 0
@ -156,15 +159,16 @@ class AbstractPolynom(Explicable):
['x', 2, '^'] ['x', 2, '^']
""" """
ans =[] ans = []
if a == [0]: if a == [0]:
pass pass
elif i == 0: elif i == 0:
ans = a ans = a
elif i == 1: elif i == 1:
ans = a * (a!=[1]) + [self._letter] + [op.mul] * (a!=[1]) ans = a * (a != [1]) + [self._letter] + [op.mul] * (a != [1])
else: else:
ans = a * (a!=[1]) + [self._letter, i, op.pw] + [op.mul] * (a!=[1]) ans = a * (a != [1]) + [self._letter, i,
op.pw] + [op.mul] * (a != [1])
return ans return ans
@ -208,20 +212,21 @@ class AbstractPolynom(Explicable):
""" """
if self == 0: if self == 0:
return [0] return [0]
# TODO: Faudrait factoriser un peu tout ça..! |dim. déc. 21 16:02:34 CET 2014 # TODO: Faudrait factoriser un peu tout ça..! |dim. déc. 21 16:02:34
# CET 2014
postfix = [] postfix = []
for (i,a) in list(enumerate(self._coef))[::-1]: for (i, a) in list(enumerate(self._coef))[::-1]:
operator = [op.add] operator = [op.add]
operator_sub1 = [] operator_sub1 = []
if type(a) == Expression: if isinstance(a, Expression):
# case coef is an arithmetic expression # case coef is an arithmetic expression
c = self.coef_postfix(a.postfix_tokens,i) c = self.coef_postfix(a.postfix_tokens, i)
if c != []: if c != []:
postfix.append(c) postfix.append(c)
if len(postfix) > 1: if len(postfix) > 1:
postfix += operator postfix += operator
elif type(a) == list: elif isinstance(a, list):
# case need to repeat the x^i # case need to repeat the x^i
for b in a: for b in a:
operator = [op.add] operator = [op.add]
@ -240,7 +245,7 @@ class AbstractPolynom(Explicable):
operator = [op.sub] operator = [op.sub]
else: else:
b = [b] b = [b]
c = self.coef_postfix(b,i) c = self.coef_postfix(b, i)
if c != []: if c != []:
postfix.append(c) postfix.append(c)
if len(postfix) > 1: if len(postfix) > 1:
@ -264,7 +269,7 @@ class AbstractPolynom(Explicable):
else: else:
a = [a] a = [a]
c = self.coef_postfix(a,i) c = self.coef_postfix(a, i)
if c != []: if c != []:
postfix.append(c) postfix.append(c)
if len(postfix) > 1: if len(postfix) > 1:
@ -285,11 +290,12 @@ class AbstractPolynom(Explicable):
""" """
if isNumber(other) and not isPolynom(other): if isNumber(other) and not isPolynom(other):
return AbstractPolynom([other], letter = self._letter) return AbstractPolynom([other], letter=self._letter)
elif isPolynom(other): elif isPolynom(other):
return other return other
else: else:
raise ValueError(type(other) + " can't be converted into a polynom") raise ValueError(type(other) +
" can't be converted into a polynom")
def reduce(self): def reduce(self):
"""Compute coefficients which have same degree """Compute coefficients which have same degree
@ -316,14 +322,15 @@ class AbstractPolynom(Explicable):
[< <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [[1, 2], [3, 4, 5], 6]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [< <class 'pymath.calculus.expression.Expression'> [1, 2, '+'] >, < <class 'pymath.calculus.expression.Expression'> [3, 4, '+', 5, '+'] >, 6]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [3, < <class 'pymath.calculus.expression.Expression'> [7, 5, '+'] >, 6]>] [< <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [[1, 2], [3, 4, 5], 6]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [< <class 'pymath.calculus.expression.Expression'> [1, 2, '+'] >, < <class 'pymath.calculus.expression.Expression'> [3, 4, '+', 5, '+'] >, 6]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [3, < <class 'pymath.calculus.expression.Expression'> [7, 5, '+'] >, 6]>]
""" """
# TODO: It doesn't not compute quick enough |ven. févr. 27 18:04:01 CET 2015 # TODO: It doesn't not compute quick enough |ven. févr. 27 18:04:01 CET
# 2015
# gather steps for every coefficients # gather steps for every coefficients
coefs_steps = [] coefs_steps = []
for coef in self._coef: for coef in self._coef:
coef_steps = [] coef_steps = []
if type(coef) ==list: if isinstance(coef, list):
# Simplify each element before adding them # Simplify each element before adding them
s = [] s = []
for c in coef: for c in coef:
@ -339,7 +346,7 @@ class AbstractPolynom(Explicable):
coef_steps += s coef_steps += s
# Convert last element into postfix addition. # Convert last element into postfix addition.
postfix_add = self.postfix_add([i for i in last if i!=0]) postfix_add = self.postfix_add([i for i in last if i != 0])
# Convert it to an expression # Convert it to an expression
coef_exp = Expression(postfix_add) coef_exp = Expression(postfix_add)
@ -393,12 +400,13 @@ class AbstractPolynom(Explicable):
>>> AbstractPolynom.postfix_add([]) >>> AbstractPolynom.postfix_add([])
[0] [0]
""" """
if not type(numbers) == list: if not isinstance(numbers, list):
return [numbers] return [numbers]
elif numbers == []: elif numbers == []:
return [0] return [0]
else: else:
ans = [[a, op.add] if i!=0 else [a] for (i,a) in enumerate(numbers)] ans = [[a, op.add] if i != 0 else [a]
for (i, a) in enumerate(numbers)]
return list(chain.from_iterable(ans)) return list(chain.from_iterable(ans))
def __eq__(self, other): def __eq__(self, other):
@ -428,9 +436,10 @@ class AbstractPolynom(Explicable):
o_poly = self.conv2poly(other) o_poly = self.conv2poly(other)
n_coef = spe_zip(self._coef, o_poly._coef) n_coef = spe_zip(self._coef, o_poly._coef)
p = AbstractPolynom(n_coef, letter = self._letter) p = AbstractPolynom(n_coef, letter=self._letter)
ini_step = [Expression(self.postfix_tokens + o_poly.postfix_tokens + [op.add])] ini_step = [Expression(self.postfix_tokens +
o_poly.postfix_tokens + [op.add])]
ans = p.simplify() ans = p.simplify()
ans.steps = ini_step + ans.steps ans.steps = ini_step + ans.steps
return ans return ans
@ -450,7 +459,8 @@ class AbstractPolynom(Explicable):
[< <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', '-'] >] [< <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', '-'] >]
""" """
ini_step = [Expression(self.postfix_tokens + [op.sub1])] ini_step = [Expression(self.postfix_tokens + [op.sub1])]
ans = AbstractPolynom([-i for i in self._coef], letter = self._letter).simplify() ans = AbstractPolynom([-i for i in self._coef],
letter=self._letter).simplify()
ans.steps = ini_step + ans.steps ans.steps = ini_step + ans.steps
return ans return ans
@ -473,7 +483,8 @@ class AbstractPolynom(Explicable):
[< <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', 6, 'x', 2, '^', '*', 5, 'x', '*', '+', 4, '+', '-'] >, < <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', 6, 'x', 2, '^', '*', '-', 5, 'x', '*', '-', 4, '-', '+'] >, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [[1, -4], [2, -5], [3, -6]]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [< <class 'pymath.calculus.expression.Expression'> [1, -4, '+'] >, < <class 'pymath.calculus.expression.Expression'> [2, -5, '+'] >, < <class 'pymath.calculus.expression.Expression'> [3, -6, '+'] >]>] [< <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', 6, 'x', 2, '^', '*', 5, 'x', '*', '+', 4, '+', '-'] >, < <class 'pymath.calculus.expression.Expression'> [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+', 6, 'x', 2, '^', '*', '-', 5, 'x', '*', '-', 4, '-', '+'] >, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [[1, -4], [2, -5], [3, -6]]>, < <class 'pymath.calculus.abstract_polynom.AbstractPolynom'> [< <class 'pymath.calculus.expression.Expression'> [1, -4, '+'] >, < <class 'pymath.calculus.expression.Expression'> [2, -5, '+'] >, < <class 'pymath.calculus.expression.Expression'> [3, -6, '+'] >]>]
""" """
o_poly = self.conv2poly(other) o_poly = self.conv2poly(other)
ini_step = [Expression(self.postfix_tokens + o_poly.postfix_tokens + [op.sub])] ini_step = [Expression(self.postfix_tokens +
o_poly.postfix_tokens + [op.sub])]
o_poly = -o_poly o_poly = -o_poly
#ini_step += o_poly.steps #ini_step += o_poly.steps
@ -518,28 +529,29 @@ class AbstractPolynom(Explicable):
""" """
o_poly = self.conv2poly(other) o_poly = self.conv2poly(other)
coefs = [0]*(self.degree + o_poly.degree + 1) coefs = [0] * (self.degree + o_poly.degree + 1)
for (i,a) in enumerate(self._coef): for (i, a) in enumerate(self._coef):
for (j,b) in enumerate(o_poly._coef): for (j, b) in enumerate(o_poly._coef):
if a == 0 or b == 0: if a == 0 or b == 0:
elem = 0 elem = 0
elif a==1: elif a == 1:
elem = b elem = b
elif b==1: elif b == 1:
elem = a elem = a
else: else:
elem = Expression([a, b, op.mul]) elem = Expression([a, b, op.mul])
if coefs[i+j]==0: if coefs[i + j] == 0:
coefs[i+j] = elem coefs[i + j] = elem
elif elem != 0: elif elem != 0:
if type(coefs[i+j]) == list: if isinstance(coefs[i + j], list):
coefs[i+j] += [elem] coefs[i + j] += [elem]
else: else:
coefs[i+j] = [coefs[i+j] , elem] coefs[i + j] = [coefs[i + j], elem]
p = AbstractPolynom(coefs, letter = self._letter) p = AbstractPolynom(coefs, letter=self._letter)
ini_step = [Expression(self.postfix_tokens + o_poly.postfix_tokens + [op.mul])] ini_step = [Expression(self.postfix_tokens +
o_poly.postfix_tokens + [op.mul])]
ans = p.simplify() ans = p.simplify()
ans.steps = [ini_step] + ans.steps ans.steps = [ini_step] + ans.steps
@ -573,25 +585,30 @@ class AbstractPolynom(Explicable):
""" """
if not type(power): if not type(power):
raise ValueError("Can't raise {obj} to {pw} power".format(obj = self.__class__, pw = str(power))) raise ValueError(
"Can't raise {obj} to {pw} power".format(
obj=self.__class__, pw=str(power)))
ini_step = [Expression(self.postfix_tokens + [power, op.pw])] ini_step = [Expression(self.postfix_tokens + [power, op.pw])]
if self.is_monom(): if self.is_monom():
if self._coef[self.degree] == 1: if self._coef[self.degree] == 1:
coefs = [0]*self.degree*power + [1] coefs = [0] * self.degree * power + [1]
p = AbstractPolynom(coefs, letter = self._letter) p = AbstractPolynom(coefs, letter=self._letter)
ans = p ans = p
else: else:
coefs = [0]*self.degree*power + [Expression([self._coef[self.degree] , power, op.pw])] coefs = [0] * self.degree * power + \
p = AbstractPolynom(coefs, letter = self._letter) [Expression([self._coef[self.degree], power, op.pw])]
p = AbstractPolynom(coefs, letter=self._letter)
ans = p.simplify() ans = p.simplify()
else: else:
if power == 2: if power == 2:
ans = self * self ans = self * self
else: else:
# TODO: faudrait changer ça c'est pas très sérieux |ven. févr. 27 22:08:00 CET 2015 # TODO: faudrait changer ça c'est pas très sérieux |ven. févr.
raise AttributeError("__pw__ not implemented yet when power is greatter than 2") # 27 22:08:00 CET 2015
raise AttributeError(
"__pw__ not implemented yet when power is greatter than 2")
ans.steps = ini_step + ans.steps ans.steps = ini_step + ans.steps
return ans return ans
@ -600,13 +617,13 @@ class AbstractPolynom(Explicable):
return self.__pow__(power) return self.__pow__(power)
if __name__ == '__main__': if __name__ == '__main__':
P = AbstractPolynom([[1,2],[3,4,5],6]) P = AbstractPolynom([[1, 2], [3, 4, 5], 6])
Q = P.reduce() Q = P.reduce()
for i in Q.explain(): for i in Q.explain():
print(i) print(i)
#import doctest #import doctest
#doctest.testmod() # doctest.testmod()
# ----------------------------- # -----------------------------

View File

@ -4,6 +4,7 @@
__all__ = ['gcd'] __all__ = ['gcd']
def gcd(a, b): def gcd(a, b):
"""Compute gcd(a,b) """Compute gcd(a,b)
@ -15,7 +16,7 @@ def gcd(a, b):
pos_a, _a = (a >= 0), abs(a) pos_a, _a = (a >= 0), abs(a)
pos_b, _b = (b >= 0), abs(b) pos_b, _b = (b >= 0), abs(b)
gcd_sgn = (-1 + 2*(pos_a or pos_b)) gcd_sgn = (-1 + 2 * (pos_a or pos_b))
if _a > _b: if _a > _b:
c = _a % _b c = _a % _b
@ -23,13 +24,13 @@ def gcd(a, b):
c = _b % _a c = _b % _a
if c == 0: if c == 0:
return gcd_sgn * min(_a,_b) return gcd_sgn * min(_a, _b)
elif _a == 1: elif _a == 1:
return gcd_sgn * _b return gcd_sgn * _b
elif _b == 1: elif _b == 1:
return gcd_sgn * _a return gcd_sgn * _a
else: else:
return gcd_sgn * gcd(min(_a,_b), c) return gcd_sgn * gcd(min(_a, _b), c)
if __name__ == '__main__': if __name__ == '__main__':
print(gcd(3, 15)) print(gcd(3, 15))

View File

@ -3,6 +3,7 @@
from .render import txt, tex from .render import txt, tex
class Renderable(object): class Renderable(object):
""" """
A Renderable object is an object which can work with Render class. It means that it has to have attribute postfix_tokens. A Renderable object is an object which can work with Render class. It means that it has to have attribute postfix_tokens.
@ -23,7 +24,7 @@ class Renderable(object):
cls.set_render(cls.DEFAULT_RENDER) cls.set_render(cls.DEFAULT_RENDER)
@classmethod @classmethod
def tmp_render(cls, render = tex): def tmp_render(cls, render=tex):
""" Create a container in which Expression render is temporary modify """ Create a container in which Expression render is temporary modify
The default temporary render is Expression in order to perform calculus inside numbers The default temporary render is Expression in order to perform calculus inside numbers
@ -56,6 +57,7 @@ class Renderable(object):
""" """
class TmpRenderEnv(object): class TmpRenderEnv(object):
def __enter__(self): def __enter__(self):
self.old_render = Renderable.get_render() self.old_render = Renderable.get_render()
Renderable.set_render(render) Renderable.set_render(render)
@ -72,7 +74,6 @@ class Renderable(object):
return False return False
class Explicable(Renderable): class Explicable(Renderable):
""" An Explicable object is an object which can be explicable! """ An Explicable object is an object which can be explicable!
@ -82,10 +83,11 @@ class Explicable(Renderable):
* explain: Generator which return steps which leed to himself * explain: Generator which return steps which leed to himself
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.steps = [] self.steps = []
def explain(self, noself = True): def explain(self, noself=True):
""" Generate and render steps which leed to itself """ Generate and render steps which leed to itself
:param noself: does explain return self :param noself: does explain return self
@ -126,9 +128,6 @@ class Explicable(Renderable):
return False return False
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
#debuging # debuging
#from debug.tools import report #from debug.tools import report
from .generic import Stack, flatten_list, expand_list, isNumber, isOperator, isNumerand from .generic import Stack, flatten_list, expand_list, isNumber, isOperator, isNumerand
@ -13,13 +13,16 @@ from .random_expression import RdExpression
__all__ = ['Expression'] __all__ = ['Expression']
class Fake_int(int, Explicable): class Fake_int(int, Explicable):
isNumber = True isNumber = True
def __init__(self, val): def __init__(self, val):
super(Fake_int, self).__init__(val) super(Fake_int, self).__init__(val)
self._val = val self._val = val
self.postfix_tokens = [self] self.postfix_tokens = [self]
self.steps = [] self.steps = []
def simplify(self): def simplify(self):
return Fake_int(self._val) return Fake_int(self._val)
@ -28,7 +31,7 @@ class Expression(Explicable):
"""A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown"""
@classmethod @classmethod
def random(self, form="", conditions=[], val_min = -10, val_max=10): def random(self, form="", conditions=[], val_min=-10, val_max=10):
"""Create a random expression from form and with conditions """Create a random expression from form and with conditions
:param form: the form of the expression (/!\ variables need to be in brackets {}) :param form: the form of the expression (/!\ variables need to be in brackets {})
@ -41,7 +44,7 @@ class Expression(Explicable):
return Expression(random_generator(val_min, val_max)) return Expression(random_generator(val_min, val_max))
@classmethod @classmethod
def tmp_render(cls, render = lambda _,x:Expression(x)): def tmp_render(cls, render=lambda _, x: Expression(x)):
""" Same ad tmp_render for Renderable but default render is Expression """ Same ad tmp_render for Renderable but default render is Expression
>>> exp = Expression("2*3/5") >>> exp = Expression("2*3/5")
@ -87,44 +90,56 @@ class Expression(Explicable):
""" """
expression = object.__new__(cls) expression = object.__new__(cls)
if type(exp) == str: if isinstance(exp, str):
expression.postfix_tokens = str2tokens(exp) expression.postfix_tokens = str2tokens(exp)
elif type(exp) == list: elif isinstance(exp, list):
# Ici on ne peut convertir les "+" en opérateur que s'ils sont d'arité 2. # Ici on ne peut convertir les "+" en opérateur que s'ils sont
exp_mod_op = [op.get_op(i) if op.can_be_operator(i) else i for i in exp] # d'arité 2.
expression.postfix_tokens = flatten_list([tok.postfix_tokens if Expression.isExpression(tok) else tok for tok in exp_mod_op]) exp_mod_op = [
op.get_op(i) if op.can_be_operator(i) else i for i in exp]
expression.postfix_tokens = flatten_list(
[tok.postfix_tokens if Expression.isExpression(tok) else tok for tok in exp_mod_op])
elif type(exp) == Expression: elif isinstance(exp, Expression):
return exp return exp
elif isNumerand(exp): elif isNumerand(exp):
expression.postfix_tokens = [exp] expression.postfix_tokens = [exp]
else: else:
raise ValueError("Can't build Expression with {} object".format(type(exp))) raise ValueError(
"Can't build Expression with {} object".format(
type(exp)))
if len(expression.postfix_tokens) == 1: if len(expression.postfix_tokens) == 1:
token = expression.postfix_tokens[0] token = expression.postfix_tokens[0]
if type(token) == Fake_int or type(token) == int: if isinstance(token, Fake_int) or isinstance(token, int):
return Fake_int(token) return Fake_int(token)
elif hasattr(token, 'simplify') and hasattr(token, 'explain'): elif hasattr(token, 'simplify') and hasattr(token, 'explain'):
ans = expression.postfix_tokens[0] ans = expression.postfix_tokens[0]
return ans return ans
elif type(token) == str: elif isinstance(token, str):
# TODO: Pourquoi ne pas créer directement un polynom ici? |jeu. févr. 26 18:59:24 CET 2015 # TODO: Pourquoi ne pas créer directement un polynom ici? |jeu. févr. 26 18:59:24 CET 2015
# On crée un faux str en ajoutant la méthode simplify et simplified et la caractérisique isNumber # On crée un faux str en ajoutant la méthode simplify et
simplify = lambda x:[x] # simplified et la caractérisique isNumber
simplify = lambda x: [x]
is_polynom = True is_polynom = True
methods_attr = {'simplify':simplify, '_isPolynom': is_polynom, 'postfix_tokens': [token]} methods_attr = {
fake_token = type('fake_str', (str,Explicable, ), methods_attr)(token) 'simplify': simplify,
'_isPolynom': is_polynom,
'postfix_tokens': [token]}
fake_token = type(
'fake_str', (str, Explicable, ), methods_attr)(token)
return fake_token return fake_token
else: else:
raise ValueError("Unknow token type in Expression: {}".format(type(token))) raise ValueError(
"Unknow token type in Expression: {}".format(
type(token)))
else: else:
expression._isExpression = 1 expression._isExpression = 1
@ -139,7 +154,8 @@ class Expression(Explicable):
return self.STR_RENDER(self.postfix_tokens) return self.STR_RENDER(self.postfix_tokens)
def __repr__(self): def __repr__(self):
return " ".join(["<", str(self.__class__) , str(self.postfix_tokens), ">"]) return " ".join(["<", str(self.__class__),
str(self.postfix_tokens), ">"])
def simplify(self): def simplify(self):
""" Compute entirely the expression and return the result with .steps attribute """ """ Compute entirely the expression and return the result with .steps attribute """
@ -157,9 +173,10 @@ class Expression(Explicable):
tmpTokenList = [] tmpTokenList = []
while len(tokenList) > 2: while len(tokenList) > 2:
# on va chercher les motifs du genre A B +, quand l'operateur est d'arité 2, pour les calculer # on va chercher les motifs du genre A B +, quand l'operateur est
# d'arité 2, pour les calculer
if isNumerand(tokenList[0]) and isNumerand(tokenList[1]) \ if isNumerand(tokenList[0]) and isNumerand(tokenList[1]) \
and isOperator(tokenList[2]) and tokenList[2].arity == 2 : and isOperator(tokenList[2]) and tokenList[2].arity == 2:
# S'il y a une opération à faire # S'il y a une opération à faire
op1 = tokenList[0] op1 = tokenList[0]
@ -170,7 +187,8 @@ class Expression(Explicable):
tmpTokenList.append(res) tmpTokenList.append(res)
# Comme on vient de faire le calcul, on peut détruire aussi les deux prochains termes # Comme on vient de faire le calcul, on peut détruire aussi les
# deux prochains termes
del tokenList[0:3] del tokenList[0:3]
# Et les motifs du gens A -, quand l'operateur est d'arité 1 # Et les motifs du gens A -, quand l'operateur est d'arité 1
@ -185,7 +203,8 @@ class Expression(Explicable):
tmpTokenList.append(res) tmpTokenList.append(res)
# Comme on vient de faire le calcul, on peut détruire aussi les deux prochains termes # Comme on vient de faire le calcul, on peut détruire aussi les
# deux prochains termes
del tokenList[0:2] del tokenList[0:2]
else: else:
@ -203,7 +222,8 @@ class Expression(Explicable):
tmpTokenList.append(res) tmpTokenList.append(res)
# Comme on vient de faire le calcul, on peut détruire aussi les deux prochains termes # Comme on vient de faire le calcul, on peut détruire aussi les
# deux prochains termes
del tokenList[0:2] del tokenList[0:2]
tmpTokenList += tokenList tmpTokenList += tokenList
@ -255,17 +275,23 @@ class Expression(Explicable):
# Some math manipulations # Some math manipulations
def operate(self, other, operator): def operate(self, other, operator):
if type(other) == Expression: if isinstance(other, Expression):
return Expression(self.postfix_tokens + other.postfix_tokens + [operator]) return Expression(
elif type(other) == list: self.postfix_tokens +
other.postfix_tokens +
[operator])
elif isinstance(other, list):
return Expression(self.postfix_tokens + other + [operator]) return Expression(self.postfix_tokens + other + [operator])
else: else:
return Expression(self.postfix_tokens + [other] + [operator]) return Expression(self.postfix_tokens + [other] + [operator])
def roperate(self, other, operator): def roperate(self, other, operator):
if type(other) == Expression: if isinstance(other, Expression):
return Expression(other.postfix_tokens + self.postfix_tokens + [operator]) return Expression(
elif type(other) == list: other.postfix_tokens +
self.postfix_tokens +
[operator])
elif isinstance(other, list):
return Expression(other + self.postfix_tokens + [operator]) return Expression(other + self.postfix_tokens + [operator])
else: else:
return Expression([other] + self.postfix_tokens + [operator]) return Expression([other] + self.postfix_tokens + [operator])
@ -358,7 +384,7 @@ def untest(exp):
b = a.simplify() b = a.simplify()
for i in b.explain(): for i in b.explain():
#print(type(i)) # print(type(i))
print(i) print(i)
#print(type(a.simplified()), ":", a.simplified()) #print(type(a.simplified()), ":", a.simplified())
@ -371,27 +397,26 @@ if __name__ == '__main__':
Ar = A.simplify() Ar = A.simplify()
for i in Ar.explain(): for i in Ar.explain():
print(i) print(i)
#print("------------") # print("------------")
#for i in Ar.explain(): # for i in Ar.explain():
# print(i) # print(i)
#print(type(Ar)) # print(type(Ar))
# print('\n-----------')
#print('\n-----------')
#A = Expression("-6 / 3 + 10 / -5") #A = Expression("-6 / 3 + 10 / -5")
#Ar = A.simplify() #Ar = A.simplify()
#for i in Ar.explain(): # for i in Ar.explain():
# print(i) # print(i)
#print('\n-----------') # print('\n-----------')
#A = Expression("1/3 + 4/6") #A = Expression("1/3 + 4/6")
#Ar = A.simplify() #Ar = A.simplify()
#for i in Ar.explain(): # for i in Ar.explain():
# print(i) # print(i)
#import doctest #import doctest
#doctest.testmod() # doctest.testmod()
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'

View File

@ -12,10 +12,11 @@ from copy import copy
__all__ = ['Fraction'] __all__ = ['Fraction']
class Fraction(Explicable): class Fraction(Explicable):
"""Fractions!""" """Fractions!"""
def __init__(self, num, denom = 1): def __init__(self, num, denom=1):
"""To initiate a fraction we need a numerator and a denominator """To initiate a fraction we need a numerator and a denominator
:param num: the numerator :param num: the numerator
@ -61,7 +62,7 @@ class Fraction(Explicable):
if self._num == 0: if self._num == 0:
return Expression([0]) return Expression([0])
elif type(self._num) == Fraction or type(self._denom) == Fraction: elif isinstance(self._num, Fraction) or isinstance(self._denom, Fraction):
return self._num / self._denom return self._num / self._denom
elif self._denom < 0: elif self._denom < 0:
@ -76,8 +77,14 @@ class Fraction(Explicable):
return Expression([n_frac]) return Expression([n_frac])
elif gcd_ != 1: elif gcd_ != 1:
n_frac = Fraction(self._num // gcd_ , self._denom // gcd_) n_frac = Fraction(self._num // gcd_, self._denom // gcd_)
ini_step += [Expression([n_frac._num, gcd_, op.mul, n_frac._denom, gcd_, op.mul, op.div ])] ini_step += [Expression([n_frac._num,
gcd_,
op.mul,
n_frac._denom,
gcd_,
op.mul,
op.div])]
n_frac.steps = ini_step + n_frac.steps n_frac.steps = ini_step + n_frac.steps
return n_frac return n_frac
@ -103,7 +110,8 @@ class Fraction(Explicable):
return str(Expression(self.postfix_tokens)) return str(Expression(self.postfix_tokens))
def __repr__(self): def __repr__(self):
return "< Fraction {num} / {denom}>".format(num=self._num, denom = self._denom) return "< Fraction {num} / {denom}>".format(
num=self._num, denom=self._denom)
def __txt__(self): def __txt__(self):
old_render = Expression.get_render() old_render = Expression.get_render()
@ -126,8 +134,8 @@ class Fraction(Explicable):
def convert2fraction(self, other): def convert2fraction(self, other):
""" Convert a other into a fraction """ """ Convert a other into a fraction """
if type(other) == Fraction: if isinstance(other, Fraction):
#cool # cool
number = other number = other
else: else:
number = Fraction(other) number = Fraction(other)
@ -188,10 +196,25 @@ class Fraction(Explicable):
coef1 = number._denom // gcd_denom coef1 = number._denom // gcd_denom
coef2 = self._denom // gcd_denom coef2 = self._denom // gcd_denom
exp = Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.add]) exp = Expression([self._num,
coef1,
op.mul,
self._denom,
coef1,
op.mul,
op.div,
number._num,
coef2,
op.mul,
number._denom,
coef2,
op.mul,
op.div,
op.add])
ans = exp.simplify() ans = exp.simplify()
ini_step = Expression(self.postfix_tokens + number.postfix_tokens + [op.add]) ini_step = Expression(self.postfix_tokens +
number.postfix_tokens + [op.add])
ans.steps = [ini_step] + ans.steps ans.steps = [ini_step] + ans.steps
return ans return ans
@ -240,9 +263,24 @@ class Fraction(Explicable):
coef1 = number._denom // gcd_denom coef1 = number._denom // gcd_denom
coef2 = self._denom // gcd_denom coef2 = self._denom // gcd_denom
exp = Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.sub]) exp = Expression([self._num,
coef1,
op.mul,
self._denom,
coef1,
op.mul,
op.div,
number._num,
coef2,
op.mul,
number._denom,
coef2,
op.mul,
op.div,
op.sub])
ini_step = Expression(self.postfix_tokens + number.postfix_tokens + [op.sub]) ini_step = Expression(self.postfix_tokens +
number.postfix_tokens + [op.sub])
ans = exp.simplify() ans = exp.simplify()
ans.steps = [ini_step] + ans.steps ans.steps = [ini_step] + ans.steps
return ans return ans
@ -313,13 +351,14 @@ class Fraction(Explicable):
elif other == 1: elif other == 1:
return copy(self) return copy(self)
# TODO: Changer dans le cas où il y a trop de 1 |dim. déc. 28 10:44:10 CET 2014 # TODO: Changer dans le cas où il y a trop de 1 |dim. déc. 28 10:44:10
# CET 2014
elif type(other) == int: elif isinstance(other, int):
gcd1 = gcd(other, self._denom) gcd1 = gcd(other, self._denom)
if gcd1 != 1: if gcd1 != 1:
num = [self._num, int(other/gcd1), op.mul, gcd1,op.mul] num = [self._num, int(other / gcd1), op.mul, gcd1, op.mul]
denom = [int(self._denom/gcd1), gcd1, op.mul] denom = [int(self._denom / gcd1), gcd1, op.mul]
else: else:
num = [self._num, other, op.mul] num = [self._num, other, op.mul]
denom = [self._denom] denom = [self._denom]
@ -332,24 +371,29 @@ class Fraction(Explicable):
gcd1 = gcd(self._num, number._denom) gcd1 = gcd(self._num, number._denom)
if gcd1 != 1: if gcd1 != 1:
num1 = [int(self._num/ gcd1), gcd1, op.mul] num1 = [int(self._num / gcd1), gcd1, op.mul]
denom2 = [int(number._denom/ gcd1), gcd1, op.mul] denom2 = [int(number._denom / gcd1), gcd1, op.mul]
else: else:
num1 = [self._num] num1 = [self._num]
denom2 = [number._denom] denom2 = [number._denom]
gcd2 = gcd(self._denom, number._num) gcd2 = gcd(self._denom, number._num)
if gcd2 != 1: if gcd2 != 1:
num2 = [int(number._num/ gcd2), gcd2, op.mul] num2 = [int(number._num / gcd2), gcd2, op.mul]
denom1 = [int(self._denom/ gcd2), gcd2, op.mul] denom1 = [int(self._denom / gcd2), gcd2, op.mul]
else: else:
num2 = [number._num] num2 = [number._num]
denom1 = [self._denom] denom1 = [self._denom]
exp = Expression(num1 +
num2 +
[op.mul] +
denom1 +
denom2 +
[op.mul, op.div])
exp = Expression(num1 + num2 + [ op.mul] + denom1 + denom2 + [op.mul, op.div]) ini_step = Expression(self.postfix_tokens +
number.postfix_tokens + [op.mul])
ini_step = Expression(self.postfix_tokens + number.postfix_tokens + [op.mul])
ans = exp.simplify() ans = exp.simplify()
ans.steps = [ini_step] + ans.steps ans.steps = [ini_step] + ans.steps
return ans return ans
@ -381,7 +425,8 @@ class Fraction(Explicable):
number = self.convert2fraction(other) number = self.convert2fraction(other)
ini_step = Expression(self.postfix_tokens + number.postfix_tokens + [op.div]) ini_step = Expression(self.postfix_tokens +
number.postfix_tokens + [op.div])
number = Fraction(number._denom, number._num) number = Fraction(number._denom, number._num)
ans = self * number ans = self * number
@ -421,8 +466,10 @@ class Fraction(Explicable):
< <class 'pymath.calculus.expression.Expression'> [27, 8, '*', 8, 8, '*', '/'] > < <class 'pymath.calculus.expression.Expression'> [27, 8, '*', 8, 8, '*', '/'] >
""" """
if not type(power) == int: if not isinstance(power, int):
raise ValueError("Can't raise fraction to power {}".format(str(power))) raise ValueError(
"Can't raise fraction to power {}".format(
str(power)))
if power == 0: if power == 0:
return Expression([1]) return Expression([1])
@ -430,7 +477,8 @@ class Fraction(Explicable):
return copy(self) return copy(self)
else: else:
ini_step = Expression(self.postfix_tokens + [power, op.pw]) ini_step = Expression(self.postfix_tokens + [power, op.pw])
exp = Expression([self._num, power, op.pw, self._denom, power, op.pw, op.div]) exp = Expression(
[self._num, power, op.pw, self._denom, power, op.pw, op.div])
ans = exp.simplify() ans = exp.simplify()
ans.steps = [ini_step] + ans.steps ans.steps = [ini_step] + ans.steps
@ -485,71 +533,70 @@ class Fraction(Explicable):
return Fraction(self._num, self._denom) return Fraction(self._num, self._denom)
if __name__ == '__main__': if __name__ == '__main__':
f = Fraction(1, 12) f = Fraction(1, 12)
g = Fraction(6, 12) g = Fraction(6, 12)
for i in g.simplify().explain(): for i in g.simplify().explain():
print("g = ",i) print("g = ", i)
h = Fraction(1,-5) h = Fraction(1, -5)
t = Fraction(10,3) t = Fraction(10, 3)
print("---------") print("---------")
for i in (0 + h).explain(): for i in (0 + h).explain():
print('0 + h = ',i) print('0 + h = ', i)
#print("---------") # print("---------")
#print(str(f) , "+", str(t)) #print(str(f) , "+", str(t))
#for i in (f + t): # for i in (f + t):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(f) , "+", str(g)) #print(str(f) , "+", str(g))
#for i in (f + g): # for i in (f + g):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(f) , "-", str(g)) #print(str(f) , "-", str(g))
#for i in (f - g): # for i in (f - g):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(f) , "*", str(g)) #print(str(f) , "*", str(g))
#for i in (f * g): # for i in (f * g):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "+", str(t)) #print(str(h) , "+", str(t))
#for i in (h + t): # for i in (h + t):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "-", str(t)) #print(str(h) , "-", str(t))
#for i in (h - t): # for i in (h - t):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "*", str(t)) #print(str(h) , "*", str(t))
#for i in (h * t): # for i in (h * t):
# print(i) # print(i)
#print("---------") # print("---------")
#print("-", str(h) ) #print("-", str(h) )
#for i in (-h): # for i in (-h):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "/", str(t)) #print(str(h) , "/", str(t))
#for i in (h / t): # for i in (h / t):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "+", str(0)) #print(str(h) , "+", str(0))
#for i in (h + 0): # for i in (h + 0):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "*", str(1)) #print(str(h) , "*", str(1))
#for i in (h * 1): # for i in (h * 1):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "*", str(0)) #print(str(h) , "*", str(0))
#for i in (h * 0): # for i in (h * 0):
# print(i) # print(i)
#print("---------") # print("---------")
#print(str(h) , "*", str(4)) #print(str(h) , "*", str(4))
#for i in (h * 4): # for i in (h * 4):
# print(i) # print(i)
#print(f.simplify()) # print(f.simplify())
import doctest import doctest
doctest.testmod() doctest.testmod()

View File

@ -4,6 +4,7 @@
from itertools import zip_longest from itertools import zip_longest
class Stack(object): class Stack(object):
"""Docstring for Stack """ """Docstring for Stack """
@ -37,7 +38,7 @@ class Stack(object):
""" """
return self.items.pop() return self.items.pop()
def peek(self, posi = 0): def peek(self, posi=0):
"""Getting the last item """Getting the last item
:param posi: which item to peek 0 (last) 1 (the onebefore the last)... :param posi: which item to peek 0 (last) 1 (the onebefore the last)...
:returns: the item :returns: the item
@ -54,6 +55,7 @@ class Stack(object):
def __add__(self, addList): def __add__(self, addList):
return self.items + addList return self.items + addList
def flatten_list(a, result=None): def flatten_list(a, result=None):
"""Flattens a nested list. """Flattens a nested list.
@ -71,6 +73,7 @@ def flatten_list(a, result=None):
return result return result
def first_elem(ll): def first_elem(ll):
"""Get the first element in imbricates lists """Get the first element in imbricates lists
# TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014 # TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014
@ -93,13 +96,14 @@ def first_elem(ll):
""" """
if hasattr(ll, '__contains__'): if hasattr(ll, '__contains__'):
if len(ll) == 1 and type(ll) == str: if len(ll) == 1 and isinstance(ll, str):
return ll[0] return ll[0]
else: else:
return first_elem(ll[0]) return first_elem(ll[0])
else: else:
return ll return ll
def last_elem(ll): def last_elem(ll):
"""Get the last element in imbricates lists """Get the last element in imbricates lists
# TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014 # TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014
@ -122,7 +126,7 @@ def last_elem(ll):
""" """
if hasattr(ll, '__contains__'): if hasattr(ll, '__contains__'):
if len(ll) == 1 and type(ll) == str: if len(ll) == 1 and isinstance(ll, str):
return ll[-1] return ll[-1]
else: else:
return last_elem(ll[-1]) return last_elem(ll[-1])
@ -139,22 +143,23 @@ def expand_list(list_list):
[[1, 2, 4, 5, 6, 7, 8]] [[1, 2, 4, 5, 6, 7, 8]]
""" """
list_in_list = [i for i in list_list if type(i) == list].copy() list_in_list = [i for i in list_list if isinstance(i, list)].copy()
try: try:
nbr_ans_list = max([len(i) for i in list_in_list]) nbr_ans_list = max([len(i) for i in list_in_list])
ans = [list_list.copy() for i in range(nbr_ans_list)] ans = [list_list.copy() for i in range(nbr_ans_list)]
for (i,l) in enumerate(ans): for (i, l) in enumerate(ans):
for (j,e) in enumerate(l): for (j, e) in enumerate(l):
if type(e) == list: if isinstance(e, list):
ans[i][j] = e[min(i,len(e)-1)] ans[i][j] = e[min(i, len(e) - 1)]
# S'il n'y a pas de liste dans la liste (2e exemple) # S'il n'y a pas de liste dans la liste (2e exemple)
except ValueError: except ValueError:
ans = [list_list] ans = [list_list]
return ans return ans
def add_in_dict(dict1, dict2): def add_in_dict(dict1, dict2):
"""Merge dictionary keys and add the content from dict1 and dict2 """Merge dictionary keys and add the content from dict1 and dict2
@ -172,7 +177,7 @@ def add_in_dict(dict1, dict2):
""" """
new_dict = {} new_dict = {}
new_dict.update(dict1) new_dict.update(dict1)
for (k,v) in dict2.items(): for (k, v) in dict2.items():
if k in new_dict.keys(): if k in new_dict.keys():
new_dict[k] += v new_dict[k] += v
else: else:
@ -180,7 +185,8 @@ def add_in_dict(dict1, dict2):
return new_dict return new_dict
def remove_in_dict(d, value = 0):
def remove_in_dict(d, value=0):
""" In a dictionary, remove keys which have certain value """ In a dictionary, remove keys which have certain value
:param d: the dictionary :param d: the dictionary
@ -193,14 +199,15 @@ def remove_in_dict(d, value = 0):
True True
""" """
new_dict = {} new_dict = {}
for (k,v) in d.items(): for (k, v) in d.items():
if v != value: if v != value:
new_dict[k] = v new_dict[k] = v
return new_dict return new_dict
def convolution_dict(D1, D2, op = lambda x,y:x*y,\
op_key = lambda x,y: x + y, \ def convolution_dict(D1, D2, op=lambda x, y: x * y,
commutative = True, op_twice = lambda x,y: x + y): op_key=lambda x, y: x + y,
commutative=True, op_twice=lambda x, y: x + y):
"""Convolution of two dictionaries """Convolution of two dictionaries
:param D1: First dictionary :param D1: First dictionary
@ -226,21 +233,22 @@ def convolution_dict(D1, D2, op = lambda x,y:x*y,\
for k1 in sorted(D1.keys()): for k1 in sorted(D1.keys()):
for k2 in sorted(D2.keys()): for k2 in sorted(D2.keys()):
if op_key(k1,k2) in new_dict.keys(): if op_key(k1, k2) in new_dict.keys():
key = op_key(k1,k2) key = op_key(k1, k2)
new_dict[key] = op_twice(new_dict[key], op(D1[k1],D2[k2])) new_dict[key] = op_twice(new_dict[key], op(D1[k1], D2[k2]))
elif op_key(k2,k1) in new_dict.keys() and commutative: elif op_key(k2, k1) in new_dict.keys() and commutative:
key = op_key(k2,k1) key = op_key(k2, k1)
new_dict[key] = op_twice(new_dict[key], op(D1[k1],D2[k2])) new_dict[key] = op_twice(new_dict[key], op(D1[k1], D2[k2]))
else: else:
key = op_key(k1,k2) key = op_key(k1, k2)
new_dict[key] = op(D1[k1],D2[k2]) new_dict[key] = op(D1[k1], D2[k2])
return new_dict return new_dict
def spe_zip(l1,l2):
def spe_zip(l1, l2):
"""Zip two lists, if a list is longer, only it's element are taken """Zip two lists, if a list is longer, only it's element are taken
>>> spe_zip([1,2], [3,4]) >>> spe_zip([1,2], [3,4])
@ -248,16 +256,17 @@ def spe_zip(l1,l2):
>>> spe_zip([1,2], [3,4,5]) >>> spe_zip([1,2], [3,4,5])
[[1, 3], [2, 4], 5] [[1, 3], [2, 4], 5]
""" """
tmp = list(zip_longest(l1,l2)) tmp = list(zip_longest(l1, l2))
ans = [] ans = []
for i in tmp: for i in tmp:
if None in i: if None in i:
j = [a for a in i if a != None][-1] j = [a for a in i if a is not None][-1]
else: else:
j = list(i) j = list(i)
ans.append(j) ans.append(j)
return ans return ans
def transpose_fill(list_lists): def transpose_fill(list_lists):
"""Transpose a list of list and if inside list have not the same length, fill with last token """Transpose a list of list and if inside list have not the same length, fill with last token
@ -277,6 +286,7 @@ def transpose_fill(list_lists):
yield col yield col
def isOperator(exp): def isOperator(exp):
"""Check if the expression is an opération in "+-*/:^" """Check if the expression is an opération in "+-*/:^"
@ -285,13 +295,14 @@ def isOperator(exp):
""" """
#return (type(exp) == str and exp in "+-*/:^") # return (type(exp) == str and exp in "+-*/:^")
try: try:
exp.isOperator exp.isOperator
except AttributeError: except AttributeError:
return 0 return 0
return 1 return 1
def isNumber(exp): def isNumber(exp):
"""Check if the expression can be a number """Check if the expression can be a number
@ -302,12 +313,13 @@ def isNumber(exp):
try: try:
exp.isNumber exp.isNumber
except AttributeError: except AttributeError:
if type(exp) == int: if isinstance(exp, int):
return 1 return 1
else: else:
return 0 return 0
return 1 return 1
def isPolynom(exp): def isPolynom(exp):
"""Check if the expression can be a polynom """Check if the expression can be a polynom
@ -330,6 +342,7 @@ def isPolynom(exp):
return 0 return 0
return 1 return 1
def isNumerand(exp): def isNumerand(exp):
"""Check is the expression is something we can compute with """Check is the expression is something we can compute with

View File

@ -13,17 +13,18 @@ import inspect
__all__ = ["Polynom"] __all__ = ["Polynom"]
def polynom_factory(func): def polynom_factory(func):
""" Decorator which specify the type of polynom that the function returns """ """ Decorator which specify the type of polynom that the function returns """
@wraps(func) @wraps(func)
def wrapper(*args, **kwrds): def wrapper(*args, **kwrds):
P = func(*args, **kwrds) P = func(*args, **kwrds)
if issubclass(type(P),AbstractPolynom) and P.degree == 2: if issubclass(type(P), AbstractPolynom) and P.degree == 2:
from .polynomDeg2 import Polynom_deg2 from .polynomDeg2 import Polynom_deg2
new_P = Polynom_deg2(poly=P) new_P = Polynom_deg2(poly=P)
new_P.steps = P.steps new_P.steps = P.steps
return new_P return new_P
elif issubclass(type(P),AbstractPolynom): elif issubclass(type(P), AbstractPolynom):
new_P = Polynom(poly=P) new_P = Polynom(poly=P)
new_P.steps = P.steps new_P.steps = P.steps
return new_P return new_P
@ -31,6 +32,7 @@ def polynom_factory(func):
return P return P
return wrapper return wrapper
class Polynom(AbstractPolynom): class Polynom(AbstractPolynom):
"""Polynom view as a function. """Polynom view as a function.
@ -47,7 +49,13 @@ class Polynom(AbstractPolynom):
""" """
@classmethod @classmethod
def random(self, coefs_form=[], conditions=[], letter = "x", degree = 0, name = "P"): def random(
self,
coefs_form=[],
conditions=[],
letter="x",
degree=0,
name="P"):
""" Create a random polynom from coefs_form and conditions """ Create a random polynom from coefs_form and conditions
:param coefs_form: list of forms (one by coef) (ascending degree sorted) :param coefs_form: list of forms (one by coef) (ascending degree sorted)
@ -71,18 +79,18 @@ class Polynom(AbstractPolynom):
""" """
if (degree > 0 and degree < 26): if (degree > 0 and degree < 26):
# Générer assez de lettre pour les coefs # Générer assez de lettre pour les coefs
coefs_name = map(chr, range(97, 98+degree)) coefs_name = map(chr, range(97, 98 + degree))
coefs_form = ["{" + i + "}" for i in coefs_name][::-1] coefs_form = ["{" + i + "}" for i in coefs_name][::-1]
form = str(coefs_form) form = str(coefs_form)
# On créé les valeurs toutes concaténées dans un string # On créé les valeurs toutes concaténées dans un string
coefs = RdExpression(form, conditions)() coefs = RdExpression(form, conditions)()
# On "parse" ce string pour créer les coefs # On "parse" ce string pour créer les coefs
coefs = [eval(i) if type(i)==str else i for i in eval(coefs)] coefs = [eval(i) if isinstance(i, str) else i for i in eval(coefs)]
# Création du polynom # Création du polynom
return Polynom(coefs = coefs, letter = letter, name = name) return Polynom(coefs=coefs, letter=letter, name=name)
def __init__(self, coefs = [1], letter = "x", name = "P", poly = 0): def __init__(self, coefs=[1], letter="x", name="P", poly=0):
"""Initiate the polynom """Initiate the polynom
:param coef: coefficients of the polynom (ascending degree sorted) :param coef: coefficients of the polynom (ascending degree sorted)
@ -138,10 +146,11 @@ class Polynom(AbstractPolynom):
3 h^{ 2 } + 8 h + 6 3 h^{ 2 } + 8 h + 6
>>> R = P(Q) >>> R = P(Q)
""" """
#if isNumerand(value) or Expression.isExpression(value): # if isNumerand(value) or Expression.isExpression(value):
# postfix_exp = [value if i==self._letter else i for i in self.postfix_tokens] # postfix_exp = [value if i==self._letter else i for i in self.postfix_tokens]
#else: # else:
postfix_exp = [Expression(value) if i==self._letter else i for i in self.postfix_tokens] postfix_exp = [
Expression(value) if i == self._letter else i for i in self.postfix_tokens]
return Expression(postfix_exp).simplify() return Expression(postfix_exp).simplify()
@ -160,7 +169,7 @@ class Polynom(AbstractPolynom):
6 x + 2 6 x + 2
""" """
derv_coefs = [] derv_coefs = []
for (i,c) in enumerate(self._coef): for (i, c) in enumerate(self._coef):
derv_coefs += [Expression([i, c, op.mul])] derv_coefs += [Expression([i, c, op.mul])]
ans = Polynom(derv_coefs[1:]).simplify() ans = Polynom(derv_coefs[1:]).simplify()
@ -178,7 +187,7 @@ for name, func in inspect.getmembers(Polynom):
if __name__ == '__main__': if __name__ == '__main__':
#from .fraction import Fraction #from .fraction import Fraction
#with Expression.tmp_render(txt): # with Expression.tmp_render(txt):
# p = Polynom([1, 2, 3]) # p = Polynom([1, 2, 3])
# q = Polynom([4, 5, 6]) # q = Polynom([4, 5, 6])
# for i in (p*q).explain(): # for i in (p*q).explain():
@ -194,27 +203,28 @@ if __name__ == '__main__':
# print(p-q) # print(p-q)
# for i in p-q: # for i in p-q:
# print(i) # print(i)
#Polynom.random(degree = 2, conditions=["{b**2-4*a*c}>0"]) # Polynom deg 2 with positive Delta (ax^2 + bx + c) # Polynom.random(degree = 2, conditions=["{b**2-4*a*c}>0"]) # Polynom deg
# 2 with positive Delta (ax^2 + bx + c)
#import doctest #import doctest
#doctest.testmod(optionflags=doctest.ELLIPSIS) # doctest.testmod(optionflags=doctest.ELLIPSIS)
# while True: # while True:
# P = Polynom.random(degree = 2) # P = Polynom.random(degree = 2)
# e = Expression.random("{a}/{b}") # e = Expression.random("{a}/{b}")
# try: # try:
# P(e) # P(e)
# except RuntimeError: # except RuntimeError:
# print(" P -> " + str(P)) # print(" P -> " + str(P))
# print(" e -> " + str(e)) # print(" e -> " + str(e))
# #
# import sys # import sys
# sys.setrecursionlimit(100) # sys.setrecursionlimit(100)
from .fraction import Fraction from .fraction import Fraction
from itertools import permutations from itertools import permutations
P = Polynom([-5,6,-4]) P = Polynom([-5, 6, -4])
f = Fraction(2,5) f = Fraction(2, 5)
P(f) P(f)
try: try:
P(f) P(f)
@ -222,15 +232,15 @@ if __name__ == '__main__':
print(e) print(e)
print("-----------------\n") print("-----------------\n")
f = Fraction(2,15) f = Fraction(2, 15)
print(str(P).replace('x','('+str(f)+')'),"= ", P(f)) print(str(P).replace('x', '(' + str(f) + ')'), "= ", P(f))
print("-----------------\n") print("-----------------\n")
f = Fraction(2,3) f = Fraction(2, 3)
print(P(f)) print(P(f))
#coefs_p = [[(i-2),(j-2)] for i,j in permutations(range(20),2)] #coefs_p = [[(i-2),(j-2)] for i,j in permutations(range(20),2)]
#fractions = [Fraction(i,j) for i,j in coefs_p if j!=0] #fractions = [Fraction(i,j) for i,j in coefs_p if j!=0]
#for f in fractions: # for f in fractions:
# try: # try:
# P(f) # P(f)
# #print("ok f -> " + str(f)) # #print("ok f -> " + str(f))

View File

@ -8,10 +8,11 @@ from .operator import op
from .random_expression import RdExpression from .random_expression import RdExpression
from sympy import sqrt, latex from sympy import sqrt, latex
#from sympy.fractions import Fraction as sp.Fraction # from sympy.fractions import Fraction as sp.Fraction
__all__ = ["Polynom_deg2"] __all__ = ["Polynom_deg2"]
class Polynom_deg2(Polynom): class Polynom_deg2(Polynom):
""" Degree 2 polynoms """ Degree 2 polynoms
@ -19,7 +20,15 @@ class Polynom_deg2(Polynom):
""" """
@classmethod @classmethod
def random(self, coefs_form = ["{c}", "{b}", "{a}"], conditions = [], letter = "x", name = "P"): def random(
self,
coefs_form=[
"{c}",
"{b}",
"{a}"],
conditions=[],
letter="x",
name="P"):
""" Create a 2nd degree poly from coefs_form ans conditions """ Create a 2nd degree poly from coefs_form ans conditions
:param coefs_form: list of forms (one by coef) (ascending degree sorted) :param coefs_form: list of forms (one by coef) (ascending degree sorted)
@ -28,27 +37,32 @@ class Polynom_deg2(Polynom):
""" """
if len(coefs_form) != 3: if len(coefs_form) != 3:
raise ValueError("Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format(len(coefs_form))) raise ValueError(
"Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format(
len(coefs_form)))
form = str(coefs_form) form = str(coefs_form)
# On créé les valeurs toutes concaténées dans un string # On créé les valeurs toutes concaténées dans un string
coefs = RdExpression(form, conditions)() coefs = RdExpression(form, conditions)()
# On "parse" ce string pour créer les coefs # On "parse" ce string pour créer les coefs
coefs = [eval(i) if type(i)==str else i for i in eval(coefs)] coefs = [eval(i) if isinstance(i, str) else i for i in eval(coefs)]
# Création du polynom # Création du polynom
return Polynom_deg2(coefs = coefs, letter = letter, name = name) return Polynom_deg2(coefs=coefs, letter=letter, name=name)
def __init__(self, coefs = [0, 0, 1], letter = "x", name = "P", poly = 0): def __init__(self, coefs=[0, 0, 1], letter="x", name="P", poly=0):
if poly: if poly:
coefs = poly._coef coefs = poly._coef
letter = poly._letter letter = poly._letter
name = poly.name name = poly.name
if len(coefs) < 3 or len(coefs) > 4: if len(coefs) < 3 or len(coefs) > 4:
raise ValueError("Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format(len(coefs))) raise ValueError(
"Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format(
len(coefs)))
if coefs[2] == 0: if coefs[2] == 0:
raise ValueError("Polynom_deg2 have to be degree 2 polynoms, coefficient of x^2 can't be 0") raise ValueError(
Polynom.__init__(self, coefs, letter, name = name) "Polynom_deg2 have to be degree 2 polynoms, coefficient of x^2 can't be 0")
Polynom.__init__(self, coefs, letter, name=name)
@property @property
def a(self): def a(self):
@ -78,7 +92,8 @@ class Polynom_deg2(Polynom):
-8 -8
""" """
return Expression([self.b, 2, op.pw, 4, self.a, self.c, op.mul, op.mul, op.sub]).simplify() return Expression([self.b, 2, op.pw, 4, self.a,
self.c, op.mul, op.mul, op.sub]).simplify()
@property @property
def alpha(self): def alpha(self):
@ -94,7 +109,8 @@ class Polynom_deg2(Polynom):
\\frac{ -1 \\times 2 }{ 3 \\times 2 } \\frac{ -1 \\times 2 }{ 3 \\times 2 }
\\frac{ -1 }{ 3 } \\frac{ -1 }{ 3 }
""" """
return Expression([self.b, op.sub1, 2, self.a, op.mul, op.div]).simplify() return Expression([self.b, op.sub1, 2, self.a,
op.mul, op.div]).simplify()
@property @property
def beta(self): def beta(self):
@ -124,7 +140,7 @@ class Polynom_deg2(Polynom):
""" """
return self(self.alpha) return self(self.alpha)
def roots(self, after_coma = 2): def roots(self, after_coma=2):
""" Compute roots of the polynom """ Compute roots of the polynom
/!\ Can't manage nice rendering because of sqrt. /!\ Can't manage nice rendering because of sqrt.
@ -146,9 +162,10 @@ class Polynom_deg2(Polynom):
['-2 - \\\\sqrt{3}', '-2 + \\\\sqrt{3}'] ['-2 - \\\\sqrt{3}', '-2 + \\\\sqrt{3}']
""" """
if self.delta > 0: if self.delta > 0:
self._roots = [latex((-self.b - sqrt(self.delta))/(2*self.a)), latex((-self.b + sqrt(self.delta))/(2*self.a))] self._roots = [latex((-self.b - sqrt(self.delta)) / (2 * self.a)),
latex((-self.b + sqrt(self.delta)) / (2 * self.a))]
elif self.delta == 0: elif self.delta == 0:
self._roots = [Fraction(-self.b,2*self.a).simplify()] self._roots = [Fraction(-self.b, 2 * self.a).simplify()]
else: else:
self._roots = [] self._roots = []
return self._roots return self._roots
@ -156,7 +173,8 @@ class Polynom_deg2(Polynom):
def tbl_sgn_header(self): def tbl_sgn_header(self):
""" Return header of the sign line for tkzTabLine""" """ Return header of the sign line for tkzTabLine"""
if self.delta > 0: if self.delta > 0:
return "{$-\\infty$, $" + str(min(self.roots())) + "$ , $" + str( max(self.roots())) + "$ , $+\\infty$}" return "{$-\\infty$, $" + str(min(self.roots())) + \
"$ , $" + str(max(self.roots())) + "$ , $+\\infty$}"
elif self.delta == 0: elif self.delta == 0:
return "{$-\\infty$, $" + str(self.roots()[0]) + "$ , $+\\infty$}" return "{$-\\infty$, $" + str(self.roots()[0]) + "$ , $+\\infty$}"
else: else:
@ -200,7 +218,7 @@ class Polynom_deg2(Polynom):
else: else:
return "\\tkzTabLine{, -,}" return "\\tkzTabLine{, -,}"
def tbl_variation(self, limits = False): def tbl_variation(self, limits=False):
"""Return the variation line for tkzTabVar """Return the variation line for tkzTabVar
:param limit: Display or not limits in tabular :param limit: Display or not limits in tabular
@ -215,9 +233,11 @@ class Polynom_deg2(Polynom):
beta = self.beta beta = self.beta
if limits: if limits:
if self.a > 0: if self.a > 0:
return "\\tkzTabVar{+/{$+\\infty$}, -/{$" + str(beta) + "$}, +/{$+\\infty$}}" return "\\tkzTabVar{+/{$+\\infty$}, -/{$" + \
str(beta) + "$}, +/{$+\\infty$}}"
else: else:
return "\\tkzTabVar{-/{$-\\infty$}, +/{$" + str(beta) + "$}, -/{$-\\infty$}}" return "\\tkzTabVar{-/{$-\\infty$}, +/{$" + \
str(beta) + "$}, -/{$-\\infty$}}"
else: else:
if self.a > 0: if self.a > 0:
return "\\tkzTabVar{+/{}, -/{$" + str(beta) + "$}, +/{}}" return "\\tkzTabVar{+/{}, -/{$" + str(beta) + "$}, +/{}}"
@ -227,7 +247,7 @@ class Polynom_deg2(Polynom):
if __name__ == '__main__': if __name__ == '__main__':
#from .render import txt #from .render import txt
#with Expression.tmp_render(txt): # with Expression.tmp_render(txt):
# P = Polynom_deg2([2, 3, 4]) # P = Polynom_deg2([2, 3, 4])
# print(P) # print(P)
@ -242,8 +262,6 @@ if __name__ == '__main__':
doctest.testmod() doctest.testmod()
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:

View File

@ -8,11 +8,13 @@ from .generic import flatten_list
from .arithmetic import gcd from .arithmetic import gcd
def random_str(form, conditions = [], val_min = -10, val_max = 10):
def random_str(form, conditions=[], val_min=-10, val_max=10):
""" Create a random string using RdExpression class """ """ Create a random string using RdExpression class """
random_str_generator = RdExpression(form, conditions) random_str_generator = RdExpression(form, conditions)
return random_str_generator(val_min, val_max) return random_str_generator(val_min, val_max)
class RdExpression(object): class RdExpression(object):
""" """
@ -20,7 +22,7 @@ class RdExpression(object):
""" """
def __init__(self, form, conditions = []): def __init__(self, form, conditions=[]):
"""Initiate the generator """Initiate the generator
:param form: the form of the expression (/!\ variables need to be in brackets {}) :param form: the form of the expression (/!\ variables need to be in brackets {})
@ -39,16 +41,18 @@ class RdExpression(object):
:returns: set for elements which have to be replaced :returns: set for elements which have to be replaced
""" """
#pattern = "\{(.*?)\}" #select inside {} non greedy way # pattern = "\{(.*?)\}" #select inside {} non greedy way
#varia_form = re.findall(pattern, self._form) #varia_form = re.findall(pattern, self._form)
# TODO: Bug with varia with spaces |dim. nov. 23 10:44:34 CET 2014 # TODO: Bug with varia with spaces |dim. nov. 23 10:44:34 CET 2014
varia_form = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr('{','}').searchString(self._form)]) varia_form = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr(
'{', '}').searchString(self._form)])
varia_form = set(varia_form) varia_form = set(varia_form)
varia_cond = set() varia_cond = set()
for c in self._conditions: for c in self._conditions:
c_varia_cond = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr('{','}').searchString(c)]) c_varia_cond = flatten_list(
[eval(str(i[0])) for i in pyparsing.nestedExpr('{', '}').searchString(c)])
varia_cond = varia_cond | set(c_varia_cond) varia_cond = varia_cond | set(c_varia_cond)
self._2replaced = varia_cond | varia_form self._2replaced = varia_cond | varia_form
@ -81,11 +85,11 @@ class RdExpression(object):
new_form = form new_form = form
while "_" in new_form: while "_" in new_form:
i += 1 i += 1
new_form = new_form.replace("_", "{"+chr(i)+"}",1) new_form = new_form.replace("_", "{" + chr(i) + "}", 1)
return new_form return new_form
def __call__(self, val_min = -10, val_max = 10): def __call__(self, val_min=-10, val_max=10):
"""RdExpression once it is initiate act like a function which create random expressions. """RdExpression once it is initiate act like a function which create random expressions.
:param val_min: minimum value random generation :param val_min: minimum value random generation
@ -95,7 +99,7 @@ class RdExpression(object):
""" """
return self.raw_str(val_min, val_max) return self.raw_str(val_min, val_max)
def raw_str(self, val_min = -10, val_max = 10): def raw_str(self, val_min=-10, val_max=10):
"""Return raw string (don't use Expression for rendering or parsing) """Return raw string (don't use Expression for rendering or parsing)
:param val_min: minimum value random generation :param val_min: minimum value random generation
@ -112,7 +116,7 @@ class RdExpression(object):
return exp return exp
def gene_varia(self, val_min = -10, val_max = 10): def gene_varia(self, val_min=-10, val_max=10):
"""Randomly generates variables/letters """Randomly generates variables/letters
Varia can't be equal to 0 Varia can't be equal to 0
@ -123,7 +127,6 @@ class RdExpression(object):
while self._gene_varia[l] == 0: while self._gene_varia[l] == 0:
self._gene_varia[l] = randint(val_min, val_max) self._gene_varia[l] = randint(val_min, val_max)
for e in self._2replaced: for e in self._2replaced:
self._gene_2replaced[e] = eval(e, globals(), self._gene_varia) self._gene_2replaced[e] = eval(e, globals(), self._gene_varia)
@ -133,18 +136,22 @@ class RdExpression(object):
""" """
if self._conditions != []: if self._conditions != []:
return eval(" and ".join(self._conditions).format(**self._gene_2replaced)) return eval(
" and ".join(
self._conditions).format(
**self._gene_2replaced))
else: else:
return True return True
def desc_rdExp(rdExp): def desc_rdExp(rdExp):
print("--------------------") print("--------------------")
print("form: ",rdExp._form) print("form: ", rdExp._form)
print("Conditions: ",rdExp._conditions) print("Conditions: ", rdExp._conditions)
print("Letters: ", rdExp._letters) print("Letters: ", rdExp._letters)
print("2replaced: ", rdExp._2replaced) print("2replaced: ", rdExp._2replaced)
print("Call : ", rdExp()) print("Call : ", rdExp())
print("type: ",type(rdExp())) print("type: ", type(rdExp()))
print("Gene varia: ", rdExp._gene_varia) print("Gene varia: ", rdExp._gene_varia)
print("Gene 2replaced: ", rdExp._gene_2replaced) print("Gene 2replaced: ", rdExp._gene_2replaced)
print('') print('')
@ -156,18 +163,25 @@ if __name__ == '__main__':
print(random_str(form, cond)) print(random_str(form, cond))
form = "{a+a*10}*4 + {a} + 2*{b}" form = "{a+a*10}*4 + {a} + 2*{b}"
cond = ["{a} + {b} in [1, 2, 3, 4, 5]", "abs({a}) not in [1]", "{b} not in [1]", "gcd({a},{b}) == 1"] cond = [
"{a} + {b} in [1, 2, 3, 4, 5]",
"abs({a}) not in [1]",
"{b} not in [1]",
"gcd({a},{b}) == 1"]
print(random_str(form, cond)) print(random_str(form, cond))
form = "{a+a*10}*4 + {a} + 2*{b}" form = "{a+a*10}*4 + {a} + 2*{b}"
cond = ["{a-b} + {b} in list(range(20))", "abs({a}) not in [1]", "{b} not in [1]", "gcd({a},{b}) == 1"] cond = [
"{a-b} + {b} in list(range(20))",
"abs({a}) not in [1]",
"{b} not in [1]",
"gcd({a},{b}) == 1"]
print(random_str(form, cond)) print(random_str(form, cond))
import doctest import doctest
doctest.testmod() doctest.testmod()
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:

View File

@ -1,10 +1,11 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
from .generic import Stack,isOperator from .generic import Stack, isOperator
__all__ = ['txt', 'tex', 'p2i'] __all__ = ['txt', 'tex', 'p2i']
class Render(object): class Render(object):
""" Create functions which know how to render postfix tokens lists """ """ Create functions which know how to render postfix tokens lists """
@ -15,7 +16,6 @@ class Render(object):
""" """
self.render = render self.render = render
def __call__(self, postfix_tokens): def __call__(self, postfix_tokens):
"""Make the object acting like a function """Make the object acting like a function
@ -45,6 +45,7 @@ class Render(object):
else: else:
return operandeStack.pop() return operandeStack.pop()
def txt_render(token): def txt_render(token):
def render(*args): def render(*args):
try: try:
@ -54,6 +55,8 @@ def txt_render(token):
return render return render
txt = Render(txt_render) txt = Render(txt_render)
def tex_render(token): def tex_render(token):
def render(*args): def render(*args):
try: try:
@ -63,6 +66,7 @@ def tex_render(token):
return render return render
tex = Render(tex_render) tex = Render(tex_render)
def p2i_render(token): def p2i_render(token):
def render(*args): def render(*args):
try: try:
@ -78,18 +82,17 @@ if __name__ == '__main__':
from pymath import Polynom from pymath import Polynom
from pymath import Expression from pymath import Expression
from pymath import Fraction from pymath import Fraction
coefs_p = [[(i-2),(j-2)] for i,j in permutations(range(5),2)] coefs_p = [[(i - 2), (j - 2)] for i, j in permutations(range(5), 2)]
coefs_q = [[2*(i-2),2*(j-2)] for i,j in permutations(range(5),2)] coefs_q = [[2 * (i - 2), 2 * (j - 2)]
for i, j in permutations(range(5), 2)]
l_p = [Polynom(i) for i in coefs_p] l_p = [Polynom(i) for i in coefs_p]
l_q = [Fraction(i,j) for i,j in coefs_q if j!=0] l_q = [Fraction(i, j) for i, j in coefs_q if j != 0]
operations = [Expression([l_p[i],l_q[j],op.mul]) for i,j in permutations(range(len(l_q)),2)] operations = [Expression([l_p[i], l_q[j], op.mul])
for i, j in permutations(range(len(l_q)), 2)]
for i in operations: for i in operations:
print(i) print(i)
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:

View File

@ -4,6 +4,7 @@
from .generic import Stack, isOperator, isNumber, isPolynom from .generic import Stack, isOperator, isNumber, isPolynom
from .operator import op from .operator import op
def str2tokens(exp): def str2tokens(exp):
""" Parse the string into tokens then turn it into postfix form """ Parse the string into tokens then turn it into postfix form
@ -19,6 +20,7 @@ def str2tokens(exp):
return post_tokens return post_tokens
def str2in_tokens(exp): def str2in_tokens(exp):
""" Parse the expression, ie tranform a string into a list of tokens """ Parse the expression, ie tranform a string into a list of tokens
@ -37,14 +39,14 @@ def str2in_tokens(exp):
for character in exp: for character in exp:
if character.isdigit(): if character.isdigit():
# for "big" numbers (like 2345) # for "big" numbers (like 2345)
if type(tokens[-1]) == int: if isinstance(tokens[-1], int):
if tokens[-1] > 0: if tokens[-1] > 0:
tokens[-1] = tokens[-1]*10 + int(character) tokens[-1] = tokens[-1] * 10 + int(character)
else: else:
tokens[-1] = tokens[-1]*10 - int(character) tokens[-1] = tokens[-1] * 10 - int(character)
# Special case for "-" at the begining of an expression or before
# Special case for "-" at the begining of an expression or before "(" # "("
elif tokens[-1] == "-" and \ elif tokens[-1] == "-" and \
str(tokens[-2]) in " (+-*/:": str(tokens[-2]) in " (+-*/:":
tokens[-1] = - int(character) tokens[-1] = - int(character)
@ -72,7 +74,7 @@ def str2in_tokens(exp):
or isPolynom(tokens[-1]): or isPolynom(tokens[-1]):
tokens.append("*") tokens.append("*")
from pymath.calculus.polynom import Polynom from pymath.calculus.polynom import Polynom
tokens.append(Polynom([0,1], letter = character)) tokens.append(Polynom([0, 1], letter=character))
elif character == ".": elif character == ".":
raise ValueError("No float number please") raise ValueError("No float number please")
@ -83,7 +85,6 @@ def str2in_tokens(exp):
return tokens[1:] return tokens[1:]
def in2post_fix(infix_tokens): def in2post_fix(infix_tokens):
""" From the infix_tokens list compute the corresponding postfix_tokens list """ From the infix_tokens list compute the corresponding postfix_tokens list
@ -105,7 +106,7 @@ def in2post_fix(infix_tokens):
arity_Stack = Stack() arity_Stack = Stack()
arity_Stack.push(0) arity_Stack.push(0)
for (pos_token,token) in enumerate(infix_tokens): for (pos_token, token) in enumerate(infix_tokens):
# Pour voir ce qu'il se passe dans cette procédure # Pour voir ce qu'il se passe dans cette procédure
#print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack)) #print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack))
@ -129,9 +130,11 @@ def in2post_fix(infix_tokens):
else: else:
arity = arity_Stack.pop() arity = arity_Stack.pop()
token_op = op.get_op(token, arity + 1) token_op = op.get_op(token, arity + 1)
# Reset arity to 0 in case there is other operators (the real operation would be "-op.arity + 1") # Reset arity to 0 in case there is other operators (the real
# operation would be "-op.arity + 1")
arity_Stack.push(0) arity_Stack.push(0)
while (not opStack.isEmpty()) and opStack.peek().priority >= token_op.priority: while (not opStack.isEmpty()) and opStack.peek(
).priority >= token_op.priority:
next_op = opStack.pop() next_op = opStack.pop()
postfix_tokens.append(next_op) postfix_tokens.append(next_op)
@ -142,29 +145,30 @@ def in2post_fix(infix_tokens):
arity = arity_Stack.pop() arity = arity_Stack.pop()
arity_Stack.push(arity + 1) arity_Stack.push(arity + 1)
## Pour voir ce qu'il se passe dans cette procédure # Pour voir ce qu'il se passe dans cette procédure
#print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack)) #print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack))
while not opStack.isEmpty(): while not opStack.isEmpty():
next_op = opStack.pop() next_op = opStack.pop()
postfix_tokens.append(next_op) postfix_tokens.append(next_op)
## Pour voir ce qu'il se passe dans cette procédure # Pour voir ce qu'il se passe dans cette procédure
#print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack)) #print(str(postfix_tokens), " | ", str(opStack), " | ", str(infix_tokens[(pos_token+1):]), " | ", str(arity_Stack))
if arity_Stack.peek() != 1: if arity_Stack.peek() != 1:
raise ValueError("Unvalid expression. The arity Stack is ", str(arity_Stack)) raise ValueError(
"Unvalid expression. The arity Stack is ",
str(arity_Stack))
return postfix_tokens return postfix_tokens
if __name__ == '__main__': if __name__ == '__main__':
#a, s, m, d, p = Operator("+"), Operator("-"), Operator("*"), Operator("/"), Operator("^") #a, s, m, d, p = Operator("+"), Operator("-"), Operator("*"), Operator("/"), Operator("^")
#in_tokens = str2in_tokens("2+3*4") #in_tokens = str2in_tokens("2+3*4")
#print("\t in_tokens :" + str(in_tokens)) #print("\t in_tokens :" + str(in_tokens))
# #
#print(in2post_fix(in_tokens)) # print(in2post_fix(in_tokens))
#print(in2post_fix([op.par, 2, op.add, 5, op.sub, 1, ')', op.div, op.par, 3, op.mul, 4, ')'])) #print(in2post_fix([op.par, 2, op.add, 5, op.sub, 1, ')', op.div, op.par, 3, op.mul, 4, ')']))
#print(in2post_fix([op.sub1, op.par, op.sub1, 2, ')'])) #print(in2post_fix([op.sub1, op.par, op.sub1, 2, ')']))
@ -179,7 +183,7 @@ if __name__ == '__main__':
print(str2tokens('x(2+1)+4')) print(str2tokens('x(2+1)+4'))
print("\n------") print("\n------")
#import doctest #import doctest
#doctest.testmod() # doctest.testmod()
# ----------------------------- # -----------------------------

View File

@ -7,12 +7,14 @@
# #
# #
# TODO: Rendre toutes les réponses Explicable!! |mar. janv. 12 09:41:00 EAT 2016 # TODO: Rendre toutes les réponses Explicable!! |mar. janv. 12 09:41:00
# EAT 2016
from math import sqrt, ceil from math import sqrt, ceil
from .number_tools import number_factory from .number_tools import number_factory
from .random_generator import random_generator from .random_generator import random_generator
class Dataset(list): class Dataset(list):
""" A dataset (a list) with statistics and latex rendering methods """ A dataset (a list) with statistics and latex rendering methods
@ -30,11 +32,11 @@ class Dataset(list):
""" """
@classmethod @classmethod
def random(cls, length, data_name = "Valeurs", \ def random(cls, length, data_name="Valeurs",
distrib = "gauss", rd_args = (0,1), \ distrib="gauss", rd_args=(0, 1),
nbr_format = lambda x:round(x,2), \ nbr_format=lambda x: round(x, 2),
v_min = None, v_max = None, \ v_min=None, v_max=None,
exact_mean = None): exact_mean=None):
""" Generate a random list of value """ Generate a random list of value
:param length: length of the dataset :param length: length of the dataset
@ -45,15 +47,15 @@ class Dataset(list):
:param v_max: maximum accepted value :param v_max: maximum accepted value
:param exact_mean: if set, the last generated number will be create in order that the computed mean is exacly equal to "exact_mean" :param exact_mean: if set, the last generated number will be create in order that the computed mean is exacly equal to "exact_mean"
""" """
data = random_generator(length,\ data = random_generator(length,
distrib, rd_args, \ distrib, rd_args,
nbr_format, \ nbr_format,
v_min, v_max, \ v_min, v_max,
exact_mean) exact_mean)
return cls(data, data_name = data_name) return cls(data, data_name=data_name)
def __init__(self, data = [], data_name = "Valeurs"): def __init__(self, data=[], data_name="Valeurs"):
""" """
Create a numeric data set Create a numeric data set
@ -86,7 +88,7 @@ class Dataset(list):
@number_factory @number_factory
def mean(self): def mean(self):
return self.sum()/self.effectif_total() return self.sum() / self.effectif_total()
@number_factory @number_factory
def deviation(self): def deviation(self):
@ -96,7 +98,7 @@ class Dataset(list):
@number_factory @number_factory
def variance(self): def variance(self):
return self.deviation()/self.effectif_total() return self.deviation() / self.effectif_total()
@number_factory @number_factory
def sd(self): def sd(self):
@ -113,10 +115,15 @@ class Dataset(list):
>>> w.quartiles() >>> w.quartiles()
(0, 2.5, 5.5, 8.5, 11) (0, 2.5, 5.5, 8.5, 11)
""" """
return (min(self) , self.quartile(1) , self.quartile(2) , self.quartile(3), max(self)) return (
min(self),
self.quartile(1),
self.quartile(2),
self.quartile(3),
max(self))
@number_factory @number_factory
def quartile(self, quartile = 1): def quartile(self, quartile=1):
""" """
Calcul un quartile de la série. Calcul un quartile de la série.
@ -145,11 +152,11 @@ class Dataset(list):
# -1 to match with list indexing # -1 to match with list indexing
position = self.posi_quartile(quartile) - 1 position = self.posi_quartile(quartile) - 1
if position.is_integer(): if position.is_integer():
return (self[int(position)] + self[int(position)+1])/2 return (self[int(position)] + self[int(position) + 1]) / 2
else: else:
return self[ceil(position)] return self[ceil(position)]
def posi_quartile(self, quartile = 1): def posi_quartile(self, quartile=1):
""" """
Calcul la position du quartile Calcul la position du quartile
@ -162,20 +169,22 @@ class Dataset(list):
# -------------------------- # --------------------------
# Rendu latex # Rendu latex
def tabular_latex(self, nbr_lines = 1): def tabular_latex(self, nbr_lines=1):
""" Latex code to display dataset as a tabular """ """ Latex code to display dataset as a tabular """
d_per_line = self.effectif_total() // nbr_lines d_per_line = self.effectif_total() // nbr_lines
d_last_line = self.effectif_total() % d_per_line d_last_line = self.effectif_total() % d_per_line
splited_data = [self[x:x+d_per_line] for x in range(0, self.effectif_total(), d_per_line)] splited_data = [self[x:x + d_per_line]
for x in range(0, self.effectif_total(), d_per_line)]
# On ajoute les éléments manquant pour la dernière line # On ajoute les éléments manquant pour la dernière line
if d_last_line: if d_last_line:
splited_data[-1] += [' ']*(d_per_line - d_last_line) splited_data[-1] += [' '] * (d_per_line - d_last_line)
# Construction du tableau # Construction du tableau
latex = "\\begin{{tabular}}{{|c|*{{{nbr_col}}}{{c|}}}} \n".format(nbr_col = d_per_line) latex = "\\begin{{tabular}}{{|c|*{{{nbr_col}}}{{c|}}}} \n".format(
nbr_col=d_per_line)
latex += "\t\t \hline \n" latex += "\t\t \hline \n"
d_lines = [' & '.join(map(str,l)) for l in splited_data] d_lines = [' & '.join(map(str, l)) for l in splited_data]
latex += " \\\\ \n \\hline \n".join(d_lines) latex += " \\\\ \n \\hline \n".join(d_lines)
latex += " \\\\ \n \\hline \n" latex += " \\\\ \n \\hline \n"
@ -184,9 +193,7 @@ class Dataset(list):
return latex return latex
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del # cursor: 16 del

View File

@ -19,9 +19,7 @@ def number_factory(fun):
return wrapper return wrapper
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del # cursor: 16 del

View File

@ -4,11 +4,11 @@
from random import randint, uniform, gauss, choice from random import randint, uniform, gauss, choice
def random_generator(length,\ def random_generator(length,
distrib = gauss, rd_args = (0,1), \ distrib=gauss, rd_args=(0, 1),
nbr_format = lambda x:round(x,2), \ nbr_format=lambda x: round(x, 2),
v_min = None, v_max = None, \ v_min=None, v_max=None,
exact_mean = None): exact_mean=None):
""" Generate a random list of value """ Generate a random list of value
:param length: length of the dataset :param length: length of the dataset
@ -28,22 +28,26 @@ def random_generator(length,\
""" """
# if exact_mean is set, we create automaticaly only length-1 value # if exact_mean is set, we create automaticaly only length-1 value
if exact_mean != None: if exact_mean is not None:
length = length - 1 length = length - 1
# build function to test created values # build function to test created values
if v_min == None: if v_min is None:
v1 = lambda x: True v1 = lambda x: True
else: else:
v1 = lambda x: x >= v_min v1 = lambda x: x >= v_min
if v_max == None: if v_max is None:
v2 = lambda x: True v2 = lambda x: True
else: else:
v2 = lambda x: x <= v_max v2 = lambda x: x <= v_max
validate = lambda x : v1(x) and v2(x) validate = lambda x: v1(x) and v2(x)
# get distrib function # get distrib function
distribs = {"gauss": gauss, "uniform": uniform, "randint":randint, "choice":choice} distribs = {
"gauss": gauss,
"uniform": uniform,
"randint": randint,
"choice": choice}
try: try:
distrib(*rd_args) distrib(*rd_args)
except TypeError: except TypeError:
@ -59,10 +63,11 @@ def random_generator(length,\
data.append(v) data.append(v)
# Build last value # Build last value
if exact_mean != None: if exact_mean is not None:
last_v = nbr_format((length+1) * exact_mean - sum(data)) last_v = nbr_format((length + 1) * exact_mean - sum(data))
if not validate(last_v): if not validate(last_v):
raise ValueError("Can't build the last value. Conflict between v_min/v_max and exact_mean") raise ValueError(
"Can't build the last value. Conflict between v_min/v_max and exact_mean")
data.append(last_v) data.append(last_v)
return data return data
@ -71,4 +76,3 @@ def random_generator(length,\
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del # cursor: 16 del

View File

@ -35,7 +35,12 @@ class WeightedDataset(dict):
""" """
def __init__(self, datas = [], data_name = "Valeurs", weights = [], weight_name = "Effectifs"): def __init__(
self,
datas=[],
data_name="Valeurs",
weights=[],
weight_name="Effectifs"):
""" """
Initiate the WeightedDataset Initiate the WeightedDataset
""" """
@ -45,14 +50,14 @@ class WeightedDataset(dict):
if len(datas) != len(weights): if len(datas) != len(weights):
raise ValueError("Datas and weights should have same length") raise ValueError("Datas and weights should have same length")
else: else:
weightedDatas = {i[0]:i[1] for i in zip(datas, weights)} weightedDatas = {i[0]: i[1] for i in zip(datas, weights)}
dict.__init__(self, weightedDatas) dict.__init__(self, weightedDatas)
self.data_name = data_name self.data_name = data_name
self.weight_name = weight_name self.weight_name = weight_name
def add_data(self, data, weight = 1): def add_data(self, data, weight=1):
try: try:
self[data] += weight self[data] += weight
except KeyError: except KeyError:
@ -68,21 +73,21 @@ class WeightedDataset(dict):
@number_factory @number_factory
def sum(self): def sum(self):
""" Not really a sum but the sum of the product of key and values """ """ Not really a sum but the sum of the product of key and values """
return sum([k*v for (k,v) in self.items()]) return sum([k * v for (k, v) in self.items()])
@number_factory @number_factory
def mean(self): def mean(self):
return self.sum()/self.effectif_total() return self.sum() / self.effectif_total()
@number_factory @number_factory
def deviation(self): def deviation(self):
""" Compute the deviation (not normalized) """ """ Compute the deviation (not normalized) """
mean = self.mean() mean = self.mean()
return sum([v*(k - mean)**2 for (k,v) in self.items()]) return sum([v * (k - mean)**2 for (k, v) in self.items()])
@number_factory @number_factory
def variance(self): def variance(self):
return self.deviation()/self.effectif_total() return self.deviation() / self.effectif_total()
@number_factory @number_factory
def sd(self): def sd(self):
@ -103,10 +108,14 @@ class WeightedDataset(dict):
(1, 3, 4, 5, 5) (1, 3, 4, 5, 5)
""" """
return (min(self.keys()) , self.quartile(1) , self.quartile(2) , self.quartile(3), max(self.keys())) return (min(self.keys()),
self.quartile(1),
self.quartile(2),
self.quartile(3),
max(self.keys()))
@number_factory @number_factory
def quartile(self, quartile = 1): def quartile(self, quartile=1):
""" """
Calcul un quartile de la série. Calcul un quartile de la série.
@ -134,13 +143,14 @@ class WeightedDataset(dict):
""" """
# -1 to match with list indexing # -1 to match with list indexing
position = self.posi_quartile(quartile) - 1 position = self.posi_quartile(quartile) - 1
expanded_values = flatten_list([v*[k] for (k,v) in self.items()]) expanded_values = flatten_list([v * [k] for (k, v) in self.items()])
if position.is_integer(): if position.is_integer():
return (expanded_values[int(position)] + expanded_values[int(position)+1])/2 return (expanded_values[int(position)] +
expanded_values[int(position) + 1]) / 2
else: else:
return expanded_values[ceil(position)] return expanded_values[ceil(position)]
def posi_quartile(self, quartile = 1): def posi_quartile(self, quartile=1):
""" """
Calcul la position du quartile Calcul la position du quartile
@ -150,21 +160,22 @@ class WeightedDataset(dict):
""" """
return quartile * self.effectif_total() / 4 return quartile * self.effectif_total() / 4
# -------------------------- # --------------------------
# Rendu latex # Rendu latex
def tabular_latex(self): def tabular_latex(self):
""" Latex code to display dataset as a tabular """ """ Latex code to display dataset as a tabular """
latex = "\\begin{{tabular}}{{|c|*{{{nbr_col}}}{{c|}}}} \n".format(nbr_col = len(self.keys())) latex = "\\begin{{tabular}}{{|c|*{{{nbr_col}}}{{c|}}}} \n".format(
nbr_col=len(self.keys()))
latex += "\t \hline \n" latex += "\t \hline \n"
data_line = "\t {data_name} ".format(data_name = self.data_name) data_line = "\t {data_name} ".format(data_name=self.data_name)
weight_line = "\t {weight_name} ".format(weight_name = self.weight_name) weight_line = "\t {weight_name} ".format(weight_name=self.weight_name)
# TODO: Il faudra trouver une solution pour le formatage des données |sam. janv. 9 13:14:26 EAT 2016 # TODO: Il faudra trouver une solution pour le formatage des données
for (v,e) in self.items(): # |sam. janv. 9 13:14:26 EAT 2016
data_line += "& {val} ".format(val = v) for (v, e) in self.items():
weight_line += "& {eff} ".format(eff = e) data_line += "& {val} ".format(val=v)
weight_line += "& {eff} ".format(eff=e)
latex += data_line + "\\\\ \n \t \\hline \n" latex += data_line + "\\\\ \n \t \\hline \n"
latex += weight_line + "\\\\ \n \t \\hline \n" latex += weight_line + "\\\\ \n \t \\hline \n"
@ -177,4 +188,3 @@ class WeightedDataset(dict):
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del # cursor: 16 del