示例#1
0
def test_solve(sentence: nnf.NNF):
    solution = sentence.solve()
    if solution is None:
        assert not sentence.satisfiable()
    else:
        assert sentence.satisfiable()
        assert sentence.satisfied_by(solution)
示例#2
0
def test_simplify_preserves_meaning(sentence: nnf.NNF, merge_nodes):
    simple = sentence.simplify(merge_nodes)
    assert sentence.equivalent(simple)
    for model in sentence.models():
        assert simple.satisfied_by(model)
    for model in simple.models():
        assert sentence.condition(model).simplify(merge_nodes) == nnf.true
示例#3
0
def test_models_deterministic_sanity(sentence: nnf.NNF):
    """Running _models_deterministic() on a non-deterministic decomposable
    sentence may return duplicate models but should not return unsatisfying
    models and should return each satisfying model at least once.
    """
    assert model_set(sentence._models_decomposable()) == model_set(
        sentence._models_deterministic())
示例#4
0
def test_simplify_solves_DNNF_satisfiability(sentence: nnf.NNF, merge_nodes):
    if sentence.satisfiable():
        event("Sentence is satisfiable")
        assert sentence.simplify(merge_nodes) != nnf.false
    else:
        event("Sentence is not satisfiable")
        assert sentence.simplify(merge_nodes) == nnf.false
示例#5
0
def test_models(sentence: nnf.NNF):
    real_models = [
        model for model in all_models(sentence.vars())
        if sentence.satisfied_by(model)
    ]
    models = list(sentence.models())
    assert len(real_models) == len(models)
    assert model_set(real_models) == model_set(models)
示例#6
0
def test_implies(a: nnf.NNF, b: nnf.NNF):
    if a.implies(b):
        event("Implication")
        for model in a.models():
            assert b.condition(model).valid()
    else:
        event("No implication")
        assert any(not b.condition(model).valid() for model in a.models())
示例#7
0
def test_to_MODS(sentence: nnf.NNF):
    assume(len(sentence.vars()) <= 5)
    mods = sentence.to_MODS()
    assert mods.is_MODS()
    assert mods.is_DNF()
    assert mods.is_DNF(strict=True)
    assert mods.smooth()
    assert isinstance(mods, Or)
    assert mods.model_count() == len(mods.children)
示例#8
0
def test_validity(sentence: nnf.NNF):
    if sentence.valid():
        event("Valid sentence")
        assert all(
            sentence.satisfied_by(model)
            for model in nnf.all_models(sentence.vars()))
    else:
        event("Invalid sentence")
        assert any(not sentence.satisfied_by(model)
                   for model in nnf.all_models(sentence.vars()))
示例#9
0
def test_simplify_merges_internal_nodes(sentence: nnf.NNF):
    if any(
            any(type(node) == type(child) for child in node.children)
            for node in sentence.walk() if isinstance(node, nnf.Internal)):
        event("Sentence contained immediately mergeable nodes")
        # Nodes may also be merged after intermediate nodes are removed
    for node in sentence.simplify().walk():
        if isinstance(node, nnf.Internal):
            for child in node.children:
                assert type(node) != type(child)
示例#10
0
def test_simplify_eliminates_bools(sentence: nnf.NNF, merge_nodes):
    assume(sentence != nnf.true and sentence != nnf.false)
    if any(node == nnf.true or node == nnf.false for node in sentence.walk()):
        event("Sentence contained booleans originally")
    sentence = sentence.simplify(merge_nodes)
    if sentence == nnf.true or sentence == nnf.false:
        event("Sentence simplified to boolean")
    else:
        for node in sentence.walk():
            assert node != nnf.true and node != nnf.false
示例#11
0
def test_DNNF_sat_strategies(sentence: nnf.NNF, merge_nodes):
    sat = sentence.satisfiable()
    if sat:
        assert sentence.simplify(merge_nodes) != nnf.false
        assert amc.SAT(sentence)
        event("Sentence satisfiable")
    else:
        assert sentence.simplify(merge_nodes) == nnf.false
        assert not amc.SAT(sentence)
        event("Sentence not satisfiable")
示例#12
0
def test_smoothing(sentence: nnf.NNF):
    if not sentence.smooth():
        event("Sentence not smooth yet")
        smoothed = sentence.make_smooth()
        assert type(sentence) is type(smoothed)
        assert smoothed.smooth()
        assert sentence.equivalent(smoothed)
        assert smoothed.make_smooth() == smoothed
    else:
        event("Sentence already smooth")
        assert sentence.make_smooth() == sentence
