[pypy-svn] r22959 - pypy/dist/pypy/lib/logic/computation_space
auc at codespeak.net
auc at codespeak.net
Thu Feb 2 17:01:27 CET 2006
Author: auc
Date: Thu Feb 2 17:01:24 2006
New Revision: 22959
Modified:
pypy/dist/pypy/lib/logic/computation_space/computationspace.py
pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py
pypy/dist/pypy/lib/logic/computation_space/variable.py
Log:
add merge operator
(now we have a basic impl. of all comp.spaces operators, next step is getting real dataflow vars)
Modified: pypy/dist/pypy/lib/logic/computation_space/computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/computationspace.py (original)
+++ pypy/dist/pypy/lib/logic/computation_space/computationspace.py Thu Feb 2 17:01:24 2006
@@ -160,11 +160,18 @@
## then it returns alternatives(N), where N is the number of
## alternatives.
+## Merge
+## -----
+
+## Merge(S Y) binds Y to the root variable of space S and discards the
+## space
+
+
from threading import Thread, Condition, RLock, local
from state import Succeeded, Distributable, Failed, Merged
-from variable import EqSet, Var, \
+from variable import EqSet, Var, NoValue, \
VariableException, NotAVariable, AlreadyInStore
from constraint import FiniteDomain, ConsistencyFailure
from distributor import DefaultDistributor
@@ -243,8 +250,10 @@
self.status = None
self.status_condition = Condition()
self.distributor = DefaultDistributor(self)
+ self.TOP = False
if parent is None:
+ self.TOP = True
self.vars = set()
# mapping of names to vars (all of them)
self.names = {}
@@ -306,6 +315,30 @@
return self.names[name]
except KeyError:
raise NotInStore(name)
+
+ def find_vars(self, *names):
+ try:
+ return [self.names[name] for name in names]
+ except KeyError:
+ raise NotInStore(name)
+
+ def is_bound(self, var):
+ """check wether a var is bound is locally bound"""
+ if self.TOP:
+ return var.is_bound()
+ return len(var.cs_get_dom(self)) == 1
+
+ def dom(self, var):
+ """return the local domain"""
+ return var.cs_get_dom(self)
+
+ def val(self, var):
+ """return the local binding without blocking"""
+ if self.TOP:
+ return var.val
+ if self.is_bound(var):
+ return var.cs_get_dom(self)[0]
+ return NoValue
#-- Constraints -------------------------
@@ -568,6 +601,9 @@
#-- Computation Space -----------------------------------------
+ def _make_choice_var(self):
+ ComputationSpace._nb_choices += 1
+ return self.var('__choice__'+str(self._nb_choices))
def _process(self):
try:
@@ -586,7 +622,7 @@
or self._distributable()
def _suspended(self):
- pass
+ raise NotImplemented
# 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
@@ -614,6 +650,8 @@
def ask(self):
# XXX: block on status being not stable for threads
+ # use a df var instead of explicit waiting
+ # XXX: truly df vars needed (not one-shot bindings)
try:
self.status_condition.acquire()
while not self._stable():
@@ -662,9 +700,12 @@
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 merge(self):
+ assert self.status == Succeeded
+ # the following ought to be atomic (?)
+ for var in self.root.val:
+ var.val = var.cs_get_dom(self).get_values()[0]
+ self.status = Merged
#-- Unifiability checks---------------------------------------
#--
Modified: pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py (original)
+++ pypy/dist/pypy/lib/logic/computation_space/test_computationspace.py Thu Feb 2 17:01:24 2006
@@ -518,6 +518,7 @@
w = spc.get_var_by_name('w')
assert spc.ask() == space.Alternatives(2)
new_spc = spc.clone()
+ # following couple of ops superceeded by inject()
new_spc.add_constraint(c.Expression(new_spc, [w], 'w == 5'))
new_spc._process()
assert spc.ask() == space.Alternatives(2)
@@ -538,3 +539,31 @@
assert w.cs_get_dom(spc) == c.FiniteDomain([5, 6, 7])
assert w.cs_get_dom(new_spc) == c.FiniteDomain([5])
+ def test_merge(self):
+ spc = space.ComputationSpace(problems.satisfiable_problem)
+ x, y, z, w = spc.find_vars('x', 'y', 'z', 'w')
+ assert spc.TOP
+ assert spc.ask() == space.Alternatives(2)
+ assert spc.dom(x) == c.FiniteDomain([6])
+ assert spc.dom(y) == c.FiniteDomain([2])
+ assert spc.dom(z) == c.FiniteDomain([4])
+ assert spc.dom(w) == c.FiniteDomain([5, 6, 7])
+
+ def more_constraints(space):
+ space.add_constraint(c.Expression(space, [w], 'w == 5'))
+
+ nspc = spc.clone()
+ nspc.inject(more_constraints)
+ x, y, z, w = nspc.find_vars('x', 'y', 'z', 'w')
+ assert not nspc.TOP
+ assert nspc.dom(x) == c.FiniteDomain([6])
+ assert nspc.dom(y) == c.FiniteDomain([2])
+ assert nspc.dom(z) == c.FiniteDomain([4])
+ assert nspc.dom(w) == c.FiniteDomain([5])
+ assert nspc.ask() == space.Succeeded
+ nspc.merge()
+ assert nspc.ask() == space.Merged
+ assert x.val == 6
+ assert y.val == 2
+ assert w.val == 5
+ assert (x, w, y) == nspc.root.val
Modified: pypy/dist/pypy/lib/logic/computation_space/variable.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/variable.py (original)
+++ pypy/dist/pypy/lib/logic/computation_space/variable.py Thu Feb 2 17:01:24 2006
@@ -55,7 +55,7 @@
return not isinstance(self._val, EqSet) \
and self._val != NoValue
- # 'transaction' support
+ # atomic unification support
def _commit(self):
self.changed = False
@@ -111,17 +111,9 @@
# should be used by threads that want to block on
# unbound variables
-## def set_dom(self, dom):
-## self.cs_set_dom(self.cs, dom)
-
-## def get_dom(self):
-## return self.cs_get_dom(self.cs)
-
-## dom = property(get_dom, set_dom)
-
def get(self):
"""Make threads wait on the variable
- being bound
+ being bound in the top-level space
"""
try:
self.value_condition.acquire()
More information about the Pypy-commit
mailing list