[pypy-svn] r22675 - pypy/dist/pypy/lib/logic

auc at codespeak.net auc at codespeak.net
Thu Jan 26 11:43:07 CET 2006


Author: auc
Date: Thu Jan 26 11:43:03 2006
New Revision: 22675

Modified:
   pypy/dist/pypy/lib/logic/computationspace.py
   pypy/dist/pypy/lib/logic/distributor.py
   pypy/dist/pypy/lib/logic/test_computationspace.py
Log:
(ale, auc)
* ask & initialisation refactoring
* status & distributable more close to correctness


Modified: pypy/dist/pypy/lib/logic/computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/computationspace.py	Thu Jan 26 11:43:03 2006
@@ -177,23 +177,32 @@
 
 ## space = ComputationSpace(fun=my_problem)
 
+from unification import Store, var
+from constraint import ConsistencyFailure
+from threading import Thread, Condition
+
 class Unprocessed:
     pass
 
 class Working:
     pass
 
-class Failed:
+class Failed(Exception):
     pass
 
 class Merged:
+    """Its constraint store has been added to a parent.
+       Any further operation operation on the space is
+       an error.
+    """
     pass
 
 class Succeeded:
+    """It contains no choice points but a solution to
+       the logic program.
+    """
     pass
 
-from unification import Store, var
-from constraint import ConsistencyFailure
 
 class ComputationSpace(object):
 
@@ -207,37 +216,57 @@
             self.root = parent.root
         self.program = program
         self.parent = parent
+        # status
         self.status = Unprocessed
-        self.children = set()
+        self.status_condition = Condition()
+        # run ...
+        self._process()
+
+    def _process(self):
+        try:
+            self.store.satisfy_all()
+        except ConsistencyFailure:
+            self.status = Failed
+        else:
+            self.status = Succeeded
 
     def _stable(self):
         #XXX: really ?
-        return self.status in (Failed, Succeeded, Merged)
+        return self.status in (Failed, Succeeded, Merged) \
+               or self._distributable()
 
-    def _distributable(self):
+    def _suspended(self):
         pass
-        #return not self._stable 
+        # 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
+        # has not yet transferred all required information to
+        # the space 
+    
+
+    def _distributable(self):
+        if self.status not in (Failed, Succeeded, Merged):
+            return self.distributor.findSmallestDomain() > 1
+        # in The Book : "the space has one thread that is
+        # suspended on a choice point with two or more alternatives.
+        # A space canhave at most one choice point; attempting to
+        # create another gives an error."
 
     def set_distributor(self, dist):
         self.distributor = dist
 
     def ask(self):
         # XXX: block on status being not stable for threads
-        if self._stable():
-            return self.status
-            #return self.store.nb_candidates()
-        else:
-            #TBD
+        try:
+            self.status_condition.acquire()
+            while not self._stable():
+                self.status_condition.wait()
+            if self._distributable():
+                return self.distributor.nb_subdomains()
             return self.status
+        finally:
+            self.status_condition.release()
 
-    def process(self):
-        self.status = Working
-        try:
-            self.store.satisfy_all()
-        except ConsistencyFailure:
-            self.status = Failed
-        else:
-            self.status = Succeeded
 
     def make_children(self):
         for dommap in self.distributor.distribute():
@@ -248,5 +277,36 @@
                 var.cs_set_dom(cs, dom)
 
 
+    def commit(self, some_number):
+        """if self is distributable, causes the Choose call in the
+           space ot complete and return some_number as a result. This
+           may cause the spzce to resume execution.
+           some_number must satisfy 1=<I=<N where N is the first arg
+           of the Choose call.
+        """
+        pass
+
+    def solve_all(self):
+        """recursively solves the problem
+        """
+        if self.status == Unprocessed:
+            self.process()
+            if self.status == Succeeded: return self.root
+            if self.status == Failed: raise Failed
+            self.make_children()
+            results = set() # to be merged/committed ?
+            for cs in self.children:
+                try:
+                    results.add(cs.solve_all())
+                except Failed:
+                    pass
+            for result in results:
+                # Q: do we (a) merge our children results right now
+                #    or (b) do we pass results up the call chain ?
+                # (b) makes sense for a SolveAll kind of method on cs's
+                # (a) might be more Oz-ish, maybe allowing some very fancy
+                #     stuff with distribution or whatever
+                self.do_something_with(result)
+            
 
         

Modified: pypy/dist/pypy/lib/logic/distributor.py
==============================================================================
--- pypy/dist/pypy/lib/logic/distributor.py	(original)
+++ pypy/dist/pypy/lib/logic/distributor.py	Thu Jan 26 11:43:03 2006
@@ -44,7 +44,7 @@
         return best
 
 
