Compare commits

..

50 Commits
dev ... master

Author SHA1 Message Date
Bertrand Benjamin 7f8939eab2 Test: separate expression build and showing it
continuous-integration/drone/push Build is passing Details
2020-08-21 19:07:34 +02:00
Bertrand Benjamin 0cadc6734e Feat: return value for random_list
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2020-08-20 20:50:54 +02:00
Bertrand Benjamin f767aa390c Fix: rename list_generator to random_list
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2020-08-20 20:42:46 +02:00
Bertrand Benjamin 55985bfe20 Tagging: bad version number!
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2020-08-20 17:40:16 +02:00
Bertrand Benjamin 41d0de79cc Tagging: change version to 2.2
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2020-08-20 17:38:06 +02:00
Bertrand Benjamin 3b5c01e5cc Feat: random list generator
continuous-integration/drone/push Build is passing Details
2020-08-20 17:36:38 +02:00
Bertrand Benjamin 73b19e9644 Feat: add autopublishing
continuous-integration/drone/push Build is passing Details
2020-08-20 17:02:09 +02:00
Bertrand Benjamin 27e7dcba20 Feat: doctest skip
continuous-integration/drone/push Build is passing Details
2020-08-20 16:59:40 +02:00
Bertrand Benjamin 5f398b4c8d Feat: change frac to dfrac for fractions 2020-08-20 16:59:40 +02:00
Bertrand Benjamin ec823c85eb Feat: force subtree to be str and tex instead of txt in tree2tex 2020-08-20 16:59:40 +02:00
Bertrand Benjamin d72a2be175 Feat: Polynomial are displayed in nicer order! 2020-08-20 16:59:40 +02:00
Bertrand Benjamin e596c1af60 Fix: clean __init__ 2020-08-20 16:59:40 +02:00
Bertrand Benjamin b84cf047bd Fix: chante value to content in raw 2020-08-20 16:59:40 +02:00
Bertrand Benjamin d446139af3 Feat: missing_times works with RdLeaf 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 975728f8dc Feat: Add doctest to rdstr2 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 2317296534 Feat: raw methods for tokens 2020-08-20 16:59:40 +02:00
Bertrand Benjamin c211ed1591 Feat: remove precision setting for Decimal 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 0c84c63ad3 Feat: overload pow for tokens 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 25bfb7699b Feat: add doctest add int and Decimal 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 0abd80655a Feat: dirty way to get decimal approx of a function 2020-08-20 16:59:40 +02:00
Bertrand Benjamin a3f7efca12 Feat: allowing to import Decimal 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 1a74c54548 Feat: allow import Integer in calculus 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 1dccaabd86 Feat: dirty sub (repeatition in explain) 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 510f6a1fa2 Feat: doctest for operation between Token and str 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 6b353d2dd0 Feat: tokens can operate with builtin int 2020-08-20 16:59:40 +02:00
Bertrand Benjamin fbfaeb5a58 Fix: precessing -> processing 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 1a4e8ffb19 Feat: start using nox 2020-08-20 16:59:40 +02:00
Bertrand Benjamin d6bb61dc48 Fix: Black does its job 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 02214b0f82 Feat: no more round in quadratic roots 2020-08-20 16:59:40 +02:00
Bertrand Benjamin e52fec4057 Feat: MOnumber creating with a integer string 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 219d923ff5 Feat: to_be_token decorator and force token to be Integer when it's
possible
2020-08-20 16:59:40 +02:00
Bertrand Benjamin 419e5955eb Feat: tokenify for everything! 2020-08-20 16:59:40 +02:00
Bertrand Benjamin f471a1efb3 Feat: Test and validate roots (but not elegant) 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 7600962fe4 Feat: doctest for composing Expressions 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 3e258b2d41 Feat: Expression call works with tokens 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 9f492378c8 Feat: Allow pure string rendering 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 0c3c20262e Fix: move __call__ to expressions 2020-08-20 16:59:40 +02:00
Bertrand Benjamin b3ec098b0b Feat: add tree2tex in all import 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 9d9224fcba Feat: Polynoms can be differentiate!!!! 2020-08-20 16:59:40 +02:00
Bertrand Benjamin b53de690d5 Fix: Issue with typing null monomial 2020-08-20 16:59:40 +02:00
Bertrand Benjamin beb319f21d Fix: replace notimplemented by NotImplementedError 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 50f77c4d60 Feat: coefficients, delta and some roots for polynomial, Linear and Quadratic 2020-08-20 16:59:40 +02:00
Bertrand Benjamin a83b5ada8d Feat: Polynomial can be evaluated 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 0aba5eaef6 Feat: Move some import into functions 2020-08-20 16:59:40 +02:00
Bertrand Benjamin 0faaf481ca Feat: start working on eval for polynoms 2020-08-20 16:59:40 +02:00
Bertrand Benjamin b51ac7880d Fix: typing filter for multiply 2020-08-20 16:59:40 +02:00
Bertrand Benjamin fdf3b088f2 Mise à jour de 'README.md'
continuous-integration/drone/push Build is failing Details
2020-07-18 06:29:21 +00:00
Bertrand Benjamin c7bd77e341 Mise à jour de '.drone.yml'
continuous-integration/drone/push Build is failing Details
2020-07-18 06:21:50 +00:00
Bertrand Benjamin 37601be549 Feat: nothing
continuous-integration/drone/push Build is failing Details
2020-07-17 20:37:51 +02:00
Bertrand Benjamin 19cdddf27e Feat: add a drone for testing 2020-07-17 20:37:00 +02:00
22 changed files with 248 additions and 458 deletions

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
from .calculus import Expression, Integer, Decimal, random_list, render, Polynomial, Fraction from .calculus import Expression, Integer, Decimal, random_list
# Expression.set_render('tex') # Expression.set_render('tex')

View File

@ -108,35 +108,26 @@ x^7
(6 + 6) * x + 4x^2 + 9 (6 + 6) * x + 4x^2 + 9
4x^2 + 12x + 9 4x^2 + 12x + 9
>>> e = Expression.from_str("(2x-3)(-x+2)")
>>> e_simplified = e.simplify()
>>> e_simplified
<Quadratic - 2x^2 + 7x - 6>
>>> for s in e_simplified.explain():
... print(s)
(2x - 3)(- x + 2)
(2x - 3)(- x + 2)
2x(- x) + 2x * 2 - 3(- x) - 3 * 2
2(- 1) * x^(1 + 1) + 2 * 2 * x - 3(- 1) * x - 6
4x + 3x - 2x^2 - 6
(4 + 3) * x - 2x^2 - 6
- 2x^2 + 7x - 6
""" """
from .renders import render
from .expression import Expression from .expression import Expression
from .tokens import Token from .tokens.number import Integer, Decimal
from .tokens.polynomial import Polynomial
from .tokens.number import Integer, Decimal, Fraction
if __name__ == "__main__": if __name__ == "__main__":
e = Expression.from_str("(2x-3)(-x+2)") e = Expression.from_str("1+2/3/4/5")
e_simplified = e.simplify() et = e._typing()
e_simplified print("typing")
for s in e_simplified.explain(): print(e._tree)
print(s._tree.map_on_leaf(lambda x: type(x))) e = et._order()
print(s) print("order")
print(e._tree)
e = e._optimize()
print("then optimize")
print(e._tree)
e = et._optimize()
print("optimize without order")
print(e._tree)
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'

View File

