class Variable(object): ! ... ! def narrow(self, values): new_values = self.values & values if not new_values: return False ! if self.values != new_values: if self._last_save_frame != self._current_save_frame: self._save(new_values) ! for constraint in self.constraints: constraint.propagate(self)
import abc ! ! class Constraint(object): __metaclass__ = abc.ABCMeta ! @abc.abstractproperty def variables(self): """ The variables involved in the constraint.""" ! @abc.abstractmethod def propagate(self, variable): """ Propagate the values in `variable` to each of the variables involved in this constraint. """
# from a hypothetical InequalityConstraint … def propagate(self, variable): if variable.is_unique: for v in self.variables: v.narrow(v.values - variable.values)
def solve(): if all(v.is_unique for v in variables): return (v.values[0] for v in variables) ! # some undo-stack management code here... ! variable = random.choice(v for v in variables if v.values > 1) for value in variable.values: if not variable.narrow(value) return ! if not any(v.is_empty for v in variables): if not solve(): return ! # more undo stack management
• Rogue Basin http://goo.gl/UTlwFU • How to Build a Contraint Propagator in a Weekend http://goo.gl/sdrbkJ • Poisson Disk Sampling http://goo.gl/71OzY • Artificial Intelligence: A Modern Approach http://goo.gl/CCCel8 • The Art of Computer Programming http://goo.gl/EUhZ8M