[pypy-svn] r33120 - in pypy/dist/pypy/objspace: . cclp cclp/constraint

auc at codespeak.net auc at codespeak.net
Tue Oct 10 17:54:23 CEST 2006


Author: auc
Date: Tue Oct 10 17:54:01 2006
New Revision: 33120

Modified:
   pypy/dist/pypy/objspace/cclp/constraint/constraint.py
   pypy/dist/pypy/objspace/cclp/constraint/distributor.py
   pypy/dist/pypy/objspace/cclp/constraint/variable.py
   pypy/dist/pypy/objspace/cclp/interp_var.py
   pypy/dist/pypy/objspace/cclp/scheduler.py
   pypy/dist/pypy/objspace/cclp/space.py
   pypy/dist/pypy/objspace/cclp/thread.py
   pypy/dist/pypy/objspace/cclp/thunk.py
   pypy/dist/pypy/objspace/cclp/variable.py
   pypy/dist/pypy/objspace/logic.py
Log:
interpreted clone (for constraint problems), removal of many debug prints -- probably not translatable right now


Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/constraint/constraint.py	(original)
+++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py	Tue Oct 10 17:54:01 2006
@@ -1,3 +1,4 @@
+from pypy.rpython.objectmodel import we_are_translated
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter import baseobjspace, typedef, gateway
@@ -43,8 +44,7 @@
 
     def w_revise(self):
         return self._space.newbool(self.revise())
