def propagate_known_value(literal: Literal, formula: List[Clause]) -> List[Clause]: """ Simplifies `formula` based on `literal`. If literal is +x, then any clauses containing +x can be removed and all -x literals can be removed. The simplified formula is returned. """ clauses_purged = purge_clauses_with_literal(literal, deepcopy(formula)) flipped_literal = Literal(literal.name, not literal.sign) both_purged = purge_literal(flipped_literal, clauses_purged) return both_purged
def sentences(): a = Literal("A", False) b = Literal("B", False) c = Literal("C", False) d = Literal("D", False) e = Literal("E", False) f = Literal("F", False) not_a = -a not_b = -b not_c = -c not_d = -d not_e = -e not_f = -f dt = dict() dt['a'] = a dt['b'] = b dt['c'] = c dt['d'] = d dt['e'] = e dt['f'] = f dt['not_a'] = not_a dt['not_b'] = not_b dt['not_c'] = not_c dt['not_d'] = not_d dt['not_e'] = not_e dt['not_f'] = not_f return dt
def do_pure_literal_elimination( formula: List[Clause]) -> (List[Clause], Mapping[int, bool]): known_mapping: Mapping[int, bool] = {} new_formula = deepcopy(formula) variables = get_variables(formula) for variable in variables: # Check variable purity on original formula because variables might get removed during purging. Purity does not # change across purges, so we're safe to use the original formula. variable_purity = get_variable_purity(variable, formula) if variable_purity is not None: new_formula = purge_clauses_with_literal( Literal(variable, variable_purity), new_formula) known_mapping[variable] = variable_purity return new_formula, known_mapping
def read_input(cnfFile: str): variableSet = [] clauseSet = [] nextCID = 0 with open(cnfFile, "r") as f: for line in f.readlines(): tokens = line.strip().split() if tokens and tokens[0] != "p" and tokens[0] != "c": literals = [] for lit in tokens[:-1]: sign = lit[0] != "-" variable = lit.strip("-") literals.append(Literal(variable, sign)) if variable not in variableSet: variableSet.append(variable) clauseSet.append(Clause(nextCID, literals)) nextCID += 1 return variableSet, clauseSet
def do_unit_elimination( formula: List[Clause]) -> (List[Clause], Mapping[bool, int]): """ For every unit clause with variable {+/-x} in formula, removes non-unit clauses containing {+/-x}, all literals that are {-/+x} (flipped sign!), and assigns x a boolean value according to its polarity. Returns a tuple with the modified formula and the mapping that was created. """ known_values = {} unit_clauses = get_unit_clauses(formula) new_formula = deepcopy(formula) for unit in unit_clauses: unit_literal = unit.literals[0] flipped_literal = Literal(unit_literal.name, not unit_literal.sign) new_formula = purge_non_unit_clauses_with_literal( unit_literal, new_formula) new_formula = purge_literal(flipped_literal, new_formula) known_values[unit_literal.name] = unit_literal.sign return new_formula, known_values
for clause in formula: for literal in clause.literals: if target == literal.name: if polarity is None: polarity = literal.sign else: if not polarity == literal.sign: return None return polarity if __name__ == "__main__": # (!x) assert (get_variable_purity(1, [Clause("foo", [Literal(1, False)])]) is False) # (x or !z) AND (!z or x) everything_pure = [ Clause("foo", [Literal(1, True), Literal(3, False)]), Clause("bar", [Literal(3, False), Literal(1, True)]) ] assert (get_variable_purity(1, everything_pure)) assert (get_variable_purity(3, everything_pure) is False) # (x or y) AND (!x or !y). Ensure global purity, not clausal purity. global_purity_check = [ Clause("foo", [Literal(1, True), Literal(2, True)]), Clause("bar", [Literal(1, False), Literal(2, False)]) ]
from util import purge_non_unit_clauses_with_literal, purge_literal from copy import deepcopy def get_unit_clauses(formula: List[Clause]) -> List[Clause]: """ Returns a list of the unit clauses in `formula` """ return [clause for clause in formula if len(clause.literals) == 1] if __name__ == "__main__": # (x or x) is not valid, so we won't test clauses that have repetitive Literals. # (x or !x) is valid, however. plus_or_minus = [Clause("foo", [Literal(1, True), Literal(1, False)])] assert (get_unit_clauses(plus_or_minus) == []) # (x) and (!x or y) and (z) three_clauses = [ Clause("foo", [Literal(1, True)]), Clause("bar", [Literal(1, False), Literal(2, True)]), Clause("baz", [Literal(3, True)]) ] unit_clauses = [ Clause("foo", [Literal(1, True)]), Clause("baz", [Literal(3, True)]) ] assert (get_unit_clauses(three_clauses) == unit_clauses)
# A series of Clause/Literal manipulators and accessors. def purge_literal(literal: Literal, formula: List[Clause]) -> List[Clause]: """ Removes all instance of `literal` from all Clauses in `formula` """ for clause in formula: clause.remove_literal(literal) return formula if __name__ == "__main__": # (x) -x-> () assert(purge_literal(Literal(1, True), [Clause("foo", [Literal(1, True)])]) == [Clause("foo", [])]) # (x or !x) -x-> (!x) assert (purge_literal(Literal(1, True), [Clause("foo", [ Literal(1, True), Literal(1, False)])]) == [Clause("foo", [Literal(1, False)])]) # (x or y) -z-> (x or y) assert (purge_literal(Literal(3, True), [Clause("foo", [ Literal(1, True), Literal(2, True) ])]) == [Clause("foo", [Literal(1, True), Literal(2, True)])]) def purge_clauses_with_literal(literal: Literal, formula: List[Clause]) -> List[Clause]: """ Removes all clauses that contain `literal` from `formula` and returns the new formula. Should be used to simplify a formula after making a guess.