[pypy-svn] r25658 - in pypy/dist/pypy/objspace: . constraint constraint/test

auc at codespeak.net auc at codespeak.net
Mon Apr 10 12:23:45 CEST 2006


Author: auc
Date: Mon Apr 10 12:23:42 2006
New Revision: 25658

Modified:
   pypy/dist/pypy/objspace/constraint/computationspace.py
   pypy/dist/pypy/objspace/constraint/constraint.py
   pypy/dist/pypy/objspace/constraint/domain.py
   pypy/dist/pypy/objspace/constraint/test/test_constraint.py
   pypy/dist/pypy/objspace/constraint/test/test_fd.py
   pypy/dist/pypy/objspace/logic.py
Log:
tries to avoid too much un/wrapping


Modified: pypy/dist/pypy/objspace/constraint/computationspace.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/computationspace.py	(original)
+++ pypy/dist/pypy/objspace/constraint/computationspace.py	Mon Apr 10 12:23:42 2006
@@ -15,10 +15,12 @@
 class W_Variable(Wrappable):
     def __init__(self, obj_space, w_name):
         self._space = obj_space
-        self.name = w_name
+        self.w_name = w_name
 
-W_Variable.typedef = typedef.TypeDef("W_Variable")
+    def name_w(self):
+        return self._space.str_w(self.w_name)
 
+W_Variable.typedef = typedef.TypeDef("W_Variable")
 
 #-- Constraints -------------------------
 
@@ -35,9 +37,6 @@
     def w_estimate_cost(self, w_cs):
         pass
 
-    def w_copy_to(self, w_computation_space):
-        pass
-
     def w_revise(self, w_cs):
         pass
     
@@ -46,9 +45,7 @@
     affected_variables = interp2app(W_Constraint.w_affected_variables),
     is_variable_relevant = interp2app(W_Constraint.w_is_variable_relevant),
     estimate_cost = interp2app(W_Constraint.w_estimate_cost),
-    copy_to = interp2app(W_Constraint.w_copy_to),
-    revise = interp2app(W_Constraint.w_revise)
-    )
+    revise = interp2app(W_Constraint.w_revise))
 
 #-- Computation space -------------------
 
@@ -69,7 +66,7 @@
 
     def w_dom(self, w_variable):
         assert isinstance(w_variable, W_Variable)
-        return self.domains.content[w_variable.name]
+        return self.domains.content[w_variable.w_name]
 
     def w_tell(self, w_constraint):
         assert isinstance(w_constraint, W_Constraint)

Modified: pypy/dist/pypy/objspace/constraint/constraint.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/constraint.py	(original)
+++ pypy/dist/pypy/objspace/constraint/constraint.py	Mon Apr 10 12:23:42 2006
@@ -32,18 +32,19 @@
         """variables is a list of variables which appear in the formula"""
         W_Constraint.__init__(self, object_space)
         assert isinstance(w_variables, W_ListObject)
-        assert self._space.is_true(self._space.ge(self._space.len(w_variables), self._space.newint(1)))
+        assert self._space.is_true(self._space.ge(self._space.len(w_variables),
+                                                  self._space.newint(1)))
         self._names_to_vars = {}
         for var in w_variables.wrappeditems:
-            self._names_to_vars[var.name] = var
-        self._variables = w_variables
+            self._names_to_vars[var.name_w()] = var
+        self._variables = w_variables.wrappeditems #unwrap once ...
 
     def w_affected_variables(self):
         """ Return a list of all variables affected by this constraint """
-        return self._variables
+        return self._space.newlist(self._variables)
 
-    def w_is_variable_relevant(self, w_variable):
-        return variable in self._variables
+    def w_knows_var(self, w_variable):
+        return self._space.newbool(variable in self._variables)
 
     def w_estimate_cost(self, w_cs):
         """Return an estimate of the cost of the narrowing of the constraint"""
@@ -58,23 +59,9 @@
     
 W_AbstractConstraint.typedef = typedef.TypeDef("W_AbstractConstraint",
     affected_variables = interp2app(W_AbstractConstraint.w_affected_variables),
-    is_variable_relevant = interp2app(W_AbstractConstraint.w_is_variable_relevant),
+    knows_var = interp2app(W_AbstractConstraint.w_knows_var),
     estimate_cost = interp2app(W_AbstractConstraint.w_estimate_cost),
-    copy_to = interp2app(W_AbstractConstraint.w_copy_to),
-    revise = interp2app(W_AbstractConstraint.w_revise)
-) 
-
-
-
-def make_lambda_head(space, w_vars):
-    var_ids = ','.join([space.str_w(var.name) for var in w_vars.wrappeditems])
-    return 'lambda ' + var_ids + ':'
-
-def expand_expr_template(space, w_expr, w_vars):
-    return space.str_w(w_expr)
-    for w_var in w_vars.wrappeditems:
-        expr.replace(w_var.name, w_var.name + '.val')
-    return expr
+    revise = interp2app(W_AbstractConstraint.w_revise)) 
 
 
 class W_AllDistinct(W_AbstractConstraint):
