X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/56ab422e3bbc5a6a072f5b2a5be9d88d1017f03f..0efaf62e3354a0663031bc16b53d9d8b597f50d0:/pypol/linear.py diff --git a/pypol/linear.py b/pypol/linear.py index 621a157..8a61744 100644 --- a/pypol/linear.py +++ b/pypol/linear.py @@ -1,5 +1,7 @@ +import ast import functools import numbers +import re from fractions import Fraction, gcd @@ -86,9 +88,40 @@ class Expression: self._dimension = len(self._symbols) return self + @classmethod + def _fromast(cls, node): + if isinstance(node, ast.Module): + assert len(node.body) == 1 + return cls._fromast(node.body[0]) + elif isinstance(node, ast.Expr): + return cls._fromast(node.value) + elif isinstance(node, ast.Name): + return Symbol(node.id) + elif isinstance(node, ast.Num): + return Constant(node.n) + elif isinstance(node, ast.UnaryOp): + if isinstance(node.op, ast.USub): + return -cls._fromast(node.operand) + elif isinstance(node, ast.BinOp): + left = cls._fromast(node.left) + right = cls._fromast(node.right) + if isinstance(node.op, ast.Add): + return left + right + elif isinstance(node.op, ast.Sub): + return left - right + elif isinstance(node.op, ast.Mult): + return left * right + elif isinstance(node.op, ast.Div): + return left / right + raise SyntaxError('invalid syntax') + @classmethod def fromstring(cls, string): - raise NotImplementedError + string = re.sub(r'(\d+|\))\s*([^\W\d_]\w*|\()', + lambda m: '{}*{}'.format(m.group(1), m.group(2)), + string) + tree = ast.parse(string, 'eval') + return cls._fromast(tree) @property def symbols(self): @@ -524,7 +557,6 @@ class Polyhedron: difference = libisl.isl_set_subtract(bset, other) return difference - def __sub__(self, other): return self.difference(other) @@ -556,42 +588,39 @@ class Polyhedron: def _toisl(self, symbols=None): if symbols is None: symbols = self.symbols - num_coefficients = len(symbols) - space = libisl.isl_space_set_alloc(_main_ctx, 0, num_coefficients) + dimension = len(symbols) + space = libisl.isl_space_set_alloc(_main_ctx, 0, dimension) bset = libisl.isl_basic_set_universe(libisl.isl_space_copy(space)) ls = libisl.isl_local_space_from_space(space) - #if there are equalities/inequalities, take each constant and coefficient and add as a constraint to the basic set - for eq in self.equalities: + for equality in self.equalities: ceq = libisl.isl_equality_alloc(libisl.isl_local_space_copy(ls)) - coeff_eq = dict(eq.coefficients()) - if eq.constant: - value = str(eq.constant).encode() - val = libisl.isl_val_read_from_str(_main_ctx, value) + for symbol, coefficient in equality.coefficients(): + val = str(coefficient).encode() + val = libisl.isl_val_read_from_str(_main_ctx, val) + dim = symbols.index(symbol) + ceq = libisl.isl_constraint_set_coefficient_val(ceq, libisl.isl_dim_set, dim, val) + if equality.constant != 0: + val = str(equality.constant).encode() + val = libisl.isl_val_read_from_str(_main_ctx, val) ceq = libisl.isl_constraint_set_constant_val(ceq, val) - for eq in coeff_eq: - number = str(coeff_eq.get(eq)).encode() - num = libisl.isl_val_read_from_str(_main_ctx, number) - iden = symbols.index(eq) - ceq = libisl.isl_constraint_set_coefficient_val(ceq, libisl.isl_dim_set, iden, num) #use 3 for type isl_dim_set bset = libisl.isl_basic_set_add_constraint(bset, ceq) - for ineq in self.inequalities: + for inequality in self.inequalities: cin = libisl.isl_inequality_alloc(libisl.isl_local_space_copy(ls)) - coeff_in = dict(ineq.coefficients()) - if ineq.constant: - value = str(ineq.constant).encode() - val = libisl.isl_val_read_from_str(_main_ctx, value) + for symbol, coefficient in inequality.coefficients(): + val = str(coefficient).encode() + val = libisl.isl_val_read_from_str(_main_ctx, val) + dim = symbols.index(symbol) + cin = libisl.isl_constraint_set_coefficient_val(cin, libisl.isl_dim_set, dim, val) + if inequality.constant != 0: + val = str(ineq.constant).encode() + val = libisl.isl_val_read_from_str(_main_ctx, val) cin = libisl.isl_constraint_set_constant_val(cin, val) - for ineq in coeff_in: - number = str(coeff_in.get(ineq)).encode() - num = libisl.isl_val_read_from_str(_main_ctx, number) - iden = symbols.index(ineq) - cin = libisl.isl_constraint_set_coefficient_val(cin, libisl.isl_dim_set, iden, num) #use 3 for type isl_dim_set bset = libisl.isl_basic_set_add_constraint(bset, cin) bset = isl.BasicSet(bset) return bset @classmethod - def _fromisl(cls, bset): + def _fromisl(cls, bset, symbols): raise NotImplementedError equalities = ... inequalities = ... @@ -606,8 +635,9 @@ Empty = eq(0,1) Universe = Polyhedron() if __name__ == '__main__': - ex1 = Expression(coefficients={'a': 6, 'b': 6}, constant= 3) #this is the expression that does not work (even without adding values) - ex2 = Expression(coefficients={'x': 4, 'y': 2}, constant= 3) - p = Polyhedron(equalities=[ex2]) - p2 = Polyhedron(equalities=[ex2]) - print(p._toisl()) # checking is values works for toisl + e1 = Expression('2a + 2b + 1') + p1 = Polyhedron(equalities=[e1]) # empty + e2 = Expression('3x + 2y + 3') + p2 = Polyhedron(equalities=[e2]) # not empty + print(p1._toisl()) + print(p2._toisl())