def _proposition_skeleton_helper(f: Formula, f2z: Mapping[Formula, PropositionalFormula], z2f: Mapping[str, Formula]): # case equality, relation, quantifier if is_equality(f.root) or is_relation(f.root) or is_quantifier(f.root): if f in f2z.keys(): return f2z[f] else: new_z = next(fresh_variable_name_generator) f_as_proposition = PropositionalFormula(new_z) z2f[new_z] = f f2z[f] = f_as_proposition return f_as_proposition # deeper recursion cases if is_unary(f.root) or is_binary(f.root): new_first = Formula._proposition_skeleton_helper(f.first, f2z, z2f) if is_binary(f.root): new_second = Formula._proposition_skeleton_helper( f.second, f2z, z2f) return PropositionalFormula(f.root, new_first, new_second) return PropositionalFormula(f.root, new_first)
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_skeleton_helper(self, mapping: Mapping[str, Formula]) \ -> Tuple[PropositionalFormula, Mapping[str, Formula]]: if is_quantifier(self.root) or is_relation(self.root) or is_equality( self.root): mapping = dict(mapping) for key in mapping.keys(): if mapping[key] == self: return PropositionalFormula(key), mapping atomic_variable = next(fresh_variable_name_generator) mapping[atomic_variable] = self return PropositionalFormula(atomic_variable), mapping elif is_unary(self.root): temp_formula, mapping = Formula.propositional_skeleton_helper( self.first, mapping) return PropositionalFormula(self.root, temp_formula), mapping elif is_binary(self.root): temp_formula1, mapping = Formula.propositional_skeleton_helper( self.first, mapping) temp_formula2, mapping = Formula.propositional_skeleton_helper( self.second, mapping) return PropositionalFormula(self.root, temp_formula1, temp_formula2), mapping
def propositional_skeleton(self, mapping=None) ->\ 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. """ # Task 9.8 if not is_binary(self.root) and not is_unary(self.root): if mapping is not None: # check if the formula was already seen, if so, don't remap it if self in mapping.keys(): return PropositionalFormula(mapping[self]), dict() # else, not in mapping, define a new variable for it new = next(fresh_variable_name_generator) pf = PropositionalFormula(new) m = {new: self} # return propositional skeleton of the Formula return pf, m if is_unary(self.root): # get the first's side propositional skeleton ps1 = Formula.propositional_skeleton(self.first, mapping) pf = PropositionalFormula(self.root, first=ps1[0]) # return new propositional formula and the map return pf, ps1[1] if is_binary(self.root): # get the first's side propositional skeleton ps1 = Formula.propositional_skeleton(self.first, mapping) if mapping is not None: new_dict = dict(mapping) else: new_dict = dict() for key in ps1[1]: new_dict[ps1[1][key]] = key # get the second's side propositional skeleton ps2 = Formula.propositional_skeleton(self.second, new_dict) pf = PropositionalFormula(self.root, first=ps1[0], second=ps2[0]) joined_map = dict(ps1[1]) joined_map.update(ps2[1]) # return new propositional formula and the two sides joined map return pf, joined_map
def propositional_skeleton_helper(self, switches_dict): if is_unary(self.root): return PropositionalFormula( self.root, self.first.propositional_skeleton_helper(switches_dict)) if is_binary(self.root): return PropositionalFormula( self.root, self.first.propositional_skeleton_helper(switches_dict), self.second.propositional_skeleton_helper(switches_dict)) if self in switches_dict: return switches_dict[self] else: value = PropositionalFormula(next(fresh_variable_name_generator)) switches_dict[self] = value return value
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 propositional_skeleton_helper(self, form_dict): """ A recursive helper for the propositional_skeleton method. :param form_dict: a dictionary of types {str : formula} mapping each variable to the formula he assigned for. :return: 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. """ if is_unary(self.root): form_var, form_dict = self.first.propositional_skeleton_helper( form_dict) str_form = PropositionalFormula(self.root, form_var) return str_form, form_dict if is_binary(self.root): form_var1, form_dict = self.first.propositional_skeleton_helper( form_dict) form_var2, form_dict = self.second.propositional_skeleton_helper( form_dict) str_form = PropositionalFormula(self.root, form_var1, form_var2) return str_form, form_dict form_var = False for k, v in form_dict.items(): if v == self: form_var = k if not form_var: form_var = next(fresh_variable_name_generator) form_dict[form_var] = self return PropositionalFormula(form_var), form_dict
def recursive_skeleton_helper(formula : PropositionalFormula, formula_map : Mapping[str, Formula]): # base case: formula is a relation equality or quantifier: if is_relation(formula.root) or is_quantifier(formula.root) or is_equality(formula.root): # check if the value is in the map for key, val in formula_map.items(): if str(val) == str(formula): return PropositionalFormula(key), formula_map else: new_term = Term(next(fresh_variable_name_generator)) formula_map[str(new_term)] = formula return PropositionalFormula(new_term.root), formula_map # unary recursive call if is_unary(formula.root): first_child_term, formula_map_first = recursive_skeleton_helper(formula.first, formula_map) return PropositionalFormula(formula.root, first_child_term), formula_map_first # binary recursive call if is_binary(formula.root): first_child_term, formula_map_first = recursive_skeleton_helper(formula.first, formula_map) second_child_term, formula_map_second = recursive_skeleton_helper(formula.second, formula_map_first) merged_map = formula_map_second return PropositionalFormula(formula.root, first_child_term, second_child_term), merged_map
def propositional_skeleton_helper(self, map): """Computes a propositional skeleton of the current formula. Args: map: the current map of from each atomic propositional formula to the subformula for which it was substituted. 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 mapping from each atomic propositional formula to the subformula for which it was substituted. """ root = self.root if is_unary(root): for key in map: if self.first == map[key]: # first arg already in the map return PropositionalFormula(root, PropositionalFormula(key)), map first, first_map = self.first.propositional_skeleton_helper(map) return PropositionalFormula(root, first), map elif is_binary(root): for key in map: if self.first == map[key]: first = PropositionalFormula( key) # first arg already in the map break else: # first arg not in the map yet first, first_map = self.first.propositional_skeleton_helper( map) for key in map: if map[key] == self.second: second = PropositionalFormula( key) # second arg already in the map break else: # second arg not in the map yet second, second_map = self.second.propositional_skeleton_helper( map) return PropositionalFormula(root, first, second), map else: for key in map: if map[key] == self: # formula in map already return PropositionalFormula(key), map var_name = next(fresh_variable_name_generator) map[var_name] = self return PropositionalFormula(var_name), map