@ -21,7 +21,7 @@ from ..core.random import (
) )
from ..core.MO import moify from ..core.MO import moify
from .tokens import factory from .tokens import factory
from .renders import render from .renders import renders
class Expression(object): class Expression(object):
@ -42,6 +42,7 @@ class Expression(object):
14 14
""" """
RENDER = "txt"
def __init__(self, tree, ancestor=None): def __init__(self, tree, ancestor=None):
""" """
@ -49,6 +50,41 @@ class Expression(object):
self._tree = tree self._tree = tree
self._ancestor = ancestor self._ancestor = ancestor
@classmethod
def set_render(cls, render):
""" Define default render function
:param render: render name (txt or tex)
:example:
>>> e = Expression.from_str("2+3*4")
>>> print(e)
2 + 3 * 4
>>> e = Expression.from_str("2+3/4")
>>> print(e)
2 + 3 / 4
>>> es = e.simplify()
>>> print(es)
11 / 4
>>> Expression.set_render('tex')
>>> Expression.RENDER
'tex'
>>> e = Expression.from_str("2+3*4")
>>> print(e)
2 + 3 \\times 4
>>> e = Expression.from_str("2+3/4")
>>> print(e)
2 + \\dfrac{3}{4}
>>> es = e.simplify()
>>> print(es)
\\dfrac{11}{4}
>>> Expression.set_render('txt')
"""
from .tokens.token import Token
Token.set_render(render)
cls.RENDER = render
@classmethod @classmethod
def from_str(cls, string, typing=True): def from_str(cls, string, typing=True):
""" Initiate the expression from a string """ Initiate the expression from a string
@ -138,16 +174,16 @@ class Expression(object):
return cls(t) return cls(t)
def __str__(self): def __str__(self):
return render(self._tree) return renders[self.RENDER](self._tree)
def __repr__(self): def __repr__(self):
return f"<Exp: {render(self._tree, 'txt')}>" return f"<Exp: {renders['txt'](self._tree)}>"
def _order(self, exclude_nodes=["*", "/", "**"]): def _order(self, exclude_nodes=["*", "/", "**"]):
""" Order the expression base on types """ Order the expression base on types
:example: :example:
>>> e = Expression.from_str("1 + 2x + 3 + 4x") >>> e = Expression.from_str("1 + 2x + 3 + 4x")
>>> print(e) >>> print(e)
1 + 2x + 3 + 4x 1 + 2x + 3 + 4x
@ -168,8 +204,7 @@ class Expression(object):
return type(leaf) return type(leaf)
else: else:
try: try:
typed_leaf = typing( typed_leaf = typing(leaf.node, leaf.left_value, leaf.right_value)
leaf.node, leaf.left_value, leaf.right_value)
return typed_leaf.signature return typed_leaf.signature
except (AttributeError, NotImplementedError, TypingError): except (AttributeError, NotImplementedError, TypingError):
return type(leaf) return type(leaf)
@ -186,7 +221,7 @@ class Expression(object):
def _optimize(self, exclude_nodes=["/", "**"]): def _optimize(self, exclude_nodes=["/", "**"]):
""" Return a copy of self with an optimize tree """ Return a copy of self with an optimize tree
:example: :example:
>>> e = Expression.from_str("2x^2+2x+3x") >>> e = Expression.from_str("2x^2+2x+3x")
>>> print(e._tree) >>> print(e._tree)
@ -227,7 +262,7 @@ class Expression(object):
def _typing(self): def _typing(self):
""" Build a copy of self with as much typing as possible """ Build a copy of self with as much typing as possible
:example: :example:
>>> e = Expression.from_str("2x", typing=False) >>> e = Expression.from_str("2x", typing=False)
>>> print(e._tree.map_on_leaf(lambda x: type(x).__name__)) >>> print(e._tree.map_on_leaf(lambda x: type(x).__name__))
@ -272,7 +307,7 @@ class Expression(object):
def _compute(self): def _compute(self):
"""" Compute one step of self """" Compute one step of self
""" """
try: try:
return Expression(self._tree.apply_on_last_level(compute)) return Expression(self._tree.apply_on_last_level(compute))
@ -309,15 +344,15 @@ class Expression(object):
comp_exp = opt_exp._compute() comp_exp = opt_exp._compute()
if typed_exp != comp_exp: if typed_exp == comp_exp:
typed_exp.set_ancestor(self._ancestor)
return typed_exp
else:
comp_exp.set_ancestor(self) comp_exp.set_ancestor(self)
return comp_exp._simplify(optimize=optimize) return comp_exp._simplify(optimize=optimize)
typed_exp.set_ancestor(self._ancestor)
return typed_exp
def simplify(self, optimize=True): def simplify(self, optimize=True):
""" Simplify the expression, keep the history and factory child """ Compute as much as possible the expression
:param optimize: bool to optimize tree when it's possible :param optimize: bool to optimize tree when it's possible
:return: an expression :return: an expression
@ -337,7 +372,7 @@ class Expression(object):
def explain(self): def explain(self):
""" Yield every calculus step which have lead to self """ Yield every calculus step which have lead to self
:example: :example:
>>> e = Expression.from_str("2+3*4") >>> e = Expression.from_str("2+3*4")
>>> f = e.simplify() >>> f = e.simplify()

View File

@ -12,59 +12,34 @@ Expression
""" """
from ..core import tree2txt, tree2tex from ..core import tree2txt, tree2tex
class Render(object):
""" Object which render Expression or token """
def __init__(self, default="txt"): def _txt(mo_tree):
self._default = default """ txt render for MOs or Trees"""
self._render = default try:
self.renders = {} return tree2txt(mo_tree)
except ValueError:
pass
def register_render(self, name, func, attribute): try:
""" register a render """ return mo_tree.__txt__
try: except AttributeError:
self.renders[name] return str(mo_tree)
except KeyError:
self.renders[name] = {"name": name, "func": func, "attribute": attribute}
else:
raise ValueError("This render name already exists")
@property
def render_name(self):
return self._render
@property
def render(self):
return self.renders[self._render]
def __call__(self, mo_tree, tmp_render=''):
if tmp_render:
r = self.renders[tmp_render]
else:
r = self.render
try:
return r["func"](mo_tree)
except ValueError:
pass
try:
return getattr(mo_tree, r["attribute"])
except AttributeError:
return str(mo_tree)
def set_render(self, render):
""" Define the render """
if render in self.renders.keys():
self._render = render
else:
raise ValueError("This render does not exists")
def _tex(mo_tree):
""" Tex render for MOs or Trees"""
try:
return tree2tex(mo_tree)
except ValueError:
pass
render = Render() try:
render.register_render("txt", tree2txt, "__txt__") return mo_tree.__tex__
render.register_render("tex", tree2tex, "__tex__") except AttributeError:
return str(mo_tree)
renders = {"txt": _txt, "tex": _tex}
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'

View File

