From 0efaf62e3354a0663031bc16b53d9d8b597f50d0 Mon Sep 17 00:00:00 2001 From: Vivien Maisonneuve Date: Thu, 19 Jun 2014 18:33:22 +0200 Subject: [PATCH] Implement Expression.fromstring --- pypol/linear.py | 41 +++++++++++++++++++++++++++++++++++++---- tests/test_linear.py | 1 - 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/pypol/linear.py b/pypol/linear.py index 3939c71..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): @@ -587,7 +620,7 @@ class Polyhedron: return bset @classmethod - def _fromisl(cls, bset): + def _fromisl(cls, bset, symbols): raise NotImplementedError equalities = ... inequalities = ... @@ -602,9 +635,9 @@ Empty = eq(0,1) Universe = Polyhedron() if __name__ == '__main__': - e1 = Expression(coefficients={'a': 2, 'b': 2}, constant= 1) + e1 = Expression('2a + 2b + 1') p1 = Polyhedron(equalities=[e1]) # empty - e2 = Expression(coefficients={'x': 3, 'y': 2}, constant= 3) + e2 = Expression('3x + 2y + 3') p2 = Polyhedron(equalities=[e2]) # not empty print(p1._toisl()) print(p2._toisl()) diff --git a/tests/test_linear.py b/tests/test_linear.py index 1fe9ac8..b722726 100644 --- a/tests/test_linear.py +++ b/tests/test_linear.py @@ -133,7 +133,6 @@ class TestExpression(unittest.TestCase): self.assertEqual(repr(self.one), 'Constant(1)') self.assertEqual(repr(self.expr), "Expression({'x': 1, 'y': -2}, 3)") - @unittest.expectedFailure def test_fromstring(self): self.assertEqual(Expression.fromstring('x'), self.x) self.assertEqual(Expression.fromstring('-x'), -self.x) -- 2.20.1