From: Vivien Maisonneuve Date: Tue, 15 Jul 2014 12:42:48 +0000 (+0200) Subject: Small implementation improvement in linexprs.py X-Git-Tag: 1.0~108 X-Git-Url: https://scm.cri.mines-paristech.fr/git/linpy.git/commitdiff_plain/9de08f6d690b0ad9f279e9ff78646c307b6beb7e?ds=inline;hp=1695c920d030869b3a842736fe5bcf963f2ffc52 Small implementation improvement in linexprs.py --- diff --git a/pypol/linexprs.py b/pypol/linexprs.py index b74628b..c5f4336 100644 --- a/pypol/linexprs.py +++ b/pypol/linexprs.py @@ -40,26 +40,26 @@ class Expression: return Rational(constant) if isinstance(coefficients, Mapping): coefficients = coefficients.items() + coefficients = list(coefficients) for symbol, coefficient in coefficients: if not isinstance(symbol, Symbol): raise TypeError('symbols must be Symbol instances') if not isinstance(coefficient, numbers.Rational): raise TypeError('coefficients must be rational numbers') - coefficients = [(symbol, Fraction(coefficient)) - for symbol, coefficient in coefficients if coefficient != 0] if not isinstance(constant, numbers.Rational): raise TypeError('constant must be a rational number') - constant = Fraction(constant) if len(coefficients) == 0: return Rational(constant) if len(coefficients) == 1 and constant == 0: symbol, coefficient = coefficients[0] if coefficient == 1: return symbol + coefficients = [(symbol, Fraction(coefficient)) + for symbol, coefficient in coefficients if coefficient != 0] + coefficients.sort(key=lambda item: item[0].sortkey()) self = object().__new__(cls) - self._coefficients = OrderedDict(sorted(coefficients, - key=lambda item: item[0].sortkey())) - self._constant = constant + self._coefficients = OrderedDict(coefficients) + self._constant = Fraction(constant) self._symbols = tuple(self._coefficients) self._dimension = len(self._symbols) return self @@ -67,10 +67,7 @@ class Expression: def coefficient(self, symbol): if not isinstance(symbol, Symbol): raise TypeError('symbol must be a Symbol instance') - try: - return Rational(self._coefficients[symbol]) - except KeyError: - return Rational(0) + return Rational(self._coefficients.get(symbol, 0)) __getitem__ = coefficient @@ -131,14 +128,14 @@ class Expression: constant = self._constant - other._constant return Expression(coefficients, constant) + @_polymorphic def __rsub__(self, other): - return -(self - other) + return other - self def __mul__(self, other): if isinstance(other, numbers.Rational): - coefficients = dict(self._coefficients) - for symbol in coefficients: - coefficients[symbol] *= other + coefficients = ((symbol, coefficient * other) + for symbol, coefficient in self._coefficients.items()) constant = self._constant * other return Expression(coefficients, constant) return NotImplemented @@ -147,38 +144,32 @@ class Expression: def __truediv__(self, other): if isinstance(other, numbers.Rational): - coefficients = dict(self._coefficients) - for symbol in coefficients: - coefficients[symbol] /= other + coefficients = ((symbol, coefficient / other) + for symbol, coefficient in self._coefficients.items()) constant = self._constant / other - # import pdb; pdb.set_trace() return Expression(coefficients, constant) return NotImplemented @_polymorphic def __eq__(self, other): - # "normal" equality + # returns a boolean, not a constraint # see http://docs.sympy.org/dev/tutorial/gotchas.html#equals-signs return isinstance(other, Expression) and \ self._coefficients == other._coefficients and \ self._constant == other._constant - @_polymorphic def __le__(self, other): from .polyhedra import Le return Le(self, other) - @_polymorphic def __lt__(self, other): from .polyhedra import Lt return Lt(self, other) - @_polymorphic def __ge__(self, other): from .polyhedra import Ge return Ge(self, other) - @_polymorphic def __gt__(self, other): from .polyhedra import Gt return Gt(self, other) @@ -349,8 +340,7 @@ class Symbol(Expression): return True def __eq__(self, other): - return not isinstance(other, Dummy) and isinstance(other, Symbol) \ - and self.name == other.name + return self.sortkey() == other.sortkey() def asdummy(self): return Dummy(self.name) @@ -374,8 +364,10 @@ class Symbol(Expression): @classmethod def fromsympy(cls, expr): import sympy - if isinstance(expr, sympy.Symbol): - return cls(expr.name) + if isinstance(expr, sympy.Dummy): + return Dummy(expr.name) + elif isinstance(expr, sympy.Symbol): + return Symbol(expr.name) else: raise TypeError('expr must be a sympy.Symbol instance') @@ -387,6 +379,8 @@ class Dummy(Symbol): def __new__(cls, name=None): if name is None: name = 'Dummy_{}'.format(Dummy._count) + elif not isinstance(name, str): + raise TypeError('name must be a string') self = object().__new__(cls) self._index = Dummy._count self._name = name.strip() @@ -403,9 +397,6 @@ class Dummy(Symbol): def sortkey(self): return self._name, self._index - def __eq__(self, other): - return isinstance(other, Dummy) and self._index == other._index - def __repr__(self): return '_{}'.format(self.name) @@ -442,12 +433,6 @@ class Rational(Expression, Fraction): def __bool__(self): return Fraction.__bool__(self) - @classmethod - def fromstring(cls, string): - if not isinstance(string, str): - raise TypeError('string must be a string instance') - return Rational(string) - def __repr__(self): if self.denominator == 1: return '{!r}'.format(self.numerator) diff --git a/pypol/tests/test_linexprs.py b/pypol/tests/test_linexprs.py index 01f844f..1966b2a 100644 --- a/pypol/tests/test_linexprs.py +++ b/pypol/tests/test_linexprs.py @@ -294,13 +294,6 @@ class TestRational(unittest.TestCase): self.assertFalse(self.zero) self.assertTrue(self.pi) - def test_fromstring(self): - self.assertEqual(Rational.fromstring('22/7'), self.pi) - with self.assertRaises(ValueError): - Rational.fromstring('a') - with self.assertRaises(TypeError): - Rational.fromstring(1) - def test_repr(self): self.assertEqual(repr(self.zero), '0') self.assertEqual(repr(self.one), '1')