From: Vivien Maisonneuve Date: Tue, 2 Dec 2014 06:08:23 +0000 (+0100) Subject: PEP 8 X-Git-Tag: 1.0.3~2 X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/commitdiff_plain/d585b06ccf67b2837519f4b48c6800dcdb924d9d?ds=inline PEP 8 --- diff --git a/examples/bac2014.py b/examples/bac2014.py index cc02126..34ddd81 100755 --- a/examples/bac2014.py +++ b/examples/bac2014.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -# This example is inspired from a math question in the French baccalauréat 2014, +# This example is inspired from a math question in the French baccalauréat 2014 # consisting in computing the intersection of a plane with a line. -from linpy import * +from linpy import Eq, symbols x, y, z = symbols('x y z') plane = Eq(x, y) & Eq(z, 6 - 2*x) diff --git a/examples/menger.py b/examples/menger.py index dcba976..8d258b1 100755 --- a/examples/menger.py +++ b/examples/menger.py @@ -20,21 +20,22 @@ import matplotlib.pyplot as plt from math import ceil from matplotlib import pylab -from mpl_toolkits.mplot3d import Axes3D -from linpy import * +from linpy import Le, Polyhedron, symbols x, y, z = symbols('x y z') _x, _y, _z = x.asdummy(), y.asdummy(), z.asdummy() + def translate(domain, *, dx=0, dy=0, dz=0): domain &= Polyhedron([x - _x + dx, y - _y + dy, z - _z + dz]) domain = domain.project([x, y, z]) domain = domain.subs({_x: x, _y: y, _z: z}) return domain + def _menger(domain, size): result = domain result |= translate(domain, dx=0, dy=size, dz=0) @@ -58,6 +59,7 @@ def _menger(domain, size): result |= translate(domain, dx=2*size, dy=2*size, dz=2*size) return result + def menger(domain, count=1, cut=False): size = 1 for i in range(count): @@ -70,9 +72,11 @@ def menger(domain, count=1, cut=False): if __name__ == '__main__': parser = argparse.ArgumentParser( description='Compute a Menger sponge.') - parser.add_argument('-n', '--iterations', type=int, default=2, + parser.add_argument( + '-n', '--iterations', type=int, default=2, help='number of iterations (default: 2)') - parser.add_argument('-c', '--cut', action='store_true', default=False, + parser.add_argument( + '-c', '--cut', action='store_true', default=False, help='cut the sponge') args = parser.parse_args() cube = Le(0, x) & Le(x, 1) & Le(0, y) & Le(y, 1) & Le(0, z) & Le(z, 1) diff --git a/examples/nsad2010.py b/examples/nsad2010.py index 4b73eef..3de2ebd 100755 --- a/examples/nsad2010.py +++ b/examples/nsad2010.py @@ -8,7 +8,7 @@ # to compute the transitive closure of an affine transformer. A refined version # of this algorithm is implemented in PIPS. -from linpy import * +from linpy import Dummy, Eq, Ge, Polyhedron, symbols class Transformer: @@ -28,7 +28,8 @@ class Transformer: delta_symbols = [symbol.asdummy() for symbol in self.range_symbols] k = Dummy('k') polyhedron = self.polyhedron - for x, xprime, dx in zip(self.range_symbols, self.domain_symbols, delta_symbols): + for x, xprime, dx in zip( + self.range_symbols, self.domain_symbols, delta_symbols): polyhedron &= Eq(dx, xprime - x) polyhedron = polyhedron.project(self.symbols) equalities, inequalities = [], [] @@ -40,7 +41,8 @@ class Transformer: inequalities.append(inequality) polyhedron = Polyhedron(equalities, inequalities) & Ge(k, 0) polyhedron = polyhedron.project([k]) - for x, xprime, dx in zip(self.range_symbols, self.domain_symbols, delta_symbols): + for x, xprime, dx in zip( + self.range_symbols, self.domain_symbols, delta_symbols): polyhedron &= Eq(dx, xprime - x) polyhedron = polyhedron.project(delta_symbols) return Transformer(polyhedron, self.range_symbols, self.domain_symbols) @@ -49,6 +51,6 @@ class Transformer: if __name__ == '__main__': i0, i, j0, j = symbols('i0 i j0 j') transformer = Transformer(Eq(i, i0 + 2) & Eq(j, j0 + 1), - [i0, j0], [i, j]) + [i0, j0], [i, j]) print('T =', transformer.polyhedron) print('T* =', transformer.star().polyhedron) diff --git a/examples/plots.py b/examples/plots.py index d172835..4b0f16e 100755 --- a/examples/plots.py +++ b/examples/plots.py @@ -6,30 +6,31 @@ import matplotlib.pyplot as plt from matplotlib import pylab -from mpl_toolkits.mplot3d import Axes3D -from linpy import * +from linpy import Ge, Le, symbols x, y, z = symbols('x y z') diam = Ge(y, x - 1) & Le(y, x + 1) & Ge(y, -x - 1) & Le(y, -x + 1) -cham = Le(0, x, 3) & Le(0, y, 3) & Le(0, z, 3) & \ - Le(z - 2, x, z + 2) & Le(1 - z, x, 5 - z) & \ - Le(z - 2, y, z + 2) & Le(1 - z, y, 5 - z) & \ - Le(y - 2, x, y + 2) & Le(1 - y, x, 5 - y) - -rhom = cham & \ - Le(x + y + z, 7) & Ge(-2, -x - y - z) & \ - Le(-1, x + y - z, 4) & Le(-1, x - y + z, 4) & Le(-1, -x + y + z, 4) - -cubo = Le(0, x, 5) & Le(0, y, 5) & Le(0, z, 5) & \ - Le(x -4, y, x + 4) & Le(-x + 1, y, -x + 9) & \ - Le(y -4, z, y + 4) & Le(-y + 1, z, -y + 9) & \ - Le(z -4, x, z + 4) & Le(-z + 1, x, -z + 9) & \ - Le(3, x + y + z, 12) & Le(-2, x - y + z, 7) & \ - Le(-2, -x + y + z, 7) & Le(-2, x + y - z, 7) +cham = ( + Le(0, x, 3) & Le(0, y, 3) & Le(0, z, 3) & + Le(z - 2, x, z + 2) & Le(1 - z, x, 5 - z) & + Le(z - 2, y, z + 2) & Le(1 - z, y, 5 - z) & + Le(y - 2, x, y + 2) & Le(1 - y, x, 5 - y)) + +rhom = cham & ( + Le(x + y + z, 7) & Ge(-2, -x - y - z) & + Le(-1, x + y - z, 4) & Le(-1, x - y + z, 4) & Le(-1, -x + y + z, 4)) + +cubo = ( + Le(0, x, 5) & Le(0, y, 5) & Le(0, z, 5) & + Le(x - 4, y, x + 4) & Le(-x + 1, y, -x + 9) & + Le(y - 4, z, y + 4) & Le(-y + 1, z, -y + 9) & + Le(z - 4, x, z + 4) & Le(-z + 1, x, -z + 9) & + Le(3, x + y + z, 12) & Le(-2, x - y + z, 7) & + Le(-2, -x + y + z, 7) & Le(-2, x + y - z, 7)) if __name__ == '__main__': diff --git a/examples/tesseract.py b/examples/tesseract.py index 383d7bd..d692e37 100755 --- a/examples/tesseract.py +++ b/examples/tesseract.py @@ -5,19 +5,22 @@ # the cube consists of 6 square faces, the hypersurface of the tesseract # consists of 8 cubical cells. -from linpy import * +from linpy import Le, symbols x, y, z, t = symbols('x y z t') tesseract = Le(0, x, 1) & Le(0, y, 1) & Le(0, z, 1) & Le(0, t, 1) + def faces(polyhedron): for points in polyhedron.faces(): face = points[0].aspolyhedron() - face = face.convex_union(*[point.aspolyhedron() for point in points[1:]]) + face = face.convex_union(*[point.aspolyhedron() + for point in points[1:]]) yield face + if __name__ == '__main__': print('Faces of tesseract\n\n {}\n\nare:\n'.format(tesseract)) for face in faces(tesseract): diff --git a/linpy/__init__.py b/linpy/__init__.py index bbe5693..d524fbc 100644 --- a/linpy/__init__.py +++ b/linpy/__init__.py @@ -19,17 +19,34 @@ A polyhedral library based on isl """ -from .geometry import GeometricObject, Point, Vector -from .linexprs import LinExpr, Symbol, symbols, Dummy, Rational -from .polyhedra import Polyhedron, Lt, Le, Eq, Ne, Ge, Gt, Ne, Empty, Universe -from .domains import Domain, And, Or, Not from ._version import __version__ +from .domains import And, Domain, Not, Or +from .geometry import GeometricObject, Point, Vector +from .linexprs import Dummy, LinExpr, Rational, Symbol, symbols +from .polyhedra import Empty, Eq, Ge, Gt, Le, Lt, Ne, Polyhedron, Universe __all__ = [ - 'LinExpr', 'Symbol', 'symbols', 'Dummy', 'Rational', - 'GeometricObject', 'Point', 'Vector', - 'Polyhedron', 'Lt', 'Le', 'Eq', 'Ne', 'Ge', 'Gt', 'Empty', 'Universe', - 'Domain', 'And', 'Or', 'Not', '__version__', + 'And', + 'Domain', + 'Dummy', + 'Empty', + 'Eq', + 'Ge', + 'GeometricObject', + 'Gt', + 'Le', + 'LinExpr', + 'Lt', + 'Ne', + 'Not', + 'Or', + 'Point', + 'Polyhedron', + 'Rational', + 'Symbol', + 'symbols', + 'Universe', + 'Vector', ] diff --git a/linpy/domains.py b/linpy/domains.py index f26b2fc..7f4fa65 100644 --- a/linpy/domains.py +++ b/linpy/domains.py @@ -23,14 +23,16 @@ import math from fractions import Fraction from . import islhelper -from .islhelper import mainctx, libisl -from .linexprs import LinExpr, Symbol from .geometry import GeometricObject, Point, Vector +from .islhelper import libisl +from .linexprs import LinExpr, Symbol __all__ = [ + 'And', 'Domain', - 'And', 'Or', 'Not', + 'Not', + 'Or', ] @@ -84,7 +86,7 @@ class Domain(GeometricObject): return argument.aspolyhedron() else: raise TypeError('argument must be a string ' - 'or a GeometricObject instance') + 'or a GeometricObject instance') else: for polyhedron in polyhedra: if not isinstance(polyhedron, Polyhedron): @@ -289,11 +291,12 @@ class Domain(GeometricObject): if symbol in symbols: n += 1 elif n > 0: - islset = libisl.isl_set_project_out(islset, - libisl.isl_dim_set, index + 1, n) + islset = libisl.isl_set_project_out( + islset, libisl.isl_dim_set, index + 1, n) n = 0 if n > 0: - islset = libisl.isl_set_project_out(islset, libisl.isl_dim_set, 0, n) + islset = libisl.isl_set_project_out( + islset, libisl.isl_dim_set, 0, n) symbols = [symbol for symbol in self.symbols if symbol not in symbols] return Domain._fromislset(islset, symbols) @@ -309,8 +312,8 @@ class Domain(GeometricObject): raise ValueError('domain must be non-empty') point = {} for index, symbol in enumerate(self.symbols): - coordinate = libisl.isl_point_get_coordinate_val(islpoint, - libisl.isl_dim_set, index) + coordinate = libisl.isl_point_get_coordinate_val( + islpoint, libisl.isl_dim_set, index) coordinate = islhelper.isl_val_to_int(coordinate) point[symbol] = coordinate libisl.isl_point_free(islpoint) @@ -402,12 +405,11 @@ class Domain(GeometricObject): Return the vertices of the domain, as a list of rational instances of Point. """ - from .polyhedra import Polyhedron if not self.isbounded(): raise ValueError('domain must be bounded') islbset = self._toislbasicset(self.equalities, self.inequalities, - self.symbols) - vertices = libisl.isl_basic_set_compute_vertices(islbset); + self.symbols) + vertices = libisl.isl_basic_set_compute_vertices(islbset) vertices = islhelper.isl_vertices_vertices(vertices) points = [] for vertex in vertices: @@ -416,11 +418,13 @@ class Domain(GeometricObject): if self._RE_COORDINATE is None: constraints = islhelper.isl_basic_set_constraints(expression) for constraint in constraints: - constant = libisl.isl_constraint_get_constant_val(constraint) + constant = libisl.isl_constraint_get_constant_val( + constraint) constant = islhelper.isl_val_to_int(constant) for index, symbol in enumerate(self.symbols): - coefficient = libisl.isl_constraint_get_coefficient_val(constraint, - libisl.isl_dim_set, index) + coefficient = \ + libisl.isl_constraint_get_coefficient_val( + constraint, libisl.isl_dim_set, index) coefficient = islhelper.isl_val_to_int(coefficient) if coefficient != 0: coordinate = -Fraction(constant, coefficient) @@ -431,7 +435,8 @@ class Domain(GeometricObject): for symbol, match in zip(self.symbols, matches): numerator = int(match.group('num')) denominator = match.group('den') - denominator = 1 if denominator is None else int(denominator) + denominator = \ + 1 if denominator is None else int(denominator) coordinate = Fraction(numerator, denominator) coordinates.append((symbol, coordinate)) points.append(Point(coordinates)) @@ -440,20 +445,19 @@ class Domain(GeometricObject): def points(self): """ Return the integer points of a bounded domain, as a list of integer - instances of Point. If the domain is not bounded, a ValueError exception - is raised. + instances of Point. If the domain is not bounded, a ValueError + exception is raised. """ if not self.isbounded(): raise ValueError('domain must be bounded') - from .polyhedra import Universe, Eq islset = self._toislset(self.polyhedra, self.symbols) islpoints = islhelper.isl_set_points(islset) points = [] for islpoint in islpoints: coordinates = {} for index, symbol in enumerate(self.symbols): - coordinate = libisl.isl_point_get_coordinate_val(islpoint, - libisl.isl_dim_set, index) + coordinate = libisl.isl_point_get_coordinate_val( + islpoint, libisl.isl_dim_set, index) coordinate = islhelper.isl_val_to_int(coordinate) coordinates[symbol] = coordinate points.append(Point(coordinates)) @@ -610,7 +614,7 @@ class Domain(GeometricObject): similar to LinExpr.subs(). """ polyhedra = [polyhedron.subs(symbol, expression) - for polyhedron in self.polyhedra] + for polyhedron in self.polyhedra] return Domain(*polyhedra) @classmethod @@ -638,12 +642,12 @@ class Domain(GeometricObject): @classmethod def _toislset(cls, polyhedra, symbols): polyhedron = polyhedra[0] - islbset = polyhedron._toislbasicset(polyhedron.equalities, - polyhedron.inequalities, symbols) + islbset = polyhedron._toislbasicset( + polyhedron.equalities, polyhedron.inequalities, symbols) islset1 = libisl.isl_set_from_basic_set(islbset) for polyhedron in polyhedra[1:]: - islbset = polyhedron._toislbasicset(polyhedron.equalities, - polyhedron.inequalities, symbols) + islbset = polyhedron._toislbasicset( + polyhedron.equalities, polyhedron.inequalities, symbols) islset2 = libisl.isl_set_from_basic_set(islbset) islset1 = libisl.isl_set_union(islset1, islset2) return islset1 @@ -754,7 +758,7 @@ class Domain(GeometricObject): Convert the domain to a SymPy expression. """ import sympy - polyhedra = [polyhedron.tosympy() for polyhedron in polyhedra] + polyhedra = [polyhedron.tosympy() for polyhedron in self.polyhedra] return sympy.Or(*polyhedra) @@ -768,6 +772,7 @@ def And(*domains): else: return domains[0].intersection(*domains[1:]) + def Or(*domains): """ Create the union domain of the domains given in arguments. @@ -778,6 +783,7 @@ def Or(*domains): else: return domains[0].union(*domains[1:]) + def Not(domain): """ Create the complementary domain of the domain given in argument. diff --git a/linpy/geometry.py b/linpy/geometry.py index 0b05493..80f7771 100644 --- a/linpy/geometry.py +++ b/linpy/geometry.py @@ -19,8 +19,8 @@ import math import numbers import operator -from abc import ABC, abstractproperty, abstractmethod -from collections import OrderedDict, Mapping +from abc import ABC, abstractmethod, abstractproperty +from collections import Mapping, OrderedDict from .linexprs import Symbol @@ -79,8 +79,8 @@ class Coordinates: def __new__(cls, coordinates): """ - Create a coordinate system from a dictionary or a sequence that maps the - symbols to their coordinates. Coordinates must be rational numbers. + Create a coordinate system from a dictionary or a sequence that maps + the symbols to their coordinates. Coordinates must be rational numbers. """ if isinstance(coordinates, Mapping): coordinates = coordinates.items() @@ -155,7 +155,7 @@ class Coordinates: def __repr__(self): string = ', '.join(['{!r}: {!r}'.format(symbol, coordinate) - for symbol, coordinate in self.coordinates()]) + for symbol, coordinate in self.coordinates()]) return '{}({{{}}})'.format(self.__class__.__name__, string) def _map(self, func): @@ -202,8 +202,8 @@ class Point(Coordinates, GeometricObject): def __sub__(self, other): """ If other is a point, substract it from self and return the resulting - vector. If other is a vector, translate the point by the opposite vector - and returns the resulting point. + vector. If other is a vector, translate the point by the opposite + vector and returns the resulting point. """ coordinates = [] if isinstance(other, Point): @@ -231,8 +231,8 @@ class Vector(Coordinates): def __new__(cls, initial, terminal=None): """ - Create a vector from a dictionary or a sequence that maps the symbols to - their coordinates, or as the displacement between two points. + Create a vector from a dictionary or a sequence that maps the symbols + to their coordinates, or as the displacement between two points. """ if not isinstance(initial, Point): initial = Point(initial) @@ -341,9 +341,6 @@ class Vector(Coordinates): result += coordinate1 * coordinate2 return result - def __hash__(self): - return super().__hash__() - def norm(self): """ Return the norm of the vector. @@ -361,7 +358,7 @@ class Vector(Coordinates): def asunit(self): """ - Return the normalized vector, i.e. the vector of same direction but with - norm 1. + Return the normalized vector, i.e. the vector of same direction but + with norm 1. """ return self / self.norm() diff --git a/linpy/islhelper.py b/linpy/islhelper.py index b0dffe7..d87eaa3 100644 --- a/linpy/islhelper.py +++ b/linpy/islhelper.py @@ -15,23 +15,27 @@ # You should have received a copy of the GNU General Public License # along with LinPy. If not, see . -import ctypes, ctypes.util +import ctypes +import ctypes.util import re from . import _islhelper -from ._islhelper import * +from ._islhelper import (isl_basic_set_constraints, isl_set_basic_sets, + isl_set_points, isl_vertices_vertices) __all__ = [ - 'libisl', - 'isl_version', - 'mainctx', - 'isl_val_to_int', - 'isl_basic_set_to_str', 'isl_basic_set_constraints', - 'isl_set_to_str', 'isl_set_basic_sets', + 'isl_basic_set_constraints', + 'isl_basic_set_to_str', + 'isl_multi_aff_to_str', + 'isl_set_basic_sets', 'isl_set_points', + 'isl_set_to_str', + 'isl_val_to_int', + 'isl_version', 'isl_vertices_vertices', - 'isl_multi_aff_to_str', + 'libisl', + 'mainctx', ] @@ -48,24 +52,28 @@ mainctx = libisl.isl_ctx_alloc() libisl.isl_printer_get_str.restype = ctypes.c_char_p + def isl_val_to_int(islval): islpr = libisl.isl_printer_to_str(mainctx) islpr = libisl.isl_printer_print_val(islpr, islval) string = libisl.isl_printer_get_str(islpr).decode() return int(string) + def isl_basic_set_to_str(islbset): islpr = libisl.isl_printer_to_str(mainctx) islpr = libisl.isl_printer_print_basic_set(islpr, islbset) string = libisl.isl_printer_get_str(islpr).decode() return string + def isl_set_to_str(islset): islpr = libisl.isl_printer_to_str(mainctx) islpr = libisl.isl_printer_print_set(islpr, islset) string = libisl.isl_printer_get_str(islpr).decode() return string + def isl_multi_aff_to_str(islmaff): islpr = libisl.isl_printer_to_str(mainctx) islpr = libisl.isl_printer_print_multi_aff(islpr, islmaff) diff --git a/linpy/linexprs.py b/linpy/linexprs.py index f361218..ccfbbfa 100644 --- a/linpy/linexprs.py +++ b/linpy/linexprs.py @@ -20,14 +20,16 @@ import functools import numbers import re -from collections import OrderedDict, defaultdict, Mapping +from collections import defaultdict, Mapping, OrderedDict from fractions import Fraction, gcd __all__ = [ + 'Dummy', 'LinExpr', - 'Symbol', 'Dummy', 'symbols', 'Rational', + 'Symbol', + 'symbols', ] @@ -59,8 +61,8 @@ class LinExpr: def __new__(cls, coefficients=None, constant=0): """ Return a linear expression from a dictionary or a sequence, that maps - symbols to their coefficients, and a constant term. The coefficients and - the constant term must be rational numbers. + symbols to their coefficients, and a constant term. The coefficients + and the constant term must be rational numbers. For example, the linear expression x + 2*y + 1 can be constructed using one of the following instructions: @@ -79,9 +81,9 @@ class LinExpr: >>> LinExpr('x + 2y + 1') A linear expression with a single symbol of coefficient 1 and no - constant term is automatically subclassed as a Symbol instance. A linear - expression with no symbol, only a constant term, is automatically - subclassed as a Rational instance. + constant term is automatically subclassed as a Symbol instance. A + linear expression with no symbol, only a constant term, is + automatically subclassed as a Rational instance. """ if isinstance(coefficients, str): if constant != 0: @@ -105,8 +107,9 @@ class LinExpr: symbol, coefficient = coefficients[0] if coefficient == 1: return symbol - coefficients = [(symbol, Fraction(coefficient)) - for symbol, coefficient in coefficients if coefficient != 0] + coefficients = [(symbol_, Fraction(coefficient_)) + for symbol_, coefficient_ in coefficients + if coefficient_ != 0] coefficients.sort(key=lambda item: item[0].sortkey()) self = object().__new__(cls) self._coefficients = OrderedDict(coefficients) @@ -223,7 +226,8 @@ class LinExpr: Return the product of the linear expression by a rational. """ if isinstance(other, numbers.Rational): - coefficients = ((symbol, coefficient * other) + coefficients = ( + (symbol, coefficient * other) for symbol, coefficient in self._coefficients.items()) constant = self._constant * other return LinExpr(coefficients, constant) @@ -236,7 +240,8 @@ class LinExpr: Return the quotient of the linear expression by a rational. """ if isinstance(other, numbers.Rational): - coefficients = ((symbol, coefficient / other) + coefficients = ( + (symbol, coefficient / other) for symbol, coefficient in self._coefficients.items()) constant = self._constant / other return LinExpr(coefficients, constant) @@ -280,7 +285,7 @@ class LinExpr: make all values integer. """ lcd = functools.reduce(lambda a, b: a*b // gcd(a, b), - [value.denominator for value in self.values()]) + [value.denominator for value in self.values()]) return self * lcd def subs(self, symbol, expression=None): @@ -405,10 +410,12 @@ class LinExpr: symbol = Symbol(symbol.name) coefficients.append((symbol, coefficient)) else: - raise TypeError('non-linear expression: {!r}'.format(expression)) + raise TypeError('non-linear expression: {!r}'.format( + expression)) expression = LinExpr(coefficients, constant) if not isinstance(expression, cls): - raise TypeError('cannot convert to a {} instance'.format(cls.__name__)) + raise TypeError('cannot convert to a {} instance'.format( + cls.__name__)) return expression def tosympy(self): diff --git a/linpy/polyhedra.py b/linpy/polyhedra.py index 820b014..9e740a4 100644 --- a/linpy/polyhedra.py +++ b/linpy/polyhedra.py @@ -16,29 +16,34 @@ # along with LinPy. If not, see . import functools -import math import numbers from . import islhelper -from .islhelper import mainctx, libisl +from .domains import Domain from .geometry import GeometricObject, Point +from .islhelper import libisl, mainctx from .linexprs import LinExpr, Rational -from .domains import Domain __all__ = [ + 'Empty', + 'Eq', + 'Ge', + 'Gt', + 'Le', + 'Lt', + 'Ne', 'Polyhedron', - 'Lt', 'Le', 'Eq', 'Ne', 'Ge', 'Gt', - 'Empty', 'Universe', + 'Universe', ] class Polyhedron(Domain): """ A convex polyhedron (or simply "polyhedron") is the space defined by a - system of linear equalities and inequalities. This space can be unbounded. A - Z-polyhedron (simply called "polyhedron" in LinPy) is the set of integer + system of linear equalities and inequalities. This space can be unbounded. + A Z-polyhedron (simply called "polyhedron" in LinPy) is the set of integer points in a convex polyhedron. """ @@ -51,9 +56,9 @@ class Polyhedron(Domain): def __new__(cls, equalities=None, inequalities=None): """ - Return a polyhedron from two sequences of linear expressions: equalities - is a list of expressions equal to 0, and inequalities is a list of - expressions greater or equal to 0. For example, the polyhedron + Return a polyhedron from two sequences of linear expressions: + equalities is a list of expressions equal to 0, and inequalities is a + list of expressions greater or equal to 0. For example, the polyhedron 0 <= x <= 2, 0 <= y <= 2 can be constructed with: >>> x, y = symbols('x y') @@ -62,8 +67,9 @@ class Polyhedron(Domain): And(0 <= x, x <= 2, 0 <= y, y <= 2) It may be easier to use comparison operators LinExpr.__lt__(), - LinExpr.__le__(), LinExpr.__ge__(), LinExpr.__gt__(), or functions Lt(), - Le(), Eq(), Ge() and Gt(), using one of the following instructions: + LinExpr.__le__(), LinExpr.__ge__(), LinExpr.__gt__(), or + functions Lt(), Le(), Eq(), Ge() and Gt(), using one of the following + instructions: >>> x, y = symbols('x y') >>> square1 = (0 <= x) & (x <= 2) & (0 <= y) & (y <= 2) @@ -74,9 +80,9 @@ class Polyhedron(Domain): >>> square1 = Polyhedron('0 <= x <= 2, 0 <= y <= 2') Finally, a polyhedron can be constructed from a GeometricObject - instance, calling the GeometricObject.aspolyedron() method. This way, it - is possible to compute the polyhedral hull of a Domain instance, i.e., - the convex hull of two polyhedra: + instance, calling the GeometricObject.aspolyedron() method. This way, + it is possible to compute the polyhedral hull of a Domain instance, + i.e., the convex hull of two polyhedra: >>> square1 = Polyhedron('0 <= x <= 2, 0 <= y <= 2') >>> square2 = Polyhedron('1 <= x <= 3, 1 <= y <= 3') @@ -100,7 +106,7 @@ class Polyhedron(Domain): sc_equalities.append(Rational(equality).scaleint()) else: raise TypeError('equalities must be linear expressions ' - 'or rational numbers') + 'or rational numbers') sc_inequalities = [] if inequalities is not None: for inequality in inequalities: @@ -110,7 +116,7 @@ class Polyhedron(Domain): sc_inequalities.append(Rational(inequality).scaleint()) else: raise TypeError('inequalities must be linear expressions ' - 'or rational numbers') + 'or rational numbers') symbols = cls._xsymbols(sc_equalities + sc_inequalities) islbset = cls._toislbasicset(sc_equalities, sc_inequalities, symbols) return cls._fromislbasicset(islbset, symbols) @@ -148,7 +154,7 @@ class Polyhedron(Domain): def isuniverse(self): islbset = self._toislbasicset(self.equalities, self.inequalities, - self.symbols) + self.symbols) universe = bool(libisl.isl_basic_set_is_universe(islbset)) libisl.isl_basic_set_free(islbset) return universe @@ -180,9 +186,9 @@ class Polyhedron(Domain): def subs(self, symbol, expression=None): equalities = [equality.subs(symbol, expression) - for equality in self.equalities] + for equality in self.equalities] inequalities = [inequality.subs(symbol, expression) - for inequality in self.inequalities] + for inequality in self.inequalities] return Polyhedron(equalities, inequalities) def asinequalities(self): @@ -234,8 +240,8 @@ class Polyhedron(Domain): constant = islhelper.isl_val_to_int(constant) coefficients = {} for index, symbol in enumerate(symbols): - coefficient = libisl.isl_constraint_get_coefficient_val(islconstraint, - libisl.isl_dim_set, index) + coefficient = libisl.isl_constraint_get_coefficient_val( + islconstraint, libisl.isl_dim_set, index) coefficient = islhelper.isl_val_to_int(coefficient) if coefficient != 0: coefficients[symbol] = coefficient @@ -260,26 +266,28 @@ class Polyhedron(Domain): islbset = libisl.isl_basic_set_universe(libisl.isl_space_copy(islsp)) islls = libisl.isl_local_space_from_space(islsp) for equality in equalities: - isleq = libisl.isl_equality_alloc(libisl.isl_local_space_copy(islls)) + isleq = libisl.isl_equality_alloc( + libisl.isl_local_space_copy(islls)) for symbol, coefficient in equality.coefficients(): islval = str(coefficient).encode() islval = libisl.isl_val_read_from_str(mainctx, islval) index = indices[symbol] - isleq = libisl.isl_constraint_set_coefficient_val(isleq, - libisl.isl_dim_set, index, islval) + isleq = libisl.isl_constraint_set_coefficient_val( + isleq, libisl.isl_dim_set, index, islval) if equality.constant != 0: islval = str(equality.constant).encode() islval = libisl.isl_val_read_from_str(mainctx, islval) isleq = libisl.isl_constraint_set_constant_val(isleq, islval) islbset = libisl.isl_basic_set_add_constraint(islbset, isleq) for inequality in inequalities: - islin = libisl.isl_inequality_alloc(libisl.isl_local_space_copy(islls)) + islin = libisl.isl_inequality_alloc( + libisl.isl_local_space_copy(islls)) for symbol, coefficient in inequality.coefficients(): islval = str(coefficient).encode() islval = libisl.isl_val_read_from_str(mainctx, islval) index = indices[symbol] - islin = libisl.isl_constraint_set_coefficient_val(islin, - libisl.isl_dim_set, index, islval) + islin = libisl.isl_constraint_set_coefficient_val( + islin, libisl.isl_dim_set, index, islval) if inequality.constant != 0: islval = str(inequality.constant).encode() islval = libisl.isl_val_read_from_str(mainctx, islval) @@ -333,7 +341,8 @@ class Polyhedron(Domain): def fromsympy(cls, expression): domain = Domain.fromsympy(expression) if not isinstance(domain, Polyhedron): - raise ValueError('non-polyhedral expression: {!r}'.format(expression)) + raise ValueError('non-polyhedral expression: {!r}'.format( + expression)) return domain def tosympy(self): @@ -400,10 +409,11 @@ def _pseudoconstructor(func): expression = Rational(expression) else: raise TypeError('arguments must be rational numbers ' - 'or linear expressions') + 'or linear expressions') return func(*expressions) return wrapper + @_pseudoconstructor def Lt(*expressions): """ @@ -414,6 +424,7 @@ def Lt(*expressions): inequalities.append(right - left - 1) return Polyhedron([], inequalities) + @_pseudoconstructor def Le(*expressions): """ @@ -424,6 +435,7 @@ def Le(*expressions): inequalities.append(right - left) return Polyhedron([], inequalities) + @_pseudoconstructor def Eq(*expressions): """ @@ -434,6 +446,7 @@ def Eq(*expressions): equalities.append(left - right) return Polyhedron(equalities, []) + @_pseudoconstructor def Ne(*expressions): """ @@ -445,6 +458,7 @@ def Ne(*expressions): domain &= ~Eq(left, right) return domain + @_pseudoconstructor def Ge(*expressions): """ @@ -455,6 +469,7 @@ def Ge(*expressions): inequalities.append(left - right) return Polyhedron([], inequalities) + @_pseudoconstructor def Gt(*expressions): """ diff --git a/linpy/tests/libhelper.py b/linpy/tests/libhelper.py index 7cefbb2..be14067 100644 --- a/linpy/tests/libhelper.py +++ b/linpy/tests/libhelper.py @@ -16,11 +16,12 @@ # along with LinPy. If not, see . import functools +import importlib import unittest try: - import sympy + importlib.import_module('sympy') def requires_sympy(func): @functools.wraps(func) diff --git a/linpy/tests/test_domains.py b/linpy/tests/test_domains.py index 0955a09..2d30b8b 100644 --- a/linpy/tests/test_domains.py +++ b/linpy/tests/test_domains.py @@ -17,9 +17,9 @@ import unittest -from ..domains import * +from ..domains import And, Or from ..linexprs import Symbol, symbols -from ..polyhedra import * +from ..polyhedra import Empty, Eq, Ge, Polyhedron class TestDomain(unittest.TestCase): @@ -27,23 +27,33 @@ class TestDomain(unittest.TestCase): def setUp(self): x, y = symbols('x y') self.square1 = Polyhedron(inequalities=[x, 2 - x, y, 2 - y]) - self.square2 = Polyhedron(inequalities=[x - 1, 3 - x , y - 1, 3 - y]) #correct representation + self.square2 = Polyhedron(inequalities=[x - 1, 3 - x, y - 1, 3 - y]) self.square3 = Polyhedron(inequalities=[x, 3 - x, y, 3 - y]) self.square4 = Polyhedron(inequalities=[x - 1, 2 - x, y - 1, 2 - y]) - self.square5 = Polyhedron(inequalities=[x - 3, 6 - x, y - 3, 6 -y]) - self.square6 = Polyhedron(equalities=[3 - y], inequalities=[x - 1, 3 - x, y - 1]) + self.square5 = Polyhedron(inequalities=[x - 3, 6 - x, y - 3, 6 - y]) + self.square6 = Polyhedron(equalities=[3 - y], + inequalities=[x - 1, 3 - x, y - 1]) self.unbound_poly = Polyhedron(inequalities=[x, 3 - x, y]) self.universe = Polyhedron([]) self.empty = Empty self.disjoint = And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)) - self.complement = Or(Ge(-x - 1, 0), Ge(x - 3, 0), And(Ge(x, 0), Ge(-x + 2, 0), Ge(-y - 1, 0)), And(Ge(x, 0), Ge(-x + 2, 0), Ge(y - 3, 0))) + self.complement = Or(Ge(-x - 1, 0), Ge(x - 3, 0), + And(Ge(x, 0), Ge(-x + 2, 0), Ge(-y - 1, 0)), + And(Ge(x, 0), Ge(-x + 2, 0), Ge(y - 3, 0))) self.hull = And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)) self.dropped = And(Ge(y, 0), Ge(-y + 2, 0)) - self.intersection = And(Ge(x - 1, 0), Ge(-x + 2, 0), Ge(y - 1, 0), Ge(-y + 2, 0)) - self.union = Or(And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)), And(Ge(x - 1, 0), Ge(-x + 3, 0), Ge(y - 1, 0), Ge(-y + 3, 0))) - self.sum1 = Or(And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)), And(Ge(x - 1, 0), Ge(-x + 3, 0), Ge(y - 1, 0), Ge(-y + 3, 0))) - self.sum2 =And(Ge(x, 0), Ge(y, 0), Ge(-y + 3, 0), Ge(-x + 3, 0), Ge(x - y + 2, 0), Ge(-x + y + 2, 0)) - self.difference1 = Or(And(Eq(x - 3, 0), Ge(y - 1, 0), Ge(-y + 3, 0)), And(Eq(y - 3, 0), Ge(x - 1, 0), Ge(-x + 2, 0))) + self.intersection = And(Ge(x - 1, 0), Ge(-x + 2, 0), Ge(y - 1, 0), + Ge(-y + 2, 0)) + self.union = Or(And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)), + And(Ge(x - 1, 0), Ge(-x + 3, 0), Ge(y - 1, 0), + Ge(-y + 3, 0))) + self.sum1 = Or(And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)), + And(Ge(x - 1, 0), Ge(-x + 3, 0), Ge(y - 1, 0), + Ge(-y + 3, 0))) + self.sum2 = And(Ge(x, 0), Ge(y, 0), Ge(-y + 3, 0), Ge(-x + 3, 0), + Ge(x - y + 2, 0), Ge(-x + y + 2, 0)) + self.difference1 = Or(And(Eq(x - 3, 0), Ge(y - 1, 0), Ge(-y + 3, 0)), + And(Eq(y - 3, 0), Ge(x - 1, 0), Ge(-x + 2, 0))) self.difference2 = And(Ge(x + y - 4, 0), Ge(-x + 3, 0), Ge(-y + 3, 0)) self.lexmin = And(Eq(y, 0), Eq(x, 0)) self.lexmax = And(Eq(y - 2, 0), Eq(x - 2, 0)) @@ -116,13 +126,15 @@ class TestDomain(unittest.TestCase): self.assertEqual(self.empty.project([]), Empty) def test_sample(self): - self.assertEqual(self.square6.sample(), {Symbol('x'): 1, Symbol('y'): 3}) + self.assertEqual(self.square6.sample(), + {Symbol('x'): 1, Symbol('y'): 3}) with self.assertRaises(ValueError): self.empty.sample() self.assertEqual(self.universe.sample(), {}) def test_intersection(self): - self.assertEqual(self.square1.intersection(self.square2), self.intersection) + self.assertEqual(self.square1.intersection(self.square2), + self.intersection) def test_and(self): self.assertEqual(self.square2 & self.square1, self.intersection) @@ -151,7 +163,8 @@ class TestDomain(unittest.TestCase): def test_difference(self): self.assertEqual(self.square2 - self.square1, self.difference1) - self.assertEqual(Polyhedron(self.square2 - self.square1), self.difference2) + self.assertEqual(Polyhedron(self.square2 - self.square1), + self.difference2) self.assertEqual(self.square2 - self.square2, Empty) self.assertEqual(self.universe - self.universe, Empty) diff --git a/linpy/tests/test_geometry.py b/linpy/tests/test_geometry.py index 0f3884c..faa20df 100644 --- a/linpy/tests/test_geometry.py +++ b/linpy/tests/test_geometry.py @@ -18,7 +18,7 @@ import math import unittest -from ..geometry import * +from ..geometry import Point, Vector from ..linexprs import Symbol from ..polyhedra import Eq @@ -37,7 +37,7 @@ class TestPoint(unittest.TestCase): def test_new(self): self.assertEqual(Point({self.x: 10, self.y: 5, self.z: 1}), self.pt1) self.assertEqual(Point([(self.x, 10), (self.y, 5), (self.z, 1)]), - self.pt1) + self.pt1) def test_symbols(self): self.assertTupleEqual(self.pt1.symbols, (self.x, self.y, self.z)) @@ -57,11 +57,10 @@ class TestPoint(unittest.TestCase): def test_coordinates(self): self.assertListEqual(list(self.pt1.coordinates()), - [(self.x, 10), (self.y, 5), (self.z, 1)]) + [(self.x, 10), (self.y, 5), (self.z, 1)]) def test_values(self): - self.assertListEqual(list(self.pt1.values()), - [10, 5, 1]) + self.assertListEqual(list(self.pt1.values()), [10, 5, 1]) def test_isorigin(self): self.assertFalse(self.pt1.isorigin()) @@ -73,15 +72,15 @@ class TestPoint(unittest.TestCase): def test_add(self): self.assertEqual(self.pt1 + self.vec1, - Point({self.x: 30, self.y: 35, self.z: 41})) + Point({self.x: 30, self.y: 35, self.z: 41})) with self.assertRaises(TypeError): self.pt1 + self.pt2 def test_sub(self): self.assertEqual(self.pt1 - self.pt2, - Vector({self.x: -5, self.y: -35, self.z: -59})) + Vector({self.x: -5, self.y: -35, self.z: -59})) self.assertEqual(self.pt1 - self.vec1, - Point({self.x: -10, self.y: -25, self.z: -39})) + Point({self.x: -10, self.y: -25, self.z: -39})) def test_eq(self): self.assertEqual(self.pt1, self.pt1) @@ -90,7 +89,7 @@ class TestPoint(unittest.TestCase): def test_aspolyhedron(self): self.assertEqual(self.pt1.aspolyhedron(), - Eq(self.x, 10) & Eq(self.y, 5) & Eq(self.z, 1)) + Eq(self.x, 10) & Eq(self.y, 5) & Eq(self.z, 1)) def test_repr(self): self.assertEqual(repr(self.pt1), 'Point({x: 10, y: 5, z: 1})') @@ -108,19 +107,25 @@ class TestVector(unittest.TestCase): self.vec2 = Vector({self.x: 45, self.y: 70, self.z: 80}) def test_add(self): - self.assertEqual(self.vec1 + self.pt1, Point({self.x: 30, self.y: 35, self.z: 41})) - self.assertEqual(self.vec1 + self.vec2, Vector({self.x: 65, self.y: 100, self.z: 120})) + self.assertEqual(self.vec1 + self.pt1, + Point({self.x: 30, self.y: 35, self.z: 41})) + self.assertEqual(self.vec1 + self.vec2, + Vector({self.x: 65, self.y: 100, self.z: 120})) def test_angle(self): self.assertEqual(math.degrees(self.vec1.angle(self.vec1)), 0) - self.assertAlmostEqual(math.degrees(self.vec1.angle(self.vec2)), 4.15129, places=5) - self.assertAlmostEqual(math.degrees(self.vec2.angle(self.vec1)), 4.15129, places=5) + self.assertAlmostEqual(math.degrees(self.vec1.angle(self.vec2)), + 4.15129, places=5) + self.assertAlmostEqual(math.degrees(self.vec2.angle(self.vec1)), + 4.15129, places=5) def test_cross(self): - self.assertEqual(self.vec1.cross(self.vec2), Vector({self.x: -400, self.y: 200, self.z: 50})) + self.assertEqual(self.vec1.cross(self.vec2), + Vector({self.x: -400, self.y: 200, self.z: 50})) def test_div(self): - self.assertEqual(self.vec1 / 10, Vector({self.x: 2, self.y: 3, self.z: 4})) + self.assertEqual(self.vec1 / 10, + Vector({self.x: 2, self.y: 3, self.z: 4})) def test_dot(self): self.assertEqual(self.vec1.dot(self.vec2), 6200) @@ -130,11 +135,14 @@ class TestVector(unittest.TestCase): self.assertNotEqual(self.vec1, self.vec2) def test_mul(self): - self.assertEqual(75 * self.vec1, Vector({self.x: 1500, self.y: 2250, self.z: 3000})) - self.assertEqual(self.vec1 * 75, Vector({self.x: 1500, self.y: 2250, self.z: 3000})) + self.assertEqual(75 * self.vec1, + Vector({self.x: 1500, self.y: 2250, self.z: 3000})) + self.assertEqual(self.vec1 * 75, + Vector({self.x: 1500, self.y: 2250, self.z: 3000})) def test_neg(self): - self.assertEqual(-self.vec1, Vector({self.x: -20, self.y: -30, self.z: -40})) + self.assertEqual(-self.vec1, + Vector({self.x: -20, self.y: -30, self.z: -40})) def test_norm(self): self.assertAlmostEqual(self.vec1.norm(), 53.85165, places=5) @@ -149,5 +157,7 @@ class TestVector(unittest.TestCase): self.assertAlmostEqual(unit[self.z], 0.74278, 5) def test_sub(self): - self.assertEqual(self.vec1 - self.pt1, Point({self.x: 10, self.y: 25, self.z: 39})) - self.assertEqual(self.vec1 - self.vec2, Vector({self.x: -25, self.y: -40, self.z: -40})) + self.assertEqual(self.vec1 - self.pt1, + Point({self.x: 10, self.y: 25, self.z: 39})) + self.assertEqual(self.vec1 - self.vec2, + Vector({self.x: -25, self.y: -40, self.z: -40})) diff --git a/linpy/tests/test_linexprs.py b/linpy/tests/test_linexprs.py index f189260..0c50e6c 100644 --- a/linpy/tests/test_linexprs.py +++ b/linpy/tests/test_linexprs.py @@ -15,12 +15,11 @@ # You should have received a copy of the GNU General Public License # along with LinPy. If not, see . -import functools import unittest from fractions import Fraction -from ..linexprs import * +from ..linexprs import Dummy, LinExpr, Rational, Symbol, symbols from .libhelper import requires_sympy @@ -76,7 +75,8 @@ class TestLinExpr(unittest.TestCase): self.expr[self.expr] def test_coefficients(self): - self.assertListEqual(list(self.expr.coefficients()), [(self.x, 1), (self.y, -2)]) + self.assertListEqual(list(self.expr.coefficients()), + [(self.x, 1), (self.y, -2)]) def test_constant(self): self.assertEqual(self.x.constant, 0) @@ -151,7 +151,7 @@ class TestLinExpr(unittest.TestCase): def test_scaleint(self): self.assertEqual((self.x + self.y/2 + self.z/3).scaleint(), - 6*self.x + 3*self.y + 2*self.z) + 6*self.x + 3*self.y + 2*self.z) def test_subs(self): self.assertEqual(self.x.subs(self.x, 3), 3) @@ -161,9 +161,12 @@ class TestLinExpr(unittest.TestCase): self.assertEqual(self.x.subs(self.y, 3), self.x) self.assertEqual(self.pi.subs(self.x, 3), self.pi) self.assertEqual(self.expr.subs(self.x, -3), -2 * self.y) - self.assertEqual(self.expr.subs([(self.x, self.y), (self.y, self.x)]), -2*self.x + self.y + 3) - self.assertEqual(self.expr.subs({self.x: self.z, self.y: self.z}), 3 - self.z) - self.assertEqual(self.expr.subs({self.x: self.z, self.y: self.z}), 3 - self.z) + self.assertEqual(self.expr.subs([(self.x, self.y), (self.y, self.x)]), + -2*self.x + self.y + 3) + self.assertEqual(self.expr.subs({self.x: self.z, self.y: self.z}), + 3 - self.z) + self.assertEqual(self.expr.subs({self.x: self.z, self.y: self.z}), + 3 - self.z) with self.assertRaises(TypeError): self.x.subs('x', 3) with self.assertRaises(TypeError): diff --git a/linpy/tests/test_polyhedra.py b/linpy/tests/test_polyhedra.py index d0ebe57..60e1b33 100644 --- a/linpy/tests/test_polyhedra.py +++ b/linpy/tests/test_polyhedra.py @@ -15,11 +15,10 @@ # You should have received a copy of the GNU General Public License # along with LinPy. If not, see . -import functools import unittest from ..linexprs import symbols -from ..polyhedra import * +from ..polyhedra import Empty, Polyhedron, Universe from .libhelper import requires_sympy @@ -37,11 +36,13 @@ class TestPolyhedron(unittest.TestCase): def test_repr(self): self.assertEqual(repr(self.square), - "And(0 <= x, x <= 1, 0 <= y, y <= 1)") + 'And(0 <= x, x <= 1, 0 <= y, y <= 1)') def test_fromstring(self): - self.assertEqual(Polyhedron.fromstring('{x >= 0, -x + 1 >= 0, ' - 'y >= 0, -y + 1 >= 0}'), self.square) + self.assertEqual( + Polyhedron.fromstring( + '{x >= 0, -x + 1 >= 0, y >= 0, -y + 1 >= 0}'), + self.square) def test_isempty(self): self.assertFalse(self.square.isempty()) @@ -53,14 +54,17 @@ class TestPolyhedron(unittest.TestCase): def test_fromsympy(self): import sympy sp_x, sp_y = sympy.symbols('x y') - self.assertEqual(Polyhedron.fromsympy((sp_x >= 0) & (sp_x <= 1) & - (sp_y >= 0) & (sp_y <= 1)), self.square) + self.assertEqual( + Polyhedron.fromsympy( + (sp_x >= 0) & (sp_x <= 1) & (sp_y >= 0) & (sp_y <= 1)), + self.square) @requires_sympy def test_tosympy(self): import sympy sp_x, sp_y = sympy.symbols('x y') - self.assertEqual(self.square.tosympy(), + self.assertEqual( + self.square.tosympy(), sympy.And(-sp_x + 1 >= 0, -sp_y + 1 >= 0, sp_x >= 0, sp_y >= 0)) diff --git a/setup.py b/setup.py index 72569e4..f3f62c1 100755 --- a/setup.py +++ b/setup.py @@ -17,14 +17,15 @@ # You should have received a copy of the GNU General Public License # along with LinPy. If not, see . -from distutils.core import setup, Extension +from distutils.core import Extension, setup with open('linpy/_version.py') as file: + __version__ = None exec(file.read()) with open('README.rst') as file: - long_description=file.read() + long_description = file.read() setup( name='LinPy', @@ -37,7 +38,7 @@ setup( packages=['linpy'], ext_modules=[ Extension('linpy._islhelper', - sources=['linpy/_islhelper.c'], - libraries=['isl']) + sources=['linpy/_islhelper.c'], + libraries=['isl']) ] )