Implement IslObjects, delete Value
authorVivien Maisonneuve <v.maisonneuve@gmail.com>
Wed, 18 Jun 2014 16:09:03 +0000 (18:09 +0200)
committerVivien Maisonneuve <v.maisonneuve@gmail.com>
Wed, 18 Jun 2014 16:09:03 +0000 (18:09 +0200)
pypol/isl.py
pypol/linear.py

index bbc8d13..0513358 100644 (file)
@@ -10,38 +10,28 @@ import numbers
 import operator
 import re
 
-from decimal import Decimal
-from fractions import Fraction
-from functools import wraps
-
 
 libisl = ctypes.CDLL(ctypes.util.find_library('isl'))
 
 libisl.isl_printer_get_str.restype = ctypes.c_char_p
 
 
-def _polymorphic_method(func):
-    @functools.wraps(func)
-    def wrapper(self, other):
-        if isinstance(other, Value):
-            return func(self, other)
-        if isinstance(other, numbers.Rational):
-            other = Value(self.context, other)
-            return func(self, other)
-        raise TypeError('operand should be a Value or a Rational')
-    return wrapper
-
-
-class Context:
+class IslObject:
 
-    __slots__ = ('_ic')
+    __slots__ = ('_ptr')
 
-    def __init__(self):
-        self._ic = libisl.isl_ctx_alloc()
+    def __init__(self, ptr):
+        self._ptr = ptr
 
     @property
     def _as_parameter_(self):
-        return self._ic
+        return self._ptr
+
+
+class Context(IslObject):
+
+    def __init__(self):
+        self._ptr = libisl.isl_ctx_alloc()
 
     #comment out so does not delete itself after being created
     #def __del__(self):
@@ -50,225 +40,16 @@ class Context:
     def __eq__(self, other):
         if not isinstance(other, Context):
             return False
-        return self._ic == other._ic
-
-
-class Value:
-
-    class _ptr(int):
-        def __new__(cls, iv):
-            return super().__new__(cls, iv)
-        def __repr__(self):
-            return '{}({})'.format(self.__class__.__name__, self)
-
-    _RE_NONFINITE = re.compile(
-            r'^\s*(?P<sign>[-+])?((?P<inf>Inf(inity)?)|(?P<nan>NaN))\s*$',
-            re.IGNORECASE)
-
-    _RE_FRACTION = re.compile(r'^(?P<num>[-+]?\d+)(/(?P<den>\d+))?$')
-
-    __slots__ = ('context', '_iv', '_numerator', '_denominator')
-
-    def __new__(cls, context, numerator=0, denominator=None):
-        self = super().__new__(cls)
-        if not isinstance(context, Context):
-            raise TypeError('first argument should be a context')
-        self.context = context
-        if isinstance(numerator, cls._ptr):
-            assert denominator is None
-            self._iv = numerator
-            if libisl.isl_val_is_rat(self):
-                # retrieve numerator and denominator as strings to avoid integer
-                # overflows
-                ip = libisl.isl_printer_to_str(self.context)
-                ip = libisl.isl_printer_print_val(ip, self)
-                string = libisl.isl_printer_get_str(ip).decode()
-                libisl.isl_printer_free(ip)
-                m = self._RE_FRACTION.match(string)
-                assert m is not None
-                self._numerator = int(m.group('num'))
-                self._denominator = int(m.group('den')) if m.group('den') else 1
-            else:
-                self._numerator = None
-                self._denominator = None
-            return self
-        if isinstance(numerator, str) and denominator is None:
-            m = self._RE_NONFINITE.match(numerator)
-            if m is not None:
-                self._numerator = None
-                self._denominator = None
-                if m.group('inf'):
-                    if m.group('sign') == '-':
-                        self._iv = libisl.isl_val_neginfty(context)
-                    else:
-                        self._iv = libisl.isl_val_infty(context)
-                else:
-                    assert m.group('nan')
-                    self._iv = libisl.isl_val_nan(context)
-                return self
-        try:
-            frac = Fraction(numerator, denominator)
-        except ValueError:
-            raise ValueError('invalid literal for {}: {!r}'.format(
-                    cls.__name__, numerator))
-        self._numerator = frac.numerator
-        self._denominator = frac.denominator
-        # values passed as strings to avoid integer overflows
-        if frac.denominator == 1:
-            numerator = str(frac.numerator).encode()
-            self._iv = libisl.isl_val_read_from_str(context, numerator)
-        else:
-            numerator = str(frac.numerator).encode()
-            numerator = libisl.isl_val_read_from_str(context, numerator)
-            denominator = str(frac.denominator).encode()
-            denominator = libisl.isl_val_read_from_str(context, denominator)
-            self._iv = libisl.isl_val_div(numerator, denominator)
-        return self
-
-    @property
-    def _as_parameter_(self):
-        return self._iv
-
-    def __del__(self):
-        libisl.isl_val_free(self)
-        self.context # prevents context from being GC'ed before the value
-
-    @property
-    def numerator(self):
-        if self._numerator is None:
-            raise ValueError('not a rational number')
-        return self._numerator
-
-    @property
-    def denominator(self):
-        if self._denominator is None:
-            raise ValueError('not a rational number')
-        return self._denominator
-
-    def __bool__(self):
-        return not bool(libisl.isl_val_is_zero(self))
+        return self._ptr == other._ptr
 