@@ -82,13 +69,9 @@
 
     def __init__(self, object_space, w_variables):
         W_AbstractConstraint.__init__(self, object_space, w_variables)
-        assert len(w_variables.wrappeditems)>1
         # worst case complexity
         self.__cost = len(w_variables.wrappeditems) * (len(w_variables.wrappeditems) - 1) / 2
 
-    def w__repr__(self):
-        return self._space.newstring('<AllDistinct %s>' % str(self._variables))
-
     def w_estimate_cost(self, w_cs):
         assert isinstance(w_cs, W_ComputationSpace)
         return self._space.newint(self.__cost)
@@ -104,7 +87,7 @@
         assert isinstance(w_cs, W_ComputationSpace)
         variables = [(self._space.int_w(w_cs.w_dom(variable).w_size()),
                       variable, w_cs.w_dom(variable))
-                     for variable in self._variables.wrappeditems]
+                     for variable in self._variables]
         
         variables.sort()
         # if a domain has a size of 1,
@@ -145,53 +128,58 @@
 W_AllDistinct.typedef = typedef.TypeDef(
     "W_AllDistinct", W_AbstractConstraint.typedef,
     estimate_cost = interp2app(W_AllDistinct.w_estimate_cost),
-    revise = interp2app(W_AllDistinct.w_revise),
-    __repr__ = interp2app(W_AllDistinct.w__repr__)
-    )
+    revise = interp2app(W_AllDistinct.w_revise))
 
 # function bolted into the space to serve as constructor
-def make_alldistinct(objectspace, w_variables):
-    return objectspace.wrap(W_AllDistinct(objectspace, w_variables))
+def make_alldistinct(object_space, w_variables):
+    return object_space.wrap(W_AllDistinct(object_space, w_variables))
 app_make_alldistinct = gateway.interp2app(make_alldistinct)
 
+
+def make_filter(object_space, w_variables, w_formula):
+    """NOT RPYTHON"""
+    var_ids = ','.join([object_space.str_w(var.w_name)
+                        for var in w_variables.wrappeditems])
+    func_head = 'lambda ' + var_ids + ':'
+    func_obj = eval(func_head + object_space.str_w(w_formula), {}, {})
+    return func_obj
+app_make_filter = gateway.interp2app(make_filter)
+
 class W_Expression(W_AbstractConstraint):
     """A constraint represented as a python expression."""
-    _FILTER_CACHE = {}
 
-    def __init__(self, o_space, w_variables, w_formula):
+    def __init__(self, object_space, w_variables, w_formula):
         """variables is a list of variables which appear in the formula
         formula is a python expression that will be evaluated as a boolean"""
-        self.formula = w_formula
-        W_AbstractConstraint.__init__(self, o_space, w_variables)
-        self.filter_func = eval(make_lambda_head(self._space, w_variables) \
-                                + self._space.str_w(w_formula), {}, {})
+        W_AbstractConstraint.__init__(self, object_space, w_variables)
+        self.formula = self._space.str_w(w_formula)
+        self.filter_func = make_filter(self._space, w_variables, w_formula)
 
     def test_solution(self, sol ):
         """test a solution against this constraint 
         accept a mapping of variable names to value"""
         args = []
         for var in self._variables:
-            args.append( sol[var.name] )
+            args.append( sol[var.w_name] )
         return self.filterFunc( *args )
 
     def _init_result_cache(self):
         """key = (variable,value), value = [has_success,has_failure]"""
         result_cache = {}
-        for var_name in self._variables.wrappeditems:
-            result_cache[self._space.str_w(var_name.name)] = {}
+        for var in self._variables:
+            result_cache[var.name_w()] = {}
         return result_cache
 
-
     def _assign_values(self, w_cs):
         variables = []
         kwargs = {}
-        for variable in self._variables.wrappeditems:
+        for variable in self._variables:
             domain = w_cs.w_dom(variable)
             values = domain.w_get_values()
             variables.append((self._space.int_w(domain.w_size()),
                               [variable, values, 0,
                                self._space.len(values)]))
-            kwargs[self._space.str_w(variable.name)] = values.wrappeditems[0]
+            kwargs[variable.name_w()] = values.wrappeditems[0]
         # sort variables to instanciate those with fewer possible values first
         variables.sort()
 
@@ -224,6 +212,8 @@
                         break
                 else:
                     continue
+            print kwargs.items()
+            print ffunc, kwargs.items()
             if ffunc(**kwargs):
                 for var, val in kwargs.items():
                     result_cache[var][val] = 1
