[pypy-svn] r22745 - in pypy/dist/pypy/lib/logic: . basic_store store_without_cs

auc at codespeak.net auc at codespeak.net
Fri Jan 27 17:37:12 CET 2006


Author: auc
Date: Fri Jan 27 17:37:08 2006
New Revision: 22745

Added:
   pypy/dist/pypy/lib/logic/basic_store/
      - copied from r22714, pypy/dist/pypy/lib/logic/store_without_cs/
   pypy/dist/pypy/lib/logic/state.py
Removed:
   pypy/dist/pypy/lib/logic/store_without_cs/
Modified:
   pypy/dist/pypy/lib/logic/computationspace.py
   pypy/dist/pypy/lib/logic/distributor.py
   pypy/dist/pypy/lib/logic/test_computationspace.py
   pypy/dist/pypy/lib/logic/variable.py
Log:
(ale, auc)
* basic choose / commit implementation (cooperation between space and distributor)
* lot of fixes
* rename store_without_cs basic_store


Modified: pypy/dist/pypy/lib/logic/computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/computationspace.py	Fri Jan 27 17:37:08 2006
@@ -179,30 +179,16 @@
 
 from threading import Thread, Condition, RLock, local
 
+from state import Succeeded, Distributable, Failed, Merged
+
 from variable import EqSet, Var, \
      VariableException, NotAVariable, AlreadyInStore
 from constraint import FiniteDomain, ConsistencyFailure
+from distributor import DefaultDistributor
 
-EmptyDom = FiniteDomain([])
-
-class Succeeded:
-    """It contains no choice points but a solution to
-       the logic program.
-    """
-    pass
-
-class Distributable:
-    pass
 
-class Failed(Exception):
-    pass
+EmptyDom = FiniteDomain([])
 
-class Merged:
-    """Its constraint store has been added to a parent.
-       Any further operation operation on the space is
-       an error.
-    """
-    pass
 
 class Alternatives(object):
 
@@ -262,6 +248,9 @@
          other but not to any other variables.
        * variables bound to a number, record or procedure
          (also called determined variables)."""
+
+    _nb_choices = 0
+
     
     def __init__(self, problem, parent=None):
         # consistency-preserving stuff
@@ -269,6 +258,7 @@
         self.bind_lock = RLock()
         self.status = None
         self.status_condition = Condition()
+        self.distributor = DefaultDistributor(self)
         
         if parent is None:
             self.vars = set()
@@ -283,6 +273,8 @@
             self.bind(self.root, problem(self))
             # check satisfiability of the space
             self._process()
+            if self.status == Distributable:
+                self.distributor.start()
         else:
             self.vars = parent.vars
             self.names = parent.names
@@ -290,6 +282,13 @@
             self.constraints = parent.constraints
             self.root = parent.root
 
+        # create a unique choice point
+        self.CHOICE = self._make_choice_var()
+
+    def __del__(self):
+        self.status = Failed
+        self.bind(self.CHOICE, 0)
+        
 #-- Store ------------------------------------------------
 
     #-- Variables ----------------------------
@@ -615,6 +614,7 @@
     def _distributable(self):
         if self.status not in (Failed, Succeeded, Merged):
             return self._distributable_domains()
+        return False
         # 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
@@ -645,11 +645,44 @@
         spc = ComputationSpace(NoProblem, parent=self)
         for var in spc.vars:
             var.cs_set_dom(spc, var.cs_get_dom(self).copy())
+        # check satisfiability of the space
+        spc._process()
+        if spc.status == Distributable:
+            spc.distributor.start()
         return spc
 
     def inject(self, restricting_problem):
+        """add additional stuff into a space"""
         pass
 
+    def commit(self, choice):
+        """if self is distributable, causes the Choose call in the
+           space to 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.
+        """
+        self.bind(self.CHOICE, choice)
+
+    def choose(self, nb_choices):
+        """
+        waits for stability
+        blocks until commit provides a value
+        between 0 and nb_choices
+        at most one choose running in a given space
+        at a given time
+        ----
+        this is used by the distributor thread
+        """
+        self.ask()
+        choice = self.CHOICE.get()
+        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 make_children(self):
         for dommap in self.distributor.distribute():
             cs = ComputationSpace(lambda cs : True,
@@ -658,16 +691,6 @@
             for var, dom in dommap.items():
                 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
         """

