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
< <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
[< <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):
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
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):

View File

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

View File

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

View File

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