Merge branch 'dev_tree' of ssh://git.opytex.org:2222/lafrite/Mapytex into dev_tree

This commit is contained in:
Bertrand Benjamin 2018-12-17 11:23:34 +01:00
commit e7015e282d
5 changed files with 210 additions and 26 deletions

View File

@ -41,14 +41,38 @@ class Expression(object):
self._ancestor = ancestor self._ancestor = ancestor
@classmethod @classmethod
def from_str(cls, string): def from_str(cls, string, typing=True):
""" Initiate the expression from a string """ Initiate the expression from a string
:param string: String to parse to generate the Expression :param string: String to parse to generate the Expression
:returns: the expression :returns: the expression
:example:
>>> e = Expression.from_str("2 + 3 * 4")
>>> e
<Exp: 2 + 3 * 4>
>>> e = Expression.from_str("2/3")
>>> e
<Fraction 2 / 3>
>>> e = Expression.from_str("2x + 1")
>>> e
<Linear 2x + 1>
>>> e = Expression.from_str("2x + 1 + 5x^2")
>>> e
<Quadratic 2x + 1 + 5x^2>
>>> e = Expression.from_str("2x + 1 + 5x")
>>> e
<Exp: 2x + 1 + 5x>
""" """
t = Tree.from_str(string) t = Tree.from_str(string)
if typing:
tt = cls(t)._typing()
try:
return factory(tt)
except TypeError as e:
return cls(t)
return cls(t) return cls(t)
@classmethod @classmethod
@ -173,7 +197,7 @@ class Expression(object):
""" 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") >>> e = Expression.from_str("2x", typing=False)
>>> print(e._tree.map_on_leaf(type)) >>> print(e._tree.map_on_leaf(type))
* *
> <class 'mapytex.calculus.core.MO.mo.MOnumber'> > <class 'mapytex.calculus.core.MO.mo.MOnumber'>
@ -185,7 +209,7 @@ class Expression(object):
>>> print(type(typed_e._tree)) >>> print(type(typed_e._tree))
<class 'mapytex.calculus.core.MO.monomial.MOMonomial'> <class 'mapytex.calculus.core.MO.monomial.MOMonomial'>
>>> e = Expression.from_str("2x+3+4/5") >>> e = Expression.from_str("2x+3+4/5", typing=False)
>>> print(e._tree.map_on_leaf(type)) >>> print(e._tree.map_on_leaf(type))
+ +
> + > +

View File

@ -60,16 +60,16 @@ def factory(exp, name="", ancestor=None):
if isinstance(mo, MOnumber): if isinstance(mo, MOnumber):
if isinstance(mo.value, int): if isinstance(mo.value, int):
return Integer(mo, name, ancestor) return Integer.from_mo(mo, name, ancestor)
elif isinstance(mo.value, _Decimal): elif isinstance(mo.value, _Decimal):
return Decimal(mo, name, ancestor) return Decimal.from_mo(mo, name, ancestor)
raise TypeError(f"Can't build from MOnumber ({mo}) neither int nor decimal") raise TypeError(f"Can't build from MOnumber ({mo}) neither int nor decimal")
elif isinstance(mo, MOFraction): elif isinstance(mo, MOFraction):
if isinstance(mo._denominator, MOnumber) and \ if isinstance(mo._denominator, MOnumber) and \
isinstance(mo._numerator, MOnumber): isinstance(mo._numerator, MOnumber):
return Fraction(mo, name, ancestor) return Fraction.from_mo(mo, name, ancestor)
raise TypeError(f"Can't build from MOFraction ({mo}) numerator and denominator are not MOnumber") raise TypeError(f"Can't build from MOFraction ({mo}) numerator and denominator are not MOnumber")
@ -79,13 +79,13 @@ def factory(exp, name="", ancestor=None):
if isinstance(mo, MOstr) or \ if isinstance(mo, MOstr) or \
(isinstance(mo, MOMonomial) and mo.power.value == 1) or \ (isinstance(mo, MOMonomial) and mo.power.value == 1) or \
(isinstance(mo, MOpolynomial) and mo.power.value == 1): (isinstance(mo, MOpolynomial) and mo.power.value == 1):
return Linear(mo, name, ancestor) return Linear.from_mo(mo, name, ancestor)
elif (isinstance(mo, MOstrPower) and mo.power.value == 2) or \ elif (isinstance(mo, MOstrPower) and mo.power.value == 2) or \
(isinstance(mo, MOMonomial) and mo.power.value == 2) or \ (isinstance(mo, MOMonomial) and mo.power.value == 2) or \
(isinstance(mo, MOpolynomial) and mo.power.value == 2): (isinstance(mo, MOpolynomial) and mo.power.value == 2):
return Quadratic(mo, name, ancestor) return Quadratic.from_mo(mo, name, ancestor)
else: else:
return Polynomial(mo, name, ancestor) return Polynomial.from_mo(mo, name, ancestor)
else: else:
raise TypeError(f"{type(mo)} is unknown MathObject") raise TypeError(f"{type(mo)} is unknown MathObject")

View File

@ -11,6 +11,7 @@ Tokens representing interger and decimal
""" """
from .token import Token from .token import Token
from ...core.MO import MO
from ...core.MO.mo import MOnumber from ...core.MO.mo import MOnumber
from ...core.MO.fraction import MOFraction from ...core.MO.fraction import MOFraction
from decimal import Decimal as _Decimal from decimal import Decimal as _Decimal
@ -19,17 +20,37 @@ __all__ = ["Integer", "Decimal"]
class Integer(Token): class Integer(Token):
""" Token representing a integer """ """ Token representing a integer
:example:
>>> Integer(4)
<Integer 4>
>>> a = MOnumber(4)
>>> Integer.from_mo(a)
<Integer 4>
"""
def __init__(self, mo, name="", ancestor=None): def __init__(self, a, name="", ancestor=None):
if not isinstance(mo, MOnumber): if not isinstance(a, MO):
raise TypeError if not isinstance(a, int):
if not isinstance(mo.value, int): raise TypeError
raise TypeError mo = MOnumber(a)
else:
mo = a
Token.__init__(self, mo, name, ancestor) Token.__init__(self, mo, name, ancestor)
self._mathtype = 'entier' self._mathtype = 'entier'
@classmethod
def from_mo(cls, mo, name="", ancestor=None):
if not isinstance(mo, MOnumber):
raise TypeError
if not isinstance(mo.value, int):
raise TypeError
return cls(mo, name, ancestor)
@classmethod @classmethod
def random(cls): def random(cls):
raise NotImplemented raise NotImplemented
@ -38,14 +59,26 @@ class Decimal(Token):
""" Token representing a decimal """ """ Token representing a decimal """
def __init__(self, mo, name="", ancestor=None): def __init__(self, a, name="", ancestor=None):
if not isinstance(a, MO):
if isinstance(a, (str, float)):
mo = MOnumber(Decimal(a))
else:
raise TypeError
else:
mo = a
self._mathtype = 'décimal'
Token.__init__(self, mo, name, ancestor)
@classmethod
def from_mo(cls, mo, name="", ancestor=None):
if not isinstance(mo, MOnumber): if not isinstance(mo, MOnumber):
raise TypeError raise TypeError
if not isinstance(mo.value, _Decimal): if not isinstance(mo.value, _Decimal):
raise TypeError raise TypeError
Token.__init__(self, mo, name, ancestor) return cls(mo, name, ancestor)
self._mathtype = 'décimal'
@classmethod @classmethod
def random(cls): def random(cls):
@ -55,7 +88,21 @@ class Fraction(Token):
""" Token representing a fraction """ """ Token representing a fraction """
def __init__(self, mo, name="", ancestor=None): def __init__(self, a, name="", ancestor=None):
if not isinstance(a, MO):
if isinstance(a, str):
num, denom = a.split('/')
mo = MOFraction(int(num), int(denom))
else:
raise TypeError
else:
mo = a
self._mathtype = 'fraction'
Token.__init__(self, mo, name, ancestor)
@classmethod
def from_mo(cls, mo, name="", ancestor=None):
if not isinstance(mo, MOFraction): if not isinstance(mo, MOFraction):
raise TypeError raise TypeError
if not isinstance(mo._numerator, MOnumber): if not isinstance(mo._numerator, MOnumber):
@ -63,8 +110,7 @@ class Fraction(Token):
if not isinstance(mo._denominator, MOnumber): if not isinstance(mo._denominator, MOnumber):
raise TypeError raise TypeError
Token.__init__(self, mo, name, ancestor) return cls(mo, name, ancestor)
self._mathtype = 'fraction'
@classmethod @classmethod
def random(cls): def random(cls):

View File

@ -11,6 +11,7 @@ Tokens representing polynomials functions
""" """
from .token import Token from .token import Token
from ...core.MO import MO
__all__ = ["Polynomial", "Quadratic", "Linear"] __all__ = ["Polynomial", "Quadratic", "Linear"]
@ -18,11 +19,23 @@ class Polynomial(Token):
""" Token representing a polynomial """ """ Token representing a polynomial """
def __init__(self, mo, name="", ancestor=None): def __init__(self, a, name="", ancestor=None):
if not isinstance(a, MO):
if isinstance(a, str):
raise TypeError
else:
raise TypeError
else:
mo = a
Token.__init__(self, mo, name, ancestor) Token.__init__(self, mo, name, ancestor)
self._mathtype = 'polynome' self._mathtype = 'polynome'
@classmethod
def from_mo(cls, mo, name="", ancestor=None):
return cls(mo, name, ancestor)
@classmethod @classmethod
def random(cls): def random(cls):
raise NotImplemented raise NotImplemented
@ -39,26 +52,26 @@ class Polynomial(Token):
""" Call a Polynomial to evaluate itself on value """ """ Call a Polynomial to evaluate itself on value """
pass pass
class Linear(Token): class Linear(Polynomial):
""" Token representing a linear """ """ Token representing a linear """
def __init__(self, mo, name="", ancestor=None): def __init__(self, mo, name="", ancestor=None):
Token.__init__(self, mo, name, ancestor) Polynomial.__init__(self, mo, name, ancestor)
self._mathtype = 'affine' self._mathtype = 'affine'
@classmethod @classmethod
def random(cls): def random(cls):
raise NotImplemented raise NotImplemented
class Quadratic(Token): class Quadratic(Polynomial):
""" Token representing a quadratic """ """ Token representing a quadratic """
def __init__(self, mo, name="", ancestor=None): def __init__(self, mo, name="", ancestor=None):
Token.__init__(self, mo, name, ancestor) Polynomial.__init__(self, mo, name, ancestor)
self._mathtype = 'polynome du 2nd degré' self._mathtype = 'polynome du 2nd degré'
@classmethod @classmethod

View File

@ -63,6 +63,107 @@ class Token(object):
def __tex__(self): def __tex__(self):
return self._mo.__tex__ return self._mo.__tex__
def _operate(self, other, operation):
""" Make a operation between 2 Tokens,
a Token and en Expression ora
a Token an a builtin type
"""
from ..expression import Expression
from ...core import Tree
from . import factory
if not isinstance(other, Token):
_other = factory(other)
else:
_other = other
tree = Tree(operation, self._mo, _other._mo)
return Expression(tree).simplify()
def __add__(self, other):
""" Adding 2 Tokens or a Token and a Expression
:example:
>>> from .number import Integer
>>> a = Integer(3)
>>> b = Integer(7)
>>> c = a + b
>>> c
<Integer 10>
>>> for i in c.explain():
... print(i)
3 + 7
10
>>> from .number import Fraction
>>> a = Fraction("4/3")
>>> b = Integer(7)
>>> c = a + b
>>> c
<Fraction 25 / 3>
>>> for i in c.explain():
... print(i)
4 / 3 + 7
4 / 3 + 7 / 1
4 / 3 + (7 * 3) / (1 * 3)
4 / 3 + 21 / 3
(4 + 21) / 3
25 / 3
"""
return self._operate(other, "+")
def __mul__(self, other):
""" Multiply 2 Tokens or a Token and a Expression
:example:
>>> from .number import Integer
>>> a = Integer(3)
>>> b = Integer(7)
>>> c = a * b
>>> c
<Integer 21>
>>> for i in c.explain():
... print(i)
3 * 7
21
>>> from .number import Fraction
>>> a = Fraction("4/3")
>>> b = Integer(7)
>>> c = a * b
>>> c
<Fraction 28 / 3>
>>> for i in c.explain():
... print(i)
4 / 3 * 7
(4 * 7) / 3
28 / 3
"""
return self._operate(other, "*")
def __truediv__(self, other):
""" Divising 2 Tokens or a Token and a Expression
:example:
>>> from .number import Integer
>>> a = Integer(3)
>>> b = Integer(7)
>>> c = a / b
>>> c
<Fraction 3 / 7>
>>> for i in c.explain():
... print(i)
3 / 7
>>> from .number import Fraction
>>> a = Fraction("4/3")
>>> b = Integer(7)
>>> c = a / b
>>> c
<Fraction 4 / 21>
>>> for i in c.explain():
... print(i)
4 / 3 / 7
4 / 3 * 1 / 7
(4 * 1) / (3 * 7)
4 / 21
"""
return self._operate(other, "/")