-    @_polymorphic_method
-    def __lt__(self, other):
-        return bool(libisl.isl_val_lt(self, other))
 
-    @_polymorphic_method
-    def __le__(self, other):
-        return bool(libisl.isl_val_le(self, other))
-
-    @_polymorphic_method
-    def __gt__(self, other):
-        return bool(libisl.isl_val_gt(self, other))
-
-    @_polymorphic_method
-    def __ge__(self, other):
-        return bool(libisl.isl_val_ge(self, other))
-
-    @_polymorphic_method
-    def __eq__(self, other):
-        return bool(libisl.isl_val_eq(self, other))
-
-    # __ne__ is not implemented, ISL semantics does not match Python's on
-    # nan != nan
-
-    def __abs__(self):
-        val = libisl.isl_val_copy(self)
-        val = libisl.isl_val_abs(val)
-        return self.__class__(self.context, self._ptr(val))
-
-    def __pos__(self):
-        return self
-
-    def __neg__(self):
-        val = libisl.isl_val_copy(self)
-        val = libisl.isl_val_neg(val)
-        return self.__class__(self.context, self._ptr(val))
-
-    def __floor__(self):
-        val = libisl.isl_val_copy(self)
-        val = libisl.isl_val_floor(val)
-        return self.__class__(self.context, self._ptr(val))
-
-    def __ceil__(self):
-        val = libisl.isl_val_copy(self)
-        val = libisl.isl_val_ceil(val)
-        return self.__class__(self.context, self._ptr(val))
-
-    def __trunc__(self):
-        val = libisl.isl_val_copy(self)
-        val = libisl.isl_val_trunc(val)
-        return self.__class__(self.context, self._ptr(val))
-
-    @_polymorphic_method
-    def __add__(self, other):
-        val1 = libisl.isl_val_copy(self)
-        val2 = libisl.isl_val_copy(other)
-        val = libisl.isl_val_add(val1, val2)
-        return self.__class__(self.context, self._ptr(val))
-
-    __radd__ = __add__
-
-    @_polymorphic_method
-    def __sub__(self, other):
-        val1 = libisl.isl_val_copy(self)
-        val2 = libisl.isl_val_copy(other)
-        val = libisl.isl_val_sub(val1, val2)
-        return self.__class__(self.context, self._ptr(val))
-
-    __rsub__ = __sub__
-
-    @_polymorphic_method
-    def __mul__(self, other):
-        val1 = libisl.isl_val_copy(self)
-        val2 = libisl.isl_val_copy(other)
-        val = libisl.isl_val_mul(val1, val2)
-        return self.__class__(self.context, self._ptr(val))
-
-    __rmul__ = __mul__
-
-    @_polymorphic_method
-    def __truediv__(self, other):
-        val1 = libisl.isl_val_copy(self)
-        val2 = libisl.isl_val_copy(other)
-        val = libisl.isl_val_div(val1, val2)
-        return self.__class__(self.context, self._ptr(val))
-
-    __rtruediv__ = __truediv__
-
-    def __float__(self):
-        if libisl.isl_val_is_rat(self):
-            return self.numerator / self.denominator
-        elif libisl.isl_val_is_infty(self):
-            return float('inf')
-        elif libisl.isl_val_is_neginfty(self):
-            return float('-inf')
-        else:
-            assert libisl.isl_val_is_nan(self)
-            return float('nan')
-
-    def is_finite(self):
-        return bool(libisl.isl_val_is_rat(self))
-
-    def is_infinite(self):
-        return bool(libisl.isl_val_is_infty(self) or
-                libisl.isl_val_is_neginfty(self))
-
-    def is_nan(self):
-        return bool(libisl.isl_val_is_nan(self))
+class BasicSet(IslObject):
 
     def __str__(self):
