X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/77d9e641db24dc1edb6d0e2b91b58d395761616f..960f0c252361dfd696359f803aae40a9b13b14a6:/pypol/polyhedra.py?ds=sidebyside diff --git a/pypol/polyhedra.py b/pypol/polyhedra.py index f8d413e..9bfc64b 100644 --- a/pypol/polyhedra.py +++ b/pypol/polyhedra.py @@ -1,3 +1,20 @@ +# Copyright 2014 MINES ParisTech +# +# This file is part of Linpy. +# +# Linpy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Linpy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Linpy. If not, see . + import functools import math import numbers @@ -56,14 +73,23 @@ class Polyhedron(Domain): @property def equalities(self): + """ + Return a list of the equalities in a set. + """ return self._equalities @property def inequalities(self): + """ + Return a list of the inequalities in a set. + """ return self._inequalities @property def constraints(self): + """ + Return ta list of the constraints of a set. + """ return self._constraints @property @@ -72,13 +98,13 @@ class Polyhedron(Domain): def disjoint(self): """ - Return this set as disjoint. + Return a set as disjoint. """ return self def isuniverse(self): """ - Return true if this set is the Universe set. + Return true if a set is the Universe set. """ islbset = self._toislbasicset(self.equalities, self.inequalities, self.symbols) @@ -88,7 +114,7 @@ class Polyhedron(Domain): def aspolyhedron(self): """ - Return polyhedral hull of this set. + Return polyhedral hull of a set. """ return self @@ -106,18 +132,43 @@ class Polyhedron(Domain): return True def subs(self, symbol, expression=None): + """ + Subsitute the given value into an expression and return the resulting + expression. + """ equalities = [equality.subs(symbol, expression) for equality in self.equalities] inequalities = [inequality.subs(symbol, expression) for inequality in self.inequalities] return Polyhedron(equalities, inequalities) + def _asinequalities(self): + inequalities = list(self.equalities) + inequalities.extend([-expression for expression in self.equalities]) + inequalities.extend(self.inequalities) + return inequalities + + def widen(self, other): + if not isinstance(other, Polyhedron): + raise ValueError('argument must be a Polyhedron instance') + inequalities1 = self._asinequalities() + inequalities2 = other._asinequalities() + inequalities = [] + for inequality1 in inequalities1: + if other <= Polyhedron(inequalities=[inequality1]): + inequalities.append(inequality1) + for inequality2 in inequalities2: + for i in range(len(inequalities1)): + inequalities3 = inequalities1[:i] + inequalities[i + 1:] + inequalities3.append(inequality2) + polyhedron3 = Polyhedron(inequalities=inequalities3) + if self == polyhedron3: + inequalities.append(inequality2) + break + return Polyhedron(inequalities=inequalities) + @classmethod def _fromislbasicset(cls, islbset, symbols): - if libisl.isl_basic_set_is_empty(islbset): - return Empty - if libisl.isl_basic_set_is_universe(islbset): - return Universe islconstraints = islhelper.isl_basic_set_constraints(islbset) equalities = [] inequalities = [] @@ -198,6 +249,7 @@ class Polyhedron(Domain): else: return 'And({})'.format(', '.join(strings)) + def _repr_latex_(self): strings = [] for equality in self.equalities: @@ -208,12 +260,18 @@ class Polyhedron(Domain): @classmethod def fromsympy(cls, expr): + """ + Convert a sympy object to an expression. + """ domain = Domain.fromsympy(expr) if not isinstance(domain, Polyhedron): raise ValueError('non-polyhedral expression: {!r}'.format(expr)) return domain def tosympy(self): + """ + Return an expression as a sympy object. + """ import sympy constraints = [] for equality in self.equalities: @@ -236,6 +294,11 @@ class EmptyType(Polyhedron): self._dimension = 0 return self + def widen(self, other): + if not isinstance(other, Polyhedron): + raise ValueError('argument must be a Polyhedron instance') + return other + def __repr__(self): return 'Empty' @@ -288,41 +351,41 @@ def _polymorphic(func): @_polymorphic def Lt(left, right): """ - Return true if the first set is less than the second. + Assert first set is less than the second set. """ return Polyhedron([], [right - left - 1]) @_polymorphic def Le(left, right): """ - Return true the first set is less than or equal to the second. + Assert first set is less than or equal to the second set. """ return Polyhedron([], [right - left]) @_polymorphic def Eq(left, right): """ - Return true if the sets are equal. + Assert first set is equal to the second set. """ return Polyhedron([left - right], []) @_polymorphic def Ne(left, right): """ - Return true if the sets are NOT equal. + Assert first set is not equal to the second set. """ return ~Eq(left, right) @_polymorphic def Gt(left, right): """ - Return true if the first set is greater than the second set. + Assert first set is greater than the second set. """ return Polyhedron([], [left - right - 1]) @_polymorphic def Ge(left, right): """ - Return true if the first set is greater than or equal the second set. + Assert first set is greater than or equal to the second set. """ return Polyhedron([], [left - right])