@ -18,7 +18,7 @@ from ...core.MO import MO, MOnumber
from ...core.MO.fraction import MOFraction from ...core.MO.fraction import MOFraction
from random import random from random import random
__all__ = ["Integer", "Decimal", "Fraction"] __all__ = ["Integer", "Decimal"]
class Integer(Token): class Integer(Token):
@ -141,7 +141,7 @@ class Decimal(Token):
class Fraction(Token): class Fraction(Token):
""" Token representing a fraction of numbers """ Token representing a fraction
:example: :example:
>>> Fraction("3/4") >>> Fraction("3/4")
@ -237,25 +237,11 @@ class Fraction(Token):
@property @property
def numerator(self): def numerator(self):
""" Get numerator of the fraction return self._mo.numerator
:example:
>>> a = Fraction("3/4")
>>> a.numerator
<Integer 3>
"""
return Integer(self._mo.numerator)
@property @property
def denominator(self): def denominator(self):
""" Get denominator of the fraction return self._mo.denominator
:example:
>>> a = Fraction("3/4")
>>> a.denominator
<Integer 4>
"""
return Integer(self._mo.denominator)
@property @property
def decimal(self): def decimal(self):
@ -269,58 +255,7 @@ class Fraction(Token):
>>> f.decimal >>> f.decimal
<Decimal 0.3333333333333333333333333333> <Decimal 0.3333333333333333333333333333>
""" """
return Decimal(self._mo._value) return Decimal(_Decimal(self._mo.numerator._value) / _Decimal(self._mo.denominator._value))
@property
def simplified(self):
""" Get the irreductible version of self
:example:
>>> f = Fraction("3/4")
>>> f.simplified
<Fraction 3 / 4>
>>> f = Fraction("12/9")
>>> f.simplified
<Fraction 4 / 3>
>>> f = Fraction("12/4")
>>> f.simplified
<Integer 3>
"""
simplified = self._mo.simplified()
if isinstance(simplified, MOnumber):
return Integer(simplified)
return Fraction(simplified)
def simplify(self):
""" Itself or its simplified version
:example:
>>> f = Fraction("12/8")
>>> fs = f.simplify()
>>> for i in fs.explain():
... print(i)
12 / 8
3 / 2
>>> f = Fraction("5/8")
>>> fs = f.simplify()
>>> for i in fs.explain():
... print(i)
5 / 8
"""
simplified = self.simplified
try:
if self.numerator == simplified.numerator:
return self
except AttributeError:
pass
simplified._ancestor = self
return simplified
# ----------------------------- # -----------------------------

View File

@ -15,7 +15,6 @@ from .token import Token
from . import to_be_token from . import to_be_token
from ...core.MO import MO from ...core.MO import MO
from ...core.MO.atoms import moify from ...core.MO.atoms import moify
from ...core.MO.polynomial import MOpolynomial
__all__ = ["Polynomial", "Quadratic", "Linear"] __all__ = ["Polynomial", "Quadratic", "Linear"]
@ -45,21 +44,9 @@ class Polynomial(Token):
return cls(mo, name, ancestor) return cls(mo, name, ancestor)
@classmethod @classmethod
def from_coefficients(cls, coefficients, variable_name="x", name=""): def from_coefficients(cls, coefficients):
""" Initiate polynomial from list of coefficients """ Initiate polynomial from list of coefficients """
pass
:examples:
>>> P = Polynomial.from_coefficients([1, 2, 3])
>>> P
<Polynomial 3x^2 + 2x + 1>
>>> P = Polynomial.from_coefficients([1, 2, -3])
>>> P
<Polynomial - 3x^2 + 2x + 1>
>>> P = Polynomial.from_coefficients([1, 2, 3], "y")
>>> P
<Polynomial 3y^2 + 2y + 1>
"""
return cls(MOpolynomial(variable_name, coefficients), name)
@classmethod @classmethod
def random(cls): def random(cls):
@ -148,11 +135,7 @@ class Linear(Polynomial):
>>> P.differentiate() >>> P.differentiate()
<Integer 2> <Integer 2>
>>> P.roots >>> P.roots
[<Integer - 2>] [<Fraction - 2 / 1>]
>>> for i in P.roots[0].explain():
... print(i)
- 2 / 1
- 2
""" """
@ -194,20 +177,9 @@ class Linear(Polynomial):
>>> from ...core.MO.polynomial import MOpolynomial, MOMonomial >>> from ...core.MO.polynomial import MOpolynomial, MOMonomial
>>> P = Linear(MOpolynomial('x', [1, 2])) >>> P = Linear(MOpolynomial('x', [1, 2]))
>>> P.roots >>> P.roots
[<Integer - 2>] [<Fraction - 2 / 1>]
>>> P = Linear(MOpolynomial('x', [2, 1])) >>> #P = Linear(MOpolynomial('x', [1, -2]))
>>> P.roots >>> #P.roots
[<Fraction - 1 / 2>]
>>> for i in P.roots[0].explain():
... print(i)
- 1 / 2
>>> P = Linear(MOpolynomial('x', [10, 6]))
>>> P.roots
[<Fraction - 3 / 5>]
>>> for i in P.roots[0].explain():
... print(i)
- 6 / 10
- 3 / 5
""" """
try: try:

View File

@ -10,7 +10,7 @@
Tokens: practical envelop of math object Tokens: practical envelop of math object
""" """
from ..renders import render from ..renders import renders
from ...core.MO.atoms import moify from ...core.MO.atoms import moify
@ -18,6 +18,8 @@ class Token(object):
""" Token: practical envelop of an math object """ """ Token: practical envelop of an math object """
RENDER = "txt"
def __init__(self, mo, name="", ancestor=None): def __init__(self, mo, name="", ancestor=None):
self._mo = mo self._mo = mo
self.name = name self.name = name
@ -32,9 +34,17 @@ class Token(object):
): ):
raise NotImplemented raise NotImplemented
@classmethod
def set_render(cls, render):
""" Define default render function
:param render: render name (txt or tex)
"""
cls.RENDER = render
def explain(self): def explain(self):
""" Yield every calculus step which have lead to self """ Yield every calculus step which have lead to self
:example: :example:
>>> from mapytex.calculus.API import Expression >>> from mapytex.calculus.API import Expression
>>> e = Expression.from_str("2+3*4") >>> e = Expression.from_str("2+3*4")
@ -54,16 +64,25 @@ class Token(object):
yield self yield self
def __repr__(self): def __repr__(self):
try: return f"<{self.__class__.__name__} {self.__txt__}>"
return f"<{self.__class__.__name__} {render(self._mo._tree, 'txt')}>"
except AttributeError:
return f"<{self.__class__.__name__} {render(self._mo, 'txt')}>"
def __str__(self): def __str__(self):
try: if self.RENDER == "tex":
return render(self._mo._tree) return self.__tex__
except AttributeError: elif self.RENDER == "txt":
return render(self._mo) return self.__txt__
else:
raise ValueError(f"Unknow render {self.RENDER}")
# return renders[self.RENDER](self._mo)
@property
def __txt__(self):
return self._mo.__txt__
@property
def __tex__(self):
return self._mo.__tex__
@property @property
def raw(self): def raw(self):
@ -242,10 +261,11 @@ class Token(object):
>>> c = a ** 2 >>> c = a ** 2
>>> c >>> c
<Decimal 5.29> <Decimal 5.29>
"""
"""
return self._operate(other, "^") return self._operate(other, "^")
def _roperate(self, other, operation): def _roperate(self, other, operation):
""" Make a operation between 2 Tokens """ """ Make a operation between 2 Tokens """
from ..expression import Expression from ..expression import Expression
@ -295,7 +315,6 @@ class Token(object):
<Linear x - 3> <Linear x - 3>
""" """
return self._roperate(other, "-") return self._roperate(other, "-")
def __rmul__(self, other): def __rmul__(self, other):
""" Multiply 2 Tokens or a Token and a Expression """ Multiply 2 Tokens or a Token and a Expression
@ -323,6 +342,7 @@ class Token(object):
""" """
return self._roperate(other, "/") return self._roperate(other, "/")
def _get_soul(self, other=None): def _get_soul(self, other=None):
""" Get the builtin soul of self or other """ """ Get the builtin soul of self or other """
if isinstance(other, Token): if isinstance(other, Token):

View File