示例#13
0
def test_implicates_implicants_negation_rule(sentence: nnf.NNF):
    """Any implicate is also a negated implicant of the negated sentence.

    .implicates() gives some implicates, and .implicants() gives all
    implicants.

    So sentence.negate().implicants().negate() gives all implicates,
    and sentence.negate().implicates().negate() gives some implicants.
    """
    assume(sentence.size() <= 30)
    assert (sentence.negate().implicants().negate().children >=
            sentence.implicates().children)
    assert (sentence.negate().implicates().negate().children <=
            sentence.implicants().children)
示例#14
0
def test_pairwise(sentence: nnf.NNF):
    new = sentence.make_pairwise()
    assert new.equivalent(sentence)
    if new not in {nnf.true, nnf.false}:
        assert all(
            len(node.children) == 2 for node in new.walk()
            if isinstance(node, nnf.Internal))
示例#15
0
    def process_theory(node: NNF):

        if node.is_CNF():
            return node

        res = []

        if isinstance(node, Var):
            res.append(node)

        assert isinstance(node, Internal)

        if len(node.children) == 1:
            [child] = node.children
            res.append(process_node(child))

        else:

            left, right = node.children

            if isinstance(node, And):
                left_to_cnf = distribute(left)
                right_to_cnf = distribute(right)
                return And({left_to_cnf, right_to_cnf})

            elif isinstance(node, Or):
                left_to_cnf = distribute(left)
                right_to_cnf = distribute(right)
                return merge_cnf(left_to_cnf, right_to_cnf)

        return res
示例#16
0
def test_tseitin(sentence: nnf.NNF):

    # Assumption to reduce the time in testing
    assume(sentence.size() <= 10)

    T = tseitin.to_CNF(sentence)
    assert T.is_CNF()
    assert T.is_CNF(strict=True)
    assert tseitin.to_CNF(T) == T
    assert T.forget_aux().equivalent(sentence)

    models = list(complete_models(T.models(), sentence.vars() | T.vars()))

    for mt in models:
        assert sentence.satisfied_by(mt)

    assert len(models) == sentence.model_count()
示例#17
0
def test_dimacs_cnf_serialize_accepts_only_cnf(sentence: nnf.NNF):
    if sentence.is_CNF():
        event("CNF sentence")
        dimacs.dumps(sentence, mode='cnf')
    else:
        event("Not CNF sentence")
        with pytest.raises(dimacs.EncodeError):
            dimacs.dumps(sentence, mode='cnf')
示例#18
0
def test_equivalent(sentence: nnf.NNF):
    assert sentence.equivalent(sentence)
    assert sentence.equivalent(sentence | nnf.false)
    assert sentence.equivalent(sentence & (nnf.Var('A') | ~nnf.Var('A')))
    if sentence.satisfiable():
        assert not sentence.equivalent(sentence & nnf.false)
        assert not sentence.equivalent(sentence & nnf.Var('A'))
    else:
        assert sentence.equivalent(sentence & nnf.false)
        assert sentence.equivalent(sentence & nnf.Var('A'))
示例#19
0
def dump(obj: NNF,
         fp: t.TextIO,
         *,
         num_variables: t.Optional[int] = None,
         var_labels: t.Optional[t.Dict[Name, int]] = None,
         comment_header: t.Optional[str] = None,
         mode: str = 'sat') -> None:
    """Dump a sentence into an open file in a DIMACS format.

    Variable names have to be integers. If the variables in the sentence you
    want to dump are not integers, you can pass a ``var_labels`` dictionary
    to map names to integers.

    :param obj: The sentence to dump.
    :param fp: The open file.
    :param num_variables: Override the number of variables, in case there
                          are variables that don't appear in the sentence.
    :param var_labels: A dictionary mapping variable names to integers,
                       to rename non-integer variables.
    :param comment_header: A comment to include at the top of the file. May
                           include newlines.
    :param mode: Either ``'sat'`` to dump in the general SAT format,
                 or ``'cnf'`` to dump in the specialized CNF format.
    """
    if num_variables is None:
        if var_labels is None:
            names = t.cast("t.FrozenSet[int]", obj.vars())
            for name in names:
                if not isinstance(name, int) or name <= 0:
                    raise EncodeError(
                        "{!r} is not an integer > 0. Try supplying a "
                        "var_labels dictionary.".format(name))
            num_vars = max(names, default=0)  # type: int
        else:
            num_vars = max(var_labels.values(), default=0)
    else:
        num_vars = num_variables

    if mode == 'sat':
        _dump_sat(obj,
                  fp,
                  num_variables=num_vars,
                  var_labels=var_labels,
                  comment_header=comment_header)
    elif mode == 'cnf':
        _dump_cnf(obj,
                  fp,
                  num_variables=num_vars,
                  var_labels=var_labels,
                  comment_header=comment_header)