-            
-    
+                
 W_AbstractConstraint.typedef = typedef.TypeDef(
     "W_AbstractConstraint",
     W_Constraint.typedef,                                           
@@ -92,6 +92,14 @@
         # self.filter_func is a function taking keyword arguments and returning a boolean
         self.filter_func = self._space.make_filter(w_variables, w_formula)
 
+    def copy(self):
+        if we_are_translated():
+            raise NotImplementedError
+        else:
+            newvars = [var.copy(self._space) for var in self._variables]
+            const = W_Expression(self._space, self._space.newlist(newvars), self._space.wrap(self.formula))
+            return const
+
     def _init_result_cache(self):
         """key = (variable,value), value = [has_success,has_failure]"""
         result_cache = self._space.newdict()
@@ -229,6 +237,14 @@
         # worst case complexity
         #self.__cost = len(w_variables.wrappeditems) * (len(w_variables.wrappeditems) - 1) / 2
 
+    def copy(self):
+        if we_are_translated():
+            raise NotImplementedError
+        else:
+            newvars = [var.copy(self._space) for var in self._variables]
+            const = W_AllDistinct(self._space, self._space.newlist(newvars))
+            return const
+
     def revise(self):
         _spc = self._space
 

Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/constraint/distributor.py	(original)
+++ pypy/dist/pypy/objspace/cclp/constraint/distributor.py	Tue Oct 10 17:54:01 2006
@@ -14,18 +14,18 @@
     assert isinstance(w_strategy, W_StringObject)
     strat = space.str_w(w_strategy)
     cspace = get_current_cspace(space)
+    dist = None
     if strat == 'dichotomy':
-         cspace.distributor = make_split_distributor(space, space.newint(2))
+         dist = make_split_distributor(space, space.newint(2))
     else:
         raise OperationError(space.w_RuntimeError,
                              space.wrap("please pick a strategy in (naive, dichotomy)"))
 
-    dist = cspace.distributor
+    cspace.distributor = dist
     # constraint distributor thread main loop
     while dist.distributable():
         choice = cspace.choose(dist.fanout())
         dist.w_distribute(choice)
-            
 app_distribute = interp2app(distribute)
 
 

Modified: pypy/dist/pypy/objspace/cclp/constraint/variable.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/constraint/variable.py	(original)
+++ pypy/dist/pypy/objspace/cclp/constraint/variable.py	Tue Oct 10 17:54:01 2006
@@ -16,7 +16,7 @@
     assert isinstance(w_name, W_StringObject)
     w_dom = W_FiniteDomain(space, w_values)
     w_var = W_CVar(space, w_dom, w_name)
-    w("CVAR", str(w_var))
+    #w("CVAR", str(w_var))
     return w_var
 app_domain = gateway.interp2app(domain)
 

Modified: pypy/dist/pypy/objspace/cclp/interp_var.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/interp_var.py	(original)
+++ pypy/dist/pypy/objspace/cclp/interp_var.py	Tue Oct 10 17:54:01 2006
@@ -40,7 +40,7 @@
 
 
 def interp_assign_aliases(w_var, w_val):
-    w("  :assign")
+    #w("  :assign")
     assert isinstance(w_var, W_Var)
     w_curr = w_var
     while 1:
@@ -54,10 +54,10 @@
         # switch to next
         w_curr = w_next
     _assign_entailed(w_var, w_val)
-    w("  :assigned")
+    #w("  :assigned")
 
 def _assign_entailed(w_var, w_val):
-    w("   :assign entailed")
+    #w("   :assign entailed")
     for var in w_var.entails:
         assert isinstance(var, W_Var)
         if interp_free(var):

Modified: pypy/dist/pypy/objspace/cclp/scheduler.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/scheduler.py	(original)
+++ pypy/dist/pypy/objspace/cclp/scheduler.py	Tue Oct 10 17:54:01 2006
@@ -16,13 +16,13 @@
         self.space = space
         self._main = ClonableCoroutine.w_getcurrent(space)
         assert isinstance(self._main, ClonableCoroutine)
+        self._switch_count = 0
         self._init_head(self._main)
         self._blocked = {} # thread set
         # variables suspension lists
         self._blocked_on = {} # var -> threads
         self._blocked_byneed = {} # var -> threads
         self._asking = {} # thread -> cspace
-        self._switch_count = 0
         # more accounting
         self._per_space_live_threads = {} # space -> nb runnable threads
         self._traced = {} # thread -> vars
@@ -69,7 +69,7 @@
             self.dec_live_thread_count(cspace)
             self.schedule()
             self.inc_live_thread_count(cspace)
-        else: # or we ask() from outside
+        else: # or we ask(), or clone() from outside
             self.schedule()
 
     #-- cspace -> thread_count helpers
@@ -93,7 +93,7 @@
     def schedule(self):
         to_be_run = self._select_next()
         assert isinstance(to_be_run, ClonableCoroutine)
-        w(".. SWITCHING", str(id(ClonableCoroutine.w_getcurrent(self.space))), "=>", str(id(to_be_run)))
+        #w(".. SWITCHING", str(id(ClonableCoroutine.w_getcurrent(self.space))), "=>", str(id(to_be_run)))
         self._switch_count += 1
         to_be_run.w_switch() 
 
@@ -104,7 +104,7 @@
         if to_be_run == curr:
             w(".. PASS")
             return
-        w(".. SWITCHING", str(id(curr)), "=>", str(id(to_be_run)))
+        #w(".. SWITCHING", str(id(curr)), "=>", str(id(to_be_run)))
         self._switch_count += 1
         to_be_run.w_switch() 
         
@@ -133,7 +133,7 @@
                 sched.uler._main = sched.uler._head = self._head
                 w(".. SCHEDULER reinitialized")
                 raise OperationError(self.space.w_AllBlockedError,
-                                     self.space.wrap("can't schedule, possible deadlock in sight"))
+                                     self.space.wrap("can't schedule, probable deadlock in sight"))
         self._head = to_be_run
         return to_be_run
 
@@ -153,7 +153,8 @@
         try:
             del self._traced[thread]
         except KeyError:
-            w(".. removing non-traced thread")
+            pass
+            #w(".. removing non-traced thread")
         l = thread._prev
         r = thread._next
         l._next = r
@@ -172,7 +173,7 @@
                 del self._per_space_live_threads[cspace]
 
     def add_to_blocked_on(self, w_var, thread):
