Merge branch 'bug_explain' into dev

This commit is contained in:
Lafrite 2015-04-22 08:53:07 +02:00
commit f33f5f8755
6 changed files with 127 additions and 124 deletions

42
debug/tools.py Normal file
View File

@ -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

View File

@ -307,6 +307,11 @@ class AbstractPolynom(Explicable):
>>> Q = P.reduce() >>> Q = P.reduce()
>>> Q >>> Q
< <class 'pymath.abstract_polynom.AbstractPolynom'> [3, 12, 6]> < <class 'pymath.abstract_polynom.AbstractPolynom'> [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 >>> Q.steps
[< <class 'pymath.abstract_polynom.AbstractPolynom'> [< <class 'pymath.expression.Expression'> [1, 2, '+'] >, < <class 'pymath.expression.Expression'> [3, 4, '+', 5, '+'] >, 6]>, < <class 'pymath.abstract_polynom.AbstractPolynom'> [3, < <class 'pymath.expression.Expression'> [7, 5, '+'] >, 6]>] [< <class 'pymath.abstract_polynom.AbstractPolynom'> [< <class 'pymath.expression.Expression'> [1, 2, '+'] >, < <class 'pymath.expression.Expression'> [3, 4, '+', 5, '+'] >, 6]>, < <class 'pymath.abstract_polynom.AbstractPolynom'> [3, < <class 'pymath.expression.Expression'> [7, 5, '+'] >, 6]>]
""" """
@ -580,6 +585,14 @@ class AbstractPolynom(Explicable):
def __xor__(self, power): def __xor__(self, power):
return self.__pow__(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()
# ----------------------------- # -----------------------------

View File

@ -4,6 +4,9 @@
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.
"""
STR_RENDER = tex STR_RENDER = tex
DEFAULT_RENDER = tex DEFAULT_RENDER = tex
@ -61,6 +64,15 @@ class Renderable(object):
Renderable.set_render(self.old_render) Renderable.set_render(self.old_render)
return TmpRenderEnv() 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): class Explicable(Renderable):
""" An Explicable object is an object which can be explicable! """ An Explicable object is an object which can be explicable!

View File

@ -1,6 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
#debuging
#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
from .str2tokens import str2tokens from .str2tokens import str2tokens
from .operator import op from .operator import op
@ -10,11 +13,20 @@ from .random_expression import RdExpression
__all__ = ['Expression'] __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): 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
@ -85,16 +97,11 @@ class Expression(Explicable):
if len(expression.postfix_tokens) == 1: if len(expression.postfix_tokens) == 1:
token = expression.postfix_tokens[0] token = expression.postfix_tokens[0]
if hasattr(token, 'simplify') and hasattr(token, 'explain'): if type(token) == Fake_int or type(token) == int:
return expression.postfix_tokens[0] return Fake_int(token)
elif hasattr(token, 'simplify') and hasattr(token, 'explain'):
elif type(token) == int: ans = expression.postfix_tokens[0]
# On crée un faux int en ajoutant la méthode simplify et simplified et la caractérisique isNumber return ans
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
elif type(token) == str: elif type(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
@ -127,11 +134,7 @@ class Expression(Explicable):
self.compute_exp() self.compute_exp()
self.simplified = self.child.simplify() self.simplified = self.child.simplify()
if self.simplified != self.child: self.simplified.steps = self.child.steps + self.simplified.steps
try:
self.simplified.steps = self.child.steps + self.simplified.steps
except AttributeError:
pass
return self.simplified return self.simplified
def compute_exp(self): def compute_exp(self):
@ -193,21 +196,25 @@ class Expression(Explicable):
tmpTokenList += tokenList tmpTokenList += tokenList
self.child = Expression(tmpTokenList) self.child = Expression(tmpTokenList)
steps = self.develop_steps(tmpTokenList)
if self.child.postfix_tokens == ini_step.postfix_tokens: if self.child.postfix_tokens == ini_step.postfix_tokens:
self.child.steps = self.develop_steps(tmpTokenList) self.child.steps = steps
else: else:
self.child.steps = [ini_step] + self.develop_steps(tmpTokenList) self.child.steps = [ini_step] + steps
def develop_steps(self, tokenList): def develop_steps(self, tokenList):
""" From a list of tokens, it develops steps of each tokens """ """ 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 = [] tmp_steps = []
with Expression.tmp_render(): with Expression.tmp_render():
for t in tokenList: for t in tokenList:
if hasattr(t, "explain"): if hasattr(t, "explain"):
tmp_steps.append([i for i in t.explain()]) tmp_steps.append([i for i in t.explain()])
else: else:
tmp_steps.append(t) tmp_steps.append([t])
if max([len(i) if type(i) == list else 1 for i in tmp_steps]) == 1: if max([len(i) for i in tmp_steps]) == 1:
# Cas où rien n'a dû être expliqué. # Cas où rien n'a dû être expliqué.
return [] return []
else: else:
@ -347,104 +354,29 @@ def untest(exp):
print("\n") print("\n")
if __name__ == '__main__': if __name__ == '__main__':
#render = lambda _,x : str(x) print('\n')
#Expression.set_render(render) A = Expression("( -8 x + 8 ) ( -8 - ( -6 x ) )")
#exp = Expression("1/2 - 4") Ar = A.simplify()
#print(list(exp.simplify())) for i in Ar.explain():
print(i)
#Expression.set_render(txt) #print("------------")
#exp = "2 ^ 3 * 5" #for i in Ar.explain():
#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(i) # print(i)
from .fraction import Fraction #print(type(Ar))
f1 = Fraction(3,5)
f2 = Fraction(5,10)
q = f1+f2
print("---------")
print(q.steps)
print("---------")
for i in q.explain():
print(i)
#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 #import doctest
#doctest.testmod() #doctest.testmod()

View File

@ -78,7 +78,7 @@ class Fraction(Explicable):
return n_frac return n_frac
else: else:
return self return copy(self)
@property @property
def postfix_tokens(self): def postfix_tokens(self):
@ -188,6 +188,7 @@ class Fraction(Explicable):
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
#print("\t\tIn add ans.steps -> ", ans.steps)
return ans return ans
def __radd__(self, other): def __radd__(self, other):

View File

@ -122,7 +122,7 @@ class Polynom_deg2(Polynom):
\\frac{ -1 + 3 }{ 3 } \\frac{ -1 + 3 }{ 3 }
\\frac{ 2 }{ 3 } \\frac{ 2 }{ 3 }
""" """
return self(self.alpha).simplify() 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
@ -226,14 +226,17 @@ 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)
# print("Delta") # print("\nDelta")
# for i in P.delta.simplify(): # for i in P.delta.explain():
# print(i) # print(i)
# print("\nBeta")
# for i in P.beta.explain():
# print(i)
import doctest import doctest
doctest.testmod() doctest.testmod()