-        if libisl.isl_val_is_rat(self):
-            if self.denominator == 1:
-                return '{}'.format(self.numerator)
-            else:
-                return '{}/{}'.format(self.numerator, self.denominator)
-        elif libisl.isl_val_is_infty(self):
-            return 'Infinity'
-        elif libisl.isl_val_is_neginfty(self):
-            return '-Infinity'
-        else:
-            assert libisl.isl_val_is_nan(self)
-            return 'NaN'
-
-    def __repr__(self):
-        return '{}({!r})'.format(self.__class__.__name__, str(self))
+        ls = libisl.isl_basic_set_get_local_space(self)
+        ctx = libisl.isl_local_space_get_ctx(ls)
+        p = libisl.isl_printer_to_str(ctx)
+        p = libisl.isl_printer_print_basic_set(p, self)
+        string = libisl.isl_printer_get_str(p)
+        string = str(string.decode())
+        return string
index 331d3af..348294c 100644 (file)
@@ -5,7 +5,7 @@ import numbers
 from fractions import Fraction, gcd
 
 from . import isl, islhelper
-from .isl import libisl, Context
+from .isl import libisl, Context, BasicSet
 
 
 __all__ = [
@@ -357,12 +357,6 @@ class Polyhedron:
                         raise TypeError('non-integer constraint: '
                                 '{} <= 0'.format(constraint))
                 self._inequalities.append(constraint)
-        self._bset = self._to_isl()
-        #print(self._bset)
-        #put this here just to test from isl method
-        #from_isl = self.from_isl(self._bset)
-        #print(from_isl)
-        #rint(self)
         return self
 
     @property
@@ -533,11 +527,7 @@ class Polyhedron:
                     iden = symbols.index(ineq)
                     cin = libisl.isl_constraint_set_coefficient_si(cin, islhelper.isl_dim_set, iden, num)  #use 3 for type isl_dim_set
             bset = libisl.isl_basic_set_add_constraint(bset, cin)
-        ip = libisl.isl_printer_to_str(ctx) #create string printer
-        ip = libisl.isl_printer_print_basic_set(ip, bset) #print basic set to printer
-        string = libisl.isl_printer_get_str(ip)   #get string from printer
-        string = str(string.decode())
-        print(string)
+        bset = BasicSet(bset)
         return bset
 
     def from_isl(self, bset):
@@ -561,7 +551,5 @@ 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])
-    #p = eq(ex2, 0)# 2a+4 = 0, in fact 6a+3 = 0
-    #p.to_isl()
-
-#universe = Polyhedron()
+    bs = p._to_isl()
+    print(bs)