-        w(".. we BLOCK thread", str(id(thread)), "on var", str(w_var))
+        #w(".. we BLOCK thread", str(id(thread)), "on var", str(w_var))
         assert isinstance(w_var, W_Var)
         assert isinstance(thread, ClonableCoroutine)
         assert thread not in self._blocked
@@ -188,13 +189,13 @@
             self.dec_live_thread_count(thread._cspace)
 
     def unblock_on(self, w_var):
-        v(".. we UNBLOCK threads dependants of var", str(w_var))
+        #v(".. we UNBLOCK threads dependants of var", str(w_var))
         assert isinstance(w_var, W_Var)
         blocked = []
         if w_var in self._blocked_on:
             blocked = self._blocked_on[w_var]
             del self._blocked_on[w_var]
-        w(str([id(thr) for thr in blocked]))
+        #w(str([id(thr) for thr in blocked]))
         for thr in blocked:
             del self._blocked[thr]
             # cspace accounting
@@ -202,7 +203,7 @@
                 self.inc_live_thread_count(thr._cspace)
 
     def add_to_blocked_byneed(self, w_var, thread):
-        w(".. we BLOCK BYNEED thread", str(id(thread)), "on var", str(w_var))
+        #w(".. we BLOCK BYNEED thread", str(id(thread)), "on var", str(w_var))
         assert isinstance(w_var, W_Var)
         assert isinstance(thread, ClonableCoroutine)
         if w_var in self._blocked_byneed:
@@ -217,7 +218,7 @@
             self.dec_live_thread_count(thread._cspace)
 
     def unblock_byneed_on(self, w_var):
-        v(".. we UNBLOCK BYNEED dependants of var", str(w_var))
+        #v(".. we UNBLOCK BYNEED dependants of var", str(w_var))
         assert isinstance(w_var, W_Var)
         blocked = []
         for w_alias in aliases(self.space, w_var):
@@ -225,7 +226,7 @@
                 blocked += self._blocked_byneed[w_alias]
                 del self._blocked_byneed[w_alias]
             w_alias.needed = True
-        w(str([id(thr) for thr in blocked]))
+        #w(str([id(thr) for thr in blocked]))
         for thr in blocked:
             del self._blocked[thr]
             # cspace accounting
@@ -238,14 +239,14 @@
     def trace_vars(self, thread, lvars):
         assert isinstance(thread, ClonableCoroutine)
         assert isinstance(lvars, list)
-        w(".. TRACING logic vars.", str(lvars), "for", str(id(thread)))
+        #w(".. TRACING logic vars.", str(lvars), "for", str(id(thread)))
         #assert not self._traced.has_key(thread) doesn't translate 
         self._traced[thread] = lvars
 
     def dirty_traced_vars(self, thread, failed_value):
         assert isinstance(thread, ClonableCoroutine)
         assert isinstance(failed_value, W_FailedValue)
-        w(".. DIRTYING traced vars")
+        #w(".. DIRTYING traced vars")
         for w_var in self._traced[thread]:
             if self.space.is_true(self.space.is_free(w_var)):
                 self.space.bind(w_var, failed_value)

Modified: pypy/dist/pypy/objspace/cclp/space.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/space.py	(original)
+++ pypy/dist/pypy/objspace/cclp/space.py	Tue Oct 10 17:54:01 2006
@@ -1,7 +1,7 @@
 from pypy.rpython.objectmodel import we_are_translated
 from pypy.interpreter import baseobjspace, gateway, argument, typedef
 from pypy.interpreter.function import Function
-from pypy.interpreter.eval import Code
+from pypy.interpreter.pycode import PyCode
 
 from pypy.interpreter.error import OperationError
 
@@ -13,9 +13,9 @@
 from pypy.objspace.cclp.global_state import sched
 from pypy.objspace.cclp.variable import newvar
 from pypy.objspace.cclp.types import ConsistencyError, Solution, W_Var, \
