-"""
-note: for islpy
-isl format: basic set: ("{[x, y] : x >= 0 and x < 5 and y >= 0 and y < x+4 }")
-"""
-
import ctypes, ctypes.util
-import math
-import numbers
-import operator
-import re
-import functools
-
-
-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
+from . import _isl
-class Context:
- __slots__ = ('_ic')
+__all__ = [
+ 'Context',
+ 'BasicSet',
+]
- def __init__(self):
- self._ic = libisl.isl_ctx_alloc()
-
- @property
- def _as_parameter_(self):
- return self._ic
-
- #def __del__(self):
- # libisl.isl_ctx_free(self)
- 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)
+libisl = ctypes.CDLL(ctypes.util.find_library('isl'))
- _RE_NONFINITE = re.compile(
- r'^\s*(?P<sign>[-+])?((?P<inf>Inf(inity)?)|(?P<nan>NaN))\s*$',
- re.IGNORECASE)
+libisl.isl_printer_get_str.restype = ctypes.c_char_p
+libisl.isl_dim_set = _isl.dim_set
- _RE_FRACTION = re.compile(r'^(?P<num>[-+]?\d+)(/(?P<den>\d+))?$')
- __slots__ = ('context', '_iv', '_numerator', '_denominator')
+class IslObject:
- 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)
- print('in isl')
- return self
+ __slots__ = (
+ '_ptr',
+ )
+ def __init__(self, ptr):
+ self._ptr = ptr
@property
def _as_parameter_(self):
- return self._iv
-
- def symbols(self):
- s = set()
- for constraint in self.constraints():
- s.update(constraint.symbols)
- yield from sorted(s)
-
- 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
+ return self._ptr
- @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))
- @_polymorphic_method
- def __lt__(self, other):
- return bool(libisl.isl_val_lt(self, other))
+class Context(IslObject):
- @_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))
+ def __init__(self):
+ ptr = libisl.isl_ctx_alloc()
+ super().__init__(ptr)
- @_polymorphic_method
- def __ge__(self, other):
- return bool(libisl.isl_val_ge(self, other))
+ #comment out so does not delete itself after being created
+ #def __del__(self):
+ # libisl.isl_ctx_free(self)
- @_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))
+ if not isinstance(other, Context):
+ return False
+ return self._ptr == other._ptr
- 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'
+ 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).decode()
+ return string
- def __repr__(self):
- return '{}({!r})'.format(self.__class__.__name__, str(self))
+ def __del__(self):
+ libisl.isl_basic_set_free(self)
+
+ def constraints(self):
+ return _isl.basic_set_constraints(self._ptr)
+
+ def _fromisl(self, cls, symbols):
+ constraints = self.constraints()
+ equalities = []
+ inequalities = []
+ co = []
+ eq_string = ""
+ in_string = ""
+ string = ""
+ for constraint in constraints:
+ ls = libisl.isl_basic_set_get_local_space(self)
+ ctx = libisl.isl_local_space_get_ctx(ls)
+ p = libisl.isl_printer_to_str(ctx)
+ if libisl.isl_constraint_is_equality(constraint): #check if equality
+ constant = libisl.isl_constraint_get_constant_val(constraint)
+ const = libisl.isl_printer_print_val(p, constant)
+ const = libisl.isl_printer_get_str(const).decode()
+ const = int(const)
+ libisl.isl_printer_free(p)
+ for symbol in symbols:
+ p = libisl.isl_printer_to_str(ctx)
+ dim = symbols.index(symbol)
+ coefficient = libisl.isl_constraint_get_coefficient_val(constraint, libisl.isl_dim_set, dim)
+ coeff = libisl.isl_printer_print_val(p, coefficient)
+ coeff = libisl.isl_printer_get_str(coeff).decode()
+ coeff = int(coeff)
+ if coeff!=0:
+ co.append('{}{}'.format(coeff, symbols[dim]))
+ for value in co:
+ string += '{}+'.format(value)
+ equalities.append('{}{}==0'.format(string, const))
+ co = []
+ string = ''
+ libisl.isl_printer_free(p)
+ else: #same for inequality
+ constant = libisl.isl_constraint_get_constant_val(constraint)
+ const = libisl.isl_printer_print_val(p, constant)
+ const = libisl.isl_printer_get_str(const).decode()
+ const = int(const)
+ libisl.isl_printer_free(p)
+ for symbol in symbols:
+ p = libisl.isl_printer_to_str(ctx)
+ dim = symbols.index(symbol)
+ coefficient = libisl.isl_constraint_get_coefficient_val(constraint, libisl.isl_dim_set, dim)
+ coeff = libisl.isl_printer_print_val(p, coefficient)
+ coeff = libisl.isl_printer_get_str(coeff).decode()
+ coeff = int(coeff)
+ if coeff!=0:
+ co.append('{}{}'.format(coeff, symbols[dim]))
+ for value in co:
+ string += '{} + '.format(value)
+ inequalities.append('{}{} <= 0'.format(string, const))
+ co = []
+ string = ""
+ libisl.isl_printer_free(p)
+
+ for equations in equalities:
+ eq_string += ' {}'.format(equations)
+ eq_strings = eq_string.split()
+ print(eq_strings)
+
+ for equations in inequalities:
+ in_string += ', {}'.format(equations)
+ print(in_string)
+ if eq_string and in_string:
+ final = '{}, {}'.format(eq_string, in_string)
+ elif eq_string != '':
+ final = '{}'.format(eq_strings)
+ elif in_string != '' :
+ final = '{}'.format(in_string)
+
+
+ return ('{}({!r})'.format(cls.__name__,final))
+