From 412149f22d4f30e5ef79edeb6443165eb68a6a4d Mon Sep 17 00:00:00 2001 From: Lafrite Date: Fri, 29 Aug 2014 17:15:29 +0200 Subject: [PATCH] Finish unify_render! :D and even mod the doc --- docs/tutorial.mdwn | 66 +++++++++++++++++++++++++---------------- pymath/expression.py | 18 ++++------- test/test_expression.py | 5 +++- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/docs/tutorial.mdwn b/docs/tutorial.mdwn index 06eb3b1..cb1d61c 100644 --- a/docs/tutorial.mdwn +++ b/docs/tutorial.mdwn @@ -25,23 +25,39 @@ Un expression peut être initialisée de deux façons différentes: à partir d' >>> exp = Expression("1 + 2 * 3") >>> exp = Expression([1, "+", 2, "*", 3]) -On peut ensuite afficher l'expression avec un *print* (pour un rendu en mode texte). +On peut ensuite afficher l'expression avec un *print*. + >>> print(exp) + 1 + 2 \times 3 + +Et si l'on souhaite un rendu plus adapté à la console: + + >>> from pymath.renders import txt + >>> exp.render(render = txt) + 1 + 2 * 3 + +Ou encore + + >>> from pymath.renders import txt + >>> Expression.STR_RENDER = txt >>> print(exp) 1 + 2 * 3 -Et si l'on souhaite un rendu en latex: +/!\ Il ne faut pas faire - >>> from pymath.renders import tex - >>> exp.render(render = tex) - 1 + 2 \times 3 + >>> exp.STR_RENDER = txt + +car le changement ne se propagera pas à toute la classe. Ce qui posera problème quand on utilisera la méthode *simplify*(les sous expressions auront l'ancien STR_RENDER). ### Simplification des expressions Une fois les expressions créées, elles peuvent se réduire en expliquant les étapes et en respectant les règles de priorités. Les exemples suivants seront données avec un rendu texte. + >>> from pymath.expression import Expression >>> from pymath.renders import txt + >>> Expression.STR_RENDER = txt + >>> exp = Expression("1 + 2 * 3") - >>> for i in exp.simplify(render = txt): + >>> for i in exp.simplify(): ... print(i) ... 1 + 2 * 3 @@ -52,7 +68,7 @@ Une fois les expressions créées, elles peuvent se réduire en expliquant les Les opérations autorisées sont les opérations "classique": + - * / ^. L'utilisation des parenthèses est aussi gérée. >>> exp = Expression("1 + 2 / 5") - >>> for i in exp.simplify(render = txt): + >>> for i in exp.simplify(): ... print(i) ... 1 + 2 / 5 @@ -70,11 +86,10 @@ Les opérations autorisées sont les opérations "classique": + - * / ^. L'utili -30 ### Différents rendus -Comme dit dans l'introduction, il y a deux types de rendus: un rendus texte (utilisé depuis le début) et un rendus latex. Voici un exemple de l'utilisation du rendu latex +Comme dit dans l'introduction, il y a deux types de rendus: un rendus texte (utilisé depuis le début) et un rendus latex. Voici un exemple de l'utilisation du rendu latex (par défaut) - >>> from pymath.renders import tex >>> exp = Expression("1 + 2 / 5") - >>> for i in exp.simplify(render = tex): + >>> for i in exp.simplify(): ... print(i) ... 1 + \frac{ 2 }{ 5 } @@ -94,12 +109,16 @@ Pour créer une expression il faut au moins une chose: la forme de l'expression. >>> form = "2* {a} + 3" >>> rd_exp = RdExpression(form) - >>> rd_exp() + >>> e = rd_exp() + >>> type(e) + pymath.expression.Expression + >>> print(e) '2 \\times 9 + 3' >>> rd_exp(30, 40) '2 \\times 31 + 3' -On remarque que ici le rendu est directement en latex (je ne sais d'ailleurs pas si c'est une très bonne idée que le rendu par défaut ne soit pas le même qu'avec expression...). +On remarque que ici que rd_exp renvoie une expression. Cela permettra qu'ensuite on puisse simplifier ou manipuler les expressions + On verra plus tard comment se passer de cette classe pour par exemple créer des expressions avec des fonctions non implémentées dans Expression. ### Créer une expression avec conditions Parfois il peut être nécessaire d'imposer des conditions sur les éléments à générer pour créer des exercices spécifiques. @@ -107,7 +126,7 @@ Parfois il peut être nécessaire d'imposer des conditions sur les éléments à >>> form = "{a} / {b} + {c} / {d}" >>> cond = ["abs({b}) != 1", "{d} > 1", "{b} != {d}", "gcd({a},{b}) == 1", "gcd({c},{d}) == 1"] >>> rd_frac_add = RdExpression(form, cond) - >>> rd_frac_add() + >>> print(rd_frac_add()) '\\frac{ 4 }{ 5 } + \\frac{ 9 }{ 7 }' La méthode pour créer les valeurs avec des conditions est la méthode par rejet. Elle n'est pas très efficace et rien n'est encore prévu dans le cas où aucune valeur n'est possible. @@ -118,35 +137,30 @@ Pour éviter de faire tourner la méthode par rejet trop longtemps, il est possi >>> form = "{a} / {b} + {c} / {k*b}" >>> cond = ["abs({b}) != 1", "{k} > 1", "{b} != {d}", "gcd({a},{b}) == 1", "gcd({c},{k*b}) == 1"] >>> rd_frac_add = RdExpression(form, cond) - >>> rd_frac_add() + >>> print(rd_frac_add()) '\\frac{ -9 }{ 7 } + \\frac{ 1 }{ 28 } ### Rendu des expressions -Le rendu des expressions se fait avec la classe Expression présentée plus haut. C'est pratique car cela permet de profiter des rendus automatiques en latex. Mais cela ne permet par de réutiliser facilement l'expression (pour une correction par exemple) et cela gène quand on veut utiliser des choses que Expression ne sait pas gérer. +On peut vouloir ne pas passer passer par la classe Expression pour obtenir notre expression (si l'on veut utiliser la racine carré par exemple). Pour cela il va falloir changer la forme du rendu + >>> RdExpression.FORM = "raw" >>> form = "{a} / {b} + {c} / {k*b}" >>> cond = ["abs({b}) != 1", "{d} > 1", "{b} != {d}", "gcd({a},{b}) == 1", "gcd({c},{k*b}) == 1"] >>> rd_frac_add = RdExpression(form, cond) - >>> exp = rd_frac_add.raw_exp() + >>> exp = rd_frac_add() + >>> type(exp) + str >>> print(exp) -2 / 5 + -8 / 35 - >>> for i in exp.simplify(render = txt): - ... print(i) - ... - -2 / 5 + -8 / 35 - -2 / 5 + ( -8 / 35 ) - ( -2 * 7 ) / ( 5 * 7 ) + ( -8 * 1 ) / ( 35 * 1 ) - ( -14 + ( -8 ) ) / 35 - -22 / 35 >>> form = "{a**2}x^2 + {2*a*b} x + {b**2}" >>> rd_id_rmq = RdExpression(form, with_Exp = False) - >>> rd_id_rmq() + >>> print(rd_id_rmq()) '100x^2 + -180 x + 81' >>> rd_id_rmq() '49x^2 + 42 x + 9' -On remarque le défaut d'utiliser *with_Exp* le rendu est moins bien fait (dans l'exemple, il n'y a pas de parenthèses autour du -180). +On remarque le défaut d'utiliser cette forme, le rendu est moins bien fait (dans l'exemple, il n'y a pas de parenthèses autour du -8). diff --git a/pymath/expression.py b/pymath/expression.py index 83b50cd..6548fdc 100644 --- a/pymath/expression.py +++ b/pymath/expression.py @@ -47,24 +47,20 @@ class Expression(object): ## --------------------- ## Mechanism functions - def simplify(self, render = lambda x:str(x)): - """ Generator which return steps for computing the expression - - :param render: function which render the list of token (postfix form now) to string - - """ + def simplify(self): + """ Generator which return steps for computing the expression """ if not self.can_go_further(): - yield render(self.postfix_tokens) + yield self.STR_RENDER(self.postfix_tokens) else: self.compute_exp() old_s = '' for s in self.steps: - new_s = render(s) + new_s = self.STR_RENDER(s) # Astuce pour éviter d'avoir deux fois la même étape (par exemple pour la transfo d'une division en fraction) if new_s != old_s: old_s = new_s yield new_s - for s in self.child.simplify(render = render): + for s in self.child.simplify(): if old_s != s: yield s @@ -329,9 +325,7 @@ class Expression(object): def test(exp): a = Expression(exp) - #for i in a.simplify(): - #for i in a.simplify(render = txt): - for i in a.simplify(render = tex): + for i in a.simplify(): print(i) print("\n") diff --git a/test/test_expression.py b/test/test_expression.py index 0bf6fa2..c4126bb 100644 --- a/test/test_expression.py +++ b/test/test_expression.py @@ -8,7 +8,7 @@ import unittest from pymath.expression import Expression from pymath.fraction import Fraction from pymath.generic import first_elem -from pymath.renders import txt +from pymath.renders import txt, tex class TestExpression(unittest.TestCase): @@ -76,6 +76,7 @@ class TestExpression(unittest.TestCase): def test_simplify_frac(self): exp = Expression("1/2 - 4") + Expression.STR_RENDER = lambda _,x : str(x) steps = ["[1, 2, '/', 4, '-']", \ "[< Fraction 1 / 2>, 4, '-']", \ "[1, 1, '*', 2, 1, '*', '/', 4, 2, '*', 1, 2, '*', '/', '-']", \ @@ -83,6 +84,8 @@ class TestExpression(unittest.TestCase): '[< Fraction -7 / 2>]'] self.assertEqual(steps, list(exp.simplify())) + Expression.STR_RENDER = tex + if __name__ == '__main__': unittest.main()