Modified: pypy/dist/pypy/lib/logic/distributor.py
==============================================================================
--- pypy/dist/pypy/lib/logic/distributor.py	(original)
+++ pypy/dist/pypy/lib/logic/distributor.py	Fri Jan 27 17:37:08 2006
@@ -1,16 +1,20 @@
 import math, random
+from threading import Thread
+from state import Succeeded, Distributable, Failed, Merged
 
-def make_new_domains(cs, variables):
-    """updates variables with copied domains indexed by computation space"""
+def arrange_domains(cs, variables):
+    """build a data structure from var to dom
+       that satisfies distribute & friends"""
     new_doms = {}
     for var in variables:
         new_doms[var] = var.cs_get_dom(cs).copy()
     return new_doms
 
-class AbstractDistributor(object):
+class AbstractDistributor(Thread):
     """_distribute is left unimplemented."""
 
     def __init__(self, c_space, nb_subspaces=2):
+        Thread.__init__(self)
         self.nb_subspaces = nb_subspaces
         self.cs = c_space
         self.verbose = 0
@@ -47,7 +51,7 @@
     def nb_subdomains(self):
         """return number of sub domains to explore"""
         return self.nb_subspaces
-
+       
     def distribute(self, verbose=0):
         """do the minimal job and let concrete class distribute variables
         """
@@ -55,7 +59,7 @@
         variables = self.cs.get_variables_with_a_domain()
         replicas = []
         for i in range(self.nb_subdomains()):
-            replicas.append(make_new_domains(self.cs, variables))
+            replicas.append(arrange_domains(self.cs, variables))
         modified_domains = self._distribute(*replicas)
         for domain in modified_domains:
             domain.reset_flags()
@@ -122,7 +126,34 @@
             return min(self.nb_subspaces, self.__to_split.cs_get_dom(self.cs).size()) #domains[self.__to_split].size())
         else:
             return self.__to_split.cs_get_dom(self.cs).size() # domains[self.__to_split].size()
-    
+
+    ### new threaded distributor
+
+    def run(self):
+        while self.cs.status == Distributable:
+            choice = self.cs.choose(self.nb_subdomains())
+            if self.cs.status == Failed:
+                return
+            self.new_distribute(choice)
+            self.cs._process()
+
+    def new_distribute(self, choice):
+        """See AbstractDistributor"""
+        variable = self.findSmallestDomain()
+        #variables = self.cs.get_variables_with_a_domain()
+        #domains = arrange_domains(self.cs, variables)
+        nb_subspaces = self.nb_subdomains()
+        values = variable.cs_get_dom(self.cs).get_values()
+        nb_elts = max(1, len(values)*1./nb_subspaces)
+        start, end = (int(math.floor(index * nb_elts)),
+                      int(math.floor((index + 1) * nb_elts)))
+        variable.cs_get_dom(self.cs).remove_values(values[:start])
+        variable.cs_get_dom(self.cs).remove_values(values[end:])
+
+
+    ### current tests rely on this old
+    ### do_everything-at-once version
+        
     def _distribute(self, *args):
         """See AbstractDistributor"""
         variable = self.__to_split

Added: pypy/dist/pypy/lib/logic/state.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/logic/state.py	Fri Jan 27 17:37:08 2006
@@ -0,0 +1,19 @@
+        
+class Succeeded:
+    """It contains no choice points but a solution to
+       the logic program.
+    """
+    pass
+
+class Distributable:
+    pass
+
+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

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	Fri Jan 27 17:37:08 2006
@@ -474,8 +474,5 @@
         assert new_spc.ask() == cs.Succeeded
         assert w.cs_get_dom(spc) == c.FiniteDomain([5, 6, 7])
         assert w.cs_get_dom(new_spc) == c.FiniteDomain([5])
-
-##         with-space(spc):
-##             assert w.dom == ... [5, 6, 7]
-##         with-space(new_spc):
-##             assert w.dom == ... [5]
+        spc.commit(0)
+        new_spc.commit(0)

Modified: pypy/dist/pypy/lib/logic/variable.py
==============================================================================
--- pypy/dist/pypy/lib/logic/variable.py	(original)
+++ pypy/dist/pypy/lib/logic/variable.py	Fri Jan 27 17:37:08 2006
@@ -103,6 +103,7 @@
         self._doms[cs] = dom
 
     def cs_get_dom(self, cs):
+        self._doms.setdefault(cs, FiniteDomain([]))
         return self._doms[cs]
 
     #---- Concurrent public ops --------------------------



More information about the Pypy-commit mailing list