예제 #1
0
 def test_unit(self: TestClause):
     clause = Clause([-6, 5, -4, 3, -2, 1])
     a1 = Assignment(set([1, 2, 3, 4, 5, 6]))
     a1.add_assignment(0, 6, 1, None)
     clause.assign(a1)
     a1.add_assignment(1, 5, 0, None)
     a1.add_assignment(2, 3, 0, None)
     a1.add_assignment(2, 4, 1, None)
     a1.add_assignment(2, 1, 0, None)
     clause.assign(a1)
     self.assertEqual(clause.get_state(a1), (Clause.UNIT, 2, 2))
     self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 3, 1])
예제 #2
0
    def add_clause(self: Formula, clause: List[int]) -> None:
        """Add a clause to the formula after initialization.

    :param clause: a list of `Literal`s that are contained in the clause;
      each variable must appear in `clause` at most once. `clause` cannot contain literals
      in variables not already present in the representation.
    """
        clause_object = Clause(clause)
        clause_object.assign(self.assignment)
        self.formula.append(clause_object)

        # update mutation history and state history
        old_head_var, old_tail_var = clause_object.get_head_tail_var()
        was_valid = False
        was_unsat = len(clause) == 0
        for d in range(0, self.decision_level + 1):
            clause_object.assign_decision_level(self.assignment, d)
            state, head_var, tail_var = clause_object.get_state(
                self.assignment.get_assignment_at_level(d))
            if head_var != old_head_var or tail_var != old_tail_var:
                self.mutation_history[d].add(clause_object)

            # can actually be commented out since we never make
            # decisions while the formila is valid or unsat
            was_valid = was_valid or state == Clause.SATISFIED
            was_unsat = was_unsat or state == Clause.UNSATISFIED
            if self.state_history[d] == Formula.SATISFIED and not was_valid:
                self.state_history[d] = Formula.UNRESOLVED
            if was_unsat:
                self.state_history[d] = Formula.UNSATISFIED

        # update current state
        state, head_var, tail_var = clause_object.get_state(self.assignment)
        if state == Clause.UNRESOLVED or state == Clause.UNIT:
            if head_var not in self.variable_clauses:
                self.variable_clauses[head_var] = set()
            self.variable_clauses[head_var].add(clause_object)
            if tail_var not in self.variable_clauses:
                self.variable_clauses[tail_var] = set()
            self.variable_clauses[tail_var].add(clause_object)

        # update unit clauses
        if state == Clause.UNIT:
            self.unit_clauses.add(clause_object)

        # update unsat clauses
        if state == Clause.UNSATISFIED:
            self.unsat_clauses.add(clause_object)
예제 #3
0
 def test_backtrack(self: TestClause):
     clause = Clause([-6, 5, -4, 3, -2, 1])
     a1 = Assignment(set([1, 2, 3, 4, 5, 6]))
     a1.add_assignment(0, 5, 0, None)
     a1.add_assignment(1, 3, 0, None)
     clause.assign(a1)
     a1.add_assignment(1, 6, 1, None)
     a1.add_assignment(1, 4, 1, None)
     a1.add_assignment(2, 1, 0, None)
     a1.add_assignment(2, 2, 1, None)
     clause.assign(a1)
     self.assertEqual(clause.get_state(a1), (Clause.UNSATISFIED, 1, 1))
     self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 3, 2, 1])
     clause.backtrack(1)
     a1.backtrack(1)
     self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 2, 1))
     self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 3])
     clause.backtrack(0)
     a1.backtrack(0)
     self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 6, 1))
     self.assertEqual(clause.get_assigned_vars(a1), [5])