@@ -264,9 +254,6 @@
         assert len(variables) == 2
         Expression.__init__(self, variables, formula, type)
 
-    def copy_to(self, space):
-        raise NotImplementedError
-
     def w_revise(self, domains):
         """specialized narrowing algorithm for binary expressions
         Runs much faster than the generic version"""
@@ -321,89 +308,5 @@
         return W_BinaryExpression(o_space, w_variables, w_formula)
     else:
         return W_Expression(o_space, w_variables, w_formula)
-
-
 app_make_expression = gateway.interp2app(make_expression)
 
-# have a look at this later ... (really needed ?)
-class W_BasicConstraint(W_Constraint):
-    """A BasicConstraint, which is never queued by the Repository
-    A BasicConstraint affects only one variable, and will be entailed
-    on the first call to narrow()"""
-    
-    def __init__(self, object_space, variable, reference, operator):
-        """variables is a list of variables on which
-        the constraint is applied"""
-        W_Constraint.__init__(self, object_space)
-        self._variable = variable
-        self._reference = reference
-        self._operator = operator
-
-    def __repr__(self):
-        return '<%s %s %s>'% (self.__class__, self._variable, self._reference)
-
-    def w_is_variable_relevant(self, w_variable):
-        return variable == self._variable
-
-    def w_estimate_cost(self):
-        return self._space.newint(0) # get in the first place in the queue
-    
-    def w_affected_variables(self):
-        return [self._variable]
-    
-    def getVariable(self):
-        return self._variable
-        
-    def w_revise(self, w_domains):
-        domain = domains[self._variable]
-        operator = self._operator
-        ref = self._reference
-        try:
-            for val in domain.get_values() :
-                if not operator(val, ref) :
-                    domain.remove_value(val)
-        except ConsistencyFailure:
-            raise ConsistencyFailure('inconsistency while applying %s' % \
-                                     repr(self))
-        return 1
-
-    def __eq__(self, other):
-        raise NotImplementedError
-
-W_BasicConstraint.typedef = typedef.TypeDef(
-    "W_BasicConstraint",
-    affected_variables = interp2app(W_BasicConstraint.w_affected_variables),
-    is_variable_relevant = interp2app(W_BasicConstraint.w_is_variable_relevant),
-    estimate_cost = interp2app(W_BasicConstraint.w_estimate_cost),
-    copy_to = interp2app(W_BasicConstraint.w_copy_to),
-    revise = interp2app(W_BasicConstraint.w_revise)
-    )
-class W_Equals(W_BasicConstraint):
-    """A basic constraint variable == constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.eq)
-
-class W_NotEquals(W_BasicConstraint):
-    """A basic constraint variable != constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.ne)
-
-class W_LesserThan(W_BasicConstraint):
-    """A basic constraint variable < constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.lt)
-
-class W_LesserOrEqual(W_BasicConstraint):
-    """A basic constraint variable <= constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.le)
-
-class W_GreaterThan(W_BasicConstraint):
-    """A basic constraint variable > constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.gt)
-
-class W_GreaterOrEqual(W_BasicConstraint):
-    """A basic constraint variable >= constant value"""
-    def __init__(self, variable, reference):
-        W_BasicConstraint.__init__(self, variable, reference, operator.ge)

Modified: pypy/dist/pypy/objspace/constraint/domain.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/domain.py	(original)
+++ pypy/dist/pypy/objspace/constraint/domain.py	Mon Apr 10 12:23:42 2006
@@ -22,20 +22,20 @@
 
     def __init__(self, space):
         self._space = space
-        self.__changed = self._space.newbool(False)
+        self.__changed = False
 
     def w_reset_flags(self):
-        self.__changed = self._space.newbool(False)
+        self.__changed = False
     
     def w_has_changed(self):
-        return self.__changed
+        return self._space.newbool(self.__changed)
 
     def w_size(self):
         pass
     
     def _value_removed(self):
         """The implementation of remove_value should call this method"""
-        self.__changed = self._space.newbool(True)
+        self.__changed = True
         if self._space.eq_w(self.w_size(), self._space.newint(0)):
             raise  OperationError(self._space.w_RuntimeError,
                              self._space.wrap('ConsistencyFailure'))
@@ -54,16 +54,20 @@
         This class uses a dictionnary to make sure that there are
         no duplicate values"""
         W_AbstractDomain.__init__(self, space)
-        self._values = space.newdict([])
+        self._values = {}
         self.set_values(w_values)
 
     def set_values(self, w_values):
+        """Objects in the value set can't be unwrapped unless we
+        specialize on specific types - this might need speccialization
+        of revise & friends
+        """
         for w_v in w_values.wrappeditems:
-            self._values.content[w_v] = self._space.w_True
+            self._values[w_v] = self._space.w_True
         
     def w_remove_value(self, w_value):
         """Remove value of domain and check for consistency"""