-     W_CVar, W_AbstractDomain
+     W_CVar, W_AbstractDomain, W_AbstractDistributor
 from pypy.objspace.cclp.interp_var import interp_bind, interp_free
-
+from pypy.objspace.cclp.constraint.distributor import distribute
 
 def newspace(space, w_callable, __args__):
     args = __args__.normalize()
@@ -61,12 +61,20 @@
     get_current_cspace(space).tell(w_constraint)
 app_tell = gateway.interp2app(tell)
 
+if not we_are_translated():
+    def fresh_distributor(space, w_dist):
+        cspace = w_dist._cspace
+        while w_dist.distributable():
+            choice = cspace.choose(w_dist.fanout())
+            w_dist.w_distribute(choice)
+    app_fresh_distributor = gateway.interp2app(fresh_distributor)
 
 class W_CSpace(baseobjspace.Wrappable):
 
     def __init__(self, space):
         self.space = space # the object space ;-)
         self.distributor = None
+        self.threads = []
         # choice mgmt
         self._choice = newvar(space)
         self._committed = newvar(space)
@@ -84,7 +92,6 @@
 
     def clone(self):
         if not we_are_translated():
-            print "<-CLONE !! -----------------------------------------------------------------------"
             # build fresh cspace & distributor thread
             thread = ClonableCoroutine(self.space)
             new_cspace = W_CSpace(self.space)
@@ -93,34 +100,39 @@
             old_dist = self.distributor
             new_dist = old_dist.__class__(self.space, old_dist._fanout)
             new_dist._cspace = new_cspace
-            # new distributor thunk
-            thunk = CSpaceThunk(self.space,
-                                Function(self.space, Code('nocode')),
-                                argument.Arguments([]),
-                                thread)
-            thread.bind(thunk)
-            sched.uler.add_new_thread(thread)
+            new_cspace.distributor = new_dist
             # copy the store
             for var in self._store.values():
                 new_cspace.register_var(var.copy(self.space))
+            # new distributor thunk & thread
+            f = Function(self.space,
+                         app_fresh_distributor._code,
+                         self.space.newdict())
+            thunk = CSpaceThunk(self.space, f,
+                                argument.Arguments(self.space, [new_dist]),
+                                thread)
+            thread.bind(thunk)
+            sched.uler.add_new_thread(thread)
             # rebuild propagators
             new_cspace._last_choice = self._last_choice
             new_cspace._solution = newvar(self.space)
-            self.space.unify(new_cspace._solution, self.space.newlist(self._store.values()))
-            try:
-                for const in self._constraints:
-                    new_cspace.tell(const)
-                # other attrs
-                #if hasattr(self, '_last_choice'):
-                
-            except Exception, e:
-                print "DUH ?"
-                import traceback
-                traceback.print_exc()
+            # copy solution variables
+            self.space.unify(new_cspace._solution,
+                             self.space.newlist([var.copy(self.space)
+                                                 for var in self._store.values()]))
+            # constraints
+            for const in self._constraints:
+                ccopy = const.copy()
+                new_cspace.tell(ccopy)
+            sched.uler.wait_stable(new_cspace)
             return new_cspace
         else:
+            # need to copy distributor & propagator threads???
+            # but, where are we going to find them ?
             raise NotImplementedError
-
+            #new_cspace = W_CSpace(self.space)
+            #for th in self.threads:
+            #    new_cspace.threads.append(th.clone())
 
     def w_ask(self):
         sched.uler.wait_stable(self)
@@ -171,13 +183,12 @@
         self._store = {}
 
     def w_merge(self):
-        self._store = {}
         # let's bind the solution variables
         sol = self._solution.w_bound_to
         if isinstance(sol, W_ListObject):
-            bind_solution_variables(sol.wrappeditems)
+            self._bind_solution_variables(sol.wrappeditems)
         elif isinstance(sol, W_TupleObject):
-            bind_solution_variables(sol.wrappeditems)
+            self._bind_solution_variables(sol.wrappeditems)
         return self._solution
 
     def __ne__(self, other):
