Mapytex/pymath/calculus/render.py

179 lines
5.1 KiB
Python
Raw Normal View History

2013-12-08 20:02:19 +00:00
#!/usr/bin/env python
# encoding: utf-8
2016-02-13 04:04:08 +00:00
from .generic import Stack, isOperator
2013-12-08 20:02:19 +00:00
__all__ = ['txt', 'tex', 'p2i']
2014-02-27 17:02:34 +00:00
2016-02-13 04:04:08 +00:00
2013-12-08 20:02:19 +00:00
class Render(object):
""" Create functions which know how to render postfix tokens lists """
2013-12-08 20:02:19 +00:00
def __init__(self, render):
2013-12-08 20:02:19 +00:00
"""Initiate the render
2016-02-13 03:29:26 +00:00
:param render: function which take an operator and return a function to render the operator with his operands
2013-12-08 20:02:19 +00:00
"""
self.render = render
2013-12-08 20:02:19 +00:00
def __call__(self, postfix_tokens):
"""Make the object acting like a function
:param postfix_tokens: the list of postfix tokens to be render
:returns: the render string
"""
operandeStack = Stack()
for token in postfix_tokens:
2016-02-13 03:29:26 +00:00
if isOperator(token):
if token.arity == 1:
2016-02-13 03:29:26 +00:00
op1 = operandeStack.pop()
2016-02-13 03:29:26 +00:00
operandeStack.push(self.render(token)(op1))
elif token.arity == 2:
op1 = operandeStack.pop()
op2 = operandeStack.pop()
# Switch op1 and op2 to respect order
operandeStack.push(self.render(token)(op2, op1))
2013-12-08 20:02:19 +00:00
else:
operandeStack.push(self.render(token)())
2014-12-21 15:03:53 +00:00
if len(operandeStack) > 1:
raise ValueError("This postfix_tokens is not a valid expression")
else:
return operandeStack.pop()
2016-02-13 04:04:08 +00:00
def txt_render(token):
def render(*args):
try:
return getattr(token, '__txt__')(*args)
except AttributeError:
return str(token)
return render
txt = Render(txt_render)
2016-02-13 04:04:08 +00:00
def tex_render(token):
def render(*args):
try:
return getattr(token, '__tex__')(*args)
except AttributeError:
return str(token)
return render
tex = Render(tex_render)
def p2i_render(token):
def render(*args):
try:
return getattr(token, '__p2i__')(*args)
except AttributeError:
2014-11-11 19:35:30 +00:00
return token
return render
p2i = Render(p2i_render)
2016-02-13 08:24:31 +00:00
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
@classmethod
def set_render(cls, render):
cls.STR_RENDER = render
@classmethod
def get_render(cls):
return cls.STR_RENDER
@classmethod
def set_default_render(cls):
cls.set_render(cls.DEFAULT_RENDER)
@classmethod
def tmp_render(cls, render=tex):
""" Create a container in which Expression render is temporary modify
The default temporary render is Expression in order to perform calculus inside numbers
>>> from .expression import Expression
>>> exp = Expression("2*3/5")
>>> print(exp)
2 \\times \\frac{ 3 }{ 5 }
>>> for i in exp.simplify().explain():
... print(i)
2 \\times \\frac{ 3 }{ 5 }
\\frac{ 3 }{ 5 } \\times 2
\\frac{ 3 \\times 2 }{ 5 }
\\frac{ 6 }{ 5 }
>>> with Expression.tmp_render(txt):
... for i in exp.simplify().explain():
... print(i)
2 * 3 / 5
3 / 5 * 2
( 3 * 2 ) / 5
6 / 5
>>> for i in exp.simplify().explain():
... print(i)
2 \\times \\frac{ 3 }{ 5 }
\\frac{ 3 }{ 5 } \\times 2
\\frac{ 3 \\times 2 }{ 5 }
\\frac{ 6 }{ 5 }
# TODO: essayer de ne pas afficher ce changement de position. |lun. avril 6 17:29:56 CEST 2015
"""
class TmpRenderEnv(object):
def __enter__(self):
self.old_render = Renderable.get_render()
Renderable.set_render(render)
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
def __txt__(self):
try:
return txt(self.postfix_tokens)
except AttributeError:
return self
def __tex__(self):
try:
return tex(self.postfix_tokens)
except AttributeError:
return self
if __name__ == '__main__':
2014-11-11 19:35:30 +00:00
from .operator import op
2015-04-27 17:09:03 +00:00
from itertools import permutations
from pymath import Polynom
2016-02-13 03:29:26 +00:00
from pymath import Expression
2015-04-27 17:35:31 +00:00
from pymath import Fraction
2016-02-13 04:04:08 +00:00
coefs_p = [[(i - 2), (j - 2)] for i, j in permutations(range(5), 2)]
coefs_q = [[2 * (i - 2), 2 * (j - 2)]
for i, j in permutations(range(5), 2)]
2015-04-27 17:09:03 +00:00
l_p = [Polynom(i) for i in coefs_p]
2016-02-13 04:04:08 +00:00
l_q = [Fraction(i, j) for i, j in coefs_q if j != 0]
operations = [Expression([l_p[i], l_q[j], op.mul])
for i, j in permutations(range(len(l_q)), 2)]
2015-04-27 17:09:03 +00:00
for i in operations:
print(i)
2014-02-26 11:48:41 +00:00
2013-12-08 20:02:19 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
2016-02-13 03:29:26 +00:00
# cursor: 16 del