X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/1d494bb187b70135df721c13306d7f26fdf33f50..7db03eb9ea6c6d0a3896d8682b64fd404a833e92:/pypol/linexprs.py?ds=sidebyside diff --git a/pypol/linexprs.py b/pypol/linexprs.py index 0db7edd..d8b020d 100644 --- a/pypol/linexprs.py +++ b/pypol/linexprs.py @@ -3,6 +3,7 @@ import functools import numbers import re +from collections import OrderedDict from fractions import Fraction, gcd @@ -67,13 +68,14 @@ class Expression: raise TypeError('coefficients must be rational numbers ' 'or Constant instances') self._coefficients[symbol] = coefficient + self._coefficients = OrderedDict(sorted(self._coefficients.items())) if isinstance(constant, Constant): constant = constant.constant if not isinstance(constant, numbers.Rational): raise TypeError('constant must be a rational number ' 'or a Constant instance') self._constant = constant - self._symbols = tuple(sorted(self._coefficients)) + self._symbols = tuple(self._coefficients) self._dimension = len(self._symbols) return self @@ -90,8 +92,7 @@ class Expression: __getitem__ = coefficient def coefficients(self): - for symbol in self.symbols: - yield symbol, self.coefficient(symbol) + yield from self._coefficients.items() @property def constant(self): @@ -220,7 +221,7 @@ class Expression: return Gt(self, other) def __hash__(self): - return hash((tuple(sorted(self._coefficients.items())), self._constant)) + return hash((tuple(self.coefficients()), self._constant)) def _toint(self): lcm = functools.reduce(lambda a, b: a*b // gcd(a, b), @@ -252,9 +253,12 @@ class Expression: return left / right raise SyntaxError('invalid syntax') + _RE_NUM_VAR = re.compile(r'(\d+|\))\s*([^\W\d_]\w*|\()') + @classmethod def fromstring(cls, string): - string = re.sub(r'(\d+|\))\s*([^\W\d_]\w*|\()', r'\1*\2', string) + # add implicit multiplication operators, e.g. '5x' -> '5*x' + string = cls._RE_NUM_VAR.sub(r'\1*\2', string) tree = ast.parse(string, 'eval') return cls._fromast(tree)