@@ -186,14 +197,15 @@
         return True
 
 
-def bind_solution_variables(solution):
-    if contains_cvar(solution): # was a constraint script
-        for var in solution:
-            assert isinstance(var, W_CVar)
-            dom = var.w_dom
-            assert isinstance(dom, W_AbstractDomain)
-            assert dom.size() == 1
-            interp_bind(var, dom.get_values()[0])
+    def _bind_solution_variables(self, solution):
+        if contains_cvar(solution): # was a constraint script
+            for var in solution:
+                assert isinstance(var, W_CVar)
+                realvar = self._store[var.name]
+                dom = realvar.w_dom
+                assert isinstance(dom, W_AbstractDomain)
+                assert dom.size() == 1
+                interp_bind(var, dom.get_values()[0])
 
 
 def contains_cvar(lst):

Modified: pypy/dist/pypy/objspace/cclp/thread.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/thread.py	(original)
+++ pypy/dist/pypy/objspace/cclp/thread.py	Tue Oct 10 17:54:01 2006
@@ -13,11 +13,7 @@
     """returns a future result"""
     #XXX we could be much more lazy wrt coro creation
     args = __args__.normalize()
-    # coro init
     coro = ClonableCoroutine(space)
-    # computation space is the same as in the parent
-    #coro.cspace = ClonableCoroutine.w_getcurrent(space).cspace
-    # feed the coro
     w_Future = W_Future(space)
     thunk = FutureThunk(space, w_callable, args, w_Future, coro)
     coro.bind(thunk)
@@ -35,10 +31,7 @@
 def stacklet(space, w_callable, __args__):
     """returns a coroutine object"""
     args = __args__.normalize()
-    # coro init
     coro = ClonableCoroutine(space)
-    # computation space is the same as in the parent
-    #coro.cspace = ClonableCoroutine.w_getcurrent(space).cspace
     thunk = ProcedureThunk(space, w_callable, args, coro)
     coro.bind(thunk)
     coro._cspace = get_current_cspace(space)

Modified: pypy/dist/pypy/objspace/cclp/thunk.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/thunk.py	(original)
+++ pypy/dist/pypy/objspace/cclp/thunk.py	Tue Oct 10 17:54:01 2006
@@ -15,7 +15,7 @@
 def logic_args(args):
     "returns logic vars found in unpacked normalized args"
     assert isinstance(args, tuple)
-    pos = args[0]
+    pos = args[0] or [] # pos is not an empty tuple but None
     kwa = args[1]
     pos_l = [arg for arg in pos
              if isinstance(arg, W_Var)]
@@ -80,7 +80,7 @@
         self._coro = coro
 
     def call(self):
-        w("-- initial thunk CALL in", str(id(self._coro)))
+        w("-- initial DISTRIBUTOR thunk CALL in", str(id(self._coro)))
         sched.uler.trace_vars(self._coro, logic_args(self.args.unpack()))
         cspace = self._coro._cspace
         space = self.space
@@ -98,7 +98,8 @@
                 w("-- clean EXIT of DISTRIBUTOR (success)", str(id(self._coro)))
                 sol = cspace._solution
                 assert isinstance(sol, W_Var)
-                interp_bind(sol, self.costate.w_tempval)
+                if interp_free(sol): # returning from a constraint/logic script
+                    interp_bind(sol, self.costate.w_tempval)
                 outcome = sol.w_bound_to
                 if not (isinstance(outcome, W_ListObject) or \
                         isinstance(outcome, W_TupleObject)):
@@ -107,6 +108,7 @@
                     return
                 assert interp_free(cspace._choice)
                 interp_bind(cspace._choice, self.space.newint(1))
+                assert sched.uler._per_space_live_threads[cspace] == 0, "there are still threads living in this space"
         finally:
             interp_bind(cspace._finished, self.space.w_True)
             sched.uler.remove_thread(self._coro)

