def dpll_satisfiable(expr): """ Check satisfiability of a propositional sentence. It returns a model rather than True when it succeeds >>> from diofant.abc import A, B >>> from diofant.logic.algorithms.dpll import dpll_satisfiable >>> dpll_satisfiable(A & ~B) == {A: True, B: False} True >>> dpll_satisfiable(A & ~A) False """ clauses = conjuncts(to_cnf(expr)) if False in clauses: return False symbols = sorted(_find_predicates(expr), key=default_sort_key) symbols_int_repr = set(range(1, len(symbols) + 1)) clauses_int_repr = to_int_repr(clauses, symbols) result = dpll_int_repr(clauses_int_repr, symbols_int_repr, {}) if not result: return result output = {} for key in result: output.update({symbols[key - 1]: result[key]}) return output
def dpll_satisfiable(expr, all_models=False): """ Check satisfiability of a propositional sentence. It returns a model rather than True when it succeeds. Returns a generator of all models if all_models is True. Examples ======== >>> from diofant.abc import A, B >>> from diofant.logic.algorithms.dpll2 import dpll_satisfiable >>> dpll_satisfiable(A & ~B) == {A: True, B: False} True >>> dpll_satisfiable(A & ~A) False """ clauses = conjuncts(to_cnf(expr)) if False in clauses: if all_models: return (f for f in [False]) return False symbols = sorted(_find_predicates(expr), key=default_sort_key) symbols_int_repr = range(1, len(symbols) + 1) clauses_int_repr = to_int_repr(clauses, symbols) solver = SATSolver(clauses_int_repr, symbols_int_repr, set(), symbols) models = solver._find_model() if all_models: return _all_models(models) try: return next(models) except StopIteration: return False
def test_to_cnf(): assert to_cnf(~(B | C)) == And(Not(B), Not(C)) assert to_cnf((A & B) | C) == And(Or(A, C), Or(B, C)) assert to_cnf(A >> B) == (~A) | B assert to_cnf(A >> (B & C)) == (~A | B) & (~A | C) assert to_cnf(A & (B | C) | ~A & (B | C), True) == B | C assert to_cnf(Equivalent(A, B)) == And(Or(A, Not(B)), Or(B, Not(A))) assert to_cnf(Equivalent(A, B & C)) == \ (~A | B) & (~A | C) & (~B | ~C | A) assert to_cnf(Equivalent(A, B | C), True) == \ And(Or(Not(B), A), Or(Not(C), A), Or(B, C, Not(A))) assert to_cnf(~(A | B) | C) == And(Or(Not(A), C), Or(Not(B), C))
def satisfiable(expr, algorithm="dpll2", all_models=False): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds. Returns {true: true} for trivially true expressions. On setting all_models to True, if given expr is satisfiable then returns a generator of models. However, if expr is unsatisfiable then returns a generator containing the single element False. Examples ======== >>> from diofant.abc import A, B >>> from diofant.logic.inference import satisfiable >>> satisfiable(A & ~B) == {A: True, B: False} True >>> satisfiable(A & ~A) False >>> satisfiable(True) {true: True} >>> next(satisfiable(A & ~A, all_models=True)) False >>> models = satisfiable((A >> B) & B, all_models=True) >>> next(models) == {A: False, B: True} True >>> next(models) == {A: True, B: True} True >>> def use_models(models): ... for model in models: ... if model: ... # Do something with the model. ... return model ... else: ... # Given expr is unsatisfiable. ... print("UNSAT") >>> use_models(satisfiable(A >> ~A, all_models=True)) {A: False} >>> use_models(satisfiable(A ^ A, all_models=True)) UNSAT """ expr = to_cnf(expr) if algorithm == "dpll": from diofant.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from diofant.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr, all_models) else: # pragma: no cover raise NotImplementedError
def retract(self, sentence): """Remove the sentence's clauses from the KB Examples ======== >>> from diofant.logic.inference import PropKB >>> from diofant.abc import x, y >>> l = PropKB() >>> l.clauses [] >>> l.tell(x | y) >>> l.clauses [Or(x, y)] >>> l.retract(x | y) >>> l.clauses [] """ for c in conjuncts(to_cnf(sentence)): self.clauses_.discard(c)
def tell(self, sentence): """Add the sentence's clauses to the KB Examples ======== >>> from diofant.logic.inference import PropKB >>> from diofant.abc import x, y >>> l = PropKB() >>> l.clauses [] >>> l.tell(x | y) >>> l.clauses [Or(x, y)] >>> l.tell(y) >>> l.clauses [y, Or(x, y)] """ for c in conjuncts(to_cnf(sentence)): self.clauses_.add(c)