From b3a07bf6e4337fc9dce9405e24789d9d76a0714f Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 09:15:21 +0100 Subject: [PATCH 1/9] adapt test on __call__ for polynom --- test/test_polynom.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/test_polynom.py b/test/test_polynom.py index 8c1cdf3..79743a7 100644 --- a/test/test_polynom.py +++ b/test/test_polynom.py @@ -33,20 +33,19 @@ class TestPolynom(unittest.TestCase): def test_eval_base(self): p = Polynom([1, 2]) - self.assertEqual(p(3).simplify(), 7) + self.assertEqual(p(3), 7) def test_eval_const(self): p = Polynom([1]) - self.assertEqual(p(3).simplify(), 1) + self.assertEqual(p(3), 1) def test_eval_const_neg(self): p = Polynom([-1]) - self.assertEqual(p(3).simplify(), -1) + self.assertEqual(p(3), -1) def test_eval_poly(self): p = Polynom([1, 2]) - hp1 = Expression("h+1") - self.assertEqual(p(hp1).simplify(), Polynom([3,2], "h")) + self.assertEqual(p("h+1"), Polynom([3,2], "h")) #def test_print(self): # p = Polynom([1,2,3]) From 6e1783da437d9648897492e9d2dd027a294921eb Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 09:15:38 +0100 Subject: [PATCH 2/9] solve bug with * and ** and polynom of high degree --- pymath/polynom.py | 57 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/pymath/polynom.py b/pymath/polynom.py index bf39fe2..ebc9223 100644 --- a/pymath/polynom.py +++ b/pymath/polynom.py @@ -5,7 +5,7 @@ from .expression import Expression from .explicable import Explicable from .operator import op -from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom +from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand from .render import txt from .random_expression import RdExpression from itertools import chain @@ -102,13 +102,27 @@ class Polynom(Explicable): :returns: Expression ready to be simplify + >>> P = Polynom([1, 2, 3]) + >>> P(2) + 17 + >>> for i in P(2).explain(): + ... print(i) + 3 \\times 2^{ 2 } + 2 \\times 2 + 1 + 3 \\times 4 + 4 + 1 + 12 + 4 + 1 + 16 + 1 + 17 + >>> Q = P("1+h") + >>> print(Q) + 3 h^{ 2 } + 8 h + 6 + >>> R = P(Q) """ - if isNumber(value): + if isNumerand(value) or Expression.isExpression(value): postfix_exp = [value if i==self._letter else i for i in self.postfix_tokens] else: postfix_exp = [Expression(value) if i==self._letter else i for i in self.postfix_tokens] - return Expression(postfix_exp) + return Expression(postfix_exp).simplify() def feed_coef(self, l_coef): """Feed coef of the polynom. Manage differently whether it's a number or an expression @@ -525,12 +539,15 @@ class Polynom(Explicable): [[< [2, 'x', '*', 1, '+', 4, 'x', 2, '^', '*', '*'] >], < Polynom [0, 0, 4, < [2, 4, '*'] >]>, < Polynom [0, 0, 4, < [2, 4, '*'] >]>] >>> p*r < Polynom [0, 1, 2]> - + >>> P = Polynom([1,2,3]) + >>> Q = Polynom([4,5,6]) + >>> P*Q + < Polynom [4, 13, 28, 27, 18]> """ # TODO: Je trouve qu'elle grille trop d'étapes... |ven. févr. 27 19:08:44 CET 2015 o_poly = self.conv2poly(other) - coefs = [] + coefs = [0]*(self.degree + o_poly.degree + 1) for (i,a) in enumerate(self._coef): for (j,b) in enumerate(o_poly._coef): if a == 0 or b == 0: @@ -541,13 +558,14 @@ class Polynom(Explicable): elem = a else: elem = Expression([a, b, op.mul]) - try: - if coefs[i+j]==0: - coefs[i+j] = elem - elif elem != 0: - coefs[i+j] = [coefs[i+j], elem] - except IndexError: - coefs.append(elem) + + if coefs[i+j]==0: + coefs[i+j] = elem + elif elem != 0: + if type(coefs[i+j]) == list: + coefs[i+j] += [elem] + else: + coefs[i+j] = [coefs[i+j] , elem] p = Polynom(coefs, letter = self._letter) ini_step = [Expression(self.postfix_tokens + o_poly.postfix_tokens + [op.mul])] @@ -578,6 +596,9 @@ class Polynom(Explicable): >>> p = Polynom([0,0,1]) >>> p**3 < Polynom [0, 0, 0, 0, 0, 0, 1]> + >>> p = Polynom([1,2,3]) + >>> p**2 + < Polynom [1, 4, 10, 12, 9]> """ if not type(power): @@ -646,11 +667,11 @@ def test(p,q): if __name__ == '__main__': #from .fraction import Fraction - # with Expression.tmp_render(txt): - # p = Polynom([1,2,3]) - # q = Polynom([0, 2]) - # for i in (p*q).explain(): - # print(i) + #with Expression.tmp_render(txt): + # p = Polynom([1, 2, 3]) + # q = Polynom([4, 5, 6]) + # for i in (p*q).explain(): + # print(i) # r = Polynom([0,1]) # for i in (r*3).explain(): # print(i) @@ -662,7 +683,7 @@ if __name__ == '__main__': # print(p-q) # for i in p-q: # 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 From 4296242afd7f625efb6e3cf9a7c81ed8a3ac0f80 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 11:05:15 +0100 Subject: [PATCH 3/9] mod __tex__ and __txt__ for Polynom --- pymath/polynom.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pymath/polynom.py b/pymath/polynom.py index ebc9223..eb31271 100644 --- a/pymath/polynom.py +++ b/pymath/polynom.py @@ -6,7 +6,7 @@ from .expression import Expression from .explicable import Explicable from .operator import op from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand -from .render import txt +from .render import txt,tex from .random_expression import RdExpression from itertools import chain from functools import wraps @@ -171,10 +171,10 @@ class Polynom(Explicable): return "< Polynom " + str(self._coef) + ">" def __txt__(self): - return self.postfix_tokens + return txt(self.postfix_tokens) def __tex__(self): - return self.postfix_tokens + return tex(self.postfix_tokens) def coef_postfix(self, a, i): """Return the postfix display of a coeficient From c832ae574231f4edd6faa796a75c8d7beca27a04 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 15:11:08 +0100 Subject: [PATCH 4/9] Add test with polynom in render --- test/test_render.py | 53 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/test/test_render.py b/test/test_render.py index 0dee1dd..b94f995 100644 --- a/test/test_render.py +++ b/test/test_render.py @@ -6,6 +6,7 @@ import unittest from pymath.render import tex, txt,p2i from pymath.fraction import Fraction +from pymath.polynom import Polynom from pymath.operator import op @@ -22,6 +23,10 @@ class TestTexRender(unittest.TestCase): def test_type_render_fraction(self): self.assertEqual(tex([Fraction(1,2)]), "\\frac{ 1 }{ 2 }") + def test_type_render_poly(self): + P = Polynom([1,2,3]) + self.assertEqual(tex([P]), "3 x^{ 2 } + 2 x + 1") + def test_mult_interger(self): exps = [ [2, 3, op.get_op("*", 2)], [2, -3, op.get_op("*", 2)], [-2, 3, op.get_op("*", 2)]] wanted_render = [ "2 \\times 3", "2 \\times ( -3 )", "-2 \\times 3"] @@ -37,20 +42,31 @@ class TestTexRender(unittest.TestCase): self.assertEqual(rend, wanted_render[i]) def test_mult_fraction(self): - exps = [ [2, Fraction(1,2), op.get_op("*", 2)], [Fraction(1,2), 3, op.get_op("*", 2)]] + exps = [ [2, Fraction(1,2), op.mul], [Fraction(1,2), 3, op.mul]] wanted_render = [ "2 \\times \\frac{ 1 }{ 2 }", "\\frac{ 1 }{ 2 } \\times 3"] for (i,e) in enumerate(exps): rend = tex(e) self.assertEqual(rend, wanted_render[i]) - def test_parentheses(self): - mul = op.get_op("*", 2) - add = op.get_op("+", 2) + def test_mult_poly(self): + exps = [[2, Polynom([1,2,3]), op.mul], + [Polynom([1,2,3]), 2, op.mul], + [Polynom([1,2,3]), Polynom([4,5,6]), op.mul], + ] + wanted_render = [ "2 ( 3 x^{ 2 } + 2 x + 1 )", + "( 3 x^{ 2 } + 2 x + 1 ) \\times 2", + "( 3 x^{ 2 } + 2 x + 1 ) ( 3 x^{ 2 } + 2 x + 1 )", + ] + for (i,e) in enumerate(exps): + rend = tex(e) + self.assertEqual(rend, wanted_render[i]) + + def test_parentheses_int(self): exps = [\ - [ 2, 3, add, 4, mul],\ - [ 2, 3, mul, 4, add],\ - [ 2, 3, 4, mul, add],\ - [ 2, 3, 4, add, add],\ + [ 2, 3, op.add, 4, op.mul],\ + [ 2, 3, op.mul, 4, op.add],\ + [ 2, 3, 4, op.mul, op.add],\ + [ 2, 3, 4, op.add, op.add],\ ] wanted_render = [\ '( 2 + 3 ) \\times 4',\ @@ -62,6 +78,27 @@ class TestTexRender(unittest.TestCase): rend = tex(e) self.assertEqual(rend, wanted_render[i]) + def test_parentheses_poly(self): + P = Polynom([1,2,3]) + Q = Polynom([4,5,6]) + exps = [\ + [ 2, P, op.add],\ + [ 2, P, op.sub],\ + [ 2, P, P, op.mul, op.sub],\ + [ Q, P, op.add],\ + [ Q, P, op.sub],\ + ] + wanted_render = [\ + '2 + 3 x^{ 2 } + 2 x + 1' ,\ + '2 - ( 3 x^{ 2 } + 2 x + 1 )' ,\ + '2 - ( 3 x^{ 2 } + 2 x + 1 ) ( 3 x^{ 2 } + 2 x + 1 )' ,\ + '( 6 x^{ 2 } + 5 x + 4 ) + 3 x^{ 2 } + 2 x + 1' ,\ + '( 6 x^{ 2 } + 5 x + 4 ) - ( 3 x^{ 2 } + 2 x + 1 )' ,\ + ] + for (i,e) in enumerate(exps): + rend = tex(e) + self.assertEqual(rend, wanted_render[i]) + def test_slash(self): pass From 374f0bc07ea25df778cd60c333c5b1c15d2d2ce9 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 18:22:46 +0100 Subject: [PATCH 5/9] change mainOp in polynom --- pymath/polynom.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pymath/polynom.py b/pymath/polynom.py index eb31271..f83788d 100644 --- a/pymath/polynom.py +++ b/pymath/polynom.py @@ -76,11 +76,13 @@ class Polynom(Explicable): - a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2 :param letter: the string describing the unknown - >>> Polynom([1,2,3]).mainOp + >>> Polynom([1, 2, 3]).mainOp '+' >>> Polynom([1]).mainOp '*' - >>> Polynom([1,2, 3])._letter + >>> Polynom([0, 0, 3]).mainOp + '*' + >>> Polynom([1, 2, 3])._letter 'x' >>> Polynom([1, 2, 3], "y")._letter 'y' @@ -91,9 +93,9 @@ class Polynom(Explicable): if self.is_monom(): - self.mainOp = "*" + self.mainOp = op.mul else: - self.mainOp = "+" + self.mainOp = op.add self._isPolynom = 1 From e031f9b903a63fe82e92c9cd76db782b11a20753 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 18:23:10 +0100 Subject: [PATCH 6/9] reset priorities --- pymath/operator.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pymath/operator.py b/pymath/operator.py index 2ba1234..701486e 100644 --- a/pymath/operator.py +++ b/pymath/operator.py @@ -139,10 +139,15 @@ class Operator(str): return ans def add_parenthesis(self, op): - """ Add parenthesis if necessary """ + """ Add parenthesis if necessary + + >>> from pymath.polynom import Polynom + >>> P = Polynom([1,2,3]) + + """ try: if op.mainOp.priority < self.priority: - op = flatten_list(["("] + [op] + [")"]) + op = flatten_list(["(", op, ")"]) except AttributeError: # op has not the attribute priority try: @@ -293,7 +298,7 @@ class op(object): caract = { "operator" : "-", \ "name" : "sub",\ - "priority" : 1, \ + "priority" : 2, \ "arity" : 2, \ "actions" : ("__sub__","__rsub__"), \ "txt" : "{op1} - {op2}",\ @@ -336,7 +341,7 @@ class op(object): caract = { "operator" : "-", \ "name" : "sub1",\ - "priority" : 2, \ + "priority" : 3, \ "arity" : 1, \ "actions" : "__neg__",\ "txt" : "- {op1}",\ @@ -461,7 +466,7 @@ class op(object): caract = { "operator" : "^", \ "name" : "pw",\ - "priority" : 5, \ + "priority" : 6, \ "arity" : 2, \ "actions" : ("__pow__",""), \ "txt" : "{op1} ^ {op2}",\ From 4841aef478285f452e94da451f8ecc9c5d66a59f Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sat, 7 Mar 2015 18:23:44 +0100 Subject: [PATCH 7/9] new tests for render (not validate yet) --- test/test_render.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_render.py b/test/test_render.py index b94f995..bb42311 100644 --- a/test/test_render.py +++ b/test/test_render.py @@ -67,12 +67,14 @@ class TestTexRender(unittest.TestCase): [ 2, 3, op.mul, 4, op.add],\ [ 2, 3, 4, op.mul, op.add],\ [ 2, 3, 4, op.add, op.add],\ + [ 2, 3, 4, op.add, op.sub],\ ] wanted_render = [\ '( 2 + 3 ) \\times 4',\ '2 \\times 3 + 4',\ '2 + 3 \\times 4',\ '2 + 3 + 4',\ + '2 - ( 3 + 4 )',\ ] for (i,e) in enumerate(exps): rend = tex(e) @@ -92,8 +94,8 @@ class TestTexRender(unittest.TestCase): '2 + 3 x^{ 2 } + 2 x + 1' ,\ '2 - ( 3 x^{ 2 } + 2 x + 1 )' ,\ '2 - ( 3 x^{ 2 } + 2 x + 1 ) ( 3 x^{ 2 } + 2 x + 1 )' ,\ - '( 6 x^{ 2 } + 5 x + 4 ) + 3 x^{ 2 } + 2 x + 1' ,\ - '( 6 x^{ 2 } + 5 x + 4 ) - ( 3 x^{ 2 } + 2 x + 1 )' ,\ + '6 x^{ 2 } + 5 x + 4 + 3 x^{ 2 } + 2 x + 1' ,\ + '6 x^{ 2 } + 5 x + 4 - ( 3 x^{ 2 } + 2 x + 1 )' ,\ ] for (i,e) in enumerate(exps): rend = tex(e) From d81d65564b6054abb3bbbdea39f5a13aaa68c5f8 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sun, 8 Mar 2015 15:55:44 +0100 Subject: [PATCH 8/9] Add a todo --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 7b2f402..64b0f4a 100644 --- a/TODO +++ b/TODO @@ -8,3 +8,4 @@ * Expression parents class and his children: Numerical_exp, toGenerate_exp and formal expression * Create tbl sgn and variation render +* Give a name to polynoms From 9ddb015a87200cb4a3d2d26184a5537f9d494138 Mon Sep 17 00:00:00 2001 From: Lafrite Date: Sun, 8 Mar 2015 18:51:53 +0100 Subject: [PATCH 9/9] Add a name to polynoms --- pymath/polynom.py | 24 +++++++++++++++++++----- pymath/polynomDeg2.py | 4 ++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/pymath/polynom.py b/pymath/polynom.py index f83788d..36e3f3d 100644 --- a/pymath/polynom.py +++ b/pymath/polynom.py @@ -33,7 +33,7 @@ class Polynom(Explicable): """Docstring for Polynom. """ @classmethod - def random(self, coefs_form=[], conditions=[], letter = "x", degree = 0): + def random(self, coefs_form=[], conditions=[], letter = "x", degree = 0, name = "P"): """ Create a random polynom from coefs_form and conditions :param coefs_form: list of forms (one by coef) (ascending degree sorted) @@ -64,9 +64,9 @@ class Polynom(Explicable): # On "parse" ce string pour créer les coefs coefs = [eval(i) if type(i)==str else i for i in eval(coefs)] # Création du polynom - return Polynom(coef = coefs, letter = letter) + return Polynom(coef = coefs, letter = letter, name = name) - def __init__(self, coef = [1], letter = "x" ): + def __init__(self, coef = [1], letter = "x", name = "P"): """Initiate the polynom :param coef: coefficients of the polynom (ascending degree sorted) @@ -75,9 +75,15 @@ class Polynom(Explicable): - [a,b,c]: list of coeficient for same degree. [1,[2,3],4] designate 1 + 2x + 3x + 4x^2 - a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2 :param letter: the string describing the unknown + :param name: Name of the polynom - >>> Polynom([1, 2, 3]).mainOp + >>> P = Polynom([1, 2, 3]) + >>> P.mainOp '+' + >>> P.name + 'P' + >>> P._letter + 'x' >>> Polynom([1]).mainOp '*' >>> Polynom([0, 0, 3]).mainOp @@ -86,10 +92,13 @@ class Polynom(Explicable): 'x' >>> Polynom([1, 2, 3], "y")._letter 'y' + >>> Polynom([1, 2, 3], name = "Q").name + 'Q' """ super(Polynom, self).__init__() self.feed_coef(coef) self._letter = letter + self.name = name if self.is_monom(): @@ -408,6 +417,8 @@ class Polynom(Explicable): >>> Q = P.derivate() >>> Q < Polynom [2, 6]> + >>> print(Q.name) + P' >>> for i in Q.explain(): ... print(i) 2 \\times 3 x + 1 \\times 2 @@ -416,7 +427,10 @@ class Polynom(Explicable): derv_coefs = [] for (i,c) in enumerate(self._coef): derv_coefs += [Expression([i, c, op.mul])] - return Polynom(derv_coefs[1:]).simplify() + + ans = Polynom(derv_coefs[1:]).simplify() + ans.name = self.name + "'" + return ans @staticmethod def postfix_add(numbers): diff --git a/pymath/polynomDeg2.py b/pymath/polynomDeg2.py index 1efd025..099eff2 100644 --- a/pymath/polynomDeg2.py +++ b/pymath/polynomDeg2.py @@ -13,12 +13,12 @@ class Polynom_deg2(Polynom): Child of Polynom with some extra tools """ - def __init__(self, coefs = [0, 0, 1], letter = "x"): + def __init__(self, coefs = [0, 0, 1], letter = "x", name = "P"): 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))) if coefs[2] == 0: raise ValueError("Polynom_deg2 have to be degree 2 polynoms, coefficient of x^2 can't be 0") - Polynom.__init__(self, coefs, letter) + Polynom.__init__(self, coefs, letter, name = name) @property def a(self):