@ -13,7 +13,7 @@ Make calculus as a student
Expression is the classe wich handle all calculus. It can randomly generate or import calculus, simplify them and explain them as a student would do. Expression is the classe wich handle all calculus. It can randomly generate or import calculus, simplify them and explain them as a student would do.
>>> from mapytex.calculus import Expression >>> from mapytex.calculus import Expression
>>> render.set_render("txt") >>> Expression.set_render("txt")
>>> e = Expression.from_str("2x + 6 - 3x") >>> e = Expression.from_str("2x + 6 - 3x")
>>> print(e) >>> print(e)
2x + 6 - 3x 2x + 6 - 3x
@ -30,7 +30,7 @@ Expression is the classe wich handle all calculus. It can randomly generate or i
""" """
from .API import Expression, Integer, Decimal, render, Polynomial, Fraction from .API import Expression, Integer, Decimal
from .core import random_list from .core import random_list
from decimal import getcontext from decimal import getcontext
#getcontext().prec = 2 #getcontext().prec = 2

View File

@ -37,7 +37,7 @@ def moify_cor(target):
>>> for i in [-2, "+", "x", "*", Decimal("3.3")]: >>> for i in [-2, "+", "x", "*", Decimal("3.3")]:
... list2molist.send(i) ... list2molist.send(i)
>>> list2molist.throw(STOOOP) >>> list2molist.throw(STOOOP)
[<MOnumber -2>, '+', <MOstr x>, '*', <MOnumber 3.3>] [<MOnumber - 2>, '+', <MOstr x>, '*', <MOnumber 3.3>]
""" """
try: try:
@ -78,7 +78,7 @@ class MOnumber(Atom):
>>> MOnumber(23) >>> MOnumber(23)
<MOnumber 23> <MOnumber 23>
>>> MOnumber(-23) >>> MOnumber(-23)
<MOnumber -23> <MOnumber - 23>
As expected there will be trouble with float As expected there will be trouble with float
@ -90,13 +90,13 @@ class MOnumber(Atom):
>>> MOnumber(Decimal("23.3")) >>> MOnumber(Decimal("23.3"))
<MOnumber 23.3> <MOnumber 23.3>
>>> MOnumber(Decimal("-23.3")) >>> MOnumber(Decimal("-23.3"))
<MOnumber -23.3> <MOnumber - 23.3>
Or directly passe a decimal string Or directly passe a decimal string
>>> MOnumber("23.3") >>> MOnumber("23.3")
<MOnumber 23.3> <MOnumber 23.3>
>>> MOnumber("-23.3") >>> MOnumber("-23.3")
<MOnumber -23.3> <MOnumber - 23.3>
MOnumber initialisation is idempotent MOnumber initialisation is idempotent
@ -259,8 +259,7 @@ class MOstr(Atom):
f"An MOstr should be initiate with a single caracter string, got {val}" f"An MOstr should be initiate with a single caracter string, got {val}"
) )
if not val.isalpha(): if not val.isalpha():
raise MOError( raise MOError(f"An MOstr should be initiate with a alpha string, got {val}")
f"An MOstr should be initiate with a alpha string, got {val}")
Atom.__init__(self, val) Atom.__init__(self, val)

View File

@ -9,8 +9,6 @@
from mapytex.calculus.core.tree import Tree from mapytex.calculus.core.tree import Tree
from .mo import Molecule, MO from .mo import Molecule, MO
from .atoms import MOnumber from .atoms import MOnumber
from decimal import Decimal
from ..arithmetic import gcd
__all__ = ["MOFraction"] __all__ = ["MOFraction"]
@ -34,10 +32,10 @@ class MOFraction(Molecule):
>>> f = MOFraction(2, 3) >>> f = MOFraction(2, 3)
>>> f >>> f
<MOFraction 2 / 3> <MOFraction 2 / 3>
>>> print(f.tree) >>> print(f.__txt__)
/ 2 / 3
> 2 >>> print(f.__tex__)
> 3 \\dfrac{2}{3}
>>> print(f) >>> print(f)
2 / 3 2 / 3
>>> f = MOFraction(2, 3, negative = True) >>> f = MOFraction(2, 3, negative = True)
@ -46,13 +44,11 @@ class MOFraction(Molecule):
""" """
_numerator = MO.factory(numerator) _numerator = MO.factory(numerator)
_denominator = MO.factory(denominator) _denominator = MO.factory(denominator)
base_tree = Tree("/", _numerator, _denominator) base_tree = Tree("/", _numerator, _denominator)
if negative: if negative:
tree = Tree("-", None, base_tree) tree = Tree("-", None, base_tree)
else: else:
tree = base_tree tree = base_tree
Molecule.__init__(self, tree) Molecule.__init__(self, tree)
self._numerator = _numerator self._numerator = _numerator
@ -72,10 +68,6 @@ class MOFraction(Molecule):
def denominator(self): def denominator(self):
return self._denominator return self._denominator
@property
def _value(self):
return Decimal(self._numerator._value) / Decimal(self._denominator._value)
def inverse(self): def inverse(self):
""" return the inverse fraction """ """ return the inverse fraction """
return MOFraction(self._denominator, self._numerator, self.negative) return MOFraction(self._denominator, self._numerator, self.negative)
@ -96,37 +88,6 @@ class MOFraction(Molecule):
else: else:
raise NotImplementedError raise NotImplementedError
def simplified(self):
""" Simplified version of self
:examplex
>>> f = MOFraction(2, 3)
>>> f
<MOFraction 2 / 3>
>>> f.simplified()
<MOFraction 2 / 3>
>>> f = MOFraction(2, 6)
>>> f
<MOFraction 2 / 6>
>>> f.simplified()
<MOFraction 1 / 3>
>>> f = MOFraction(32, 24)
>>> f.simplified()
<MOFraction 4 / 3>
>>> f = MOFraction(32, 8)
>>> f.simplified()
<MOnumber 4>
"""
frac_gcd = gcd(self.numerator._value, self.denominator._value)
new_num = self.numerator._value / frac_gcd
new_denom = self.denominator._value / frac_gcd
if new_denom == 1:
return MOnumber(new_num)
return MOFraction(new_num, new_denom)
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'

View File

@ -57,12 +57,20 @@ class MO(ABC):
pass pass
def __repr__(self): def __repr__(self):
return f"<{self.__class__.__name__} {self.__str__()}>" return f"<{self.__class__.__name__} {self.__txt__}>"
@abstractmethod @abstractmethod
def __str__(self): def __str__(self):
pass pass
@abstractmethod
def __txt__(self):
pass
@abstractmethod
def __tex__(self):
pass
def __hash__(self): def __hash__(self):
try: try:
return self._tree.__hash__() return self._tree.__hash__()
@ -153,21 +161,21 @@ class Molecule(MO):
It is a wrapping of tree It is a wrapping of tree
Its wrapping tree can be access through .tree property Its wrapping tree can be access throw .tree property
""" """
MAINOP = None MAINOP = None
def __init__(self, tree): def __init__(self, value):
""" Initiate the MO """ Initiate the MO
It should be idempotent. It should be idempotent.
""" """
try: try:
self._tree = tree._tree self._tree = value._tree
except AttributeError: except AttributeError:
self._tree = tree self._tree = value
self.is_scalar = True self.is_scalar = True
self._signature = None self._signature = None
@ -178,10 +186,18 @@ class Molecule(MO):
@property @property
def content(self): def content(self):
return self.tree return self._tree
def __str__(self): def __str__(self):
return tree2txt(self.tree) return str(self.__txt__)
@property
def __txt__(self):
return tree2txt(self._tree)
@property
def __tex__(self):
return tree2tex(self._tree)
# ----------------------------- # -----------------------------

View File

