47 Commits

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

View File

@@ -108,52 +108,12 @@ 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+1)")
>>> e_simplified = e.simplify()
>>> e_simplified
<Quadratic - 2x^2 - x + 3>
>>> for s in e_simplified.explain():
... print(s)
""" """
from .expression import Expression from .expression import Expression
from .tokens import Token
from .tokens.number import Integer, Decimal from .tokens.number import Integer, Decimal
def set_render(render):
"""
: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
>>> set_render('tex')
>>> Expression.RENDER
'tex'
>>> Token.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}
>>> set_render('txt')
"""
Expression.set_render(render)
Token.set_render(render)
if __name__ == "__main__": if __name__ == "__main__":
e = Expression.from_str("1+2/3/4/5") e = Expression.from_str("1+2/3/4/5")
et = e._typing() et = e._typing()

View File

@@ -56,7 +56,33 @@ class Expression(object):
:param render: render name (txt or tex) :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 cls.RENDER = render
@classmethod @classmethod
@@ -110,11 +136,9 @@ class Expression(object):
:returns: TODO :returns: TODO
:example: :example:
>>> e = Expression.random("{a}/{a*k}") >>> Expression.random("{a}/{a*k}") # doctest: +SKIP
>>> e # doctest: +SKIP
<Exp: -3 / -15> <Exp: -3 / -15>
>>> e = Expression.random("{a}/{a*k} - 3*{b}", variables_scope={'a':{'min_max':(10, 30)}}) >>> Expression.random("{a}/{a*k} - 3*{b}", variables_scope={'a':{'min_max':(10, 30)}}) # doctest: +SKIP
>>> e # doctest: +SKIP
<Exp: 18 / 108 - 3 * 9> <Exp: 18 / 108 - 3 * 9>
>>> e = Expression.random("{a}*x + {b}*x + 3", ["a>b"], rejected=[0, 1]) >>> e = Expression.random("{a}*x + {b}*x + 3", ["a>b"], rejected=[0, 1])
>>> ee = e.simplify() >>> ee = e.simplify()
@@ -157,7 +181,7 @@ class Expression(object):
""" 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
@@ -178,8 +202,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)
@@ -196,7 +219,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)
@@ -237,7 +260,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__))
@@ -282,7 +305,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))
@@ -347,7 +370,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

@@ -44,7 +44,7 @@ class Token(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:
>>> 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")
@@ -64,10 +64,25 @@ class Token(object):
yield self yield self
def __repr__(self): def __repr__(self):
return f"<{self.__class__.__name__} {renders['txt'](self._mo)}>" return f"<{self.__class__.__name__} {self.__txt__}>"
def __str__(self): def __str__(self):
return renders[self.RENDER](self._mo) if self.RENDER == "tex":
return self.__tex__
elif self.RENDER == "txt":
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):
@@ -246,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
@@ -299,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
@@ -327,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

@@ -31,7 +31,7 @@ Expression is the classe wich handle all calculus. It can randomly generate or i
""" """
from .API import Expression, Integer, Decimal from .API import Expression, Integer, Decimal
from .core import random_list from .core import list_generator
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

@@ -32,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)
@@ -44,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

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,8 +123,7 @@ 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))
@@ -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

@@ -66,7 +66,7 @@ from .tree import Tree, AssocialTree
from .compute import compute from .compute import compute
from .typing import typing, TypingError from .typing import typing, TypingError
from .renders import tree2txt, tree2tex from .renders import tree2txt, tree2tex
from .random import list_generator as random_list from .random import list_generator
# ----------------------------- # -----------------------------

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

@@ -71,7 +71,7 @@ This function ignores tree structure and works with lists
{'a': -8, 'a*b': -40, 'b': 5, 'c': 4} {'a': -8, 'a*b': -40, 'b': 5, 'c': 4}
""" """
__all__ = ["list_generator"] __all__ = ["generator"]
from random import choice from random import choice
from functools import reduce from functools import reduce
@@ -256,7 +256,7 @@ def build_variable_scope(rd_variables, rejected, min_max, variables_scope):
return complete_scope return complete_scope
def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), variables_scope={}, dictionnary=False): def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), variables_scope={}):
""" Generate random computed values from the list """ Generate random computed values from the list
:param rd_variables: list of random variables to generate (can be computed value - "a*b") :param rd_variables: list of random variables to generate (can be computed value - "a*b")
@@ -264,25 +264,17 @@ def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), var
:param rejected: Rejected values for the generator (default [0]) :param rejected: Rejected values for the generator (default [0])
:param min_max: (min, max) limits in between variables will be generated :param min_max: (min, max) limits in between variables will be generated
:param variables_scope: rejected and min_max define for individual variables :param variables_scope: rejected and min_max define for individual variables
:param dictionnary: the return value will be a dictionnary with var_list as keys (default False)
:return: dictionnary of generated variables :return: dictionnary of generated variables
:example: :example:
>>> a, ab, b, c = list_generator(["a", "a*b", "b", "c"]) >>> values = list_generator(["a", "a*b", "b", "c"])
>>> a, ab, b, c # doctest: +SKIP >>> values # doctest: +SKIP
(5, -20, -4, -3) >>> values["a"] * values["b"] == values["a*b"]
>>> a * b == ab
True True
>>> ab # doctest: +SKIP >>> values["a*b"] # doctest: +SKIP
-20 >>> values["a"] * values["b"] # doctest: +SKIP
>>> a, b # doctest: +SKIP
5, -4
>>> list_generator(["a", "a*b", "b", "c"], dictionnary=True) # doctest: +SKIP
{'a': -3, 'a*b': 18, 'b': -6, 'c': -4}
""" """
rv = extract_rv(var_list) rv = extract_rv(var_list)
rv_gen = random_generator(rv, conditions, rejected, min_max, variables_scope) rv_gen = random_generator(rv, conditions, rejected, min_max, variables_scope)
generated = compute_leafs(var_list, rv_gen) generated = compute_leafs(var_list, rv_gen)
if dictionnary: return generated
return generated
return [generated[v] for v in var_list]

View File

@@ -210,8 +210,7 @@ def render_with_parenthesis(subtree, operator):
return subtree_ return subtree_
OPERATOR2TEX = {"+": plus2tex, "-": minus2tex, OPERATOR2TEX = {"+": plus2tex, "-": minus2tex, "*": mul2tex, "/": div2tex, "^": pow2tex}
"*": mul2tex, "/": div2tex, "^": pow2tex}
def tree2tex(tree): def tree2tex(tree):
@@ -231,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

@@ -214,8 +214,7 @@ def render_with_parenthesis(subtree, operator):
return subtree_ return subtree_
OPERATOR2TXT = {"+": plus2txt, "-": minus2txt, OPERATOR2TXT = {"+": plus2txt, "-": minus2txt, "*": mul2txt, "/": div2txt, "^": pow2txt}
"*": mul2txt, "/": div2txt, "^": pow2txt}
def tree2txt(tree): def tree2txt(tree):
@@ -235,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

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

@@ -7,7 +7,7 @@ except ImportError:
setup( setup(
name="mapytex", name="mapytex",
version="2.3.2", version="2.3",
description="Computing like a student", description="Computing like a student",
author="Benjamin Bertrand", author="Benjamin Bertrand",
author_email="programming@opytex.org", author_email="programming@opytex.org",