Modified: pypy/dist/pypy/objspace/cclp/variable.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/variable.py	(original)
+++ pypy/dist/pypy/objspace/cclp/variable.py	Tue Oct 10 17:54:01 2006
@@ -27,7 +27,7 @@
     return w_obj
 
 def wait__Var(space, w_var):
-    w("###:wait", str(id(ClonableCoroutine.w_getcurrent(space))))
+    #w("###:wait", str(id(ClonableCoroutine.w_getcurrent(space))))
     if space.is_true(space.is_free(w_var)):
         sched.uler.unblock_byneed_on(w_var)
         sched.uler.add_to_blocked_on(w_var, ClonableCoroutine.w_getcurrent(space))
@@ -239,7 +239,7 @@
 
 
 def entail__Var_Var(space, w_v1, w_v2):
-    w("  :entail Var Var")
+    #w("  :entail Var Var")
     if space.is_true(space.is_bound(w_v1)):
         if space.is_true(space.is_bound(w_v2)):
             return unify(space,
@@ -260,7 +260,7 @@
     return space.w_None
         
 def _assign_aliases(space, w_var, w_val):
-    w("  :assign")
+    #w("  :assign")
     assert isinstance(w_var, W_Var)
     #assert isinstance(w_val, W_Root)
     w_curr = w_var
@@ -275,11 +275,11 @@
         # switch to next
         w_curr = w_next
     _assign_entailed(space, w_var, w_val)
-    w("  :assigned")
+    #w("  :assigned")
     return space.w_None
 
 def _assign_entailed(space, w_var, w_val):
-    w("   :assign entailed")
+    #w("   :assign entailed")
     for var in w_var.entails:
         if space.is_true(space.is_free(var)):
             _assign_aliases(space, var, w_val)
@@ -299,7 +299,7 @@
        user must ensure freeness of both vars"""
     assert isinstance(w_v1, W_Var)
     assert isinstance(w_v2, W_Var)
-    w("  :alias", str(id(w_v1)), str(id(w_v2)))
+    #w("  :alias", str(id(w_v1)), str(id(w_v2)))
     if space.is_true(space.is_nb_(w_v1, w_v2)):
         return space.w_None
     if space.is_true(is_aliased(space, w_v1)):
@@ -316,7 +316,7 @@
 def _add_to_aliases(space, w_v1, w_v2):
     assert isinstance(w_v1, W_Var)
     assert isinstance(w_v2, W_Var)
-    w("   :add to aliases")
+    #w("   :add to aliases")
     w_tail = w_v1.w_bound_to
     w_v1.w_bound_to = w_v2
     w_v2.w_bound_to = w_tail
@@ -325,7 +325,7 @@
 def _merge_aliases(space, w_v1, w_v2):
     assert isinstance(w_v1, W_Var)
     assert isinstance(w_v2, W_Var)
-    w("   :merge aliases")
+    #w("   :merge aliases")
     w_tail1 = get_ring_tail(space, w_v1)
     w_tail2 = get_ring_tail(space, w_v2)
     w_tail1.w_bound_to = w_v2

Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Tue Oct 10 17:54:01 2006
@@ -95,15 +95,15 @@
     def eq(w_obj1, w_obj2):
         assert isinstance(w_obj1, W_Root)
         assert isinstance(w_obj2, W_Root)
-        w("#> check identity")
+        #w("#> check identity")
         if space.is_true(space.is_nb_(w_obj1, w_obj2)):
             return space.newbool(True)
-        w("#> check aliasing")
+        #w("#> check aliasing")
         if space.is_true(space.is_free(w_obj1)):
             if space.is_true(space.is_free(w_obj2)):
                 if space.is_true(alias_of(space, w_obj1, w_obj2)):
                     return space.newbool(True) # and just go on ...
-        w("#> using parent eq")
+        #w("#> using parent eq")
         return parentfn(wait(space, w_obj1), wait(space, w_obj2))
     return eq
 



More information about the Pypy-commit mailing list