@ -31,10 +31,10 @@ class MOstrPower(Molecule):
<MOstrPower x^2> <MOstrPower x^2>
>>> print(s) >>> print(s)
x^2 x^2
>>> print(s.tree) >>> print(s.__txt__)
^ x^2
> x >>> print(s.__tex__)
> 2 x^{2}
>>> MOstrPower(3, 1) >>> MOstrPower(3, 1)
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -59,8 +59,7 @@ class MOstrPower(Molecule):
""" """
_variable = MO.factory(variable) _variable = MO.factory(variable)
if not isinstance(_variable, MOstr): if not isinstance(_variable, MOstr):
raise MOError( raise MOError("The variable of a monomial should be convertible into MOstr")
"The variable of a monomial should be convertible into MOstr")
self._variable = _variable self._variable = _variable
_power = MO.factory(power) _power = MO.factory(power)
@ -103,7 +102,7 @@ class MOstrPower(Molecule):
@property @property
def signature(self): def signature(self):
""" Name of the mo in the API """ Name of the mo in the API
:example: :example:
>>> MOstrPower("x", 3).signature >>> MOstrPower("x", 3).signature
'monome3' 'monome3'
@ -124,15 +123,14 @@ class MOstrPower(Molecule):
""" """
if self._power > 2: if self._power > 2:
return Tree( return Tree(
"*", self.power, MOstrPower(self.variable, "*", self.power, MOstrPower(self.variable, self._power._value - 1)
self._power._value - 1)
) )
return Tree("*", self.power, MOstr(self.variable)) return Tree("*", self.power, MOstr(self.variable))
class MOMonomial(Molecule): class MOMonomial(Molecule):
""" Monomial math object : ax^n""" """ Monomial math object"""
MAINOP = "*" MAINOP = "*"
@ -149,20 +147,22 @@ class MOMonomial(Molecule):
<MOMonomial 4x> <MOMonomial 4x>
>>> print(m) >>> print(m)
4x 4x
>>> print(m.tree) >>> print(m.__txt__)
* 4x
> 4 >>> print(m.__tex__)
> x 4x
>>> x = MOstrPower('x', 2) >>> x = MOstrPower('x', 2)
>>> MOMonomial(4, x) >>> MOMonomial(4, x)
<MOMonomial 4x^2> <MOMonomial 4x^2>
>>> m = MOMonomial(-1, 'x') >>> m = MOMonomial(4, 'x')
>>> m >>> m
<MOMonomial - x> <MOMonomial 4x>
>>> print(m.tree) >>> print(m)
- 4x
> None >>> print(m.__txt__)
> x 4x
>>> print(m.__tex__)
4x
>>> MOMonomial(4, 'x', 1) >>> MOMonomial(4, 'x', 1)
<MOMonomial 4x> <MOMonomial 4x>
>>> MOMonomial(4, 'x', 2) >>> MOMonomial(4, 'x', 2)
@ -170,13 +170,6 @@ class MOMonomial(Molecule):
>>> x2 = MOstrPower('x', 2) >>> x2 = MOstrPower('x', 2)
>>> MOMonomial(4, x2, 3) >>> MOMonomial(4, x2, 3)
<MOMonomial 4x^6> <MOMonomial 4x^6>
>>> m = MOMonomial(-1, 'x', 2)
>>> m
<MOMonomial - x^2>
>>> print(m.tree)
-
> None
> x^2
>>> MOMonomial(0, x) >>> MOMonomial(0, x)
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -206,21 +199,34 @@ class MOMonomial(Molecule):
self._power = _power self._power = _power
try: try:
if self.coefficient.value == 1: if self._coefficient.value != 1:
_tree = self.strpower _tree = Tree("*", self._coefficient, self.strpower)
else: else:
_tree = Tree("*", self.coefficient, self.strpower) _tree = self.strpower
except AttributeError: except AttributeError:
_tree = Tree("*", self.coefficient, self.strpower) _tree = Tree("*", self._coefficient, self.strpower)
Molecule.__init__(self, _tree) Molecule.__init__(self, _tree)
@property def __str__(self):
def tree(self): if self._coefficient != -1:
if self._coefficient == -1: return super(MOMonomial, self).__str__()
return Tree("-", None, self.strpower) else:
return "- " + self.strpower.__str__()
return Tree("*", self.coefficient, self.strpower) @property
def __txt__(self):
if self._coefficient != -1:
return super(MOMonomial, self).__txt__
else:
return "- " + self.strpower.__txt__
@property
def __tex__(self):
if self._coefficient != -1:
return super(MOMonomial, self).__tex__
else:
return "- " + self.strpower.__tex__
@property @property
def coefficient(self): def coefficient(self):
@ -259,7 +265,7 @@ class MOMonomial(Molecule):
@property @property
def signature(self): def signature(self):
""" Name of the mo in the API """ Name of the mo in the API
:example: :example:
>>> MOMonomial(2, "x").signature >>> MOMonomial(2, "x").signature
'monome1' 'monome1'

View File

@ -18,7 +18,7 @@ __all__ = ["MOpolynomial"]
class MOpolynomial(Molecule): class MOpolynomial(Molecule):
""" MO polynomial: ax^n + ... + z (can't be a monomial)""" """ MO polynomial"""
MAINOP = "+" MAINOP = "+"
@ -39,14 +39,6 @@ class MOpolynomial(Molecule):
<MOpolynomial 4x^3 + 1> <MOpolynomial 4x^3 + 1>
>>> MOpolynomial('x', {0: 1, 3: 1}) >>> MOpolynomial('x', {0: 1, 3: 1})
<MOpolynomial x^3 + 1> <MOpolynomial x^3 + 1>
>>> MOpolynomial('x', [0, 0, 3])
Traceback (most recent call last):
...
TypeError: A MOpolynomial can't be monomial it has to have more than one coefficient.
>>> MOpolynomial('x', {3: 1})
Traceback (most recent call last):
...
TypeError: A MOpolynomial can't be monomial it has to have more than one coefficient.
""" """
_variable = MO.factory(variable) _variable = MO.factory(variable)
@ -66,9 +58,6 @@ class MOpolynomial(Molecule):
raise TypeError("Coefs needs to be a dictionnary or a list") raise TypeError("Coefs needs to be a dictionnary or a list")
self._coefs = _coefs self._coefs = _coefs
if len(self._coefs) == 1:
raise TypeError("A MOpolynomial can't be monomial it has to have more than one coefficient.")
monomials = OrderedDict() monomials = OrderedDict()
for deg in sorted(self._coefs.keys()): for deg in sorted(self._coefs.keys()):
coef = self._coefs[deg] coef = self._coefs[deg]

View File

@ -40,7 +40,7 @@ def compute(node, left_v, right_v):
>>> compute("+", MOnumber(1), MOnumber(2)) >>> compute("+", MOnumber(1), MOnumber(2))
<MOnumber 3> <MOnumber 3>
>>> compute("-", None, MOnumber(2)) >>> compute("-", None, MOnumber(2))
<MOnumber -2> <MOnumber - 2>
>>> compute("*", MOnumber(1), MOnumber(2)) >>> compute("*", MOnumber(1), MOnumber(2))
<MOnumber 2> <MOnumber 2>
>>> compute("~", MOnumber(1), MOnumber(2)) >>> compute("~", MOnumber(1), MOnumber(2))
@ -70,8 +70,7 @@ def compute_capacities(node):
op = OPERATIONS[node] op = OPERATIONS[node]
lines = [[node] + [mo.__name__ for mo in MOS]] lines = [[node] + [mo.__name__ for mo in MOS]]
for left_mo in MOS: for left_mo in MOS:
lines.append([left_mo.__name__] + lines.append([left_mo.__name__] + [(left_mo, i) in op.funcs for i in MOS])
[(left_mo, i) in op.funcs for i in MOS])
return lines return lines

View File

