X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/8f61fe65a53ff47b23c8527c47e2bed32c1d2e6f..7fff25bf40e4db570565586fb49165d1675002c2:/linpy/linexprs.py diff --git a/linpy/linexprs.py b/linpy/linexprs.py index aedf170..bc36fda 100644 --- a/linpy/linexprs.py +++ b/linpy/linexprs.py @@ -49,6 +49,9 @@ class Expression: """ def __new__(cls, coefficients=None, constant=0): + """ + Create a new expression. + """ if isinstance(coefficients, str): if constant != 0: raise TypeError('too many arguments') @@ -82,6 +85,9 @@ class Expression: return self def coefficient(self, symbol): + """ + Return the coefficient value of the given symbol. + """ if not isinstance(symbol, Symbol): raise TypeError('symbol must be a Symbol instance') return Rational(self._coefficients.get(symbol, 0)) @@ -89,31 +95,52 @@ class Expression: __getitem__ = coefficient def coefficients(self): + """ + Return a list of the coefficients of an expression + """ for symbol, coefficient in self._coefficients.items(): yield symbol, Rational(coefficient) @property def constant(self): + """ + Return the constant value of an expression. + """ return Rational(self._constant) @property def symbols(self): + """ + Return a list of symbols in an expression. + """ return self._symbols @property def dimension(self): + """ + Create and return a new linear expression from a string or a list of coefficients and a constant. + """ return self._dimension def __hash__(self): return hash((tuple(self._coefficients.items()), self._constant)) def isconstant(self): + """ + Return true if an expression is a constant. + """ return False def issymbol(self): + """ + Return true if an expression is a symbol. + """ return False def values(self): + """ + Return the coefficient and constant values of an expression. + """ for coefficient in self._coefficients.values(): yield Rational(coefficient) yield Rational(self._constant) @@ -129,6 +156,9 @@ class Expression: @_polymorphic def __add__(self, other): + """ + Return the sum of two expressions. + """ coefficients = defaultdict(Fraction, self._coefficients) for symbol, coefficient in other._coefficients.items(): coefficients[symbol] += coefficient @@ -139,6 +169,9 @@ class Expression: @_polymorphic def __sub__(self, other): + """ + Return the difference between two expressions. + """ coefficients = defaultdict(Fraction, self._coefficients) for symbol, coefficient in other._coefficients.items(): coefficients[symbol] -= coefficient @@ -150,6 +183,9 @@ class Expression: return other - self def __mul__(self, other): + """ + Return the product of two expressions if other is a rational number. + """ if isinstance(other, numbers.Rational): coefficients = ((symbol, coefficient * other) for symbol, coefficient in self._coefficients.items()) @@ -169,8 +205,9 @@ class Expression: @_polymorphic def __eq__(self, other): - # returns a boolean, not a constraint - # see http://docs.sympy.org/dev/tutorial/gotchas.html#equals-signs + """ + Test whether two expressions are equal + """ return isinstance(other, Expression) and \ self._coefficients == other._coefficients and \ self._constant == other._constant @@ -192,11 +229,18 @@ class Expression: return Gt(self, other) def scaleint(self): + """ + Multiply an expression by a scalar to make all coefficients integer values. + """ lcm = functools.reduce(lambda a, b: a*b // gcd(a, b), [value.denominator for value in self.values()]) return self * lcm def subs(self, symbol, expression=None): + """ + Subsitute symbol by expression in equations and return the resulting + expression. + """ if expression is None: if isinstance(symbol, Mapping): symbol = symbol.items() @@ -244,6 +288,9 @@ class Expression: @classmethod def fromstring(cls, string): + """ + Create an expression from a string. + """ # add implicit multiplication operators, e.g. '5x' -> '5*x' string = Expression._RE_NUM_VAR.sub(r'\1*\2', string) tree = ast.parse(string, 'eval') @@ -306,6 +353,9 @@ class Expression: @classmethod def fromsympy(cls, expr): + """ + Convert sympy object to an expression. + """ import sympy coefficients = [] constant = 0 @@ -321,6 +371,9 @@ class Expression: return Expression(coefficients, constant) def tosympy(self): + """ + Return an expression as a sympy object. + """ import sympy expr = 0 for symbol, coefficient in self.coefficients(): @@ -333,6 +386,9 @@ class Expression: class Symbol(Expression): def __new__(cls, name): + """ + Create and return a symbol from a string. + """ if not isinstance(name, str): raise TypeError('name must be a string') self = object().__new__(cls) @@ -360,6 +416,9 @@ class Symbol(Expression): return self.sortkey() == other.sortkey() def asdummy(self): + """ + Return a symbol as a Dummy Symbol. + """ return Dummy(self.name) @classmethod @@ -390,10 +449,15 @@ class Symbol(Expression): class Dummy(Symbol): - + """ + This class returns a dummy symbol to ensure that no variables are repeated in an expression + """ _count = 0 def __new__(cls, name=None): + """ + Create and return a new dummy symbol. + """ if name is None: name = 'Dummy_{}'.format(Dummy._count) elif not isinstance(name, str): @@ -422,12 +486,18 @@ class Dummy(Symbol): def symbols(names): + """ + Transform strings into instances of the Symbol class + """ if isinstance(names, str): names = names.replace(',', ' ').split() return tuple(Symbol(name) for name in names) class Rational(Expression, Fraction): + """ + This class represents integers and rational numbers of any size. + """ def __new__(cls, numerator=0, denominator=None): self = object().__new__(cls) @@ -444,9 +514,15 @@ class Rational(Expression, Fraction): @property def constant(self): + """ + Return rational as a constant. + """ return self def isconstant(self): + """ + Test whether a value is a constant. + """ return True def __bool__(self): @@ -470,6 +546,9 @@ class Rational(Expression, Fraction): @classmethod def fromsympy(cls, expr): + """ + Create a rational object from a sympy expression + """ import sympy if isinstance(expr, sympy.Rational): return Rational(expr.p, expr.q)