def winCondition(): """ Simple encoding to see if all ship coordinates are hit """ e = Encoding() # List to hold conjunctions win = [] # Checks to see if all ship parts are hit, win_con is true if all are hit, false otherwise for i in range(1,size + 1): for j in range(1,size + 1): win.append((s1.position[(i,j)] & player_board.hit_board[(i,j)])) e.add_constraint(nnf.And(win).negate() | win_con) e.add_constraint(nnf.And(win) | ~win_con) return e
def compile(self, CNF=True) -> "nnf.NNF": """Convert constraints into a theory in conjunctive normal form, or if specified, the simpler negation-normal form. Arguments --------- CNF : bool Default is True. Converts a theory to CNF. Returns ------- theory : NNF Conjunctive or Negation normal form of constraints. """ if not self.constraints and not self._custom_constraints: raise ValueError( f"Constraints in {self} are empty." " This can happen if no objects from" " decorated classes are instantiated," " if no classes/methods are decorated" " with @constraint or no function" " calls of the form constraint.add_method" ) if not self.propositions.values(): raise ValueError( f"Constraints in {self} are empty." " This can happen if no objects from" " decorated classes are instantiated." ) theory = [] self.clear_debug_constraints() # custom constraints for constraint in self._custom_constraints: clause = constraint.compile() theory.append(clause) self.debug_constraints[constraint] = clause # builder constraints for constraint in self.constraints: clause = constraint.build(self.propositions) if CNF: clause = clause.to_CNF() if clause: theory.append(clause) try: self.debug_constraints[constraint] = clause except Exception as e: raise (e) else: warnings.warn( f"The {constraint} was not built and" "will not be added to the theory." ) return nnf.And(theory)
def compile(self): if self.typ == "var": return self.args[0] elif self.typ == "and": return nnf.And(map(lambda x: x.compile(), self.args)) elif self.typ == "or": return nnf.Or(map(lambda x: x.compile(), self.args)) elif self.typ == "not": return self.args[0].compile().negate() elif self.typ == "imp": return self.args[0].compile().negate() | self.args[1].compile()
def startingSquareHelper(ship): """ Helper function that makes sure that the specified ship may only exist on one square. Returns a list of constraints specific for each ship which will be added as a constraint of disjunctions in the main starting square function. """ # empty list to be populated to become list of a list of conjuncts conjunct_list = [] # the returned list of list of conjuncts constraint_list = [] for i in range(1,size + 1): for j in range(1,size + 1): # For each square, creates conjunction between the square and the ~squares of the rest of the grid to make # sure that there exists a square that the ship may reside on, and it may only reside on that one square for k in range(1,size + 1): for l in range(1,size + 1): if k == i and l == j: conjunct_list.append(ship.startPosition[k,l]) else: conjunct_list.append(~ship.startPosition[k,l]) constraint_list.append(nnf.And(conjunct_list)) conjunct_list = [] return constraint_list
def And(self, children: t.Iterable[T_NNF] = ()) -> nnf.And[T_NNF]: ret = nnf.And(children) return self.stored.setdefault(ret, ret) # type: ignore
def test_to_model(model: dict): sentence = nnf.And(nnf.Var(k, v) for k, v in model.items()) assert sentence.to_model() == model