@ -35,7 +35,7 @@ def monumber(_, right):
>>> a = MOnumber(4) >>> a = MOnumber(4)
>>> minus(None, a) >>> minus(None, a)
<MOnumber -4> <MOnumber - 4>
""" """
return MO.factory(-right.value) return MO.factory(-right.value)

View File

@ -91,11 +91,9 @@ def mul2tex(left, right):
'- 3x' '- 3x'
>>> mul2tex(a, a) >>> mul2tex(a, a)
'x \\times x' 'x \\times x'
>>> mul2tex(a, MO.factory(-3))
'x(- 3)'
""" """
left_ = render_with_parenthesis(left, "*") left_ = render_with_parenthesis(left, "*")
right_ = render_with_parenthesis(right, "*", is_at_right=True) right_ = render_with_parenthesis(right, "*")
display_time = True display_time = True
# if (right_[0].isalpha() and (left_.isnumeric() or left_.isdecimal())) or right_[ # if (right_[0].isalpha() and (left_.isnumeric() or left_.isdecimal())) or right_[
@ -185,17 +183,23 @@ def pow2tex(left, right):
return f"{left_}^{{{right_}}}" return f"{left_}^{{{right_}}}"
def render_with_parenthesis(subtree, operator, is_at_right=False): def render_with_parenthesis(subtree, operator):
subtree_need_parenthesis = False subtree_need_parenthesis = False
try: try:
subtree.node subtree.node
except AttributeError: except AttributeError:
try:
if (
OPERATORS[subtree.MAINOP]["precedence"]
< OPERATORS[operator]["precedence"]
):
subtree_need_parenthesis = True
except (AttributeError, KeyError):
pass
try: try:
subtree_ = subtree.__tex__ subtree_ = subtree.__tex__
except AttributeError: except AttributeError:
subtree_ = str(subtree) subtree_ = str(subtree)
if subtree_.startswith("-") and OPERATORS["-"]["precedence"] < OPERATORS[operator]["precedence"] and is_at_right:
subtree_need_parenthesis = True
else: else:
if OPERATORS[subtree.node]["precedence"] < OPERATORS[operator]["precedence"]: if OPERATORS[subtree.node]["precedence"] < OPERATORS[operator]["precedence"]:
subtree_need_parenthesis = True subtree_need_parenthesis = True
@ -206,8 +210,7 @@ def render_with_parenthesis(subtree, operator, is_at_right=False):
return subtree_ return subtree_
OPERATOR2TEX = {"+": plus2tex, "-": minus2tex, OPERATOR2TEX = {"+": plus2tex, "-": minus2tex, "*": mul2tex, "/": div2tex, "^": pow2tex}
"*": mul2tex, "/": div2tex, "^": pow2tex}
def tree2tex(tree): def tree2tex(tree):
@ -227,17 +230,8 @@ def tree2tex(tree):
from ..tree import Tree from ..tree import Tree
if not isinstance(tree, Tree): if not isinstance(tree, Tree):
raise ValueError( raise ValueError(f"Can only render a Tree (got {type(tree).__name__}: {tree})")
f"Can only render a Tree (got {type(tree).__name__}: {tree})") return OPERATOR2TEX[tree.node](tree.left_value, tree.right_value)
def expand(leaf):
try:
return leaf.tree
except AttributeError:
return leaf
expanded_tree = tree.map_on_leaf(expand)
return OPERATOR2TEX[expanded_tree.node](expanded_tree.left_value, expanded_tree.right_value)
# ----------------------------- # -----------------------------

View File

@ -91,13 +91,11 @@ def mul2txt(left, right):
'- 3x' '- 3x'
>>> mul2txt(a, a) >>> mul2txt(a, a)
'x * x' 'x * x'
>>> mul2txt(a, MO.factory(-3))
'x(- 3)'
""" """
display_time = True display_time = True
left_ = render_with_parenthesis(left, "*") left_ = render_with_parenthesis(left, "*")
right_ = render_with_parenthesis(right, "*", is_at_right=True) right_ = render_with_parenthesis(right, "*")
if right_[0].isalpha(): if right_[0].isalpha():
# TODO: C'est bien beurk en dessous... |ven. déc. 21 12:03:07 CET 2018 # TODO: C'est bien beurk en dessous... |ven. déc. 21 12:03:07 CET 2018
@ -189,22 +187,23 @@ def pow2txt(left, right):
return f"{left_}^{right_}" return f"{left_}^{right_}"
def tree_with_parenthesis(subtree, operator): def render_with_parenthesis(subtree, operator):
""" Assuming the subtree is a tree, then have .node """
pass
def render_with_parenthesis(subtree, operator, is_at_right=False):
subtree_need_parenthesis = False subtree_need_parenthesis = False
try: try:
subtree.node subtree.node
except AttributeError: except AttributeError:
try:
if (
OPERATORS[subtree.MAINOP]["precedence"]
< OPERATORS[operator]["precedence"]
):
subtree_need_parenthesis = True
except (AttributeError, KeyError):
pass
try: try:
subtree_ = subtree.__txt__ subtree_ = subtree.__txt__
except AttributeError: except AttributeError:
subtree_ = str(subtree) subtree_ = str(subtree)
if subtree_.startswith("-") and OPERATORS["-"]["precedence"] < OPERATORS[operator]["precedence"] and is_at_right:
subtree_need_parenthesis = True
else: else:
if OPERATORS[subtree.node]["precedence"] < OPERATORS[operator]["precedence"]: if OPERATORS[subtree.node]["precedence"] < OPERATORS[operator]["precedence"]:
subtree_need_parenthesis = True subtree_need_parenthesis = True
@ -215,8 +214,7 @@ def render_with_parenthesis(subtree, operator, is_at_right=False):
return subtree_ return subtree_
OPERATOR2TXT = {"+": plus2txt, "-": minus2txt, OPERATOR2TXT = {"+": plus2txt, "-": minus2txt, "*": mul2txt, "/": div2txt, "^": pow2txt}
"*": mul2txt, "/": div2txt, "^": pow2txt}
def tree2txt(tree): def tree2txt(tree):
@ -236,17 +234,8 @@ def tree2txt(tree):
from ..tree import Tree from ..tree import Tree
if not isinstance(tree, Tree): if not isinstance(tree, Tree):
raise ValueError( raise ValueError(f"Can only render a Tree (got {type(tree).__name__}: {tree})")
f"Can only render a Tree (got {type(tree).__name__}: {tree})") return OPERATOR2TXT[tree.node](tree.left_value, tree.right_value)
def expand(leaf):
try:
return leaf.tree
except AttributeError:
return leaf
expanded_tree = tree.map_on_leaf(expand)
return OPERATOR2TXT[expanded_tree.node](expanded_tree.left_value, expanded_tree.right_value)
# ----------------------------- # -----------------------------

View File

