def count_clauses_satisfied_by_assignment(self, variable: str, assignment: bool): assert is_variable(variable) sat_counter = 0 for clause in self.variable_to_containing_clause[variable]: if clause.is_satisfied_under_assignment(variable, assignment): sat_counter += 1 return sat_counter
def add_inference(self, variable: str, assignment: bool, causing_clause: CNFClause): assert is_variable(variable) assert variable not in self.total_model.keys() self.inferred_variables[-1].update({variable: assignment}) self.total_model[variable] = assignment self.causing_clauses[variable] = (causing_clause, self.curr_decision_level)
def add_decision(self, variable, assignment): assert is_variable(variable) assert variable not in self.total_model.keys() self.curr_decision_level += 1 self.decision_variables.append({variable: assignment}) self.inferred_variables.append(dict()) self.total_model[variable] = assignment self.causing_clauses[variable] = (None, self.curr_decision_level)
def __init__(self, positive_literals: Set[str] = None, negative_literals: Set[str] = None): self.positive_literals = positive_literals if positive_literals is not None else set( ) self.negative_literals = negative_literals if negative_literals is not None else set( ) self.all_literals = dict.fromkeys(self.positive_literals, True) self.all_literals.update(dict.fromkeys(self.negative_literals, False)) for pos_var in self.positive_literals: assert is_variable(pos_var) for neg_var in self.negative_literals: assert is_variable(neg_var) self.is_sat = UNSAT if len(self) == 0 else SAT_UNKNOWN self.inferred_assignment = None self.watched_literals = set() self.update_watched_literals_and_maybe_propagate(dict())
def update_with_new_assignment(self, variable: str, assignment: bool, model: Model): assert is_variable(variable) are_all_sat = True found_unsat = None inferred_assignment = SAT_UNKNOWN # If we got one inferred assignment, we'll return it. Otherwise, we'll return SAT_UNKNOWN for clause in self.variable_to_containing_clause[variable]: result = clause.update_with_new_assignment(variable, assignment, model) if result == UNSAT: found_unsat = clause # Maybe can return here, but won't make big difference are_all_sat = False elif result == SAT: continue elif result == SAT_UNKNOWN: are_all_sat = False else: # Result is a inferred assignment. Continue looping to make sure not UNSAT. Note that means inferred_assignment might change inferred_assignment = result + (clause, ) are_all_sat = False if found_unsat is not None: self.last_result = UNSAT, found_unsat elif are_all_sat: # Only if all clauses containing the last assigned var are SAT, bother checking all the rest are SAT, and if not put SAT_UNKOWN for clause in self.clauses: if clause.is_sat != SAT: are_all_sat = False self.last_result = SAT if are_all_sat else SAT_UNKNOWN else: self.last_result = inferred_assignment
def get_causing_variables(self, variable: str) -> Set[str]: assert is_variable(variable) causing_clause = self.get_causing_clause_of_variable(variable) return causing_clause.get_all_variables( ) if causing_clause is not None else set()
def get_decision_level_of_variable(self, variable: str) -> int: assert is_variable(variable) return self.causing_clauses[variable][1]
def get_causing_clause_of_variable(self, variable: str) -> CNFClause: assert is_variable(variable) return self.causing_clauses[variable][0]