-        del self._values.content[w_value]
+        del self._values[w_value]
         self._value_removed()
 
     def w_remove_values(self, w_values):
@@ -71,19 +75,19 @@
         if self._space.is_true(self._space.gt(self._space.len(w_values),
                                               self._space.newint(0))) :
             for w_val in w_values.wrappeditems :
-                del self._values.content [w_val]
+                del self._values[w_val]
             self._value_removed()
     __delitem__ = w_remove_value
     
     def w_size(self):
         """computes the size of a finite domain"""
-        return self._space.newint(len(self._values.content))
+        return self._space.newint(len(self._values))
     __len__ = w_size
     
     def w_get_values(self):
         """return all the values in the domain
            in an indexable sequence"""
-        return self._space.newlist([x for x in self._values.content])
+        return self._space.newlist([x for x in self._values])
 
     def __iter__(self):
         return iter(self._values)
@@ -98,7 +102,7 @@
     def __eq__(self, w_other):
         if not isinstance(w_other, W_FiniteDomain):
             return self._space.newbool(False)
-        return self._space.eq(self._values, w_other._values)
+        return self._space.newbool(self._values ==  w_other._values)
             
 
     def __ne__(self, w_other):
@@ -118,8 +122,8 @@
 
 
 def intersection__FiniteDomain_FiniteDomain(space, w_fd1, w_fd2):
-    w_v1 = w_fd1._values.content
-    w_res = [w_v for w_v in w_fd2.w_get_values().wrappeditems
+    w_v1 = w_fd1._values
+    w_res = [w_v for w_v in w_fd2._values
              if w_v in w_v1]
     return make_fd(space, space.newlist(w_res))
 

Modified: pypy/dist/pypy/objspace/constraint/test/test_constraint.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_constraint.py	(original)
+++ pypy/dist/pypy/objspace/constraint/test/test_constraint.py	Mon Apr 10 12:23:42 2006
@@ -71,8 +71,7 @@
         cstr = make_expression([v1], '2*v1==2')
         assert str(cstr).startswith('<W_Expression object at')        
 
-
-    def notest_revise(self):
+    def test_revise(self):
         csp = newspace()
         v1 = csp.var('v1', FiniteDomain([1, 2]))
         cstr = make_expression([v1], '2*v1==2')

Modified: pypy/dist/pypy/objspace/constraint/test/test_fd.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_fd.py	(original)
+++ pypy/dist/pypy/objspace/constraint/test/test_fd.py	Mon Apr 10 12:23:42 2006
@@ -56,7 +56,5 @@
         """not used for now"""
         fd1 = FiniteDomain([1, 2, 3])
         fd2 = FiniteDomain([2, 3, 4])
-        assert intersection(fd1, fd2)  == FiniteDomain([2, 3])
-        assert intersection(fd2, fd1)  == FiniteDomain([3, 2])
-
-
+        assert intersection(fd1, fd2) == FiniteDomain([2, 3])
+        assert intersection(fd2, fd1) == FiniteDomain([3, 2])

Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Mon Apr 10 12:23:42 2006
@@ -801,7 +801,7 @@
             return func_with_new_name(boundmethod, 'boundmethod_'+name)
         boundmethod = make_boundmethod()
         setattr(space, name, boundmethod)  # store into 'space' instance
-    # /multimethod hack
+    # /multimethods hack
 
     # provide a UnificationError exception
     space.ExceptionTable.append('UnificationError')
@@ -821,12 +821,6 @@
                   space.wrap(app_alias_of))
     space.setitem(space.builtin.w_dict, space.wrap('is_aliased'),
                   space.wrap(app_is_aliased))
-    space.setitem(space.builtin.w_dict, space.wrap('newspace'),
-                 space.wrap(computationspace.app_newspace))
-    space.setitem(space.builtin.w_dict, space.wrap('AllDistinct'),
-                 space.wrap(constraint.app_make_alldistinct))
-    space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
-                 space.wrap(constraint.app_make_expression))
     space.setitem(space.builtin.w_dict, space.wrap('bind'),
                  space.wrap(app_bind))
     space.setitem(space.builtin.w_dict, space.wrap('unify'),
@@ -839,6 +833,14 @@
                  space.wrap(domain.app_make_fd))
     space.setitem(space.builtin.w_dict, space.wrap('intersection'),
                  space.wrap(domain.app_intersection))
+    #-- contraint ----
+    space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
+                 space.wrap(constraint.app_make_expression))
+    space.setitem(space.builtin.w_dict, space.wrap('make_filter'),
+                 space.wrap(constraint.app_make_filter))
+    space.setitem(space.builtin.w_dict, space.wrap('AllDistinct'),
+                 space.wrap(constraint.app_make_alldistinct))
+    
     if USE_COROUTINES:
         import os
         def exitfunc():



More information about the Pypy-commit mailing list