@ -271,7 +271,7 @@ def concurent_broadcast(target, lookfors=[]):
>>> a = searcher.throw(STOOOP) >>> a = searcher.throw(STOOOP)
>>> print(a) >>> print(a)
['az', 'ABC', 'a', 'b', 'az', 'b'] ['az', 'ABC', 'a', 'b', 'az', 'b']
>>> lfop = lookfor(something_in("+-*/()"), lambda x: f"op{x}") >>> lfop = lookfor(something_in("+-*/()"), lambda x: f"op{x}")
>>> searcher = concurent_broadcast(list_sink, [lfop]) >>> searcher = concurent_broadcast(list_sink, [lfop])
>>> for i in '12+3+234': >>> for i in '12+3+234':
@ -484,8 +484,7 @@ def lookforNumbers(target):
if current.replace("-", "", 1).isdigit(): if current.replace("-", "", 1).isdigit():
current += tok current += tok
else: else:
raise ParsingError( raise ParsingError(f"Can't build decimal with '{current}'")
f"Can't build decimal with '{current}'")
elif tok == "-": elif tok == "-":
if current == "": if current == "":
current = tok current = tok
@ -803,8 +802,7 @@ def str2(sink, convert_to_mo=True):
operator_corout(missing_times(moify_cor(pparser(sink)))) operator_corout(missing_times(moify_cor(pparser(sink))))
) )
else: else:
str2_corout = lookforNumbers( str2_corout = lookforNumbers(operator_corout(missing_times(pparser(sink))))
operator_corout(missing_times(pparser(sink))))
for i in expression.replace(" ", ""): for i in expression.replace(" ", ""):
str2_corout.send(i) str2_corout.send(i)
@ -821,7 +819,7 @@ def rdstr2(sink):
:example: :example:
>>> rdstr2list = rdstr2(list_sink) >>> rdstr2list = rdstr2(list_sink)
>>> rdstr2list("{a}+{a*b}-2") >>> rdstr2list("{a}+{a*b}-2")
[<RdLeaf a>, '+', <RdLeaf a*b>, '+', <MOnumber -2>] [<RdLeaf a>, '+', <RdLeaf a*b>, '+', <MOnumber - 2>]
>>> rdstr2list("{a}({b}x+{c})") >>> rdstr2list("{a}({b}x+{c})")
[<RdLeaf a>, '*', [<RdLeaf b>, '*', <MOstr x>, '+', <RdLeaf c>]] [<RdLeaf a>, '*', [<RdLeaf b>, '*', <MOstr x>, '+', <RdLeaf c>]]
""" """
@ -830,8 +828,7 @@ def rdstr2(sink):
def pipeline(expression): def pipeline(expression):
str2_corout = look_for_rdleaf( str2_corout = look_for_rdleaf(
lookforNumbers(operator_corout( lookforNumbers(operator_corout(missing_times(moify_cor(pparser(sink)))))
missing_times(moify_cor(pparser(sink)))))
) )
for i in expression.replace(" ", ""): for i in expression.replace(" ", ""):

View File

