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]