[pypy-svn] r22959 - pypy/dist/pypy/lib/logic/computation_space

auc at codespeak.net auc at codespeak.net
Thu Feb 2 17:01:27 CET 2006


Author: auc
Date: Thu Feb  2 17:01:24 2006
New Revision: 22959

Modified:
   pypy/dist/pypy/lib/logic/computation_space/computationspace.py
   pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py
   pypy/dist/pypy/lib/logic/computation_space/variable.py
Log:
add merge operator

(now we have a basic impl. of all comp.spaces operators, next step is getting real dataflow vars)


Modified: pypy/dist/pypy/lib/logic/computation_space/computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/computationspace.py	Thu Feb  2 17:01:24 2006
@@ -160,11 +160,18 @@
 ## then it returns alternatives(N), where N is the number of
 ## alternatives.
 
+## Merge
+## -----
+
+## Merge(S Y) binds Y to the root variable of space S and discards the
+## space
+
+
 from threading import Thread, Condition, RLock, local
 
 from state import Succeeded, Distributable, Failed, Merged
 
-from variable import EqSet, Var, \
+from variable import EqSet, Var, NoValue, \
      VariableException, NotAVariable, AlreadyInStore
 from constraint import FiniteDomain, ConsistencyFailure
 from distributor import DefaultDistributor
@@ -243,8 +250,10 @@
         self.status = None
         self.status_condition = Condition()
         self.distributor = DefaultDistributor(self)
+        self.TOP = False
         
         if parent is None:
+            self.TOP = True
             self.vars = set()
             # mapping of names to vars (all of them)
             self.names = {}
@@ -306,6 +315,30 @@
             return self.names[name]
         except KeyError:
             raise NotInStore(name)
+
+    def find_vars(self, *names):
+        try:
+            return [self.names[name] for name in names]
+        except KeyError:
+            raise NotInStore(name)
+
+    def is_bound(self, var):
+        """check wether a var is bound is locally bound"""
+        if self.TOP:
+            return var.is_bound()
+        return len(var.cs_get_dom(self)) == 1
+
+    def dom(self, var):
+        """return the local domain"""
+        return var.cs_get_dom(self)
+
+    def val(self, var):
+        """return the local binding without blocking"""
+        if self.TOP:
+            return var.val
+        if self.is_bound(var):
+            return var.cs_get_dom(self)[0]
+        return NoValue
     
     #-- Constraints -------------------------
 
@@ -568,6 +601,9 @@
 
 #-- Computation Space -----------------------------------------
 
+    def _make_choice_var(self):
+        ComputationSpace._nb_choices += 1
+        return self.var('__choice__'+str(self._nb_choices))
 
     def _process(self):
         try:
@@ -586,7 +622,7 @@
                or self._distributable()
 
     def _suspended(self):
-        pass
+        raise NotImplemented
         # additional basic constraints done in an ancestor can
         # make it runnable ; it is a temporary condition due
         # to concurrency ; it means that some ancestor space
@@ -614,6 +650,8 @@
 
     def ask(self):
         # XXX: block on status being not stable for threads
+        #      use a df var instead of explicit waiting
+        # XXX: truly df vars needed (not one-shot bindings)
         try:
             self.status_condition.acquire()
             while not self._stable():
@@ -662,9 +700,12 @@
         self.CHOICE = self._make_choice_var()
         return choice    
 
-    def _make_choice_var(self):
-        ComputationSpace._nb_choices += 1
-        return self.var('__choice__'+str(self._nb_choices))
+    def merge(self):
+        assert self.status == Succeeded
+        # the following ought to be atomic (?)
+        for var in self.root.val:
+            var.val = var.cs_get_dom(self).get_values()[0]
+        self.status = Merged
 
 #-- Unifiability checks---------------------------------------
 #--

Modified: pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py	Thu Feb  2 17:01:24 2006
@@ -518,6 +518,7 @@
         w = spc.get_var_by_name('w')
         assert spc.ask() == space.Alternatives(2)
         new_spc = spc.clone()
+        # following couple of ops superceeded by inject()
         new_spc.add_constraint(c.Expression(new_spc, [w], 'w == 5'))
         new_spc._process()
         assert spc.ask() == space.Alternatives(2)
@@ -538,3 +539,31 @@
         assert w.cs_get_dom(spc) == c.FiniteDomain([5, 6, 7])
         assert w.cs_get_dom(new_spc) == c.FiniteDomain([5])
         
+    def test_merge(self):
+        spc = space.ComputationSpace(problems.satisfiable_problem)
+        x, y, z, w = spc.find_vars('x', 'y', 'z', 'w')
+        assert spc.TOP
+        assert spc.ask() == space.Alternatives(2)
+        assert spc.dom(x) == c.FiniteDomain([6])
+        assert spc.dom(y) == c.FiniteDomain([2])
+        assert spc.dom(z) == c.FiniteDomain([4])
+        assert spc.dom(w) == c.FiniteDomain([5, 6, 7])
+
+        def more_constraints(space):
+            space.add_constraint(c.Expression(space, [w], 'w == 5'))
+
+        nspc = spc.clone()
+        nspc.inject(more_constraints)
+        x, y, z, w = nspc.find_vars('x', 'y', 'z', 'w')
+        assert not nspc.TOP
+        assert nspc.dom(x) == c.FiniteDomain([6])
+        assert nspc.dom(y) == c.FiniteDomain([2])
+        assert nspc.dom(z) == c.FiniteDomain([4])
+        assert nspc.dom(w) == c.FiniteDomain([5])
+        assert nspc.ask() == space.Succeeded
+        nspc.merge()
+        assert nspc.ask() == space.Merged
+        assert x.val == 6
+        assert y.val == 2
+        assert w.val == 5
+        assert (x, w, y) == nspc.root.val

Modified: pypy/dist/pypy/lib/logic/computation_space/variable.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/variable.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/variable.py	Thu Feb  2 17:01:24 2006
@@ -55,7 +55,7 @@
         return not isinstance(self._val, EqSet) \
                and self._val != NoValue
 
-    # 'transaction' support
+    # atomic unification support
 
     def _commit(self):
         self.changed = False
@@ -111,17 +111,9 @@
     # should be used by threads that want to block on
     # unbound variables
 
-##     def set_dom(self, dom):
-##         self.cs_set_dom(self.cs, dom)
-
-##     def get_dom(self):
-##         return self.cs_get_dom(self.cs)
-
-##     dom = property(get_dom, set_dom)
-
     def get(self):
         """Make threads wait on the variable
-           being bound
+           being bound in the top-level space
         """
         try:
             self.value_condition.acquire()



More information about the Pypy-commit mailing list