diff --git a/debug/tools.py b/debug/tools.py new file mode 100644 index 0000000..6b7ef2a --- /dev/null +++ b/debug/tools.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# encoding: utf-8 + +__report_indent = [0] +def report(fn): + """Decorator to print information about a function + call for use while debugging. + Prints function name, arguments, and call number + when the function is called. Prints this information + again along with the return value when the function + returns. + """ + + def wrap(*params,**kwargs): + call = wrap.callcount = wrap.callcount + 1 + + indent = ' ' * __report_indent[0] + fc = "%s(%s)" % (fn.__name__, ', '.join( + [a.__repr__() for a in params] + + ["%s = %s" % (a, repr(b)) for a,b in kwargs.items()] + )) + + print( "Call %s%s called [#%s]" + % (indent, fc, call)) + __report_indent[0] += 1 + ret = fn(*params,**kwargs) + __report_indent[0] -= 1 + try: + print(' '*(__report_indent[0]+4), "ret.steps -> ", len(ret.steps)) + except AttributeError: + print(' '*(__report_indent[0]+4), ret, " has no steps") + print( "End %s%s returned %s [#%s]" + % (indent, fc, repr(ret), call)) + + return ret + wrap.callcount = 0 + return wrap + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/pymath/abstract_polynom.py b/pymath/abstract_polynom.py index 9eb8894..bc2fcf6 100644 --- a/pymath/abstract_polynom.py +++ b/pymath/abstract_polynom.py @@ -307,6 +307,11 @@ class AbstractPolynom(Explicable): >>> Q = P.reduce() >>> Q < [3, 12, 6]> + >>> for i in Q.explain(): + ... print(i) + 6 x^{ 2 } + ( 3 + 4 + 5 ) x + 1 + 2 + 6 x^{ 2 } + ( 7 + 5 ) x + 3 + 6 x^{ 2 } + 12 x + 3 >>> Q.steps [< [< [1, 2, '+'] >, < [3, 4, '+', 5, '+'] >, 6]>, < [3, < [7, 5, '+'] >, 6]>] """ @@ -580,6 +585,14 @@ class AbstractPolynom(Explicable): def __xor__(self, power): return self.__pow__(power) +if __name__ == '__main__': + P = AbstractPolynom([[1,2],[3,4,5],6]) + Q = P.reduce() + for i in Q.explain(): + print(i) + + #import doctest + #doctest.testmod() # ----------------------------- diff --git a/pymath/explicable.py b/pymath/explicable.py index d764132..fb91efd 100644 --- a/pymath/explicable.py +++ b/pymath/explicable.py @@ -4,6 +4,9 @@ from .render import txt, tex 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. + """ STR_RENDER = tex DEFAULT_RENDER = tex @@ -60,6 +63,15 @@ class Renderable(object): def __exit__(self, type, value, traceback): Renderable.set_render(self.old_render) return TmpRenderEnv() + + def __eq__(self, other): + """ Two Renderable objects are the same if they have same postfix_tokens """ + try: + return self.postfix_tokens == other.postfix_tokens + except AttributeError: + return False + + class Explicable(Renderable): diff --git a/pymath/expression.py b/pymath/expression.py index 79e4f06..4ec22ea 100644 --- a/pymath/expression.py +++ b/pymath/expression.py @@ -1,6 +1,9 @@ #!/usr/bin/env python # encoding: utf-8 +#debuging +#from debug.tools import report + from .generic import Stack, flatten_list, expand_list, isNumber, isOperator, isNumerand from .str2tokens import str2tokens from .operator import op @@ -10,11 +13,20 @@ from .random_expression import RdExpression __all__ = ['Expression'] +class Fake_int(int, Explicable): + isNumber = True + def __init__(self, val): + super(Fake_int, self).__init__(val) + self._val = val + self.postfix_tokens = [self] + self.steps = [] + def simplify(self): + return Fake_int(self._val) + class Expression(Explicable): """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" - @classmethod def random(self, form="", conditions=[], val_min = -10, val_max=10): """Create a random expression from form and with conditions @@ -85,16 +97,11 @@ class Expression(Explicable): if len(expression.postfix_tokens) == 1: token = expression.postfix_tokens[0] - if hasattr(token, 'simplify') and hasattr(token, 'explain'): - return expression.postfix_tokens[0] - - elif type(token) == int: - # On crée un faux int en ajoutant la méthode simplify et simplified et la caractérisique isNumber - simplify = lambda x:x - is_number = True - methods_attr = {'simplify':simplify, 'isNumber': is_number, 'postfix_tokens': [token]} - fake_token = type('fake_int', (int,Explicable, ), methods_attr)(token) - return fake_token + if type(token) == Fake_int or type(token) == int: + return Fake_int(token) + elif hasattr(token, 'simplify') and hasattr(token, 'explain'): + ans = expression.postfix_tokens[0] + return ans elif type(token) == str: # TODO: Pourquoi ne pas créer directement un polynom ici? |jeu. févr. 26 18:59:24 CET 2015 @@ -127,11 +134,7 @@ class Expression(Explicable): self.compute_exp() self.simplified = self.child.simplify() - if self.simplified != self.child: - try: - self.simplified.steps = self.child.steps + self.simplified.steps - except AttributeError: - pass + self.simplified.steps = self.child.steps + self.simplified.steps return self.simplified def compute_exp(self): @@ -193,21 +196,25 @@ class Expression(Explicable): tmpTokenList += tokenList self.child = Expression(tmpTokenList) + + steps = self.develop_steps(tmpTokenList) + if self.child.postfix_tokens == ini_step.postfix_tokens: - self.child.steps = self.develop_steps(tmpTokenList) + self.child.steps = steps else: - self.child.steps = [ini_step] + self.develop_steps(tmpTokenList) + self.child.steps = [ini_step] + steps def develop_steps(self, tokenList): """ From a list of tokens, it develops steps of each tokens """ + # TODO: Attention les étapes sont dans le mauvais sens |lun. avril 20 10:06:03 CEST 2015 tmp_steps = [] with Expression.tmp_render(): for t in tokenList: if hasattr(t, "explain"): tmp_steps.append([i for i in t.explain()]) else: - tmp_steps.append(t) - if max([len(i) if type(i) == list else 1 for i in tmp_steps]) == 1: + tmp_steps.append([t]) + if max([len(i) for i in tmp_steps]) == 1: # Cas où rien n'a dû être expliqué. return [] else: @@ -347,105 +354,30 @@ def untest(exp): print("\n") if __name__ == '__main__': - #render = lambda _,x : str(x) - #Expression.set_render(render) - #exp = Expression("1/2 - 4") - #print(list(exp.simplify())) - - #Expression.set_render(txt) - #exp = "2 ^ 3 * 5" - #untest(exp) - - #exp = "2x + 5" - #untest(exp) - - #Expression.set_render(tex) - - #untest(exp1) - - #from pymath.operator import op - #exp = [2, 3, op.pw, 5, op.mul] - #untest(exp) - - #untest([Expression(exp1), Expression(exp), op.add]) - - #exp = "1 + 3 * 5" - #e = Expression(exp) - #f = -e - #print(f) - - #exp = "2 * 3 * 3 * 5" - #untest(exp) - - #exp = "2 * 3 + 3 * 5" - #untest(exp) - - #exp = "2 * ( 3 + 4 ) + 3 * 5" - #untest(exp) - - #exp = "2 * ( 3 + 4 ) + ( 3 - 4 ) * 5" - #untest(exp) - # - #exp = "2 * ( 2 - ( 3 + 4 ) ) + ( 3 - 4 ) * 5" - #untest(exp) - # - #exp = "2 * ( 2 - ( 3 + 4 ) ) + 5 * ( 3 - 4 )" - #untest(exp) - # - #exp = "2 + 5 * ( 3 - 4 )" - #untest(exp) - - #exp = "( 2 + 5 ) * ( 3 - 4 )^4" - #untest(exp) - - #exp = "( 2 + 5 ) * ( 3 * 4 )" - #untest(exp) - - #exp = "( 2 + 5 - 1 ) / ( 3 * 4 )" - #untest(exp) - - #exp = "( 2 + 5 ) / ( 3 * 4 ) + 1 / 12" - #untest(exp) - - #exp = "( 2+ 5 )/( 3 * 4 ) + 1 / 2" - #untest(exp) - - #exp="(-2+5)/(3*4)+1/12+5*5" - #untest(exp) - - #exp="-2*4(12 + 1)(3-12)" - #untest(exp) - - - #exp="(-2+5)/(3*4)+1/12+5*5" - #untest(exp) - - # TODO: The next one doesn't work |ven. janv. 17 14:56:58 CET 2014 - #exp="-2*(-a)(12 + 1)(3-12)" - #e = Expression(exp) - #print(e) - - ## Can't handle it yet!! - #exp="-(-2)" - #untest(exp) - - #print("\n") - #exp = Expression.random("({a} + 3)({b} - 1)", ["{a} > 4"]) - #for i in exp.simplify(): + print('\n') + A = Expression("( -8 x + 8 ) ( -8 - ( -6 x ) )") + Ar = A.simplify() + for i in Ar.explain(): + print(i) + #print("------------") + #for i in Ar.explain(): # print(i) - from .fraction import Fraction - f1 = Fraction(3,5) - f2 = Fraction(5,10) - q = f1+f2 - print("---------") - print(q.steps) - print("---------") - - for i in q.explain(): - print(i) + #print(type(Ar)) + #print('\n-----------') + #A = Expression("-6 / 3 + 10 / -5") + #Ar = A.simplify() + #for i in Ar.explain(): + # print(i) + + #print('\n-----------') + #A = Expression("1/3 + 4/6") + #Ar = A.simplify() + #for i in Ar.explain(): + # print(i) + #import doctest #doctest.testmod() diff --git a/pymath/fraction.py b/pymath/fraction.py index 63ddac7..9369c64 100644 --- a/pymath/fraction.py +++ b/pymath/fraction.py @@ -78,7 +78,7 @@ class Fraction(Explicable): return n_frac else: - return self + return copy(self) @property def postfix_tokens(self): @@ -188,6 +188,7 @@ class Fraction(Explicable): ans = exp.simplify() ini_step = Expression(self.postfix_tokens + number.postfix_tokens + [op.add]) ans.steps = [ini_step] + ans.steps + #print("\t\tIn add ans.steps -> ", ans.steps) return ans def __radd__(self, other): diff --git a/pymath/polynomDeg2.py b/pymath/polynomDeg2.py index bb27cb3..1f76e1d 100644 --- a/pymath/polynomDeg2.py +++ b/pymath/polynomDeg2.py @@ -122,7 +122,7 @@ class Polynom_deg2(Polynom): \\frac{ -1 + 3 }{ 3 } \\frac{ 2 }{ 3 } """ - return self(self.alpha).simplify() + return self(self.alpha) def roots(self, after_coma = 2): """ Compute roots of the polynom @@ -226,14 +226,17 @@ class Polynom_deg2(Polynom): if __name__ == '__main__': - # from .render import txt - # with Expression.tmp_render(txt): - # P = Polynom_deg2([2, 3, 4]) - # print(P) + #from .render import txt + #with Expression.tmp_render(txt): + # P = Polynom_deg2([2, 3, 4]) + # print(P) - # print("Delta") - # for i in P.delta.simplify(): - # print(i) + # print("\nDelta") + # for i in P.delta.explain(): + # print(i) + # print("\nBeta") + # for i in P.beta.explain(): + # print(i) import doctest doctest.testmod()