def ensure_conjunction_sat(system, *parts): """Modifies the constraint system such that it is only solvable if the conjunction of all parts is satisfiable. Each part must be an iterator, generator, or an iterable over literals.""" pos = defaultdict(set) neg = defaultdict(set) for literal in itertools.chain(*parts): if literal.predicate == "=": # use (in)equalities in conditions if literal.negated: n = constraints.NegativeClause([literal.args]) system.add_negative_clause(n) else: a = constraints.Assignment([literal.args]) system.add_assignment_disjunction([a]) else: if literal.negated: neg[literal.predicate].add(literal) else: pos[literal.predicate].add(literal) for pred, posatoms in pos.items(): if pred in neg: for posatom in posatoms: for negatom in neg[pred]: parts = list(zip(negatom.args, posatom.args)) if parts: negative_clause = constraints.NegativeClause(parts) system.add_negative_clause(negative_clause)
def imply_del_effect(self, del_effect, lhs_by_pred): """returns a constraint system that is solvable if lhs implies the del effect (only if lhs is satisfiable). If a solvable lhs never implies the del effect, return None.""" # del_effect.cond and del_effect.atom must be implied by lhs implies_system = constraints.ConstraintSystem() for literal in itertools.chain(get_literals(del_effect.condition), [del_effect.literal.negate()]): poss_assignments = [] for match in lhs_by_pred[literal.predicate]: if match.negated != literal.negated: continue else: a = constraints.Assignment(list(zip(literal.args, match.args))) poss_assignments.append(a) if not poss_assignments: return None implies_system.add_assignment_disjunction(poss_assignments) return implies_system
def get_assignment(self, parameters, literal): equalities = [(arg, literal.args[argpos]) for arg, argpos in zip(parameters, self.order)] return constraints.Assignment(equalities)