Skip to content

Commit e296aa4

Browse files
committed
Fix .implicates() docs and tests. Resolves #3.
1 parent 32ae536 commit e296aa4

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

nnf/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,13 +781,16 @@ def implicants(self) -> 'Or[And[Var]]':
781781
return Or(self._do_PI()[0])
782782

783783
def implicates(self) -> 'And[Or[Var]]':
784-
"""Extract the prime implicates of the sentence.
784+
"""Extract a prime implicate cover of the sentence.
785785
786786
Prime implicates are the minimal implied clauses. This method
787787
returns a conjunction of clauses that's equivalent to the original
788788
sentence, and minimal, meaning that there are no clauses implied by
789789
the sentence that are strict subsets of any of the clauses in this
790790
representation, so no clauses could be made smaller.
791+
792+
While :meth:`NNF.implicants` returns all implicants, this method may
793+
only return some of the implicates.
791794
"""
792795
return And(self._do_PI()[1])
793796

test_nnf.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -610,20 +610,37 @@ def test_implicates_implicants_idempotent(sentence: nnf.NNF):
610610
assert implicates.implicants() == implicants
611611

612612

613-
# TODO: This test fails, see the example below.
614-
# I don't know if this is a bug in the test or in the implementation.
615-
@pytest.mark.xfail
616613
@given(NNF())
617614
def test_implicates_implicants_negation_rule(sentence: nnf.NNF):
618-
assert sentence.negate().implicants().negate() == sentence.implicates()
619-
assert sentence.negate().implicates().negate() == sentence.implicants()
615+
"""Any implicate is also a negated implicant of the negated sentence.
616+
617+
.implicates() gives some implicates, and .implicants() gives all
618+
implicants.
619+
620+
So sentence.negate().implicants().negate() gives all implicates,
621+
and sentence.negate().implicates().negate() gives some implicants.
622+
"""
623+
assert (
624+
sentence.negate().implicants().negate().children
625+
>= sentence.implicates().children
626+
)
627+
assert (
628+
sentence.negate().implicates().negate().children
629+
<= sentence.implicants().children
630+
)
620631

621632

622-
@pytest.mark.xfail(strict=True)
623633
def test_implicates_implicants_negation_rule_example():
634+
"""These failed an old version of the previous test. See issue #3."""
624635
sentence = Or({And({~Var(1), Var(2)}), And({~Var(3), Var(1)})})
625-
assert sentence.negate().implicants().negate() == sentence.implicates()
626-
assert sentence.negate().implicates().negate() == sentence.implicants()
636+
assert (
637+
sentence.negate().implicants().negate().children
638+
>= sentence.implicates().children
639+
)
640+
assert (
641+
sentence.negate().implicates().negate().children
642+
<= sentence.implicants().children
643+
)
627644

628645

629646
@given(NNF(), NNF())

0 commit comments

Comments
 (0)