def propositional_prove(formula: str, assumptions: List[str]): from propositions.syntax import Formula from propositions.tautology import proof_or_counterexample, prove_in_model, evaluate, all_models from propositions.tautology import prove_tautology, encode_as_formula from propositions.proofs import InferenceRule f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None collected_assumptions = [] for assumption in assumptions: a = Formula.parse(assumption) if a is None: print_error('Could not parse the given assumption') return None collected_assumptions.append(a) f = encode_as_formula(InferenceRule(collected_assumptions, f)) valid_proofs = [] for model in all_models(list(f.variables())): if not evaluate(f, model): valid_proofs.append(prove_in_model(f, model)) if len(valid_proofs) > 0: print_result('Found valid proof:\n' + str(valid_proofs)) return True print_result('No valid proof.\n' + str(proof_or_counterexample(f))) return False
def compile_formula(self, skeleton: Dict[str, Formula], reversed_skeleton=None) -> Formula: """ compiles the formula for the needed skeleton, as well as updating the mapping between every z to its formula representative :param skeleton: str to formula :param reversed_skeleton: formula to str :return: compiled formula """ if reversed_skeleton is None: reversed_skeleton = dict() if is_binary(self.root): compiled_formula1 = self.first.compile_formula(skeleton, reversed_skeleton) compiled_formula2 = self.second.compile_formula(skeleton, reversed_skeleton) compiled_formula = PropositionalFormula(self.root, compiled_formula1, compiled_formula2) elif is_unary(self.root): compiled_formula1 = self.first.compile_formula(skeleton, reversed_skeleton) compiled_formula = PropositionalFormula(self.root, compiled_formula1) else: if self in reversed_skeleton: return reversed_skeleton[self] z = next(fresh_variable_name_generator) parsed_z = PropositionalFormula.parse(z) skeleton[z] = self reversed_skeleton[self] = parsed_z return parsed_z return compiled_formula
def propositional_convert_to(formula: str, to: str): from propositions.syntax import Formula from propositions.operators import to_implies_false, to_implies_not, to_nand, to_not_and, to_not_and_or f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None to = to.lower().strip('to_') if to == 'implies_false': f = to_implies_false(f) elif to == 'implies_not': f = to_implies_not(f) elif to == 'nand': f = to_nand(f) elif to == 'not_and': f = to_not_and(f) elif to == 'not_and_or': f = to_not_and_or(f) else: print_error('Undefined action: ' + to + '. Allowed actions are: implies_false, implies_not, ' 'nand, not_and, not_and_or.') return False print_result(str(f)) return True
def propositional_is_consistent(formulas: List[str]): from propositions.syntax import Formula from propositions.tautology import all_models, evaluate from propositions.operators import to_implies_not formulas_list = [] for f in formulas: f = Formula.parse(f) if f is None: print_error('Could not parse the given formula') return None f = to_implies_not(f) formulas_list.append(f) all_variables = list() for formula in formulas_list: all_variables += list(formula.variables()) # Check if we got a formula that doesn't evaluate to true with one of the models for model in all_models(all_variables): if not any(True for f in formulas_list if not evaluate(f, model)): print_result('Formulas: ' + str(formulas) + '\nThat is consistent! Model: ' + str(model)) return True print_result('Formulas: ' + str(formulas) + '\nThat is NOT consistent!') return False
def predicate_try_find_world(formula: str, relation: str, arity: int, max_item: int = 4): from predicates.prenex import to_prenex_normal_form from predicates.syntax import Formula from predicates.semantics import Model from itertools import product, combinations f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None world = set(range(1, max_item)) world_prod = set(product(world, repeat=arity)) i = 1 while i < 10: cbns = list(combinations(world_prod, i)) if len(cbns) == 0: break i += 1 for cbn in cbns: try: m = Model(world, {str(k): k for k in world}, {str(relation): set(cbn)}) if m.is_model_of({f}): print_result('Found Model!\nWorld: ' + str(world) + "\nModel: " + str(m)) return True except: pass print_error('Couldnt find model. Maybe we should try different args.')
def run_sat_cnf(formula: str): """run sat solver on CNF formula without redundancies""" f_prop = propositional_Formula.parse(formula) to_solve = Sat_Solver(f_prop) msg, _ = to_solve.start_sat() if msg is not True: return msg, None to_decide = True decision_var = BUG_MSG while True: # decide if to_decide: decision_var, assignments = to_solve.decide() if decision_var == SAT_MSG: return SAT_MSG, assignments else: to_decide = True # propagate assert decision_var != BUG_MSG # sanity check conflict_clause, backjump_level = to_solve.propagate(decision_var) # backtrack if conflict_clause is not True and conflict_clause != UNSAT_MSG: to_solve.backtrack(conflict_clause, backjump_level) to_decide = False decision_var = BACKTRACK_MSG if conflict_clause is UNSAT_MSG: return UNSAT_MSG, None
def run_sat_solver(formula: str): """preprocess non cnf formula with redundancies and then hand off to sat solver""" f_prop = propositional_Formula.parse(formula) # tseitin and preprocessing f_tseitin = propositions.tseitin.to_tseitin(f_prop) f_tseitin_processed = propositions.tseitin.preprocess_clauses(f_tseitin) if f_tseitin_processed.root == 'F': return UNSAT_MSG, None elif f_tseitin_processed.root == 'T': variables = f_prop.variables() if variables == set(): return SAT_MSG, "Trivial" else: model = next(propositional_semantics.all_models(list(variables))) return SAT_MSG, str(model) # deduction steps msg, settings = run_sat_cnf(str(f_tseitin_processed)) if msg == SAT_MSG: original_variables = f_prop.variables() original_settings = {key: settings[key] for key in original_variables} return msg, original_settings else: return msg, settings
def propositional_to_prefix(formula: str): from propositions.syntax import Formula f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None print(f.polish())
def predicate_create_instance(schema_name: str, instantiation_map, destination_formula: str = None): from predicates.syntax import Formula from predicates.proofs import PROPOSITIONAL_AXIOM_TO_SCHEMA from predicates.prover import Prover consts = [name for name in vars(Prover) if not name.startswith('_')] if schema_name not in consts: print_error('Cant find the schema name.') return for key in instantiation_map: if isinstance(instantiation_map[key], str): instantiation_map[key] = Formula.parse(instantiation_map[key]) schema = vars(Prover)[schema_name] result = [str(schema)] result.append('Instantiation Map: ' + str(instantiation_map)) result.append('') instance = None try: # instantiation_map = {'Q': Formula.parse('Ax[Q(x)]')} instance = schema.instantiate(instantiation_map) result.append('Instance: ' + str(instance)) except AssertionError: # raise result.append('ASSERT ERROR. CAN NOT GENERATE INSTANCE.') print_result('\n'.join(result)) return if destination_formula is not None: destination_formula = Formula.parse(destination_formula) if destination_formula is None: print_error('Could not parse the given destination_formula') return None result.append('') result.append('Destination Formula: ' + str(destination_formula)) result.append('') if destination_formula == instance: result.append('V! Formulas are equal.') else: result.append('X! Formulas ARE NOT equal.') print_result('\n'.join(result))
def helper(self, already_map: dict) -> Tuple[PropositionalFormula, dict]: if is_quantifier(self.root) or is_equality(self.root) or is_relation( self.root): # d = dict() if self in already_map.values(): for key in already_map.keys(): if already_map[key] == self: return (PropositionalFormula.parse(key), already_map) new_fresh_var = next(fresh_variable_name_generator) already_map[new_fresh_var] = self return (PropositionalFormula.parse(new_fresh_var), already_map) if is_unary(self.root): formula1, d = self.first.helper(already_map) return (PropositionalFormula("~", formula1), d) if is_binary(self.root): formula1, d1 = self.first.helper(already_map) formula2, d2 = self.second.helper(d1) return (PropositionalFormula(self.root, formula1, formula2), d2)
def predicate_get_primitives(formula: str): from predicates.syntax import Formula from predicates.completeness import get_primitives, get_constants f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None print_result('Formula: ' + str(f) + '\nPrimitives: ' + str(get_primitives(f)))
def predicate_is_model(formula: str, world: Set[int], relations: Mapping[str, Set[Tuple]]): from predicates.prenex import to_prenex_normal_form from predicates.syntax import Formula from predicates.semantics import Model f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None m = Model(world, {str(k): k for k in world}, relations) print_result(m.is_model_of({f}))
def predicate_prenex_form(formula: str): from predicates.prenex import to_prenex_normal_form, is_in_prenex_normal_form from predicates.syntax import Formula f = Formula.parse(formula) if f is None: print_error('Could not parse the given formula') return None if is_in_prenex_normal_form(f): print_result('Original formula was already in prenex normal form.') else: print_result('Original formula wasnt in prenex normal form.' '\nPrenex Normal Form: ' + str(to_prenex_normal_form(f)[0]))
def propositional_skeleton( self) -> Tuple[PropositionalFormula, Mapping[str, Formula]]: """Computes a propositional skeleton of the current formula. Returns: A pair. The first element of the pair is a propositional formula obtained from the current formula by substituting every (outermost) subformula that has a relation or quantifier at its root with an atomic propositional formula, consistently such that multiple equal such (outermost) subformulas are substituted with the same atomic propositional formula. The atomic propositional formulas used for substitution are obtained, from left to right, by calling `next`\ ``(``\ `~logic_utils.fresh_variable_name_generator`\ ``)``. The second element of the pair is a map from each atomic propositional formula to the subformula for which it was substituted. """ substitution_map = {} skeleton = self.__create_propositional_skeleton(substitution_map) skeleton = PropositionalFormula.parse(str(skeleton)) return skeleton, {v.root: k for k, v in substitution_map.items()}