def distribute_and_over_or(s): """Given a sentence s consisting of conjunctions and disjunctions of literals, return an equivalent sentence in CNF. >>> distribute_and_over_or((A & B) | C) ((A | C) & (B | C)) """ s = expr(s) if s.op == '|': s = associate('|', s.args) if s.op != '|': return distribute_and_over_or(s) if len(s.args) == 0: return False if len(s.args) == 1: return distribute_and_over_or(s.args[0]) conj = first(arg for arg in s.args if arg.op == '&') if not conj: return s others = [a for a in s.args if a is not conj] rest = associate('|', others) return associate('&', [distribute_and_over_or(c | rest) for c in conj.args]) elif s.op == '&': return associate('&', list(map(distribute_and_over_or, s.args))) else: return s
def actions(self, state): """Return a list of applicable actions: nonconflicting assignments to an unassigned variable.""" if len(state) == len(self.variables): return [] else: assignment = dict(state) var = first([v for v in self.variables if v not in assignment]) return [(var, val) for val in self.domains[var] if self.nconflicts(var, val, assignment) == 0]
def occur_check(var, x, s): """Return true if variable var occurs anywhere in x (or in subst(s, x), if s has a binding for x).""" if var == x: return True elif is_variable(x) and x in s: return occur_check(var, s[x], s) elif isinstance(x, Expr): return (occur_check(var, x.op, s) or occur_check(var, x.args, s)) elif isinstance(x, (list, tuple)): return first(e for e in x if occur_check(var, e, s)) else: return False
def first_unassigned_variable(assignment, csp): """The default variable order.""" return first([var for var in csp.variables if var not in assignment])
def ask(self, query): """Return a substitution that makes the query true, or, failing that, return False.""" return first(self.ask_generator(query), default=False)