[pypy-svn] r25496 - in pypy/dist/pypy/objspace/constraint: . test
auc at codespeak.net
auc at codespeak.net
Fri Apr 7 15:24:47 CEST 2006
Author: auc
Date: Fri Apr 7 15:24:45 2006
New Revision: 25496
Modified:
pypy/dist/pypy/objspace/constraint/computationspace.py
pypy/dist/pypy/objspace/constraint/constraint.py
pypy/dist/pypy/objspace/constraint/test/test_computationspace.py
pypy/dist/pypy/objspace/constraint/test/test_constraint.py
Log:
made the constraints stateless
Modified: pypy/dist/pypy/objspace/constraint/computationspace.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/computationspace.py (original)
+++ pypy/dist/pypy/objspace/constraint/computationspace.py Fri Apr 7 15:24:45 2006
@@ -7,8 +7,11 @@
from pypy.objspace.constraint.domain import W_AbstractDomain
+
all_mms = {}
+#-- Variables ---------------------------
+
class W_Variable(Wrappable):
def __init__(self, obj_space, w_name):
self._space = obj_space
@@ -16,10 +19,44 @@
W_Variable.typedef = typedef.TypeDef("W_Variable")
+
+#-- Constraints -------------------------
+
+class W_Constraint(Wrappable):
+ def __init__(self, object_space):
+ self._space = object_space
+
+ def w_affected_variables(self):
+ pass
+
+ def w_is_variable_relevant(self, w_var):
+ pass
+
+ def w_estimate_cost(self, w_cs):
+ pass
+
+ def w_copy_to(self, w_computation_space):
+ pass
+
+ def w_revise(self, w_cs):
+ pass
+
+W_Constraint.typedef = typedef.TypeDef(
+ "W_Constraint",
+ 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)
+ )
+
+#-- Computation space -------------------
+
class W_ComputationSpace(Wrappable):
def __init__(self, obj_space):
self._space = obj_space
self.domains = self._space.newdict({})
+ self.constraints = self._space.newdict({})
def w_var(self, w_name, w_domain):
assert isinstance(w_name, W_StringObject)
@@ -34,10 +71,15 @@
assert isinstance(w_variable, W_Variable)
return self.domains.content[w_variable.name]
+ def w_tell(self, w_constraint):
+ assert isinstance(w_constraint, W_Constraint)
+ self.constraints.content[w_constraint] = self._space.w_True
+
W_ComputationSpace.typedef = typedef.TypeDef(
"W_ComputationSpace",
var = interp2app(W_ComputationSpace.w_var),
- dom = interp2app(W_ComputationSpace.w_dom))
+ dom = interp2app(W_ComputationSpace.w_dom),
+ tell = interp2app(W_ComputationSpace.w_tell))
def newspace(space):
Modified: pypy/dist/pypy/objspace/constraint/constraint.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/constraint.py (original)
+++ pypy/dist/pypy/objspace/constraint/constraint.py Fri Apr 7 15:24:45 2006
@@ -5,8 +5,9 @@
from pypy.objspace.std.listobject import W_ListObject
-
from pypy.objspace.constraint.computationspace import W_ComputationSpace
+from pypy.objspace.constraint.computationspace import W_Constraint
+
#from variable import NoDom
import operator
@@ -24,42 +25,12 @@
#-- Constraints ------------------------------------------
-class W_Constraint(Wrappable):
- def __init__(self, object_space, computation_space):
- self._space = object_space
- assert isinstance(computation_space, W_ComputationSpace)
- self.cs = computation_space
-
- def w_affected_variables(self):
- pass
-
- def w_is_variable_relevant(self, w_var):
- pass
-
- def w_estimate_cost(self):
- pass
-
- def w_copy_to(self, w_computation_space):
- pass
-
- def w_revise(self):
- pass
-
-W_Constraint.typedef = typedef.TypeDef(
- "W_Constraint",
- 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)
- )
-
class W_AbstractConstraint(W_Constraint):
- def __init__(self, object_space, c_space, w_variables):
+ def __init__(self, object_space, w_variables):
"""variables is a list of variables which appear in the formula"""
- W_Constraint.__init__(self, object_space, c_space)
+ W_Constraint.__init__(self, object_space)
assert isinstance(w_variables, W_ListObject)
assert self._space.is_true(self._space.gt(self._space.len(w_variables), self._space.newint(1)))
self._names_to_vars = {}
@@ -74,13 +45,12 @@
def w_is_variable_relevant(self, w_variable):
return variable in self._variables
- def w_estimate_cost(self):
+ def w_estimate_cost(self, w_cs):
"""Return an estimate of the cost of the narrowing of the constraint"""
+ assert isinstance(w_cs, W_ComputationSpace)
return reduce(operator.mul,
- [self.cs.w_dom(var).size() for var in self._variables])
-
- def copy_to(self, space):
- return self.__class__(space, self._variables)
+ [w_cs.w_dom(var).size()
+ for var in self._variables])
def __eq__(self, other): #FIXME and parent
if not isinstance(other, self.__class__): return False
@@ -93,61 +63,8 @@
copy_to = interp2app(W_AbstractConstraint.w_copy_to),
revise = interp2app(W_AbstractConstraint.w_revise)
)
-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_copy_to(self, w_computation_space):
- raise NotImplementedError
-
- 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)
- )
def make_lambda_head(vars):
var_ids = ','.join([var.name for var in vars])
@@ -162,8 +79,8 @@
class W_AllDistinct(W_AbstractConstraint):
"""Contraint: all values must be distinct"""
- def __init__(self, object_space, w_c_space, w_variables):
- W_AbstractConstraint.__init__(self, object_space, w_c_space, w_variables)
+ 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
@@ -171,10 +88,8 @@
def w__repr__(self):
return self._space.newstring('<AllDistinct %s>' % str(self._variables))
- def w_copy_to(self, w_computation_space):
- return self.__class__(space, self._variables)
-
- def w_estimate_cost(self):
+ def w_estimate_cost(self, w_cs):
+ assert isinstance(w_cs, W_ComputationSpace)
return self._space.newint(self.__cost)
def test_solution(self, sol):
@@ -184,9 +99,10 @@
value_set = set(values)
return len(value_set) == len(sol)
- def w_revise(self):
- variables = [(self._space.int_w(self.cs.w_dom(variable).w_size()),
- variable, self.cs.w_dom(variable))
+ def w_revise(self, w_cs):
+ 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]
variables.sort()
@@ -233,8 +149,8 @@
)
# function bolted into the space to serve as constructor
-def make_alldistinct(objectspace, w_computationspace, w_variables):
- return objectspace.wrap(W_AllDistinct(objectspace, w_computationspace, w_variables))
+def make_alldistinct(objectspace, w_variables):
+ return objectspace.wrap(W_AllDistinct(objectspace, w_variables))
app_make_alldistinct = gateway.interp2app(make_alldistinct)
class W_Expression(W_AbstractConstraint):
@@ -275,11 +191,11 @@
return result_cache
- def _assign_values(self):
+ def _assign_values(self, w_cs):
variables = []
kwargs = {}
for variable in self._variables:
- domain = self.cs.w_dom(variable)
+ domain = w_cs.w_dom(variable)
values = domain.w_get_values()
variables.append((domain.w_size(), [variable, values, 0, len(values)]))
kwargs[variable.name] = values[0]
@@ -302,13 +218,13 @@
# it's over
go_on = 0
- def revise(self):
- # removed domain arg. (auc, ale)
+ def revise(self, w_cs):
"""generic propagation algorithm for n-ary expressions"""
+ assert isinstance(w_cs, W_ComputationSpace)
maybe_entailed = 1
ffunc = self.filterFunc
result_cache = self._init_result_cache()
- for kwargs in self._assign_values():
+ for kwargs in self._assign_values(w_cs):
if maybe_entailed:
for var, val in kwargs.iteritems():
if val not in result_cache[var]:
@@ -323,7 +239,7 @@
try:
for var, keep in result_cache.iteritems():
- domain = self.cs.w_dom(self._names_to_vars[var])
+ domain = w_cs.w_dom(self._names_to_vars[var])
domain.remove_values([val for val in domain if val not in keep])
except ConsistencyFailure:
@@ -349,6 +265,7 @@
W_AbstractConstraint.typedef)
+# completely unported
class BinaryExpression(W_Expression):
"""A binary constraint represented as a python expression
@@ -431,6 +348,65 @@
return Expression(vars, formula)
+
+
+
+
+
+
+# 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):
Modified: pypy/dist/pypy/objspace/constraint/test/test_computationspace.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_computationspace.py (original)
+++ pypy/dist/pypy/objspace/constraint/test/test_computationspace.py Fri Apr 7 15:24:45 2006
@@ -25,4 +25,9 @@
assert cspace.dom(v) is domain
-
+ def test_tell(self):
+ csp = newspace()
+ v1 = csp.var('v1', FiniteDomain([1, 2]))
+ v2 = csp.var('v2', FiniteDomain([1, 2]))
+ cstr = AllDistinct([v1, v2])
+ csp.tell(cstr)
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 Fri Apr 7 15:24:45 2006
@@ -10,7 +10,7 @@
cspace = newspace()
v1 = cspace.var('v1', FiniteDomain([1,2]))
v2 = cspace.var('v2', FiniteDomain([1,2]))
- cstr = AllDistinct(cspace, [v1, v2])
+ cstr = AllDistinct([v1, v2])
variables = cstr.affected_variables()
assert variables is not None
assert len(variables) == 2
@@ -21,38 +21,41 @@
csp = newspace()
v1 = csp.var('v1', FiniteDomain([1, 2]))
v2 = csp.var('v2', FiniteDomain([1, 2]))
- cstr = AllDistinct(csp, [v1, v2])
- assert cstr.estimate_cost() == 1
+ cstr = AllDistinct([v1, v2])
+ assert cstr.estimate_cost(csp) == 1
def notest_repr(self):
csp = newspace()
v1 = csp.var('v1', FiniteDomain([1, 2]))
v2 = csp.var('v2', FiniteDomain([1, 2]))
- cstr = AllDistinct(csp, [v1, v2])
+ cstr = AllDistinct([v1, v2])
print cstr
def test_revise(self):
csp = newspace()
v1 = csp.var('v1', FiniteDomain([1, 2]))
v2 = csp.var('v2', FiniteDomain([1, 2]))
- cstr = AllDistinct(csp, [v1, v2])
- assert cstr.revise() == 0 # not entailed
+ cstr = AllDistinct([v1, v2])
+ assert cstr.revise(csp) == 0 # not entailed
v3 = csp.var('v3', FiniteDomain([1]))
v4 = csp.var('v4', FiniteDomain([2]))
- cstr = AllDistinct(csp, [v3, v4])
- assert cstr.revise() == 1 # entailed
+ cstr = AllDistinct([v3, v4])
+ assert cstr.revise(csp) == 1 # entailed
v5 = csp.var('v5', FiniteDomain([1]))
v6 = csp.var('v6', FiniteDomain([1]))
- cstr = AllDistinct(csp, [v5, v6])
- raises(Exception, cstr.revise)
-
- cstr = AllDistinct(csp, [v1, v5])
- assert cstr.revise() == 1
- assert csp.dom(v1).get_values() == [2]
+ cstr = AllDistinct([v5, v6])
+ raises(Exception, cstr.revise, csp)
v7 = csp.var('v7', FiniteDomain([1, 2]))
v8 = csp.var('v8', FiniteDomain([1, 2]))
- cstr = AllDistinct(csp, [v2, v7, v8])
- raises(Exception, cstr.revise)
+ cstr = AllDistinct([v2, v7, v8])
+ raises(Exception, cstr.revise, csp)
+
+ v9 = csp.var('v9', FiniteDomain([1]))
+ v10= csp.var('v10', FiniteDomain([1,2]))
+ cstr = AllDistinct([v9, v10])
+ assert cstr.revise(csp) == 1
+ assert csp.dom(v10).get_values() == [2]
+
More information about the Pypy-commit
mailing list