-    def nb_subdomains(self, domains):
+    def nb_subdomains(self):
         """return number of sub domains to explore"""
         return self.nb_subspaces
 
@@ -54,7 +54,7 @@
         self.verbose = verbose
         variables = self.c_space.store.get_variables_with_a_domain()
         replicas = []
-        for i in range(self.nb_subdomains(variables)):
+        for i in range(self.nb_subdomains()):
             replicas.append(make_new_domains(variables))
         modified_domains = self._distribute(*replicas)
         for domain in modified_domains:
@@ -115,7 +115,7 @@
         AbstractDistributor.__init__(self, c_space, nb_subspaces)
         self.__to_split = None
 
-    def nb_subdomains(self, domains):
+    def nb_subdomains(self):
         """See AbstractDistributor"""
         self.__to_split = self.findSmallestDomain()
         if self.nb_subspaces:

Modified: pypy/dist/pypy/lib/logic/test_computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/test_computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/test_computationspace.py	Thu Jan 26 11:43:03 2006
@@ -60,68 +60,39 @@
 
     def test_process_and_ask_success(self):
         spc = cs.ComputationSpace(satisfiable_problem)
-        assert spc.ask() == cs.Unprocessed
-        spc.process()
         assert spc.ask() == cs.Succeeded
-        
 
     def test_process_and_ask_failure(self):
         spc = cs.ComputationSpace(unsatisfiable_problem)
-        assert spc.ask() == cs.Unprocessed
-        spc.process()
         assert spc.ask() == cs.Failed
 
     def test_distribute(self):
         spc = cs.ComputationSpace(satisfiable_problem)
-        spc.process()
-        new_domains = [d.items() for d in
+        new_domains = [tuple(d.items()) for d in
                        spc.distributor.distribute()]
         x, y, z, w = (spc.store.get_var_by_name('x'),
                       spc.store.get_var_by_name('y'),
                       spc.store.get_var_by_name('z'),
                       spc.store.get_var_by_name('w'))
-        expected_domains = [{x: c.FiniteDomain([6]),
+        expected_domains = [tuple({x: c.FiniteDomain([6]),
                              y: c.FiniteDomain([2]),
                              z: c.FiniteDomain([4]),
-                             w: c.FiniteDomain([5])}.items(),
-                            {x: c.FiniteDomain([6]),
+                             w: c.FiniteDomain([5])}.items()),
+                            tuple({x: c.FiniteDomain([6]),
                              y: c.FiniteDomain([2]),
                              z: c.FiniteDomain([4]),
-                             w: c.FiniteDomain([6, 7])}.items()]
+                             w: c.FiniteDomain([6, 7])}.items())]
+        print new_domains, expected_domains
+        assert len(new_domains) == len(expected_domains)
         for (d1, d2) in zip(new_domains, expected_domains):
+            assert len(d1) == len(d2)
             for (e1, e2) in zip(d1, d2):
                 print e1, '=?', e2
                 assert e1 == e2
         # the following assertion fails for mysterious reasons
         # have we discovered a bug in CPython ?
-        # assert set(new_domains) == set(expected_domains)
+        #print hash(new_domains[0]), hash(new_domains[1])
+        #print hash(expected_domains[0]), hash(expected_domains[1])
+        #assert set(new_domains) == set(expected_domains)
 
-    def test_make_children(self):
-        spc = cs.ComputationSpace(satisfiable_problem)
-        x, y, z, w = (spc.store.get_var_by_name('x'),
-                      spc.store.get_var_by_name('y'),
-                      spc.store.get_var_by_name('z'),
-                      spc.store.get_var_by_name('w'))
-        spc.process()
-        spc.make_children()
-        assert len(spc.children) == 2
-        new_domains = []
-        all_vars = spc.store.get_variables_with_a_domain()
-        for child in spc.children:
-            new_domains.append([(var, var.cs_get_dom(child))
-                                for var in all_vars])
-            
-        expected_domains = [{x: c.FiniteDomain([6]),
-                             y: c.FiniteDomain([2]),
-                             z: c.FiniteDomain([4]),
-                             w: c.FiniteDomain([5])}.items(),
-                            {x: c.FiniteDomain([6]),
-                             y: c.FiniteDomain([2]),
-                             z: c.FiniteDomain([4]),
-                             w: c.FiniteDomain([6, 7])}.items()]
-
-        for (d1, d2) in zip(new_domains, expected_domains):
-            for (e1, e2) in zip(d1, d2):
-                print e1, '=?', e2
-                assert e1 == e2
         



More information about the Pypy-commit mailing list