示例#20
0
def test_forget(sentence: nnf.NNF):
    # Assumption to reduce the time in testing
    assume(sentence.size() <= 15)

    # Test that forgetting a backbone variable doesn't change the theory
    T = sentence & Var('added_var')
    assert sentence.equivalent(T.forget({'added_var'}))

    # Test the tseitin projection
    assert sentence.equivalent(sentence.to_CNF().forget_aux())

    # Test that models of a projected theory are consistent with the original
    names = list(sentence.vars())[:2]
    T = sentence.forget(names)
    assert not any([v in T.vars() for v in names])

    for m in T.models():
        assert sentence.condition(m).satisfiable()
示例#21
0
def print_stats(sentence: NNF) -> None:
    if sentence.is_CNF():
        print("Sentence is in CNF.")
    if sentence.decomposable():
        print("Sentence is decomposable.")
    if sentence.smooth():
        print("Sentence is smooth.")
    print("Variables:   {}".format(len(sentence.vars())))
    print("Size:        {}".format(sentence.size()))
    if sentence.is_CNF():
        print("Clauses:     {}".format(len(sentence)))  # type: ignore
        sizes = {len(clause) for clause in sentence}  # type: ignore
        low, high = min(sizes), max(sizes)
        if low == high:
            print("Clause size: {}".format(low))
        else:
            print("Clause size: {}-{}".format(low, high))
示例#22
0
def test_implicates(sentence: nnf.NNF):
    implicates = sentence.implicates()
    assert implicates.equivalent(sentence)
    assert implicates.is_CNF(strict=True)
    assert not any(a.children < b.children for a in implicates.children
                   for b in implicates.children)
示例#23
0
def test_is_MODS(sentence: nnf.NNF):
    assert sentence.is_MODS()
示例#24
0
def test_implicants(sentence: nnf.NNF):
    implicants = sentence.implicants()
    assert implicants.equivalent(sentence)
    assert implicants.is_DNF()
    assert not any(a.children < b.children for a in implicants.children
                   for b in implicants.children)
示例#25
0
def test_pickling(sentence: nnf.NNF):
    new = pickle.loads(pickle.dumps(sentence))
    assert sentence == new
    assert sentence is not new
    assert sentence.object_count() == new.object_count()
示例#26
0
def test_project(sentence: nnf.NNF):
    # Test that we get the same as projecting and forgetting
    assume(len(sentence.vars()) > 3)
    vars1 = list(sentence.vars())[:2]
    vars2 = list(sentence.vars())[2:]
    assert sentence.forget(vars1).equivalent(sentence.project(vars2))
示例#27
0
def test_iff(a: nnf.NNF, b: nnf.NNF):
    c = operators.iff(a, b)
    for model in nnf.all_models(c.vars()):
        assert ((a.satisfied_by(model) == b.satisfied_by(model)
                 ) == c.satisfied_by(model))
示例#28
0
def test_implied_by(a: nnf.NNF, b: nnf.NNF):
    c = operators.implied_by(a, b)
    for model in nnf.all_models(c.vars()):
        assert ((b.satisfied_by(model) and not a.satisfied_by(model)) !=
                c.satisfied_by(model))
示例#29
0
def test_nor(a: nnf.NNF, b: nnf.NNF):
    c = operators.nor(a, b)
    for model in nnf.all_models(c.vars()):
        assert ((a.satisfied_by(model) or b.satisfied_by(model)) !=
                c.satisfied_by(model))
示例#30
0
def test_implicants_idempotent(sentence: nnf.NNF):
    assume(len(sentence.vars()) <= 6)
    implicants = sentence.implicants()
    implicates = sentence.implicates()
    assert implicants.implicants() == implicants
    assert implicates.implicants() == implicants