X-Git-Url: https://svn.cri.ensmp.fr/git/linpy.git/blobdiff_plain/3b1b3560c8880ef25995a18b6e365e0d730a2df2..af10bce9dc286c2b3ffe6520c4ed0047a4475320:/pypol/linear.py diff --git a/pypol/linear.py b/pypol/linear.py index 8e96f35..5f3c559 100644 --- a/pypol/linear.py +++ b/pypol/linear.py @@ -72,15 +72,17 @@ class Expression: if not isinstance(constant, numbers.Rational): raise TypeError('constant must be a rational number') self._constant = constant + self._symbols = tuple(sorted(self._coefficients)) + self._dimension = len(self._symbols) return self - + @property def symbols(self): - yield from sorted(self._coefficients) + return self._symbols @property def dimension(self): - return len(list(self.symbols())) + return self._dimension def coefficient(self, symbol): if isinstance(symbol, Expression) and symbol.issymbol(): @@ -94,9 +96,8 @@ class Expression: __getitem__ = coefficient - @property def coefficients(self): - for symbol in self.symbols(): + for symbol in self.symbols: yield symbol, self.coefficient(symbol) @property @@ -107,19 +108,20 @@ class Expression: return len(self._coefficients) == 0 def values(self): - for symbol in self.symbols(): + for symbol in self.symbols: yield self.coefficient(symbol) yield self.constant def values_int(self): - for symbol in self.symbols(): + for symbol in self.symbols: return self.coefficient(symbol) return int(self.constant) + @property def symbol(self): if not self.issymbol(): raise ValueError('not a symbol: {}'.format(self)) - for symbol in self.symbols(): + for symbol in self.symbols: return symbol def issymbol(self): @@ -136,8 +138,8 @@ class Expression: @_polymorphic_method def __add__(self, other): - coefficients = dict(self.coefficients) - for symbol, coefficient in other.coefficients: + coefficients = dict(self.coefficients()) + for symbol, coefficient in other.coefficients(): if symbol in coefficients: coefficients[symbol] += coefficient else: @@ -149,8 +151,8 @@ class Expression: @_polymorphic_method def __sub__(self, other): - coefficients = dict(self.coefficients) - for symbol, coefficient in other.coefficients: + coefficients = dict(self.coefficients()) + for symbol, coefficient in other.coefficients(): if symbol in coefficients: coefficients[symbol] -= coefficient else: @@ -164,7 +166,7 @@ class Expression: @_polymorphic_method def __mul__(self, other): if other.isconstant(): - coefficients = dict(self.coefficients) + coefficients = dict(self.coefficients()) for symbol in coefficients: coefficients[symbol] *= other.constant constant = self.constant * other.constant @@ -202,7 +204,6 @@ class Expression: def __str__(self): string = '' - symbols = sorted(self.symbols()) i = 0 for symbol in symbols: coefficient = self[symbol] @@ -247,7 +248,7 @@ class Expression: def __repr__(self): string = '{}({{'.format(self.__class__.__name__) - for i, (symbol, coefficient) in enumerate(self.coefficients): + for i, (symbol, coefficient) in enumerate(self.coefficients()): if i != 0: string += ', ' string += '{!r}: {!r}'.format(symbol, coefficient) @@ -269,30 +270,30 @@ class Expression: def __hash__(self): return hash((self._coefficients, self._constant)) - def _canonify(self): + def _toint(self): lcm = functools.reduce(lambda a, b: a*b // gcd(a, b), [value.denominator for value in self.values()]) return self * lcm @_polymorphic_method def _eq(self, other): - return Polyhedron(equalities=[(self - other)._canonify()]) + return Polyhedron(equalities=[(self - other)._toint()]) @_polymorphic_method def __le__(self, other): - return Polyhedron(inequalities=[(other - self)._canonify()]) + return Polyhedron(inequalities=[(other - self)._toint()]) @_polymorphic_method def __lt__(self, other): - return Polyhedron(inequalities=[(other - self)._canonify() - 1]) + return Polyhedron(inequalities=[(other - self)._toint() - 1]) @_polymorphic_method def __ge__(self, other): - return Polyhedron(inequalities=[(self - other)._canonify()]) + return Polyhedron(inequalities=[(self - other)._toint()]) @_polymorphic_method def __gt__(self, other): - return Polyhedron(inequalities=[(self - other)._canonify() - 1]) + return Polyhedron(inequalities=[(self - other)._toint() - 1]) def constant(numerator=0, denominator=None): @@ -352,6 +353,7 @@ class Polyhedron: raise TypeError('non-integer constraint: ' '{} == 0'.format(constraint)) self._equalities.append(constraint) + self._equalities = tuple(self._equalities) self._inequalities = [] if inequalities is not None: for constraint in inequalities: @@ -360,46 +362,36 @@ class Polyhedron: raise TypeError('non-integer constraint: ' '{} <= 0'.format(constraint)) self._inequalities.append(constraint) + self._inequalities = tuple(self._inequalities) + self._constraints = self._equalities + self._inequalities + self._symbols = set() + for constraint in self._constraints: + self.symbols.update(constraint.symbols) + self._symbols = tuple(sorted(self._symbols)) return self @property def equalities(self): - yield from self._equalities + return self._equalities @property def inequalities(self): - yield from self._inequalities + return self._inequalities @property - def constant(self): - return self._constant - - def isconstant(self): - return len(self._coefficients) == 0 - - def isempty(self): - return bool(libisl.isl_basic_set_is_empty(self._bset)) - def constraints(self): - yield from self.equalities - yield from self.inequalities + return self._constraints + @property def symbols(self): - s = set() - for constraint in self.constraints(): - s.update(constraint.symbols()) - return sorted(s) + return self._symbols @property def dimension(self): - return len(self.symbols()) + return len(self.symbols) def __bool__(self): - # return false if the polyhedron is empty, true otherwise - if self._equalities or self._inequalities: - return False - else: - return True + return not self.is_empty() def __contains__(self, value): # is the value in the polyhedron? @@ -408,11 +400,12 @@ class Polyhedron: def __eq__(self, other): raise NotImplementedError - def is_empty(self): - return + def isempty(self): + bset = self._to_isl() + return bool(libisl.isl_basic_set_is_empty(bset)) def isuniverse(self): - return self == universe + raise NotImplementedError def isdisjoint(self, other): # return true if the polyhedron has no elements in common with other @@ -429,11 +422,6 @@ class Polyhedron: def issuperset(self, other): # test whether every element in other is in the polyhedron - for value in other: - if value == self.constraints(): - return True - else: - return False raise NotImplementedError def __ge__(self, other): @@ -492,14 +480,14 @@ class Polyhedron: raise NotImplementedError def _symbolunion(self, *others): - symbols = set(self.symbols()) + symbols = set(self.symbols) for other in others: - symbols.update(other.symbols()) + symbols.update(other.symbols) return sorted(symbols) def _to_isl(self, symbols=None): if symbols is None: - symbols = self.symbols() + symbols = self.symbols num_coefficients = len(symbols) space = libisl.isl_space_set_alloc(_main_ctx, 0, num_coefficients) bset = libisl.isl_basic_set_universe(libisl.isl_space_copy(space)) @@ -509,7 +497,7 @@ class Polyhedron: '''if there are equalities/inequalities, take each constant and coefficient and add as a constraint to the basic set''' if list(self.equalities): #check if any equalities exist for eq in self.equalities: - coeff_eq = dict(eq.coefficients) + coeff_eq = dict(eq.coefficients()) if eq.constant: value = eq.constant ceq = libisl.isl_constraint_set_constant_si(ceq, value) @@ -520,7 +508,7 @@ class Polyhedron: bset = libisl.isl_basic_set_add_constraint(bset, ceq) if list(self.inequalities): #check if any inequalities exist for ineq in self.inequalities: - coeff_in = dict(ineq.coefficients) + coeff_in = dict(ineq.coefficients()) if ineq.constant: value = ineq.constant cin = libisl.isl_constraint_set_constant_si(cin, value) @@ -532,26 +520,34 @@ class Polyhedron: bset = isl.BasicSet(bset) return bset - def from_isl(self, bset): + @classmethod + def _from_isl(cls, bset): '''takes basic set in isl form and puts back into python version of polyhedron isl example code gives isl form as: "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}") our printer is giving form as: b'{ [i0] : 1 = 0 }' ''' + raise NotImplementedError + equalities = ... + inequalities = ... + return cls(equalities, inequalities) #bset = self - if self._equalities: - constraints = libisl.isl_basic_set_equalities_matrix(bset, 3) - elif self._inequalities: - constraints = libisl.isl_basic_set_inequalities_matrix(bset, 3) - print(constraints) - return constraints + # if self._equalities: + # constraints = libisl.isl_basic_set_equalities_matrix(bset, 3) + # elif self._inequalities: + # constraints = libisl.isl_basic_set_inequalities_matrix(bset, 3) + # print(constraints) + # return constraints empty = None #eq(0,1) universe = None #Polyhedron() + if __name__ == '__main__': ex1 = Expression(coefficients={'a': 1, 'x': 2}, constant=2) ex2 = Expression(coefficients={'a': 3 , 'b': 2}, constant=3) p = Polyhedron(inequalities=[ex1, ex2]) bs = p._to_isl() print(bs) + print('empty ?', p.isempty()) + print('empty ?', eq(0, 1).isempty())