@ -11,11 +11,11 @@ Add MO with typing
""" """
from multipledispatch import Dispatcher from multipledispatch import Dispatcher
from ..MO import MOnumber, MOstr from ..tree import Tree
from ..MO import MO, MOnumber, MOstr
from ..MO.monomial import MOstrPower, MOMonomial from ..MO.monomial import MOstrPower, MOMonomial
from ..MO.polynomial import MOpolynomial from ..MO.polynomial import MOpolynomial
from ..MO.fraction import MOFraction from ..MO.fraction import MOFraction
from ..compute.filters import special_case
add_doc = """ Add MOs add_doc = """ Add MOs
@ -27,26 +27,8 @@ add_doc = """ Add MOs
add = Dispatcher("add", doc=add_doc) add = Dispatcher("add", doc=add_doc)
def add_filter(left, right):
""" Special cases for add MO (adding 0)
:param left: MO
:param right: MO
:returns: MO if it is a special case, nothing other wise
"""
try:
if left == 0:
return right
except TypeError:
pass
try:
if right == 0:
return left
except TypeError:
pass
@add.register((MOnumber, MOFraction), MOstr) @add.register((MOnumber, MOFraction), MOstr)
@special_case(add_filter)
def moscalar_mostr(left, right): def moscalar_mostr(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -57,15 +39,11 @@ def moscalar_mostr(left, right):
>>> a = MOFraction(1, 5) >>> a = MOFraction(1, 5)
>>> add(a, b) >>> add(a, b)
<MOpolynomial x + 1 / 5> <MOpolynomial x + 1 / 5>
>>> a = MOnumber(0)
>>> add(a, b)
<MOstr x>
""" """
return MOpolynomial(right, [left, 1]) return MOpolynomial(right, [left, 1])
@add.register(MOstr, (MOnumber, MOFraction)) @add.register(MOstr, (MOnumber, MOFraction))
@special_case(add_filter)
def mostr_moscalar(left, right): def mostr_moscalar(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -76,15 +54,11 @@ def mostr_moscalar(left, right):
>>> b = MOFraction(1, 5) >>> b = MOFraction(1, 5)
>>> add(a, b) >>> add(a, b)
<MOpolynomial x + 1 / 5> <MOpolynomial x + 1 / 5>
>>> b = MOnumber(0)
>>> add(a, b)
<MOstr x>
""" """
return MOpolynomial(left, [right, 1]) return MOpolynomial(left, [right, 1])
@add.register((MOnumber, MOFraction), MOstrPower) @add.register((MOnumber, MOFraction), MOstrPower)
@special_case(add_filter)
def moscalar_mostrpower(left, right): def moscalar_mostrpower(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -100,7 +74,6 @@ def moscalar_mostrpower(left, right):
@add.register(MOstrPower, (MOnumber, MOFraction)) @add.register(MOstrPower, (MOnumber, MOFraction))
@special_case(add_filter)
def mostrpower_moscalar(left, right): def mostrpower_moscalar(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -116,7 +89,6 @@ def mostrpower_moscalar(left, right):
@add.register((MOnumber, MOFraction), MOMonomial) @add.register((MOnumber, MOFraction), MOMonomial)
@special_case(add_filter)
def moscalar_momonomial(left, right): def moscalar_momonomial(left, right):
""" add a scalar with a MOMonomial to create a MOpolynomial """ add a scalar with a MOMonomial to create a MOpolynomial
@ -127,17 +99,11 @@ def moscalar_momonomial(left, right):
>>> a = MOFraction(1, 5) >>> a = MOFraction(1, 5)
>>> add(a, b) >>> add(a, b)
<MOpolynomial 3x^4 + 1 / 5> <MOpolynomial 3x^4 + 1 / 5>
>>> a = MOnumber(0)
>>> b = MOMonomial(2, 'x', 4)
>>> add(a, b)
<MOMonomial 2x^4>
""" """
return MOpolynomial(right.variable, {right.power: right.coefficient, 0: left}) return MOpolynomial(right.variable, {right.power: right.coefficient, 0: left})
@add.register(MOMonomial, (MOnumber, MOFraction)) @add.register(MOMonomial, (MOnumber, MOFraction))
@special_case(add_filter)
def momonial_moscalar(left, right): def momonial_moscalar(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -149,17 +115,11 @@ def momonial_moscalar(left, right):
>>> add(a, b) >>> add(a, b)
<MOpolynomial 3x^4 + 1 / 5> <MOpolynomial 3x^4 + 1 / 5>
>>> a = MOMonomial(2, 'x', 4)
>>> b = MOnumber(0)
>>> add(a, b)
<MOMonomial 2x^4>
""" """
return MOpolynomial(left.variable, {0: right, left.power: left.coefficient}) return MOpolynomial(left.variable, {0: right, left.power: left.coefficient})
@add.register((MOnumber, MOFraction), MOpolynomial) @add.register((MOnumber, MOFraction), MOpolynomial)
@special_case(add_filter)
def moscalar_mopolynomial(left, right): def moscalar_mopolynomial(left, right):
""" add a scalar with a MOpolynomial to create a MOpolynomial """ add a scalar with a MOpolynomial to create a MOpolynomial
@ -183,7 +143,6 @@ def moscalar_mopolynomial(left, right):
@add.register(MOpolynomial, (MOnumber, MOFraction)) @add.register(MOpolynomial, (MOnumber, MOFraction))
@special_case(add_filter)
def mopolynomial_moscalar(left, right): def mopolynomial_moscalar(left, right):
""" add a scalar with a MOpolynomial to create a MOpolynomial """ add a scalar with a MOpolynomial to create a MOpolynomial
@ -205,7 +164,6 @@ def mopolynomial_moscalar(left, right):
@add.register(MOstr, MOstr) @add.register(MOstr, MOstr)
@special_case(add_filter)
def mostr_mostr(left, right): def mostr_mostr(left, right):
""" add 2 mostr """ add 2 mostr
@ -220,7 +178,6 @@ def mostr_mostr(left, right):
@add.register(MOstr, MOstrPower) @add.register(MOstr, MOstrPower)
@special_case(add_filter)
def mostr_mostrpower(left, right): def mostr_mostrpower(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -238,7 +195,6 @@ def mostr_mostrpower(left, right):
@add.register(MOstrPower, MOstr) @add.register(MOstrPower, MOstr)
@special_case(add_filter)
def mostrpower_mostr(left, right): def mostrpower_mostr(left, right):
""" add a scalar with a letter to create a MOpolynomial """ add a scalar with a letter to create a MOpolynomial
@ -256,7 +212,6 @@ def mostrpower_mostr(left, right):
@add.register(MOstrPower, MOstrPower) @add.register(MOstrPower, MOstrPower)
@special_case(add_filter)
def mostrpower_mostrpower(left, right): def mostrpower_mostrpower(left, right):
""" add 2 mostrpower """ add 2 mostrpower
@ -276,7 +231,6 @@ def mostrpower_mostrpower(left, right):
@add.register(MOstr, MOpolynomial) @add.register(MOstr, MOpolynomial)
@special_case(add_filter)
def mostr_mopolynomial(left, right): def mostr_mopolynomial(left, right):
""" add a str with a MOpolynomial to create a MOpolynomial """ add a str with a MOpolynomial to create a MOpolynomial
@ -295,7 +249,6 @@ def mostr_mopolynomial(left, right):
@add.register(MOpolynomial, MOstr) @add.register(MOpolynomial, MOstr)
@special_case(add_filter)
def mopolynomial_mostr(left, right): def mopolynomial_mostr(left, right):
""" add a str with a MOpolynomial to create a MOpolynomial """ add a str with a MOpolynomial to create a MOpolynomial
@ -313,7 +266,6 @@ def mopolynomial_mostr(left, right):
@add.register(MOstrPower, MOpolynomial) @add.register(MOstrPower, MOpolynomial)
@special_case(add_filter)
def mostrpower_mopolynomial(left, right): def mostrpower_mopolynomial(left, right):
""" add a strPower with a MOpolynomial to create a MOpolynomial """ add a strPower with a MOpolynomial to create a MOpolynomial
@ -332,7 +284,6 @@ def mostrpower_mopolynomial(left, right):
@add.register(MOpolynomial, MOstrPower) @add.register(MOpolynomial, MOstrPower)
@special_case(add_filter)
def mopolynomial_mostrpower(left, right): def mopolynomial_mostrpower(left, right):
""" add a strPower with a MOpolynomial to create a MOpolynomial """ add a strPower with a MOpolynomial to create a MOpolynomial
@ -350,7 +301,6 @@ def mopolynomial_mostrpower(left, right):
@add.register(MOMonomial, MOpolynomial) @add.register(MOMonomial, MOpolynomial)
@special_case(add_filter)
def momonomial_mopolynomial(left, right): def momonomial_mopolynomial(left, right):
""" add a Monomial with a MOpolynomial to create a MOpolynomial """ add a Monomial with a MOpolynomial to create a MOpolynomial
@ -369,7 +319,6 @@ def momonomial_mopolynomial(left, right):
@add.register(MOpolynomial, MOMonomial) @add.register(MOpolynomial, MOMonomial)
@special_case(add_filter)
def mopolynomial_momonomial(left, right): def mopolynomial_momonomial(left, right):
""" add a Monomial with a MOpolynomial to create a MOpolynomial """ add a Monomial with a MOpolynomial to create a MOpolynomial
@ -387,7 +336,6 @@ def mopolynomial_momonomial(left, right):
@add.register(MOpolynomial, MOpolynomial) @add.register(MOpolynomial, MOpolynomial)
@special_case(add_filter)
def mopolynomial_mopolynomial(left, right): def mopolynomial_mopolynomial(left, right):
""" add a polynomial with a MOpolynomial to create a MOpolynomial """ add a polynomial with a MOpolynomial to create a MOpolynomial
@ -407,7 +355,6 @@ def mopolynomial_mopolynomial(left, right):
@add.register(MOstr, MOMonomial) @add.register(MOstr, MOMonomial)
@special_case(add_filter)
def mostr_monomial(left, right): def mostr_monomial(left, right):
""" add a mostr with a MOMonomial to create a MOpolynomial """ add a mostr with a MOMonomial to create a MOpolynomial
@ -423,7 +370,6 @@ def mostr_monomial(left, right):
@add.register(MOMonomial, MOstr) @add.register(MOMonomial, MOstr)
@special_case(add_filter)
def monomial_mostr(left, right): def monomial_mostr(left, right):
""" add a mostr with a MOMonomial to create a MOpolynomial """ add a mostr with a MOMonomial to create a MOpolynomial
@ -439,7 +385,6 @@ def monomial_mostr(left, right):
@add.register(MOstrPower, MOMonomial) @add.register(MOstrPower, MOMonomial)
@special_case(add_filter)
def mostrpower_monomial(left, right): def mostrpower_monomial(left, right):
""" add a mostrPower with a MOMonomial to create a MOpolynomial """ add a mostrPower with a MOMonomial to create a MOpolynomial
@ -457,7 +402,6 @@ def mostrpower_monomial(left, right):
@add.register(MOMonomial, MOstrPower) @add.register(MOMonomial, MOstrPower)
@special_case(add_filter)
def monomial_mostrpower(left, right): def monomial_mostrpower(left, right):
""" add a mostrPower with a MOMonomial to create a MOpolynomial """ add a mostrPower with a MOMonomial to create a MOpolynomial
@ -475,7 +419,6 @@ def monomial_mostrpower(left, right):
@add.register(MOMonomial, MOMonomial) @add.register(MOMonomial, MOMonomial)
@special_case(add_filter)
def monomial_momonomial(left, right): def monomial_momonomial(left, right):
""" add a moMonomial with a MOMonomial to create a MOpolynomial """ add a moMonomial with a MOMonomial to create a MOpolynomial

View File

@ -21,6 +21,6 @@ pyparsing==2.3.0
pytest==3.10.1 pytest==3.10.1
simplegeneric==0.8.1 simplegeneric==0.8.1
six==1.11.0 six==1.11.0
tabulate==0.8.7 tabulate==0.8.2
traitlets==4.3.2 traitlets==4.3.2
wcwidth==0.1.7 wcwidth==0.1.7

View File

View File

@ -1,31 +0,0 @@
import mapytex
def test_default_render():
assert mapytex.render.render_name == "txt"
def test_default_rending():
e = mapytex.Expression("2*3")
assert str(e) == "2*3"
def test_changing_render():
assert mapytex.render.render_name == "txt"
mapytex.render.set_render("tex")
assert mapytex.render.render_name == "tex"
mapytex.render.set_render("txt")
assert mapytex.render.render_name == "txt"
def test_changing_rending():
e = mapytex.Expression.from_str("2*3")
f = mapytex.Fraction("2/3")
assert str(e) == "2 * 3"
assert str(f) == "2 / 3"
mapytex.render.set_render("tex")
assert str(e) == "2 \\times 3"
assert str(f) == "\\dfrac{2}{3}"
mapytex.render.set_render("txt")
assert str(e) == "2 * 3"
assert str(f) == "2 / 3"