Support for dummy symbols
authorVivien Maisonneuve <v.maisonneuve@gmail.com>
Thu, 3 Jul 2014 08:19:39 +0000 (10:19 +0200)
committerVivien Maisonneuve <v.maisonneuve@gmail.com>
Thu, 3 Jul 2014 09:13:22 +0000 (11:13 +0200)
examples/nsad2010.py
pypol/__init__.py
pypol/linexprs.py
pypol/tests/test_linexprs.py

index e2cacc7..1bf97d8 100755 (executable)
@@ -2,17 +2,13 @@
 
 from pypol import *
 
-def affine_derivative_closure(T, x0s):
+def affine_derivative_closure(T, x0s, xs):
 
-    xs = [Symbol("{}'".format(x0.name)) for x0 in x0s]
-    dxs = [Symbol('d{}'.format(x0.name)) for x0 in x0s]
-    k = Symbol('k')
+    dxs = [x0.asdummy() for x0 in x0s]
+    k = Dummy('k')
 
     for x in T.symbols:
         assert x in x0s + xs
-    for dx in dxs:
-        assert dx.name not in T.symbols
-    assert k.name not in T.symbols
 
     T0 = T
 
@@ -48,5 +44,5 @@ i0, j0, i, j = symbols(['i', 'j', "i'", "j'"])
 T = Eq(i, i0 + 2) & Eq(j, j0 + 1)
 
 print('T =', T)
-Tstar = affine_derivative_closure(T, [i0, j0])
+Tstar = affine_derivative_closure(T, [i0, j0], [i, j])
 print('T* =', Tstar)
index 89f80fc..c81cb25 100644 (file)
@@ -2,13 +2,13 @@
 A polyhedral library based on ISL.
 """
 
-from .linexprs import Expression, Symbol, symbols, Rational
+from .linexprs import Expression, Symbol, symbols, Dummy, Rational
 from .polyhedra import Polyhedron, Eq, Ne, Le, Lt, Ge, Gt, Ne, Empty, Universe
 from .domains import Domain, And, Or, Not
 
 
 __all__ = [
-    'Expression', 'Symbol', 'symbols', 'Rational',
+    'Expression', 'Symbol', 'symbols', 'Dummy', 'Rational',
     'Polyhedron', 'Eq', 'Ne', 'Le', 'Lt', 'Ge', 'Gt', 'Empty', 'Universe',
     'Domain', 'And', 'Or', 'Not',
 ]
index 73c6b0e..f3cff23 100644 (file)
@@ -9,7 +9,7 @@ from fractions import Fraction, gcd
 
 __all__ = [
     'Expression',
-    'Symbol', 'symbols',
+    'Symbol', 'symbols', 'Dummy',
     'Rational',
 ]
 
@@ -355,7 +355,7 @@ class Symbol(Expression):
         return self._name
 
     def __hash__(self):
-        return hash(self._name)
+        return hash(self.sortkey())
 
     def coefficient(self, symbol):
         if not isinstance(symbol, Symbol):
@@ -390,7 +390,11 @@ class Symbol(Expression):
         yield 1
 
     def __eq__(self, other):
-        return isinstance(other, Symbol) and self.name == other.name
+        return not isinstance(other, Dummy) and isinstance(other, Symbol) \
+            and self.name == other.name
+
+    def asdummy(self):
+        return Dummy(self.name)
 
     @classmethod
     def _fromast(cls, node):
@@ -417,6 +421,34 @@ def symbols(names):
     return tuple(Symbol(name) for name in names)
 
 
+class Dummy(Symbol):
+
+    __slots__ = (
+        '_name',
+        '_index',
+    )
+
+    _count = 0
+
+    def __new__(cls, name=None):
+        if name is None:
+            name = 'Dummy_{}'.format(Dummy._count)
+        self = object().__new__(cls)
+        self._name = name.strip()
+        self._index = Dummy._count
+        Dummy._count += 1
+        return self
+
+    def __hash__(self):
+        return hash(self.sortkey())
+
+    def sortkey(self):
+        return self._name, self._index
+
+    def __eq__(self, other):
+        return isinstance(other, Dummy) and self._index == other._index
+
+
 class Rational(Expression):
 
     __slots__ = (
index adfec7d..508c57b 100644 (file)
@@ -231,6 +231,23 @@ class TestSymbol(unittest.TestCase):
         self.assertListEqual(list(symbols(['x', 'y'])), [self.x, self.y])
 
 
+class TestDummy(unittest.TestCase):
+
+    def setUp(self):
+        self.x = Dummy('x')
+
+    def test_new(self):
+        self.assertEqual(self.x.name, 'x')
+        self.assertTrue(Dummy().name.startswith('Dummy'))
+
+    def test_eq(self):
+        self.assertEqual(self.x, self.x)
+        self.assertNotEqual(self.x, Symbol('x'))
+        self.assertNotEqual(Symbol('x'), self.x)
+        self.assertNotEqual(self.x, Dummy('x'))
+        self.assertNotEqual(Dummy(), Dummy())
+
+
 class TestRational(unittest.TestCase):
 
     def setUp(self):